feat(admin): add drag-and-drop group sort order

- Add `sort_order` field to groups table with migration
- Add `PUT /api/v1/admin/groups/sort-order` API for batch update
- Implement drag-and-drop UI using vue-draggable-plus
- All queries now order groups by sort_order
- Add i18n support (en/zh) for sort-related UI text
- Update test stubs to satisfy new interface methods
This commit is contained in:
bayma888
2026-02-08 16:53:45 +08:00
parent b4ec65785d
commit bac9e2bfd5
33 changed files with 611 additions and 6 deletions

View File

@@ -7059,6 +7059,8 @@ type GroupMutation struct {
mcp_xml_inject *bool
supported_model_scopes *[]string
appendsupported_model_scopes []string
sort_order *int
addsort_order *int
clearedFields map[string]struct{}
api_keys map[int64]struct{}
removedapi_keys map[int64]struct{}
@@ -8411,6 +8413,62 @@ func (m *GroupMutation) ResetSupportedModelScopes() {
m.appendsupported_model_scopes = nil
}
// SetSortOrder sets the "sort_order" field.
func (m *GroupMutation) SetSortOrder(i int) {
m.sort_order = &i
m.addsort_order = nil
}
// SortOrder returns the value of the "sort_order" field in the mutation.
func (m *GroupMutation) SortOrder() (r int, exists bool) {
v := m.sort_order
if v == nil {
return
}
return *v, true
}
// OldSortOrder returns the old "sort_order" field's value of the Group entity.
// If the Group object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *GroupMutation) OldSortOrder(ctx context.Context) (v int, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldSortOrder is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldSortOrder requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldSortOrder: %w", err)
}
return oldValue.SortOrder, nil
}
// AddSortOrder adds i to the "sort_order" field.
func (m *GroupMutation) AddSortOrder(i int) {
if m.addsort_order != nil {
*m.addsort_order += i
} else {
m.addsort_order = &i
}
}
// AddedSortOrder returns the value that was added to the "sort_order" field in this mutation.
func (m *GroupMutation) AddedSortOrder() (r int, exists bool) {
v := m.addsort_order
if v == nil {
return
}
return *v, true
}
// ResetSortOrder resets all changes to the "sort_order" field.
func (m *GroupMutation) ResetSortOrder() {
m.sort_order = nil
m.addsort_order = nil
}
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by ids.
func (m *GroupMutation) AddAPIKeyIDs(ids ...int64) {
if m.api_keys == nil {
@@ -8769,7 +8827,7 @@ func (m *GroupMutation) Type() string {
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *GroupMutation) Fields() []string {
fields := make([]string, 0, 24)
fields := make([]string, 0, 25)
if m.created_at != nil {
fields = append(fields, group.FieldCreatedAt)
}
@@ -8842,6 +8900,9 @@ func (m *GroupMutation) Fields() []string {
if m.supported_model_scopes != nil {
fields = append(fields, group.FieldSupportedModelScopes)
}
if m.sort_order != nil {
fields = append(fields, group.FieldSortOrder)
}
return fields
}
@@ -8898,6 +8959,8 @@ func (m *GroupMutation) Field(name string) (ent.Value, bool) {
return m.McpXMLInject()
case group.FieldSupportedModelScopes:
return m.SupportedModelScopes()
case group.FieldSortOrder:
return m.SortOrder()
}
return nil, false
}
@@ -8955,6 +9018,8 @@ func (m *GroupMutation) OldField(ctx context.Context, name string) (ent.Value, e
return m.OldMcpXMLInject(ctx)
case group.FieldSupportedModelScopes:
return m.OldSupportedModelScopes(ctx)
case group.FieldSortOrder:
return m.OldSortOrder(ctx)
}
return nil, fmt.Errorf("unknown Group field %s", name)
}
@@ -9132,6 +9197,13 @@ func (m *GroupMutation) SetField(name string, value ent.Value) error {
}
m.SetSupportedModelScopes(v)
return nil
case group.FieldSortOrder:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetSortOrder(v)
return nil
}
return fmt.Errorf("unknown Group field %s", name)
}
@@ -9170,6 +9242,9 @@ func (m *GroupMutation) AddedFields() []string {
if m.addfallback_group_id_on_invalid_request != nil {
fields = append(fields, group.FieldFallbackGroupIDOnInvalidRequest)
}
if m.addsort_order != nil {
fields = append(fields, group.FieldSortOrder)
}
return fields
}
@@ -9198,6 +9273,8 @@ func (m *GroupMutation) AddedField(name string) (ent.Value, bool) {
return m.AddedFallbackGroupID()
case group.FieldFallbackGroupIDOnInvalidRequest:
return m.AddedFallbackGroupIDOnInvalidRequest()
case group.FieldSortOrder:
return m.AddedSortOrder()
}
return nil, false
}
@@ -9277,6 +9354,13 @@ func (m *GroupMutation) AddField(name string, value ent.Value) error {
}
m.AddFallbackGroupIDOnInvalidRequest(v)
return nil
case group.FieldSortOrder:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddSortOrder(v)
return nil
}
return fmt.Errorf("unknown Group numeric field %s", name)
}
@@ -9445,6 +9529,9 @@ func (m *GroupMutation) ResetField(name string) error {
case group.FieldSupportedModelScopes:
m.ResetSupportedModelScopes()
return nil
case group.FieldSortOrder:
m.ResetSortOrder()
return nil
}
return fmt.Errorf("unknown Group field %s", name)
}