mirror of
https://github.com/snltty/linker.git
synced 2025-12-20 02:16:44 +08:00
管理页面代码重构
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
v1.9.6
|
||||
2025-11-16 20:01:56
|
||||
2025-11-17 16:52:54
|
||||
1. 一些累计更新,一些BUG修复
|
||||
2. 优化客户端数据同步,减少服务器流量
|
||||
3. 去除cdkey,改为发电解锁中继速度
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using linker.messenger.tunnel;
|
||||
using linker.libs;
|
||||
using linker.messenger.tunnel;
|
||||
using linker.tunnel.transport;
|
||||
|
||||
namespace linker.messenger.store.file.tunnel
|
||||
@@ -21,11 +22,9 @@ namespace linker.messenger.store.file.tunnel
|
||||
{
|
||||
this.runningConfig = runningConfig;
|
||||
|
||||
var list = config.Data.Client.Tunnel.Transports;
|
||||
if (list != null && list.Count > 0)
|
||||
if (config.Data.Client.Tunnel.Transports != null && config.Data.Client.Tunnel.Transports.Count > 0)
|
||||
{
|
||||
|
||||
runningConfig.Data.Tunnel.Transports.AddOrUpdate("default", list, (a, b) => list);
|
||||
runningConfig.Data.Tunnel.Transports.AddOrUpdate(Helper.GlobalString, config.Data.Client.Tunnel.Transports, (a, b) => config.Data.Client.Tunnel.Transports);
|
||||
runningConfig.Data.Update();
|
||||
|
||||
config.Data.Client.Tunnel.Transports = [];
|
||||
@@ -43,20 +42,121 @@ namespace linker.messenger.store.file.tunnel
|
||||
|
||||
return true;
|
||||
}
|
||||
public async Task<bool> SetTunnelTransports(string machineId, List<ITunnelTransport> list)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(machineId)) return false;
|
||||
|
||||
if (runningConfig.Data.Tunnel.Transports.TryGetValue(machineId, out List<TunnelTransportItemInfo> transportItems) == false)
|
||||
{
|
||||
transportItems = new List<TunnelTransportItemInfo>();
|
||||
}
|
||||
|
||||
Rebuild(transportItems, list);
|
||||
ForceUpdate(transportItems, list);
|
||||
|
||||
runningConfig.Data.Tunnel.Transports.AddOrUpdate(machineId, transportItems, (a, b) => transportItems);
|
||||
runningConfig.Data.Update();
|
||||
|
||||
OnChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<List<TunnelTransportItemInfo>> GetTunnelTransports(string machineId)
|
||||
{
|
||||
if (runningConfig.Data.Tunnel.Transports.TryGetValue(machineId, out List<TunnelTransportItemInfo> list))
|
||||
{
|
||||
if (runningConfig.Data.Tunnel.Transports.TryGetValue(Helper.GlobalString, out List<TunnelTransportItemInfo> defaults))
|
||||
{
|
||||
if(Rebuild(list, defaults))
|
||||
{
|
||||
runningConfig.Data.Tunnel.Transports.AddOrUpdate(machineId, list, (a, b) => list);
|
||||
runningConfig.Data.Update();
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
if (runningConfig.Data.Tunnel.Transports.TryGetValue("default", out list))
|
||||
if (runningConfig.Data.Tunnel.Transports.TryGetValue(Helper.GlobalString, out list))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private void ForceUpdate(List<TunnelTransportItemInfo> currents, List<ITunnelTransport> news)
|
||||
{
|
||||
//强制更新一些信息
|
||||
foreach (var item in currents)
|
||||
{
|
||||
var transport = news.FirstOrDefault(c => c.Name == item.Name);
|
||||
if (transport != null)
|
||||
{
|
||||
item.DisableReverse = transport.DisableReverse;
|
||||
item.DisableSSL = transport.DisableSSL;
|
||||
item.Name = transport.Name;
|
||||
item.Label = transport.Label;
|
||||
if (transport.DisableReverse)
|
||||
{
|
||||
item.Reverse = transport.Reverse;
|
||||
}
|
||||
if (transport.DisableSSL)
|
||||
{
|
||||
item.SSL = transport.SSL;
|
||||
}
|
||||
if (item.Order == 0)
|
||||
{
|
||||
item.Order = transport.Order;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private bool Rebuild(List<TunnelTransportItemInfo> currents, List<ITunnelTransport> news)
|
||||
{
|
||||
return Rebuild(currents, news.Select(c => new TunnelTransportItemInfo
|
||||
{
|
||||
Label = c.Label,
|
||||
Name = c.Name,
|
||||
ProtocolType = c.ProtocolType.ToString(),
|
||||
Reverse = c.Reverse,
|
||||
DisableReverse = c.DisableReverse,
|
||||
SSL = c.SSL,
|
||||
DisableSSL = c.DisableSSL,
|
||||
Order = c.Order
|
||||
}).ToList());
|
||||
}
|
||||
private bool Rebuild(List<TunnelTransportItemInfo> currents,List<TunnelTransportItemInfo> news)
|
||||
{
|
||||
//有新的协议
|
||||
var newTransportNames = news.Select(c => c.Name).Except(currents.Select(c => c.Name));
|
||||
if (newTransportNames.Any())
|
||||
{
|
||||
currents.AddRange(news.Where(c => newTransportNames.Contains(c.Name)).Select(c => new TunnelTransportItemInfo
|
||||
{
|
||||
Label = c.Label,
|
||||
Name = c.Name,
|
||||
ProtocolType = c.ProtocolType.ToString(),
|
||||
Reverse = c.Reverse,
|
||||
DisableReverse = c.DisableReverse,
|
||||
SSL = c.SSL,
|
||||
DisableSSL = c.DisableSSL,
|
||||
Order = c.Order
|
||||
}));
|
||||
}
|
||||
//有已移除的协议
|
||||
var oldTransportNames = currents.Select(c => c.Name).Except(news.Select(c => c.Name));
|
||||
if (oldTransportNames.Any())
|
||||
{
|
||||
foreach (var item in currents.Where(c => oldTransportNames.Contains(c.Name)).ToList())
|
||||
{
|
||||
currents.Remove(item);
|
||||
}
|
||||
}
|
||||
return newTransportNames.Any() || oldTransportNames.Any();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<bool> SetRouteLevelPlus(int level)
|
||||
{
|
||||
runningConfig.Data.Tunnel.RouteLevelPlus = level;
|
||||
@@ -64,7 +164,6 @@ namespace linker.messenger.store.file.tunnel
|
||||
OnChanged();
|
||||
return await Task.FromResult(true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> SetPortMap(int privatePort, int publicPort)
|
||||
{
|
||||
runningConfig.Data.Tunnel.PortMapLan = privatePort;
|
||||
@@ -73,7 +172,6 @@ namespace linker.messenger.store.file.tunnel
|
||||
OnChanged();
|
||||
return await Task.FromResult(true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> SetNetwork(TunnelPublicNetworkInfo network)
|
||||
{
|
||||
runningConfig.Data.Update();
|
||||
|
||||
@@ -124,6 +124,7 @@ namespace linker.messenger.tunnel
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取打洞协议
|
||||
/// </summary>
|
||||
@@ -133,7 +134,7 @@ namespace linker.messenger.tunnel
|
||||
{
|
||||
if (param.Content == signInClientStore.Id || string.IsNullOrWhiteSpace(param.Content))
|
||||
{
|
||||
return await tunnelMessengerAdapter.GetTunnelTransports("default").ConfigureAwait(false);
|
||||
return await tunnelMessengerAdapter.GetTunnelTransports(Helper.GlobalString).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
@@ -161,7 +162,7 @@ namespace linker.messenger.tunnel
|
||||
TunnelTransportItemSetInfo info = param.Content.DeJson<TunnelTransportItemSetInfo>();
|
||||
if (info.MachineId == signInClientStore.Id || string.IsNullOrWhiteSpace(info.MachineId))
|
||||
{
|
||||
await tunnelMessengerAdapter.SetTunnelTransports("default", info.Data).ConfigureAwait(false);
|
||||
await tunnelMessengerAdapter.SetTunnelTransports(Helper.GlobalString, info.Data).ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
await tunnelMessengerAdapter.SetTunnelTransports(info.MachineId, info.Data).ConfigureAwait(false);
|
||||
@@ -174,6 +175,7 @@ namespace linker.messenger.tunnel
|
||||
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||
}
|
||||
|
||||
|
||||
public async Task<TunnelLocalNetworkInfo> GetNetwork(ApiControllerParamsInfo param)
|
||||
{
|
||||
if (param.Content == signInClientStore.Id)
|
||||
|
||||
@@ -51,7 +51,13 @@ namespace linker.messenger.tunnel
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
public Task<bool> SetTunnelTransports(string machineId, List<TunnelTransportItemInfo> list);
|
||||
|
||||
/// <summary>
|
||||
/// 保存打洞协议列表
|
||||
/// </summary>
|
||||
/// <param name="machineId"></param>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> SetTunnelTransports(string machineId, List<ITunnelTransport> list);
|
||||
|
||||
public Action OnChanged { get; set; }
|
||||
|
||||
@@ -112,13 +118,18 @@ namespace linker.messenger.tunnel
|
||||
{
|
||||
return await tunnelClientStore.GetTunnelTransports(machineid).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> SetTunnelTransports(string machineid, List<TunnelTransportItemInfo> list)
|
||||
{
|
||||
bool res = await tunnelClientStore.SetTunnelTransports(machineid, list).ConfigureAwait(false);
|
||||
SetCounter();
|
||||
return res;
|
||||
}
|
||||
public async Task<bool> SetTunnelTransports(string machineid, List<ITunnelTransport> list)
|
||||
{
|
||||
bool res = await tunnelClientStore.SetTunnelTransports(machineid, list).ConfigureAwait(false);
|
||||
SetCounter();
|
||||
return res;
|
||||
}
|
||||
private void SetCounter()
|
||||
{
|
||||
counterDecenter.SetValue($"transport", tunnelClientStore.TransportMachineIdCount);
|
||||
|
||||
@@ -20,12 +20,12 @@ namespace linker.messenger.tunnel
|
||||
}
|
||||
public Memory<byte> GetData()
|
||||
{
|
||||
return serializer.Serialize(tunnelMessengerAdapter.GetTunnelTransports("default").Result);
|
||||
return serializer.Serialize(tunnelMessengerAdapter.GetTunnelTransports(Helper.GlobalString).Result);
|
||||
}
|
||||
|
||||
public void SetData(Memory<byte> data)
|
||||
{
|
||||
tunnelMessengerAdapter.SetTunnelTransports("default", serializer.Deserialize<List<TunnelTransportItemInfo>>(data.Span));
|
||||
tunnelMessengerAdapter.SetTunnelTransports(Helper.GlobalString, serializer.Deserialize<List<TunnelTransportItemInfo>>(data.Span));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace linker.messenger.wlist
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, double>> List(ApiControllerParamsInfo param)
|
||||
public async Task<Dictionary<string, Dictionary<int, double>>> List(ApiControllerParamsInfo param)
|
||||
{
|
||||
KeyValueInfo info = param.Content.DeJson<KeyValueInfo>();
|
||||
|
||||
@@ -135,10 +135,10 @@ namespace linker.messenger.wlist
|
||||
}).ConfigureAwait(false);
|
||||
if (resp.Code == MessageResponeCodes.OK)
|
||||
{
|
||||
return serializer.Deserialize<Dictionary<string, double>>(resp.Data.Span);
|
||||
return serializer.Deserialize<Dictionary<string, Dictionary<int, double>>>(resp.Data.Span);
|
||||
}
|
||||
|
||||
return new Dictionary<string, double>();
|
||||
return [];
|
||||
}
|
||||
sealed class KeyValueInfo
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using linker.libs;
|
||||
using linker.libs.extends;
|
||||
using linker.libs.winapis;
|
||||
using linker.messenger.relay.server;
|
||||
using linker.messenger.signin;
|
||||
@@ -38,6 +39,7 @@ namespace linker.messenger.wlist
|
||||
connection.Write(Helper.FalseArray);
|
||||
return;
|
||||
}
|
||||
Console.WriteLine(info.Data.ToJson());
|
||||
await whiteListServerStore.Add(info.Data).ConfigureAwait(false);
|
||||
connection.Write(Helper.TrueArray);
|
||||
}
|
||||
@@ -144,13 +146,11 @@ namespace linker.messenger.wlist
|
||||
|
||||
List<WhiteListInfo> whites = await whiteListServerStore.Get(info.Key, userids, info.Value).ConfigureAwait(false);
|
||||
|
||||
var result = whites.Where(c => string.IsNullOrWhiteSpace(c.UserId) == false).GroupBy(c => c.UserId).ToDictionary(c => $"u_{c.Key}", v =>
|
||||
{
|
||||
return v.Any(x => x.Bandwidth == 0) ? v.First(x => x.Bandwidth == 0).Bandwidth : v.OrderByDescending(x => x.Bandwidth).First().Bandwidth;
|
||||
}).Concat(whites.Where(c => string.IsNullOrWhiteSpace(c.MachineId) == false).GroupBy(c => c.MachineId).ToDictionary(c => $"m_{c.Key}", v =>
|
||||
{
|
||||
return v.Any(x => x.Bandwidth == 0) ? v.First(x => x.Bandwidth == 0).Bandwidth : v.OrderByDescending(x => x.Bandwidth).First().Bandwidth;
|
||||
})).ToDictionary();
|
||||
var result = whites.Where(c => string.IsNullOrWhiteSpace(c.UserId) == false).GroupBy(c => c.UserId)
|
||||
.ToDictionary(c => $"u_{c.Key}", v => v.Select(c => c).ToDictionary(x => x.Id, x => x.Bandwidth))
|
||||
.Concat(whites.Where(c => string.IsNullOrWhiteSpace(c.MachineId) == false).GroupBy(c => c.MachineId)
|
||||
.ToDictionary(c => $"m_{c.Key}", v => v.Select(c => c).ToDictionary(x => x.Id, x => x.Bandwidth)))
|
||||
.ToDictionary();
|
||||
connection.Write(serializer.Serialize(result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,5 +66,12 @@ namespace linker.tunnel
|
||||
/// </summary>
|
||||
/// <param name="transports"></param>
|
||||
public Task<bool> SetTunnelTransports(string machineid,List<TunnelTransportItemInfo> list);
|
||||
/// <summary>
|
||||
/// 保存打洞协议列表
|
||||
/// </summary>
|
||||
/// <param name="machineid"></param>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> SetTunnelTransports(string machineid, List<ITunnelTransport> list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,59 +53,7 @@ namespace linker.tunnel
|
||||
}
|
||||
private async Task RebuildTransports()
|
||||
{
|
||||
var transportItems = (await tunnelMessengerAdapter.GetTunnelTransports("default").ConfigureAwait(false)).ToList();
|
||||
//有新的协议
|
||||
var newTransportNames = transports.Select(c => c.Name).Except(transportItems.Select(c => c.Name));
|
||||
if (newTransportNames.Any())
|
||||
{
|
||||
transportItems.AddRange(transports.Where(c => newTransportNames.Contains(c.Name)).Select(c => new TunnelTransportItemInfo
|
||||
{
|
||||
Label = c.Label,
|
||||
Name = c.Name,
|
||||
ProtocolType = c.ProtocolType.ToString(),
|
||||
Reverse = c.Reverse,
|
||||
DisableReverse = c.DisableReverse,
|
||||
SSL = c.SSL,
|
||||
DisableSSL = c.DisableSSL,
|
||||
Order = c.Order
|
||||
}));
|
||||
}
|
||||
//有已移除的协议
|
||||
var oldTransportNames = transportItems.Select(c => c.Name).Except(transports.Select(c => c.Name));
|
||||
if (oldTransportNames.Any())
|
||||
{
|
||||
foreach (var item in transportItems.Where(c => oldTransportNames.Contains(c.Name)))
|
||||
{
|
||||
transportItems.Remove(item);
|
||||
}
|
||||
}
|
||||
//强制更新一些信息
|
||||
foreach (var item in transportItems)
|
||||
{
|
||||
var transport = transports.FirstOrDefault(c => c.Name == item.Name);
|
||||
if (transport != null)
|
||||
{
|
||||
item.DisableReverse = transport.DisableReverse;
|
||||
item.DisableSSL = transport.DisableSSL;
|
||||
item.Name = transport.Name;
|
||||
item.Label = transport.Label;
|
||||
if (transport.DisableReverse)
|
||||
{
|
||||
item.Reverse = transport.Reverse;
|
||||
}
|
||||
if (transport.DisableSSL)
|
||||
{
|
||||
item.SSL = transport.SSL;
|
||||
}
|
||||
if (item.Order == 0)
|
||||
{
|
||||
item.Order = transport.Order;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await tunnelMessengerAdapter.SetTunnelTransports("default",transportItems).ConfigureAwait(false);
|
||||
|
||||
await tunnelMessengerAdapter.SetTunnelTransports(Helper.GlobalString, transports).ConfigureAwait(false);
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Info($"load tunnel transport:{string.Join(",", transports.Select(c => c.GetType().Name))}");
|
||||
}
|
||||
|
||||
1
src/linker.web/public/blist.svg
Normal file
1
src/linker.web/public/blist.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763363882257" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10530" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#FF090B" p-id="10531"></path><path d="M512 512m-426.666667 0a426.666667 426.666667 0 1 0 853.333334 0 426.666667 426.666667 0 1 0-853.333334 0Z" fill="#FFFFFF" p-id="10532"></path><path d="M624.64 469.333333v104.106667l95.573333 220.16s29.013333 46.08-17.066666 59.733333c0 0-30.72 5.12-46.08-23.893333l-85.333334-160.426667s-18.773333-47.786667-34.133333-30.72L477.866667 703.146667s-17.066667 34.133333-17.066667 128c0 0 6.826667 22.186667-37.546667 22.186666 0 0-30.72 1.706667-30.72-20.48v-87.04s5.12-98.986667 92.16-197.973333v-29.013333l-15.36-81.92s-17.066667-20.48-29.013333-3.413334c0 0 3.413333 23.893333-47.786667 51.2l-58.026666 20.48s-32.426667 11.946667-37.546667-6.826666c0 0-11.946667-25.6 6.826667-32.426667l52.906666-29.013333s61.44-40.96 58.026667-92.16c0 0 10.24-58.026667 63.146667-75.093334 0 0 25.6-20.48 58.026666-8.533333l138.24 63.146667s18.773333 11.946667 18.773334 25.6v136.533333s3.413333 25.6-15.36 25.6c0 0-30.72-10.24-30.72-18.773333l1.706666-102.4s-3.413333-8.533333-25.6-22.186667l-22.186666-17.066667s-25.6-17.066667-20.48 6.826667c-1.706667 0 44.373333 68.266667 44.373333 110.933333zM445.44 256c-32.426667 0-59.733333-25.6-59.733333-59.733333 0-32.426667 25.6-59.733333 59.733333-59.733334s59.733333 25.6 59.733333 59.733334-25.6 59.733333-59.733333 59.733333z" fill="#1E1C1A" p-id="10533"></path><path d="M200.6528 152.3712l670.976 670.976-48.2816 48.264533L152.3712 200.635733z" fill="#FF090B" p-id="10534"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763014920950" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11190" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><path d="M0 0m78.769231 0l866.461538 0q78.769231 0 78.769231 78.769231l0 866.461538q0 78.769231-78.769231 78.769231l-866.461538 0q-78.769231 0-78.769231-78.769231l0-866.461538q0-78.769231 78.769231-78.769231Z" fill="#FFFFFF" fill-opacity="0" p-id="11191"></path><path d="M555.204923 445.518769h232.763077l-299.244308 432.206769v-299.244307H256l299.204923-432.206769v299.244307z" fill="#FF0000" p-id="11192"></path></svg>
|
||||
|
Before Width: | Height: | Size: 747 B |
1
src/linker.web/public/wlist-none.svg
Normal file
1
src/linker.web/public/wlist-none.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763364230445" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12699" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><path d="M0 512c0 282.4 229.6 512 512 512s512-229.6 512-512S794.4 0 512 0 0 229.6 0 512z" fill="#515151" p-id="12700" data-spm-anchor-id="a313x.search_index.0.i2.53a83a81qrVrBK" class="selected"></path><path d="M85.6 512c0 236 191.2 426.4 426.4 426.4 236 0 426.4-191.2 426.4-426.4 0-236-191.2-426.4-426.4-426.4S85.6 276 85.6 512z" fill="#FFFFFF" p-id="12701"></path><path d="M624.8 469.6v104L720 793.6s28.8 46.4-16.8 60c0 0-30.4 4.8-46.4-24L572 668.8s-18.4-48-34.4-30.4l-60 64.8s-16.8 34.4-16.8 128c0 0 7.2 22.4-37.6 22.4 0 0-30.4 1.6-30.4-20.8V745.6s4.8-99.2 92-197.6v-28.8l-15.2-81.6s-16.8-20.8-28.8-3.2c0 0 3.2 24-48 51.2l-58.4 20.8s-32.8 12-37.6-7.2c0 0-12-25.6 7.2-32.8l52.8-28.8s61.6-40.8 58.4-92c0 0 10.4-58.4 63.2-75.2 0 0 25.6-20.8 58.4-8.8l138.4 63.2s18.4 12 18.4 25.6v136.8s3.2 25.6-15.2 25.6c0 0-30.4-10.4-30.4-18.4l1.6-102.4s-3.2-8.8-25.6-22.4l-22.4-16.8S576 336 580.8 360c-2.4-1.6 44 66.4 44 109.6zM445.6 256c-32.8 0-60-25.6-60-60 0-32.8 25.6-60 60-60s60 25.6 60 60-26.4 60-60 60z" fill="#515151" p-id="12702" data-spm-anchor-id="a313x.search_index.0.i3.53a83a81qrVrBK" class="selected"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
src/linker.web/public/wlist.svg
Normal file
1
src/linker.web/public/wlist.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763363855111" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8440" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><path d="M0 512c0 282.4 229.6 512 512 512s512-229.6 512-512S794.4 0 512 0 0 229.6 0 512z" fill="#009944" p-id="8441"></path><path d="M85.6 512c0 236 191.2 426.4 426.4 426.4 236 0 426.4-191.2 426.4-426.4 0-236-191.2-426.4-426.4-426.4S85.6 276 85.6 512z" fill="#FFFFFF" p-id="8442"></path><path d="M624.8 469.6v104L720 793.6s28.8 46.4-16.8 60c0 0-30.4 4.8-46.4-24L572 668.8s-18.4-48-34.4-30.4l-60 64.8s-16.8 34.4-16.8 128c0 0 7.2 22.4-37.6 22.4 0 0-30.4 1.6-30.4-20.8V745.6s4.8-99.2 92-197.6v-28.8l-15.2-81.6s-16.8-20.8-28.8-3.2c0 0 3.2 24-48 51.2l-58.4 20.8s-32.8 12-37.6-7.2c0 0-12-25.6 7.2-32.8l52.8-28.8s61.6-40.8 58.4-92c0 0 10.4-58.4 63.2-75.2 0 0 25.6-20.8 58.4-8.8l138.4 63.2s18.4 12 18.4 25.6v136.8s3.2 25.6-15.2 25.6c0 0-30.4-10.4-30.4-18.4l1.6-102.4s-3.2-8.8-25.6-22.4l-22.4-16.8S576 336 580.8 360c-2.4-1.6 44 66.4 44 109.6zM445.6 256c-32.8 0-60-25.6-60-60 0-32.8 25.6-60 60-60s60 25.6 60 60-26.4 60-60 60z" fill="#009944" p-id="8443"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -13,4 +13,7 @@ export const wlistStatus = (type) => {
|
||||
}
|
||||
export const wlistAddOrder = (data) => {
|
||||
return sendWebsocketMsg('whitelist/addorder', data);
|
||||
}
|
||||
export const wlistList = (data) => {
|
||||
return sendWebsocketMsg('whitelist/list', data);
|
||||
}
|
||||
@@ -13,20 +13,9 @@
|
||||
</p>
|
||||
<p class="flex">
|
||||
<template v-if="scope.row.Connected">
|
||||
<div>
|
||||
<template v-if="scope.row.hook_tuntap && scope.row.hook_tuntap.systems">
|
||||
<template v-for="system in scope.row.hook_tuntap.systems">
|
||||
<span :title="scope.row.hook_tuntap.SystemInfo">
|
||||
<img class="system" :src="`./${system}.svg`" />
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
<span title="20Mbps">
|
||||
<a href="javascript:;"><img class="system" src="lightning.svg" /></a>
|
||||
</span>
|
||||
|
||||
<SystemInfo :item="scope.row"></SystemInfo>
|
||||
<span class="flex-1"></span>
|
||||
<WlistShow type="Relay" :item="scope.row"></WlistShow>
|
||||
<UpdaterBtn :config="true" :item="scope.row"></UpdaterBtn>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -42,10 +31,13 @@ import { ref } from 'vue';
|
||||
import {Search} from '@element-plus/icons-vue'
|
||||
import UpdaterBtn from '../updater/UpdaterBtn.vue';
|
||||
import DeviceName from './DeviceName.vue';
|
||||
import SystemInfo from '../tuntap/SystemInfo.vue';
|
||||
import WlistShow from '../wlist/Device.vue'
|
||||
|
||||
|
||||
export default {
|
||||
emits:['refresh'],
|
||||
components:{Search,UpdaterBtn,DeviceName},
|
||||
components:{Search,UpdaterBtn,DeviceName,SystemInfo,WlistShow},
|
||||
setup(props,{emit}) {
|
||||
|
||||
const name = ref(sessionStorage.getItem('search-name') || '');
|
||||
@@ -62,16 +54,8 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
|
||||
.el-input{
|
||||
width:12rem;
|
||||
margin-right:.6rem
|
||||
}
|
||||
img.system{
|
||||
height:1.4rem;
|
||||
vertical-align: middle;
|
||||
margin-right:.1rem
|
||||
border:1px solid rgba(0,0,0,.1);
|
||||
border-radius:.2rem;
|
||||
}
|
||||
</style>
|
||||
@@ -31,6 +31,7 @@ export const provideDevices = () => {
|
||||
}
|
||||
const deviceRefreshHook = (name) => {
|
||||
if(hooks[name]) {
|
||||
hooks[name].refresh = true;
|
||||
hooks[name].changed = true;
|
||||
}
|
||||
}
|
||||
@@ -41,7 +42,7 @@ export const provideDevices = () => {
|
||||
const hook = hooks[name];
|
||||
if(hook.refresh) {
|
||||
hook.refresh = false;
|
||||
hook.refreshFn();
|
||||
hook.refreshFn(devices.page.List);
|
||||
}
|
||||
}
|
||||
for(let name in hooks) {
|
||||
@@ -57,7 +58,7 @@ export const provideDevices = () => {
|
||||
}
|
||||
for(let name in hooks) {
|
||||
const hook = hooks[name];
|
||||
hook.changed = await hook.dataFn();
|
||||
hook.changed = await hook.dataFn(devices.page.List);
|
||||
}
|
||||
devices.timer1 = setTimeout(fn,1000);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<AccessBoolean value="FirewallOther">
|
||||
<AccessBoolean value="FirewallSelf,FirewallOther">
|
||||
<template #default="{values}">
|
||||
<template v-if="values.FirewallOther && !item.isSelf">
|
||||
<template v-if="(values.FirewallSelf && item.isSelf) || (values.FirewallOther && !item.isSelf)">
|
||||
<el-col :span="12">
|
||||
<a href="javascript:;" :class="{green:firewallCounter>0}" @click="handleFirewall"><img src="firewall.svg" alt="firewall"> ({{firewallCounter}})</a>
|
||||
</el-col>
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
<div>
|
||||
<div class="numbers">
|
||||
<el-row>
|
||||
<FirewallOper :item="scope.row"></FirewallOper>
|
||||
<WakeupOper :item="scope.row"></WakeupOper>
|
||||
<TransportOper :item="scope.row"></TransportOper>
|
||||
<template v-if="scope.row.Connected">
|
||||
<FirewallOper :item="scope.row"></FirewallOper>
|
||||
<WakeupOper :item="scope.row"></WakeupOper>
|
||||
<TransportOper :item="scope.row"></TransportOper>
|
||||
</template>
|
||||
<el-col :span="12">
|
||||
<el-dropdown size="small" >
|
||||
<div class="dropdown">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<AccessShow value="Transport">
|
||||
<el-col :span="12" v-if="!item.isSelf">
|
||||
<el-col :span="12">
|
||||
<a href="javascript:;" :class="{green:transportCounter>0}" @click="handleTransport"><img src="transport.svg" alt="transport"> ({{ transportCounter }})</a>
|
||||
</el-col>
|
||||
</AccessShow>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-dialog v-model="state.show" append-to=".app-wrap" :title="`本机与[${state.machineName}]之间的打洞协议`" top="1vh" width="98%">
|
||||
<el-dialog v-model="state.show" append-to=".app-wrap" :title="state.title" top="1vh" width="98%">
|
||||
<div>
|
||||
<Transport :machineId="state.machineId"></Transport>
|
||||
</div>
|
||||
@@ -9,6 +9,7 @@
|
||||
import { reactive, watch } from 'vue';
|
||||
import Transport from '../transport/Transport.vue'
|
||||
import { useTransport } from './transport';
|
||||
import { injectGlobalData } from '@/provide';
|
||||
export default {
|
||||
props: ['modelValue'],
|
||||
emits: ['update:modelValue'],
|
||||
@@ -16,12 +17,16 @@ export default {
|
||||
Transport
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
|
||||
const globalData = injectGlobalData();
|
||||
const transport = useTransport();
|
||||
|
||||
|
||||
const isSelf = globalData.value.config.Client.Id == transport.value.device.id || !transport.value.device.id;
|
||||
|
||||
const state = reactive({
|
||||
show: true,
|
||||
machineId: transport.value.device.id,
|
||||
machineName: transport.value.device.name
|
||||
title:isSelf? `[${transport.value.device.name}]上的打洞协议` : `本机与[${transport.value.device.name}]之间的打洞协议`,
|
||||
});
|
||||
watch(() => state.show, (val) => {
|
||||
if (!val) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-dialog v-model="state.show" append-to=".app-wrap" :title="`与[${state.device.MachineName}]的链接`" top="1vh" width="500">
|
||||
<el-dialog v-model="state.show" append-to=".app-wrap" :title="`与[${state.device.MachineName}]的链接`" top="1vh" width="350">
|
||||
<div>
|
||||
<el-descriptions border size="small" :column="2" column-max-width="120px" overlength-control="wrap">
|
||||
<el-descriptions border size="small" :column="1" column-max-width="120px" overlength-control="wrap">
|
||||
<el-descriptions-item label="目标">{{ state.connection.IPEndPoint || '0.0.0.0:0' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="事务">{{ state.transactions[state.connection.TransactionId] }}</el-descriptions-item>
|
||||
<el-descriptions-item label="协议">
|
||||
@@ -48,7 +48,7 @@
|
||||
<template #reference>
|
||||
<el-button type="danger" size="small"><el-icon>
|
||||
<Delete />
|
||||
</el-icon></el-button>
|
||||
</el-icon></el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</AccessShow>
|
||||
|
||||
30
src/linker.web/src/views/components/tuntap/SystemInfo.vue
Normal file
30
src/linker.web/src/views/components/tuntap/SystemInfo.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div>
|
||||
<template v-if="item.hook_tuntap && item.hook_tuntap.systems">
|
||||
<template v-for="system in item.hook_tuntap.systems">
|
||||
<span :title="item.hook_tuntap.SystemInfo">
|
||||
<img :src="`./${system}.svg`" />
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props:['item'],
|
||||
setup () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
img{
|
||||
height:1.4rem;
|
||||
vertical-align: middle;
|
||||
margin-right:.1rem
|
||||
border:1px solid rgba(0,0,0,.1);
|
||||
border-radius:.2rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<AccessBoolean value="WakeupOther">
|
||||
<AccessBoolean value="WakeupSelf,WakeupOther">
|
||||
<template #default="{values}">
|
||||
<template v-if="values.WakeupOther && !item.isSelf">
|
||||
<template v-if="(values.WakeupSelf && item.isSelf) || (values.WakeupOther && !item.isSelf)">
|
||||
<el-col :span="12">
|
||||
<a href="javascript:;" :class="{green:wakeupCounter>0}" @click="handleWakeup"><img src="wakeup.svg" alt="wakeup"> ({{ wakeupCounter }})</a>
|
||||
</el-col>
|
||||
|
||||
@@ -105,7 +105,7 @@ export default {
|
||||
UserId:editState.value.UserId || '',
|
||||
Name:editState.value.Name || '',
|
||||
Remark:editState.value.Remark || '',
|
||||
Nodes:editState.value.Nodes || [],
|
||||
Nodes:editState.value.Nodes || ['*'],
|
||||
Bandwidth:editState.value.Bandwidth || 0,
|
||||
UseTime:editState.value.UseTime || '',
|
||||
EndTime:editState.value.EndTime || '',
|
||||
@@ -138,7 +138,8 @@ export default {
|
||||
state.ruleForm.Nodes = state.nodeIds.concat(ports);
|
||||
}
|
||||
|
||||
const handleShowNodes = ()=>{
|
||||
const handleShowNodes = ()=>{
|
||||
return false;
|
||||
state.nodeIds = state.ruleForm.Nodes.filter(c=>!!!state.prefix ||c.indexOf(state.prefix) < 0);
|
||||
state.showNodes = true;
|
||||
}
|
||||
|
||||
64
src/linker.web/src/views/components/wlist/Device.vue
Normal file
64
src/linker.web/src/views/components/wlist/Device.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<span>
|
||||
<a href="javascript:;" :title="wlist.title" @click="handleWlist">
|
||||
<img :src="wlist.img" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue';
|
||||
import { useWlist } from './wlist';
|
||||
|
||||
export default {
|
||||
props: ['item','type'],
|
||||
setup (props) {
|
||||
const wlistState = useWlist();
|
||||
const text = {'Relay':'中继','SForward':'穿透'}[props.type];
|
||||
const choiceOnece = (json)=>{
|
||||
const arr = Object.keys(json).reduce((arr,curr)=>{
|
||||
arr.push({ id:curr,value:json[curr] });
|
||||
return arr;
|
||||
},[]);
|
||||
|
||||
const denyOrAllow = arr.filter(c=>c.value <= 0);
|
||||
const result = denyOrAllow.length > 0
|
||||
? denyOrAllow.sort((a,b)=>a.value - b.value)[0]
|
||||
: arr.sort((a,b)=>b.value - a.value)[0];
|
||||
|
||||
return {
|
||||
id:result.id,
|
||||
value:result.value,
|
||||
title:result.value < 0 ? `拒绝${text}` : result.value == 0 ? `允许无限速${text}` : `允许${result.value}Mbps限速${text}`,
|
||||
img:result.value < 0 ? 'blist.svg':'wlist.svg'
|
||||
};
|
||||
}
|
||||
|
||||
const wlist = computed(()=>props.item.hook_wlist === undefined || Object.keys(props.item.hook_wlist).length == 0
|
||||
? {id:0,value:0,title:`无${text}限制配置`,img:'wlist-none.svg'}
|
||||
: choiceOnece(props.item.hook_wlist));
|
||||
|
||||
const handleWlist = ()=>{
|
||||
wlistState.value.device.id = props.item.MachineId;
|
||||
wlistState.value.device.name = props.item.MachineName;
|
||||
wlistState.value.device.type = props.type;
|
||||
wlistState.value.device.typeText = text;
|
||||
wlistState.value.show = true;
|
||||
}
|
||||
|
||||
return {
|
||||
wlist,handleWlist
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
img{
|
||||
height:1.4rem;
|
||||
vertical-align: middle;
|
||||
margin-right:.1rem
|
||||
border:1px solid rgba(0,0,0,.1);
|
||||
border-radius:.2rem;
|
||||
}
|
||||
</style>
|
||||
@@ -111,7 +111,7 @@ export default {
|
||||
provide('edit',editState);
|
||||
|
||||
const handleAdd = ()=>{
|
||||
editState.value = {Id:0,Name:'',Nodes:[],Remark:'',UserId:'',Type:props.type,prefix:props.prefix || ''};
|
||||
editState.value = {Id:0,Name:'',Nodes:['*'],Remark:'',UserId:'',Type:props.type,prefix:props.prefix || ''};
|
||||
state.showAdd = true;
|
||||
}
|
||||
const handleEdit = (row)=>{
|
||||
|
||||
127
src/linker.web/src/views/components/wlist/OperDialog.vue
Normal file
127
src/linker.web/src/views/components/wlist/OperDialog.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<el-dialog v-model="state.show" append-to=".app-wrap" :title="state.title" top="1vh" width="370">
|
||||
<div>
|
||||
<el-descriptions border size="small" :column="1" column-max-width="120px" overlength-control="wrap">
|
||||
<el-descriptions-item label="名称">{{ state.status.Info.Name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="带宽">
|
||||
<div>
|
||||
<span v-if="state.status.Info.Bandwidth < 0">禁止</span>
|
||||
<span v-if="state.status.Info.Bandwidth == 0">无限制</span>
|
||||
<span v-else-if="state.status.Info.Bandwidth>0">{{state.status.Info.Bandwidth}}Mbps</span>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ state.status.Info.UseTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结束时间">{{ state.status.Info.EndTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="作用于">
|
||||
<span v-if="state.status.Info.UserId">同用户id客户端</span>
|
||||
<span v-else-if="state.status.Info.MachineId">本客户端</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">{{ state.status.Info.Remark }}</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="操作">
|
||||
<div v-if="state.super">
|
||||
<template v-if="state.status.Info.Id > 0">
|
||||
<el-popconfirm confirm-button-text="确认" cancel-button-text="取消" title="确定删除?" @confirm="handleDel">
|
||||
<template #reference>
|
||||
<el-button type="danger" size="small" :loading="state.loading"><el-icon> <Delete /></el-icon></el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button type="success" size="small" :loading="state.loading" @click="handleAdd"><el-icon> <Plus /></el-icon></el-button>
|
||||
</template>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<Add v-if="state.showAdd" v-model="state.showAdd" @success="handleAddSuccess"></Add>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, onMounted, provide, reactive, ref, watch } from 'vue';
|
||||
import { useWlist } from './wlist';
|
||||
import { wlistDel, wlistStatus } from '@/apis/wlist';
|
||||
import { Delete, Plus } from '@element-plus/icons-vue';
|
||||
import { injectGlobalData } from '@/provide';
|
||||
import Add from './Add.vue';
|
||||
export default {
|
||||
props: ['modelValue'],
|
||||
emits: ['update:modelValue'],
|
||||
components: {Delete, Plus,Add },
|
||||
setup(props, { emit }) {
|
||||
const wlist = useWlist();
|
||||
const globalData = injectGlobalData();
|
||||
|
||||
const state = reactive({
|
||||
show: true,
|
||||
machineId: wlist.value.device.id,
|
||||
title: `[${wlist.value.device.name}]上的${wlist.value.device.typeText}白名单`,
|
||||
status: {
|
||||
Enabled:false,
|
||||
Type:'',
|
||||
Info:{}
|
||||
},
|
||||
super:computed(()=>globalData.value.signin.Super),
|
||||
loading:false,
|
||||
showAdd:false
|
||||
});
|
||||
watch(() => state.show, (val) => {
|
||||
if (!val) {
|
||||
setTimeout(() => {
|
||||
emit('update:modelValue', val);
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
|
||||
const handleRefreshData = ()=>{
|
||||
wlistStatus(wlist.value.device.type).then(res=>{
|
||||
state.status = res;
|
||||
state.status.Info = res.Info || {}
|
||||
});
|
||||
}
|
||||
const handleDel = ()=>{
|
||||
state.loading = true;
|
||||
wlistDel(state.status.Info.Id).then(()=>{
|
||||
state.loading = false;
|
||||
handleRefreshData();
|
||||
emit('change');
|
||||
}).catch(()=>{
|
||||
state.loading = false;
|
||||
})
|
||||
}
|
||||
|
||||
const editState = ref({});
|
||||
const nodes = ref([]);
|
||||
provide('edit',editState);
|
||||
provide('nodes',nodes);
|
||||
const handleAdd = ()=>{
|
||||
editState.value = {
|
||||
Id:0
|
||||
,Name:wlist.value.device.name
|
||||
,Nodes:['*']
|
||||
,Remark:''
|
||||
,MachineId:wlist.value.device.id
|
||||
,Type:wlist.value.device.type
|
||||
,prefix:''
|
||||
};
|
||||
state.showAdd = true;
|
||||
}
|
||||
const handleAddSuccess = ()=>{
|
||||
handleRefreshData();
|
||||
emit('change');
|
||||
}
|
||||
|
||||
|
||||
onMounted(()=>{
|
||||
handleRefreshData();
|
||||
});
|
||||
|
||||
return {
|
||||
state,handleRefreshData,handleDel,handleAdd,handleAddSuccess
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
|
||||
</style>
|
||||
@@ -41,10 +41,8 @@ export default {
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
|
||||
wlistStatus(props.type).then(res=>{
|
||||
state.status = res;
|
||||
console.log(res);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
47
src/linker.web/src/views/components/wlist/wlist.js
Normal file
47
src/linker.web/src/views/components/wlist/wlist.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { wlistList } from "@/apis/wlist";
|
||||
import { inject, provide, ref } from "vue"
|
||||
const wlistSymbol = Symbol();
|
||||
export const provideWlist = () => {
|
||||
const wlist = ref({
|
||||
device: {id:'',name:'',type:'',typeText:''},
|
||||
show:false,
|
||||
|
||||
list: null,
|
||||
});
|
||||
provide(wlistSymbol, wlist);
|
||||
|
||||
|
||||
const wlistDataFn = (devices) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if(wlist.value.list !== null){
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
wlistList({Key:'Relay',Value:devices.map(c=>c.MachineId)}).then((res) => {
|
||||
wlist.value.list = res;
|
||||
resolve(true);
|
||||
}).catch(() => {
|
||||
resolve(false);
|
||||
});
|
||||
})
|
||||
}
|
||||
const wlistRefreshFn = () => {
|
||||
wlist.value.list = null;
|
||||
}
|
||||
const wlistProcessFn = (device,json) => {
|
||||
if(wlist.value.list){
|
||||
Object.assign(json,{
|
||||
hook_wlist: wlist.value.list[`m_${device.MachineId}`] || wlist.value.list[`u_${device.Args.userid}`] || {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
wlist,wlistDataFn,wlistProcessFn,wlistRefreshFn
|
||||
}
|
||||
}
|
||||
|
||||
export const useWlist = () => {
|
||||
return inject(wlistSymbol);
|
||||
}
|
||||
@@ -36,6 +36,7 @@
|
||||
<OperAction v-if="action.show" v-model="action.show" ></OperAction>
|
||||
<Stopwatch v-if="flow.showStopwatch" v-model="flow.showStopwatch" ></Stopwatch>
|
||||
<OperFlow v-if="flow.show" v-model="flow.show" ></OperFlow>
|
||||
<OperWlist v-if="wlist.show" v-model="wlist.show" @change="deviceRefreshHook('wlist')" ></OperWlist>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -95,6 +96,8 @@ import { provideFirewall } from '@/views/components/firewall/firewall'
|
||||
import { provideWakeup } from '@/views/components/wakeup/wakeup'
|
||||
import { provideTransport } from '@/views/components/transport/transport'
|
||||
import { provideAction } from '@/views/components/action/action'
|
||||
import { provideWlist } from '@/views/components/wlist/wlist'
|
||||
import OperWlist from '../../../components/wlist/OperDialog.vue'
|
||||
|
||||
|
||||
export default {
|
||||
@@ -108,7 +111,7 @@ export default {
|
||||
Forward,ForwardEdit,
|
||||
SForwardEdit ,UpdaterConfirm,
|
||||
Stopwatch,
|
||||
Oper,OperFirewall,OperWakeup ,OperTransport,OperAction,OperFlow
|
||||
Oper,OperFirewall,OperWakeup ,OperTransport,OperAction,OperFlow,OperWlist
|
||||
},
|
||||
setup(props) {
|
||||
|
||||
@@ -144,6 +147,9 @@ export default {
|
||||
deviceAddHook('tuntap',tuntapDataFn,tuntapProcessFn,tuntapRefreshFn);
|
||||
const {connections,connectionDataFn,connectionProcessFn,connectionRefreshFn } = provideConnections();
|
||||
deviceAddHook('connection',connectionDataFn,connectionProcessFn,connectionRefreshFn);
|
||||
const {wlist,wlistDataFn,wlistProcessFn,wlistRefreshFn} = provideWlist();
|
||||
deviceAddHook('wlist',wlistDataFn,wlistProcessFn,wlistRefreshFn);
|
||||
|
||||
|
||||
const handleSortChange = (row)=>{
|
||||
|
||||
@@ -212,7 +218,7 @@ export default {
|
||||
tunnel,connections,
|
||||
forward,
|
||||
sforward,
|
||||
updater,flow,oper,firewall,wakeup,transport,action
|
||||
updater,flow,oper,firewall,wakeup,transport,action,wlist
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user