添加项目文件。
This commit is contained in:
71
UIShare/UIViewModel/CanMessageShowModel.cs
Normal file
71
UIShare/UIViewModel/CanMessageShowModel.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class CanMessageShowModel : BindableBase
|
||||
{
|
||||
// 字段声明
|
||||
private byte _通道;
|
||||
private int _报文ID;
|
||||
private ulong _时间戳;
|
||||
private byte _长度;
|
||||
private bool _fd;
|
||||
private bool _isTx;
|
||||
private byte[] _bytes = new byte[64];
|
||||
private string _报文;
|
||||
|
||||
// 通道属性
|
||||
public byte 通道
|
||||
{
|
||||
get { return _通道; }
|
||||
set { SetProperty(ref _通道, value); }
|
||||
}
|
||||
|
||||
// 报文ID属性
|
||||
public int 报文ID
|
||||
{
|
||||
get { return _报文ID; }
|
||||
set { SetProperty(ref _报文ID, value); }
|
||||
}
|
||||
|
||||
// 时间戳属性
|
||||
public ulong 时间戳
|
||||
{
|
||||
get { return _时间戳; }
|
||||
set { SetProperty(ref _时间戳, value); }
|
||||
}
|
||||
|
||||
// 长度属性
|
||||
public byte 长度
|
||||
{
|
||||
get { return _长度; }
|
||||
set { SetProperty(ref _长度, value); }
|
||||
}
|
||||
|
||||
// FD属性
|
||||
public bool FD
|
||||
{
|
||||
get { return _fd; }
|
||||
set { SetProperty(ref _fd, value); }
|
||||
}
|
||||
|
||||
// IsTx属性
|
||||
public bool IsTx
|
||||
{
|
||||
get { return _isTx; }
|
||||
set { SetProperty(ref _isTx, value); }
|
||||
}
|
||||
|
||||
// Bytes属性
|
||||
public byte[] Bytes
|
||||
{
|
||||
get { return _bytes; }
|
||||
set { SetProperty(ref _bytes, value); }
|
||||
}
|
||||
|
||||
// 报文属性
|
||||
public string 报文
|
||||
{
|
||||
get { return _报文; }
|
||||
set { SetProperty(ref _报文, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
22
UIShare/UIViewModel/CustomPanelItem.cs
Normal file
22
UIShare/UIViewModel/CustomPanelItem.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Prism.Mvvm;
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class CustomPanelItem : BindableBase
|
||||
{
|
||||
private string _name;
|
||||
private string _pointY;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
public string PointY
|
||||
{
|
||||
get => _pointY;
|
||||
set => SetProperty(ref _pointY, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
UIShare/UIViewModel/DeviceInfoModel.cs
Normal file
44
UIShare/UIViewModel/DeviceInfoModel.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class DeviceInfoModel : BindableBase
|
||||
{
|
||||
private string _deviceName;
|
||||
public string DeviceName
|
||||
{
|
||||
get => _deviceName;
|
||||
set => SetProperty(ref _deviceName, value);
|
||||
}
|
||||
|
||||
private string _deviceType;
|
||||
public string DeviceType
|
||||
{
|
||||
get => _deviceType;
|
||||
set => SetProperty(ref _deviceType, value);
|
||||
}
|
||||
|
||||
private string _remark;
|
||||
public string Remark
|
||||
{
|
||||
get => _remark;
|
||||
set => SetProperty(ref _remark, value);
|
||||
}
|
||||
|
||||
private bool _isEnabled;
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set => SetProperty(ref _isEnabled, value);
|
||||
}
|
||||
|
||||
private bool _isConnected;
|
||||
public bool IsConnected
|
||||
{
|
||||
get => _isConnected;
|
||||
set => SetProperty(ref _isConnected, value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
18
UIShare/UIViewModel/InstructionNode.cs
Normal file
18
UIShare/UIViewModel/InstructionNode.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class InstructionNode
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ObservableCollection<InstructionNode> Children { get; set; } = new();
|
||||
public object Tag { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
40
UIShare/UIViewModel/MethodModel.cs
Normal file
40
UIShare/UIViewModel/MethodModel.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class MethodModel
|
||||
{
|
||||
|
||||
#region 构造函数
|
||||
|
||||
public MethodModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MethodModel(MethodModel source)
|
||||
{
|
||||
if (source == null) return;
|
||||
|
||||
Name = source.Name;
|
||||
FullName = source.FullName;
|
||||
|
||||
// 深拷贝参数
|
||||
Parameters = new ObservableCollection<ParameterModel>(
|
||||
source.Parameters.Select(p => new ParameterModel(p)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public string? Name { get; set; }
|
||||
|
||||
public string? FullName { get; set; }
|
||||
|
||||
public ObservableCollection<ParameterModel> Parameters { get; set; } = [];
|
||||
}
|
||||
}
|
||||
316
UIShare/UIViewModel/ParameterModel.cs
Normal file
316
UIShare/UIViewModel/ParameterModel.cs
Normal file
@@ -0,0 +1,316 @@
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Mvvm; // 引入 Prism 的 BindableBase
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class ParameterModel : BindableBase
|
||||
{
|
||||
#region 构造函数
|
||||
|
||||
public ParameterModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ParameterModel(ParameterModel source)
|
||||
{
|
||||
if (source == null) return;
|
||||
|
||||
ID = source.ID;
|
||||
Name = source.Name;
|
||||
Type = source.Type;
|
||||
Category = source.Category;
|
||||
IsUseVar = source.IsUseVar;
|
||||
IsSave = source.IsSave;
|
||||
VariableName = source.VariableName;
|
||||
VariableID = source.VariableID;
|
||||
IsGlobal = source.IsGlobal;
|
||||
Value = source.Value;
|
||||
LowerLimit = source.LowerLimit;
|
||||
UpperLimit = source.UpperLimit;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Guid _id = Guid.NewGuid();
|
||||
public Guid ID
|
||||
{
|
||||
get => _id;
|
||||
set => SetProperty(ref _id, value);
|
||||
}
|
||||
|
||||
private bool _isVisible = true;
|
||||
public bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set => SetProperty(ref _isVisible, value);
|
||||
}
|
||||
|
||||
private string _name;
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
private Type _type = typeof(string);
|
||||
public Type Type
|
||||
{
|
||||
get => _type;
|
||||
set => SetProperty(ref _type, value);
|
||||
}
|
||||
|
||||
private ParameterCategory _category = ParameterCategory.Temp;
|
||||
public ParameterCategory Category
|
||||
{
|
||||
get => _category;
|
||||
set => SetProperty(ref _category, value);
|
||||
}
|
||||
|
||||
private bool _isGlobal;
|
||||
public bool IsGlobal
|
||||
{
|
||||
get => _isGlobal;
|
||||
set => SetProperty(ref _isGlobal, value);
|
||||
}
|
||||
|
||||
private object? _value;
|
||||
public object? Value
|
||||
{
|
||||
get => _value;
|
||||
set => SetProperty(ref _value, value);
|
||||
}
|
||||
|
||||
private object? _lowerLimit;
|
||||
public object? LowerLimit
|
||||
{
|
||||
get => _lowerLimit;
|
||||
set => SetProperty(ref _lowerLimit, value);
|
||||
}
|
||||
|
||||
private object? _upperLimit;
|
||||
public object? UpperLimit
|
||||
{
|
||||
get => _upperLimit;
|
||||
set => SetProperty(ref _upperLimit, value);
|
||||
}
|
||||
|
||||
private bool _result = true;
|
||||
public bool Result
|
||||
{
|
||||
get => _result;
|
||||
set => SetProperty(ref _result, value);
|
||||
}
|
||||
|
||||
private bool _isUseVar;
|
||||
public bool IsUseVar
|
||||
{
|
||||
get => _isUseVar;
|
||||
set => SetProperty(ref _isUseVar, value);
|
||||
}
|
||||
|
||||
private bool _isSave;
|
||||
public bool IsSave
|
||||
{
|
||||
get => _isSave;
|
||||
set => SetProperty(ref _isSave, value);
|
||||
}
|
||||
|
||||
private string? _variableName;
|
||||
public string? VariableName
|
||||
{
|
||||
get => _variableName;
|
||||
set => SetProperty(ref _variableName, value);
|
||||
}
|
||||
|
||||
private Guid? _variableID;
|
||||
public Guid? VariableID
|
||||
{
|
||||
get => _variableID;
|
||||
set => SetProperty(ref _variableID, value);
|
||||
}
|
||||
|
||||
public enum ParameterCategory
|
||||
{
|
||||
Input,
|
||||
Output,
|
||||
Temp
|
||||
}
|
||||
|
||||
public object? GetActualValue(Dictionary<Guid, ParameterModel> paraList)
|
||||
{
|
||||
HashSet<Guid> visitedIds = new HashSet<Guid>();
|
||||
ParameterModel current = this;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
if (!current.IsUseVar)
|
||||
{
|
||||
return current.Value;
|
||||
}
|
||||
|
||||
if (visitedIds.Contains(current.ID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
visitedIds.Add(current.ID);
|
||||
|
||||
if (current.VariableID == null)
|
||||
{
|
||||
if (Type != null && Value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ChangeType(Value, Type);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParameterModel? next = paraList[(Guid)current.VariableID!];
|
||||
if (next == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ParameterModel? GetCurrentParameter(Dictionary<Guid, ParameterModel> paraList)
|
||||
{
|
||||
HashSet<Guid> visitedIds = new HashSet<Guid>();
|
||||
ParameterModel current = this;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
if (current.VariableID == null)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
if (visitedIds.Contains(current.ID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
visitedIds.Add(current.ID);
|
||||
|
||||
if (current.VariableID == null)
|
||||
{
|
||||
if (Type != null && Value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return current;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParameterModel? next = paraList[(Guid)current.VariableID!];
|
||||
if (next == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public (bool, string?) GetResult()
|
||||
{
|
||||
if (Type == typeof(string) && (!string.IsNullOrWhiteSpace(LowerLimit?.ToString()) || !string.IsNullOrWhiteSpace(UpperLimit?.ToString())))
|
||||
{
|
||||
return (true, $"参数 [ {Name}({Type}) ] 不可比较");
|
||||
}
|
||||
|
||||
if (Value == null || (LowerLimit == null && UpperLimit == null))
|
||||
{
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Value?.ToString()) || (string.IsNullOrWhiteSpace(LowerLimit?.ToString()) && string.IsNullOrWhiteSpace(UpperLimit?.ToString())))
|
||||
{
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
object? comparableValue = ConvertToComparable(Value);
|
||||
object? comparableLower = LowerLimit != null ? ConvertToComparable(LowerLimit) : null;
|
||||
object? comparableUpper = UpperLimit != null ? ConvertToComparable(UpperLimit) : null;
|
||||
|
||||
if (comparableValue == null)
|
||||
{
|
||||
return (true, $"参数 [ {Name}({Type}) ] 不可比较");
|
||||
}
|
||||
|
||||
bool lowerValid = true;
|
||||
bool upperValid = true;
|
||||
|
||||
if (comparableLower != null)
|
||||
{
|
||||
lowerValid = CompareValues(comparableValue, comparableLower) >= 0;
|
||||
}
|
||||
|
||||
if (comparableUpper != null)
|
||||
{
|
||||
upperValid = CompareValues(comparableValue, comparableUpper) <= 0;
|
||||
}
|
||||
|
||||
return (lowerValid && upperValid, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (true, $"参数 [ {Name}({Type}) ] 上下限比较失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static object? ConvertToComparable(object value)
|
||||
{
|
||||
if (value is IConvertible convertible)
|
||||
{
|
||||
try
|
||||
{
|
||||
return convertible.ToDouble(null);
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
return convertible.ToDateTime(null);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int CompareValues(object a, object b)
|
||||
{
|
||||
if (a is double aDouble && b is double bDouble)
|
||||
{
|
||||
return aDouble.CompareTo(bDouble);
|
||||
}
|
||||
|
||||
if (a is DateTime aDate && b is DateTime bDate)
|
||||
{
|
||||
return aDate.CompareTo(bDate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
51
UIShare/UIViewModel/ProgramModel.cs
Normal file
51
UIShare/UIViewModel/ProgramModel.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Prism.Mvvm; // 引入 Prism 的 BindableBase
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class ProgramModel : BindableBase
|
||||
{
|
||||
#region 构造函数
|
||||
|
||||
public ProgramModel()
|
||||
{
|
||||
// 可以进行初始化操作
|
||||
}
|
||||
|
||||
public ProgramModel(ProgramModel source)
|
||||
{
|
||||
ID = source.ID;
|
||||
StepCollection = new ObservableCollection<StepModel>(source.StepCollection.Select(p => new StepModel(p)));
|
||||
ErrorStepCollection = new ObservableCollection<StepModel>(source.ErrorStepCollection.Select(p => new StepModel(p)));
|
||||
Parameters = new ObservableCollection<ParameterModel>(source.Parameters.Select(p => new ParameterModel(p)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Guid ID { get; set; } = Guid.NewGuid();
|
||||
|
||||
private ObservableCollection<StepModel> _stepCollection = new ObservableCollection<StepModel>();
|
||||
public ObservableCollection<StepModel> StepCollection
|
||||
{
|
||||
get => _stepCollection;
|
||||
set => SetProperty(ref _stepCollection, value);
|
||||
}
|
||||
private ObservableCollection<StepModel> _errorStepCollection = new ObservableCollection<StepModel>();
|
||||
public ObservableCollection<StepModel> ErrorStepCollection
|
||||
{
|
||||
get => _errorStepCollection;
|
||||
set => SetProperty(ref _errorStepCollection, value);
|
||||
}
|
||||
|
||||
private ObservableCollection<ParameterModel> _parameters = new ObservableCollection<ParameterModel>();
|
||||
public ObservableCollection<ParameterModel> Parameters
|
||||
{
|
||||
get => _parameters;
|
||||
set => SetProperty(ref _parameters, value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
178
UIShare/UIViewModel/StepModel.cs
Normal file
178
UIShare/UIViewModel/StepModel.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Mvvm; // 引入 Prism 的 BindableBase
|
||||
using System;
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class StepModel : BindableBase
|
||||
{
|
||||
#region 构造函数
|
||||
|
||||
public StepModel() { }
|
||||
|
||||
public StepModel(StepModel source)
|
||||
{
|
||||
if (source == null) return;
|
||||
|
||||
ID = source.ID;
|
||||
Index = source.Index;
|
||||
Name = source.Name;
|
||||
StepType = source.StepType;
|
||||
LoopCount = source.LoopCount;
|
||||
LoopStartStepId = source.LoopStartStepId;
|
||||
OKExpression = source.OKExpression;
|
||||
OKGotoStepID = source.OKGotoStepID;
|
||||
GotoSettingString = source.GotoSettingString;
|
||||
NGGotoStepID = source.NGGotoStepID;
|
||||
Description = source.Description;
|
||||
IsUsed = source.IsUsed;
|
||||
|
||||
if (source.Method != null)
|
||||
{
|
||||
Method = new MethodModel(source.Method);
|
||||
}
|
||||
if (source.SubProgram != null)
|
||||
{
|
||||
SubProgram = new ProgramModel(source.SubProgram);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Guid _id = Guid.NewGuid();
|
||||
|
||||
public Guid ID
|
||||
{
|
||||
get => _id;
|
||||
set => SetProperty(ref _id, value);
|
||||
}
|
||||
|
||||
private bool _isUsed = true;
|
||||
|
||||
public bool IsUsed
|
||||
{
|
||||
get => _isUsed;
|
||||
set => SetProperty(ref _isUsed, value);
|
||||
}
|
||||
|
||||
private int _index;
|
||||
|
||||
public int Index
|
||||
{
|
||||
get => _index;
|
||||
set => SetProperty(ref _index, value);
|
||||
}
|
||||
|
||||
private string? _name;
|
||||
|
||||
public string? Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
private string? _stepType;
|
||||
|
||||
public string? StepType
|
||||
{
|
||||
get => _stepType;
|
||||
set => SetProperty(ref _stepType, value);
|
||||
}
|
||||
|
||||
private MethodModel? _method;
|
||||
|
||||
public MethodModel? Method
|
||||
{
|
||||
get => _method;
|
||||
set => SetProperty(ref _method, value);
|
||||
}
|
||||
|
||||
private ProgramModel? _subProgram;
|
||||
|
||||
public ProgramModel? SubProgram
|
||||
{
|
||||
get => _subProgram;
|
||||
set => SetProperty(ref _subProgram, value);
|
||||
}
|
||||
|
||||
private int? _loopCount;
|
||||
|
||||
public int? LoopCount
|
||||
{
|
||||
get => _loopCount;
|
||||
set => SetProperty(ref _loopCount, value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
private int? _currentLoopCount;
|
||||
[JsonIgnore]
|
||||
public int? CurrentLoopCount
|
||||
{
|
||||
get => _currentLoopCount;
|
||||
set => SetProperty(ref _currentLoopCount, value);
|
||||
}
|
||||
|
||||
private Guid? _loopStartStepId;
|
||||
|
||||
public Guid? LoopStartStepId
|
||||
{
|
||||
get => _loopStartStepId;
|
||||
set => SetProperty(ref _loopStartStepId, value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
private int _result = -1;
|
||||
[JsonIgnore]
|
||||
public int Result
|
||||
{
|
||||
get => _result;
|
||||
set => SetProperty(ref _result, value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
private int? _runTime;
|
||||
[JsonIgnore]
|
||||
public int? RunTime
|
||||
{
|
||||
get => _runTime;
|
||||
set => SetProperty(ref _runTime, value);
|
||||
}
|
||||
|
||||
private string? _okExpression;
|
||||
|
||||
public string? OKExpression
|
||||
{
|
||||
get => _okExpression;
|
||||
set => SetProperty(ref _okExpression, value);
|
||||
}
|
||||
|
||||
private string _gotoSettingString = "";
|
||||
|
||||
public string GotoSettingString
|
||||
{
|
||||
get => _gotoSettingString;
|
||||
set => SetProperty(ref _gotoSettingString, value);
|
||||
}
|
||||
|
||||
private Guid? _okGotoStepID;
|
||||
|
||||
public Guid? OKGotoStepID
|
||||
{
|
||||
get => _okGotoStepID;
|
||||
set => SetProperty(ref _okGotoStepID, value);
|
||||
}
|
||||
|
||||
private Guid? _ngGotoStepID;
|
||||
|
||||
public Guid? NGGotoStepID
|
||||
{
|
||||
get => _ngGotoStepID;
|
||||
set => SetProperty(ref _ngGotoStepID, value);
|
||||
}
|
||||
|
||||
private string? _description;
|
||||
|
||||
public string? Description
|
||||
{
|
||||
get => _description;
|
||||
set => SetProperty(ref _description, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
UIShare/UIViewModel/SubProgramItem.cs
Normal file
15
UIShare/UIViewModel/SubProgramItem.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
public class SubProgramItem
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
public string FilePath { get; set; } = "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user