移除不必要的功能

This commit is contained in:
CaIon 2023-09-09 03:11:42 +08:00
parent 43be1982d7
commit 9ab4f7a271
13 changed files with 943 additions and 1016 deletions

View File

@ -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

View File

@ -19,66 +19,61 @@ 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)
midjourneyChannel, err := model.GetChannelById(task.ChannelId, true)
if err != nil {
log.Printf("UpdateMidjourneyTask: %v", err)
continue
}
req, err := http.NewRequest("POST", requestUrl, bytes.NewBuffer(jsonStr))
task.FailReason = fmt.Sprintf("获取渠道信息失败请联系管理员渠道ID%d", task.ChannelId)
task.Status = "FAILURE"
task.Progress = "100%"
err := task.Update()
if err != nil {
log.Printf("UpdateMidjourneyTask: %v", err)
log.Printf("UpdateMidjourneyTask error: %v", err)
}
continue
}
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", "uhiftyuwadbkjshbiklahcuitguasguzhxliawodawdu")
req.Header.Set("mj-api-secret", midjourneyChannel.Key)
resp, err := httpClient.Do(req)
if err != nil {
log.Printf("UpdateMidjourneyTask: %v", err)
log.Printf("UpdateMidjourneyTask error: %v", err)
continue
}
defer resp.Body.Close()
var response []Midjourney
err = json.NewDecoder(resp.Body).Decode(&response)
var responseItem Midjourney
err = json.NewDecoder(resp.Body).Decode(&responseItem)
if err != nil {
log.Printf("UpdateMidjourneyTask: %v", err)
log.Printf("UpdateMidjourneyTask error: %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 {
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)
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 {
@ -87,22 +82,21 @@ func UpdateMidjourneyTask() {
ratio := modelRatio * groupRatio
quota := int(ratio * 1 * 1000)
if quota != 0 {
err := model.IncreaseUserQuota(midjourneyTask.UserId, quota)
err := model.IncreaseUserQuota(task.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)
logContent := fmt.Sprintf("%s 构图失败,补偿 %s", task.MjId, common.LogQuota(quota))
model.RecordLog(task.UserId, 1, logContent)
}
}
}
err = midjourneyTask.Update()
err = task.Update()
if err != nil {
log.Printf("UpdateMidjourneyTaskFail: %v", err)
}
log.Printf("UpdateMidjourneyTask: %v", midjourneyTask)
log.Printf("UpdateMidjourneyTask error: %v", err)
}
log.Printf("UpdateMidjourneyTask success: %v", task)
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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")
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
}
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 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))})
}

View File

@ -95,43 +95,14 @@ 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 = "稳定渠道已经宕机,请联系管理员"
if channel != nil {
common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id))
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{
c.JSON(http.StatusServiceUnavailable, gin.H{
"error": gin.H{
"message": message,
"type": "one_api_error",
@ -141,7 +112,6 @@ func Distribute() func(c *gin.Context) {
return
}
}
}
c.Set("channel", channel.Type)
c.Set("channel_id", channel.Id)
c.Set("channel_name", channel.Name)

View File

@ -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 {

View File

@ -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":

View File

@ -1,5 +1,5 @@
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';
@ -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);
@ -32,10 +28,6 @@ const PersonalSetting = () => {
const [affLink, setAffLink] = useState("");
const [systemToken, setSystemToken] = useState("");
// setStableMode(userState.user.stableMode, userState.user.maxPrice);
console.log(userState.user)
useEffect(() => {
let status = localStorage.getItem('status');
if (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,20 +53,6 @@ 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 }));
};
@ -87,7 +62,8 @@ const PersonalSetting = () => {
const { success, message, data } = res.data;
if (success) {
setSystemToken(data);
setAffLink("");await copy(data);
setAffLink("");
await copy(data);
showSuccess(`令牌已重置并已复制到剪贴板`);
} else {
showError(message);
@ -100,7 +76,8 @@ const PersonalSetting = () => {
if (success) {
let link = `${window.location.origin}/register?aff=${data}`;
setAffLink(link);
setSystemToken("");await copy(link);
setSystemToken("");
await copy(link);
showSuccess(`邀请链接已复制到剪切板`);
} else {
showError(message);
@ -117,7 +94,9 @@ const PersonalSetting = () => {
e.target.select();
await copy(e.target.value);
showSuccess(`系统令牌已复制到剪切板`);
};const deleteAccount = async () => {
};
const deleteAccount = async () => {
if (inputs.self_account_deletion_confirmation !== userState.user.username) {
showError('请输入你的账户名以确认删除!');
return;
@ -193,8 +172,6 @@ const PersonalSetting = () => {
setLoading(false);
};
// const setStableMod = ;
return (
<div style={{ lineHeight: '40px' }}>
<Header as='h3'>通用设置</Header>
@ -209,66 +186,7 @@ const PersonalSetting = () => {
<Button onClick={() => {
setShowAccountDeleteModal(true);
}}>删除个人账户</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 && (
<Form.Input
fluid
@ -286,7 +204,8 @@ const PersonalSetting = () => {
onClick={handleAffLinkClick}
style={{ marginTop: '10px' }}
/>
)}<Divider/>
)}
<Divider />
<Header as='h3'>账号绑定</Header>
{
status.wechat_login && (
@ -431,7 +350,8 @@ const PersonalSetting = () => {
/>
) : (
<></>
)}<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
)}
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
<Button
color='red'
fluid
@ -440,7 +360,8 @@ const PersonalSetting = () => {
loading={loading}
>
确认删除
</Button><div style={{ width: '1rem' }}></div>
</Button>
<div style={{ width: '1rem' }}></div>
<Button
fluid
size='large'

View File

@ -17,6 +17,10 @@ const SystemSetting = () => {
SMTPFrom: '',
SMTPToken: '',
ServerAddress: '',
EpayId: '',
EpayKey: '',
Price: '',
PayAddress: '',
Footer: '',
WeChatAuthEnabled: '',
WeChatServerAddress: '',
@ -105,6 +109,10 @@ const SystemSetting = () => {
name === 'Notice' ||
name.startsWith('SMTP') ||
name === 'ServerAddress' ||
name === 'EpayId' ||
name === 'EpayKey' ||
name === 'Price' ||
name === 'PayAddress' ||
name === 'GitHubClientId' ||
name === 'GitHubClientSecret' ||
name === 'WeChatServerAddress' ||
@ -125,6 +133,18 @@ const SystemSetting = () => {
await updateOption('ServerAddress', ServerAddress);
};
const submitPayAddress = async () => {
if (inputs.ServerAddress === '') {
showError('请先填写服务器地址');
return
}
let PayAddress = removeTrailingSlash(inputs.PayAddress);
await updateOption('PayAddress', PayAddress);
await updateOption('EpayId', inputs.EpayId);
await updateOption('EpayKey', inputs.EpayKey);
await updateOption('Price', inputs.Price);
};
const submitSMTP = async () => {
if (originInputs['SMTPServer'] !== inputs.SMTPServer) {
await updateOption('SMTPServer', inputs.SMTPServer);
@ -241,6 +261,43 @@ const SystemSetting = () => {
更新服务器地址
</Form.Button>
<Divider/>
<Header as='h3'>支付设置当前仅支持易支付接口使用上方服务器地址作为回调地址</Header>
<Form.Group widths='equal'>
<Form.Input
label='支付地址,不填写则不启用在线支付'
placeholder='例如https://yourdomain.com'
value={inputs.PayAddress}
name='PayAddress'
onChange={handleInputChange}
/>
<Form.Input
label='易支付商户ID'
placeholder='例如0001'
value={inputs.EpayId}
name='EpayId'
onChange={handleInputChange}
/>
<Form.Input
label='易支付商户密钥'
placeholder='例如dejhfueqhujasjmndbjkqaw'
value={inputs.EpayKey}
name='EpayKey'
onChange={handleInputChange}
/>
<Form.Input
label='充值价格x元/美金)'
placeholder='例如7就是7元/美金'
value={inputs.Price}
name='Price'
type='number'
min={0}
onChange={handleInputChange}
/>
</Form.Group>
<Form.Button onClick={submitPayAddress}>
更新支付地址
</Form.Button>
<Divider/>
<Header as='h3'>配置登录注册</Header>
<Form.Group inline>
<Form.Checkbox

View File

@ -15,7 +15,8 @@ const Home = () => {
if (success) {
let oldNotice = localStorage.getItem('notice');
if (data !== oldNotice && data !== '') {
showNotice(data);
const htmlNotice = marked(data);
showNotice(htmlNotice, true);
localStorage.setItem('notice', data);
}
} else {
@ -53,20 +54,28 @@ const Home = () => {
return (
<>
{
// homePageContentLoaded && homePageContent === '' ?
<>
homePageContentLoaded && homePageContent === '' ? <>
<Segment>
<Header as='h3'>当前状态</Header>
<Header as='h3'>系统状况</Header>
<Grid columns={2} stackable>
<Grid.Column>
<Card fluid>
<Card.Content>
<Card.Header>GPT-3.5</Card.Header>
<Card.Meta>信息总览</Card.Meta>
<Card.Header>系统信息</Card.Header>
<Card.Meta>系统信息总览</Card.Meta>
<Card.Description>
<p>通道官方通道</p>
<p>状态存活</p>
<p>价格{statusState?.status?.base_price}R&nbsp;/&nbsp;</p>
<p>名称{statusState?.status?.system_name}</p>
<p>版本{statusState?.status?.version ? statusState?.status?.version : "unknown"}</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.Content>
</Card>
@ -74,26 +83,32 @@ const Home = () => {
<Grid.Column>
<Card fluid>
<Card.Content>
<Card.Header>GPT-4</Card.Header>
<Card.Meta>信息总览</Card.Meta>
<Card.Header>系统配置</Card.Header>
<Card.Meta>系统配置总览</Card.Meta>
<Card.Description>
<p>通道官方通道低价通道</p>
<p>
状态
{statusState?.status?.stable_price===-1?
<span style={{color:'red'}}>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
:
<span style={{color:'green'}}>&emsp;&emsp;</span>
}
{statusState?.status?.normal_price===-1?
<span style={{color:'red'}}>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
:
<span style={{color:'green'}}>&emsp;&emsp;</span>
}
邮箱验证
{statusState?.status?.email_verification === true
? '已启用'
: '未启用'}
</p>
<p>
价格{statusState?.status?.stable_price}R&nbsp;/&nbsp;刀|{statusState?.status?.normal_price}R&nbsp;/&nbsp;
GitHub 身份验证
{statusState?.status?.github_oauth === true
? '已启用'
: '未启用'}
</p>
<p>
微信身份验证
{statusState?.status?.wechat_login === true
? '已启用'
: '未启用'}
</p>
<p>
Turnstile 用户校验
{statusState?.status?.turnstile_check === true
? '已启用'
: '未启用'}
</p>
</Card.Description>
</Card.Content>
@ -101,6 +116,7 @@ const Home = () => {
</Grid.Column>
</Grid>
</Segment>
</> : <>
{
homePageContent.startsWith('https://') ? <iframe
src={homePageContent}
@ -108,10 +124,6 @@ const Home = () => {
/> : <div style={{ fontSize: 'larger' }} dangerouslySetInnerHTML={{ __html: homePageContent }}></div>
}
</>
// :
// <>
// </>
}
</>

View File

@ -78,9 +78,9 @@ const TopUp = () => {
form.submit()
document.body.removeChild(form)
} else {
showError(message);
showError(data);
// setTopUpCount(parseInt(res.data.count));
setAmount(parseInt(data));
// setAmount(parseInt(data));
}
} else {
showError(res);
@ -160,9 +160,9 @@ const TopUp = () => {
setRedemptionCode(e.target.value);
}}
/>
{/*<Button color='green' onClick={openTopUpLink}>*/}
{/* 获取兑换码*/}
{/*</Button>*/}
<Button color='green' onClick={openTopUpLink}>
获取兑换码
</Button>
<Button color='yellow' onClick={topUp} disabled={isSubmitting}>
{isSubmitting ? '兑换中...' : '兑换'}
</Button>
@ -179,7 +179,7 @@ const TopUp = () => {
</Grid>
</Segment>
<Segment>
<Header as='h3'>在线充值最小10刀</Header>
<Header as='h3'>在线充值</Header>
<Grid columns={2} stackable>
<Grid.Column>
<Form>
@ -194,27 +194,27 @@ const TopUp = () => {
await getAmount(e.target.value);
}}
/>
<Form.Input
placeholder='充值码,如果你没有充值码,可不填写'
name='redemptionCount'
value={topUpCode}
onChange={(e) => {
setTopUpCode(e.target.value);
}}
/>
{/*<Form.Input*/}
{/* placeholder='充值码,如果你没有充值码,可不填写'*/}
{/* name='redemptionCount'*/}
{/* value={topUpCode}*/}
{/* onChange={(e) => {*/}
{/* setTopUpCode(e.target.value);*/}
{/* }}*/}
{/*/>*/}
<Button color='blue' onClick={
async () => {
onlineTopUp('zfb')
}
}>
支付宝最大2000元
支付宝
</Button>
<Button color='green' onClick={
async () => {
onlineTopUp('wx')
}
}>
微信最大2000元
微信
</Button>
</Form>
</Grid.Column>