Compare commits

...

60 Commits

Author SHA1 Message Date
Kimdiego2098
32844a20c6 2.0.9.2 2023-08-19 12:08:49 +08:00
Kimdiego2098
5b6532c601 xml 2023-08-19 11:06:05 +08:00
Kimdiego2098
2c5b4b4027 修复TcpClient重复释放导致锁异常 2023-08-19 11:05:29 +08:00
Kimdiego2098
72d7ecf195 mas1.0.2默认中文 2023-08-18 18:36:30 +08:00
Kimdiego2098
2cfa6b4306 更新masa1.0.2 2023-08-18 13:59:17 +08:00
Kimdiego2098
6f6ffde0ab 2.0.9.1 2023-08-18 13:33:45 +08:00
Kimdiego2098
1694739a16 修改锁为EasyLock 2023-08-18 12:07:01 +08:00
Kimdiego2098
95d1e8bfca 代码文件编码统一utf-8 2023-08-18 09:57:03 +08:00
Kimdiego2098
60dec08e3c 更换DEMO Include为PackageReference 2023-08-17 15:30:35 +08:00
Kimdiego2098
a99d71be93 底层驱动添加netstandard输出 2023-08-17 15:24:07 +08:00
Kimdiego2098
f1331b6a0c 2.0.8 2023-08-17 10:58:48 +08:00
Kimdiego2098
10d66b642b 调整readme,方便copy账密 2023-08-17 10:28:47 +08:00
Kimdiego2098
cd2310e4a8 优化变量地址输入分割方法;s7读写字符串添加默认编码 2023-08-17 09:50:10 +08:00
Kimdiego2098
1b399cf6b0 优化s7读写字符串,更改特殊方法为读写共用 2023-08-16 17:20:20 +08:00
Kimdiego2098
877445bc0a 修复写入返回结果时的解析,0XFF为成功 2023-08-16 15:56:25 +08:00
Kimdiego2098
9a5b345bde 修复s7字符串打包读取 2023-08-16 15:47:37 +08:00
Kimdiego2098
fc9e8ea7b3 修复s7字符串读取 2023-08-16 15:35:15 +08:00
Kimdiego2098
32be6fcfc1 主动释放锁 2023-08-16 14:56:47 +08:00
Kimdiego2098
49847236c2 OPCUA死区不再固定传入 2023-08-16 14:21:19 +08:00
Kimdiego2098
d8424443e6 fix: 优化JsonUtils中的获取type语句顺序 2023-08-16 08:59:18 +08:00
Kimdiego2098
f3b571ec3f OPC系列增加导出excel/导入系统双选项 2023-08-15 17:38:40 +08:00
Kimdiego2098
99318bb5d7 OPCUA采集设备写入字符串,不再需要传入双引号 2023-08-15 14:15:39 +08:00
Kimdiego2098
1aa154c9aa 历史数据/报警 线程初始化时不再阻塞 2023-08-15 12:12:00 +08:00
Kimdiego2098
c65d8a445b 更改ItemGroup Condition条件 2023-08-14 17:36:59 +08:00
Kimdiego2098
80f4f85570 传播token;
更新admin解决方案
2023-08-14 16:43:30 +08:00
Kimdiego2098
5beee43a6b 优化适配器解析代码 2023-08-14 14:21:00 +08:00
Kimdiego2098
8d6ae203a0 2.0.6 2023-08-13 16:57:12 +08:00
Kimdiego2098
4353479a5c OPCUACClient订阅初始化添加trycatch 2023-08-13 16:29:59 +08:00
Kimdiego2098
34d7687f9e Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-08-13 15:53:33 +08:00
Kimdiego2098
b1dc3cf4af 更新opcuaclient,初始读取server类型改为动态读取 2023-08-13 15:50:47 +08:00
Diego2098
6a58b95933 更新nuget包 2023-08-12 12:09:50 +08:00
Kimdiego2098
d3badfd02b 修复批量令牌强退失效 2023-08-11 15:15:50 +08:00
Kimdiego2098
0098be057b 中间变量导入时添加标识 2023-08-11 14:15:22 +08:00
Kimdiego2098
6f972aa515 2.0.5 2023-08-10 18:23:40 +08:00
Kimdiego2098
7407ba6313 去除不需要的模板 2023-08-10 16:28:52 +08:00
Kimdiego2098
1c79de207b 修改详情模板 2023-08-10 11:23:18 +08:00
Kimdiego2098
257c79db92 添加自定义详情模板 2023-08-10 10:35:19 +08:00
Kimdiego2098
9d1934a308 底层修改:如果连接端口断开,停止等待返回 2023-08-10 10:35:01 +08:00
Kimdiego2098
d70f959902 上传DTO添加 单位 参数 2023-08-10 09:09:09 +08:00
Kimdiego2098
e4d810222f 调整调试页面 2023-08-09 23:45:53 +08:00
Kimdiego2098
bc1af4ae07 添加单文件发布配置 2023-08-09 15:12:55 +08:00
Kimdiego2098
6e688ef43f 去除页面多余引号 2023-08-09 13:45:27 +08:00
Kimdiego2098
f0fe1b23dc 更新2.0.4 2023-08-09 13:00:10 +08:00
Kimdiego2098
aaf2006401 更新opcua写入 2023-08-09 12:43:05 +08:00
Kimdiego2098
b821e26935 更新opcua调试页面 2023-08-09 12:01:23 +08:00
Kimdiego2098
7ae4287157 更新opcua 2023-08-09 11:47:04 +08:00
Kimdiego2098
c6fcc38a65 修复中间变量导入错误 2023-08-09 09:00:49 +08:00
Kimdiego2098
ab2d5c8853 修正错误注释 2023-08-08 18:09:23 +08:00
Kimdiego2098
5e557ff0bc opcua添加初始化连接错误重试 2023-08-08 18:04:24 +08:00
Kimdiego2098
918ca449a1 更新readme 2023-08-08 16:14:06 +08:00
Kimdiego2098
8e73368008 优化大量设备线程重启的耗时 2023-08-08 14:02:00 +08:00
Kimdiego2098
f3c1faf672 2.0.3 2023-08-08 12:59:14 +08:00
Kimdiego2098
d6df04dd6a 底层部分方法更改 2023-08-08 12:31:42 +08:00
Kimdiego2098
b1b9e51ab6 报警/历史值查询时区转换 2023-08-08 09:05:15 +08:00
Kimdiego2098
e49d4770ac 时间最小最大值时不再转换时区 2023-08-08 08:39:20 +08:00
Kimdiego2098
8fa1075511 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2023-08-08 08:28:37 +08:00
Kimdiego2098
9a70169b94 默认不启用单用户登录 2023-08-08 08:28:27 +08:00
Diego2098
fefb928237 更新文档 2023-08-07 22:31:51 +08:00
Diego2098
ad7e700d0d 去除DateTimeOffset类型 2023-08-07 22:30:38 +08:00
Kimdiego2098
1699c69147 更新文档 2023-08-07 17:38:53 +08:00
264 changed files with 2584 additions and 1646 deletions

5
.gitignore vendored
View File

@@ -360,4 +360,7 @@ MigrationBackup/
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
FodyWeavers.xsd
/framework/*Pro*

View File

@@ -5,12 +5,11 @@
**NetCore** 跨平台边缘采集网关(工业设备采集)
**ThingsGateway** 存储库同时提供 [**设备采集驱动**](https://www.nuget.org/profiles/KimDiego)
**ThingsGateway** 存储库同时提供 [**设备采集驱动**](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)
**ThingsGateway** 存储库同时提供 **基于Blazor的权限框架** 查看 [**ThingsGateway.Admin**](https://gitee.com/dotnetchina/ThingsGateway/blob/master/framework/ThingsGateway.Admin.sln)
## 文档
[ThingsGateway](https://diego2098.gitee.io/thingsgateway-docs/) 文档。
@@ -23,7 +22,9 @@
[ThingsGateway演示地址](http://120.24.62.140:5000/)
账户 : **superAdmin** 密码 : **111111**
账户 : **superAdmin**
密码 : **111111**
## 赞助

View File

@@ -81,6 +81,15 @@ dotnet_diagnostic.CA2208.severity = none
# IDE0057: 使用范围运算符
dotnet_diagnostic.IDE0057.severity = none
# IDE0056: 使用索引运算符
dotnet_diagnostic.IDE0056.severity = none
# CA1830: 最好使用 StringBuilder 的强类型 Append 和 Insert 方法重载
dotnet_diagnostic.CA1830.severity = none
# CA1847: 将字符型文本用于单个字符查找
dotnet_diagnostic.CA1847.severity = none
[*.vb]
#### 命名样式 ####

View File

@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Version>2.0.0.0</Version>
<Version>2.0.9.2</Version>
<Authors>Diego</Authors>
<Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright>

View File

@@ -19,7 +19,7 @@ using ThingsGateway.Admin.Core;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 后台登录控制器
/// 文件下载
/// </summary>
[ApiDescriptionSettings(CateGoryConst.ThingsGatewayAdmin, Order = 200)]
[Route("file")]

View File

@@ -46,7 +46,7 @@ namespace ThingsGateway.Admin.Application
[AllowAnonymous, NonUnify]
public async Task<int> SwaggerCheckUrlAsync()
{
var enable = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGERLOGIN_OPEN)).ConfigValue.ToBool();
var enable = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGERLOGIN_OPEN)).ConfigValue.ToBoolean();
return enable ? 401 : 200;
}

View File

@@ -30,7 +30,7 @@
</member>
<member name="T:ThingsGateway.Admin.Application.FileController">
<summary>
后台登录控制器
文件下载
</summary>
</member>
<member name="M:ThingsGateway.Admin.Application.FileController.#ctor(ThingsGateway.Admin.Application.IFileService,ThingsGateway.Admin.Application.IOperateLogService,ThingsGateway.Admin.Application.IVisitLogService)">

View File

@@ -22,7 +22,7 @@ public class LoginOpenApiEvent
/// <summary>
/// 时间
/// </summary>
public DateTimeOffset DateTimeOffset = SysDateTimeExtensions.CurrentDateTime;
public DateTime DateTime = SysDateTimeExtensions.CurrentDateTime;
/// <summary>
/// 登录设备

View File

@@ -41,7 +41,7 @@ public class OpenApiAuthEventSubscriber : IEventSubscriber, ISingleton
openApiUser.LastLoginTime = openApiUser.LatestLoginTime;
openApiUser.LatestLoginDevice = loginEvent.Device.ToString();
openApiUser.LatestLoginIp = loginEvent.Ip;
openApiUser.LatestLoginTime = loginEvent.DateTimeOffset;
openApiUser.LatestLoginTime = loginEvent.DateTime;
#endregion ,

View File

@@ -135,7 +135,7 @@ public class OpenApiAuthService : IOpenApiAuthService, ITransient
{
//获取verificat列表
List<VerificatInfo> verificatInfos = await GetVerificatInfos(loginEvent.OpenApiUser.Id);
var verificatTimeout = loginEvent.DateTimeOffset.AddMinutes(loginEvent.Expire);
var verificatTimeout = loginEvent.DateTime.AddMinutes(loginEvent.Expire);
//生成verificat信息
var verificatInfo = new VerificatInfo
{
@@ -149,7 +149,7 @@ public class OpenApiAuthService : IOpenApiAuthService, ITransient
{
bool isSingle = false;//默认不开启单用户登录
var singleConfig = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SINGLE_OPEN);//获取系统单用户登录选项
if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBool();//如果配置不为空则设置单用户登录选项为系统配置的值
if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBoolean();//如果配置不为空则设置单用户登录选项为系统配置的值
//判断是否单用户登录
if (isSingle)

View File

@@ -40,7 +40,7 @@ public class OpenApiSessionOutput : PrimaryKeyEntity
///</summary>
[Description("最新登录时间")]
[DataTable(Order = 3, IsShow = true, Sortable = true)]
public DateTimeOffset? LatestLoginTime { get; set; }
public DateTime? LatestLoginTime { get; set; }
/// <summary>
/// 令牌数量

View File

@@ -52,8 +52,8 @@ public class OpenApiSessionService : DbRepository<OpenApiUser>, IOpenApiSessionS
//获取该用户的verificat信息
List<VerificatInfo> verificatInfos = await _verificatService.GetOpenApiVerificatIdAsync(input.Id);
//当前需要踢掉用户的verificat
var deleteVerificats = verificatInfos.Where(it => input.VerificatIds.Contains(it.Id)).ToList();
await _verificatService.SetOpenApiVerificatIdAsync(input.Id, deleteVerificats);//如果还有verificat则更新verificat
var setVerificats = verificatInfos.Where(it => !input.VerificatIds.Contains(it.Id)).ToList();
await _verificatService.SetOpenApiVerificatIdAsync(input.Id, setVerificats);//如果还有verificat则更新verificat
}
/// <summary>

View File

@@ -77,7 +77,7 @@
"Id": "22222222222232",
"Category": "SYS_CONFIGBASEDEFAULT",
"ConfigKey": "CONFIG_SINGLE_OPEN",
"ConfigValue": "true",
"ConfigValue": "false",
"Remark": "单用户登录开关",
"SortCode": "10",
"IsDelete": "false"

View File

@@ -42,7 +42,7 @@ public class AuthEventSubscriber : IEventSubscriber, ISingleton
sysUser.LastLoginTime = sysUser.LatestLoginTime;
sysUser.LatestLoginDevice = loginEvent.Device.ToString();
sysUser.LatestLoginIp = loginEvent.Ip;
sysUser.LatestLoginTime = loginEvent.DateTimeOffset;
sysUser.LatestLoginTime = loginEvent.DateTime;
#endregion ,

View File

@@ -79,7 +79,7 @@ public class AuthService : IAuthService
if (sysBase != null)//如果有这个配置项
{
if (sysBase.ConfigValue.ToBool())//如果需要验证码
if (sysBase.ConfigValue.ToBoolean())//如果需要验证码
{
//如果没填验证码,提示验证码不能为空
if (input.ValidCode.IsNullOrEmpty() || input.ValidCodeReqNo == 0) throw Oops.Bah("验证码不能为空").StatusCode(410);
@@ -202,7 +202,7 @@ public class AuthService : IAuthService
{
//获取verificat列表
List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(loginEvent.SysUser.Id);
var verificatTimeout = loginEvent.DateTimeOffset.AddMinutes(loginEvent.Expire);
var verificatTimeout = loginEvent.DateTime.AddMinutes(loginEvent.Expire);
//生成verificat信息
var verificatInfo = new VerificatInfo
{
@@ -217,7 +217,7 @@ public class AuthService : IAuthService
bool isSingle = false;//默认不开启单用户登录
var singleConfig = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SINGLE_OPEN);//获取系统单用户登录选项
if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBool();//如果配置不为空则设置单用户登录选项为系统配置的值
if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBoolean();//如果配置不为空则设置单用户登录选项为系统配置的值
if (isSingle)//判断是否单用户登录
{
await _noticeService.LogoutAsync(loginEvent.SysUser.Id, verificatInfos.Where(it => it.Device == loginEvent.Device.ToString()).ToList(), "该账号已在别处登录!");//通知其他用户下线

View File

@@ -22,7 +22,7 @@ public class LoginEvent
/// <summary>
/// 时间
/// </summary>
public DateTimeOffset DateTimeOffset = SysDateTimeExtensions.CurrentDateTime;
public DateTime DateTime = SysDateTimeExtensions.CurrentDateTime;
/// <summary>
/// 登录设备

View File

@@ -40,7 +40,7 @@ public class SessionOutput : PrimaryKeyEntity
///</summary>
[Description("最新登录时间")]
[DataTable(Order = 4, IsShow = true, Sortable = true)]
public DateTimeOffset? LatestLoginTime { get; set; }
public DateTime? LatestLoginTime { get; set; }
/// <summary>
/// 在线状态

View File

@@ -52,12 +52,11 @@ public class SessionService : DbRepository<SysUser>, ISessionService
{
//获取该用户的verificat信息
List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(input.Id);
//当前需要踢掉用户的verificat
List<VerificatInfo> deleteVerificats = new();
//踢掉包含verificat列表的verificat信息
deleteVerificats = verificatInfos.Where(it => input.VerificatIds.Contains(it.Id)).ToList();
await _verificatService.SetVerificatIdAsync(input.Id, deleteVerificats);//如果还有verificat则更新verificat
var setVerificats = verificatInfos.Where(it => !input.VerificatIds.Contains(it.Id)).ToList();
var deleteVerificats = verificatInfos.Where(it => input.VerificatIds.Contains(it.Id)).ToList();
await _verificatService.SetVerificatIdAsync(input.Id, setVerificats);//如果还有verificat则更新verificat
var message = "您已被强制下线!";
await _noticeService.LogoutAsync(input.Id, deleteVerificats, message);//通知下线

View File

@@ -479,7 +479,7 @@
登录事件参数
</summary>
</member>
<member name="F:ThingsGateway.Admin.Application.LoginOpenApiEvent.DateTimeOffset">
<member name="F:ThingsGateway.Admin.Application.LoginOpenApiEvent.DateTime">
<summary>
时间
</summary>
@@ -1192,7 +1192,7 @@
登录事件参数
</summary>
</member>
<member name="F:ThingsGateway.Admin.Application.LoginEvent.DateTimeOffset">
<member name="F:ThingsGateway.Admin.Application.LoginEvent.DateTime">
<summary>
时间
</summary>

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -20,19 +20,19 @@ namespace ThingsGateway.Admin.Blazor.Core;
public partial class AppBarItems
{
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 链接
/// </summary>
[Parameter]
public string CONFIG_COPYRIGHT_URL { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD>Ȩ
/// 版权
/// </summary>
[Parameter]
public string CONFIG_COPYRIGHT { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 标题
/// </summary>
[Parameter]
public string CONFIG_TITLE { get; set; }

View File

@@ -294,7 +294,7 @@ public partial class AppDateTimePicker
Value = dateTime;
if (ValueChanged.HasDelegate)
{
await ValueChanged.InvokeAsync(dateTime);
await ValueChanged.InvokeAsync(DateTime.SpecifyKind(dateTime.Value, DateTimeKind.Utc));
}
}

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Components;
namespace ThingsGateway.Admin.Blazor.Core;
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><><CDA3> <20>ı<EFBFBD><C4B1><EFBFBD>ʾ
/// 启用/停用 文本提示
/// </summary>
public partial class EnableChip
{
@@ -46,5 +46,5 @@ public partial class EnableChip
private string TextColor => Value ? "green" : "error";
private string Color => Value ? "green-lighten" : "warning-lighten";
private string Label => Value ? EnabledLabel ?? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : DisabledLabel ?? "ͣ<EFBFBD><EFBFBD>";
private string Label => Value ? EnabledLabel ?? "启用" : DisabledLabel ?? "停用";
}

View File

@@ -1,18 +1,18 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Admin.Blazor.Core;
/// <summary>
/// <EFBFBD>ղ<EFBFBD>/<2F><><EFBFBD>ݷ<EFBFBD>ʽ
/// 收藏/快捷方式
/// </summary>
public partial class Favorite
{

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -22,17 +22,17 @@ public partial class Foter
{
private string Version = "";
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 链接
/// </summary>
[Parameter]
public string CONFIG_COPYRIGHT_URL { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD>Ȩ
/// 版权
/// </summary>
[Parameter]
public string CONFIG_COPYRIGHT { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 标题
/// </summary>
[Parameter]
public string CONFIG_TITLE { get; set; }

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -20,23 +20,23 @@ namespace ThingsGateway.Admin.Blazor.Core;
public partial class Logo
{
/// <summary>
/// Logo<EFBFBD>߶<EFBFBD>
/// Logo高度
/// </summary>
[Parameter]
public int HeightInt { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 链接
/// </summary>
[Parameter]
public string CONFIG_COPYRIGHT_URL { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD>Ȩ
/// 版权
/// </summary>
[Parameter]
public string CONFIG_COPYRIGHT { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 标题
/// </summary>
[Parameter]
public string CONFIG_TITLE { get; set; }

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -34,7 +34,7 @@ public partial class PageTabs
return op;
}
/// <summary>
/// Tabsʵ<EFBFBD><EFBFBD>
/// Tabs实例
/// </summary>
public PPageTabs PPageTabs { get; private set; }
@@ -46,7 +46,7 @@ public partial class PageTabs
[Parameter]
public IEnumerable<string> SelfPatterns { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 子组件
/// </summary>
[Parameter]
public RenderFragment ChildContent { get; set; }

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -49,11 +49,11 @@ public partial class UserMenu
var ret = str?.ToJsonWithT<UnifyResult<string>>();
if (ret?.Code != 200)
{
await PopupService.EnqueueSnackbarAsync("ע<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>", AlertTypes.Error);
await PopupService.EnqueueSnackbarAsync("注销失败", AlertTypes.Error);
}
else
{
await PopupService.EnqueueSnackbarAsync("ע<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
await PopupService.EnqueueSnackbarAsync("注销成功", AlertTypes.Success);
await Task.Delay(500);
NavigationManager.NavigateTo(NavigationManager.Uri);
}

View File

@@ -0,0 +1,68 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion.DependencyInjection;
namespace BlazorComponent.I18n;
/// <summary>
/// CookieStorage
/// </summary>
public class CookieStorage : IScoped
{
private readonly IJSRuntime _jsRuntime;
/// <summary>
/// CookieStorage
/// </summary>
/// <param name="jsRuntime"></param>
public CookieStorage(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
/// <summary>
/// GetCookieAsync
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<string> GetCookieAsync(string key)
{
return await _jsRuntime.InvokeAsync<string>(JsInteropConstants.GetCookie, key);
}
/// <summary>
/// GetCookie
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string GetCookie(string key)
{
if (_jsRuntime is IJSInProcessRuntime jsInProcess)
{
return jsInProcess.Invoke<string>(JsInteropConstants.GetCookie, key);
}
return null;
}
/// <summary>
/// SetItemAsync
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
public async void SetItemAsync<T>(string key, T value)
{
try
{
await _jsRuntime.InvokeVoidAsync(JsInteropConstants.SetCookie, key, value?.ToString());
}
catch
{
}
}
}

View File

@@ -10,6 +10,8 @@
//------------------------------------------------------------------------------
#endregion
using BlazorComponent;
using Furion;
using Masa.Blazor;
@@ -61,6 +63,8 @@ public class Startup : AppStartup
});
options.Locale = new Locale("zh-CN", "en-US");
});
services.AddScoped<InitTimezone>();

View File

@@ -14,8 +14,8 @@
<ItemGroup>
<PackageReference Include="Masa.Blazor" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.9" />
<PackageReference Include="Masa.Blazor" Version="1.0.2" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.10" />
</ItemGroup>

View File

@@ -857,5 +857,38 @@
设置深浅主题统一由这个方法为入口
</summary>
</member>
<member name="T:BlazorComponent.I18n.CookieStorage">
<summary>
CookieStorage
</summary>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.#ctor(Microsoft.JSInterop.IJSRuntime)">
<summary>
CookieStorage
</summary>
<param name="jsRuntime"></param>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.GetCookieAsync(System.String)">
<summary>
GetCookieAsync
</summary>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.GetCookie(System.String)">
<summary>
GetCookie
</summary>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:BlazorComponent.I18n.CookieStorage.SetItemAsync``1(System.String,``0)">
<summary>
SetItemAsync
</summary>
<typeparam name="T"></typeparam>
<param name="key"></param>
<param name="value"></param>
</member>
</members>
</doc>

View File

@@ -153,7 +153,7 @@ public class UserResoures : IDisposable
{
if (MasaBlazor.Theme.Dark != isDark || isDark == null)
MasaBlazor.ToggleTheme();
_cookieStorage?.SetItemAsync(BlazorResourceConst.ThemeCookieKey, isDark.ToJsonString());
_cookieStorage?.SetItemAsync(BlazorResourceConst.ThemeCookieKey, MasaBlazor.Theme.Dark.ToJsonString());
}
private void InitCookie(IRequestCookieCollection cookies)

View File

@@ -48,8 +48,7 @@
var controllerTypes = App.EffectiveTypes.
Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
&& u.IsDefined(typeof(Microsoft.AspNetCore.Components.RouteAttribute), false))
.Where(it => it.Assembly != typeof(BlazorApp).Assembly)
;
.Where(it => it.Assembly != typeof(BlazorApp).Assembly);
var assemblys = controllerTypes?.Select(it => it.Assembly)?.Distinct();
return assemblys;
}

View File

@@ -189,38 +189,39 @@
}
else
{
if (context?.Value?.GetType() == typeof(DateTimeOffset))
if (ItemColWithDTTemplate != null)
{
<span>
@(((DateTimeOffset)context.Value).ToOffset(InitTimezone.TimezoneOffset).ToDefaultDateTimeFormat())
</span>
}
else if (context?.Value?.GetType() == typeof(DateTime))
{
<span>
@(((DateTime)context.Value).Add(InitTimezone.TimezoneOffset).ToDefaultDateTimeFormat())
</span>
}
else if (ItemColTemplate != null)
{
@ItemColTemplate(context)
@ItemColWithDTTemplate(context)
}
else
{
@if (context.Header.CellClass?.Contains("text-truncate") == true)
if (context?.Value?.GetType() == typeof(DateTime))
{
<span title=@context.Value>
@context.Value
<span>
@(((DateTime)context.Value).ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset))
</span>
}
else if (ItemColTemplate != null)
{
@ItemColTemplate(context)
}
else
{
@context.Value
}
@if (context.Header.CellClass?.Contains("text-truncate") == true)
{
<span title=@context.Value>
@context.Value
</span>
}
else
{
@context.Value
}
}
}
}
</ItemColContent>
</MDataTable>
@@ -309,16 +310,24 @@
{
string value = DetailModelPairs[item.Value];
{
<tr @key="item.Text">
<td class="text-start table-minwidth">
@item.Text
</td>
<td class="text-start ">
<div style="word-break:break-all; white-space:pre-wrap;">
@value
</div>
</td>
</tr>
@if (Detailemplate != null)
{
@Detailemplate((item,value))
}
else
{
<tr @key="item.Text">
<td class="text-start table-minwidth">
@item.Text
</td>
<td class="text-start ">
<div style="word-break:break-all; white-space:pre-wrap;">
@value
</div>
</td>
</tr>
}
}
}
}

View File

@@ -72,12 +72,6 @@ public partial class AppDataTable<TItem, SearchItem, AddItem, EditItem> : IAppDa
[Parameter]
public bool Dense { get; set; }
/// <summary>
/// 获得/设置 明细行模板
/// </summary>
[Parameter]
public RenderFragment<TItem> DetailRowTemplate { get; set; }
/// <summary>
/// 编辑项委托
/// </summary>
@@ -89,6 +83,11 @@ public partial class AppDataTable<TItem, SearchItem, AddItem, EditItem> : IAppDa
/// </summary>
[Parameter]
public RenderFragment<EditItem> EditTemplate { get; set; }
/// <summary>
/// 获得/设置 详情模板
/// </summary>
[Parameter]
public RenderFragment<(DataTableHeader<TItem>, string)> Detailemplate { get; set; }
/// <summary>
/// 表头过滤返回DataTableHeader列表传输参数已包含全部初始表头与表头标题
@@ -193,6 +192,13 @@ public partial class AppDataTable<TItem, SearchItem, AddItem, EditItem> : IAppDa
[Parameter]
public RenderFragment<ItemColProps<TItem>> ItemColTemplate { get; set; }
/// <summary>
/// 独立设置 Table Cols 模板需自行实现DateTime类型的时区转换
/// </summary>
[Parameter]
public RenderFragment<ItemColProps<TItem>> ItemColWithDTTemplate { get; set; }
/// <summary>
/// 当前显示项目
/// </summary>
@@ -457,13 +463,9 @@ public partial class AppDataTable<TItem, SearchItem, AddItem, EditItem> : IAppDa
if (item != BlazorResourceConst.DataTableActions)
{
var value = typeof(TItem).GetMemberInfoValue(DetailModel, item);
if (value is DateTimeOffset dt)
if (value is DateTime dt2)
{
value = dt.ToOffset(InitTimezone.TimezoneOffset).ToDefaultDateTimeFormat();
}
else if (value is DateTime dt2)
{
value = dt2.Add(InitTimezone.TimezoneOffset).ToDefaultDateTimeFormat();
value = dt2.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset);
}
keyValuePairs.Add(item, value?.ToString());
}

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion

View File

@@ -66,7 +66,7 @@
Small>
<MRow Class="pt-1">
<MCol Cols="4">
<span class="text-caption">@item.OpTime.ToDefaultDateTimeFormat()</span>
<span class="text-caption">@item.OpTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)</span>
</MCol>
<MCol>
<div class="text-body-1">@item.Name</div>
@@ -93,7 +93,7 @@
Small>
<MRow Class="pt-1">
<MCol Cols="4">
<span class="text-caption">@item.OpTime.ToDefaultDateTimeFormat()</span>
<span class="text-caption">@item.OpTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)</span>
</MCol>
<MCol>
<div class="text-body-1">@item.Name</div>

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -18,7 +18,7 @@ using ThingsGateway.Admin.Core;
namespace ThingsGateway.Admin.Blazor;
/// <summary>
/// <EFBFBD><EFBFBD>ҳ
/// 首页
/// </summary>
public partial class Index
{

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -18,7 +18,7 @@ using ThingsGateway.Admin.Core;
namespace ThingsGateway.Admin.Blazor;
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 个人设置
/// </summary>
public partial class UserCenter
{
@@ -50,25 +50,25 @@ public partial class UserCenter
{
await UserCenterService.UpdateUserDefaultRazorAsync(UserManager.UserId, DefaultMenuId);
await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
}
async Task OnShortcutSaveAsync()
{
await UserCenterService.UpdateWorkbenchAsync(_menusChoice);
await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
}
async Task OnUpdatePasswordInfoAsync(FormContext context)
{
var success = context.Validate();
if (success)
{
//<EFBFBD><EFBFBD>֤<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>
//验证成功,操作业务
_passwordInfoInput.Id = UserResoures.CurrentUser.Id;
await UserCenterService.EditPasswordAsync(_passwordInfoInput);
await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>¼", AlertTypes.Success);
await PopupService.EnqueueSnackbarAsync("成功,将重新登录", AlertTypes.Success);
await Task.Delay(2000);
NavigationManager.NavigateTo(NavigationManager.Uri);
}
@@ -78,6 +78,6 @@ public partial class UserCenter
{
await UserCenterService.UpdateUserInfoAsync(_updateInfoInput);
await MainLayout.StateHasChangedAsync();
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
}
}

View File

@@ -133,7 +133,7 @@ public partial class Login
GetCaptchaInfo();
CONFIG_TITLE = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_TITLE))?.ConfigValue;
CONFIG_REMARK = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_REMARK))?.ConfigValue;
_showCaptcha = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_CAPTCHA_OPEN))?.ConfigValue?.ToBool() == true;
_showCaptcha = (await App.GetService<IConfigService>().GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_CAPTCHA_OPEN))?.ConfigValue?.ToBoolean() == true;
Welcome = "欢迎使用" + CONFIG_TITLE + "!";
await base.OnParametersSetAsync();
}

View File

@@ -43,11 +43,6 @@
表格紧凑
</summary>
</member>
<member name="P:ThingsGateway.Admin.Blazor.Core.AppDataTable`4.DetailRowTemplate">
<summary>
获得/设置 明细行模板
</summary>
</member>
<member name="P:ThingsGateway.Admin.Blazor.Core.AppDataTable`4.EditCallAsync">
<summary>
编辑项委托
@@ -58,6 +53,11 @@
获得/设置 编辑模板
</summary>
</member>
<member name="P:ThingsGateway.Admin.Blazor.Core.AppDataTable`4.Detailemplate">
<summary>
获得/设置 详情模板
</summary>
</member>
<member name="P:ThingsGateway.Admin.Blazor.Core.AppDataTable`4.FilterHeaders">
<summary>
表头过滤返回DataTableHeader列表传输参数已包含全部初始表头与表头标题
@@ -148,6 +148,11 @@
获得/设置 Table Cols 模板
</summary>
</member>
<member name="P:ThingsGateway.Admin.Blazor.Core.AppDataTable`4.ItemColWithDTTemplate">
<summary>
独立设置 Table Cols 模板需自行实现DateTime类型的时区转换
</summary>
</member>
<member name="P:ThingsGateway.Admin.Blazor.Core.AppDataTable`4.Items">
<summary>
当前显示项目

View File

@@ -22,7 +22,7 @@ public class UserManager
/// <summary>
/// 是否超级管理员
/// </summary>
public static bool IsSuperAdmin => (App.User?.FindFirst(ClaimConst.IsSuperAdmin)?.Value).ToBool();
public static bool IsSuperAdmin => (App.User?.FindFirst(ClaimConst.IsSuperAdmin)?.Value).ToBoolean();
/// <summary>
/// 当前用户账号

View File

@@ -50,7 +50,7 @@ public abstract class BaseEntity : PrimaryKeyEntity
/// </summary>
[SugarColumn(ColumnDescription = "创建时间", IsOnlyIgnoreUpdate = true, IsNullable = true)]
[IgnoreExcel]
public virtual DateTimeOffset? CreateTime { get; set; }
public virtual DateTime? CreateTime { get; set; }
/// <summary>
/// 创建人
@@ -78,7 +78,7 @@ public abstract class BaseEntity : PrimaryKeyEntity
/// </summary>
[SugarColumn(ColumnDescription = "更新时间", IsOnlyIgnoreInsert = true, IsNullable = true)]
[IgnoreExcel]
public virtual DateTimeOffset? UpdateTime { get; set; }
public virtual DateTime? UpdateTime { get; set; }
/// <summary>
/// 更新人

View File

@@ -54,7 +54,7 @@ public class OpenApiUser : BaseEntity
///</summary>
[SugarColumn(ColumnName = "LastLoginTime", ColumnDescription = "上次登录时间", IsNullable = true)]
[DataTable(Order = 10, IsShow = true, Sortable = true, DefaultFilter = true)]
public DateTimeOffset? LastLoginTime { get; set; }
public DateTime? LastLoginTime { get; set; }
/// <summary>
/// 最新登录设备
@@ -75,7 +75,7 @@ public class OpenApiUser : BaseEntity
///</summary>
[SugarColumn(ColumnName = "LatestLoginTime", ColumnDescription = "最新登录时间", IsNullable = true)]
[DataTable(Order = 7, IsShow = true, Sortable = true)]
public DateTimeOffset? LatestLoginTime { get; set; }
public DateTime? LatestLoginTime { get; set; }
/// <summary>
/// 密码

View File

@@ -60,7 +60,7 @@ public class SysUser : BaseEntity
///</summary>
[SugarColumn(ColumnName = "LastLoginTime", ColumnDescription = "上次登录时间", IsNullable = true)]
[DataTable(Order = 5, IsShow = true, Sortable = true, DefaultFilter = true)]
public DateTimeOffset? LastLoginTime { get; set; }
public DateTime? LastLoginTime { get; set; }
/// <summary>
/// 最新登录设备
@@ -81,7 +81,7 @@ public class SysUser : BaseEntity
///</summary>
[SugarColumn(ColumnName = "LatestLoginTime", ColumnDescription = "最新登录时间", IsNullable = true)]
[DataTable(Order = 8, IsShow = true, Sortable = true, DefaultFilter = false)]
public DateTimeOffset? LatestLoginTime { get; set; }
public DateTime? LatestLoginTime { get; set; }
/// <summary>
/// 密码

View File

@@ -100,5 +100,5 @@ public class VerificatInfo : PrimaryIdEntity
/// </summary>
[Description("超时时间")]
[DataTable(Order = 5, IsShow = true, Sortable = true)]
public DateTimeOffset VerificatTimeout { get; set; }
public DateTime VerificatTimeout { get; set; }
}

View File

@@ -75,7 +75,7 @@ public class SysVisitLog : BaseEntity
///</summary>
[SugarColumn(ColumnName = "OpTime", ColumnDescription = "操作时间")]
[DataTable(Order = 8, IsShow = true, Sortable = true, DefaultFilter = false)]
public DateTimeOffset OpTime { get; set; }
public DateTime OpTime { get; set; }
/// <summary>
/// 验证Id

View File

@@ -330,7 +330,7 @@ public static class ObjectExtensions
/// 转换布尔值
/// </summary>
/// <returns></returns>
public static bool ToBool(this object value, bool defaultValue = false) => value?.ToString().ToUpper() switch
public static bool ToBoolean(this object value, bool defaultValue = false) => value?.ToString().ToUpper() switch
{
"1" or "TRUE" => true,
_ => defaultValue,
@@ -356,10 +356,22 @@ public static class ObjectExtensions
{
return Double.IsNaN(d) ? defaultValue : (Decimal)d;
}
var str = value.ToString();
var str = value?.ToString();
return str.IsNullOrEmpty() ? defaultValue : Decimal.TryParse(str, out var n) ? n : defaultValue;
}
/// <summary>
/// ToDecimal
/// </summary>
/// <returns></returns>
public static double ToDouble(this object value, double defaultValue = 0)
{
if (value is Double d)
{
return Double.IsNaN(d) ? defaultValue : (Double)d;
}
var str = value?.ToString();
return str.IsNullOrEmpty() ? defaultValue : double.TryParse(str, out var n) ? n : defaultValue;
}
/// <summary>
/// JsonElement 转 Object

View File

@@ -97,7 +97,7 @@ public static class StringExtensions
/// 转换布尔值
/// </summary>
/// <returns></returns>
public static bool ToBool(this string value, bool defaultValue = false) => value?.ToUpper() switch
public static bool ToBoolean(this string value, bool defaultValue = false) => value?.ToUpper() switch
{
"1" or "TRUE" => true,
_ => defaultValue,

View File

@@ -21,26 +21,39 @@ namespace ThingsGateway.Admin.Core;
public static class SysDateTimeExtensions
{
private static readonly DateTime _dt1970 = new(1970, 1, 1);
private static readonly DateTimeOffset _dto1970 = new(new DateTime(1970, 1, 1));
/// <summary>
/// 系统默认使用的当前时间
/// </summary>
public static DateTimeOffset CurrentDateTime => DateTimeOffset.Now;
public static DateTime CurrentDateTime => DateTime.Now;
/// <summary>
/// 返回yyyy-MM-dd HH:mm:ss:fff zz时间格式字符串
/// </summary>
public static string ToDefaultDateTimeFormat(this in DateTime dt) => dt.ToString("yyyy-MM-dd HH:mm:ss:fff zz");
public static string ToDefaultDateTimeFormat(this in DateTime dt, TimeSpan offset)
{
if (dt.Kind == DateTimeKind.Utc)
return new DateTimeOffset(dt.ToLocalTime(), offset).ToString("yyyy-MM-dd HH:mm:ss:fff zz");
else if (dt == DateTime.MinValue || dt == DateTime.MaxValue)
return dt.ToString("yyyy-MM-dd HH:mm:ss:fff zz");
else
return new DateTimeOffset(dt, offset).ToString("yyyy-MM-dd HH:mm:ss:fff zz");
}
/// <summary>
/// 返回yyyy-MM-dd HH:mm:ss:fff zz时间格式字符串
/// </summary>
public static string ToDefaultDateTimeFormat(this in DateTimeOffset dt) => dt.ToString("yyyy-MM-dd HH:mm:ss:fff zz");
public static string ToDefaultDateTimeFormat(this in DateTime dt)
{
return dt.ToString("yyyy-MM-dd HH:mm:ss:fff zz");
}
/// <summary>
/// 返回yyyy-MM-dd HH-mm-ss-fff zz时间格式字符串
/// 返回yyyy-MM-dd HH:mm:ss:fff zz时间格式字符串
/// </summary>
public static string ToFileDateTimeFormat(this in DateTimeOffset dt) => dt.ToString("yyyy-MM-dd HH-mm-ss-fff zz");
public static string ToFileDateTimeFormat(this in DateTime dt)
{
return dt.ToString("yyyy-MM-dd HH-mm-ss-fff zz");
}
/// <summary>
@@ -166,15 +179,5 @@ public static class SysDateTimeExtensions
return (Int64)(value - _dt1970).TotalMilliseconds;
}
/// <summary>
/// ToLong
/// </summary>
/// <returns></returns>
public static long ToLong(this DateTimeOffset value, long defaultValue = 0)
{
// 特殊处理时间转Unix毫秒
return value == DateTimeOffset.MinValue ? 0 : (Int64)(value - _dto1970).TotalMilliseconds;
}
}

View File

@@ -12,10 +12,10 @@
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.8.8.40" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.8.8.40" />
<PackageReference Include="Furion.Pure" Version="4.8.8.40" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.94" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.99" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
<PackageReference Include="MiniExcel" Version="1.31.0" />
<PackageReference Include="MiniExcel" Version="1.31.2" />
</ItemGroup>
</Project>

View File

@@ -1026,7 +1026,7 @@
<param name="str"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.Core.ObjectExtensions.ToBool(System.Object,System.Boolean)">
<member name="M:ThingsGateway.Admin.Core.ObjectExtensions.ToBoolean(System.Object,System.Boolean)">
<summary>
转换布尔值
</summary>
@@ -1050,6 +1050,12 @@
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.Core.ObjectExtensions.ToDouble(System.Object,System.Double)">
<summary>
ToDecimal
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.Core.ObjectExtensions.ToObject(System.Text.Json.JsonElement)">
<summary>
JsonElement 转 Object
@@ -1142,7 +1148,7 @@
<param name="input"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.Core.StringExtensions.ToBool(System.String,System.Boolean)">
<member name="M:ThingsGateway.Admin.Core.StringExtensions.ToBoolean(System.String,System.Boolean)">
<summary>
转换布尔值
</summary>
@@ -1196,21 +1202,21 @@
系统默认使用的当前时间
</summary>
</member>
<member name="M:ThingsGateway.Admin.Core.SysDateTimeExtensions.ToDefaultDateTimeFormat(System.DateTime@,System.TimeSpan)">
<summary>
返回yyyy-MM-dd HH:mm:ss:fff zz时间格式字符串
</summary>
</member>
<member name="M:ThingsGateway.Admin.Core.SysDateTimeExtensions.ToDefaultDateTimeFormat(System.DateTime@)">
<summary>
返回yyyy-MM-dd HH:mm:ss:fff zz时间格式字符串
</summary>
</member>
<member name="M:ThingsGateway.Admin.Core.SysDateTimeExtensions.ToDefaultDateTimeFormat(System.DateTimeOffset@)">
<member name="M:ThingsGateway.Admin.Core.SysDateTimeExtensions.ToFileDateTimeFormat(System.DateTime@)">
<summary>
返回yyyy-MM-dd HH:mm:ss:fff zz时间格式字符串
</summary>
</member>
<member name="M:ThingsGateway.Admin.Core.SysDateTimeExtensions.ToFileDateTimeFormat(System.DateTimeOffset@)">
<summary>
返回yyyy-MM-dd HH-mm-ss-fff zz时间格式字符串
</summary>
</member>
<member name="M:ThingsGateway.Admin.Core.SysDateTimeExtensions.GetDiffTime(System.DateTime@,System.DateTime@)">
<summary>
计算2个时间差返回文字描述
@@ -1233,12 +1239,6 @@
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.Core.SysDateTimeExtensions.ToLong(System.DateTimeOffset,System.Int64)">
<summary>
ToLong
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Admin.Core.TextWriterExtensions">
<summary>
TextWriter扩展

View File

@@ -41,5 +41,5 @@ public class UnifyResult<T>
/// <summary>
/// 时间
/// </summary>
public DateTimeOffset Time { get; set; }
public DateTime Time { get; set; }
}

View File

@@ -21,7 +21,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.ApiController;
/// <summary>
/// 后台登录控制器
/// 文件下载
/// </summary>
[ApiDescriptionSettings(CateGoryConst.ThingsGatewayAdmin, Order = 200)]
[Route("gatewayFile")]

View File

@@ -26,7 +26,7 @@
</member>
<member name="T:ThingsGateway.ApiController.FileController">
<summary>
后台登录控制器
文件下载
</summary>
</member>
<member name="M:ThingsGateway.ApiController.FileController.#ctor(ThingsGateway.Application.IRpcLogService,ThingsGateway.Application.IBackendLogService,ThingsGateway.Application.ICollectDeviceService,ThingsGateway.Application.IUploadDeviceService,ThingsGateway.Application.IVariableService)">

View File

@@ -34,13 +34,13 @@ public class TimerTick
/// <summary>
/// 上次操作时间
/// </summary>
public DateTimeOffset LastTime { get; private set; }
public DateTime LastTime { get; private set; }
/// <summary>
/// 是否触发时间刻度
/// </summary>
/// <returns></returns>
public bool IsTickHappen(DateTimeOffset currentTime)
public bool IsTickHappen(DateTime currentTime)
{
var dateTime = LastTime.AddMilliseconds(milliSeconds);
if (currentTime < dateTime)

View File

@@ -28,7 +28,7 @@ public class BackendLog : PrimaryIdEntity
/// </summary>
[SugarColumn(ColumnName = "LogTime", ColumnDescription = "日志时间", IsNullable = false)]
[DataTable(Order = 1, IsShow = true, Sortable = true)]
public DateTimeOffset LogTime { get; set; }
public DateTime LogTime { get; set; }
/// <summary>
/// 日志级别
/// </summary>

View File

@@ -31,7 +31,7 @@ public class DeviceVariable : MemoryVariable
public virtual long DeviceId { get; set; }
/// <summary>
/// 写入表达式
/// 单位
/// </summary>
[SugarColumn(ColumnName = "Unit", ColumnDescription = "单位", Length = 200, IsNullable = true)]
[DataTable(Order = 3, IsShow = true, Sortable = true)]
@@ -59,12 +59,7 @@ public class DeviceVariable : MemoryVariable
[DataTable(Order = 3, IsShow = true, Sortable = true)]
public string VariableAddress { get; set; }
/// <summary>
/// 写入表达式
/// </summary>
[SugarColumn(ColumnName = "WriteExpressions", ColumnDescription = "写入表达式", Length = 200, IsNullable = true)]
[DataTable(Order = 7, IsShow = true, Sortable = true)]
public string WriteExpressions { get; set; }
/// <summary>
/// 是否中间变量

View File

@@ -71,13 +71,13 @@ public class HistoryAlarm : PrimaryIdEntity
/// <inheritdoc cref="DeviceVariableRunTime.AlarmTime"/>
[SugarColumn(ColumnName = "AlarmTime", ColumnDescription = "报警时间", IsNullable = false)]
[DataTable(Order = 8, IsShow = true, Sortable = true, CellClass = " table-text-truncate ")]
public DateTimeOffset AlarmTime { get; set; }
public DateTime AlarmTime { get; set; }
/// <inheritdoc cref="DeviceVariableRunTime.EventTime"/>
[SugarColumn(ColumnName = "EventTime", ColumnDescription = "事件时间", IsNullable = false)]
[DataTable(Order = 8, IsShow = true, Sortable = true, CellClass = " table-text-truncate ")]
public DateTimeOffset EventTime { get; set; }
public DateTime EventTime { get; set; }
/// <summary>

View File

@@ -51,7 +51,12 @@ public class MemoryVariable : BaseEntity
[SugarColumn(ColumnName = "ReadExpressions", ColumnDescription = "读取表达式", Length = 200, IsNullable = true)]
[DataTable(Order = 7, IsShow = true, Sortable = true, CellClass = " table-text-truncate ")]
public string ReadExpressions { get; set; }
/// <summary>
/// 写入表达式
/// </summary>
[SugarColumn(ColumnName = "WriteExpressions", ColumnDescription = "写入表达式", Length = 200, IsNullable = true)]
[DataTable(Order = 7, IsShow = true, Sortable = true)]
public string WriteExpressions { get; set; }
/// <summary>
/// 是否中间变量
/// </summary>

View File

@@ -24,7 +24,7 @@ public class RpcLog : PrimaryIdEntity
/// </summary>
[SugarColumn(ColumnName = "LogTime", ColumnDescription = "日志时间", IsNullable = false)]
[DataTable(Order = 1, IsShow = true, Sortable = true, CellClass = " table-text-truncate ")]
public DateTimeOffset LogTime { get; set; }
public DateTime LogTime { get; set; }
/// <summary>
/// 操作源

View File

@@ -44,7 +44,7 @@ public class BackendLogDatabaseLoggingWriter : IDatabaseLoggingWriter
LogLevel = logMsg.LogLevel,
LogMessage = logMsg.State.ToString(),
LogSource = logMsg.LogName,
LogTime = logMsg.LogDateTime.ToUniversalTime(),
LogTime = logMsg.LogDateTime,
Exception = logMsg.Exception?.ToString(),
};
_logQueues.Enqueue(logRuntime);

View File

@@ -55,7 +55,7 @@ public class CollectDeviceRunTime : CollectDevice
/// 设备活跃时间
/// </summary>
[Description("活跃时间")]
public DateTimeOffset ActiveTime { get; private set; } = DateTimeOffset.MinValue;
public DateTime ActiveTime { get; private set; } = DateTime.MinValue;
/// <summary>
/// 设备状态
/// </summary>
@@ -121,7 +121,7 @@ public class CollectDeviceRunTime : CollectDevice
/// <param name="activeTime"></param>
/// <param name="errorCount"></param>
/// <param name="lastErrorMessage"></param>
public void SetDeviceStatus(DateTimeOffset? activeTime = null, int? errorCount = null, string lastErrorMessage = null)
public void SetDeviceStatus(DateTime? activeTime = null, int? errorCount = null, string lastErrorMessage = null)
{
if (activeTime != null)
ActiveTime = activeTime.Value;

View File

@@ -23,7 +23,7 @@ public class DeviceData
/// <inheritdoc cref="CollectDeviceRunTime.DeviceVariableCount"/>
public int DeviceVariablesCount { get; set; }
/// <inheritdoc cref="CollectDeviceRunTime.ActiveTime"/>
public DateTimeOffset ActiveTime { get; set; }
public DateTime ActiveTime { get; set; }
/// <inheritdoc cref="CollectDeviceRunTime.DeviceStatus"/>
public int DeviceStatus { get; set; }
/// <inheritdoc cref="CollectDeviceRunTime.LastErrorMessage"/>

View File

@@ -64,7 +64,7 @@ public class DeviceVariableMethodSource
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public bool CheckIfRequestAndUpdateTime(DateTimeOffset time) => exTimerTick.IsTickHappen(time);
public bool CheckIfRequestAndUpdateTime(DateTime time) => exTimerTick.IsTickHappen(time);
}

View File

@@ -82,7 +82,7 @@ public class DeviceVariableRunTime : DeviceVariable
/// </summary>
/// <param name="value"></param>
/// <param name="dateTime"></param>
public OperResult SetValue(object value, DateTimeOffset dateTime = default)
public OperResult SetValue(object value, DateTime dateTime = default)
{
try
{
@@ -129,7 +129,7 @@ public class DeviceVariableRunTime : DeviceVariable
void Set(object data)
{
DateTimeOffset time;
DateTime time;
if (dateTime == default)
{
time = SysDateTimeExtensions.CurrentDateTime;
@@ -139,22 +139,8 @@ public class DeviceVariableRunTime : DeviceVariable
time = dateTime;
}
CollectTime = time;
if (data?.GetType().IsValueType == true)
{
if (data != _value && LastSetValue != data || isOnlineChanged)
{
ChangeTime = time;
if (IsOnline)
{
_value = data;
}
LastSetValue = data;
VariableValueChange?.Invoke(this);
}
}
else
{
if (data?.ToString() != _value?.ToString() && LastSetValue?.ToString() != data?.ToString() || isOnlineChanged)
if ((data?.ToString() != _value?.ToString() && LastSetValue?.ToString() != data?.ToString()) || isOnlineChanged)
{
ChangeTime = time;
if (IsOnline)
@@ -175,13 +161,13 @@ public class DeviceVariableRunTime : DeviceVariable
/// </summary>
[Description("变化时间")]
[DataTable(Order = 2, IsShow = true, Sortable = true)]
public DateTimeOffset ChangeTime { get; private set; }
public DateTime ChangeTime { get; private set; }
/// <summary>
/// 采集时间
/// </summary>
[Description("采集时间")]
[DataTable(Order = 2, IsShow = true, Sortable = true)]
public DateTimeOffset CollectTime { get; private set; }
public DateTime CollectTime { get; private set; }
/// <summary>
@@ -255,11 +241,11 @@ public class DeviceVariableRunTime : DeviceVariable
/// <summary>
/// 报警时间
/// </summary>
public DateTimeOffset AlarmTime { get; set; }
public DateTime AlarmTime { get; set; }
/// <summary>
/// 事件时间
/// </summary>
public DateTimeOffset EventTime { get; set; }
public DateTime EventTime { get; set; }
/// <summary>
/// 报警类型
/// </summary>

View File

@@ -55,6 +55,6 @@ public class DeviceVariableSourceRead
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public bool CheckIfRequestAndUpdateTime(DateTimeOffset time) => exTimerTick.IsTickHappen(time);
public bool CheckIfRequestAndUpdateTime(DateTime time) => exTimerTick.IsTickHappen(time);
}

View File

@@ -35,7 +35,7 @@ public class UploadDeviceRunTime : UploadDevice
/// 设备活跃时间
/// </summary>
[Description("活跃时间")]
public DateTimeOffset ActiveTime { get; private set; } = DateTimeOffset.MinValue;
public DateTime ActiveTime { get; private set; } = DateTime.MinValue;
/// <summary>
/// 设备状态
/// </summary>
@@ -113,7 +113,7 @@ public class UploadDeviceRunTime : UploadDevice
/// <param name="activeTime"></param>
/// <param name="errorCount"></param>
/// <param name="lastErrorMessage"></param>
public void SetDeviceStatus(DateTimeOffset? activeTime = null, int? errorCount = null, string lastErrorMessage = null)
public void SetDeviceStatus(DateTime? activeTime = null, int? errorCount = null, string lastErrorMessage = null)
{
if (activeTime != null)
ActiveTime = activeTime.Value;

View File

@@ -20,6 +20,8 @@ public class VariableData
public long Id { get; set; }
/// <inheritdoc cref="MemoryVariable.Name"/>
public string Name { get; set; }
/// <inheritdoc cref="DeviceVariable.Unit"/>
public string Unit { get; set; }
/// <inheritdoc cref="MemoryVariable.Description"/>
public string Description { get; set; }
/// <inheritdoc cref="DeviceVariableRunTime.DeviceName"/>
@@ -29,14 +31,14 @@ public class VariableData
/// <inheritdoc cref="DeviceVariableRunTime.Value"/>
public object Value { get; set; }
/// <inheritdoc cref="DeviceVariableRunTime.ChangeTime"/>
public DateTimeOffset ChangeTime { get; set; }
public DateTime ChangeTime { get; set; }
/// <inheritdoc cref="DeviceVariableRunTime.CollectTime"/>
public DateTimeOffset CollectTime { get; set; }
public DateTime CollectTime { get; set; }
/// <inheritdoc cref="DeviceVariableRunTime.IsOnline"/>
public bool IsOnline { get; set; }
/// <inheritdoc cref="MemoryVariable.ReadExpressions"/>
public string ReadExpressions { get; set; }
/// <inheritdoc cref="DeviceVariable.WriteExpressions"/>
/// <inheritdoc cref="MemoryVariable.WriteExpressions"/>
public string WriteExpressions { get; set; }
/// <inheritdoc cref="DeviceVariable.IntervalTime"/>
public int IntervalTime { get; set; }

View File

@@ -17,8 +17,6 @@ using Newtonsoft.Json.Linq;
using ThingsGateway.Foundation;
using ThingsGateway.Foundation.Serial;
using TouchSocket.Core;
namespace ThingsGateway.Application;
/// <summary>
/// <para></para>

View File

@@ -48,7 +48,7 @@ public abstract class DriverBase : DisposableObject
base.Dispose(disposing);
}
/// <summary>
/// 调试UI Type继承实现<see cref="DriverDebugUIBase"/>后返回继承类的Type如果不存在返回null
/// 调试UI Type如果不存在返回null
/// </summary>
public abstract Type DriverDebugUIType { get; }

View File

@@ -55,7 +55,7 @@ public interface IVariableService : ITransient
/// <summary>
/// 导出
/// </summary>
Task<MemoryStream> ExportFileAsync(List<DeviceVariable> collectDeviceVariables = null);
Task<MemoryStream> ExportFileAsync(List<DeviceVariable> collectDeviceVariables = null, string deviceName = null);
/// <summary>
/// 导出
/// </summary>

View File

@@ -318,7 +318,7 @@ public class VariableService : DbRepository<DeviceVariable>, IVariableService
/// <inheritdoc/>
[OperDesc("导出采集变量表", IsRecordPar = false)]
public async Task<MemoryStream> ExportFileAsync(List<DeviceVariable> deviceVariables = null)
public async Task<MemoryStream> ExportFileAsync(List<DeviceVariable> deviceVariables = null, string deviceName = null)
{
deviceVariables ??= await GetListAsync(a => !a.IsMemoryVariable);
@@ -343,7 +343,8 @@ public class VariableService : DbRepository<DeviceVariable>, IVariableService
);
Dictionary<string, object> variableExport = new();
//变量实体没有包含设备名称,手动插入
variableExport.Add(ExportHelpers.DeviceName, collectDeviceDicts[devData.DeviceId].Name);
var devName = collectDeviceDicts.GetValueOrDefault(devData.DeviceId)?.Name ?? deviceName;
variableExport.Add(ExportHelpers.DeviceName, devName);
foreach (var item in data)
{
@@ -445,7 +446,7 @@ public class VariableService : DbRepository<DeviceVariable>, IVariableService
try
{
var variable = ((ExpandoObject)item).ConvertToEntity<DeviceVariable>(true);
variable.IsMemoryVariable = true;
//变量ID都需要手动补录
variables.Add(variable);
if (dbVariableDicts.TryGetValue(variable.Name, out var dbvar1))

View File

@@ -44,9 +44,5 @@
<ProjectReference Include="..\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" />
<ProjectReference Include="..\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Workers\Helper\" />
</ItemGroup>
</Project>

View File

@@ -184,7 +184,7 @@
上次操作时间
</summary>
</member>
<member name="M:ThingsGateway.Application.TimerTick.IsTickHappen(System.DateTimeOffset)">
<member name="M:ThingsGateway.Application.TimerTick.IsTickHappen(System.DateTime)">
<summary>
是否触发时间刻度
</summary>
@@ -360,7 +360,7 @@
</member>
<member name="P:ThingsGateway.Application.DeviceVariable.Unit">
<summary>
写入表达式
单位
</summary>
</member>
<member name="P:ThingsGateway.Application.DeviceVariable.IntervalTime">
@@ -378,11 +378,6 @@
变量地址,可能带有额外的信息,比如<see cref="T:ThingsGateway.Foundation.DataFormat"/> ,以;分割
</summary>
</member>
<member name="P:ThingsGateway.Application.DeviceVariable.WriteExpressions">
<summary>
写入表达式
</summary>
</member>
<member name="P:ThingsGateway.Application.DeviceVariable.IsMemoryVariable">
<summary>
是否中间变量
@@ -524,6 +519,11 @@
读取表达式
</summary>
</member>
<member name="P:ThingsGateway.Application.MemoryVariable.WriteExpressions">
<summary>
写入表达式
</summary>
</member>
<member name="P:ThingsGateway.Application.MemoryVariable.IsMemoryVariable">
<summary>
是否中间变量
@@ -1457,7 +1457,7 @@
距上次成功时的读取失败次数,超过3次设备更新为离线等于0时设备更新为在线
</summary>
</member>
<member name="M:ThingsGateway.Application.CollectDeviceRunTime.SetDeviceStatus(System.Nullable{System.DateTimeOffset},System.Nullable{System.Int32},System.String)">
<member name="M:ThingsGateway.Application.CollectDeviceRunTime.SetDeviceStatus(System.Nullable{System.DateTime},System.Nullable{System.Int32},System.String)">
<summary>
传入设备的状态信息
</summary>
@@ -1559,7 +1559,7 @@
地址参数,以;分割参数值
</summary>
</member>
<member name="M:ThingsGateway.Application.DeviceVariableMethodSource.CheckIfRequestAndUpdateTime(System.DateTimeOffset)">
<member name="M:ThingsGateway.Application.DeviceVariableMethodSource.CheckIfRequestAndUpdateTime(System.DateTime)">
<summary>
检测是否达到读取间隔
</summary>
@@ -1601,7 +1601,7 @@
最近一次值
</summary>
</member>
<member name="M:ThingsGateway.Application.DeviceVariableRunTime.SetValue(System.Object,System.DateTimeOffset)">
<member name="M:ThingsGateway.Application.DeviceVariableRunTime.SetValue(System.Object,System.DateTime)">
<summary>
设置变量值与时间设置为null时只更改质量戳状态
</summary>
@@ -1725,7 +1725,7 @@
读取长度
</summary>
</member>
<member name="M:ThingsGateway.Application.DeviceVariableSourceRead.CheckIfRequestAndUpdateTime(System.DateTimeOffset)">
<member name="M:ThingsGateway.Application.DeviceVariableSourceRead.CheckIfRequestAndUpdateTime(System.DateTime)">
<summary>
检测是否达到读取间隔
</summary>
@@ -1772,7 +1772,7 @@
距上次成功时的读取失败次数,超过3次设备更新为离线等于0时设备更新为在线
</summary>
</member>
<member name="M:ThingsGateway.Application.UploadDeviceRunTime.SetDeviceStatus(System.Nullable{System.DateTimeOffset},System.Nullable{System.Int32},System.String)">
<member name="M:ThingsGateway.Application.UploadDeviceRunTime.SetDeviceStatus(System.Nullable{System.DateTime},System.Nullable{System.Int32},System.String)">
<summary>
传入设备的状态信息
</summary>
@@ -1791,6 +1791,9 @@
<member name="P:ThingsGateway.Application.VariableData.Name">
<inheritdoc cref="P:ThingsGateway.Application.MemoryVariable.Name"/>
</member>
<member name="P:ThingsGateway.Application.VariableData.Unit">
<inheritdoc cref="P:ThingsGateway.Application.DeviceVariable.Unit"/>
</member>
<member name="P:ThingsGateway.Application.VariableData.Description">
<inheritdoc cref="P:ThingsGateway.Application.MemoryVariable.Description"/>
</member>
@@ -1816,7 +1819,7 @@
<inheritdoc cref="P:ThingsGateway.Application.MemoryVariable.ReadExpressions"/>
</member>
<member name="P:ThingsGateway.Application.VariableData.WriteExpressions">
<inheritdoc cref="P:ThingsGateway.Application.DeviceVariable.WriteExpressions"/>
<inheritdoc cref="P:ThingsGateway.Application.MemoryVariable.WriteExpressions"/>
</member>
<member name="P:ThingsGateway.Application.VariableData.IntervalTime">
<inheritdoc cref="P:ThingsGateway.Application.DeviceVariable.IntervalTime"/>
@@ -1951,7 +1954,7 @@
</member>
<member name="P:ThingsGateway.Application.DriverBase.DriverDebugUIType">
<summary>
调试UI Type继承实现<see cref="T:ThingsGateway.Application.DriverDebugUIBase"/>返回继承类的Type如果不存在返回null
调试UI Type如果不存在返回null
</summary>
</member>
<member name="P:ThingsGateway.Application.DriverBase.DriverPlugin">
@@ -1995,78 +1998,6 @@
底层日志输出
</summary>
</member>
<member name="T:ThingsGateway.Application.DriverDebugUIBase">
<summary>
调试UI
</summary>
</member>
<member name="F:ThingsGateway.Application.DriverDebugUIBase.isDownExport">
<summary>
导出提示
</summary>
</member>
<member name="F:ThingsGateway.Application.DriverDebugUIBase.Messages">
<summary>
日志缓存
</summary>
</member>
<member name="P:ThingsGateway.Application.DriverDebugUIBase.Plc">
<summary>
默认读写设备
</summary>
</member>
<member name="P:ThingsGateway.Application.DriverDebugUIBase.Address">
<summary>
变量地址
</summary>
</member>
<member name="P:ThingsGateway.Application.DriverDebugUIBase.DataTypeEnum">
<summary>
数据类型
</summary>
</member>
<member name="P:ThingsGateway.Application.DriverDebugUIBase.JS">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Application.DriverDebugUIBase.WriteValue">
<summary>
写入值
</summary>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.Dispose">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.ReadAsync">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.WriteAsync">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DownDeviceExportAsync(ThingsGateway.Application.CollectDevice)">
<summary>
导入设备
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DownDeviceExportAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable})">
<summary>
导入变量
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.DownDeviceMessageExportAsync(System.Collections.Generic.IEnumerable{System.String})">
<summary>
导出
</summary>
<param name="values"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.LogOut(TouchSocket.Core.LogLevel,System.Object,System.String,System.Exception)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Application.DriverDebugUIBase.OnInitialized">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Application.PluginSingletonService">
<summary>
驱动插件服务
@@ -3244,7 +3175,7 @@
编辑变量
</summary>
</member>
<member name="M:ThingsGateway.Application.IVariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable})">
<member name="M:ThingsGateway.Application.IVariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable},System.String)">
<summary>
导出
</summary>
@@ -3339,7 +3270,7 @@
<member name="M:ThingsGateway.Application.VariableService.MemoryVariableExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.MemoryVariable})">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Application.VariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable})">
<member name="M:ThingsGateway.Application.VariableService.ExportFileAsync(System.Collections.Generic.List{ThingsGateway.Application.DeviceVariable},System.String)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Application.VariableService.MemoryVariablePreviewAsync(Microsoft.AspNetCore.Components.Forms.IBrowserFile)">
@@ -3633,6 +3564,11 @@
开始采集
</summary>
</member>
<member name="M:ThingsGateway.Application.CollectDeviceThread.BeforeStopThreadAsync">
<summary>
停止采集前提前取消Token
</summary>
</member>
<member name="M:ThingsGateway.Application.CollectDeviceThread.StopThreadAsync">
<summary>
停止采集
@@ -4006,6 +3942,11 @@
开始上传
</summary>
</member>
<member name="M:ThingsGateway.Application.UploadDeviceThread.BeforeStopThreadAsync">
<summary>
停止采集前提前取消Token
</summary>
</member>
<member name="M:ThingsGateway.Application.UploadDeviceThread.StopThreadAsync">
<summary>
停止上传

View File

@@ -66,7 +66,7 @@ public class AlarmWorker : BackgroundService
/// </summary>
public OperResult StatuString { get; set; } = new OperResult("初始化");
private ConcurrentQueue<DeviceVariableRunTime> DeviceVariables { get; set; } = new();
private ConcurrentQueue<DeviceVariableRunTime> HisAlarmDeviceVariables { get; set; } = new();
private ConcurrentQueue<HistoryAlarm> HisAlarmDeviceVariables { get; set; } = new();
/// <summary>
/// 获取数据库链接
/// </summary>
@@ -74,7 +74,7 @@ public class AlarmWorker : BackgroundService
public async Task<OperResult<SqlSugarClient>> GetAlarmDbAsync()
{
var ConfigService = ServiceHelper.Services.GetService<IConfigService>();
var alarmEnable = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_AlarmConfig_Base, ThingsGatewayConfigConst.Config_Alarm_Enable))?.ConfigValue?.ToBool();
var alarmEnable = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_AlarmConfig_Base, ThingsGatewayConfigConst.Config_Alarm_Enable))?.ConfigValue?.ToBoolean();
var alarmDbType = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_AlarmConfig_Base, ThingsGatewayConfigConst.Config_Alarm_DbType))?.ConfigValue;
var alarmConnstr = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_AlarmConfig_Base, ThingsGatewayConfigConst.Config_Alarm_ConnStr))?.ConfigValue;
@@ -132,14 +132,14 @@ public class AlarmWorker : BackgroundService
limit = string.Empty;
expressions = string.Empty;
text = string.Empty;
if (tag.BoolCloseAlarmEnable && tag.Value.ToBool() == false)
if (tag.BoolCloseAlarmEnable && tag.Value.ToBoolean() == false)
{
limit = false.ToString();
expressions = tag.BoolCloseRestrainExpressions;
text = tag.BoolCloseAlarmText;
return AlarmEnum.Close;
}
if (tag.BoolOpenAlarmEnable && tag.Value.ToBool() == true)
if (tag.BoolOpenAlarmEnable && tag.Value.ToBoolean() == true)
{
limit = true.ToString();
expressions = tag.BoolOpenRestrainExpressions;
@@ -465,7 +465,7 @@ public class AlarmWorker : BackgroundService
OnAlarmChanged?.Invoke(item.Adapt<DeviceVariableRunTime>());
if (!IsExited)
{
HisAlarmDeviceVariables.Enqueue(item);
HisAlarmDeviceVariables.Enqueue(item.Adapt<HistoryAlarm>());
}
if (eventEnum == EventEnum.Alarm)
@@ -536,6 +536,7 @@ public class AlarmWorker : BackgroundService
HisAlarmTask = await Task.Factory.StartNew(async () =>
{
_logger?.LogInformation($"历史报警线程开始");
await Task.Yield();//返回线程控制,不再阻塞
try
{
await Task.Delay(500, stoppingToken.Token);
@@ -561,8 +562,14 @@ public class AlarmWorker : BackgroundService
}
catch (Exception)
{
if (stoppingToken.Token.IsCancellationRequested)
{
IsExited = true;
return;
}
try
{
_logger.LogWarning("连接历史报警表失败,尝试初始化表");
sqlSugarClient.CodeFirst.InitTables(typeof(HistoryAlarm));
isSuccess = true;
StatuString = OperResult.CreateSuccessResult();
@@ -586,18 +593,20 @@ public class AlarmWorker : BackgroundService
//缓存值
var cacheData = await CacheDb.GetCacheData();
var data = cacheData.SelectMany(a => a.CacheStr.FromJson<List<HistoryAlarm>>()).ToList();
try
if (cacheData.Count > 0)
{
var count = await sqlSugarClient.Insertable(data).ExecuteCommandAsync(stoppingToken.Token);
await CacheDb.DeleteCacheData(cacheData.Select(a => a.Id).ToArray());
var data = cacheData.SelectMany(a => a.CacheStr.FromJson<List<HistoryAlarm>>()).ToList();
try
{
var count = await sqlSugarClient.Insertable(data).ExecuteCommandAsync(stoppingToken.Token);
await CacheDb.DeleteCacheData(cacheData.Select(a => a.Id).ToArray());
}
catch (Exception ex)
{
if (isSuccess)
_logger.LogWarning(ex, "写入历史报警失败");
}
}
catch (Exception ex)
{
if (isSuccess)
_logger.LogWarning(ex, "写入历史报警失败");
}
if (stoppingToken.Token.IsCancellationRequested)
break;
@@ -605,16 +614,15 @@ public class AlarmWorker : BackgroundService
var list = HisAlarmDeviceVariables.ToListWithDequeue();
if (list.Count != 0)
{
var hisalarm = list.Adapt<List<HistoryAlarm>>();
////Sql保存
hisalarm.ForEach(it =>
list.ForEach(it =>
{
it.Id = YitIdHelper.NextId();
});
//插入
try
{
await sqlSugarClient.Insertable(hisalarm).ExecuteCommandAsync(stoppingToken.Token);
await sqlSugarClient.Insertable(list).ExecuteCommandAsync(stoppingToken.Token);
isSuccess = true;
}
catch (Exception ex)
@@ -622,7 +630,7 @@ public class AlarmWorker : BackgroundService
if (isSuccess)
_logger.LogWarning(ex, "写入历史报警失败");
var cacheDatas = hisalarm.ChunkTrivialBetter(500);
var cacheDatas = list.ChunkTrivialBetter(500);
foreach (var a in cacheDatas)
{
await CacheDb.AddCacheData("", a.ToJson(), 50000);

View File

@@ -269,6 +269,7 @@ public class CollectDeviceCore
{
isInitSuccess = false;
GlobalDeviceData.CollectDevices.RemoveWhere(it => it.Id == Device.Id);
easyLock.SafeDispose();
}
}
@@ -329,11 +330,6 @@ public class CollectDeviceCore
return ThreadRunReturn.Continue;
}
if (DeviceVariableSourceReads.Count == 0 && Device.DeviceVariableRunTimes.Where(a => string.IsNullOrEmpty(a.OtherMethod)).Any())
{
//无采集变量
return ThreadRunReturn.Continue;
}
if (token.IsCancellationRequested)
return ThreadRunReturn.Break;
@@ -533,7 +529,7 @@ public class CollectDeviceCore
if (!string.IsNullOrEmpty(methodResult.MethodStr))
{
string[] strs = methodResult.MethodStr?.Trim()?.Split(';');
string[] strs = methodResult.MethodStr?.Trim()?.TrimEnd(';').Split(';');
try
{
int index = 0;
@@ -545,6 +541,8 @@ public class CollectDeviceCore
}
else
{
if (strs.Length <= index)
continue;
//得到对于的方法参数值
methodResult.MethodObj[i] = methodResult.Converter.ConvertFrom(strs[index], ps[i].ParameterType);
index++;
@@ -600,8 +598,8 @@ public class CollectDeviceCore
if (!string.IsNullOrEmpty(deviceVariableMethodSource.MethodStr) || !string.IsNullOrEmpty(value))
{
string[] strs1 = deviceVariableMethodSource.MethodStr?.Trim()?.Split(';');
string[] strs2 = value?.Trim()?.Split(';');
string[] strs1 = deviceVariableMethodSource.MethodStr?.Trim()?.TrimEnd(';').Split(';');
string[] strs2 = value?.Trim()?.TrimEnd(';').Split(';');
//通过分号分割,并且合并参数
var strs = strs1?.SpliceArray(strs2);
int index = 0;
@@ -667,18 +665,25 @@ public class CollectDeviceCore
if (method.HasReturn && result != null && result.IsSuccess)
{
var content = deviceVariableMethodSource.Converter.ConvertTo(result.Content?.ToString()?.Replace($"\0", ""));
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(content);
if (!operResult.IsSuccess)
if (isRead)
{
_logger?.LogWarning(operResult.Message, ToString());
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(content);
if (!operResult.IsSuccess)
{
_logger?.LogWarning(operResult.Message, ToString());
}
}
}
else
{
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(null);
if (!operResult.IsSuccess)
if (isRead)
{
_logger?.LogWarning(operResult.Message, ToString());
var operResult = deviceVariableMethodSource.DeviceVariable.SetValue(null);
if (!operResult.IsSuccess)
{
_logger?.LogWarning(operResult.Message, ToString());
}
}
}
return result;

View File

@@ -62,6 +62,7 @@ public class CollectDeviceThread : IAsyncDisposable
public async ValueTask DisposeAsync()
{
await StopThreadAsync();
easyLock.SafeDispose();
CollectDeviceCores.Clear();
}
@@ -85,6 +86,29 @@ public class CollectDeviceThread : IAsyncDisposable
easyLock.Release();
}
}
/// <summary>
/// 停止采集前提前取消Token
/// </summary>
public virtual async Task BeforeStopThreadAsync()
{
try
{
await easyLock.WaitAsync();
if (DeviceTask == null)
{
return;
}
foreach (var token in StoppingTokens)
{
token.Cancel();
}
}
finally
{
easyLock.Release();
}
}
/// <summary>
/// 停止采集
@@ -173,7 +197,10 @@ public class CollectDeviceThread : IAsyncDisposable
foreach (var device in CollectDeviceCores)
{
try
{//初始化成功才能执行
{
if (stoppingToken.IsCancellationRequested)
break;
//初始化成功才能执行
if (device.IsInitSuccess)
{
//如果是共享通道类型,需要每次转换时切换适配器

View File

@@ -328,6 +328,18 @@ public class CollectDeviceWorker : BackgroundService
/// </summary>
private async Task RemoveAllDeviceThreadAsync()
{
await CollectDeviceThreads.ParallelForEachAsync(async (deviceThread, token) =>
{
try
{
await deviceThread.BeforeStopThreadAsync();
}
catch (Exception ex)
{
_logger?.LogError(ex, deviceThread.ToString());
}
}, 10);
await CollectDeviceThreads.ParallelForEachAsync(async (deviceThread, token) =>
{
try
@@ -496,7 +508,7 @@ public class CollectDeviceWorker : BackgroundService
{
//超过30分钟或者(初始化失败并超过10分钟)会重启
if (
(devcore.Device.ActiveTime != DateTimeOffset.MinValue &&
(devcore.Device.ActiveTime != DateTime.MinValue &&
devcore.Device.ActiveTime.AddMinutes(30) <= SysDateTimeExtensions.CurrentDateTime)
|| (devcore.IsInitSuccess == false && devcore.Device.ActiveTime.AddMinutes(10) <= SysDateTimeExtensions.CurrentDateTime)
)

View File

@@ -60,7 +60,7 @@ public class HistoryValueWorker : BackgroundService
public async Task<OperResult<SqlSugarClient>> GetHisDbAsync()
{
var ConfigService = ServiceHelper.Services.GetService<IConfigService>();
var hisEnable = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_HisConfig_Base, ThingsGatewayConfigConst.Config_His_Enable))?.ConfigValue?.ToBool();
var hisEnable = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_HisConfig_Base, ThingsGatewayConfigConst.Config_His_Enable))?.ConfigValue?.ToBoolean();
var hisDbType = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_HisConfig_Base, ThingsGatewayConfigConst.Config_His_DbType))?.ConfigValue;
var hisConnstr = (await ConfigService.GetByConfigKeyAsync(ThingsGatewayConfigConst.ThingGateway_HisConfig_Base, ThingsGatewayConfigConst.Config_His_ConnStr))?.ConfigValue;
@@ -167,7 +167,7 @@ public class HistoryValueWorker : BackgroundService
HistoryValueTask = await Task.Factory.StartNew(async () =>
{
_logger?.LogInformation($"历史数据线程开始");
IsExited = false;
await Task.Yield();//返回线程控制,不再阻塞
try
{
var result = await GetHisDbAsync();
@@ -191,8 +191,14 @@ public class HistoryValueWorker : BackgroundService
}
catch (Exception)
{
if (stoppingToken.Token.IsCancellationRequested)
{
IsExited = true;
return;
}
try
{
_logger.LogWarning("连接历史数据表失败,尝试初始化表");
sqlSugarClient.CodeFirst.InitTables(typeof(HistoryValue));
LastIsSuccess = true;
StatuString = OperResult.CreateSuccessResult();
@@ -204,6 +210,7 @@ public class HistoryValueWorker : BackgroundService
_logger.LogWarning(ex, "连接历史数据库失败");
}
}
IsExited = false;
while (!stoppingToken.Token.IsCancellationRequested)
{
@@ -299,7 +306,6 @@ public class HistoryValueWorker : BackgroundService
LastIsSuccess = false;
}
}
IsExited = true;
}
}
@@ -317,9 +323,11 @@ public class HistoryValueWorker : BackgroundService
IsExited = true;
_logger?.LogError(ex, $"历史数据循环异常");
}
IsExited = true;
}
, TaskCreationOptions.LongRunning);
}
/// <summary>
/// 重启
/// </summary>
@@ -451,14 +459,14 @@ public class HistoryValueMapper : IRegister
{
config.ForType<DeviceVariableRunTime, HistoryValue>()
.Map(dest => dest.Value, (src) => ValueReturn(src))
.Map(dest => dest.CollectTime, (src) => src.CollectTime.UtcDateTime);
.Map(dest => dest.CollectTime, (src) => src.CollectTime.ToUniversalTime());//注意sqlsugar插入时无时区直接utc时间
}
private static object ValueReturn(DeviceVariableRunTime src)
{
if (src.Value?.ToString()?.IsBoolValue() == true)
{
if (src.Value.ToBool())
if (src.Value.ToBoolean())
{
return 1;
}

View File

@@ -225,7 +225,13 @@ public class UploadDeviceCore
{
_logger?.LogError(ex, $"{Device.Name} 释放失败");
}
isInitSuccess = false;
finally
{
isInitSuccess = false;
easyLock.SafeDispose();
}
}
/// <summary>

View File

@@ -51,6 +51,7 @@ public class UploadDeviceThread : IAsyncDisposable
public async ValueTask DisposeAsync()
{
await StopThreadAsync();
easyLock.SafeDispose();
UploadDeviceCores.Clear();
}
@@ -74,6 +75,29 @@ public class UploadDeviceThread : IAsyncDisposable
easyLock.Release();
}
}
/// <summary>
/// 停止采集前提前取消Token
/// </summary>
public virtual async Task BeforeStopThreadAsync()
{
try
{
await easyLock.WaitAsync();
if (DeviceTask == null)
{
return;
}
foreach (var token in StoppingTokens)
{
token.Cancel();
}
}
finally
{
easyLock.Release();
}
}
/// <summary>
/// 停止上传
@@ -152,7 +176,10 @@ public class UploadDeviceThread : IAsyncDisposable
foreach (var device in UploadDeviceCores)
{
try
{//初始化成功才能执行
{
if (stoppingToken.IsCancellationRequested)
break;
//初始化成功才能执行
if (device.IsInitSuccess)
{

View File

@@ -239,6 +239,17 @@ public class UploadDeviceWorker : BackgroundService
/// </summary>
private async Task RemoveAllDeviceThreadAsync()
{
await UploadDeviceThreads.ParallelForEachAsync(async (deviceThread, token) =>
{
try
{
await deviceThread.BeforeStopThreadAsync();
}
catch (Exception ex)
{
_logger?.LogError(ex, deviceThread.ToString());
}
}, 10);
await UploadDeviceThreads.ParallelForEachAsync(async (deviceThread, token) =>
{
try
@@ -373,7 +384,7 @@ public class UploadDeviceWorker : BackgroundService
{
//超过30分钟或者(初始化失败并超过10分钟)会重启
if (
(devcore.Device.ActiveTime != DateTimeOffset.MinValue
(devcore.Device.ActiveTime != DateTime.MinValue
&& devcore.Device.ActiveTime.AddMinutes(30) <= SysDateTimeExtensions.CurrentDateTime)
|| (devcore.IsInitSuccess == false && devcore.Device.ActiveTime.AddMinutes(10) <= SysDateTimeExtensions.CurrentDateTime)
)

View File

@@ -102,44 +102,6 @@
}
@foreach (var item in ImportPreviews)
{
<MSubheader Class="mt-2 font-weight-black">
@(
$"{item.Key},预计导入{item.Value.DataCount}条数据"
)
</MSubheader>
<MSubheader Class=@((item.Value.HasError?"mt-2 red--text":"mt-2 green--text"))>
@(
(item.Value.HasError ? "出现错误" : "验证成功")
)
</MSubheader>
<MVirtualScroll Context="item1" Height=300 OverscanCount=2 ItemSize="60" Items="item.Value.Results">
<ItemContent>
<MListItem>
<MListItemAction>
<MChip Class="ma-2">
@(
$"第{item1.row}行"
)
</MChip>
</MListItemAction>
<MListItemContent>
<MListItemTitle Class=@((item1.isSuccess?"green--text":"red--text"))>
<strong>@item1.resultString</strong>
</MListItemTitle>
</MListItemContent>
</MListItem>
<MDivider></MDivider>
</ItemContent>
</MVirtualScroll>
}
</div>
<div class="mt-6">
<MButton Color="primary" Disabled=@ImportPreviews.Any(it=>it.Value.HasError) OnClick="()=>Step=3">下一步</MButton>

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -21,7 +21,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor;
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>excel
/// 导入excel
/// </summary>
public partial class ImportExcel
{
@@ -33,21 +33,21 @@ public partial class ImportExcel
bool isSaveImport;
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 导入
/// </summary>
[Parameter]
public Func<Dictionary<string, ImportPreviewOutputBase>, Task> Import { get; set; }
/// <summary>
/// <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ʾ
/// 是否显示
/// </summary>
public bool IsShowImport { get; set; }
/// <summary>
/// Ԥ<EFBFBD><EFBFBD>
/// 预览
/// </summary>
[Parameter]
public Func<IBrowserFile, Task<Dictionary<string, ImportPreviewOutputBase>>> Preview { get; set; }
/// <summary>
/// <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 当前步数
/// </summary>
public int Step { get; set; }
@@ -75,7 +75,7 @@ public partial class ImportExcel
StateHasChanged();
await Import.Invoke(ImportPreviews);
_importFile = null;
await PopupService.EnqueueSnackbarAsync("<EFBFBD>ɹ<EFBFBD>", AlertTypes.Success);
await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
}
finally
{

View File

@@ -21,9 +21,9 @@ public class HisPageInput : VariablePageInput
/// <summary>
/// 开始时间
/// </summary>
public DateTime? StartTime { get; set; } = DateTime.Now.AddDays(-1);
public DateTime? StartTime { get; set; } = DateTime.UtcNow.AddDays(-1);
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; } = DateTime.Now.AddDays(1);
public DateTime? EndTime { get; set; } = DateTime.UtcNow.AddDays(1);
}

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -54,7 +54,7 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
/// </summary>
public UdpSessionPage UdpSessionPage;
/// <summary>
/// ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>1-TCPCLIENT<EFBFBD><EFBFBD>2-<2D><><EFBFBD>ڣ<EFBFBD>3-UDP<EFBFBD><EFBFBD>4-TCPServer
/// 选择,1-TCPCLIENT2-串口,3-UDP4-TCPServer
/// </summary>
[Parameter]
public ChannelEnum Channel { get; set; }
@@ -65,12 +65,12 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
public override ThingsGateway.Foundation.IReadWriteDevice Plc { get; set; }
/// <summary>
/// ģ<EFBFBD><EFBFBD>
/// 模板
/// </summary>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// <EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>
/// 自定义模板
/// </summary>
[Parameter]
public RenderFragment OtherContent { get; set; }
@@ -100,7 +100,7 @@ public partial class DefalutDebugDriverPage : DriverDebugUIBase
TcpServerPage.LogAction = LogOut;
if (UdpSessionPage != null)
UdpSessionPage.LogAction = LogOut;
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//载入配置
StateHasChanged();
}

View File

@@ -14,6 +14,11 @@ using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using System.IO;
using System.Threading;
using ThingsGateway.Admin.Blazor.Core;
using ThingsGateway.Admin.Core;
using ThingsGateway.Application.Extensions;
using ThingsGateway.Foundation;
@@ -65,6 +70,8 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
[Inject]
private IVariableService VariableService { get; set; }
[Inject]
private InitTimezone InitTimezone { get; set; }
/// <inheritdoc/>
public virtual void Dispose()
@@ -80,18 +87,18 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
var data = await Plc.ReadAsync(Address, DataTypeEnum.GetSystemType());
if (data.IsSuccess)
{
Messages.Add((LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat() + " - 对应类型值:" + data.Content));
Messages.Add((LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - 对应类型值:" + data.Content));
}
else
{
Messages.Add((LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat() + " - " + data.Message));
Messages.Add((LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message));
}
}
catch (Exception ex)
{
Messages.Add((LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat() + "错误:" + ex.Message));
Messages.Add((LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + "错误:" + ex.Message));
}
}
@@ -104,23 +111,23 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
var data = await Plc.WriteAsync(Address, DataTypeEnum.GetSystemType(), WriteValue);
if (data.IsSuccess)
{
Messages.Add((LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat() + " - " + data.Message));
Messages.Add((LogLevel.Information, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message));
}
else
{
Messages.Add((LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat() + " - " + data.Message));
Messages.Add((LogLevel.Warning, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + data.Message));
}
}
catch (Exception ex)
{
Messages.Add((LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat() + " - " + "写入前失败:" + ex.Message));
Messages.Add((LogLevel.Error, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + "写入前失败:" + ex.Message));
}
}
/// <summary>
/// 导入设备
/// </summary>
/// <returns></returns>
public async Task DownDeviceExportAsync(CollectDevice data)
public async Task DeviceImportAsync(CollectDevice data)
{
try
{
@@ -138,7 +145,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
/// 导入变量
/// </summary>
/// <returns></returns>
public async Task DownDeviceExportAsync(List<DeviceVariable> data)
public async Task DeviceVariableImportAsync(List<DeviceVariable> data)
{
try
{
@@ -152,6 +159,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
}
}
/// <summary>
/// 导出
/// </summary>
@@ -180,10 +188,55 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
isDownExport = false;
}
}
/// <summary>
/// 导出到excel
/// </summary>
/// <returns></returns>
public async Task DownDeviceExportAsync(CollectDevice data)
{
try
{
isDownExport = true;
StateHasChanged();
using var memoryStream = await CollectDeviceService.ExportFileAsync(new List<CollectDevice>() { data });
memoryStream.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: memoryStream);
_helper ??= await JS.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js");
await _helper.InvokeVoidAsync("downloadFileFromStream", $"设备导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef);
}
finally
{
isDownExport = false;
}
}
/// <summary>
/// 导出到excel
/// </summary>
/// <returns></returns>
public async Task DownDeviceVariableExportAsync(List<DeviceVariable> data, string devName)
{
try
{
isDownExport = true;
StateHasChanged();
using var memoryStream = await VariableService.ExportFileAsync(data, devName);
memoryStream.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: memoryStream);
_helper ??= await JS.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js");
await _helper.InvokeVoidAsync("downloadFileFromStream", $"变量导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef);
}
finally
{
isDownExport = false;
}
}
/// <inheritdoc/>
public void LogOut(TouchSocket.Core.LogLevel logLevel, object source, string message, Exception exception)
{
Messages.Add(((LogLevel)logLevel, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat() + " - " + message + (exception != null ? exception.Message : "")));
Messages.Add(((LogLevel)logLevel, SysDateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + message + (exception != null ? exception.Message : "")));
if (Messages.Count > 2500)
{
Messages.Clear();

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -20,7 +20,7 @@ namespace ThingsGateway.Blazor;
public partial class SerialClientPage
{
/// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 日志输出
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
@@ -36,7 +36,7 @@ public partial class SerialClientPage
SerialClient.SafeDispose();
}
/// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 获取对象
/// </summary>
/// <returns></returns>
public SerialClient GetSerialClient()
@@ -47,7 +47,7 @@ public partial class SerialClientPage
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetSerialProperty(serialProperty);
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//载入配置
SerialClient.Setup(config);
return SerialClient;
}
@@ -78,8 +78,7 @@ public partial class SerialClientPage
/// <inheritdoc/>
protected override void OnInitialized()
{
config?.Dispose();
config = new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new TouchSocket.Core.LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -23,7 +23,7 @@ namespace ThingsGateway.Blazor;
public partial class TcpClientPage
{
/// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 日志输出
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
@@ -33,7 +33,7 @@ public partial class TcpClientPage
/// </summary>
private string IP = "127.0.0.1";
/// <summary>
/// <EFBFBD>˿<EFBFBD>
/// 端口
/// </summary>
[Parameter]
public int Port { get; set; } = 502;
@@ -73,18 +73,17 @@ public partial class TcpClientPage
}
}
/// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 获取对象
/// </summary>
/// <returns></returns>
public TcpClientEx GetTcpClient()
{
config?.Dispose();
config = new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new TouchSocket.Core.LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(IP + ":" + Port)).SetBufferLength(300);
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//载入配置
TcpClientEx.Setup(config);
return TcpClientEx;
}

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -19,7 +19,7 @@ namespace ThingsGateway.Blazor;
public partial class TcpServerPage
{
/// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 日志输出
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
@@ -62,19 +62,18 @@ public partial class TcpServerPage
}
}
/// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 获取对象
/// </summary>
/// <returns></returns>
public TcpService GetTcpServer()
{
config?.Dispose();
config = new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new TouchSocket.Core.LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) });
config.SetBufferLength(300);
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//载入配置
TcpServer.Setup(config);
return TcpServer;
}

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -19,7 +19,7 @@ namespace ThingsGateway.Blazor;
public partial class UdpSessionPage : IDisposable
{
/// <summary>
/// <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 日志输出
/// </summary>
public Action<LogLevel, object, string, Exception> LogAction;
@@ -62,19 +62,18 @@ public partial class UdpSessionPage : IDisposable
}
}
/// <summary>
/// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 获取对象
/// </summary>
/// <returns></returns>
public UdpSession GetUdpSession()
{
config?.Dispose();
config = new TouchSocketConfig();
config ??= new TouchSocketConfig();
var LogMessage = new TouchSocket.Core.LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Trace };
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = TouchSocket.Core.LogLevel.Trace });
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
config.SetRemoteIPHost(new IPHost(ip + ":" + port)).SetBufferLength(300);
config.SetBindIPHost(new IPHost(0));
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//载入配置
UdpSession.Setup(config);
return UdpSession;
}

View File

@@ -62,6 +62,7 @@
<MTextField Dense Style="max-width:200px;" HideDetails=@("auto") Class="mx-2 my-1" @bind-Value="_collectDeviceGroupSearchName"
Outlined Label=@typeof(CollectDevice).GetDescription(nameof(CollectDevice.DeviceGroup)) />
</MCardTitle>
<MTreeview Style=@($"height: calc(100vh - {BlazorResourceConst.DefaultHeight + 240}px; overflow-y:auto)") Dense TItem="string" TKey="string" ActiveChanged=@(async a=>
{
if(_collectDeviceGroup!=a.FirstOrDefault())
@@ -95,7 +96,7 @@
<MLabel Class=@((item.Device?.DeviceStatus==DeviceStatusEnum.OnLine?"green--text":"red--text")+$" text-h6")>
<div class="mt-1 d-flex align-center justify-space-between" title=@item.Device?.Name>
<span>@item.Device?.Name</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat() + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
</div>
</MLabel>
</MListItemTitle>
@@ -127,7 +128,7 @@
<MLabel Class=@((item.Device?.DeviceStatus==DeviceStatusEnum.OnLine?"green--text":"red--text")+$" text-h6")>
<div class="mt-1 d-flex align-center justify-space-between">
<span class="mx-3">@item.Device?.Name</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption mx-3">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat() + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption mx-3">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
</div>
</MLabel>
@@ -180,7 +181,7 @@
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
<MCol Md=6 Cols="12" Class="px-4 mt-1 d-flex align-center justify-space-between">
<span class="text-subtitle-2 grey--text">@item.Device?.Description(a=>a.ActiveTime)</span>
<span class="text-caption">@item.Device?.ActiveTime.ToDefaultDateTimeFormat()</span>
<span class="text-caption">@item.Device?.ActiveTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)</span>
</MCol>
<MCol Md=6 Cols="12" Class="px-4 mt-1 d-flex align-center justify-space-between">
<span class="text-subtitle-2 grey--text">@item.Device?.Description(a=>a.SourceVariableCount)</span>
@@ -346,7 +347,7 @@
<MLabel Class=@((item.Device?.DeviceStatus==DeviceStatusEnum.OnLine?"green--text":"red--text")+$" text-h6")>
<div class="mt-1 d-flex align-center justify-space-between" title=@item.Device?.Name>
<span>@item.Device?.Name</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat() + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
</div>
</MLabel>
</MListItemTitle>
@@ -378,7 +379,7 @@
<MLabel Class=@((item.Device?.DeviceStatus==DeviceStatusEnum.OnLine?"green--text":"red--text")+$" text-h6")>
<div class="mt-1 d-flex align-center justify-space-between">
<span class="mx-3">@item.Device?.Name</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption mx-3">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat() + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
<span style="white-space: nowrap !important;overflow: hidden !important; text-overflow: ellipsis !important;" class="text-caption mx-3">@(item.Device?.ActiveTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " " + typeof(DeviceStatusEnum).GetDescription(item.Device?.DeviceStatus.ToString()))</span>
</div>
</MLabel>
@@ -432,7 +433,7 @@
<MRow Class="ml-2 mr-2 d-flex" NoGutters>
<MCol Md=6 Cols="12" Class="px-4 mt-1 d-flex align-center justify-space-between">
<span class="text-subtitle-2 grey--text">@item.Device?.Description(a=>a.ActiveTime)</span>
<span class="text-caption">@item.Device?.ActiveTime.ToDefaultDateTimeFormat()</span>
<span class="text-caption">@item.Device?.ActiveTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)</span>
</MCol>
<MCol Md=6 Cols="12" Class="px-4 mt-1 d-flex align-center justify-space-between">
<span class="text-subtitle-2 grey--text">@item.Device?.Description(a=>a.UploadVariableCount)</span>

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -32,7 +32,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor;
/// <summary>
/// <EFBFBD>豸״̬ҳ<EFBFBD><EFBFBD>
/// 设备状态页面
/// </summary>
public partial class DeviceStatusPage : IDisposable
{
@@ -110,7 +110,7 @@ public partial class DeviceStatusPage : IDisposable
{
try
{
var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
if (confirm)
{
isAllRestart = true;
@@ -142,8 +142,8 @@ public partial class DeviceStatusPage : IDisposable
}
async Task ConfigAsync(long devId, bool? isStart)
{
var str = isStart == true ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>ͣ";
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"ȷ<EFBFBD><EFBFBD>{str}?");
var str = isStart == true ? "启动" : "暂停";
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"确定{str}?");
if (confirm)
{
CollectDeviceHostService.ConfigDeviceThread(devId, isStart == true);
@@ -167,19 +167,19 @@ public partial class DeviceStatusPage : IDisposable
memoryStream.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: memoryStream);
Helper ??= await JS.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Admin.Blazor.Core/js/downloadFileFromStream.js");
await Helper.InvokeVoidAsync("downloadFileFromStream", $"<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.txt", streamRef);
await Helper.InvokeVoidAsync("downloadFileFromStream", $"报文导出{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.txt", streamRef);
}
finally
{
isDownExport = false;
}
}
//ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//去除单个采集重启
//async Task RestartAsync(long devId)
//{
// try
// {
// var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
// var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
// if (confirm)
// {
// isRestart = true;
@@ -199,7 +199,6 @@ public partial class DeviceStatusPage : IDisposable
// await MainLayout.StateHasChangedAsync();
// }
//}
private async Task RunTimerAsync()
{
while (await _periodicTimer.WaitForNextTickAsync())
@@ -232,8 +231,8 @@ public partial class DeviceStatusPage : IDisposable
async Task UpConfigAsync(long devId, bool? isStart)
{
var str = isStart == true ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>ͣ";
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"ȷ<EFBFBD><EFBFBD>{str}?");
var str = isStart == true ? "启动" : "暂停";
var confirm = await PopupService.OpenConfirmDialogAsync(str, $"确定{str}?");
if (confirm)
{
UploadDeviceHostService.ConfigDeviceThread(devId, isStart == true);
@@ -254,7 +253,7 @@ public partial class DeviceStatusPage : IDisposable
{
try
{
var confirm = await PopupService.OpenConfirmDialogAsync("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
var confirm = await PopupService.OpenConfirmDialogAsync("重启", "确定重启?");
if (confirm)
{
isRestart = true;

View File

@@ -180,8 +180,41 @@ else
}
</ItemColTemplate>
<Detailemplate>
@{
switch (context.Item1.Value)
{
case nameof(DeviceVariable.DeviceId):
<tr @key="context.Item1.Text">
<td class="text-start table-minwidth">
@context.Item1.Text
</td>
<td class="text-start ">
<div style="word-break:break-all; white-space:pre-wrap;">
@(App.GetService<ICollectDeviceService>().GetNameById(context.Item2.ToLong()))
</div>
</td>
</tr>
break;
default:
<tr @key="context.Item1.Text">
<td class="text-start table-minwidth">
@context.Item1.Text
</td>
<td class="text-start ">
<div style="word-break:break-all; white-space:pre-wrap;">
@context.Item2
</div>
</td>
</tr>
break;
}
}
</Detailemplate>
</AppDataTable>
;
;
return renderFragment;
}

View File

@@ -61,6 +61,7 @@ else
</span>
</LabelContent>
</MTreeview>
</MCard>
</MCol>
<MCol Md=10 Cols="12">
@@ -119,7 +120,38 @@ else
}
</ItemColTemplate>
<Detailemplate>
@{
switch (context.Item1.Value)
{
case nameof(DeviceVariable.DeviceId):
<tr @key="context.Item1.Text">
<td class="text-start table-minwidth">
@context.Item1.Text
</td>
<td class="text-start ">
<div style="word-break:break-all; white-space:pre-wrap;">
@(App.GetService<ICollectDeviceService>().GetNameById(context.Item2.ToLong()))
</div>
</td>
</tr>
break;
default:
<tr @key="context.Item1.Text">
<td class="text-start table-minwidth">
@context.Item1.Text
</td>
<td class="text-start ">
<div style="word-break:break-all; white-space:pre-wrap;">
@context.Item2
</div>
</td>
</tr>
break;
}
}
</Detailemplate>
</AppDataTable>
;

View File

@@ -1,12 +1,12 @@
#region copyright
#region copyright
//------------------------------------------------------------------------------
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
// GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
// GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
// ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
// QQȺ<EFBFBD><EFBFBD>605534569
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
@@ -28,7 +28,7 @@ using ThingsGateway.Application;
namespace ThingsGateway.Blazor;
/// <summary>
/// ʵʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ
/// 实时数据页
/// </summary>
public partial class DeviceVariableRunTimePage
{
@@ -37,13 +37,13 @@ public partial class DeviceVariableRunTimePage
List<DeviceTree> _deviceGroups = new();
string _searchName;
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 设备名称
/// </summary>
[Parameter]
[SupplyParameterFromQuery]
public string DeviceName { get; set; }
/// <summary>
/// <EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// 上传设备名称
/// </summary>
[Parameter]
[SupplyParameterFromQuery]
@@ -157,7 +157,7 @@ public partial class DeviceVariableRunTimePage
}
private async Task WriteAsync(DeviceVariableRunTime collectVariableRunTime)
{
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>
// 将异步方法添加到事件回调上
WriteValueAsync = EventCallback.Factory.Create<string>(this, value => OnWriteValueAsync(collectVariableRunTime, value));
await PopupService.OpenAsync(typeof(WriteValue), new Dictionary<string, object>()
{

Some files were not shown because too many files have changed in this diff Show More