feat(group): add node group management UI

Add node group management interface with automatic user assignment and traffic-based grouping.

Features:
- Node group CRUD with traffic range configuration
- Three grouping modes: average, subscription-based, and traffic-based
- Group recalculation with preview and history tracking
- Subscribe-to-group mapping management
- User subscription group locking
- Group calculation history with detailed reports
- Multi-language support (en-US, zh-CN)
- Enhanced node and subscription forms with group selection
This commit is contained in:
EUForest
2026-03-08 23:39:30 +08:00
parent dc55d85056
commit ae31019477
55 changed files with 6249 additions and 262 deletions
@@ -1,4 +1,5 @@
{
"all": "All",
"cancel": "Cancel",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
@@ -7,13 +8,16 @@
"create": "Create",
"createSubscribe": "Create Subscription",
"createSuccess": "Create Successful",
"currentUserGroup": "Current User Group",
"defaultNodeGroup": "Default Node Group",
"delete": "Delete",
"nodeGroups": "Node Groups",
"nodes": "nodes",
"deleteSuccess": "Delete Successful",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"deviceLimit": "IP Limit",
"edit": "Edit",
"editSubscribe": "Edit Subscription",
"sortSuccess": "Sort completed successfully",
"form": {
"annualReset": "Annual Reset",
"basic": "Basic",
@@ -30,7 +34,6 @@
"discountPercent": "Discount Percentage",
"Hour": "Hour",
"inventory": "Subscription Limit",
"unlimitedInventory": "Unlimited (enter -1)",
"language": "Language",
"languageDescription": "Leave empty for default without language restriction",
"languagePlaceholder": "Language identifier for the subscription, e.g., en-US, zh-CN",
@@ -40,7 +43,19 @@
"name": "Name",
"node": "Node",
"nodeGroup": "Node Group",
"nodes": "Nodes",
"nodeGroups": "Node Groups",
"nodeGroupsDescription": "Assign this product to multiple node groups. Users will get nodes from these groups.",
"nodeGroupsFirstSelectionDescription": "Select node groups for this product. The first selected group will be set as the default node group.",
"defaultNodeGroup": "Default Node Group",
"defaultNodeGroupDescription": "Select the default node group for this product. This will be automatically included in the backup node groups.",
"selectDefaultNodeGroup": "Select a default node group...",
"noDefaultNodeGroup": "No Default Node Group",
"backupNodeGroups": "Backup Node Groups",
"backupNodeGroupsDescription": "Select additional backup node groups. The default node group is automatically included.",
"nodes": "Linked Nodes",
"nodesDescription": "Select nodes for this subscription",
"nodesInGroup": "Nodes in this group:",
"nodesWithoutGroupsDescription": "Nodes without group assignment will be shown here (nodes that belong to groups are managed in the Node Groups section above)",
"noLimit": "No Limit",
"NoLimit": "No Limit",
"noReset": "No Reset",
@@ -61,16 +76,42 @@
"traffic": "Traffic",
"unitPrice": "Unit Price",
"unitTime": "Unit Time",
"unlimitedInventory": "Unlimited (enter -1)",
"Year": "Year"
},
"groupMapping": "Group Mapping",
"groupMappingTitle": "Group Mapping",
"groupMappingUpdateFailed": "Failed to update group mapping",
"groupMappingUpdateSuccess": "Group mapping updated successfully",
"migrateUsers": "Migrate Users",
"migrateUsersTitle": "Migrate Users",
"migrateUsersDescription": "Migrate all users from the current user group to another group",
"migrateUsersWarning": "This will migrate {count} users from \"{group}\" to the target group. This action cannot be undone.",
"migrateUsersSuccess": "Successfully migrated {count} users to the target group",
"migrateUsersFailed": "Failed to migrate users",
"targetUserGroup": "Target User Group",
"selectTargetGroup": "Select a target group...",
"selectTargetGroupFirst": "Please select a target group first",
"cannotMigrateToSameGroup": "Cannot migrate to the same group",
"noSourceGroup": "No source group available",
"selectedGroup": "Selected Group",
"userCount": "User Count",
"migrating": "Migrating...",
"inventory": "Subscription Limit",
"language": "Language",
"loading": "Loading...",
"name": "Name",
"noMapping": "No mapping set",
"noNodes": "No nodes in this group",
"quota": "Purchase Limit/Time",
"replacement": "Reset Price/Time",
"save": "Save",
"selectGroupPlaceholder": "Select a group...",
"selectUserGroup": "Select User Group",
"sell": "Sell",
"show": "Display",
"sold": "Subscription Count",
"sortSuccess": "Sort completed successfully",
"traffic": "Traffic",
"unitPrice": "Unit Price",
"updateSuccess": "Update Successful"