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
aeec39a1
authored
Aug 04, 2025
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add multi-key management
parent
bb08de0b
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
325 additions
and
32 deletions
+325
-32
controller/channel.go
+258
-0
model/channel.go
+17
-6
model/channel_cache.go
+1
-1
router/api-router.go
+1
-0
web/src/components/table/channels/ChannelsColumnDefs.js
+24
-25
web/src/components/table/channels/ChannelsTable.jsx
+7
-0
web/src/components/table/channels/index.jsx
+7
-0
web/src/components/table/channels/modals/MultiKeyManageModal.jsx
+0
-0
web/src/hooks/channels/useChannelsData.js
+10
-0
No files found.
controller/channel.go
View file @
aeec39a1
...
@@ -1030,3 +1030,261 @@ func CopyChannel(c *gin.Context) {
...
@@ -1030,3 +1030,261 @@ func CopyChannel(c *gin.Context) {
// success
// success
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
""
,
"data"
:
gin
.
H
{
"id"
:
clone
.
Id
}})
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
""
,
"data"
:
gin
.
H
{
"id"
:
clone
.
Id
}})
}
}
// MultiKeyManageRequest represents the request for multi-key management operations
type
MultiKeyManageRequest
struct
{
ChannelId
int
`json:"channel_id"`
Action
string
`json:"action"`
// "disable_key", "enable_key", "delete_disabled_keys", "get_key_status"
KeyIndex
*
int
`json:"key_index,omitempty"`
// for disable_key and enable_key actions
}
// MultiKeyStatusResponse represents the response for key status query
type
MultiKeyStatusResponse
struct
{
Keys
[]
KeyStatus
`json:"keys"`
}
type
KeyStatus
struct
{
Index
int
`json:"index"`
Status
int
`json:"status"`
// 1: enabled, 2: disabled
DisabledTime
int64
`json:"disabled_time,omitempty"`
Reason
string
`json:"reason,omitempty"`
KeyPreview
string
`json:"key_preview"`
// first 10 chars of key for identification
}
// ManageMultiKeys handles multi-key management operations
func
ManageMultiKeys
(
c
*
gin
.
Context
)
{
request
:=
MultiKeyManageRequest
{}
err
:=
c
.
ShouldBindJSON
(
&
request
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
channel
,
err
:=
model
.
GetChannelById
(
request
.
ChannelId
,
true
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"渠道不存在"
,
})
return
}
if
!
channel
.
ChannelInfo
.
IsMultiKey
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"该渠道不是多密钥模式"
,
})
return
}
switch
request
.
Action
{
case
"get_key_status"
:
keys
:=
channel
.
GetKeys
()
var
keyStatusList
[]
KeyStatus
for
i
,
key
:=
range
keys
{
status
:=
1
// default enabled
var
disabledTime
int64
var
reason
string
if
channel
.
ChannelInfo
.
MultiKeyStatusList
!=
nil
{
if
s
,
exists
:=
channel
.
ChannelInfo
.
MultiKeyStatusList
[
i
];
exists
{
status
=
s
}
}
if
status
!=
1
{
if
channel
.
ChannelInfo
.
MultiKeyDisabledTime
!=
nil
{
disabledTime
=
channel
.
ChannelInfo
.
MultiKeyDisabledTime
[
i
]
}
if
channel
.
ChannelInfo
.
MultiKeyDisabledReason
!=
nil
{
reason
=
channel
.
ChannelInfo
.
MultiKeyDisabledReason
[
i
]
}
}
// Create key preview (first 10 chars)
keyPreview
:=
key
if
len
(
key
)
>
10
{
keyPreview
=
key
[
:
10
]
+
"..."
}
keyStatusList
=
append
(
keyStatusList
,
KeyStatus
{
Index
:
i
,
Status
:
status
,
DisabledTime
:
disabledTime
,
Reason
:
reason
,
KeyPreview
:
keyPreview
,
})
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
""
,
"data"
:
MultiKeyStatusResponse
{
Keys
:
keyStatusList
},
})
return
case
"disable_key"
:
if
request
.
KeyIndex
==
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"未指定要禁用的密钥索引"
,
})
return
}
keyIndex
:=
*
request
.
KeyIndex
if
keyIndex
<
0
||
keyIndex
>=
channel
.
ChannelInfo
.
MultiKeySize
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"密钥索引超出范围"
,
})
return
}
if
channel
.
ChannelInfo
.
MultiKeyStatusList
==
nil
{
channel
.
ChannelInfo
.
MultiKeyStatusList
=
make
(
map
[
int
]
int
)
}
if
channel
.
ChannelInfo
.
MultiKeyDisabledTime
==
nil
{
channel
.
ChannelInfo
.
MultiKeyDisabledTime
=
make
(
map
[
int
]
int64
)
}
if
channel
.
ChannelInfo
.
MultiKeyDisabledReason
==
nil
{
channel
.
ChannelInfo
.
MultiKeyDisabledReason
=
make
(
map
[
int
]
string
)
}
channel
.
ChannelInfo
.
MultiKeyStatusList
[
keyIndex
]
=
2
// disabled
channel
.
ChannelInfo
.
MultiKeyDisabledTime
[
keyIndex
]
=
common
.
GetTimestamp
()
channel
.
ChannelInfo
.
MultiKeyDisabledReason
[
keyIndex
]
=
"手动禁用"
err
=
channel
.
Update
()
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
model
.
InitChannelCache
()
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
"密钥已禁用"
,
})
return
case
"enable_key"
:
if
request
.
KeyIndex
==
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"未指定要启用的密钥索引"
,
})
return
}
keyIndex
:=
*
request
.
KeyIndex
if
keyIndex
<
0
||
keyIndex
>=
channel
.
ChannelInfo
.
MultiKeySize
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"密钥索引超出范围"
,
})
return
}
// 从状态列表中删除该密钥的记录,使其回到默认启用状态
if
channel
.
ChannelInfo
.
MultiKeyStatusList
!=
nil
{
delete
(
channel
.
ChannelInfo
.
MultiKeyStatusList
,
keyIndex
)
}
if
channel
.
ChannelInfo
.
MultiKeyDisabledTime
!=
nil
{
delete
(
channel
.
ChannelInfo
.
MultiKeyDisabledTime
,
keyIndex
)
}
if
channel
.
ChannelInfo
.
MultiKeyDisabledReason
!=
nil
{
delete
(
channel
.
ChannelInfo
.
MultiKeyDisabledReason
,
keyIndex
)
}
err
=
channel
.
Update
()
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
model
.
InitChannelCache
()
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
"密钥已启用"
,
})
return
case
"delete_disabled_keys"
:
keys
:=
channel
.
GetKeys
()
var
remainingKeys
[]
string
var
deletedCount
int
var
newStatusList
=
make
(
map
[
int
]
int
)
var
newDisabledTime
=
make
(
map
[
int
]
int64
)
var
newDisabledReason
=
make
(
map
[
int
]
string
)
newIndex
:=
0
for
i
,
key
:=
range
keys
{
status
:=
1
// default enabled
if
channel
.
ChannelInfo
.
MultiKeyStatusList
!=
nil
{
if
s
,
exists
:=
channel
.
ChannelInfo
.
MultiKeyStatusList
[
i
];
exists
{
status
=
s
}
}
// 只删除自动禁用(status == 3)的密钥,保留启用(status == 1)和手动禁用(status == 2)的密钥
if
status
==
3
{
deletedCount
++
}
else
{
remainingKeys
=
append
(
remainingKeys
,
key
)
// 保留非自动禁用密钥的状态信息,重新索引
if
status
!=
1
{
newStatusList
[
newIndex
]
=
status
if
channel
.
ChannelInfo
.
MultiKeyDisabledTime
!=
nil
{
if
t
,
exists
:=
channel
.
ChannelInfo
.
MultiKeyDisabledTime
[
i
];
exists
{
newDisabledTime
[
newIndex
]
=
t
}
}
if
channel
.
ChannelInfo
.
MultiKeyDisabledReason
!=
nil
{
if
r
,
exists
:=
channel
.
ChannelInfo
.
MultiKeyDisabledReason
[
i
];
exists
{
newDisabledReason
[
newIndex
]
=
r
}
}
}
newIndex
++
}
}
if
deletedCount
==
0
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"没有需要删除的自动禁用密钥"
,
})
return
}
// Update channel with remaining keys
channel
.
Key
=
strings
.
Join
(
remainingKeys
,
"
\n
"
)
channel
.
ChannelInfo
.
MultiKeySize
=
len
(
remainingKeys
)
channel
.
ChannelInfo
.
MultiKeyStatusList
=
newStatusList
channel
.
ChannelInfo
.
MultiKeyDisabledTime
=
newDisabledTime
channel
.
ChannelInfo
.
MultiKeyDisabledReason
=
newDisabledReason
err
=
channel
.
Update
()
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
model
.
InitChannelCache
()
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
fmt
.
Sprintf
(
"已删除 %d 个自动禁用的密钥"
,
deletedCount
),
"data"
:
deletedCount
,
})
return
default
:
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"不支持的操作"
,
})
return
}
}
model/channel.go
View file @
aeec39a1
...
@@ -41,6 +41,7 @@ type Channel struct {
...
@@ -41,6 +41,7 @@ type Channel struct {
Priority
*
int64
`json:"priority" gorm:"bigint;default:0"`
Priority
*
int64
`json:"priority" gorm:"bigint;default:0"`
AutoBan
*
int
`json:"auto_ban" gorm:"default:1"`
AutoBan
*
int
`json:"auto_ban" gorm:"default:1"`
OtherInfo
string
`json:"other_info"`
OtherInfo
string
`json:"other_info"`
Settings
string
`json:"settings"`
Tag
*
string
`json:"tag" gorm:"index"`
Tag
*
string
`json:"tag" gorm:"index"`
Setting
*
string
`json:"setting" gorm:"type:text"`
// 渠道额外设置
Setting
*
string
`json:"setting" gorm:"type:text"`
// 渠道额外设置
ParamOverride
*
string
`json:"param_override" gorm:"type:text"`
ParamOverride
*
string
`json:"param_override" gorm:"type:text"`
...
@@ -55,6 +56,8 @@ type ChannelInfo struct {
...
@@ -55,6 +56,8 @@ type ChannelInfo struct {
IsMultiKey
bool
`json:"is_multi_key"`
// 是否多Key模式
IsMultiKey
bool
`json:"is_multi_key"`
// 是否多Key模式
MultiKeySize
int
`json:"multi_key_size"`
// 多Key模式下的Key数量
MultiKeySize
int
`json:"multi_key_size"`
// 多Key模式下的Key数量
MultiKeyStatusList
map
[
int
]
int
`json:"multi_key_status_list"`
// key状态列表,key index -> status
MultiKeyStatusList
map
[
int
]
int
`json:"multi_key_status_list"`
// key状态列表,key index -> status
MultiKeyDisabledReason
map
[
int
]
string
`json:"multi_key_disabled_reason"`
// key禁用原因列表,key index -> reason
MultiKeyDisabledTime
map
[
int
]
int64
`json:"multi_key_disabled_time"`
// key禁用时间列表,key index -> time
MultiKeyPollingIndex
int
`json:"multi_key_polling_index"`
// 多Key模式下轮询的key索引
MultiKeyPollingIndex
int
`json:"multi_key_polling_index"`
// 多Key模式下轮询的key索引
MultiKeyMode
constant
.
MultiKeyMode
`json:"multi_key_mode"`
MultiKeyMode
constant
.
MultiKeyMode
`json:"multi_key_mode"`
}
}
...
@@ -70,7 +73,7 @@ func (c *ChannelInfo) Scan(value interface{}) error {
...
@@ -70,7 +73,7 @@ func (c *ChannelInfo) Scan(value interface{}) error {
return
common
.
Unmarshal
(
bytesValue
,
c
)
return
common
.
Unmarshal
(
bytesValue
,
c
)
}
}
func
(
channel
*
Channel
)
g
etKeys
()
[]
string
{
func
(
channel
*
Channel
)
G
etKeys
()
[]
string
{
if
channel
.
Key
==
""
{
if
channel
.
Key
==
""
{
return
[]
string
{}
return
[]
string
{}
}
}
...
@@ -101,7 +104,7 @@ func (channel *Channel) GetNextEnabledKey() (string, int, *types.NewAPIError) {
...
@@ -101,7 +104,7 @@ func (channel *Channel) GetNextEnabledKey() (string, int, *types.NewAPIError) {
}
}
// Obtain all keys (split by \n)
// Obtain all keys (split by \n)
keys
:=
channel
.
g
etKeys
()
keys
:=
channel
.
G
etKeys
()
if
len
(
keys
)
==
0
{
if
len
(
keys
)
==
0
{
// No keys available, return error, should disable the channel
// No keys available, return error, should disable the channel
return
""
,
0
,
types
.
NewError
(
errors
.
New
(
"no keys available"
),
types
.
ErrorCodeChannelNoAvailableKey
)
return
""
,
0
,
types
.
NewError
(
errors
.
New
(
"no keys available"
),
types
.
ErrorCodeChannelNoAvailableKey
)
...
@@ -528,8 +531,8 @@ func CleanupChannelPollingLocks() {
...
@@ -528,8 +531,8 @@ func CleanupChannelPollingLocks() {
})
})
}
}
func
handlerMultiKeyUpdate
(
channel
*
Channel
,
usingKey
string
,
status
int
)
{
func
handlerMultiKeyUpdate
(
channel
*
Channel
,
usingKey
string
,
status
int
,
reason
string
)
{
keys
:=
channel
.
g
etKeys
()
keys
:=
channel
.
G
etKeys
()
if
len
(
keys
)
==
0
{
if
len
(
keys
)
==
0
{
channel
.
Status
=
status
channel
.
Status
=
status
}
else
{
}
else
{
...
@@ -547,6 +550,14 @@ func handlerMultiKeyUpdate(channel *Channel, usingKey string, status int) {
...
@@ -547,6 +550,14 @@ func handlerMultiKeyUpdate(channel *Channel, usingKey string, status int) {
delete
(
channel
.
ChannelInfo
.
MultiKeyStatusList
,
keyIndex
)
delete
(
channel
.
ChannelInfo
.
MultiKeyStatusList
,
keyIndex
)
}
else
{
}
else
{
channel
.
ChannelInfo
.
MultiKeyStatusList
[
keyIndex
]
=
status
channel
.
ChannelInfo
.
MultiKeyStatusList
[
keyIndex
]
=
status
if
channel
.
ChannelInfo
.
MultiKeyDisabledReason
==
nil
{
channel
.
ChannelInfo
.
MultiKeyDisabledReason
=
make
(
map
[
int
]
string
)
}
if
channel
.
ChannelInfo
.
MultiKeyDisabledTime
==
nil
{
channel
.
ChannelInfo
.
MultiKeyDisabledTime
=
make
(
map
[
int
]
int64
)
}
channel
.
ChannelInfo
.
MultiKeyDisabledReason
[
keyIndex
]
=
reason
channel
.
ChannelInfo
.
MultiKeyDisabledTime
[
keyIndex
]
=
common
.
GetTimestamp
()
}
}
if
len
(
channel
.
ChannelInfo
.
MultiKeyStatusList
)
>=
channel
.
ChannelInfo
.
MultiKeySize
{
if
len
(
channel
.
ChannelInfo
.
MultiKeyStatusList
)
>=
channel
.
ChannelInfo
.
MultiKeySize
{
channel
.
Status
=
common
.
ChannelStatusAutoDisabled
channel
.
Status
=
common
.
ChannelStatusAutoDisabled
...
@@ -569,7 +580,7 @@ func UpdateChannelStatus(channelId int, usingKey string, status int, reason stri
...
@@ -569,7 +580,7 @@ func UpdateChannelStatus(channelId int, usingKey string, status int, reason stri
}
}
if
channelCache
.
ChannelInfo
.
IsMultiKey
{
if
channelCache
.
ChannelInfo
.
IsMultiKey
{
// 如果是多Key模式,更新缓存中的状态
// 如果是多Key模式,更新缓存中的状态
handlerMultiKeyUpdate
(
channelCache
,
usingKey
,
status
)
handlerMultiKeyUpdate
(
channelCache
,
usingKey
,
status
,
reason
)
//CacheUpdateChannel(channelCache)
//CacheUpdateChannel(channelCache)
//return true
//return true
}
else
{
}
else
{
...
@@ -600,7 +611,7 @@ func UpdateChannelStatus(channelId int, usingKey string, status int, reason stri
...
@@ -600,7 +611,7 @@ func UpdateChannelStatus(channelId int, usingKey string, status int, reason stri
if
channel
.
ChannelInfo
.
IsMultiKey
{
if
channel
.
ChannelInfo
.
IsMultiKey
{
beforeStatus
:=
channel
.
Status
beforeStatus
:=
channel
.
Status
handlerMultiKeyUpdate
(
channel
,
usingKey
,
status
)
handlerMultiKeyUpdate
(
channel
,
usingKey
,
status
,
reason
)
if
beforeStatus
!=
channel
.
Status
{
if
beforeStatus
!=
channel
.
Status
{
shouldUpdateAbilities
=
true
shouldUpdateAbilities
=
true
}
}
...
...
model/channel_cache.go
View file @
aeec39a1
...
@@ -70,7 +70,7 @@ func InitChannelCache() {
...
@@ -70,7 +70,7 @@ func InitChannelCache() {
//channelsIDM = newChannelId2channel
//channelsIDM = newChannelId2channel
for
i
,
channel
:=
range
newChannelId2channel
{
for
i
,
channel
:=
range
newChannelId2channel
{
if
channel
.
ChannelInfo
.
IsMultiKey
{
if
channel
.
ChannelInfo
.
IsMultiKey
{
channel
.
Keys
=
channel
.
g
etKeys
()
channel
.
Keys
=
channel
.
G
etKeys
()
if
channel
.
ChannelInfo
.
MultiKeyMode
==
constant
.
MultiKeyModePolling
{
if
channel
.
ChannelInfo
.
MultiKeyMode
==
constant
.
MultiKeyModePolling
{
if
oldChannel
,
ok
:=
channelsIDM
[
i
];
ok
{
if
oldChannel
,
ok
:=
channelsIDM
[
i
];
ok
{
// 存在旧的渠道,如果是多key且轮询,保留轮询索引信息
// 存在旧的渠道,如果是多key且轮询,保留轮询索引信息
...
...
router/api-router.go
View file @
aeec39a1
...
@@ -120,6 +120,7 @@ func SetApiRouter(router *gin.Engine) {
...
@@ -120,6 +120,7 @@ func SetApiRouter(router *gin.Engine) {
channelRoute
.
POST
(
"/batch/tag"
,
controller
.
BatchSetChannelTag
)
channelRoute
.
POST
(
"/batch/tag"
,
controller
.
BatchSetChannelTag
)
channelRoute
.
GET
(
"/tag/models"
,
controller
.
GetTagModels
)
channelRoute
.
GET
(
"/tag/models"
,
controller
.
GetTagModels
)
channelRoute
.
POST
(
"/copy/:id"
,
controller
.
CopyChannel
)
channelRoute
.
POST
(
"/copy/:id"
,
controller
.
CopyChannel
)
channelRoute
.
POST
(
"/multi_key/manage"
,
controller
.
ManageMultiKeys
)
}
}
tokenRoute
:=
apiRouter
.
Group
(
"/token"
)
tokenRoute
:=
apiRouter
.
Group
(
"/token"
)
tokenRoute
.
Use
(
middleware
.
UserAuth
())
tokenRoute
.
Use
(
middleware
.
UserAuth
())
...
...
web/src/components/table/channels/ChannelsColumnDefs.js
View file @
aeec39a1
...
@@ -210,7 +210,9 @@ export const getChannelsColumns = ({
...
@@ -210,7 +210,9 @@ export const getChannelsColumns = ({
copySelectedChannel
,
copySelectedChannel
,
refresh
,
refresh
,
activePage
,
activePage
,
channels
channels
,
setShowMultiKeyManageModal
,
setCurrentMultiKeyChannel
})
=>
{
})
=>
{
return
[
return
[
{
{
...
@@ -503,10 +505,6 @@ export const getChannelsColumns = ({
...
@@ -503,10 +505,6 @@ export const getChannelsColumns = ({
/
>
/
>
<
/SplitButtonGroup
>
<
/SplitButtonGroup
>
{
record
.
channel_info
?.
is_multi_key
?
(
<
SplitButtonGroup
aria
-
label
=
{
t
(
'多密钥渠道操作项目组'
)}
>
{
{
record
.
status
===
1
?
(
record
.
status
===
1
?
(
<
Button
<
Button
...
@@ -525,14 +523,32 @@ export const getChannelsColumns = ({
...
@@ -525,14 +523,32 @@ export const getChannelsColumns = ({
<
/Button
>
<
/Button
>
)
)
}
}
{
record
.
channel_info
?.
is_multi_key
?
(
<
SplitButtonGroup
aria
-
label
=
{
t
(
'多密钥渠道操作项目组'
)}
>
<
Button
type
=
'tertiary'
size
=
"small"
onClick
=
{()
=>
{
setEditingChannel
(
record
);
setShowEdit
(
true
);
}}
>
{
t
(
'编辑'
)}
<
/Button
>
<
Dropdown
<
Dropdown
trigger
=
'click'
trigger
=
'click'
position
=
'bottomRight'
position
=
'bottomRight'
menu
=
{[
menu
=
{[
{
{
node
:
'item'
,
node
:
'item'
,
name
:
t
(
'启用全部密钥'
),
name
:
t
(
'多key管理'
),
onClick
:
()
=>
manageChannel
(
record
.
id
,
'enable_all'
,
record
),
onClick
:
()
=>
{
setCurrentMultiKeyChannel
(
record
);
setShowMultiKeyManageModal
(
true
);
},
}
}
]}
]}
>
>
...
@@ -544,24 +560,6 @@ export const getChannelsColumns = ({
...
@@ -544,24 +560,6 @@ export const getChannelsColumns = ({
<
/Dropdown
>
<
/Dropdown
>
<
/SplitButtonGroup
>
<
/SplitButtonGroup
>
)
:
(
)
:
(
record
.
status
===
1
?
(
<
Button
type
=
'danger'
size
=
"small"
onClick
=
{()
=>
manageChannel
(
record
.
id
,
'disable'
,
record
)}
>
{
t
(
'禁用'
)}
<
/Button
>
)
:
(
<
Button
size
=
"small"
onClick
=
{()
=>
manageChannel
(
record
.
id
,
'enable'
,
record
)}
>
{
t
(
'启用'
)}
<
/Button
>
)
)}
<
Button
<
Button
type
=
'tertiary'
type
=
'tertiary'
size
=
"small"
size
=
"small"
...
@@ -572,6 +570,7 @@ export const getChannelsColumns = ({
...
@@ -572,6 +570,7 @@ export const getChannelsColumns = ({
>
>
{
t
(
'编辑'
)}
{
t
(
'编辑'
)}
<
/Button
>
<
/Button
>
)}
<
Dropdown
<
Dropdown
trigger
=
'click'
trigger
=
'click'
...
...
web/src/components/table/channels/ChannelsTable.jsx
View file @
aeec39a1
...
@@ -57,6 +57,9 @@ const ChannelsTable = (channelsData) => {
...
@@ -57,6 +57,9 @@ const ChannelsTable = (channelsData) => {
setEditingTag
,
setEditingTag
,
copySelectedChannel
,
copySelectedChannel
,
refresh
,
refresh
,
// Multi-key management
setShowMultiKeyManageModal
,
setCurrentMultiKeyChannel
,
}
=
channelsData
;
}
=
channelsData
;
// Get all columns
// Get all columns
...
@@ -79,6 +82,8 @@ const ChannelsTable = (channelsData) => {
...
@@ -79,6 +82,8 @@ const ChannelsTable = (channelsData) => {
refresh
,
refresh
,
activePage
,
activePage
,
channels
,
channels
,
setShowMultiKeyManageModal
,
setCurrentMultiKeyChannel
,
});
});
},
[
},
[
t
,
t
,
...
@@ -98,6 +103,8 @@ const ChannelsTable = (channelsData) => {
...
@@ -98,6 +103,8 @@ const ChannelsTable = (channelsData) => {
refresh
,
refresh
,
activePage
,
activePage
,
channels
,
channels
,
setShowMultiKeyManageModal
,
setCurrentMultiKeyChannel
,
]);
]);
// Filter columns based on visibility settings
// Filter columns based on visibility settings
...
...
web/src/components/table/channels/index.jsx
View file @
aeec39a1
...
@@ -30,6 +30,7 @@ import ModelTestModal from './modals/ModelTestModal.jsx';
...
@@ -30,6 +30,7 @@ import ModelTestModal from './modals/ModelTestModal.jsx';
import
ColumnSelectorModal
from
'./modals/ColumnSelectorModal.jsx'
;
import
ColumnSelectorModal
from
'./modals/ColumnSelectorModal.jsx'
;
import
EditChannelModal
from
'./modals/EditChannelModal.jsx'
;
import
EditChannelModal
from
'./modals/EditChannelModal.jsx'
;
import
EditTagModal
from
'./modals/EditTagModal.jsx'
;
import
EditTagModal
from
'./modals/EditTagModal.jsx'
;
import
MultiKeyManageModal
from
'./modals/MultiKeyManageModal.jsx'
;
import
{
createCardProPagination
}
from
'../../../helpers/utils'
;
import
{
createCardProPagination
}
from
'../../../helpers/utils'
;
const
ChannelsPage
=
()
=>
{
const
ChannelsPage
=
()
=>
{
...
@@ -54,6 +55,12 @@ const ChannelsPage = () => {
...
@@ -54,6 +55,12 @@ const ChannelsPage = () => {
/>
/>
<
BatchTagModal
{
...
channelsData
}
/>
<
BatchTagModal
{
...
channelsData
}
/>
<
ModelTestModal
{
...
channelsData
}
/>
<
ModelTestModal
{
...
channelsData
}
/>
<
MultiKeyManageModal
visible=
{
channelsData
.
showMultiKeyManageModal
}
onCancel=
{
()
=>
channelsData
.
setShowMultiKeyManageModal
(
false
)
}
channel=
{
channelsData
.
currentMultiKeyChannel
}
onRefresh=
{
channelsData
.
refresh
}
/>
{
/* Main Content */
}
{
/* Main Content */
}
<
CardPro
<
CardPro
...
...
web/src/components/table/channels/modals/MultiKeyManageModal.jsx
0 → 100644
View file @
aeec39a1
This diff is collapsed.
Click to expand it.
web/src/hooks/channels/useChannelsData.js
View file @
aeec39a1
...
@@ -83,6 +83,10 @@ export const useChannelsData = () => {
...
@@ -83,6 +83,10 @@ export const useChannelsData = () => {
const
[
isProcessingQueue
,
setIsProcessingQueue
]
=
useState
(
false
);
const
[
isProcessingQueue
,
setIsProcessingQueue
]
=
useState
(
false
);
const
[
modelTablePage
,
setModelTablePage
]
=
useState
(
1
);
const
[
modelTablePage
,
setModelTablePage
]
=
useState
(
1
);
// Multi-key management states
const
[
showMultiKeyManageModal
,
setShowMultiKeyManageModal
]
=
useState
(
false
);
const
[
currentMultiKeyChannel
,
setCurrentMultiKeyChannel
]
=
useState
(
null
);
// Refs
// Refs
const
requestCounter
=
useRef
(
0
);
const
requestCounter
=
useRef
(
0
);
const
allSelectingRef
=
useRef
(
false
);
const
allSelectingRef
=
useRef
(
false
);
...
@@ -885,6 +889,12 @@ export const useChannelsData = () => {
...
@@ -885,6 +889,12 @@ export const useChannelsData = () => {
setModelTablePage
,
setModelTablePage
,
allSelectingRef
,
allSelectingRef
,
// Multi-key management states
showMultiKeyManageModal
,
setShowMultiKeyManageModal
,
currentMultiKeyChannel
,
setCurrentMultiKeyChannel
,
// Form
// Form
formApi
,
formApi
,
setFormApi
,
setFormApi
,
...
...
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