merge: 同步 upstream/main 新功能到定制版本
Build and Release / Build (push) Has been cancelled
Issue Close Require / issue-close-require (push) Has been cancelled

- 分流规则 + 用户流量统计
- 验证码功能
- 节点分组管理 UI
- 重构用户分组组件
This commit is contained in:
2026-03-19 03:16:59 -07:00
89 changed files with 7036 additions and 383 deletions
@@ -1,4 +1,11 @@
{
"captcha": {
"clickToRefresh": "点击刷新",
"noImage": "无图片",
"placeholder": "请输入验证码...",
"refresh": "刷新验证码",
"required": "请输入验证码"
},
"check": {
"description": "验证您的身份",
"title": "验证"
@@ -40,6 +40,8 @@
"40005": "您没有访问权限,如有疑问请联系管理员。",
"50001": "找不到对应的优惠券信息,请检查后重试。",
"50002": "该优惠券已被使用,无法再次使用。",
"50003": "",
"50004": "",
"60001": "订阅已过期,请续费后使用。",
"60002": "暂时无法使用该订阅,请稍后再试。",
"60003": "检测到现有订阅,请先取消后再继续。",
@@ -0,0 +1,201 @@
{
"actions": "操作",
"autoTrigger": "自动",
"averageMode": "平均分组",
"cancel": "取消",
"completed": "已完成",
"confirm": "确认",
"confirmDelete": "确认删除",
"config": "配置",
"create": "创建",
"created": "创建成功",
"createdAt": "创建时间",
"createNodeGroup": "创建节点组",
"createUserGroup": "创建用户组",
"delete": "删除",
"deleted": "删除成功",
"deleteNodeGroupConfirm": "此操作将删除节点组。该组中的节点将被重新分配。",
"deleteUserGroupConfirm": "此操作将删除用户组。该组中的用户将被重新分配到默认组。",
"description": "描述",
"descriptionPlaceholder": "输入描述",
"edit": "编辑",
"editNodeGroup": "编辑节点组",
"editUserGroup": "编辑用户组",
"editUserGroupDescription": "编辑用户组分配和锁定状态",
"selectGroup": "选择一个组",
"endTime": "结束时间",
"errorMessage": "错误信息",
"export": "导出",
"failed": "失败",
"failedCount": "失败",
"groupConfig": "分组配置",
"groupConfigDescription": "管理节点组并自动为用户订阅分配节点组",
"groupDetails": "分组详情",
"groupEnabled": "启用分组管理",
"groupEnabledDescription": "启用分组管理以控制用户对节点的访问",
"groupHistory": "分组计算历史",
"groupHistoryDescription": "查看分组重算历史和结果",
"groupHistoryDetail": "分组计算详情",
"groupId": "分组ID",
"groupIdPlaceholder": "输入唯一的分组ID",
"groupMode": "分组模式",
"groupModeDescription": "选择分组算法以将用户分配到组",
"groupName": "分组名称",
"groupNamePlaceholder": "输入分组名称",
"groupRecalculation": "分组重新计算",
"groupRecalculationDescription": "根据当前配置手动触发所有有效用户订阅的节点组重新分配",
"history": "历史记录",
"historyId": "历史ID",
"id": "ID",
"idPrefix": "#",
"idle": "空闲",
"separator": "",
"loading": "加载中...",
"loadFailed": "加载配置失败",
"locked": "已锁定",
"manualTrigger": "手动",
"name": "名称",
"namePlaceholder": "输入名称",
"nodeCount": "节点数",
"nodeGroup": "节点组",
"nodeGroupFormDescription": "配置节点组设置",
"nodeGroups": "节点组",
"nodeGroupsDescription": "管理节点组以控制用户访问权限",
"noDetails": "暂无详情",
"operator": "操作人",
"progress": "进度",
"recalculate": "重新计算",
"recalculateAll": "重新分配节点组",
"recalculationCompleted": "重新计算成功完成",
"recalculationFailed": "重新计算失败,请重试。",
"recalculationStarted": "重新计算已启动",
"recalculationWarning": "重新计算将根据当前配置重新分配所有有效用户订阅的节点组。此操作无法撤消。",
"running": "运行中",
"save": "保存",
"scheduleTrigger": "定时",
"sort": "排序",
"sortOrder": "排序顺序",
"startTime": "开始时间",
"subscribeMode": "套餐分组",
"successCount": "成功",
"title": "分组管理",
"totalUsers": "总用户数",
"totalNodes": "总节点数",
"totalGroups": "总分组数",
"trafficMode": "流量分组",
"triggerType": "触发类型",
"userGroup": "用户组",
"userGroups": "用户组",
"userGroupsDescription": "管理用户组以控制节点访问权限",
"updated": "更新成功",
"updateFailed": "更新失败",
"userCount": "用户数",
"viewDetail": "查看详情",
"warning": "警告",
"yes": "是",
"no": "否",
"saving": "保存中...",
"enableGrouping": "启用分组",
"enableGroupingDescription": "启用后,用户订阅将根据分配模式自动分配节点组",
"groupingMode": "分组方式",
"averageModeConfig": "平均模式配置",
"subscribeModeConfig": "订阅模式配置",
"trafficModeConfig": "流量模式配置",
"averageModeDescription": "为有效用户订阅随机分配可用节点组",
"subscribeModeDescription": "根据订阅套餐设置用户组的默认节点组",
"trafficModeDescription": "根据用户订阅的流量使用情况分配节点组",
"defaultUserGroupId": "默认用户组ID",
"defaultUserGroupDescription": "新用户将被分配到此组",
"defaultUserGroupForExpiredDescription": "订阅过期的用户将被分配到此组",
"autoCreateGroup": "自动创建组",
"autoCreateGroupDescription": "添加新订阅计划时自动创建新的用户组",
"lockGroup": "锁定分组",
"lockGroupDescription": "防止自动重新计算更改此用户的分组",
"trafficRangesComingSoon": "流量区间配置即将推出...",
"currentStatus": "当前状态",
"trafficRangesConfig": "流量区间配置",
"trafficRangesDescription": "配置用户流量分组区间。流量根据用户计费周期计算。",
"minTrafficGB": "最小流量 (GB)",
"maxTrafficGB": "最大流量 (GB)",
"addRange": "添加区间",
"remove": "移除",
"note": "注意",
"trafficRangesNote": "区间不能重叠且必须覆盖所有值而不留空档。流量大于最后一个区间上限的用户将被分配到最后一个组。",
"defaultUserGroup": "默认用户组",
"defaultUserGroupForTrafficDescription": "超出所有定义区间的用户将被分配到此组",
"rangeError": "区间错误",
"overlapError": "区间重叠错误",
"gapError": "存在空档错误",
"groupByTraffic": "按流量分组",
"resetGroups": "重置所有分组",
"resetGroupsTitle": "重置所有分组",
"resetGroupsDescription": "此操作将删除所有节点组和用户组,将所有用户的组ID重置为0,清空所有商品的节点组ID,清空所有节点的节点组ID。此操作无法撤消。",
"resetSuccess": "所有分组已成功重置",
"resetFailed": "重置分组失败",
"saved": "配置保存成功",
"saveFailed": "保存配置失败",
"autoCalculated": "自动统计",
"userGroupCountAutoCalculated": "自动统计实际用户组数量",
"userGroupCount": "用户组数",
"nodeGroupCountAutoCalculated": "自动统计实际节点组数量",
"nodeGroupCount": "节点组数",
"arrow": " → ",
"availableNodeGroups": "可用节点组",
"currentGroupingResult": "当前分组结果",
"calculationInfo": "计算信息",
"groupingDetailsStatistics": "分组详情统计",
"successFailedCount": "成功/失败",
"latestGroupingCalculation": "最新分组计算详情",
"userList": "用户列表",
"email": "邮箱",
"noUsers": "未找到用户",
"showing": "显示",
"to": "至",
"of": "共",
"previous": "上一页",
"next": "下一页",
"result": "结果",
"bindNodeGroup": "绑定节点组",
"bindNodeGroupDescription": "选择一个节点组绑定到以下用户组:{{userGroups}}",
"selectNodeGroup": "选择节点组",
"selectNodeGroupPlaceholder": "请选择节点组...",
"selectNodeGroupRequired": "请选择一个节点组",
"unbound": "未绑定",
"bindSuccess": "成功将 {{userGroupCount}} 个用户组绑定到节点组",
"bindFailed": "绑定节点组失败",
"groupMapping": "分组对应关系",
"forCalculation": "参与计算",
"trafficRange": "流量区间 (GB)",
"configSaved": "配置保存成功",
"subscribeGroupMappingTitle": "套餐-节点组对应关系",
"subscribeName": "订阅计划",
"userGroupName": "用户组",
"nodeGroupName": "节点组",
"notMapped": "未映射",
"noMappingData": "暂无映射数据",
"forCalculationDescription": "此节点组是否参与分组计算",
"trafficRangeGB": "流量区间 (GB)",
"trafficRangeDescription": "流量大于等于最小值且小于最大值的用户将被分配到此节点组",
"minCannotExceedMax": "最小流量不能超过最大流量",
"rangeOverlap": "区间与节点组 \"{{name}}\" 重叠",
"nodeGroupNotFound": "未找到节点组",
"validationFailed": "验证失败",
"totalNodeGroups": "总节点组数",
"invalidRange": "最小流量必须小于最大流量",
"rangeConflict": "流量区间与节点组 \"{{name}}\" 冲突(区间:{{min}} - {{max}} GB",
"isExpiredGroup": "过期节点组",
"isExpiredGroupDescription": "允许过期用户使用受限节点",
"expiredDaysLimit": "过期天数限制",
"expiredDaysLimitDescription": "用户订阅过期后仍可访问节点的天数",
"maxTrafficGBExpired": "过期用户最大流量 (GB)",
"maxTrafficGBExpiredDescription": "过期用户允许使用的最大流量(0 = 不限制)",
"speedLimit": "限速 (KB/s)",
"speedLimitDescription": "该节点组用户的速度限制(0 = 不限制)",
"expiredGroup": "过期专用",
"expiredSettings": "过期设置",
"days": "天",
"expiredGroupExists": "系统中已存在过期节点组:{{name}}",
"nodeGroupUsedBySubscribe": "该节点组已被订阅商品设置为默认节点组,不能设为过期节点组",
"expiredGroupForCalculationDescription": "过期专用节点组不能参与分组计算"
}
@@ -10,6 +10,7 @@
"Document Management": "文档管理",
"Email": "邮件",
"Gift": "赠送",
"Group Management": "分组管理",
"Login": "登录",
"Logs & Analytics": "日志与分析",
"Maintenance": "维护",
@@ -1,5 +1,6 @@
{
"address": "地址",
"all": "全部",
"cancel": "取消",
"confirm": "确认",
"confirmDeleteDesc": "此操作无法撤销。",
@@ -17,15 +18,21 @@
"enabled_off": "已禁用",
"enabled_on": "已启用",
"name": "名称",
"nodeGroup": "节点分组",
"nodeGroups": "节点分组",
"nodeGroup_description": "将此节点分配到多个分组以控制用户访问。",
"pageTitle": "节点",
"port": "端口",
"protocol": "协议",
"public": "公共",
"selectNodeGroup": "选择节点分组…",
"select_protocol": "选择协议…",
"select_server": "选择服务器…",
"server": "服务器",
"sorted_success": "排序成功",
"tags": "标签",
"tags_description": "权限分组标签(包含计划绑定和投递策略)。",
"tags_groupMode_description": "可选标签,用于显示和过滤(如果为空,节点组名称将作为标签使用)。",
"tags_placeholder": "使用回车或逗号 (,) 添加多个标签",
"updated": "已更新"
}
@@ -1,4 +1,5 @@
{
"all": "全部",
"cancel": "取消",
"confirm": "确认",
"confirmDelete": "确定要删除吗?",
@@ -7,13 +8,16 @@
"create": "创建",
"createSubscribe": "创建订阅",
"createSuccess": "创建成功",
"currentUserGroup": "当前用户分组",
"defaultNodeGroup": "默认节点组",
"delete": "删除",
"nodeGroups": "节点组",
"nodes": "个节点",
"deleteSuccess": "删除成功",
"deleteWarning": "删除后数据无法恢复,请谨慎操作。",
"deviceLimit": "IP限制",
"edit": "编辑",
"editSubscribe": "编辑订阅",
"sortSuccess": "排序成功",
"form": {
"annualReset": "年度重置",
"basic": "基本",
@@ -30,7 +34,6 @@
"discountPercent": "折扣百分比",
"Hour": "小时",
"inventory": "订阅库存",
"unlimitedInventory": "无限制(输入 -1",
"language": "语言",
"languageDescription": "留空为默认无语言限制",
"languagePlaceholder": "订阅的语言标识符,例如 en-US、zh-CN",
@@ -40,7 +43,19 @@
"name": "名称",
"node": "节点",
"nodeGroup": "节点组",
"nodes": "节点",
"nodeGroups": "节点",
"nodeGroupsDescription": "将此商品分配到多个节点分组。用户将可以从这些分组获取节点。",
"nodeGroupsFirstSelectionDescription": "为此商品选择节点组。第一个选中的组将被设置为默认节点组。",
"defaultNodeGroup": "默认节点组",
"defaultNodeGroupDescription": "为此商品选择默认节点组。将自动包含在备用节点组中。",
"selectDefaultNodeGroup": "选择默认节点组...",
"noDefaultNodeGroup": "无默认节点组",
"backupNodeGroups": "备用节点组",
"backupNodeGroupsDescription": "选择其他备用节点组。默认节点组会自动包含。",
"nodes": "关联节点",
"nodesDescription": "选择此订阅的节点",
"nodesInGroup": "分组中的节点:",
"nodesWithoutGroupsDescription": "未分配到分组的节点将在此处显示(属于分组的节点在上方的节点组部分管理)",
"noLimit": "无限制",
"NoLimit": "无限制",
"noReset": "不重置",
@@ -59,18 +74,55 @@
"showOriginalPriceDescription": "开启后,在订阅卡片上将会显示原价和折后价,帮助用户了解优惠幅度",
"speedLimit": "速度限制",
"traffic": "流量",
"trafficLimit": "按量限速",
"trafficLimitRules": "按量限速规则",
"trafficLimitDescription": "配置基于流量的限速规则。当流量使用达到指定量时,将进行限速。",
"addTrafficLimitRule": "添加限速规则",
"statType": "统计类型",
"selectStatType": "选择类型...",
"statTypeHour": "小时",
"statTypeDay": "天",
"statValue": "时间值",
"trafficUsage": "使用流量(GB",
"speedLimitKb": "限速(kb",
"unitPrice": "单价",
"unitTime": "时间单位",
"unlimitedInventory": "无限制(输入 -1",
"Year": "年"
},
"groupMapping": "分组映射",
"groupMappingTitle": "分组映射",
"groupMappingUpdateFailed": "更新分组映射失败",
"groupMappingUpdateSuccess": "分组映射更新成功",
"migrateUsers": "迁移用户",
"migrateUsersTitle": "迁移用户",
"migrateUsersDescription": "将当前用户组的所有用户迁移到另一个用户组",
"migrateUsersWarning": "这将把 {count} 个用户从 \"{group}\" 迁移到目标用户组。此操作无法撤销。",
"migrateUsersSuccess": "成功将 {count} 个用户迁移到目标用户组",
"migrateUsersFailed": "迁移用户失败",
"targetUserGroup": "目标用户组",
"selectTargetGroup": "选择目标用户组...",
"selectTargetGroupFirst": "请先选择目标用户组",
"cannotMigrateToSameGroup": "无法迁移到相同的用户组",
"noSourceGroup": "没有可用的源用户组",
"selectedGroup": "已选择的分组",
"userCount": "用户数量",
"migrating": "迁移中...",
"inventory": "订阅库存",
"language": "语言",
"loading": "加载中...",
"name": "名称",
"noMapping": "未设置映射",
"noNodes": "该分组下没有节点",
"quota": "购买限制/次",
"replacement": "重置价格/次",
"save": "保存",
"selectGroupPlaceholder": "选择分组...",
"selectUserGroup": "选择用户分组",
"sell": "销售",
"show": "显示",
"sold": "订阅数量",
"sortSuccess": "排序成功",
"traffic": "流量",
"unitPrice": "单价",
"updateSuccess": "更新成功"
@@ -1,5 +1,4 @@
{
"active": "有效",
"cancel": "取消",
"code": "兑换码",
"confirm": "确认",
@@ -13,7 +12,6 @@
"duration": "兑换可用时长",
"edit": "编辑",
"editRedemptionCode": "编辑兑换码",
"exhausted": "已用尽",
"form": {
"batchCount": "批次数量",
"batchCountPlaceholder": "批次数量",
@@ -26,16 +24,12 @@
"halfYear": "半年",
"month": "月",
"quarter": "季度",
"quantityRequired": "数量为必填项",
"selectPlan": "选择兑换套餐",
"selectUnitTime": "选择兑换时长单位",
"subscribePlan": "兑换套餐",
"subscribePlanRequired": "兑换套餐为必填项",
"totalCount": "兑换码可用次数",
"totalCountPlaceholder": "兑换码可用次数",
"totalCountRequired": "兑换码可用次数为必填项",
"unitTime": "兑换时长单位",
"unitTimeRequired": "兑换时长单位为必填项",
"year": "年"
},
"id": "ID",
@@ -50,8 +44,8 @@
"status": "状态",
"subscribeId": "套餐ID",
"subscribePlan": "兑换套餐",
"totalCount": "兑换码可用次数",
"total": "总计",
"totalCount": "兑换码可用次数",
"unitTime": "兑换时长单位",
"updateSuccess": "更新成功",
"usedCount": "已使用数量",
@@ -20,6 +20,7 @@
"description": "配置货币单位、符号和汇率 API 设置",
"title": "货币配置"
},
"groupSettings": "",
"invite": {
"description": "配置用户邀请和推荐奖励设置",
"forcedInvite": "强制邀请注册",
@@ -124,13 +125,20 @@
},
"userSecuritySettings": "用户与安全",
"verify": {
"description": "配置 Turnstile 验证码和验证设置",
"enableLoginVerify": "登录验证",
"enableLoginVerifyDescription": "启用后,用户登录时必须通过人机验证",
"enablePasswordVerify": "密码重置验证",
"enablePasswordVerifyDescription": "启用后,用户重置密码时必须通过人机验证",
"enableRegisterVerify": "注册验证",
"enableRegisterVerifyDescription": "启用后,用户注册时必须通过人机验证",
"captchaType": "验证码类型",
"captchaTypeDescription": "选择本地图形验证码(离线)或 Cloudflare Turnstile",
"captchaTypeLocal": "本地图形验证",
"captchaTypePlaceholder": "选择验证码类型",
"captchaTypeTurnstile": "Cloudflare Turnstile",
"description": "配置验证码类型和验证设置",
"enableAdminLoginCaptcha": "启用管理端认证验证",
"enableAdminLoginCaptchaDescription": "启用后,管理员登录或重置密码时必须通过验证码验证",
"enableUserLoginCaptcha": "启用用户端登录验证码",
"enableUserLoginCaptchaDescription": "启用后,用户登录时必须通过验证码验证",
"enableUserRegisterCaptcha": "启用用户端注册验证码",
"enableUserRegisterCaptchaDescription": "启用后,用户注册时必须通过验证码验证",
"enableUserResetPasswordCaptcha": "启用用户重置密码验证码",
"enableUserResetPasswordCaptchaDescription": "启用后,用户重置密码时必须通过验证码验证",
"saveFailed": "保存失败",
"saveSuccess": "保存成功",
"title": "安全验证",
@@ -12,6 +12,7 @@
"systemReboot": "系统重启",
"systemServices": "系统服务",
"update": "更新",
"updateDescription": "",
"updateFailed": "更新失败",
"updateServerDescription": "确定要将服务器版本从 {{current}} 更新到 {{latest}} 吗?",
"updateSuccess": "更新成功",
@@ -7,6 +7,10 @@
"serverRequired": "请选择服务器"
},
"form": {
"quantityRequired": "",
"subscribePlanRequired": "",
"totalCountRequired": "",
"unitTimeRequired": "",
"validation": {
"nameRequired": "客户端名称必填",
"userAgentRequiredSuffix": "是必填项"
@@ -2,6 +2,7 @@
"accountEnable": "账户启用",
"add": "添加",
"administrator": "管理员",
"all": "全部",
"areaCodePlaceholder": "区号",
"authMethodsTitle": "认证方式",
"avatar": "头像",
@@ -17,6 +18,9 @@
"confirm": "确认",
"confirmDelete": "确认删除",
"confirmOffline": "确认下线",
"confirmResetToken": "确认重置订阅地址",
"confirmResumeSubscribe": "确认恢复订阅",
"confirmStopSubscribe": "确认暂停订阅",
"copySubscription": "复制订阅",
"copySuccess": "复制成功",
"create": "创建",
@@ -39,7 +43,10 @@
"downloadTraffic": "下载流量",
"edit": "编辑",
"email": "邮箱",
"editGroup": "编辑分组",
"editSubscription": "编辑订阅",
"editUserGroup": "编辑用户组",
"editUserGroupDescription": "编辑用户组分配和锁定状态",
"enable": "启用",
"enabled": "启用",
"disabled": "禁用",
@@ -84,6 +91,7 @@
"inviteCount": "邀请用户数",
"inviteStats": "邀请统计",
"invitedUsers": "已邀请用户",
"isDeleted": "状态",
"kickOfflineConfirm": "确认踢下线",
"kickOfflineSuccess": "设备已踢下线",
"lastSeen": "最后上线",
@@ -132,32 +140,32 @@
"resetTime": "重置时间",
"resetToken": "重置订阅地址",
"resetTokenDescription": "这将重置订阅地址并重新生成新的令牌。",
"saving": "保存中...",
"resetTokenSuccess": "订阅地址重置成功",
"confirmResetToken": "确认重置订阅地址",
"resumeSubscribe": "恢复订阅",
"selectGroup": "选择一个组",
"resumeSubscribeDescription": "这将恢复订阅,允许用户继续使用。",
"resumeSubscribeSuccess": "订阅已恢复",
"save": "保存",
"shortCode": "短码",
"speedLimit": "速度限制",
"startTime": "开始时间",
"status": "状态",
"statusActive": "活跃",
"statusDeducted": "已扣除",
"statusExpired": "已过期",
"statusFinished": "已完成",
"statusPending": "待处理",
"statusStopped": "已停止",
"stopSubscribe": "暂停订阅",
"stopSubscribeDescription": "这将暂时停止订阅。用户将无法使用。",
"stopSubscribeSuccess": "订阅已暂停",
"confirmStopSubscribe": "确认暂停订阅",
"resumeSubscribe": "恢复订阅",
"resumeSubscribeDescription": "这将恢复订阅,允许用户继续使用。",
"resumeSubscribeSuccess": "订阅已恢复",
"confirmResumeSubscribe": "确认恢复订阅",
"status": "状态",
"statusPending": "待处理",
"statusActive": "活跃",
"statusFinished": "已完成",
"statusExpired": "已过期",
"statusDeducted": "已扣除",
"statusStopped": "已停止",
"save": "保存",
"search": "搜索",
"searchPlaceholder": "邮箱 / 邀请码 / 设备ID",
"searchInputPlaceholder": "请输入搜索内容",
"sharedSubscription": "共享",
"sharedSubscriptionInfo": "该用户为设备组成员,当前显示所有者 (ID: {{ownerId}}) 的共享订阅",
"sharedSubscriptionList": "共享订阅列表",
"speedLimit": "速度限制",
"startTime": "开始时间",
"subscription": "订阅",
"subscriptionId": "订阅 ID",
"subscriptionInfo": "订阅信息",
@@ -175,10 +183,12 @@
"trafficLimit": "流量限制",
"trafficStats": "流量统计",
"trafficUsage": "流量使用",
"remainingTraffic": "剩余流量",
"unlimited": "无限制",
"unverified": "未验证",
"update": "更新",
"updateSuccess": "更新成功",
"groupUpdated": "分组更新成功",
"upload": "上传",
"uploadTraffic": "上传流量",
"userAgent": "用户代理",
@@ -189,7 +199,20 @@
"userList": "用户列表",
"userName": "用户名",
"userProfile": "用户资料",
"userGroup": "用户分组",
"verified": "已验证",
"viewDeviceGroup": "查看设备组",
"viewOwner": "查看所有者"
"viewOwner": "查看所有者",
"locked": "锁定",
"lockGroup": "锁定分组",
"lockGroupDescription": "防止自动分组更改此用户的分组",
"groupLocked": "分组已锁定",
"previewNodes": "预览节点",
"availableNodes": "可用节点",
"name": "名称",
"address": "地址",
"noNodesAvailable": "无可用节点",
"nodeGroup": "节点组",
"publicNodes": "公共节点",
"subscriptionNodes": "套餐节点"
}