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
d530edad
authored
Dec 01, 2024
by
Calcium-Ion
Committed by
GitHub
Dec 01, 2024
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #587 from Calcium-Ion/channel-tag
feat: add tag aggregation mode to channels API and UI
parents
c0c9b1f6
d2fc3fa7
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
63 additions
and
40 deletions
+63
-40
controller/channel.go
+19
-23
model/channel.go
+8
-1
web/src/components/ChannelsTable.js
+36
-16
No files found.
controller/channel.go
View file @
d530edad
...
@@ -3,12 +3,13 @@ package controller
...
@@ -3,12 +3,13 @@ package controller
import
(
import
(
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"net/http"
"one-api/common"
"one-api/common"
"one-api/model"
"one-api/model"
"strconv"
"strconv"
"strings"
"strings"
"github.com/gin-gonic/gin"
)
)
type
OpenAIModel
struct
{
type
OpenAIModel
struct
{
...
@@ -48,8 +49,11 @@ func GetAllChannels(c *gin.Context) {
...
@@ -48,8 +49,11 @@ func GetAllChannels(c *gin.Context) {
if
pageSize
<
0
{
if
pageSize
<
0
{
pageSize
=
common
.
ItemsPerPage
pageSize
=
common
.
ItemsPerPage
}
}
channelData
:=
make
([]
*
model
.
Channel
,
0
)
idSort
,
_
:=
strconv
.
ParseBool
(
c
.
Query
(
"id_sort"
))
idSort
,
_
:=
strconv
.
ParseBool
(
c
.
Query
(
"id_sort"
))
channels
,
err
:=
model
.
GetAllChannels
(
p
*
pageSize
,
pageSize
,
false
,
idSort
)
enableTagMode
,
_
:=
strconv
.
ParseBool
(
c
.
Query
(
"tag_mode"
))
if
enableTagMode
{
tags
,
err
:=
model
.
GetPaginatedTags
(
p
*
pageSize
,
pageSize
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"success"
:
false
,
...
@@ -57,32 +61,24 @@ func GetAllChannels(c *gin.Context) {
...
@@ -57,32 +61,24 @@ func GetAllChannels(c *gin.Context) {
})
})
return
return
}
}
tags
:=
make
(
map
[
string
]
bool
)
for
_
,
tag
:=
range
tags
{
channelData
:=
make
([]
*
model
.
Channel
,
0
,
len
(
channels
))
if
tag
!=
nil
&&
*
tag
!=
""
{
tagChannels
:=
make
([]
*
model
.
Channel
,
0
)
tagChannel
,
err
:=
model
.
GetChannelsByTag
(
*
tag
)
for
_
,
channel
:=
range
channels
{
channelTag
:=
channel
.
GetTag
()
if
channelTag
!=
""
&&
!
tags
[
channelTag
]
{
tags
[
channelTag
]
=
true
tagChannel
,
err
:=
model
.
GetChannelsByTag
(
channelTag
)
if
err
==
nil
{
if
err
==
nil
{
tagChannels
=
append
(
tagChannels
,
tagChannel
...
)
channelData
=
append
(
channelData
,
tagChannel
...
)
}
}
else
{
channelData
=
append
(
channelData
,
channel
)
}
}
}
}
for
i
,
channel
:=
range
tagChannels
{
find
:=
false
for
_
,
can
:=
range
channelData
{
if
channel
.
Id
==
can
.
Id
{
find
=
true
break
}
}
}
else
{
channels
,
err
:=
model
.
GetAllChannels
(
p
*
pageSize
,
pageSize
,
false
,
idSort
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
}
if
!
find
{
channelData
=
channels
channelData
=
append
(
channelData
,
tagChannels
[
i
])
}
}
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"success"
:
true
,
...
...
model/channel.go
View file @
d530edad
...
@@ -2,9 +2,10 @@ package model
...
@@ -2,9 +2,10 @@ package model
import
(
import
(
"encoding/json"
"encoding/json"
"gorm.io/gorm"
"one-api/common"
"one-api/common"
"strings"
"strings"
"gorm.io/gorm"
)
)
type
Channel
struct
{
type
Channel
struct
{
...
@@ -403,3 +404,9 @@ func DeleteDisabledChannel() (int64, error) {
...
@@ -403,3 +404,9 @@ func DeleteDisabledChannel() (int64, error) {
result
:=
DB
.
Where
(
"status = ? or status = ?"
,
common
.
ChannelStatusAutoDisabled
,
common
.
ChannelStatusManuallyDisabled
)
.
Delete
(
&
Channel
{})
result
:=
DB
.
Where
(
"status = ? or status = ?"
,
common
.
ChannelStatusAutoDisabled
,
common
.
ChannelStatusManuallyDisabled
)
.
Delete
(
&
Channel
{})
return
result
.
RowsAffected
,
result
.
Error
return
result
.
RowsAffected
,
result
.
Error
}
}
func
GetPaginatedTags
(
offset
int
,
limit
int
)
([]
*
string
,
error
)
{
var
tags
[]
*
string
err
:=
DB
.
Model
(
&
Channel
{})
.
Select
(
"DISTINCT tag"
)
.
Where
(
"tag != ''"
)
.
Offset
(
offset
)
.
Limit
(
limit
)
.
Find
(
&
tags
)
.
Error
return
tags
,
err
}
web/src/components/ChannelsTable.js
View file @
d530edad
...
@@ -439,6 +439,7 @@ const ChannelsTable = () => {
...
@@ -439,6 +439,7 @@ const ChannelsTable = () => {
const
[
editingTag
,
setEditingTag
]
=
useState
(
''
);
const
[
editingTag
,
setEditingTag
]
=
useState
(
''
);
const
[
selectedChannels
,
setSelectedChannels
]
=
useState
([]);
const
[
selectedChannels
,
setSelectedChannels
]
=
useState
([]);
const
[
showEditPriority
,
setShowEditPriority
]
=
useState
(
false
);
const
[
showEditPriority
,
setShowEditPriority
]
=
useState
(
false
);
const
[
enableTagMode
,
setEnableTagMode
]
=
useState
(
false
);
const
removeRecord
=
(
record
)
=>
{
const
removeRecord
=
(
record
)
=>
{
...
@@ -464,13 +465,12 @@ const ChannelsTable = () => {
...
@@ -464,13 +465,12 @@ const ChannelsTable = () => {
}
}
};
};
const
setChannelFormat
=
(
channels
)
=>
{
const
setChannelFormat
=
(
channels
,
enableTagMode
)
=>
{
let
channelDates
=
[];
let
channelDates
=
[];
let
channelTags
=
{};
let
channelTags
=
{};
for
(
let
i
=
0
;
i
<
channels
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
channels
.
length
;
i
++
)
{
channels
[
i
].
key
=
''
+
channels
[
i
].
id
;
channels
[
i
].
key
=
''
+
channels
[
i
].
id
;
if
(
!
enableTagMode
)
{
if
(
channels
[
i
].
tag
===
''
||
channels
[
i
].
tag
===
null
)
{
let
test_models
=
[];
let
test_models
=
[];
channels
[
i
].
models
.
split
(
','
).
forEach
((
item
,
index
)
=>
{
channels
[
i
].
models
.
split
(
','
).
forEach
((
item
,
index
)
=>
{
test_models
.
push
({
test_models
.
push
({
...
@@ -554,10 +554,10 @@ const ChannelsTable = () => {
...
@@ -554,10 +554,10 @@ const ChannelsTable = () => {
}
}
};
};
const
loadChannels
=
async
(
startIdx
,
pageSize
,
idSort
)
=>
{
const
loadChannels
=
async
(
startIdx
,
pageSize
,
idSort
,
enableTagMode
)
=>
{
setLoading
(
true
);
setLoading
(
true
);
const
res
=
await
API
.
get
(
const
res
=
await
API
.
get
(
`/api/channel/?p=
${
startIdx
}
&page_size=
${
pageSize
}
&id_sort=
${
idSort
}
`
`/api/channel/?p=
${
startIdx
}
&page_size=
${
pageSize
}
&id_sort=
${
idSort
}
&tag_mode=
${
enableTagMode
}
`
);
);
if
(
res
===
undefined
)
{
if
(
res
===
undefined
)
{
return
;
return
;
...
@@ -565,11 +565,11 @@ const ChannelsTable = () => {
...
@@ -565,11 +565,11 @@ const ChannelsTable = () => {
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
success
)
{
if
(
startIdx
===
0
)
{
if
(
startIdx
===
0
)
{
setChannelFormat
(
data
);
setChannelFormat
(
data
,
enableTagMode
);
}
else
{
}
else
{
let
newChannels
=
[...
channels
];
let
newChannels
=
[...
channels
];
newChannels
.
splice
(
startIdx
*
pageSize
,
data
.
length
,
...
data
);
newChannels
.
splice
(
startIdx
*
pageSize
,
data
.
length
,
...
data
);
setChannelFormat
(
newChannels
);
setChannelFormat
(
newChannels
,
enableTagMode
);
}
}
}
else
{
}
else
{
showError
(
message
);
showError
(
message
);
...
@@ -602,7 +602,7 @@ const ChannelsTable = () => {
...
@@ -602,7 +602,7 @@ const ChannelsTable = () => {
};
};
const
refresh
=
async
()
=>
{
const
refresh
=
async
()
=>
{
await
loadChannels
(
activePage
-
1
,
pageSize
,
idSort
);
await
loadChannels
(
activePage
-
1
,
pageSize
,
idSort
,
enableTagMode
);
};
};
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -612,7 +612,7 @@ const ChannelsTable = () => {
...
@@ -612,7 +612,7 @@ const ChannelsTable = () => {
parseInt
(
localStorage
.
getItem
(
'page-size'
))
||
ITEMS_PER_PAGE
;
parseInt
(
localStorage
.
getItem
(
'page-size'
))
||
ITEMS_PER_PAGE
;
setIdSort
(
localIdSort
);
setIdSort
(
localIdSort
);
setPageSize
(
localPageSize
);
setPageSize
(
localPageSize
);
loadChannels
(
0
,
localPageSize
,
localIdSort
)
loadChannels
(
0
,
localPageSize
,
localIdSort
,
enableTagMode
)
.
then
()
.
then
()
.
catch
((
reason
)
=>
{
.
catch
((
reason
)
=>
{
showError
(
reason
);
showError
(
reason
);
...
@@ -770,18 +770,22 @@ const ChannelsTable = () => {
...
@@ -770,18 +770,22 @@ const ChannelsTable = () => {
const
searchChannels
=
async
(
searchKeyword
,
searchGroup
,
searchModel
)
=>
{
const
searchChannels
=
async
(
searchKeyword
,
searchGroup
,
searchModel
)
=>
{
if
(
searchKeyword
===
''
&&
searchGroup
===
''
&&
searchModel
===
''
)
{
if
(
searchKeyword
===
''
&&
searchGroup
===
''
&&
searchModel
===
''
)
{
// if keyword is blank, load files instead.
await
loadChannels
(
0
,
pageSize
,
idSort
,
enableTagMode
);
await
loadChannels
(
0
,
pageSize
,
idSort
);
setActivePage
(
1
);
setActivePage
(
1
);
return
;
return
;
}
}
setSearching
(
true
);
setSearching
(
true
);
const
res
=
await
API
.
get
(
const
res
=
await
API
.
get
(
`/api/channel/search?keyword=
${
searchKeyword
}
&group=
${
searchGroup
}
&model=
${
searchModel
}
&id_sort=
${
idSort
}
`
`/api/channel/search?keyword=
${
searchKeyword
}
&group=
${
searchGroup
}
&model=
${
searchModel
}
&id_sort=
${
idSort
}
&tag_mode=
${
enableTagMode
}
`
);
);
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
success
)
{
setChannelFormat
(
data
);
if
(
enableTagMode
)
{
setChannelFormat
(
data
,
enableTagMode
);
}
else
{
setChannels
(
data
.
map
(
channel
=>
({...
channel
,
key
:
''
+
channel
.
id
})));
setChannelCount
(
data
.
length
);
}
setActivePage
(
1
);
setActivePage
(
1
);
}
else
{
}
else
{
showError
(
message
);
showError
(
message
);
...
@@ -887,7 +891,7 @@ const ChannelsTable = () => {
...
@@ -887,7 +891,7 @@ const ChannelsTable = () => {
setActivePage
(
page
);
setActivePage
(
page
);
if
(
page
===
Math
.
ceil
(
channels
.
length
/
pageSize
)
+
1
)
{
if
(
page
===
Math
.
ceil
(
channels
.
length
/
pageSize
)
+
1
)
{
// In this case we have to load more data and then append them.
// In this case we have to load more data and then append them.
loadChannels
(
page
-
1
,
pageSize
,
idSort
).
then
((
r
)
=>
{
loadChannels
(
page
-
1
,
pageSize
,
idSort
,
enableTagMode
).
then
((
r
)
=>
{
});
});
}
}
};
};
...
@@ -896,7 +900,7 @@ const ChannelsTable = () => {
...
@@ -896,7 +900,7 @@ const ChannelsTable = () => {
localStorage
.
setItem
(
'page-size'
,
size
+
''
);
localStorage
.
setItem
(
'page-size'
,
size
+
''
);
setPageSize
(
size
);
setPageSize
(
size
);
setActivePage
(
1
);
setActivePage
(
1
);
loadChannels
(
0
,
size
,
idSort
)
loadChannels
(
0
,
size
,
idSort
,
enableTagMode
)
.
then
()
.
then
()
.
catch
((
reason
)
=>
{
.
catch
((
reason
)
=>
{
showError
(
reason
);
showError
(
reason
);
...
@@ -1052,7 +1056,7 @@ const ChannelsTable = () => {
...
@@ -1052,7 +1056,7 @@ const ChannelsTable = () => {
onChange
=
{(
v
)
=>
{
onChange
=
{(
v
)
=>
{
localStorage
.
setItem
(
'id-sort'
,
v
+
''
);
localStorage
.
setItem
(
'id-sort'
,
v
+
''
);
setIdSort
(
v
);
setIdSort
(
v
);
loadChannels
(
0
,
pageSize
,
v
)
loadChannels
(
0
,
pageSize
,
v
,
enableTagMode
)
.
then
()
.
then
()
.
catch
((
reason
)
=>
{
.
catch
((
reason
)
=>
{
showError
(
reason
);
showError
(
reason
);
...
@@ -1153,6 +1157,22 @@ const ChannelsTable = () => {
...
@@ -1153,6 +1157,22 @@ const ChannelsTable = () => {
<
/Popconfirm
>
<
/Popconfirm
>
<
/Space
>
<
/Space
>
<
/div
>
<
/div
>
<
div
style
=
{{
marginTop
:
20
}}
>
<
Space
>
<
Typography
.
Text
strong
>
标签聚合模式
<
/Typography.Text
>
<
Switch
checked
=
{
enableTagMode
}
label
=
"标签聚合模式"
uncheckedText
=
"关"
aria
-
label
=
"是否启用标签聚合"
onChange
=
{(
v
)
=>
{
setEnableTagMode
(
v
);
// 切换模式时重新加载数据
loadChannels
(
0
,
pageSize
,
idSort
,
v
);
}}
/
>
<
/Space
>
<
/div
>
<
Table
<
Table
...
...
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