Feat/auto group (#6590)

* feat(token): support custom auto group order

* feat(keys): enhance auto group presentation

* fix(keys): rework Auto flow border and compact inherited order

The Auto group highlight previously tinted the whole control surface
with a gradient and animated only a 1px top sweep, which read as a
background color rather than a flowing border. Replace it with a
border-only effect: an aria-hidden, pointer-events-none overlay whose
conic gradient is masked down to a thin ring hugging the rounded
perimeter, so the highlight travels around all four edges and corners
every 3.2s. The interior stays neutral with a restrained static
primary border and glow; prefers-reduced-motion hides the moving
layer while keeping the static emphasis.

The inherited global Auto order also rendered as spacious two-line
rows with circular sequence markers, wasting drawer space. Render it
as a compact wrapping strip of one-line chips (index, name, ratio
badge) with descriptions kept accessible via title and sr-only text,
scrolling only past a much smaller max height.

Custom add/remove/reorder editing, empty-array inheritance semantics,
and the submit payload are unchanged.

* fix(keys): preserve Auto inheritance and unify effects

* refactor(keys): temporarily disable AutoGroupBadge in api-key-group-cell
This commit is contained in:
Calcium-Ion
2026-08-01 23:19:01 +08:00
committed by GitHub
parent bd585d78ef
commit 0ab0202060
57 changed files with 3922 additions and 210 deletions
+33
View File
@@ -1,15 +1,27 @@
package setting
import (
"fmt"
"strconv"
"sync/atomic"
"github.com/QuantumNous/new-api/common"
)
const DefaultMaxTokenAutoGroups = 5
var autoGroups = []string{
"default",
}
var DefaultUseAutoGroup = false
var maxTokenAutoGroups atomic.Int64
func init() {
maxTokenAutoGroups.Store(DefaultMaxTokenAutoGroups)
}
func ContainsAutoGroup(group string) bool {
for _, autoGroup := range autoGroups {
if autoGroup == group {
@@ -35,3 +47,24 @@ func AutoGroups2JsonString() string {
func GetAutoGroups() []string {
return autoGroups
}
func GetMaxTokenAutoGroups() int {
return int(maxTokenAutoGroups.Load())
}
func ValidateMaxTokenAutoGroups(value string) error {
maxCount, err := strconv.Atoi(value)
if err != nil || maxCount <= 0 {
return fmt.Errorf("MaxTokenAutoGroups must be a positive integer")
}
return nil
}
func UpdateMaxTokenAutoGroups(value string) error {
if err := ValidateMaxTokenAutoGroups(value); err != nil {
return err
}
maxCount, _ := strconv.Atoi(value)
maxTokenAutoGroups.Store(int64(maxCount))
return nil
}
+29
View File
@@ -0,0 +1,29 @@
package setting
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUpdateMaxTokenAutoGroupsAcceptsAnyPositiveInteger(t *testing.T) {
original := GetMaxTokenAutoGroups()
t.Cleanup(func() {
require.NoError(t, UpdateMaxTokenAutoGroups(fmt.Sprintf("%d", original)))
})
require.NoError(t, UpdateMaxTokenAutoGroups("123456"))
assert.Equal(t, 123456, GetMaxTokenAutoGroups())
}
func TestUpdateMaxTokenAutoGroupsRejectsInvalidValuesWithoutChangingState(t *testing.T) {
original := GetMaxTokenAutoGroups()
for _, value := range []string{"", "0", "-1", "1.5", "not-a-number"} {
t.Run(value, func(t *testing.T) {
assert.Error(t, UpdateMaxTokenAutoGroups(value))
assert.Equal(t, original, GetMaxTokenAutoGroups())
})
}
}