Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
f73ecc57
authored
Sep 09, 2023
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
移除不必要的功能
parent
e25bcce4
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
261 additions
and
334 deletions
+261
-334
common/constants.go
+4
-4
controller/midjourney.go
+39
-45
controller/misc.go
+4
-3
controller/relay-mj.go
+1
-0
controller/relay-text.go
+0
-6
controller/topup.go
+35
-60
middleware/distributor.go
+4
-34
model/midjourney.go
+1
-0
model/option.go
+12
-11
web/src/components/PersonalSetting.js
+24
-103
web/src/components/SystemSetting.js
+73
-16
web/src/pages/Home/index.js
+48
-36
web/src/pages/TopUp/index.js
+16
-16
No files found.
common/constants.go
View file @
f73ecc57
...
...
@@ -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
...
...
controller/midjourney.go
View file @
f73ecc57
...
...
@@ -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
)
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
}
req
,
err
:=
http
.
NewRequest
(
"POST"
,
requestUrl
,
bytes
.
NewBuffer
(
jsonStr
))
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
: %v"
,
err
)
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
(
midjourneyT
ask
.
UserId
,
quota
)
err
:=
model
.
IncreaseUserQuota
(
t
ask
.
UserId
,
quota
)
if
err
!=
nil
{
log
.
Println
(
"fail to increase user quota"
)
}
logContent
:=
fmt
.
Sprintf
(
"%s 构图失败,补偿 %s"
,
midjourneyT
ask
.
MjId
,
common
.
LogQuota
(
quota
))
model
.
RecordLog
(
midjourneyT
ask
.
UserId
,
1
,
logContent
)
logContent
:=
fmt
.
Sprintf
(
"%s 构图失败,补偿 %s"
,
t
ask
.
MjId
,
common
.
LogQuota
(
quota
))
model
.
RecordLog
(
t
ask
.
UserId
,
1
,
logContent
)
}
}
}
err
=
midjourneyT
ask
.
Update
()
err
=
t
ask
.
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
)
}
}
}
...
...
controller/misc.go
View file @
f73ecc57
...
...
@@ -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
...
...
controller/relay-mj.go
View file @
f73ecc57
...
...
@@ -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
...
...
controller/relay-text.go
View file @
f73ecc57
...
...
@@ -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
)
}
...
...
controller/topup.go
View file @
f73ecc57
...
...
@@ -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
})
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
})
c
.
JSON
(
200
,
gin
.
H
{
"message"
:
"error"
,
"data"
:
"参数错误"
})
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
)
)})
}
middleware/distributor.go
View file @
f73ecc57
...
...
@@ -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
=
"稳定渠道已经宕机,请联系管理员"
}
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 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
)
...
...
model/midjourney.go
View file @
f73ecc57
...
...
@@ -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
{
...
...
model/option.go
View file @
f73ecc57
...
...
@@ -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"
:
...
...
web/src/components/PersonalSetting.js
View file @
f73ecc57
This diff is collapsed.
Click to expand it.
web/src/components/SystemSetting.js
View file @
f73ecc57
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Button
,
Divider
,
Form
,
Grid
,
Header
,
Modal
,
Message
}
from
'semantic-ui-react'
;
import
{
API
,
removeTrailingSlash
,
showError
}
from
'../helpers'
;
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Button
,
Divider
,
Form
,
Grid
,
Header
,
Modal
,
Message
}
from
'semantic-ui-react'
;
import
{
API
,
removeTrailingSlash
,
showError
}
from
'../helpers'
;
const
SystemSetting
=
()
=>
{
let
[
inputs
,
setInputs
]
=
useState
({
...
...
@@ -17,6 +17,10 @@ const SystemSetting = () => {
SMTPFrom
:
''
,
SMTPToken
:
''
,
ServerAddress
:
''
,
EpayId
:
''
,
EpayKey
:
''
,
Price
:
''
,
PayAddress
:
''
,
Footer
:
''
,
WeChatAuthEnabled
:
''
,
WeChatServerAddress
:
''
,
...
...
@@ -37,7 +41,7 @@ const SystemSetting = () => {
const
getOptions
=
async
()
=>
{
const
res
=
await
API
.
get
(
'/api/option/'
);
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
let
newInputs
=
{};
data
.
forEach
((
item
)
=>
{
...
...
@@ -50,7 +54,7 @@ const SystemSetting = () => {
setOriginInputs
(
newInputs
);
setEmailDomainWhitelist
(
newInputs
.
EmailDomainWhitelist
.
split
(
','
).
map
((
item
)
=>
{
return
{
key
:
item
,
text
:
item
,
value
:
item
};
return
{
key
:
item
,
text
:
item
,
value
:
item
};
}));
}
else
{
showError
(
message
);
...
...
@@ -81,7 +85,7 @@ const SystemSetting = () => {
key
,
value
});
const
{
success
,
message
}
=
res
.
data
;
const
{
success
,
message
}
=
res
.
data
;
if
(
success
)
{
if
(
key
===
'EmailDomainWhitelist'
)
{
value
=
value
.
split
(
','
);
...
...
@@ -95,7 +99,7 @@ const SystemSetting = () => {
setLoading
(
false
);
};
const
handleInputChange
=
async
(
e
,
{
name
,
value
})
=>
{
const
handleInputChange
=
async
(
e
,
{
name
,
value
})
=>
{
if
(
name
===
'PasswordLoginEnabled'
&&
inputs
[
name
]
===
'true'
)
{
// block disabling password login
setShowPasswordWarningModal
(
true
);
...
...
@@ -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'
||
...
...
@@ -114,7 +122,7 @@ const SystemSetting = () => {
name
===
'TurnstileSecretKey'
||
name
===
'EmailDomainWhitelist'
)
{
setInputs
((
inputs
)
=>
({
...
inputs
,
[
name
]:
value
}));
setInputs
((
inputs
)
=>
({...
inputs
,
[
name
]:
value
}));
}
else
{
await
updateOption
(
name
,
value
);
}
...
...
@@ -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
);
...
...
@@ -240,7 +260,44 @@ const SystemSetting = () => {
<
Form
.
Button
onClick
=
{
submitServerAddress
}
>
更新服务器地址
<
/Form.Button
>
<
Divider
/>
<
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
...
...
@@ -255,7 +312,7 @@ const SystemSetting = () => {
open
=
{
showPasswordWarningModal
}
onClose
=
{()
=>
setShowPasswordWarningModal
(
false
)}
size
=
{
'tiny'
}
style
=
{{
maxWidth
:
'450px'
}}
style
=
{{
maxWidth
:
'450px'
}}
>
<
Modal
.
Header
>
警告
<
/Modal.Header
>
<
Modal
.
Content
>
...
...
@@ -314,7 +371,7 @@ const SystemSetting = () => {
onChange
=
{
handleInputChange
}
/
>
<
/Form.Group
>
<
Divider
/>
<
Divider
/>
<
Header
as
=
'h3'
>
配置邮箱域名白名单
<
Header
.
Subheader
>
用以防止恶意用户利用临时邮箱批量注册
<
/Header.Subheader
>
...
...
@@ -356,13 +413,13 @@ const SystemSetting = () => {
autoComplete
=
'new-password'
placeholder
=
'输入新的允许的邮箱域名'
value
=
{
restrictedDomainInput
}
onChange
=
{(
e
,
{
value
})
=>
{
onChange
=
{(
e
,
{
value
})
=>
{
setRestrictedDomainInput
(
value
);
}}
/
>
<
/Form.Group
>
<
Form
.
Button
onClick
=
{
submitEmailDomainWhitelist
}
>
保存邮箱域名白名单设置
<
/Form.Button
>
<
Divider
/>
<
Divider
/>
<
Header
as
=
'h3'
>
配置
SMTP
<
Header
.
Subheader
>
用以支持系统的邮件发送
<
/Header.Subheader
>
...
...
@@ -413,7 +470,7 @@ const SystemSetting = () => {
/>
<
/Form.Group
>
<
Form
.
Button
onClick
=
{
submitSMTP
}
>
保存
SMTP
设置
<
/Form.Button
>
<
Divider
/>
<
Divider
/>
<
Header
as
=
'h3'
>
配置
GitHub
OAuth
App
<
Header
.
Subheader
>
...
...
@@ -451,7 +508,7 @@ const SystemSetting = () => {
<
Form
.
Button
onClick
=
{
submitGitHubOAuth
}
>
保存
GitHub
OAuth
设置
<
/Form.Button
>
<
Divider
/>
<
Divider
/>
<
Header
as
=
'h3'
>
配置
WeChat
Server
<
Header
.
Subheader
>
...
...
@@ -495,7 +552,7 @@ const SystemSetting = () => {
<
Form
.
Button
onClick
=
{
submitWeChat
}
>
保存
WeChat
Server
设置
<
/Form.Button
>
<
Divider
/>
<
Divider
/>
<
Header
as
=
'h3'
>
配置
Turnstile
<
Header
.
Subheader
>
...
...
web/src/pages/Home/index.js
View file @
f73ecc57
import
React
,
{
useContext
,
useEffect
,
useState
}
from
'react'
;
import
{
Card
,
Grid
,
Header
,
Segment
}
from
'semantic-ui-react'
;
import
{
API
,
showError
,
showNotice
,
timestamp2string
}
from
'../../helpers'
;
import
{
StatusContext
}
from
'../../context/Status'
;
import
{
marked
}
from
'marked'
;
import
React
,
{
useContext
,
useEffect
,
useState
}
from
'react'
;
import
{
Card
,
Grid
,
Header
,
Segment
}
from
'semantic-ui-react'
;
import
{
API
,
showError
,
showNotice
,
timestamp2string
}
from
'../../helpers'
;
import
{
StatusContext
}
from
'../../context/Status'
;
import
{
marked
}
from
'marked'
;
const
Home
=
()
=>
{
const
[
statusState
,
statusDispatch
]
=
useContext
(
StatusContext
);
...
...
@@ -11,11 +11,12 @@ const Home = () => {
const
displayNotice
=
async
()
=>
{
const
res
=
await
API
.
get
(
'/api/notice'
);
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
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
{
...
...
@@ -26,7 +27,7 @@ const Home = () => {
const
displayHomePageContent
=
async
()
=>
{
setHomePageContent
(
localStorage
.
getItem
(
'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
)
{
let
content
=
data
;
if
(
!
data
.
startsWith
(
'https://'
))
{
...
...
@@ -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
;
/ 刀</
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
;
/ 刀|{statusState
?
.status
?
.normal_price}R /
&
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
>
}
<
/
>
// :
// <>
// </>
}
<
/
>
...
...
web/src/pages/TopUp/index.js
View file @
f73ecc57
...
...
@@ -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
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment