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
+8
View File
@@ -25,6 +25,7 @@ interface NodeState {
isServerReferencedByNodes: (serverId: number) => boolean;
getNodesByTag: (tag: string) => API.Node[];
getNodesWithoutTags: () => API.Node[];
getNodesWithoutGroups: () => API.Node[];
getNodeTags: () => string[];
getAllAvailableTags: () => string[];
}
@@ -92,6 +93,12 @@ export const useNodeStore = create<NodeState>((set, get) => ({
getNodesWithoutTags: () =>
get().nodes.filter((node) => (node.tags || []).length === 0),
getNodesWithoutGroups: () =>
get().nodes.filter((node) => {
const groupIds = (node as any).node_group_ids;
return !groupIds || groupIds.length === 0;
}),
getNodeTags: () =>
Array.from(
new Set(
@@ -135,6 +142,7 @@ export const useNode = () => {
isServerReferencedByNodes: store.isServerReferencedByNodes,
getNodesByTag: store.getNodesByTag,
getNodesWithoutTags: store.getNodesWithoutTags,
getNodesWithoutGroups: store.getNodesWithoutGroups,
getNodeTags: store.getNodeTags,
getAllAvailableTags: store.getAllAvailableTags,
};