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
762d2c81
authored
Jun 08, 2025
by
Calcium-Ion
Committed by
GitHub
Jun 08, 2025
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1179 from QuantumNous/alpha
merge alpha to main
parents
e1039c67
f1153427
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
87 additions
and
12 deletions
+87
-12
common/redis.go
+3
-3
controller/channel.go
+41
-0
model/token_cache.go
+1
-1
model/user_cache.go
+3
-2
router/api-router.go
+1
-0
web/src/components/table/MjLogsTable.js
+2
-1
web/src/components/table/TaskLogsTable.js
+1
-1
web/src/index.js
+1
-0
web/src/pages/Channel/EditTagModal.js
+25
-1
web/src/pages/Token/EditToken.js
+9
-3
No files found.
common/redis.go
View file @
762d2c81
...
@@ -92,12 +92,12 @@ func RedisDel(key string) error {
...
@@ -92,12 +92,12 @@ func RedisDel(key string) error {
return
RDB
.
Del
(
ctx
,
key
)
.
Err
()
return
RDB
.
Del
(
ctx
,
key
)
.
Err
()
}
}
func
Redis
HDelObj
(
key
string
)
error
{
func
Redis
DelKey
(
key
string
)
error
{
if
DebugEnabled
{
if
DebugEnabled
{
SysLog
(
fmt
.
Sprintf
(
"Redis
HDEL
: key=%s"
,
key
))
SysLog
(
fmt
.
Sprintf
(
"Redis
DEL Key
: key=%s"
,
key
))
}
}
ctx
:=
context
.
Background
()
ctx
:=
context
.
Background
()
return
RDB
.
H
Del
(
ctx
,
key
)
.
Err
()
return
RDB
.
Del
(
ctx
,
key
)
.
Err
()
}
}
func
RedisHSetObj
(
key
string
,
obj
interface
{},
expiration
time
.
Duration
)
error
{
func
RedisHSetObj
(
key
string
,
obj
interface
{},
expiration
time
.
Duration
)
error
{
...
...
controller/channel.go
View file @
762d2c81
...
@@ -623,3 +623,44 @@ func BatchSetChannelTag(c *gin.Context) {
...
@@ -623,3 +623,44 @@ func BatchSetChannelTag(c *gin.Context) {
})
})
return
return
}
}
func
GetTagModels
(
c
*
gin
.
Context
)
{
tag
:=
c
.
Query
(
"tag"
)
if
tag
==
""
{
c
.
JSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"success"
:
false
,
"message"
:
"tag不能为空"
,
})
return
}
channels
,
err
:=
model
.
GetChannelsByTag
(
tag
,
false
)
// Assuming false for idSort is fine here
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusInternalServerError
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
var
longestModels
string
maxLength
:=
0
// Find the longest models string among all channels with the given tag
for
_
,
channel
:=
range
channels
{
if
channel
.
Models
!=
""
{
currentModels
:=
strings
.
Split
(
channel
.
Models
,
","
)
if
len
(
currentModels
)
>
maxLength
{
maxLength
=
len
(
currentModels
)
longestModels
=
channel
.
Models
}
}
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
""
,
"data"
:
longestModels
,
})
return
}
model/token_cache.go
View file @
762d2c81
...
@@ -19,7 +19,7 @@ func cacheSetToken(token Token) error {
...
@@ -19,7 +19,7 @@ func cacheSetToken(token Token) error {
func
cacheDeleteToken
(
key
string
)
error
{
func
cacheDeleteToken
(
key
string
)
error
{
key
=
common
.
GenerateHMAC
(
key
)
key
=
common
.
GenerateHMAC
(
key
)
err
:=
common
.
Redis
HDelObj
(
fmt
.
Sprintf
(
"token:%s"
,
key
))
err
:=
common
.
Redis
DelKey
(
fmt
.
Sprintf
(
"token:%s"
,
key
))
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
...
model/user_cache.go
View file @
762d2c81
...
@@ -3,11 +3,12 @@ package model
...
@@ -3,11 +3,12 @@ package model
import
(
import
(
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"github.com/gin-gonic/gin"
"one-api/common"
"one-api/common"
"one-api/constant"
"one-api/constant"
"time"
"time"
"github.com/gin-gonic/gin"
"github.com/bytedance/gopkg/util/gopool"
"github.com/bytedance/gopkg/util/gopool"
)
)
...
@@ -57,7 +58,7 @@ func invalidateUserCache(userId int) error {
...
@@ -57,7 +58,7 @@ func invalidateUserCache(userId int) error {
if
!
common
.
RedisEnabled
{
if
!
common
.
RedisEnabled
{
return
nil
return
nil
}
}
return
common
.
Redis
HDelObj
(
getUserCacheKey
(
userId
))
return
common
.
Redis
DelKey
(
getUserCacheKey
(
userId
))
}
}
// updateUserCache updates all user cache fields using hash
// updateUserCache updates all user cache fields using hash
...
...
router/api-router.go
View file @
762d2c81
...
@@ -105,6 +105,7 @@ func SetApiRouter(router *gin.Engine) {
...
@@ -105,6 +105,7 @@ func SetApiRouter(router *gin.Engine) {
channelRoute
.
GET
(
"/fetch_models/:id"
,
controller
.
FetchUpstreamModels
)
channelRoute
.
GET
(
"/fetch_models/:id"
,
controller
.
FetchUpstreamModels
)
channelRoute
.
POST
(
"/fetch_models"
,
controller
.
FetchModels
)
channelRoute
.
POST
(
"/fetch_models"
,
controller
.
FetchModels
)
channelRoute
.
POST
(
"/batch/tag"
,
controller
.
BatchSetChannelTag
)
channelRoute
.
POST
(
"/batch/tag"
,
controller
.
BatchSetChannelTag
)
channelRoute
.
GET
(
"/tag/models"
,
controller
.
GetTagModels
)
}
}
tokenRoute
:=
apiRouter
.
Group
(
"/token"
)
tokenRoute
:=
apiRouter
.
Group
(
"/token"
)
tokenRoute
.
Use
(
middleware
.
UserAuth
())
tokenRoute
.
Use
(
middleware
.
UserAuth
())
...
...
web/src/components/table/MjLogsTable.js
View file @
762d2c81
...
@@ -462,7 +462,7 @@ const LogsTable = () => {
...
@@ -462,7 +462,7 @@ const LogsTable = () => {
percent
=
{
text
?
parseInt
(
text
.
replace
(
'%'
,
''
))
:
0
}
percent
=
{
text
?
parseInt
(
text
.
replace
(
'%'
,
''
))
:
0
}
showInfo
=
{
true
}
showInfo
=
{
true
}
aria
-
label
=
'drawing progress'
aria
-
label
=
'drawing progress'
style
=
{{
minWidth
:
'
20
0px'
}}
style
=
{{
minWidth
:
'
16
0px'
}}
/
>
/
>
}
}
<
/div
>
<
/div
>
...
@@ -483,6 +483,7 @@ const LogsTable = () => {
...
@@ -483,6 +483,7 @@ const LogsTable = () => {
setModalImageUrl
(
text
);
setModalImageUrl
(
text
);
setIsModalOpenurl
(
true
);
setIsModalOpenurl
(
true
);
}}
}}
className
=
"!rounded-full"
>
>
{
t
(
'查看图片'
)}
{
t
(
'查看图片'
)}
<
/Button
>
<
/Button
>
...
...
web/src/components/table/TaskLogsTable.js
View file @
762d2c81
...
@@ -395,7 +395,7 @@ const LogsTable = () => {
...
@@ -395,7 +395,7 @@ const LogsTable = () => {
percent
=
{
text
?
parseInt
(
text
.
replace
(
'%'
,
''
))
:
0
}
percent
=
{
text
?
parseInt
(
text
.
replace
(
'%'
,
''
))
:
0
}
showInfo
=
{
true
}
showInfo
=
{
true
}
aria
-
label
=
'task progress'
aria
-
label
=
'task progress'
style
=
{{
minWidth
:
'
20
0px'
}}
style
=
{{
minWidth
:
'
16
0px'
}}
/
>
/
>
)
)
}
}
...
...
web/src/index.js
View file @
762d2c81
import
React
from
'react'
;
import
React
from
'react'
;
import
ReactDOM
from
'react-dom/client'
;
import
ReactDOM
from
'react-dom/client'
;
import
{
BrowserRouter
}
from
'react-router-dom'
;
import
{
BrowserRouter
}
from
'react-router-dom'
;
import
'@douyinfe/semi-ui/dist/css/semi.css'
;
import
{
UserProvider
}
from
'./context/User'
;
import
{
UserProvider
}
from
'./context/User'
;
import
'react-toastify/dist/ReactToastify.css'
;
import
'react-toastify/dist/ReactToastify.css'
;
import
{
StatusProvider
}
from
'./context/Status'
;
import
{
StatusProvider
}
from
'./context/Status'
;
...
...
web/src/pages/Channel/EditTagModal.js
View file @
762d2c81
...
@@ -194,6 +194,24 @@ const EditTagModal = (props) => {
...
@@ -194,6 +194,24 @@ const EditTagModal = (props) => {
},
[
originModelOptions
,
inputs
.
models
]);
},
[
originModelOptions
,
inputs
.
models
]);
useEffect
(()
=>
{
useEffect
(()
=>
{
const
fetchTagModels
=
async
()
=>
{
if
(
!
tag
)
return
;
setLoading
(
true
);
try
{
const
res
=
await
API
.
get
(
`/api/channel/tag/models?tag=
${
tag
}
`
);
if
(
res
?.
data
?.
success
)
{
const
models
=
res
.
data
.
data
?
res
.
data
.
data
.
split
(
','
)
:
[];
setInputs
((
inputs
)
=>
({
...
inputs
,
models
:
models
}));
}
else
{
showError
(
res
.
data
.
message
);
}
}
catch
(
error
)
{
showError
(
error
.
message
);
}
finally
{
setLoading
(
false
);
}
};
setInputs
({
setInputs
({
...
originInputs
,
...
originInputs
,
tag
:
tag
,
tag
:
tag
,
...
@@ -201,7 +219,8 @@ const EditTagModal = (props) => {
...
@@ -201,7 +219,8 @@ const EditTagModal = (props) => {
});
});
fetchModels
().
then
();
fetchModels
().
then
();
fetchGroups
().
then
();
fetchGroups
().
then
();
},
[
visible
]);
fetchTagModels
().
then
();
// Call the new function
},
[
visible
,
tag
]);
// Add tag to dependency array
const
addCustomModels
=
()
=>
{
const
addCustomModels
=
()
=>
{
if
(
customModel
.
trim
()
===
''
)
return
;
if
(
customModel
.
trim
()
===
''
)
return
;
...
@@ -347,6 +366,11 @@ const EditTagModal = (props) => {
...
@@ -347,6 +366,11 @@ const EditTagModal = (props) => {
<
div
className
=
"space-y-4"
>
<
div
className
=
"space-y-4"
>
<
div
>
<
div
>
<
Text
strong
className
=
"block mb-2"
>
{
t
(
'模型'
)}
<
/Text
>
<
Text
strong
className
=
"block mb-2"
>
{
t
(
'模型'
)}
<
/Text
>
<
Banner
type
=
"info"
description
=
{
t
(
'当前模型列表为该标签下所有渠道模型列表最长的一个,并非所有渠道的并集,请注意可能导致某些渠道模型丢失。'
)}
className
=
"!rounded-lg mb-4"
/>
<
Select
<
Select
placeholder
=
{
t
(
'请选择该渠道所支持的模型,留空则不更改'
)}
placeholder
=
{
t
(
'请选择该渠道所支持的模型,留空则不更改'
)}
name
=
'models'
name
=
'models'
...
...
web/src/pages/Token/EditToken.js
View file @
762d2c81
...
@@ -219,9 +219,15 @@ const EditToken = (props) => {
...
@@ -219,9 +219,15 @@ const EditToken = (props) => {
let
successCount
=
0
;
// 记录成功创建的令牌数量
let
successCount
=
0
;
// 记录成功创建的令牌数量
for
(
let
i
=
0
;
i
<
tokenCount
;
i
++
)
{
for
(
let
i
=
0
;
i
<
tokenCount
;
i
++
)
{
let
localInputs
=
{
...
inputs
};
let
localInputs
=
{
...
inputs
};
if
(
i
!==
0
)
{
// 如果用户想要创建多个令牌,则给每个令牌一个序号后缀
// 检查用户是否填写了令牌名称
localInputs
.
name
=
`
${
inputs
.
name
}
-
${
generateRandomSuffix
()}
`
;
const
baseName
=
inputs
.
name
.
trim
()
===
''
?
'default'
:
inputs
.
name
;
if
(
i
!==
0
||
inputs
.
name
.
trim
()
===
''
)
{
// 如果创建多个令牌(i !== 0)或者用户没有填写名称,则添加随机后缀
localInputs
.
name
=
`
${
baseName
}
-
${
generateRandomSuffix
()}
`
;
}
else
{
localInputs
.
name
=
baseName
;
}
}
localInputs
.
remain_quota
=
parseInt
(
localInputs
.
remain_quota
);
localInputs
.
remain_quota
=
parseInt
(
localInputs
.
remain_quota
);
...
...
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