mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-11 03:36:37 +08:00
变更流量计费方法
This commit is contained in:
Binary file not shown.
Binary file not shown.
+1
-1
@@ -119,7 +119,7 @@ func main() {
|
|||||||
log := xlogger.NewLogger()
|
log := xlogger.NewLogger()
|
||||||
logger.SetDefault(log)
|
logger.SetDefault(log)
|
||||||
|
|
||||||
wsReporter := socket.StartWebSocketReporterWithConfig(config.Addr, config.Secret, "1.0.7")
|
wsReporter := socket.StartWebSocketReporterWithConfig(config.Addr, config.Secret, "1.1.0")
|
||||||
defer wsReporter.Stop()
|
defer wsReporter.Stop()
|
||||||
|
|
||||||
service.SetHTTPReportURL(config.Addr, config.Secret)
|
service.SetHTTPReportURL(config.Addr, config.Secret)
|
||||||
|
|||||||
@@ -369,19 +369,10 @@ func (s *defaultService) observeStats(ctx context.Context) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
if outputBytes > 0 || inputBytes > 0 {
|
if outputBytes > 0 || inputBytes > 0 {
|
||||||
reportItems := []TrafficReportItem{
|
reportItems := TrafficReportItem{
|
||||||
{
|
N: s.name,
|
||||||
N: s.name,
|
U: int64(outputBytes),
|
||||||
T: "cc",
|
D: int64(inputBytes),
|
||||||
U: int64(outputBytes),
|
|
||||||
D: int64(inputBytes),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
N: s.name,
|
|
||||||
T: "conn",
|
|
||||||
U: int64(inputBytes),
|
|
||||||
D: int64(outputBytes),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
success, err := sendTrafficReport(ctx, reportItems)
|
success, err := sendTrafficReport(ctx, reportItems)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ var httpAESCrypto *crypto.AESCrypto // 新增:HTTP上报加密器
|
|||||||
// TrafficReportItem 流量报告项(压缩格式)
|
// TrafficReportItem 流量报告项(压缩格式)
|
||||||
type TrafficReportItem struct {
|
type TrafficReportItem struct {
|
||||||
N string `json:"n"` // 服务名(name缩写)
|
N string `json:"n"` // 服务名(name缩写)
|
||||||
T string `json:"t"` // 连接类型:conn, cc(type缩写)
|
|
||||||
U int64 `json:"u"` // 上行流量(up缩写)
|
U int64 `json:"u"` // 上行流量(up缩写)
|
||||||
D int64 `json:"d"` // 下行流量(down缩写)
|
D int64 `json:"d"` // 下行流量(down缩写)
|
||||||
}
|
}
|
||||||
@@ -43,7 +42,7 @@ func SetHTTPReportURL(addr string, secret string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sendTrafficReport 发送流量报告到HTTP接口
|
// sendTrafficReport 发送流量报告到HTTP接口
|
||||||
func sendTrafficReport(ctx context.Context, reportItems []TrafficReportItem) (bool, error) {
|
func sendTrafficReport(ctx context.Context, reportItems TrafficReportItem) (bool, error) {
|
||||||
jsonData, err := json.Marshal(reportItems)
|
jsonData, err := json.Marshal(reportItems)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("序列化报告数据失败: %v", err)
|
return false, fmt.Errorf("序列化报告数据失败: %v", err)
|
||||||
|
|||||||
@@ -5,13 +5,9 @@ import lombok.Data;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class FlowDto {
|
public class FlowDto {
|
||||||
// [{n=41_tcp, t=cc, u=73225, d=35043}, {n=41_tcp, t=conn, u=35043, d=73225}]
|
|
||||||
// 转发id_类型
|
// 转发id_类型
|
||||||
private String n;
|
private String n;
|
||||||
|
|
||||||
// 是请求还是接收
|
|
||||||
private String t;
|
|
||||||
|
|
||||||
// 上传流量
|
// 上传流量
|
||||||
private Long u;
|
private Long u;
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ public class FlowController extends BaseController {
|
|||||||
// 常量定义
|
// 常量定义
|
||||||
private static final String SUCCESS_RESPONSE = "ok";
|
private static final String SUCCESS_RESPONSE = "ok";
|
||||||
private static final String DEFAULT_USER_TUNNEL_ID = "0";
|
private static final String DEFAULT_USER_TUNNEL_ID = "0";
|
||||||
private static final int FLOW_TYPE_UPLOAD_ONLY = 1;
|
|
||||||
private static final int FLOW_TYPE_BIDIRECTIONAL = 2;
|
|
||||||
private static final long BYTES_TO_GB = 1024L * 1024L * 1024L;
|
private static final long BYTES_TO_GB = 1024L * 1024L * 1024L;
|
||||||
|
|
||||||
// 用于同步相同用户和隧道的流量更新操作
|
// 用于同步相同用户和隧道的流量更新操作
|
||||||
@@ -132,12 +130,9 @@ public class FlowController extends BaseController {
|
|||||||
String decryptedData = decryptIfNeeded(rawData, secret);
|
String decryptedData = decryptIfNeeded(rawData, secret);
|
||||||
|
|
||||||
// 3. 解析为FlowDto列表
|
// 3. 解析为FlowDto列表
|
||||||
List<FlowDto> flowDataList = JSON.parseArray(decryptedData, FlowDto.class);
|
FlowDto flowDataList = JSONObject.parseObject(decryptedData, FlowDto.class);
|
||||||
|
|
||||||
if (flowDataList.isEmpty()) {
|
if (Objects.equals(flowDataList.getN(), "web_api")) {
|
||||||
return SUCCESS_RESPONSE;
|
|
||||||
}
|
|
||||||
if (Objects.equals(flowDataList.get(0).getN(), "web_api")) {
|
|
||||||
return SUCCESS_RESPONSE;
|
return SUCCESS_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,9 +204,9 @@ public class FlowController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 处理流量数据的核心逻辑
|
* 处理流量数据的核心逻辑
|
||||||
*/
|
*/
|
||||||
private String processFlowData(List<FlowDto> flowDataList) {
|
private String processFlowData(FlowDto flowDataList) {
|
||||||
// 2. 解析服务名称获取ID信息
|
// 2. 解析服务名称获取ID信息
|
||||||
String[] serviceIds = parseServiceName(flowDataList.get(0).getN());
|
String[] serviceIds = parseServiceName(flowDataList.getN());
|
||||||
String forwardId = serviceIds[0];
|
String forwardId = serviceIds[0];
|
||||||
String userId = serviceIds[1];
|
String userId = serviceIds[1];
|
||||||
String userTunnelId = serviceIds[2];
|
String userTunnelId = serviceIds[2];
|
||||||
@@ -224,43 +219,41 @@ public class FlowController extends BaseController {
|
|||||||
userTunnel = userTunnelService.getById(userTunnelId);
|
userTunnel = userTunnelService.getById(userTunnelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 处理流量倍率
|
|
||||||
List<FlowDto> validFlowData = filterFlowData(flowDataList, forward);
|
|
||||||
|
|
||||||
// 5. 计算总流量
|
// 4. 获取流量计费类型
|
||||||
FlowStatistics flowStats = calculateTotalFlow(validFlowData);
|
|
||||||
|
|
||||||
// 6. 获取流量计费类型
|
|
||||||
int flowType = getFlowType(forward);
|
int flowType = getFlowType(forward);
|
||||||
|
|
||||||
// 7. 先更新所有流量统计 - 确保流量数据的一致性
|
// 5. 处理流量倍率及单双向计算
|
||||||
// 7.1 更新转发流量
|
FlowDto flowStats = filterFlowData(flowDataList, forward, flowType);
|
||||||
|
|
||||||
|
// 6. 先更新所有流量统计 - 确保流量数据的一致性
|
||||||
|
// 6.1 更新转发流量
|
||||||
if (forward != null) {
|
if (forward != null) {
|
||||||
updateForwardFlow(forwardId, flowStats);
|
updateForwardFlow(forwardId, flowStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.2 更新用户流量
|
// 6.2 更新用户流量
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
updateUserFlow(userId, flowStats, flowType);
|
updateUserFlow(userId, flowStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.3 更新隧道权限流量
|
// 6.3 更新隧道权限流量
|
||||||
if (userTunnel != null) {
|
if (userTunnel != null) {
|
||||||
updateUserTunnelFlow(userTunnelId, flowStats);
|
updateUserTunnelFlow(userTunnelId, flowStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. 流量更新完成后,再进行各种检查和服务暂停操作
|
// 7. 流量更新完成后,再进行各种检查和服务暂停操作
|
||||||
// 8.1 用户相关检查
|
// 7.1 用户相关检查
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
checkUserRelatedLimits(user, userTunnelId);
|
checkUserRelatedLimits(user, userTunnelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.2 隧道权限相关检查
|
// 7.2 隧道权限相关检查
|
||||||
if (userTunnel != null) {
|
if (userTunnel != null) {
|
||||||
checkUserTunnelRelatedLimits(userTunnel, forwardId, userId, userTunnelId, forward, flowType);
|
checkUserTunnelRelatedLimits(userTunnel, forwardId, userId, userTunnelId, forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.3 转发状态检查
|
// 7.3 转发状态检查
|
||||||
if (forward != null) {
|
if (forward != null) {
|
||||||
checkForwardStatus(forward, userId, userTunnelId);
|
checkForwardStatus(forward, userId, userTunnelId);
|
||||||
}
|
}
|
||||||
@@ -270,24 +263,34 @@ public class FlowController extends BaseController {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private List<FlowDto> filterFlowData(List<FlowDto> flowDataList, Forward forward) {
|
private FlowDto filterFlowData(FlowDto flowDto, Forward forward, int flowType) {
|
||||||
|
// 判断 forward 是否不为空,避免空指针异常
|
||||||
if (forward != null) {
|
if (forward != null) {
|
||||||
|
// 根据 forward 中的隧道ID查询隧道对象
|
||||||
Tunnel tunnel = tunnelService.getById(forward.getTunnelId());
|
Tunnel tunnel = tunnelService.getById(forward.getTunnelId());
|
||||||
|
// 如果隧道对象存在,继续处理
|
||||||
if (tunnel != null){
|
if (tunnel != null){
|
||||||
|
// 获取隧道的流量倍率 trafficRatio
|
||||||
BigDecimal trafficRatio = tunnel.getTrafficRatio();
|
BigDecimal trafficRatio = tunnel.getTrafficRatio();
|
||||||
for (FlowDto flowDto : flowDataList) {
|
|
||||||
BigDecimal originalD = BigDecimal.valueOf(flowDto.getD());
|
|
||||||
BigDecimal originalU = BigDecimal.valueOf(flowDto.getU());
|
|
||||||
|
|
||||||
BigDecimal newD = originalD.multiply(trafficRatio);
|
// 把 flowDto 中的下载流量 D 转换为 BigDecimal 类型
|
||||||
BigDecimal newU = originalU.multiply(trafficRatio);
|
BigDecimal originalD = BigDecimal.valueOf(flowDto.getD());
|
||||||
|
// 把 flowDto 中的上传流量 U 转换为 BigDecimal 类型
|
||||||
|
BigDecimal originalU = BigDecimal.valueOf(flowDto.getU());
|
||||||
|
|
||||||
flowDto.setD(newD.longValue());
|
// 下载流量乘以流量倍率,得到新的下载流量
|
||||||
flowDto.setU(newU.longValue());
|
BigDecimal newD = originalD.multiply(trafficRatio);
|
||||||
}
|
// 上传流量乘以流量倍率,得到新的上传流量
|
||||||
|
BigDecimal newU = originalU.multiply(trafficRatio);
|
||||||
|
|
||||||
|
// 将计算后的下载流量转换回 long 类型并设置回 flowDto
|
||||||
|
flowDto.setD(newD.longValue() * flowType);
|
||||||
|
// 将计算后的上传流量转换回 long 类型并设置回 flowDto
|
||||||
|
flowDto.setU(newU.longValue() * flowType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flowDataList;
|
// 返回处理后的流量数据对象
|
||||||
|
return flowDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -306,26 +309,12 @@ public class FlowController extends BaseController {
|
|||||||
return serviceName.split("_");
|
return serviceName.split("_");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算总流量统计
|
|
||||||
*/
|
|
||||||
private FlowStatistics calculateTotalFlow(List<FlowDto> validFlowData) {
|
|
||||||
long totalUpload = 0L;
|
|
||||||
long totalDownload = 0L;
|
|
||||||
|
|
||||||
for (FlowDto flow : validFlowData) {
|
|
||||||
totalUpload += flow.getU();
|
|
||||||
totalDownload += flow.getD();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FlowStatistics(totalUpload, totalDownload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取流量计费类型 - 优化版本,使用传入的Forward实体
|
* 获取流量计费类型 - 优化版本,使用传入的Forward实体
|
||||||
*/
|
*/
|
||||||
private int getFlowType(Forward forward) {
|
private int getFlowType(Forward forward) {
|
||||||
int defaultFlowType = FLOW_TYPE_BIDIRECTIONAL;
|
int defaultFlowType = 2;
|
||||||
|
|
||||||
if (forward != null) {
|
if (forward != null) {
|
||||||
Tunnel tunnel = tunnelService.getById(forward.getTunnelId());
|
Tunnel tunnel = tunnelService.getById(forward.getTunnelId());
|
||||||
@@ -340,13 +329,13 @@ public class FlowController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 更新转发流量统计 - 使用原子操作避免并发问题
|
* 更新转发流量统计 - 使用原子操作避免并发问题
|
||||||
*/
|
*/
|
||||||
private boolean updateForwardFlow(String forwardId, FlowStatistics flowStats) {
|
private boolean updateForwardFlow(String forwardId, FlowDto flowStats) {
|
||||||
// 对相同转发的流量更新进行同步,避免并发覆盖
|
// 对相同转发的流量更新进行同步,避免并发覆盖
|
||||||
synchronized (getForwardLock(forwardId)) {
|
synchronized (getForwardLock(forwardId)) {
|
||||||
UpdateWrapper<Forward> updateWrapper = new UpdateWrapper<>();
|
UpdateWrapper<Forward> updateWrapper = new UpdateWrapper<>();
|
||||||
updateWrapper.eq("id", forwardId);
|
updateWrapper.eq("id", forwardId);
|
||||||
updateWrapper.setSql("in_flow = in_flow + " + flowStats.getDownload());
|
updateWrapper.setSql("in_flow = in_flow + " + flowStats.getD());
|
||||||
updateWrapper.setSql("out_flow = out_flow + " + flowStats.getUpload());
|
updateWrapper.setSql("out_flow = out_flow + " + flowStats.getU());
|
||||||
|
|
||||||
return forwardService.update(null, updateWrapper);
|
return forwardService.update(null, updateWrapper);
|
||||||
}
|
}
|
||||||
@@ -355,21 +344,14 @@ public class FlowController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 更新用户流量统计 - 使用原子操作避免并发问题
|
* 更新用户流量统计 - 使用原子操作避免并发问题
|
||||||
*/
|
*/
|
||||||
private boolean updateUserFlow(String userId, FlowStatistics flowStats, int flowType) {
|
private boolean updateUserFlow(String userId, FlowDto flowStats) {
|
||||||
// 对相同用户的流量更新进行同步,避免并发覆盖
|
// 对相同用户的流量更新进行同步,避免并发覆盖
|
||||||
synchronized (getUserLock(userId)) {
|
synchronized (getUserLock(userId)) {
|
||||||
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
|
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
|
||||||
updateWrapper.eq("id", userId);
|
updateWrapper.eq("id", userId);
|
||||||
|
|
||||||
// 使用SQL的原子更新操作,避免读取-修改-写入的并发问题
|
updateWrapper.setSql("in_flow = in_flow + " + flowStats.getD());
|
||||||
if (flowType == FLOW_TYPE_BIDIRECTIONAL) {
|
updateWrapper.setSql("out_flow = out_flow + " + flowStats.getU());
|
||||||
// 双向计费:同时更新上传和下载流量
|
|
||||||
updateWrapper.setSql("in_flow = in_flow + " + flowStats.getDownload());
|
|
||||||
updateWrapper.setSql("out_flow = out_flow + " + flowStats.getUpload());
|
|
||||||
} else {
|
|
||||||
// 仅上传计费:只更新上传流量
|
|
||||||
updateWrapper.setSql("out_flow = out_flow + " + flowStats.getUpload());
|
|
||||||
}
|
|
||||||
|
|
||||||
return userService.update(null, updateWrapper);
|
return userService.update(null, updateWrapper);
|
||||||
}
|
}
|
||||||
@@ -378,7 +360,7 @@ public class FlowController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 更新用户隧道流量统计 - 优化版本,仅负责流量更新
|
* 更新用户隧道流量统计 - 优化版本,仅负责流量更新
|
||||||
*/
|
*/
|
||||||
private boolean updateUserTunnelFlow(String userTunnelId, FlowStatistics flowStats) {
|
private boolean updateUserTunnelFlow(String userTunnelId, FlowDto flowStats) {
|
||||||
if (Objects.equals(userTunnelId, DEFAULT_USER_TUNNEL_ID)) {
|
if (Objects.equals(userTunnelId, DEFAULT_USER_TUNNEL_ID)) {
|
||||||
return true; // 默认隧道不需要更新,返回成功
|
return true; // 默认隧道不需要更新,返回成功
|
||||||
}
|
}
|
||||||
@@ -387,8 +369,8 @@ public class FlowController extends BaseController {
|
|||||||
synchronized (getTunnelLock(userTunnelId)) {
|
synchronized (getTunnelLock(userTunnelId)) {
|
||||||
UpdateWrapper<UserTunnel> updateWrapper = new UpdateWrapper<>();
|
UpdateWrapper<UserTunnel> updateWrapper = new UpdateWrapper<>();
|
||||||
updateWrapper.eq("id", userTunnelId);
|
updateWrapper.eq("id", userTunnelId);
|
||||||
updateWrapper.setSql("in_flow = in_flow + " + flowStats.getDownload());
|
updateWrapper.setSql("in_flow = in_flow + " + flowStats.getD());
|
||||||
updateWrapper.setSql("out_flow = out_flow + " + flowStats.getUpload());
|
updateWrapper.setSql("out_flow = out_flow + " + flowStats.getU());
|
||||||
|
|
||||||
return userTunnelService.update(null, updateWrapper);
|
return userTunnelService.update(null, updateWrapper);
|
||||||
}
|
}
|
||||||
@@ -397,11 +379,8 @@ public class FlowController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 检查用户隧道流量限制 - 优化版本,使用传入的UserTunnel实体
|
* 检查用户隧道流量限制 - 优化版本,使用传入的UserTunnel实体
|
||||||
*/
|
*/
|
||||||
private void checkUserTunnelFlowLimit(UserTunnel userTunnel, int flowType,
|
private void checkUserTunnelFlowLimit(UserTunnel userTunnel, String forwardId, String userId, String userTunnelId) {
|
||||||
String forwardId, String userId, String userTunnelId) {
|
long currentFlow = userTunnel.getInFlow() + userTunnel.getOutFlow();
|
||||||
long currentFlow = (flowType == FLOW_TYPE_UPLOAD_ONLY) ?
|
|
||||||
userTunnel.getOutFlow() :
|
|
||||||
userTunnel.getInFlow() + userTunnel.getOutFlow();
|
|
||||||
|
|
||||||
long flowLimit = userTunnel.getFlow() * BYTES_TO_GB;
|
long flowLimit = userTunnel.getFlow() * BYTES_TO_GB;
|
||||||
|
|
||||||
@@ -513,7 +492,7 @@ public class FlowController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 检查用户隧道权限相关的所有限制 - 隧道权限存在时统一处理
|
* 检查用户隧道权限相关的所有限制 - 隧道权限存在时统一处理
|
||||||
*/
|
*/
|
||||||
private void checkUserTunnelRelatedLimits(UserTunnel userTunnel, String forwardId, String userId, String userTunnelId, Forward forward, int flowType) {
|
private void checkUserTunnelRelatedLimits(UserTunnel userTunnel, String forwardId, String userId, String userTunnelId, Forward forward) {
|
||||||
// 重新查询用户隧道权限以获取最新的流量数据
|
// 重新查询用户隧道权限以获取最新的流量数据
|
||||||
UserTunnel updatedUserTunnel = userTunnelService.getById(userTunnel.getId());
|
UserTunnel updatedUserTunnel = userTunnelService.getById(userTunnel.getId());
|
||||||
if (updatedUserTunnel == null) {
|
if (updatedUserTunnel == null) {
|
||||||
@@ -521,7 +500,7 @@ public class FlowController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查隧道权限流量限制
|
// 检查隧道权限流量限制
|
||||||
checkUserTunnelFlowLimit(updatedUserTunnel, flowType, forwardId, userId, userTunnelId);
|
checkUserTunnelFlowLimit(updatedUserTunnel, forwardId, userId, userTunnelId);
|
||||||
|
|
||||||
// 检查隧道权限到期时间
|
// 检查隧道权限到期时间
|
||||||
if (updatedUserTunnel.getExpTime() != null && updatedUserTunnel.getExpTime() <= System.currentTimeMillis()) {
|
if (updatedUserTunnel.getExpTime() != null && updatedUserTunnel.getExpTime() <= System.currentTimeMillis()) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class ForwardServiceImpl extends ServiceImpl<ForwardMapper, Forward> impl
|
|||||||
private static final int FORWARD_STATUS_PAUSED = 0;
|
private static final int FORWARD_STATUS_PAUSED = 0;
|
||||||
private static final int FORWARD_STATUS_ERROR = -1;
|
private static final int FORWARD_STATUS_ERROR = -1;
|
||||||
private static final int TUNNEL_STATUS_ACTIVE = 1;
|
private static final int TUNNEL_STATUS_ACTIVE = 1;
|
||||||
private static final int FLOW_TYPE_UPLOAD_ONLY = 1;
|
|
||||||
private static final long BYTES_TO_GB = 1024L * 1024L * 1024L;
|
private static final long BYTES_TO_GB = 1024L * 1024L * 1024L;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@@ -753,9 +753,8 @@ public class ForwardServiceImpl extends ServiceImpl<ForwardMapper, Forward> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查隧道流量限制
|
// 检查隧道流量限制
|
||||||
long tunnelFlow = (tunnel.getFlow() == FLOW_TYPE_UPLOAD_ONLY) ?
|
// 数据库中的流量已按计费类型处理,直接使用总和
|
||||||
userTunnel.getOutFlow() :
|
long tunnelFlow = userTunnel.getInFlow() + userTunnel.getOutFlow();
|
||||||
userTunnel.getInFlow() + userTunnel.getOutFlow();
|
|
||||||
|
|
||||||
if (userTunnel.getFlow() * BYTES_TO_GB <= tunnelFlow) {
|
if (userTunnel.getFlow() * BYTES_TO_GB <= tunnelFlow) {
|
||||||
return R.err("该隧道流量已用完,无法恢复服务");
|
return R.err("该隧道流量已用完,无法恢复服务");
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export type SiteConfig = typeof siteConfig;
|
|||||||
|
|
||||||
// 缓存相关常量
|
// 缓存相关常量
|
||||||
const CACHE_PREFIX = 'vite_config_';
|
const CACHE_PREFIX = 'vite_config_';
|
||||||
const VERSION = "1.1.1";
|
const VERSION = "1.2.0";
|
||||||
|
|
||||||
// 缓存策略:
|
// 缓存策略:
|
||||||
// - 长期有效,不设置过期时间
|
// - 长期有效,不设置过期时间
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ export default function DashboardPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const calculateUserTotalUsedFlow = (): number => {
|
const calculateUserTotalUsedFlow = (): number => {
|
||||||
|
// 后端已按计费类型处理流量,前端直接使用入站+出站总和
|
||||||
return (userInfo.inFlow || 0) + (userInfo.outFlow || 0);
|
return (userInfo.inFlow || 0) + (userInfo.outFlow || 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -313,11 +314,8 @@ export default function DashboardPage() {
|
|||||||
if (!tunnel) return 0;
|
if (!tunnel) return 0;
|
||||||
const inFlow = tunnel.inFlow || 0;
|
const inFlow = tunnel.inFlow || 0;
|
||||||
const outFlow = tunnel.outFlow || 0;
|
const outFlow = tunnel.outFlow || 0;
|
||||||
if (tunnel.tunnelFlow === 1) {
|
// 后端已按计费类型处理流量,前端直接使用入站+出站总和
|
||||||
return outFlow;
|
return inFlow + outFlow;
|
||||||
} else {
|
|
||||||
return inFlow + outFlow;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateTunnelFlowPercentage = (tunnel: UserTunnel): number => {
|
const calculateTunnelFlowPercentage = (tunnel: UserTunnel): number => {
|
||||||
@@ -523,19 +521,11 @@ export default function DashboardPage() {
|
|||||||
const calculateForwardBillingFlow = (forward: Forward): number => {
|
const calculateForwardBillingFlow = (forward: Forward): number => {
|
||||||
if (!forward) return 0;
|
if (!forward) return 0;
|
||||||
|
|
||||||
const tunnel = userTunnels.find(t => t.tunnelId === forward.tunnelId);
|
|
||||||
if (!tunnel) {
|
|
||||||
return (forward.inFlow || 0) + (forward.outFlow || 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const inFlow = forward.inFlow || 0;
|
const inFlow = forward.inFlow || 0;
|
||||||
const outFlow = forward.outFlow || 0;
|
const outFlow = forward.outFlow || 0;
|
||||||
|
|
||||||
if (tunnel.tunnelFlow === 1) {
|
// 后端已按计费类型处理流量,前端直接使用入站+出站总和
|
||||||
return outFlow;
|
return inFlow + outFlow;
|
||||||
} else {
|
|
||||||
return inFlow + outFlow;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
|||||||
@@ -98,11 +98,8 @@ const calculateTunnelUsedFlow = (tunnel: UserTunnel): number => {
|
|||||||
const inFlow = tunnel.inFlow || 0;
|
const inFlow = tunnel.inFlow || 0;
|
||||||
const outFlow = tunnel.outFlow || 0;
|
const outFlow = tunnel.outFlow || 0;
|
||||||
|
|
||||||
if (tunnel.tunnelFlow === 1) {
|
// 后端已按计费类型处理流量,前端直接使用入站+出站总和
|
||||||
return outFlow; // 单向计算:只计算上传流量
|
return inFlow + outFlow;
|
||||||
} else {
|
|
||||||
return inFlow + outFlow; // 双向计算或默认:计算上传和下载的总流量
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function UserPage() {
|
export default function UserPage() {
|
||||||
|
|||||||
Reference in New Issue
Block a user