Compare commits

..

1191 Commits

Author SHA1 Message Date
Diego
d20cb7a928 兼容10.4.8以下数据库 2025-04-17 09:41:15 +08:00
Diego
952c134aba build: 10.4.19 2025-04-16 09:08:35 +08:00
2248356998 qq.com
5533d980e3 删除不必要的代码 2025-04-15 21:14:35 +08:00
2248356998 qq.com
aa0213818f 添加规则引擎日志清理任务 2025-04-15 20:59:01 +08:00
2248356998 qq.com
af88ffd57c 添加语言资源 2025-04-15 20:07:44 +08:00
2248356998 qq.com
87447b1c2a 传输model添加runtimetype 2025-04-15 20:01:21 +08:00
Diego
384a12880b 网关表格按钮权限 2025-04-15 10:13:37 +08:00
Diego
791f91f377 build: 10.4.18 2025-04-14 15:28:35 +08:00
Diego
4f8b405cc3 build:10.4.17 2025-04-13 13:03:39 +08:00
2248356998 qq.com
e1b7af201a 修改表单映射 2025-04-13 12:09:12 +08:00
2248356998 qq.com
a04b7817a9 refactor: 表格编辑框 model映射 2025-04-13 09:56:11 +08:00
2248356998 qq.com
21bf83aec7 edit css 2025-04-12 14:57:19 +08:00
2248356998 qq.com
d060d5179d build: 10.4.16 2025-04-12 12:24:05 +08:00
2248356998 qq.com
e73dd58e46 fix: 初始连接时,适配器空错误 2025-04-11 23:24:52 +08:00
Diego
a34e4a6942 添加api 2025-04-11 20:21:35 +08:00
Diego
a7ee6d78b5 fix: mqttcollect 重载变量寄存器 2025-04-11 11:01:29 +08:00
Diego
0a6651ac11 build: 10.4.14 2025-04-11 10:30:18 +08:00
Diego
fa25053c13 fix: 宏电ddp协议 tcpudp差异 2025-04-11 10:23:52 +08:00
Diego
61dd4edeb5 更新依赖 2025-04-09 18:28:25 +08:00
Diego
dbaeff302b build: 10.4.13
fix: 通道,设备名称为中文时,日志路径错误
2025-04-09 17:22:46 +08:00
Diego
6cbe7ebcf2 fix: 复制通道 2025-04-09 13:32:04 +08:00
youthalan
2826e08c8c !64 -注册授权页面显示 2025-04-08 14:36:22 +00:00
Diego
e30e337efa refactor: 删除重复的注册授权页面 2025-04-08 10:44:54 +08:00
Diego
39788e0357 refactor: 删除重复的注册授权页面 2025-04-08 10:35:37 +08:00
Diego
c47363df71 build: 10.4.11 2025-04-08 10:20:33 +08:00
Diego
4199453038 refactor: 删除logenable 2025-04-08 09:44:08 +08:00
Diego
db991081c8 build: 10.4.10 2025-04-08 00:53:41 +08:00
Diego
24f946a727 refactor: 组件属性删除 2025-04-08 00:53:22 +08:00
Diego
772dae047a refactor: 删除logenable字段 2025-04-08 00:37:41 +08:00
Diego
020f440fdd !63 build: 10.4.8
* 10.4.8
* 优化ui
* 调整规则引擎
2025-04-07 15:54:03 +00:00
Diego
c88fc5ec09 !62 build: 10.4.7
* build: 10.4.7
* 格式化
* Merge branch 'v10' into v10-dev
* Merge branch 'v10' of gitee.com:ThingsGateway/ThingsGateway into v10-dev
* 修改通道显示字符串
* fix: ddp协议
* 更新依赖
* 10.4.6
* 通道 本地主机地址和远程主机地址 文本修改
* 注册页面位置更改
* 修复导出设备失败,注册页面位置更改
* 更新依赖
* 格式化
* 更新依赖
* 删除会话管理字段
* logo size
* 更新依赖
2025-04-07 07:37:17 +00:00
Diego
475849fbef !61 fix: ddp协议
* Merge branch 'v10' of gitee.com:ThingsGateway/ThingsGateway into v10-dev
* 修改通道显示字符串
* fix: ddp协议
* 更新依赖
* 10.4.6
* 通道 本地主机地址和远程主机地址 文本修改
* 注册页面位置更改
* 修复导出设备失败,注册页面位置更改
* 更新依赖
* 格式化
* 更新依赖
* 删除会话管理字段
* logo size
* 更新依赖
2025-04-07 05:01:56 +00:00
Diego
1d63228fb2 !60 build: 10.4.6
fix: 修复导出设备失败,注册页面位置更改

refactor:通道 本地主机地址和远程主机地址 文本修改
refactor:注册页面位置更改
refactor:更新依赖包
refactor:删除会话管理字段
2025-04-06 12:28:24 +00:00
Diego
c918c0c010 更新authorizel类库 2025-04-03 02:01:08 +08:00
Diego
1028179983 build: 10.4.4 2025-04-03 01:27:43 +08:00
Diego
686f61ff90 refactor: docker镜像基础改为net8 2025-04-02 21:38:36 +08:00
Diego
ae43fadca3 更新依赖包 2025-04-02 20:40:11 +08:00
Diego
1bf05780b3 build: 10.4.3
调整pro授权密钥方式
2025-04-02 18:49:51 +08:00
Diego
3e30daa1d3 refactor: 修改文件名称 2025-04-02 12:37:06 +08:00
Diego
54ef1233b1 refactor: 重启通道时,清空内存池 2025-04-02 10:56:24 +08:00
Diego
4413633de7 build: 10.3.1 2025-04-01 22:58:06 +08:00
2248356998 qq.com
c76e20d146 dispose 2025-04-01 22:56:58 +08:00
Diego
36d53b7ce4 build: 10.2.26 2025-04-01 22:45:58 +08:00
2248356998 qq.com
0b0bce2761 fix: 设备冗余检测事件未释放 2025-04-01 22:44:46 +08:00
Diego
d47a9be03c build: 10.2.25 2025-04-01 22:22:58 +08:00
2248356998 qq.com
bc32d7ae7a refacotr: 插件释放时显式清理较大内存资源 2025-04-01 22:18:39 +08:00
Diego
e6747a2c2c build: 10.2.24
fix: ui page dispose方法未自动执行,可能导致内存泄露
2025-04-01 14:53:10 +08:00
Diego
3fb48cb64e refactor: 报警恢复时报警文本不清空 2025-04-01 11:34:41 +08:00
Diego
381db1cf53 nuget构建 2025-04-01 11:15:23 +08:00
Diego
d3939aeb9d build: 10.2.22
更新依赖项
2025-04-01 11:05:32 +08:00
Diego
5956f90557 Merge branch 'v10' of https://gitee.com/ThingsGateway/ThingsGateway into v10 2025-04-01 10:57:44 +08:00
Diego
7f54ecfe5d build: 10.2.21
feat: 增加汇川plc插件
2025-04-01 10:57:42 +08:00
Diego
e7bda99c8b build: 10.2.21
feat: 增加汇川plc插件
2025-04-01 10:57:06 +08:00
2248356998 qq.com
ea7ab5a2bf refactor: 插件停止方式改为token取消委托 2025-03-31 19:26:11 +08:00
Diego
ee566d199a 规则引擎rpc日志 增加 源名称 2025-03-31 16:19:43 +08:00
Diego
56eca454b1 更新usheet依赖项 2025-03-31 15:26:53 +08:00
Diego
d057974c3e build:10.2.20 2025-03-31 12:39:35 +08:00
Argo Zhang
9514e7fdea 更新样式适配紧凑模式下按钮大小 (#25) 2025-03-31 12:29:56 +08:00
Diego
e546113873 refactor: 添加规则名称 2025-03-31 12:14:10 +08:00
Diego
60f1139355 feat: 增加pro插件标识 2025-03-31 10:05:37 +08:00
Diego
1b18b59054 build: 10.2.18
更新依赖库
2025-03-30 16:39:10 +08:00
Diego
afec0187e9 build: 10.2.17 2025-03-29 21:24:12 +08:00
2248356998 qq.com
d0d7e1ccf8 feat: 优化ui刷新性能 2025-03-29 21:21:51 +08:00
Diego
d72376b4b7 build: 10.2.16 2025-03-29 19:00:00 +08:00
2248356998 qq.com
3be60cb305 refactor: opcua加载复杂类型添加条件 2025-03-29 18:51:57 +08:00
Diego
75b1f351a1 build: 10.2.15 2025-03-29 12:25:51 +08:00
2248356998 qq.com
07185f8018 refactor: 多通道设备日志 2025-03-29 12:23:53 +08:00
Diego
2f081b62a7 build: 10.2.14 2025-03-29 11:42:18 +08:00
2248356998 qq.com
bbce2a11e1 refactor:opcua检查订阅 2025-03-29 11:38:17 +08:00
2248356998 qq.com
96ab609157 删除注释 2025-03-29 11:23:49 +08:00
2248356998 qq.com
d961d56a35 refactor: opcua日志内容 2025-03-29 00:20:38 +08:00
Diego
82a5335a92 build: 10.2.13 2025-03-28 23:32:16 +08:00
2248356998 qq.com
729a23949c refactor: opcua增加质量戳bad日志 2025-03-28 23:29:12 +08:00
2248356998 qq.com
a1b0419d7a refactor: 在线excel 2025-03-28 23:12:00 +08:00
2248356998 qq.com
7a23015b9d refactor: 采集插件基类CollectBase更名CollectFoundationBase,CollectBase适用与与touchsocket无关的采集插件 2025-03-28 22:58:19 +08:00
Diego
9cbe0dbae1 feat: 增加tab右键菜单
refactor: mqtt协议版本增加默认值3.11
2025-03-28 17:15:45 +08:00
Diego
4f139b7d03 更新readme 2025-03-28 11:16:28 +08:00
Diego
1e925e2560 refactor: 自定义cookie名称 2025-03-28 11:14:01 +08:00
Diego
a42e1e3af3 feat: mqtt插件添加mqtt版本选择
fix: s7地址格式解析db块逻辑错误
2025-03-28 10:45:50 +08:00
Diego
799caec7ee refactor: 删除没有使用的代码 2025-03-28 10:20:35 +08:00
Diego
dd7d30498f feat: 添加变量复制按钮 2025-03-28 09:06:54 +08:00
Diego
e9b1720e98 refactor: DataHandleAdapter 2025-03-27 17:46:53 +08:00
Diego
5f41371bdb refactor: 更新配置 2025-03-27 17:09:13 +08:00
Diego
5226bfae20 build: 10.2.9 2025-03-27 15:06:02 +08:00
Diego
d1eab168b7 build: 10.2.8 2025-03-26 17:47:24 +08:00
Diego
8760518c10 build: 10.2.7 2025-03-26 09:19:46 +08:00
Diego
6719a352c2 hybrid程序startup 2025-03-25 17:14:37 +08:00
Diego
8449b6c6b8 refactor: miniexcel版本回退 2025-03-25 15:27:05 +08:00
Diego
0550eaf465 feat: 规则引擎 自定义脚本 增加主动释放方法 2025-03-25 10:55:25 +08:00
Diego
bdc9eb44ec feat: 规则引擎 自定义执行脚本支持 `IDisposable` 接口
refactor: 脚本内日志对象统一命名为 ``Logger``
2025-03-25 10:46:03 +08:00
Diego
37b99cb1b0 feat: 增加脚本提示 2025-03-25 03:22:37 +08:00
Diego
492381e4fc refactor: 修改变量数量限制逻辑 2025-03-24 14:49:41 +08:00
Diego
27d65dd799 refactor: 变量名称不再限制 不包含. 符号 2025-03-24 11:40:27 +08:00
Diego
434724310c build: 10.2.1
feat: 新增 配置 通道、设备、变量的数量限制,防止OOM

feat: 优化 ``opcuaserver`` 插件刷新变量逻辑

refactor: taos插件 表名称 强制小写

refactor: 数据库插件 脚本父类更改
2025-03-24 11:23:08 +08:00
Diego
e5ad5a8521 feat: 变量新建时自动设置已选择的设备 2025-03-21 16:46:40 +08:00
Diego
3942819fed refactor: ui样式修改 2025-03-21 10:48:11 +08:00
Diego
1cc5f538aa feat: 报警实体添加 `恢复值` 属性 2025-03-20 11:04:55 +08:00
Diego
b0d8534ea4 fix: 规则引擎按钮权限异常 2025-03-19 17:46:17 +08:00
Diego
5b2bc38670 refactor: 删除不需要的代码 2025-03-19 17:09:42 +08:00
Diego
b36aa3557c feat: opcUaServer支持同时多个写入 2025-03-19 10:57:57 +08:00
Diego
a1a525e6e3 fix: 导出excel失败 2025-03-19 09:42:37 +08:00
Diego
14453cc437 fix: rpc日志入队条件错误 2025-03-19 08:45:24 +08:00
Diego
db760ba5d8 fix: taos插件sql语句缺失标识符 2025-03-18 17:01:02 +08:00
Diego
4ae692008f 资源文件翻译错别字 2025-03-18 15:54:08 +08:00
Diego
f37449f9ac feat: 新增在线excel编辑 2025-03-18 15:44:00 +08:00
Diego
8b7348b3d4 build: 10.1.20
feat: 优化excel导入速度
feat: 优化taos插件插入数据速度
feat: DB插件全部增加设备名称筛选项

refactor: 更改默认sqlite数据库目录

fix: taos插件多个插件设备但同个变量名称的插入逻辑错误
2025-03-17 19:39:19 +08:00
Diego
709cbb7b2e build: 10.1.19 2025-03-16 23:35:52 +08:00
2248356998 qq.com
187f1a4ce2 refactor: 更新依赖项 2025-03-16 23:31:37 +08:00
2248356998 qq.com
0f2ebd3a54 refactor: 调整发送延迟方法位置 2025-03-15 14:16:57 +08:00
Diego
86b63c2792 fix: 动态topic推断错误 2025-03-14 17:02:04 +08:00
Diego
cec2e71b41 build: 10.1.18
feat: opcuaMaster兼容性增强
refactor: controlLogix插件改为符号方式
2025-03-14 13:53:13 +08:00
Diego
9380f3e1ec feat: opcua 兼容性增强 2025-03-13 17:36:45 +08:00
Diego
76c2934e12 fix: modbusSlave驱动插件配置错误 2025-03-13 10:08:01 +08:00
Diego
9714c35d4b refactor: 修改依赖项版本 2025-03-13 09:14:24 +08:00
Diego
0d9beb713a refactor: 修改依赖项版本 2025-03-13 09:10:57 +08:00
Diego
c5f8d0e0b7 feat: 添加DTU服务类型字段 2025-03-12 23:14:23 +08:00
youthalan
5e8f4b075d !59 用户实体 语言json资源更改
* 用户实体 语言json资源更改
2025-03-11 08:23:26 +00:00
Diego
4b53fca3db build: 10.1.13 2025-03-11 14:39:57 +08:00
Diego
5d9c030a09 feat: 添加json缩进格式配置 2025-03-11 14:00:35 +08:00
Diego
bacbb9a28e fix: opcuaserver释放时空异常 2025-03-10 13:32:20 +08:00
Diego
7c287e0c03 refactor: 同步依赖库代码 2025-03-10 11:48:52 +08:00
Diego
10f675137d build: 10.1.9 2025-03-09 23:04:59 +08:00
2248356998 qq.com
6bdb5328e3 feat: mqttclient插件支持tls 2025-03-09 22:53:22 +08:00
2248356998 qq.com
14f529ac4e refactor: 调整授权cookie名称 2025-03-09 19:34:41 +08:00
Diego
ffe96d9ef1 build: 10.1.8 2025-03-09 10:23:21 +08:00
2248356998 qq.com
335f264caa refactor: 日志/缓存文件夹 由Id 改为 名称 2025-03-09 10:22:05 +08:00
2248356998 qq.com
b73e86ea9f refactor: 方法名称错别字 2025-03-07 20:51:36 +08:00
Diego
2bc2c4c57b refactor: table默认紧凑 2025-03-07 16:59:28 +08:00
Diego
6f87c2f03a refactor: 优化UI细节 2025-03-07 16:14:13 +08:00
Diego
75e677af88 feat: web页面更新为紧凑主题 2025-03-07 15:47:39 +08:00
Diego
9ffe355396 build: 10.1.5
feat: 添加复制通道、复制设备功能
refactor: 优化UI提示
2025-03-07 12:21:09 +08:00
Diego
60b0fb23f8 refactor: 调整模块顺序 2025-03-07 08:52:43 +08:00
Diego
1c05ffc6ed build: 10.1.4 2025-03-06 21:17:14 +08:00
Diego
8cd4e43c68 fix: web页面 业务设备节点查询变量空异常 2025-03-06 20:55:45 +08:00
Diego
8486d28310 refactor: sql错误输出文本日志 2025-03-06 18:00:16 +08:00
Diego
e8aadda185 refactor: 显示未知类型插件 2025-03-06 17:46:28 +08:00
Diego
fcfd0428ab fix: s7设备无法保存 2025-03-06 16:33:43 +08:00
Diego
ddcc087800 build: 10.1.2
refactor: EnableWriteXorExecute 默认0
fix: 集合多线程更改错误
2025-03-06 12:09:50 +08:00
Diego
d574de54b4 refactor: EnableWriteXorExecute 默认0 2025-03-06 11:43:50 +08:00
Diego
1682ac03ac build: 10.1.1
fix: 变量寄存器编辑UI 输出错误
2025-03-06 11:08:52 +08:00
Diego
447dbece1c refactor: variableRuntime dispose 2025-03-06 10:45:39 +08:00
Diego
dcca901b17 refactor: 调整生产环境配置 2025-03-06 10:39:36 +08:00
Diego
a32c779074 refactor: 日志显示刷新频率降低 2025-03-06 09:13:30 +08:00
Diego
187c0f9829 refactor: 添加过滤条件 2025-03-06 08:44:55 +08:00
Diego
6c970c88ab feat: 优化组态重载逻辑 2025-03-06 00:46:24 +08:00
Diego
28a4520c77 build: 添加包构建条件 2025-03-05 16:37:21 +08:00
Diego
02d0dcdff7 fix: 变量页面筛选总条数显示错误 2025-03-05 14:58:17 +08:00
Diego
427d4e31c9 build: 10.1.0.4
fix: 包构建缺失内容
2025-03-05 14:40:09 +08:00
Diego
c60f7aac44 build: 10.1.0.3 2025-03-05 11:50:10 +08:00
Diego
42a7758a34 fix: webapi rpc写入 json反序列化错误 2025-03-05 11:26:38 +08:00
Diego
e0bade4670 fix: 规则引擎 变量Node 查询名称空异常 2025-03-04 23:12:53 +08:00
Diego
6af83152de build: 10.1.0.1
feat: 变量名称 由 全局唯一 更改为 采集设备内唯一
fix: opcda订阅方式初始化时未更新变量状态,导致后续变了状态一直是offline
feat: mqttServer 允许的连接ID前缀 为空时可为任意id

破坏性更新:
1、兼容旧版本数据库,但不兼容旧版本excel文件,不同点在于变量excel 业务属性页,添加了设备名称和业务设备名称,旧版本只有业务设备名称
2、业务上传内容更改为 字典类型,键为设备名称,值为变量列表。变量列表内容与旧版本相同
2025-03-04 21:09:11 +08:00
Diego
091a30045d feat: 规则引擎触发器UI优化 2025-03-03 18:07:18 +08:00
Diego
b2c8ae0c33 更新依赖包 2025-03-03 13:02:27 +08:00
Diego
8b6e0982c6 feat: 页面添加变量寄存器格式提示titile 2025-03-01 21:00:24 +08:00
Diego
caa3ebd600 feat: db动态脚本基类修改 2025-03-01 16:04:40 +08:00
Diego
d248e047b3 build: 10.0.2.14 2025-02-27 18:04:51 +08:00
Diego
25a95a1de0 fea(variableRuntimeService): 方法添加是否重启参数 2025-02-27 17:48:03 +08:00
Diego
d506b2c692 fix: api登录异常 2025-02-27 11:11:53 +08:00
Diego
24c672c2b9 feat: 优化树节点右键菜单内容 2025-02-27 10:51:05 +08:00
Diego
c407e0e83e feat: taos时序库支持每个数据点独立子表
feat: 重启运行时方法改为重载数据库获取通道设备变量
2025-02-26 21:59:41 +08:00
Diego
b1346698d6 feat: 优化opcua历史查询 2025-02-26 14:40:38 +08:00
Diego
5c01129567 补充解决方案文件 2025-02-25 16:39:03 +08:00
Diego
cd7ce53bd0 feat: 新增webhook插件 2025-02-25 16:23:43 +08:00
Diego
4c95c20061 feat: 添加动态变量新增和删除的方法 2025-02-25 15:21:06 +08:00
Diego
5339db5058 refactor: 删除opcua105 2025-02-25 10:04:02 +08:00
Diego
623e932f8c feat: 增加 microLogix1400 plc驱动(pro插件) 2025-02-24 20:23:07 +08:00
Diego
43659de4f4 feat: mqttServer增加匿名登录选项 2025-02-23 22:22:47 +08:00
Argo Zhang
2a661eda42 refactor: 调整插件调试样式 (#23) 2025-02-23 22:03:51 +08:00
Diego
c85a93a17b build: 10.0.2.3 2025-02-21 08:45:04 +08:00
2248356998 qq.com
8ab36cb3e1 feat: 优化opcua订阅 2025-02-20 23:18:37 +08:00
Diego
72820d0708 feat: 添加注册服务 2025-02-20 11:33:39 +08:00
Diego
95b551d4ba feat: 优化opc单设备大批变量检索速度
fix: 定时任务删除网关日志无效
2025-02-19 20:39:42 +08:00
Diego
68af9a0695 feat: 语言资源 2025-02-18 19:33:14 +08:00
Diego
6953c3989b feat: 添加刷新变量日志 2025-02-18 09:03:51 +08:00
Diego
cd4cb385d5 fix: 修复设备冗余多次切换后设备状态异常导致切换事件不触发 2025-02-17 14:58:44 +08:00
Diego
f4f6d595fc feat: 优化设备冗余,网关冗余 2025-02-17 13:31:29 +08:00
Diego
d2356f00e9 feat: 业务插件增加循环间隔 2025-02-17 09:35:59 +08:00
2248356998 qq.com
e408136196 feat: 优化组态配置流畅度 2025-02-15 20:12:59 +08:00
Diego
c355968add 支持冗余备用设备变量并集 2025-02-14 17:15:58 +08:00
Diego
783f878947 fix: 转换器实例初始化方法 2025-02-14 16:23:00 +08:00
Diego
4faf41e482 fix: 修复设备冗余切换 2025-02-14 14:48:28 +08:00
Diego
d8964b6ed2 feat: 优化设备冗余 2025-02-14 11:11:12 +08:00
Diego
b5b999941c 10.0.1.3 2025-02-14 09:43:15 +08:00
2248356998 qq.com
deeba8c4de 默认关闭多租户 2025-02-13 20:33:19 +08:00
youthalan
9e48729eb0 !58 修复按钮资源值及默认开启租户状态
* 修复按钮资源值及默认开启租户状态
2025-02-13 12:32:26 +00:00
2248356998 qq.com
936e374c05 fix: 修改设备后,变量实体中的设备名称实时生效 2025-02-13 20:29:50 +08:00
Diego
0f3524b114 feat: opc插件支持实时修改变量 2025-02-12 16:23:05 +08:00
Diego
d62de3d72c feat: 上传 网关冗余/更新以及规则引擎 源码 2025-02-10 09:32:02 +08:00
Diego
957a80da4b feat: 优化变量寄存器界面加载 2025-02-07 18:09:51 +08:00
Diego
1dccd70f7c feat(uaserver): 删除登录策略限制 2025-02-07 16:37:25 +08:00
Diego
006a5d4e61 feat: excel导入支持空白单元格 2025-02-07 10:50:33 +08:00
Diego
ce7cdcf54e fix: 变量编辑样式修正 2025-02-07 10:17:12 +08:00
Diego
c1ebb4a79b feat: 公开mqttServer发布方法 2025-02-06 16:43:05 +08:00
Diego
41964ae1de fix: 修改通道时,设备没有及时修改插件 2025-02-06 16:30:51 +08:00
Diego
66cf34adf7 fix: 修改通道时,设备没有及时修改插件 2025-02-06 16:04:49 +08:00
Diego
9e9e0009cf fix: opcua插件名称重复 2025-02-06 14:26:51 +08:00
Diego
d5cd9660fc feat: 调整blazor授权,添加自定义刷新逻辑 2025-02-06 12:08:40 +08:00
Diego
12a7803653 更新readme 2025-02-05 11:47:42 +08:00
Diego
8f7bef6a20 feat: 添加1.05版本opcua依赖库 2025-02-05 10:49:22 +08:00
2248356998 qq.com
a0715b830c feat: 日志读取长度限制放宽 2025-02-03 21:22:37 +08:00
2248356998 qq.com
f87ce10dc4 feat: 更新依赖包 2025-02-03 19:57:16 +08:00
2248356998 qq.com
ee4936b8c9 fix: 变量实时值偶发错误
feat: 优化内存占用
2025-01-25 16:02:06 +08:00
2248356998 qq.com
3cb2592660 fix: 清空变量时空异常 2025-01-24 23:22:41 +08:00
2248356998 qq.com
574c901b40 v10迁移 2025-01-24 22:42:26 +08:00
2248356998 qq.com
7590ba4ad5 更新插件 2025-01-06 20:57:36 +08:00
Diego
39ce18f8bb 更新readme 2025-01-06 16:06:01 +08:00
Diego
777a4f9d3f 更新插件 2025-01-06 14:29:51 +08:00
Diego
b91a938787 更新构建脚本 2025-01-06 14:02:41 +08:00
Diego
c903abdb1b 更新admin 2025-01-06 11:24:49 +08:00
Diego
3279bc0580 更新构建脚本 2025-01-06 11:12:04 +08:00
Diego
bd32c9f49e 更新插件 2025-01-06 10:28:14 +08:00
Diego
5507088e3d 更新插件 2025-01-06 09:48:55 +08:00
2248356998 qq.com
37ad48ae4a 7.2.3.6
更新依赖包
2025-01-05 23:46:31 +08:00
2248356998 qq.com
120c6e6d87 7.2.3.5
opcuaclient: 心跳机制异常
2025-01-05 00:46:52 +08:00
2248356998 qq.com
866e907b7e 同步 2025-01-02 20:47:47 +08:00
2248356998 qq.com
2bd8c2cb10 更新mc1e插件 2025-01-02 20:45:19 +08:00
Diego
c6c9919178 更新依赖包 2025-01-02 16:45:31 +08:00
Diego
575bf9d1e0 update Version MSBuildProperty 2025-01-02 13:56:38 +08:00
Diego
82a56e0285 更新构建脚本 2025-01-02 12:56:52 +08:00
Diego
25d5f7c132 设定动态编译缓存目录 2025-01-02 12:27:57 +08:00
Diego2098
a3e9ecf30f !56 恢复插件隔离
* 恢复插件域
2025-01-02 04:03:14 +00:00
2248356998 qq.com
ec5ff0a07f 7.2.1.3
更新mqttnet版本
更新admin
2025-01-01 16:25:19 +08:00
Diego
be836d30c5 更新admin 2024-12-30 12:11:08 +08:00
2248356998 qq.com
42b1529a5f 添加Release解决方案 2024-12-28 10:35:02 +08:00
2248356998 qq.com
47708c4807 添加Release解决方案 2024-12-28 10:30:17 +08:00
2248356998 qq.com
d2a51e004c 7.2.0.99
规则引擎:自定义脚本接口定义修改,增加Logger属性
数据库上传插件:回退修改,恢复string类型Value字段
2024-12-28 04:19:37 +08:00
2248356998 qq.com
ab14230101 修复通道报文日志失效 2024-12-26 21:36:09 +08:00
Diego
4bcf8c1f78 修复设备通讯变量点位 2024-12-26 15:38:19 +08:00
Diego
44d00e9da3 数据库插件实体类修改! 2024-12-26 14:45:25 +08:00
Diego
d7e6a4493c 更新依赖 2024-12-26 13:22:51 +08:00
Diego
53e89d8c54 7.2.0.95
修复 LL优先级比L低
添加报警属性验证规则
2024-12-25 12:26:06 +08:00
Diego
4497c13634 代码清理 2024-12-25 10:53:43 +08:00
Diego
4a35fade46 更新插件 2024-12-24 17:44:51 +08:00
Diego
6cba0601fd fix: 上一提交导致other通道创建错误 2024-12-24 17:21:10 +08:00
Diego
ed4332ea78 更新readme 2024-12-24 14:14:30 +08:00
Diego
aba069cec5 7.2.0.91
修复dlt645驱动
调整异步方法
2024-12-24 14:03:39 +08:00
Diego
8a82ac0a11 更新测试方法 2024-12-23 16:43:35 +08:00
Diego
1cd1456d75 7.2.0.87
更新admin
2024-12-23 15:31:16 +08:00
Diego
b791a3eb10 修复 动态插件属性 验证错误 2024-12-23 15:21:42 +08:00
2248356998 qq.com
3b22a8b170 7.2.0.85
更新依赖
2024-12-22 15:59:15 +08:00
2248356998 qq.com
419e8214ca 更新规则引擎,优化性能 2024-12-20 22:32:37 +08:00
Diego
b9f8571f0f 7.2.0.83
fix(VariableRuntime): 修改判断变量变化方法
feat(TestVariable): 修改添加测试变量UI
2024-12-20 14:28:44 +08:00
Diego
c6d9a9d7f8 修改判断变量变化方法 2024-12-20 14:27:29 +08:00
Diego
310aba6ccb 修改添加测试变量UI 2024-12-20 12:11:20 +08:00
Diego
9bd89ac4f6 添加 git 更新子模块 bat 2024-12-19 18:40:13 +08:00
Diego
ea6a51dca9 更新admin 2024-12-19 18:16:01 +08:00
Diego
e701bcc50c 调整插件基类,增加上传模式配置 2024-12-19 18:15:47 +08:00
Diego
a1abf06e75 7.2.0.78
更新opc插件
2024-12-19 16:11:13 +08:00
Diego
76ace394b0 更新opcua插件 2024-12-19 15:21:21 +08:00
Diego
4dac462f8f 更新解决方案 2024-12-19 12:21:32 +08:00
Diego
039672b1e7 更新admin 2024-12-19 12:19:55 +08:00
Diego
1b26ecbbf5 添加 admin 子模块 2024-12-19 11:54:14 +08:00
Diego2098
f4a7e96943 add Admin submodule.
Signed-off-by: Diego2098 <2248356998@qq.com>
2024-12-19 03:17:59 +00:00
Diego
a45bc2954f 移动文件夹 2024-12-19 11:16:24 +08:00
Diego
62f32467b7 移动文件夹 2024-12-19 11:15:18 +08:00
Diego
600a1bf201 7.2.0.75 2024-12-18 12:36:49 +08:00
Diego
7e196e7aa6 更新admin 2024-12-17 14:16:15 +08:00
Diego
9ad3507b66 7.2.0.72
修复变量导入错误
2024-12-17 13:51:51 +08:00
Diego
add1bdfcf6 更新admin 2024-12-17 13:26:27 +08:00
Diego
7ea8a7c079 7.2.0.70
修复初始值解析
2024-12-17 10:51:52 +08:00
Diego
28e31f5165 7.2.0.69
更新实体特性
2024-12-17 10:22:03 +08:00
Diego
10a6975c5d 7.2.0.68
更新modbusSlave插件,适配03功能码单写bit
2024-12-16 18:24:16 +08:00
Diego
b34ea87660 7.2.0.67
更新db插件,增加 单独配置实时表上传间隔时间 属性
2024-12-16 17:38:42 +08:00
Diego
86ed69c50b 7.2.0.66
更新版本
2024-12-16 11:29:52 +08:00
Diego
02e824154c 7.2.0.65
读取间隔增加cron支持
2024-12-16 11:13:23 +08:00
Matrix
dc973c8491 !55 TimeTick 新增 Cron
* TimeTick 新增 cron定时
2024-12-16 03:03:39 +00:00
2248356998 qq.com
0a28e3a8d3 7.2.0.64 2024-12-15 23:41:07 +08:00
2248356998 qq.com
7a48c260e1 更新插件 2024-12-14 15:22:19 +08:00
Diego
c55c49a3a2 添加TS自定义二进制序列化方式 2024-12-13 12:19:12 +08:00
Diego
0fc9b06d12 7.2.0.62
优化上传插件批量性能
2024-12-11 15:52:00 +08:00
Diego
d71ad5a6bf 单文件发布 2024-12-11 11:13:58 +08:00
Diego
f0b3028306 更新规则引擎 2024-12-11 09:15:27 +08:00
2248356998 qq.com
752992c527 7.2.0.60
更新admin
删除不需要的文件
2024-12-10 14:30:18 +08:00
Diego
43c4476396 7.2.0.58
更新aop框架版本
2024-12-09 15:43:29 +08:00
Diego
f8172bed56 修复单文件发布 2024-12-09 11:33:00 +08:00
Diego
c1f71b4cfc 7.2.0.57
添加数据库解密示例

更新依赖包
2024-12-09 11:11:16 +08:00
2248356998 qq.com
4799da15e7 7.2.0.53
更新语言资源
更新规则引擎
2024-12-08 22:01:16 +08:00
2248356998 qq.com
4936e47c7a 7.2.0.50 2024-12-07 18:34:51 +08:00
2248356998 qq.com
cb965373aa 更新插件 2024-12-07 18:30:25 +08:00
2248356998 qq.com
654a91184a 7.2.0.48
更新依赖
2024-12-07 17:51:48 +08:00
Diego
57997f7f4b 优化规则引擎 2024-12-06 10:45:56 +08:00
Diego
ca2f5be3d1 7.2.0.46
更新Admin,修复错误插件dll导致程序无法启动的问题
2024-12-05 17:15:54 +08:00
Diego
1b091073f1 7.2.0.45 2024-12-05 11:10:43 +08:00
Diego
85d2d3c442 更新pro插件 2024-12-05 11:09:31 +08:00
Diego
d77dfd63cf 增加规则引擎插件 2024-12-05 02:13:02 +08:00
Diego
db2bf52fca 调整脚本编辑UI 2024-12-04 08:48:27 +08:00
Diego
2c62d97440 迁移重启后台按钮到设备状态页面 2024-12-03 22:23:26 +08:00
Diego
53b2e64214 修复net6 界面白屏 2024-12-02 18:11:16 +08:00
Diego
ccf82a3ee5 添加layout显示条件 2024-12-02 17:08:50 +08:00
Diego
9cb6f35e60 修改代码规范文件,更新依赖包 2024-12-02 11:28:54 +08:00
2248356998 qq.com
da2e33a040 7.2.0.36 2024-11-30 21:00:05 +08:00
2248356998 qq.com
f2d260bfa4 动态调整线程池最大活动数目 2024-11-30 01:53:26 +08:00
Diego
783c7244f9 修正語言資源 2024-11-29 17:05:21 +08:00
Diego
c9287e0e63 更新依赖
命名空间变化
2024-11-29 16:53:00 +08:00
Diego
69b84d115c 添加变量导入校验缓存 2024-11-29 10:01:02 +08:00
Diego
1745b898b1 删除文件 2024-11-29 09:22:36 +08:00
Diego
5ba4c85249 更新依赖包,转移部分代码到插件仓库 2024-11-28 21:14:14 +08:00
Diego
03c87bb46d 更新admin 2024-11-28 14:13:50 +08:00
Diego
dff5a76e9e 更新docker构建脚本 2024-11-27 16:05:16 +08:00
Diego
50386f4ca4 cache try dispose 2024-11-26 11:29:52 +08:00
Diego
de6ba2ec80 更新版本 2024-11-25 13:26:11 +08:00
Diego
ce126015d9 更新pro插件 2024-11-25 12:52:04 +08:00
Diego
f2337c3d43 更新依赖 2024-11-25 11:38:09 +08:00
Diego
41b59d322a 更新依赖,添加bacnet,HJ212 2024-11-25 11:32:28 +08:00
2248356998 qq.com
dfea7c111e 更新依赖 2024-11-23 17:36:59 +08:00
2248356998 qq.com
3d5d672297 更新版本 2024-11-22 19:57:31 +08:00
2248356998 qq.com
e4dcc6f342 更新插件 2024-11-22 19:57:11 +08:00
Diego
9847249611 修改非数采插件的引用方式 2024-11-21 23:52:31 +08:00
Diego
19742a54ec 更新插件 2024-11-21 18:37:11 +08:00
Diego
5af9ae7a80 修复上个版本导致驱动sign量无法正常返回的bug 2024-11-21 17:42:11 +08:00
Diego
78962a4a75 去掉api日志显示 2024-11-21 17:05:13 +08:00
Diego
9a35d826aa 添加 更新服务 启用选项 2024-11-21 16:47:09 +08:00
Diego
c9cdc89d35 更新版本 2024-11-20 18:28:16 +08:00
Diego
33b75703ba 更新種子數據 2024-11-20 09:40:49 +08:00
Diego
ca55aa3a24 更新插件 2024-11-19 17:03:52 +08:00
Diego
95307c3902 更新版本文件 2024-11-19 12:10:40 +08:00
Diego
89c8eae7e2 更新依赖 2024-11-19 10:48:49 +08:00
Diego
91614772dc 更新版本 2024-11-19 10:28:42 +08:00
Diego
cd497ab4dc 更换快捷方式实现方式 2024-11-18 10:03:45 +08:00
2248356998 qq.com
f81895905e 更新依赖包 2024-11-18 00:24:18 +08:00
2248356998 qq.com
d82fafaa7a 更新后台版本 2024-11-17 14:14:28 +08:00
2248356998 qq.com
0ea01acc46 驱动在丢弃错误报文时提示日志 2024-11-16 20:58:46 +08:00
2248356998 qq.com
df55792a68 调试工具css更新 2024-11-16 20:29:36 +08:00
Diego
6a19c45269 更新版本 2024-11-15 21:51:39 +08:00
Diego
23ee345441 更新插件 2024-11-15 21:13:43 +08:00
Diego
0e8ff253f3 更新admin版本 2024-11-15 16:53:44 +08:00
2248356998 qq.com
89bddb0bc4 修复双机热备功能,添加日志显示 2024-11-14 22:34:03 +08:00
Diego
77bbca9bb3 调整公共页面位置 2024-11-14 15:13:34 +08:00
2248356998 qq.com
1acd4d8d58 更新版本 2024-11-14 00:31:33 +08:00
2248356998 qq.com
4db72a712d 更新依赖 2024-11-13 22:08:59 +08:00
Diego
da2b7ba08e 调整css 2024-11-13 17:32:39 +08:00
Diego
f8b49411bf 添加net9.0 2024-11-13 16:15:04 +08:00
Diego
a04b0d99b0 添加更新服务器 2024-11-12 16:14:09 +08:00
Diego
9e9735f617 更新admin版本 2024-11-11 17:28:34 +08:00
Diego
f906b36f01 更新插件版本 2024-11-11 17:26:12 +08:00
Diego
a9d1f4f854 更新版本 2024-11-10 20:29:42 +08:00
Diego
d017ae905f 添加重启软件功能 2024-11-10 01:18:05 +08:00
Diego
bede280507 种子数据默认不更新 2024-11-08 00:35:08 +08:00
Diego
ea130047bc 修复配置 2024-11-07 16:36:18 +08:00
Diego
d77d8de63e 更新依赖包 2024-11-07 16:27:44 +08:00
Diego
f5413d9202 修复插件关联设备数量缓存不刷新 2024-11-07 15:08:15 +08:00
Diego
559fc8f216 更新后台 2024-11-06 16:25:10 +08:00
Diego
34b2df911d 更新插件版本 2024-11-06 13:16:47 +08:00
Diego
3d5a8a8cbd Merge branch 'master' into release 2024-11-06 10:19:16 +08:00
Diego
2b07097e14 导入变量时写入机构id 2024-11-06 10:18:52 +08:00
Diego
372e943d8b Merge branch 'master' into release 2024-11-06 09:32:24 +08:00
Diego
95afcedc4f 更新后台 2024-11-06 09:32:01 +08:00
Diego
c1dc8f017c Merge branch 'master' into release 2024-11-06 09:15:04 +08:00
Diego
dbeddca263 整理格式 2024-11-06 09:13:09 +08:00
Diego
e65d133dec 更新依赖包 2024-11-06 09:02:11 +08:00
Diego
b5e1dea1c2 Merge branch 'master' into release 2024-11-05 14:52:58 +08:00
Diego
3f19469939 更新后台 2024-11-05 14:52:27 +08:00
Diego
87874b037a Merge branch 'master' into release 2024-11-05 11:59:50 +08:00
Diego
adda6841d1 更新后台版本 2024-11-05 11:58:24 +08:00
Diego
a8092b921b 添加机构 2024-11-05 06:05:23 +08:00
Diego
930e4d69d1 恢复sqlite数据库类型 2024-11-05 05:41:07 +08:00
Diego
d9219df45b 后台管理添加机构功能 2024-11-05 05:39:07 +08:00
Diego
a6d4ec28db 删除不必要的构建 2024-10-29 14:26:06 +08:00
Diego
b29e13f777 更新构建脚本 2024-10-28 17:08:35 +08:00
Diego
9363b78ff6 Merge branch 'master' of https://gitee.com/ThingsGateway/ThingsGateway 2024-10-28 16:58:42 +08:00
Diego
eba411fec7 更新插件 2024-10-28 16:49:09 +08:00
Diego2098
9afe99e134 !53 7.0.1.6
* Merge branch 'release' of gitee.com:ThingsGateway/ThingsGateway into master
* 更新依赖包
* 更新依赖包,雪花ID方法
* 更新依赖包,雪花ID方法
2024-10-28 00:40:55 +00:00
Diego2098
6678856178 Merge branch 'release' of gitee.com:ThingsGateway/ThingsGateway into master
Signed-off-by: Diego2098 <2248356998@qq.com>
2024-10-28 00:40:40 +00:00
Diego
a1fea38c2c 更新依赖包 2024-10-28 08:32:18 +08:00
Diego2098
2d3265e66d !52 7.0.1.5
* 更新依赖包,雪花ID方法
* 更新依赖包,雪花ID方法
2024-10-23 11:03:51 +00:00
Diego
f6d4400db9 更新依赖包,雪花ID方法 2024-10-23 19:01:13 +08:00
Diego
6d892a9266 更新依赖包,雪花ID方法 2024-10-23 19:00:23 +08:00
Diego2098
356fa08da5 !51 7.0.1.4
Merge pull request !51 from Diego2098/master
2024-10-16 15:13:04 +00:00
Diego
2225f8c890 修复数组类型比较错误 2024-10-16 22:37:35 +08:00
Diego2098
d1a89739f9 !50 7.0.1.3
Merge pull request !50 from Diego2098/master
2024-10-16 05:23:38 +00:00
Diego
6ec6896763 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2024-10-16 13:19:42 +08:00
Diego
9fb718d610 更新依赖包 2024-10-16 13:18:09 +08:00
Diego2098
c913b89a47 !49 7.0.1.2
Merge pull request !49 from Diego2098/master
2024-10-16 03:59:53 +00:00
Diego2098
58b45693b7 !48 7.0.1.2
Merge pull request !48 from Diego2098/release
2024-10-16 03:59:16 +00:00
Diego
29d3ece9b1 更新依赖包 2024-10-15 17:47:12 +08:00
Diego2098
7e5db75230 !47 7.0.1.2
Merge pull request !47 from Diego2098/master
2024-10-14 11:51:48 +00:00
Diego
283c0b9845 修改:更新脚本编辑UI 2024-10-14 19:51:22 +08:00
Diego2098
071a0f1651 !46 7.0.1.1
Merge pull request !46 from Diego2098/master
2024-10-14 11:07:55 +00:00
Diego
1a116557a4 修改:移入部分项目代码 2024-10-14 19:06:09 +08:00
Diego
1468297626 修改:更新依赖包 2024-10-12 23:41:40 +08:00
Diego
87e94fdf52 修改:更新依赖包 2024-10-12 10:59:12 +08:00
Diego
64e15c33c8 修改:更新依赖包 2024-10-12 10:57:10 +08:00
Diego2098
7170f435d1 !45 7.0.0.26
Merge pull request !45 from Diego2098/master
2024-10-11 07:31:21 +00:00
Diego
9942be0493 修复:更新依赖包,修复脚本编辑框无法显示的问题 2024-10-11 15:29:45 +08:00
Diego
eaad36277f 修改:脚本编辑更改代码编辑器 2024-10-10 17:25:37 +08:00
Diego
37cc498568 修改:脚本编辑更改代码编辑器 2024-10-10 16:44:39 +08:00
Diego
8a3191340a 修改:更新依赖包 2024-10-09 22:15:56 +08:00
Diego
0f4e998f0a 修改:更新依赖包 2024-10-08 13:40:43 +08:00
Diego
0c93b649ba 新增:预添加网关检查更新,网关系统重启等页面 2024-10-08 13:27:45 +08:00
Diego
947d269877 新增:预添加网关检查更新,网关系统重启等页面 2024-10-08 13:21:55 +08:00
Diego
b4b9453948 新增:语言资源 2024-10-08 09:59:20 +08:00
Diego
b99a4cd095 修改:插件添加方式 2024-10-06 00:08:40 +08:00
Diego
a363d5aa46 修改:业务插件变量属性添加enable字段 2024-10-05 23:05:27 +08:00
Diego
ae442dabb4 新增:添加设备关联变量跳转 2024-10-05 21:23:00 +08:00
Diego
1477c88397 新增:添加插件关联设备数量字段 2024-10-05 21:22:52 +08:00
Diego
4172462938 新增:添加专业版插件标识 2024-10-05 13:54:43 +08:00
Diego
27341ba4f8 修改:更新nuget依赖 2024-10-02 09:19:08 +08:00
Diego2098
7443076094 修改:更新nuget依赖 2024-10-02 09:15:41 +08:00
Diego
a764bb4b1d 构建:共用版本变量 2024-09-30 12:20:05 +08:00
Diego
57130e1af7 release:7.0
代码架构重构,兼容6.0数据库
2024-09-30 01:39:39 +08:00
Diego
3f8a354c99 refactor: 更新依赖 2024-09-23 16:59:26 +08:00
Diego
0b10d92929 release:6.1.0.33 2024-09-22 22:28:32 +08:00
Diego
1a1c55e661 docs: 更新文档 2024-09-22 22:27:44 +08:00
Diego
87768f9e8b release:6.1.0.32
refactor: 合并工具库代码

fix: 操作日志 orm特性 在特定数据库类型下 可能会报错

refactor: 部分文件更换目录
2024-09-22 21:38:36 +08:00
Diego
d079f50364 fix: 操作日志 orm特性 在特定数据库类型下 可能会报错 2024-09-19 12:32:10 +08:00
Diego
72a89835c5 refactor: 合并工具库代码 2024-09-19 11:17:13 +08:00
Diego
39d686810b release:6.1.0.29
feat: 增加变量业务属性自定义UI

fix: 设备状态更新错误

refactor: 变量导出导入excel排序
2024-09-18 09:14:56 +08:00
Diego
d936626001 feat: 增加变量业务属性自定义UI 2024-09-18 09:05:48 +08:00
Diego2098
cdce1c5ea6 refactor: 更新依赖 2024-09-17 16:00:48 +08:00
Diego
d59530a54f other: 更新文档地址 2024-09-14 18:17:25 +08:00
Diego
fe480811fb fix: 设备状态更新错误 2024-09-14 15:41:27 +08:00
Diego
2e3e0d34c3 refactor: 变量导出导入排序 2024-09-14 14:22:42 +08:00
Diego
1e2984d0d9 refactor: 更新依赖 2024-09-14 03:02:51 +08:00
Diego
3e9fe693c7 release:6.1.0.27
feat: 添加链路关闭前事件
feat: 添加AB PLC ControlLogix协议驱动

refactor: 更新依赖
refactor: mqttCollect支持简单json对象
refactor: 每次采集成功都更新设备成功状态
2024-09-14 01:14:09 +08:00
Diego
63161838d8 feat: 添加链路关闭前事件
refactor: 更新依赖
refactor: mqttCollect支持简单json对象
refactor: 每次采集成功都更新设备成功状态
2024-09-12 18:12:38 +08:00
Diego
7c92951ae9 release:6.1.0.26
feat: 添加保存值功能
feat: 增加特殊地址变量,方便用户自定义设备状态变量或当前设备计算点

refactor: 繁體詞彙修改與新增UI翻譯
refactor: 更新依赖
2024-09-10 11:49:58 +08:00
Diego
59a25854ef feat: 添加保存值功能 2024-09-10 10:59:58 +08:00
rotoyang
3ca5768974 繁中語系更新 (#21)
* 繁體詞彙修改與新增UI翻譯

* TYPO

---------

Co-authored-by: RY <ry@address.no>
2024-09-10 10:23:33 +08:00
Diego
9a2dce43dd feat: 增加特殊地址变量,方便用户自定义设备状态变量或当前设备计算点 2024-09-09 16:21:24 +08:00
Diego
b7fce4317b release:6.1.0.25
docs: 更新采集插件开发文档
fix: 偶发重启后台出现变量重复
refactor: 更新依赖
2024-09-09 14:29:13 +08:00
Diego
97d9514b00 fix(mqttcollect): 重试时间默认为0错误 2024-09-08 16:18:07 +08:00
Diego
58f88708fa docs: 更新文档 2024-09-07 21:24:11 +08:00
Diego
d79c874aa5 release:6.1.0.24
fix: modbus、s7 读取字节某一位开始的数组时,请求长度太大
feat: linux桌面软件添加net8实现
2024-09-07 20:03:41 +08:00
Diego2098
58917c1ff8 refactor: 更新依赖 2024-09-07 18:24:08 +08:00
Diego2098
13b171a62d fix: modbus、s7 读取字节某一位开始的数组时,请求长度太大 2024-09-07 18:23:39 +08:00
Diego2098
f0a601922a fix: modbus、s7 读取字节某一位开始的数组时,请求长度太大 2024-09-07 16:23:59 +08:00
Diego
d90090b35e release:6.1.0.23
feat: 增加mqtt采集插件
fix: net6框架中的opcuaserver缺少dll文件
2024-09-06 15:12:27 +08:00
Diego
094d1142e7 fix: net6框架中的opcuaserver缺少dll文件 2024-09-06 10:08:11 +08:00
Diego
eb09d1c925 refactor: 恢复插件创建方式 2024-09-06 03:10:44 +08:00
Diego
bd5d75361e refactor: 恢复插件创建方式 2024-09-06 03:10:16 +08:00
Diego
5d7c0c635b release:6.1.0.21
feat: 关系库存储插件支持动态表格式脚本
refactor: 内存变量插件修改读取逻辑
2024-09-06 02:06:08 +08:00
Diego
606f538bf3 other: 修改引入条件 2024-09-06 01:02:23 +08:00
Diego
574c0eea27 feat: 关系库存储插件支持动态表格式脚本 2024-09-06 00:59:19 +08:00
Diego
4730cbc543 refactor: 内存变量插件修改读取逻辑 2024-09-05 15:29:23 +08:00
Diego
5c63359550 release:6.1.0.20
feat: 添加报警确认api
feat: 添加插件属性自定义ui
2024-09-05 11:45:28 +08:00
Diego
ec3607f779 refactor: 更新繁体资源 2024-09-04 16:58:13 +08:00
Diego
7efd0f8098 release:6.1.0.19
refactor: 更新依赖
feat: 添加繁体资源
2024-09-04 16:39:57 +08:00
Diego
2a7c30a21a refactor: netcoreApp添加去重 2024-09-04 16:12:39 +08:00
Diego2098
2639c3ee3f !43 feat: 添加繁体资源
* feat: 添加繁体资源
2024-09-04 08:08:37 +00:00
Diego2098
547e0153cb !42 refactor: 更新依赖 2024-09-04 03:21:17 +00:00
Diego
423664fcfa other: 补充忽略文件 2024-09-04 08:41:06 +08:00
Diego2098
c986c230ef !41 release:6.1.0.17
* 添加pro nuget包
* 更新依赖
2024-09-03 14:37:57 +00:00
Diego
7c6001f76e refactor: 修改插件构建项 2024-09-03 16:32:38 +08:00
Diego
d3620946ac fix(Admin): adminIndex编译错误 2024-09-02 17:01:57 +08:00
Diego2098
479643221c !40 release:6.1.0.1
release:6.1.0.1

refactor: 部分插件方法访问权限修改
refactor: 优化采集/业务后台服务可读代码
refactor(modbusSlave): 默认建立时启动服务
refactor(modbusSlave): 对于设置的不同设备地址,不返回错误码(不再响应,以防止干扰通讯链路中的其他设备)
refactor: 更新依赖库
2024-09-02 08:08:59 +00:00
Diego
c9ef8bcf6a fix: 报警插件记录到questdb时出现错误sql 2024-08-30 17:06:54 +08:00
Diego
d655a7c2f6 fix: opc插件调试日志不显示 2024-08-30 13:54:57 +08:00
Diego
306861d3b4 release:6.0.5.30
refactor:  mqtt插件重启时忽略报错日志

fix(mqttClient): 订阅配置错误
fix: 获取实时报警api接口返回值错误
2024-08-30 13:22:30 +08:00
Diego
7abab41eed refactor: 更新注释 2024-08-30 08:58:59 +08:00
Diego
acc2691e33 fix: 获取实时报警api接口返回值错误 2024-08-29 17:41:06 +08:00
Diego
21a65956b0 refactor: mqtt插件重启时忽略报错日志 2024-08-29 16:14:33 +08:00
Diego
9738275ad1 fix: DB插件编译 2024-08-29 13:10:59 +08:00
Diego
7265034703 refactor: 更新构建项 2024-08-29 13:08:05 +08:00
Diego
9bcc45591d docs: 更新文档 2024-08-29 12:49:48 +08:00
Diego
38d657ba0e fix(mqttClient): 订阅配置错误 2024-08-29 12:43:10 +08:00
Diego
6a0d16c5bb release:6.0.5.29
refactor:  mqttServer不再保留全部变量遗嘱数据,可使用quest rpc获取
feat: 增加net6编译程序,只在低版本操作系统中推荐
2024-08-29 11:54:56 +08:00
Diego
490d4abb56 feat: 更新构建项 2024-08-29 10:48:48 +08:00
Diego
a7d0f7fc99 refactor: mqttServer不再保留全部变量遗嘱数据,可使用quest rpc获取 2024-08-28 17:46:04 +08:00
Diego
0d2d3ff528 release:6.0.5.28
refactor:  更新依赖库
refactor:  删除tab 扩展按钮,固定首页不可关闭
feat: 添加调试页面winbox窗口
2024-08-28 13:26:59 +08:00
Diego
526169f0aa release:6.0.5.27
refactor:  更新依赖库
feat: 日志组件添加等级筛选
feat: 补充多语言资源
fix: dlt645驱动上个版本提交bug
2024-08-27 16:43:59 +08:00
Diego
42940ff0e3 feat: 补充多语言资源 2024-08-27 14:55:10 +08:00
Diego
e9b943363d feat: 日志组件添加等级筛选 2024-08-27 14:24:26 +08:00
Diego
01e98ff10c refactor: 更新依赖库 2024-08-27 10:48:53 +08:00
Diego
d38981a17d release:6.0.5.26
feat: 关系库插件 添加 自动建库 功能
feat: 驱动库添加压测
2024-08-27 10:37:12 +08:00
Diego
7612e91691 feat: 关系库插件 添加 自动建库 功能 2024-08-27 08:38:19 +08:00
Diego
76b0f20033 release:6.0.5.25
fix: 单通道多设备时,偶发空指针错误
2024-08-26 18:06:27 +08:00
Diego
b78c0f8a29 refactor: 驱动库send方法默认添加锁 2024-08-26 11:45:50 +08:00
Diego
ea93c7c8fc release:6.0.5.24
feat: 基础库增加 net8 编译项
feat: SqlHisAlarm添加表名称配置属性
refactor:  默认server gc true,如有低内存需要,更改 MSBuild 项
2024-08-26 11:11:50 +08:00
Diego
8ac1952974 release:6.0.5.23
feat: 基础库增加 net8 编译项
feat: SqlHisAlarm添加表名称配置属性
refactor:  默认server gc true,如有低内存需要,更改 MSBuild 项
2024-08-26 11:02:21 +08:00
Diego
b4514a5bbf release:6.0.5.21
feat: 完善mqtt脚本,适配thingsboard
2024-08-25 18:10:26 +08:00
Diego
568053b06d feat: 增加多语言资源 2024-08-24 23:05:17 +08:00
Diego
bb180bfc39 release:6.0.5.20
refactor:  启动项目文件结构优化
2024-08-24 18:29:04 +08:00
Diego
5ee635caed fix: 字节池对象获取ArraySegment错误 2024-08-23 16:48:01 +08:00
Diego
5dfd7c8597 release:6.0.5.17
feat: 添加内存变量插件
refactor:  变量数据页面序列化数据概要json.net
2024-08-23 14:51:29 +08:00
Diego
fe61b75d7e feat: 添加内存变量插件 2024-08-23 13:11:28 +08:00
Diego
e7bf565418 feat: 添加内存变量插件 2024-08-23 13:11:06 +08:00
Diego
12071f6251 feat: 添加内存变量插件 2024-08-23 13:10:35 +08:00
Diego
72ed2e3ed0 release:6.0.5.16
docs: 更新文档
refactor:  questdb初始化失败时更新的时间为格里威治时间
2024-08-22 19:41:13 +08:00
Diego
d7c1f134fe release:6.0.5.15
docs: 更新文档
refactor:  更新依赖包
refactor:  优化UI卡顿问题
refactor:  await统一添加ConfigureAwait(false)
2024-08-22 19:22:45 +08:00
Diego
5072d9f7ad fix: mqtt脚本检查功能中的类型转换错误 2024-08-21 20:44:52 +08:00
Diego
5d42a1247a docs: 更新文档 2024-08-21 20:16:16 +08:00
Diego
ce64be22bd docs: 更新文档 2024-08-21 20:10:50 +08:00
Diego
36f9386e8d release:6.0.5.14
feat: 添加报警延时逻辑
feat: mqtt脚本添加检查按钮
fix(opcuamaster): 服务端时间戳选项在轮询模式下不生效
refactor:  aop插入日志ip字段 非null
2024-08-21 19:44:34 +08:00
Diego
e9dc963805 feat: mqtt脚本添加检查按钮 2024-08-21 18:19:39 +08:00
Diego
8854322997 fix(opcuamaster): 服务端时间戳选项在轮询模式下不生效 2024-08-21 16:08:13 +08:00
Diego
6018f1e8ca refactor: aop插入日志ip字段 非null 2024-08-21 12:25:53 +08:00
Diego
68f8ebb543 release:6.0.5.13
refactor:  修改用户中心的修改密码为密码输入框
refactor:  opcua轮询采集时异常捕获内容包含当前读取地址
2024-08-20 16:13:00 +08:00
youthalan
301f0218fd !39 修改用户中心的修改密码为密码输入框
修改用户中心的修改密码为密码输入框
2024-08-20 04:39:42 +00:00
Diego
a9c4a56893 other: 更新发布脚本 2024-08-19 18:07:00 +08:00
Diego
3ea3d72f11 refactor: 全屏按钮重复 2024-08-19 15:25:20 +08:00
Diego
33da5bf4a7 release:6.0.5.12
refactor:  更新依赖项
build:  修改构建脚本
build:  添加arm64 docker镜像
2024-08-19 13:08:05 +08:00
Diego
e3de01948a release:6.0.5.12
refactor:  更新依赖项
build:  修改构建脚本
build:  添加arm64 docker镜像
2024-08-19 13:06:02 +08:00
Diego
3cd92aaf54 other: winform标题修改 2024-08-18 21:17:43 +08:00
Diego
ab4e1996dd other: 添加演示站自动更新功能 2024-08-18 21:14:33 +08:00
Diego
b9ef082abf release:6.0.5.10
refactor:  photino版本退出时释放资源
feat:  添加winform版本
2024-08-18 18:34:14 +08:00
Diego
dac7186da3 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2024-08-18 04:03:15 +08:00
Diego
1fd6cc2b5e release:6.0.5.9
refactor: 封装furion swagger文档
refactor:简化代码
refactor:更新依赖包
2024-08-18 04:03:01 +08:00
youthalan
0b7da9790a !38 修复AdminTable的行编辑按钮和行删除按钮的回调显示
!38 修复AdminTable的行编辑按钮和行删除按钮的回调显示
2024-08-16 07:26:01 +00:00
Diego
a9e0e0ead6 other: 添加一键发布脚本 2024-08-16 13:05:57 +08:00
Diego
079754f1a9 release:6.0.5.7
refactor: 设备PluginType属性增加多语言资源键值
fix: 权限框架解决方案编译错误
refactor: index 首页 页面文件迁移至主程序
refactor:更新依赖包
2024-08-16 11:55:49 +08:00
Diego
c45b5b1e86 release:6.0.5.7
refactor: 设备PluginType属性增加多语言资源键值
fix: 权限框架解决方案编译错误
refactor: index 首页 页面文件迁移至主程序
2024-08-16 11:43:34 +08:00
Diego
2115cc685c fix: visual studio2022.17.11.0版本编译错误,razor条件编译方式更换 2024-08-15 15:58:00 +08:00
Diego
b99e56fc19 release:6.0.5.6 2024-08-15 11:48:45 +08:00
Diego
74c057eb84 refactor: 更新依赖库 2024-08-14 20:56:12 +08:00
Diego
e8ececc0dc other: 代码清理 2024-08-14 20:55:50 +08:00
Diego
ad120b7736 fix(chart): pie饼图加载异常,回退依赖版本 2024-08-14 15:13:35 +08:00
Diego
61c0711e79 release:6.0.5.5
fix: newlife.x工具库部分命名空间错误
refactor: DtuId属性描述添加'UTF8'
refactor: 更新依赖项
2024-08-14 11:52:35 +08:00
Diego
81c3f6fce0 refactor: 调整工具库命名空间 2024-08-13 18:33:54 +08:00
Diego2098
0a4416e633 !37 release:6.0.5.3
refactor: 完善桌面端版本多语言资源

refactor: 忽略部分文件夹
2024-08-13 08:49:17 +00:00
Diego
6bb712854d Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2024-08-13 00:27:08 +08:00
Diego
46959e2407 docs: 更新文档 2024-08-13 00:27:00 +08:00
Diego2098
debbb049b0 !36 release:6.0.5.2
* feat: 增加IHostApplicationLifetime实现
* fix(FAIconList): js位置错误
2024-08-12 16:02:37 +00:00
Diego
375377fef9 release:6.0.5.1
refactor: 分离部分代码
refactor: 调整代码架构,分出blaor server与blazor hybrid架构的服务代码
2024-08-12 16:48:33 +08:00
Diego
d5758dd6a3 refactor: 代码清理 2024-08-12 14:22:07 +08:00
Diego
d5deffea58 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2024-08-11 18:10:35 +08:00
Diego
fadb43d9a1 release:6.0.4.61
refactor: 更新依赖库版本
refactor: card默认背景颜色更改
2024-08-11 18:10:24 +08:00
youthalan
044b641df0 !35 将快捷按钮归入到SPA模块中
* -将快捷按钮归入到SPA模块中
2024-08-09 01:48:19 +00:00
Diego
fbbacdb2ff Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2024-08-08 10:57:09 +08:00
Diego
4bfd7acd96 release:6.0.4.60
refactor: 支持全局按钮权限
refactor: 修改服务类插件启动错误后的等待间隔时间
2024-08-08 10:56:23 +08:00
youthalan
ff03225cf4 !34 补充TableExtensionToolbarTemplate及TableExtensionToolbarBeforeTemplate属性
* -补充TableExtensionToolbarTemplate及TableExtensionToolbarBeforeTemplate属性
2024-08-07 05:54:09 +00:00
Diego
8e820c0e47 fix(s7): 插件写入时错误 2024-08-07 11:16:41 +08:00
Diego
d718314324 other: 更新readme 2024-08-06 14:21:45 +08:00
Diego
1c653ec1b1 release:6.0.4.58 2024-08-05 20:13:54 +08:00
Diego
fe16ddadce fix: sql历史数据分包查询错误 2024-08-05 11:23:33 +08:00
Diego
7a978054cc refactor: 默认的登录页路径设置 2024-08-05 10:42:27 +08:00
Diego
8ed3b5a747 refactor: 整理权限框架 2024-08-04 00:38:07 +08:00
youthalan
6885150800 !33 修复用户页面手机号显示问题
* -修复用户页面手机号显示问题
2024-08-02 03:53:49 +00:00
Diego
35d33a1c7d fix: 修复上一提交导致的字典服务错误 2024-08-02 00:26:41 +08:00
Diego
93a16bbd3c fix: 修复上一提交导致的字典服务错误 2024-08-02 00:08:28 +08:00
Diego
d3cf6a4985 fix: 修复上一提交导致的字典服务错误 2024-08-01 23:54:42 +08:00
Diego
8ef7200c32 fix: 修复上一提交导致的字典服务缓存实体类型错误 2024-08-01 23:07:43 +08:00
Diego
e43da5ba86 release:6.0.4.48 2024-08-01 22:13:56 +08:00
youthalan
10428b4340 !32 添加查询自定义字典参数
* -修改字典种子数据字段名称
* -添加查询自定义字典参数
2024-08-01 14:08:46 +00:00
Diego
43b7c05cd7 refactor: 删除空文件夹 2024-08-01 17:31:17 +08:00
Diego
057f64b04c refactor: 文件更名 2024-08-01 17:28:21 +08:00
Diego
0971d783f3 release:6.0.4.47 2024-08-01 14:54:39 +08:00
Diego
54aabad3e8 refactor: 添加桌面端导出服务 2024-07-31 17:18:53 +08:00
Diego
606fbb5fec build: 调整构建脚本 2024-07-31 11:14:27 +08:00
Diego
5093c27ba5 release:6.0.4.45
fix: 会话管理离线通知功能失效
2024-07-31 09:28:01 +08:00
Diego
1d3661c946 refactor: 添加桌面端后台服务启停; 2024-07-30 21:04:17 +08:00
Diego
304f7a068d release:6.0.4.43
refactor: 支持blazor hybrid;
feat(s7): 支持多写;
2024-07-30 20:45:22 +08:00
Diego
7ea91be3fc release:6.0.4.43
refactor: 支持blazor hybrid;
feat(s7): 支持多写;
2024-07-30 20:44:20 +08:00
Diego
d15464b1ae release:6.0.4.42
refactor: 支持blazor hybrid;
feat(s7): 支持多写;
2024-07-30 19:57:23 +08:00
Diego
150435f24e release:6.0.4.41
refactor: 支持blazor hybrid;
feat(s7): 支持多写;
2024-07-30 19:45:06 +08:00
Diego
e49507cd14 release:6.0.4.38
refactor: 支持blazor hybrid;
feat(s7): 支持多写;
2024-07-30 19:44:47 +08:00
Diego
ad3cc3ebb6 refactor: 添加Cors 2024-07-29 09:47:58 +08:00
Diego
ecaf53836d release:6.0.4.31 2024-07-26 17:25:03 +08:00
Diego
8fc36e7b24 refactor: s7打包后不再主动关闭连接,因为可能对通道多设备产生影响 2024-07-26 17:24:26 +08:00
Diego
1dbbac2aa3 refactor: 更新依赖包 2024-07-26 08:56:44 +08:00
Diego
4e5775fde4 fix(modbusServer): modbusServer 写入布尔量错误 2024-07-24 00:06:45 +08:00
Diego
9d81c7c366 other: 删除backup文件 2024-07-19 10:28:23 +08:00
Diego
2df0441f0f release:6.0.4.28
fix: 变量导出excel偶发插件属性丢失
refactor: 变量并发导出按变量名称排序
2024-07-19 09:12:17 +08:00
Diego
4216002ce5 feat: startup适配移动平台 2024-07-18 20:50:06 +08:00
Diego
1af6f4e151 feat: 导出扩展方法 2024-07-18 08:20:57 +08:00
Diego
05f284bc11 refactor(S7): 对于变长字符串,连读打包解析时,根据返回字节解析长度 2024-07-17 14:51:48 +08:00
Diego
40c19b3ad4 refactor: 完善多语言资源 2024-07-16 17:06:03 +08:00
Diego
d1d972cca0 refactor: 文件夹更名 2024-07-16 15:54:30 +08:00
Diego
2a969921d6 refactor: nuget包添加打包 2024-07-16 08:32:27 +08:00
Diego
4b3e1f5187 refactor: nuget包添加打包 2024-07-15 20:45:12 +08:00
Diego
561963aa26 refactor: 整理格式 2024-07-15 20:36:36 +08:00
Diego
6c2c192836 refactor: 整理格式 2024-07-15 17:44:32 +08:00
Diego
f0730f2295 refactor: 恢复格式 2024-07-14 21:17:09 +08:00
Diego
9df91d2b63 refactor: 整理格式 2024-07-14 17:48:17 +08:00
Diego
09da1941fd refactor: 整理格式 2024-07-14 17:45:18 +08:00
Diego
613c8e4c28 refactor: 整理格式 2024-07-14 14:49:40 +08:00
Diego
7b407fd34d refactor: 整理格式 2024-07-14 12:19:20 +08:00
Diego
fb7ff7a803 refactor: 整理格式 2024-07-14 12:18:13 +08:00
Diego
0c1f0e0522 refactor: 分离部分代码 2024-07-13 22:31:45 +08:00
Diego
b5d771e9aa refactor: 分离部分代码 2024-07-13 22:22:53 +08:00
Diego
2f64255895 refactor(modbus): 修改方法访问级别 2024-07-13 13:30:06 +08:00
Diego
5b629a5c40 release:6.0.3.81
更新依赖包
2024-07-12 16:40:08 +08:00
Diego
b749cf52c3 feat(RpcService): rpc多写性能优化 2024-07-12 09:33:17 +08:00
Diego
b9a36a9223 feat: 更新常用方法 2024-07-09 17:27:21 +08:00
Diego
32debf6e6b fix: modbus byte类型读取偏移 2024-07-09 16:45:52 +08:00
Diego
06f6ae01c9 feat(modbus):支持byte类型连读 2024-07-09 16:20:42 +08:00
Diego
db4d8ad802 release:6.0.3.76 2024-07-09 15:40:36 +08:00
Diego
9c82de9c9e feat(opcuaServer): 优化opcuaServer更新数据效率 2024-07-09 12:01:06 +08:00
Diego
8329835528 refactor: 更新依赖项 2024-07-08 18:35:27 +08:00
Diego
8e624aa31b refactor: 更新依赖项 2024-07-07 17:08:04 +08:00
Diego2098
a2e8741517 refactor: 实时数据页面去除变量值筛选 2024-07-06 17:03:58 +08:00
Diego2098
3b7c107e8f release:6.0.3.72
fix(dlt645): 最大需量及发生时间数据标识编码错误
2024-07-06 17:00:54 +08:00
Diego
558bc3f971 release:6.0.3.71
fix(s7): 打包时pdulength不需要再次减去其他字节量

fix(s7): 打包时尝试连接一次
2024-07-05 15:07:05 +08:00
Diego
90a326f380 refactor: 实时数据页面去除变量值排序 2024-07-04 23:08:57 +08:00
Diego
867dc1ae35 refactor: 实时数据页面去除变量值排序 2024-07-04 22:53:20 +08:00
Diego
3f555464f7 fix(s7): 非主动发送时忽略解析 2024-07-04 22:35:38 +08:00
Diego
c0c0782258 release:6.0.3.69
fix(s7):写入结果错误
2024-07-04 19:18:24 +08:00
Diego
377f57bcb6 release:6.0.3.68
refactor: modbustcp修改错误
refactor: 连接失败时延时返回
refactor: 添加Dtu心跳回应间隔
2024-07-04 16:11:16 +08:00
Diego
a51253f1e5 refactor: modbustcp修改错误 2024-07-04 10:35:58 +08:00
Diego
e674e94da6 refactor: 驱动连接失败时延时返回 2024-07-04 10:28:02 +08:00
Diego
93a415f6d3 refactor: 添加Dtu心跳回应间隔 2024-07-04 10:04:10 +08:00
Diego
9364b97692 release:6.0.3.67 2024-07-03 17:46:38 +08:00
Diego
030915c9ea refactor: modbus排除干扰报文 2024-07-03 17:41:22 +08:00
Diego
10882c309a refactor: 修改 未选择数据时,批量编辑按钮提示信息 2024-07-03 15:11:52 +08:00
Diego
8232fde160 refactor: s7 2024-07-03 09:29:03 +08:00
Diego
45c3474d4d feat: 更新主题修改方式 2024-07-01 12:12:03 +08:00
Diego
c5a9e85343 release:6.0.3.66
feat: SQHisAlarm 支持questDB数据库
2024-07-01 10:20:19 +08:00
Diego
8c7ef59583 release:6.0.3.66
feat: SQHisAlarm 支持questDB数据库
2024-07-01 09:33:39 +08:00
Diego
36404b5c92 release:6.0.3.65 2024-06-29 18:53:05 +08:00
Diego
9949a117be refactor: 优化dtu服务显示页面 2024-06-29 17:07:45 +08:00
Diego
a3896db4f5 fix: signalr client在blazor server中,指定的url需按本机地址 2024-06-29 15:27:19 +08:00
Diego2098
f668062cab release:6.0.3.64 2024-06-29 12:02:04 +08:00
Diego2098
bac0721078 refactor: 任务启动前捕获操作取消日志 2024-06-29 11:46:51 +08:00
Diego2098
e29d7244d8 release:6.0.3.63 2024-06-29 10:36:36 +08:00
Diego2098
5a34b91a7a release:6.0.3.62 2024-06-29 08:17:28 +08:00
Diego2098
eaac8b1428 release:6.0.3.62
fix: dtu插件错误
2024-06-29 08:11:28 +08:00
Diego2098
6c6275dc88 release:6.0.3.61 2024-06-29 01:48:45 +08:00
Diego2098
bd350ae679 fix: tcpService被动连接读取错误 2024-06-29 00:53:32 +08:00
Diego
cadee28c68 release:6.0.3.60 2024-06-28 18:38:57 +08:00
Diego
3534828a99 feat: 支持DataService 2024-06-28 15:59:03 +08:00
Diego
e1c5777e25 release:6.0.3.59 2024-06-28 15:41:56 +08:00
Diego
63553d4dd3 release:6.0.3.59 2024-06-28 15:35:15 +08:00
Diego
6033d779fc release:6.0.3.58 2024-06-28 15:24:29 +08:00
Diego
97db27e61f release:6.0.3.57 2024-06-27 18:57:04 +08:00
Diego
8ed861c05f release:6.0.3.56 2024-06-27 15:55:54 +08:00
Diego
4d416657bf release:6.0.3.55 2024-06-27 12:24:21 +08:00
Diego
ede0399275 release:6.0.3.55 2024-06-27 12:20:42 +08:00
Diego
1a28ada04c fix: 服务启动时状态设置错误 2024-06-27 11:36:14 +08:00
Diego
8ac771cde4 release:6.0.3.51 2024-06-27 10:54:25 +08:00
Diego
c6afbbfc73 fix: 通道多设备时,适配器设置偶发错误 2024-06-27 10:54:06 +08:00
Diego
5ba71e8109 refactor: modbus/s7 2024-06-27 10:43:31 +08:00
Diego
a0d2922aca fix: 菜单缓存未及时刷新 2024-06-26 21:06:53 +08:00
Diego2098
446610b9df release:6.0.3.50 (#10)
release:6.0.3.50
2024-06-26 20:16:31 +08:00
Diego
4905eea503 refactor: modbus插件删除并发数量 2024-06-24 17:59:08 +08:00
Diego
519fc128f6 refactor: Admin 2024-06-24 16:25:04 +08:00
Diego
cc10955483 refactor: 修改测试库 2024-06-24 12:16:19 +08:00
Diego
e0bd47bb87 refactor: 修改注释 2024-06-24 10:48:12 +08:00
Diego
fb0c3c4a06 release:6.0.3.47 2024-06-24 10:39:19 +08:00
Diego
ceef1fdaf2 release:6.0.3.47 2024-06-24 10:38:05 +08:00
Diego
e1ac287ed1 release:6.0.3.46 2024-06-24 10:19:17 +08:00
Diego2098
29cd3a5945 release:6.0.3.44 2024-06-23 22:49:01 +08:00
Diego2098
cab082166b release:6.0.3.38 2024-06-23 00:01:26 +08:00
Diego
711dfd4da9 release:6.0.3.35 2024-06-21 18:18:28 +08:00
Diego
643948331d other: 更新demo 2024-06-21 18:10:13 +08:00
Diego2098
119030f1a5 release:6.0.3.34 2024-06-21 18:05:20 +08:00
Diego2098
3efee3dc52 refactor: 修改DTU未连接的错误提示 2024-06-21 18:01:15 +08:00
Diego2098
70716d5121 fix: mapster忽略大小写策略错误,导致部分插件属性映射错误 2024-06-21 09:43:11 +08:00
Diego
a7d11ead62 fix: 调试工具多读功能寄存器数据类型未绑定 2024-06-20 18:32:51 +08:00
Diego
017830e433 docs: 更新文档 2024-06-20 18:09:38 +08:00
Diego
bceb175c75 release:6.0.3.32 2024-06-20 16:49:53 +08:00
Diego
98277c6b71 release:6.0.3.32 2024-06-20 16:49:01 +08:00
Diego
b227fbe523 feat(opcda): 值变化事件添加组名称参数 2024-06-20 16:48:37 +08:00
Diego
ac6659a293 refactor: 通道释放等待池 2024-06-20 14:42:53 +08:00
Diego
30a24ced1d refactor: 修改日志输出顺序 2024-06-20 13:02:51 +08:00
Diego
3d1f4ae2ed fix: blazor form验证 2024-06-19 19:28:23 +08:00
Diego
e86aff049c fix(调试工具): 断开连接 2024-06-19 18:55:33 +08:00
Diego
8ec0ba7c9e other: 更新demo 2024-06-19 17:16:00 +08:00
Diego
c2898f0b2e other: 更新demo 2024-06-19 15:35:30 +08:00
Diego
0747374378 release:6.0.3.31 2024-06-19 11:43:53 +08:00
Diego
a0c2fea833 feat: 支持单文件发布 2024-06-19 11:43:14 +08:00
Diego
811c1a445f refactor: 修改基准测试项 2024-06-18 14:55:56 +08:00
Diego
72d3041e7e release:6.0.3.30 2024-06-18 14:31:52 +08:00
Diego
503180e7ec release:6.0.3.23 2024-06-18 12:25:54 +08:00
Diego
8ad548cad7 release:6.0.3.22 2024-06-18 12:14:38 +08:00
Diego2098
85d9acf605 refactor: 并发锁位置调整 2024-06-18 10:09:01 +08:00
Diego
fc93c5ffcb refactor: 并发锁位置调整 2024-06-17 17:01:13 +08:00
Diego
d6b0a9314c refactor: 初始化缓存编译读写表达式 2024-06-17 13:49:45 +08:00
Diego
83bc07c3ff release:6.0.3.11
修改默认启动端口
2024-06-17 10:32:05 +08:00
Diego2098
6ca680cd41 refactor: 数据库表名风格统一 2024-06-16 13:59:17 +08:00
Diego2098
2b533dcb2b fix: s7驱动多语言文本错误 2024-06-15 20:18:37 +08:00
Diego2098
13a5a09f98 refactor: 优化modbusSlave 2024-06-15 19:09:18 +08:00
Diego
75ff7ebdbe other:更新调试工具 2024-06-14 16:01:42 +08:00
Diego
6d8f3a1fc8 release:6.0.3.9 2024-06-14 14:14:39 +08:00
Diego
a11b411912 fix: 修复上个提交导致的表达式空指针错误 2024-06-14 09:28:18 +08:00
Diego
2dba817c69 feat: 登录页面添加版本提示 2024-06-13 16:55:54 +08:00
Diego
d4df9a545f release:6.0.3.8 2024-06-13 14:22:36 +08:00
Diego
cae21391e5 release:6.0.3.8 2024-06-13 14:20:53 +08:00
Diego
573b22d2c2 refactor: 优化CSScript编译 2024-06-13 14:20:30 +08:00
Diego
14d4112a9d fix: 命名空间错误 2024-06-13 13:47:18 +08:00
Diego
28aa9db9c5 更新依赖 2024-06-13 13:40:33 +08:00
Diego
d50c349e00 release:6.0.3.7
破坏性更改

动态编译脚本表达式,传入值不再是dynamic类型,而是object,注意类型转换
2024-06-13 13:38:17 +08:00
Diego
905362c59c release:6.0.3.6 2024-06-13 10:23:36 +08:00
Diego
97e7d44310 fix: 特殊方法选择错误 2024-06-12 16:29:04 +08:00
Diego
bb71a1ef23 feat: tcpservice支持多个ip绑定,以分号间隔 2024-06-12 14:29:14 +08:00
youthalan
de2771d008 !31 添加ShowExtendEditButtonCallback等
Merge pull request !31 from youthalan/master
2024-06-12 02:59:09 +00:00
Diego
02de34b65a refactor: crc方法修改 2024-06-11 19:03:19 +08:00
youthalan
c6e14889f2 !30 添加SetRowClassFormatter属性等
Merge pull request !30 from youthalan/master
2024-06-11 08:07:06 +00:00
Diego
f843732790 other: dockerfile 2024-06-11 15:50:52 +08:00
Diego
80e7ff0fc1 release:6.0.3.5 2024-06-11 15:47:58 +08:00
Diego
2964db6bdd fix: modbusUdp已发送数组获取失败 2024-06-11 15:47:36 +08:00
Diego
5fbd94ec74 refactor: 更新依赖 2024-06-11 15:37:50 +08:00
Diego
1d8d31d4f0 other: 更新docker地址 2024-06-11 12:53:08 +08:00
Diego
707c3eed99 release:6.0.3.3
refactor: 优化错误提示
2024-06-11 12:24:17 +08:00
Diego2098
e33a81ad36 refactor: 优化错误提示 2024-06-10 22:53:48 +08:00
Diego2098
0f7d216379 refactor: 优化错误提示 2024-06-10 22:47:54 +08:00
Diego2098
f0052e97a6 refactor: 修改注销方式 2024-06-10 21:05:59 +08:00
Diego
5c6076d48d refactor: 修改token缓存服务 2024-06-09 19:49:29 +08:00
Diego
883bd31249 refactor: 优化debug软件体验 2024-06-09 17:55:57 +08:00
Diego
d7b5fde3c7 fix: 取消mapster映射忽略大小写,这会导致字典键错误 2024-06-09 17:16:56 +08:00
Diego
f4273efef0 fix: 冗余心跳错误 2024-06-09 14:12:39 +08:00
Diego
471dc966d9 fix: 冗余心跳错误 2024-06-09 13:52:12 +08:00
Diego
50368654a4 build: Photino修改为net6 2024-06-09 13:34:01 +08:00
Diego
b1e1cc04ce refactor: dockerfile 2024-06-09 13:18:49 +08:00
Diego
554f67e295 release:6.0.2.27 2024-06-09 13:16:10 +08:00
Diego
278bd09a6c refactor: 优化插件调试通道创建步骤 2024-06-09 13:12:42 +08:00
Diego
300d083038 release:6.0.2.27
refactor: 优化插件调试通道创建步骤
2024-06-09 13:11:03 +08:00
Diego
34664f0025 other: 代码整理 2024-06-09 12:30:45 +08:00
Diego
7aaa803813 docs: 更新文档 2024-06-09 12:25:28 +08:00
Diego
b075b3ec1c Revert "dcos: 更新大小端配置方式"
This reverts commit 6a1f1ebf9d.
2024-06-09 12:24:01 +08:00
Diego
0f3f4b0f5b refactor: 字节解析顺序回退5.x版本策略 2024-06-09 12:23:55 +08:00
Diego
fd5ed78442 feat: 支持modbus服务端模拟dtu设备 2024-06-07 22:39:17 +08:00
Diego
d516e7dcb4 fix: 回退5.x版本bool解析策略 2024-06-07 13:48:37 +08:00
Diego
6a1f1ebf9d dcos: 更新大小端配置方式 2024-06-06 19:08:15 +08:00
Diego
6ba5c02dd6 release:6.0.2.25 2024-06-06 16:29:19 +08:00
Diego
c9b8f90859 fix: 线程管理锁策略错误 2024-06-06 15:18:58 +08:00
Diego
70a0bf6d5c fix: 心跳格式判断错误(多余空格) 2024-06-06 14:50:05 +08:00
Diego
4caf8d6fab refactor: 默认GC策略修改 2024-06-06 10:32:42 +08:00
Diego
aa90593158 refactor: 优化动态主题错误提示 2024-06-06 09:07:13 +08:00
youthalan
9da5531483 feat(AdminTable): 增加BeforeRowButtonTemplate属性 2024-06-06 01:05:11 +00:00
youthalan
9483459ba7 feat(AdminTable): 增加BeforeRowButtonTemplate属性
feat(AdminTable): 增加BeforeRowButtonTemplate属性
2024-06-05 09:58:13 +00:00
Diego
ae57883770 refactor: 适配touchsocket nuget包新版本 2024-06-05 16:50:30 +08:00
Diego
8cb5a89d10 other: 更新Dockerfile 2024-06-05 16:15:10 +08:00
Diego
1a35fb0d4d release:6.0.2.22 2024-06-05 15:55:58 +08:00
Diego
1a2483c68c docs: 更新mqtt文档 2024-06-05 15:55:35 +08:00
Diego
6c806238b2 refactor: mqttRpc主题策略更改
Break Changes

mqttRpc主题策略更改
2024-06-05 15:51:08 +08:00
Diego
ea6e07a38b refactor: 代码整理 2024-06-05 14:56:34 +08:00
Diego
ec6b07b275 fix: 业务插件基类定时上传方法循环错误 2024-06-05 14:48:54 +08:00
Diego
e85a03a1ca release:6.0.2.20
refactor: 更新依赖包版本
2024-06-05 14:18:03 +08:00
Diego
5d66b7677f refactor: 缓存文件名称修改 2024-06-05 13:19:11 +08:00
Diego
3932834172 other: 修改解决方案文件 2024-06-05 12:36:10 +08:00
Diego
d2e8294a1a release:6.0.2.19
fix: 自定义实时报警条件错误

refactor: webapi登录返回实体更改,添加token到响应body
2024-06-05 10:27:13 +08:00
Diego
b06aa66ad8 refactor: 优化本地化语言显示 2024-06-04 19:15:10 +08:00
Diego
c45b48d949 release:6.0.2.18
fix: 重启运行时偶发空异常

refactor: 变量批量编辑支持报警属性

fix: 批量编辑时刷新缓存
2024-06-04 18:54:37 +08:00
Diego
f779af1f65 fix: 重启运行时偶发空异常 2024-06-04 15:39:16 +08:00
Diego
78d039cd5f refactor: 变量批量编辑支持报警属性 2024-06-04 15:02:53 +08:00
Diego
fdbd5418c7 release:6.0.2.17
fix: 变量业务属性为空时保存失败

fix: TD数据库列描述不支持,删除对应特性

feat: 增加删除缓存按钮
2024-06-04 14:47:11 +08:00
Diego
5df42466fd fix: 变量业务属性为空时保存失败;
fix: TD数据库列描述不支持,删除对应特性
2024-06-04 14:12:46 +08:00
Diego
ff2bed87f2 release:6.0.2.16
refactor: 优化DTU模式采集
2024-06-04 12:02:38 +08:00
Diego
765e7d0b1e release:6.0.2.15
refactor: 优化DTU模式采集
2024-06-04 11:16:22 +08:00
Diego
71ab6d42c8 fix: dtu模式下modbus打包逻辑错误 2024-06-03 18:39:03 +08:00
Diego
2ea2a662ef refactor: 删除不必要的锁操作 2024-06-03 18:28:28 +08:00
Diego
c2d45349a4 release:6.0.2.10
refactor: update touchsocket
2024-06-03 15:11:03 +08:00
Diego
1b5cf410b7 release:6.0.2.7
fix: 回退touchsocket版本
2024-06-03 14:08:33 +08:00
Diego
3e79e2bed0 feat: 增加可选配置json文件 2024-06-03 13:30:31 +08:00
Diego
2a1f933702 release:6.0.2.6
refactor: update touchsocket

refactor: update photino
2024-06-03 09:44:12 +08:00
Diego2098
251d3b487f release:6.0.2.6
refactor: 打包参数策略修改,防止数据类型用户填写错误时出现未能理解的错误
2024-06-01 12:50:50 +08:00
Diego
e55ec48c7d release:6.0.2.5
refactor: 修改每包读取延迟策略
2024-05-31 17:11:05 +08:00
Diego
7ce2195adb release:6.0.2.4
feat: 添加docker公共镜像
refactor: 首次连接失败opcua时,实时重连
2024-05-31 16:51:30 +08:00
Diego
537b79f1c2 feat: opcua客户端读取数据增加服务端时间属性读取 2024-05-30 16:39:02 +08:00
Diego
e4c4d22f56 docs: 更新pro用户列表 2024-05-30 15:58:32 +08:00
Diego
c4d244398c release: 6.0.2.1
refactor: 更新BootstrapBlazor版本

refactor: opc导入导出去重
2024-05-30 15:40:20 +08:00
Diego
47260cdaf0 feat: 添加ValueTask同步扩展 2024-05-30 14:26:45 +08:00
Diego
7ef13058c7 fix: 修复上一提交导致的偶发空异常 2024-05-30 12:37:04 +08:00
Diego
8066cb1804 feat: 优化变量离线逻辑,当设备无法连接时,直接判断全部变量离线 2024-05-30 12:18:17 +08:00
Diego
c5af6062fa fix: 修复网页重启运行时与冗余网关配置重启运行时逻辑冲突错误 2024-05-30 11:23:14 +08:00
Diego
908a2eba20 feat: 添加等待并比较读取返回值的扩展方法 2024-05-30 10:31:03 +08:00
Diego
6f43957703 other: 更新demo 2024-05-30 09:32:14 +08:00
Diego
897ea28cf4 release: 6.0.1.5
fix: table查询返回IsAdvanceSearch属性错误

refactor: 日志表默认时间倒序显示
2024-05-30 09:30:12 +08:00
Diego
d056ddbff1 fix: table查询返回IsAdvanceSearch属性错误 2024-05-30 09:26:30 +08:00
Diego
f157350059 refactor: 日志表默认时间倒序显示 2024-05-30 08:25:17 +08:00
Diego2098
7e3d99bda3 release: 6.0.1.5
refactor: 部分选项恢复上一版本默认值
2024-05-29 23:08:14 +08:00
Diego2098
c7c53e1d94 release: 6.0.1.4
other: 同步master
2024-05-29 22:15:45 +08:00
Diego
b912ee3f6f refactor: 删除多余代码 2024-05-29 19:09:38 +08:00
Diego2098
06c05ad8e5 feat: 更新6.0.1.3 (#9)
1、更新TouchSocket2.1版本,重构相关代码.

2、优化多处细节,提供运行效率.
2024-05-29 19:03:40 +08:00
Diego
7f411400d5 fix(CacheService): GetOrCreate方法错误触发委托 2024-05-27 18:28:07 +08:00
Diego
f24f234869 fix: 修复因缓存修改导致的插件显示错误 #I9NKA7 2024-05-17 12:28:10 +08:00
Kimdiego2098
4e384e7811 refactor: 按钮disable改为isshow 2024-05-06 15:32:57 +08:00
Kimdiego2098
5143448163 fix: 变量上传属性删除按钮丢失 2024-05-06 14:34:10 +08:00
Diego2098
8e5e9f7cbc build: 更新admin解决方案 2024-05-04 22:30:28 +08:00
Diego2098
5ea7fd01bf release: 6.0.0.13 2024-05-04 22:22:20 +08:00
Kimdiego2098
8f3f6bc774 fix: 修正BusinessBaseWithCacheInterval初始化顺序 2024-04-30 17:55:59 +08:00
Kimdiego2098
7f1524b42f fix: v6代码错漏,间隔上传基类重写BusinessPropertyWithCache属性 2024-04-30 17:35:08 +08:00
Diego2098
4b7db4689d fix: variable实体类读写表达式执行错误 (#8)
* fix: variable实体类读写表达式执行错误

fix: 读写表达式编译错误,缺少using

feat: 增加部分使用demo

* refactor: 整理格式
2024-04-29 16:03:38 +08:00
Diego2098
92831ecb43 refactor: 修改下拉框全选项文本 (#7)
* refactor: 修改下拉框全选项文本

refactor: 修改下拉框全选项文本

fix: i18n(AlarmTopic)中文错误

* build: 更新版本号
2024-04-29 14:50:14 +08:00
Argo-AscioTech
d486f3f306 chore: 删除冗余代码 2024-04-29 03:08:22 +00:00
Diego2098
bfb7468f62 !26 test:回退 'Pull Request !22: fix: 增加 fill 元素保证小屏幕时用户信息靠右'
* 回退 'Pull Request !25 : fix: 增加 fill 元素保证小屏幕时用户信息靠右'
2024-04-29 02:27:13 +00:00
Argo-AscioTech
2e417d41db chore: 删除冗余代码 2024-04-29 02:18:45 +00:00
Argo-AscioTech
b17f68cbfb fix: 增加 fill 元素保证小屏幕时用户信息靠右 2024-04-29 02:18:45 +00:00
Argo-AscioTech
8a22a523d6 doc: 代码格式化 2024-04-29 02:18:45 +00:00
Diego2098
97fe752a4e 回退 'Pull Request !22 : fix: 增加 fill 元素保证小屏幕时用户信息靠右' 2024-04-29 02:13:39 +00:00
Diego2098
cc4ea122a2 !22 fix: 增加 fill 元素保证小屏幕时用户信息靠右
* chore: 删除冗余代码
* fix: 增加 fill 元素保证小屏幕时用户信息靠右
* doc: 代码格式化
2024-04-29 02:05:15 +00:00
Kimdiego2098
db995d29e5 Merge branch 'master' of https://gitee.com/dotnetchina/ThingsGateway 2024-04-29 10:04:07 +08:00
Kimdiego2098
c22dde8008 fix(mqttClient): AlarmTopic upload failure
fix: 报警主题中文名称错误

fix: 报警事件订阅漏写
2024-04-29 10:03:55 +08:00
Diego2098
462d888894 refactor: update appsettings
* refactor: 调整顺序,最大通道数量默认改为10000
2024-04-28 19:22:28 +08:00
Argo Zhang
9311b914ad refactor(AdminTable): update page items from 20 (#4)
* chore: 增加单词拼写字典

* refactor: 更改页码每页最少 20 行数据
2024-04-28 19:13:17 +08:00
Argo Zhang
c5e0488210 feat(AdminTable): add ClientTableName parameter (#5)
* refactor: 代码格式化

* feat: 增加 ClientTableName 参数
2024-04-28 19:13:00 +08:00
Kimdiego2098
f548c27179 refactor: modbusSlave默认启用rpc 2024-04-28 15:20:10 +08:00
Kimdiego2098
1f5f405b52 release: 6.0.0.12 2024-04-28 14:41:20 +08:00
Kimdiego2098
cd923ab838 other: 更新readme 2024-04-28 14:40:56 +08:00
Kimdiego2098
aacdff92d2 docs: 更新文档 2024-04-28 14:25:02 +08:00
Kimdiego2098
32160d388a docs: 迁移文档站点 2024-04-28 13:41:41 +08:00
Kimdiego2098
72e31929eb docs: 迁移文档站点 2024-04-28 13:33:35 +08:00
Kimdiego2098
29014bb40e other: 修改git忽略项 2024-04-28 13:32:24 +08:00
Kimdiego2098
e9d0a65536 fix: 重载插件几率死锁 2024-04-28 11:03:14 +08:00
Kimdiego2098
f7a3b68834 fix: 重载插件几率死锁 2024-04-28 10:13:26 +08:00
Kimdiego2098
dcc9d3b588 docs: 更新文档 2024-04-28 09:54:06 +08:00
Kimdiego2098
b8f6f65943 fix(tcpservice): 客户端断开时不需重置全部同步锁 2024-04-28 09:53:46 +08:00
Kimdiego2098
3dacdda21a build: 更新mapster nuget版本 2024-04-28 09:53:05 +08:00
Diego2098
49b766120f refactor: json序列化忽略null值 2024-04-27 16:19:54 +08:00
Diego2098
2d7e1553f8 refactor: 优化间隔检测 2024-04-26 21:17:27 +08:00
Kimdiego2098
d5d41213b0 release: 6.0.0.11 2024-04-26 18:02:23 +08:00
Kimdiego2098
328df00d2e fix: 通道日志导出时,支持中文名称 2024-04-26 18:01:50 +08:00
Kimdiego2098
e4a5bf8234 feat: 添加批量编辑方法 2024-04-26 17:43:41 +08:00
Kimdiego2098
d6ee0f216c feat: 添加demo 2024-04-26 17:20:00 +08:00
Kimdiego2098
0246ef6b6a feat: 添加demo 2024-04-26 17:03:22 +08:00
Kimdiego2098
7fd40518fd refactor: 内存优化 2024-04-26 12:25:38 +08:00
Kimdiego2098
95eb53edf6 feat: 添加当前进程占用内存显示 2024-04-26 11:22:42 +08:00
Kimdiego2098
4cdf2962cd release: 6.0.0.10 2024-04-26 10:07:55 +08:00
Kimdiego2098
5bf8ccd1fd refactor: 优化网关模块页面的使用体验 2024-04-26 10:06:54 +08:00
Kimdiego2098
dd9fbbcfa7 feat: 添加通用并发锁条件 2024-04-26 09:28:44 +08:00
Diego2098
72d8fd5be0 refactor: 设备状态页面优化 2024-04-25 23:25:52 +08:00
Diego2098
b577229ed3 refactor: 表格去除列宽持久化 2024-04-25 23:20:45 +08:00
Diego2098
4ae870b799 fix: 多页面通知刷新 2024-04-25 23:11:43 +08:00
Diego2098
0590e74b30 feat: SystemTextJson修改NumberHandling选项,支持特殊数字 2024-04-25 22:32:54 +08:00
Diego2098
b9956ba800 fix: v6版本支持系统服务 2024-04-25 19:40:18 +08:00
Kimdiego2098
fef6259d09 release: 6.0.0.9 2024-04-25 18:07:00 +08:00
Kimdiego2098
e24f19e88b docs: 更新文档 2024-04-25 18:06:03 +08:00
Kimdiego2098
cc6de1e71c build: 更新肉夹馍nuget版本 2024-04-25 18:00:19 +08:00
Kimdiego2098
b0240a1c95 refactor: appsettings添加urls配置例子 2024-04-25 17:54:43 +08:00
Kimdiego2098
8acdec333b refactor: 控制台字符logo更新 2024-04-25 17:53:56 +08:00
Kimdiego2098
eafcbb81f9 feat: DEBUG启动自动填充账密 2024-04-25 17:52:44 +08:00
Kimdiego2098
4b083463c8 refactor: gateway命名空间 2024-04-25 15:39:00 +08:00
Kimdiego2098
78e834e04f build: 修改插件类库拷贝脚本 2024-04-25 15:13:26 +08:00
Kimdiego2098
2ed1893620 feat: 添加Description方法 2024-04-25 15:12:36 +08:00
Kimdiego2098
35f188a7dd fix: CSScript using namespace无效 2024-04-25 09:47:46 +08:00
Kimdiego2098
07f577a9dd release: 6.0.0.8 2024-04-25 09:26:08 +08:00
Kimdiego2098
25c72b50c0 build: 类库net版本降至net6 2024-04-25 09:25:47 +08:00
Kimdiego2098
e07346ebea other: update readme 2024-04-24 15:00:07 +08:00
Diego2098
699b466291 other: git忽略文件 2024-04-23 21:44:59 +08:00
Diego2098
f0f24ff96f release: 6.0.0.7 2024-04-23 21:21:58 +08:00
Diego2098
1113997c71 fix: 修复类似400001.0位格式读取打包错误 2024-04-23 21:21:40 +08:00
Kimdiego2098
487fb6e5c9 release: 6.0.0.6 2024-04-23 18:34:35 +08:00
Kimdiego2098
62908a323c fix: v6版本modbusRtu bodyLength错误 2024-04-23 18:33:41 +08:00
Kimdiego2098
021131271a other: modify Pro ProjectReference Include 2024-04-23 18:08:21 +08:00
Kimdiego2098
c20fa4dbd2 fix: VersionService取消Assembly.Location用法 2024-04-23 16:54:38 +08:00
Kimdiego2098
b1826678da release: 6.0.0.5 2024-04-23 12:12:17 +08:00
Kimdiego2098
1630338f4e refactor: 修改条件编译 2024-04-23 12:11:53 +08:00
Kimdiego2098
78af3d979c fix: 菜单curd
1、创建模块后,切换模块列表不能马上显示
2、创建根菜单时,不填写路径会出错
2024-04-23 12:08:40 +08:00
Kimdiego2098
8346dfb1f5 perf: 添加ConfigureAwait(false) 2024-04-23 11:33:26 +08:00
Kimdiego2098
5ecb4e4fe4 refactor(VerificatInfoCacheService): DEBUG模式下,实时持久化登录凭据 2024-04-23 08:45:16 +08:00
Kimdiego2098
ec9ff23b23 refactor(DeviceStatusPage): 设备页面筛选下拉框null值显示为none 2024-04-23 08:37:27 +08:00
Diego2098
149e9931e7 refactor: 修改user默认模块种子数据 2024-04-23 00:02:11 +08:00
Diego2098
58b62094bd release: 6.0.0.4 2024-04-22 23:57:51 +08:00
Diego2098
d357074ad4 refactor: 修改excel导出的字段排序 2024-04-22 23:57:14 +08:00
Diego2098
d9bacc129b feat: 业务缓存设备基类添加属性(缓存文件最大长度) 2024-04-22 23:31:48 +08:00
Diego2098
28d869b099 refactor: excel导入时,按行号排序 2024-04-22 23:25:40 +08:00
Kimdiego2098
d04e87718a release: 6.0.0.3 2024-04-22 18:31:41 +08:00
Kimdiego2098
8d81bf60c9 feat(dlt645): 修改FE前导符为自定义格式 2024-04-22 18:30:47 +08:00
Kimdiego2098
4fe9094ff7 refactor: trace日志构建前设置条件 2024-04-22 17:41:22 +08:00
Kimdiego2098
4cfde45755 refactor: 修改单线程读写时的锁范围 2024-04-22 17:12:16 +08:00
Kimdiego2098
c28844dbeb refactor: 迁移读写方法到基础类库 2024-04-22 16:59:14 +08:00
Kimdiego2098
837ea7c8d6 refactor: 迁移Dtu读写方法到基础类库 2024-04-22 14:42:27 +08:00
Kimdiego2098
6c85ac8827 refactor: 补充nuget发布类库 2024-04-22 14:27:53 +08:00
Kimdiego2098
c8eb8bf35d release: 6.0.0.2 2024-04-22 14:22:37 +08:00
Kimdiego2098
0f6cbddd57 refactor: 迁移DtuPlugin到共用类库 2024-04-22 14:18:57 +08:00
Kimdiego2098
530b4755bf refactor: 底层驱动类库升级net版本,保留net462以及netstandard2.0 2024-04-22 13:58:14 +08:00
Kimdiego2098
679395b3fe refactor: modbusMaster 添加 分部定义 2024-04-22 13:56:45 +08:00
Kimdiego2098
9293442836 fix: editForm不应该直接修改缓存 2024-04-22 10:33:51 +08:00
Kimdiego2098
4841b412f3 feat: v6网关模块添加按钮权限 2024-04-22 10:08:57 +08:00
Kimdiego2098
f03575ad89 fix: 角色授权流程错误 2024-04-22 10:07:49 +08:00
Diego2098
e0e5428ebd feat: 添加业务设备离线缓存 2024-04-21 00:06:32 +08:00
Diego2098
015f7edae2 style: 表格列宽调整 2024-04-20 23:14:47 +08:00
Diego2098
d5414f5d91 !20 fix: 修复表格不对齐问题
* fix: 修复表格不对齐问题 , thanks to @Argo
2024-04-20 14:59:00 +00:00
Kimdiego2098
4bc3512d42 按钮授权初始化授权列表错误 2024-04-19 12:50:48 +08:00
Kimdiego2098
4c305994ca 添加多语言资源 2024-04-19 11:39:10 +08:00
Kimdiego2098
788e2cba04 修改变量页面默认排序 2024-04-18 16:52:19 +08:00
Kimdiego2098
b79b79970e 实时数据页面添加关键词搜索 2024-04-18 16:18:53 +08:00
Kimdiego2098
8b0f4de516 更新 2024-04-18 16:15:54 +08:00
Kimdiego2098
a17000ad6d 修改判断值变化方法 2024-04-18 16:15:53 +08:00
Kimdiego2098
c9f63c58df 修改项目文件 2024-04-18 16:01:38 +08:00
Kimdiego2098
c311b1c706 更新git文件 2024-04-18 14:36:58 +08:00
Kimdiego2098
072451afae 删除多余重写属性 2024-04-18 11:06:00 +08:00
Kimdiego2098
7349793463 更新项目文件 2024-04-18 10:21:31 +08:00
Kimdiego2098
c0144eab86 调整项目文件 2024-04-18 10:18:09 +08:00
Kimdiego2098
ba79b25944 VerificatInfo删除不必要的属性 2024-04-17 18:56:20 +08:00
Kimdiego2098
3fb34b12a0 更新部署文件 2024-04-17 15:00:09 +08:00
Kimdiego2098
b6c17e76c2 更新部署文件 2024-04-17 14:57:01 +08:00
Kimdiego2098
1201f20d79 删除不必要的文件 2024-04-17 12:30:44 +08:00
Kimdiego2098
98ae8e692e 添加文档 2024-04-17 12:20:01 +08:00
Kimdiego2098
8342dbff4e 更新6.0版本 2024-04-17 12:18:00 +08:00
Kimdiego2098
a22aa0f9a7 Merge branch 'dev' into temp 2024-04-17 12:15:23 +08:00
Kimdiego2098
b49d221ec1 准备合并dev分支 2024-04-17 12:14:05 +08:00
Kimdiego2098
f1be315147 更新插件 2024-04-17 11:32:36 +08:00
Kimdiego2098
8aaac2a3d4 更新插件UI 2024-04-17 10:55:46 +08:00
Kimdiego2098
bd07d30e47 更新插件 2024-04-17 10:51:42 +08:00
Kimdiego2098
54e103f00f 更新插件 2024-04-17 10:32:31 +08:00
Kimdiego2098
5404d8f7ab 更新插件 2024-04-17 10:21:45 +08:00
Diego2098
1364e02c67 更新插件 2024-04-17 00:42:25 +08:00
Diego2098
b4818e2f9a 修复 变量页面 自动刷新时,每页条数会恢复初始值 的问题 2024-04-16 22:54:05 +08:00
Diego2098
734cf57d4a 更新插件 2024-04-16 21:22:49 +08:00
Diego2098
9236610ec1 更新插件 2024-04-16 21:12:38 +08:00
Diego2098
c33828a5d9 更新插件 2024-04-16 21:11:42 +08:00
Diego2098
faadb03e46 !18 更新插件
Merge pull request !18 from BAD MAN/dev_20240416
2024-04-16 10:11:54 +00:00
allrightsreserved
3a0c4c51d2 Merge branch 'dev' of https://gitee.com/dancingqueen/ThingsGateway into dev 2024-04-16 16:02:40 +08:00
Kimdiego2098
6c28c2b91e 更新OPCUA OPCDA 2024-04-16 16:02:26 +08:00
Kimdiego2098
5226df6194 更新readme 2024-04-16 14:45:15 +08:00
Kimdiego2098
1ad23a3cbb 更新依赖 2024-04-16 14:29:13 +08:00
Kimdiego2098
c4149ca304 修改变量服务 导出方法名称 2024-04-16 14:26:19 +08:00
Kimdiego2098
68b02fe950 优化导入导出,支持属性验证 2024-04-16 14:02:41 +08:00
Kimdiego2098
d9408523a5 更新插件 2024-04-16 11:12:28 +08:00
Diego2098
40ad0f063a 更新版本 2024-04-15 23:31:57 +08:00
Diego2098
40d85e8926 恢复部分代码:tcpclientbase;IDBHistoryAlarm;sqlhisalarm 2024-04-15 23:31:43 +08:00
Diego2098
e655f719e6 !16 为历史报警增加外部访问接口,linux下隐藏 OPCDA 调试选项,TgTcpClientBase.cs 增加try catch,防止出现设备无法连接时visualstudio 抛出异常“在一个非嵌套字上尝试了一个操作”
Merge pull request !16 from BAD MAN/master
2024-04-15 15:26:40 +00:00
BAD MAN
ede0ea02c5 Merge branch 'master' of https://gitee.com/dancingqueen/ThingsGateway 2024-04-15 22:46:37 +08:00
Diego2098
e579575b21 为 history alarm 增加 GetDBHistoryAlarmsAsync 和 GetDBHistoryAlarmPagesAsync 接口,方便外部访问历史报警;增加try catch,防止出现设备无法连接时visualstudio 抛出异常“在一个非嵌套字上尝试了一个操作”;linux 环境下 OPCDA 不显示 2024-04-15 22:46:35 +08:00
Kimdiego2098
06ffcc9fdf 更新插件 2024-04-15 18:14:23 +08:00
Kimdiego2098
774d03e510 更新插件 2024-04-15 17:39:02 +08:00
Kimdiego2098
adcac9dfe6 添加任务最大数量限制 2024-04-15 16:50:06 +08:00
Kimdiego2098
399e14c70c 去除头像种子数据 2024-04-15 14:25:35 +08:00
Kimdiego2098
ec8b51033b signalr dispose 忽略exception 2024-04-15 14:23:29 +08:00
Kimdiego2098
ca5d167b6a 更新插件 2024-04-15 13:57:05 +08:00
Kimdiego2098
fcd1b001d1 更新readme 2024-04-15 13:34:32 +08:00
Kimdiego2098
1cabbefe04 更新插件 2024-04-15 13:31:28 +08:00
Kimdiego2098
ecefe22c95 更新插件 2024-04-15 13:06:43 +08:00
Kimdiego2098
64db77b9a2 更新插件 2024-04-15 13:03:32 +08:00
Kimdiego2098
19d7360ad5 更新插件 2024-04-15 13:01:46 +08:00
Kimdiego2098
2f014cd827 更新插件 2024-04-15 12:46:17 +08:00
Kimdiego2098
7fb84205d9 更新插件 2024-04-15 12:38:07 +08:00
Kimdiego2098
47e1127c5f 更新插件 2024-04-15 12:21:16 +08:00
Kimdiego2098
e036b59306 更新插件 2024-04-15 12:04:34 +08:00
Kimdiego2098
f4904c3b53 添加插件 2024-04-15 11:31:13 +08:00
Diego2098
3002a63ba5 更新BootstrapBlazor版本 2024-04-14 23:38:47 +08:00
Diego2098
b69717e6c3 更新版本 2024-04-14 23:37:05 +08:00
Diego2098
d07962953f 修改注释 2024-04-14 23:16:30 +08:00
Diego2098
857cf0d21e delay策略更改 2024-04-14 23:10:37 +08:00
Diego2098
5f08c2615d 修复缓存类型转换错误 2024-04-14 23:05:21 +08:00
Diego2098
e87428ef33 更新6.0版本 2024-04-14 22:51:56 +08:00
Kimdiego2098
03fd54fe70 td时序库上传时间不应作为主键 2024-04-12 16:57:09 +08:00
Kimdiego2098
086c2c8253 取消ParallelForEachAsync方法 2024-04-11 14:54:54 +08:00
Kimdiego2098
05c19a32ea s7 修改解析 返回码 顺序 2024-04-10 15:20:18 +08:00
Kimdiego2098
99d174906a 更新版本 2024-04-08 21:48:50 +08:00
Kimdiego2098
82e30a326a 修复上个版本 modbus驱动打包变量 代码错误 2024-04-08 21:46:47 +08:00
Diego2098
2963a9cdca !14 获取历史数据之前检查历史数据库是否连接成功
Merge pull request !14 from BAD MAN/master
2024-04-05 13:53:55 +00:00
BAD MAN
288da75b2b Merge branch 'master' of https://gitee.com/dancingqueen/ThingsGateway 2024-04-05 21:05:57 +08:00
Kimdiego2098
0943a496dd 获取历史数据之前检查历史数据库是否连接成功更新版本 2024-04-05 21:04:47 +08:00
Kimdiego2098
e5dd7cc2fa 强推 2024-04-03 19:01:57 +08:00
Kimdiego2098
358836ef9f 更新版本 2024-04-01 10:00:00 +08:00
Kimdiego2098
aab4fac6c5 modbus DTU模式 修复socketid不同时的变量打包方式,以及心跳注册包等不再影响正常数据收发 2024-04-01 09:59:48 +08:00
Kimdiego2098
525540b603 S7打包方法内变量名称修正 2024-03-31 11:36:56 +08:00
Kimdiego2098
b30eeb4694 mchart 更新 2024-03-30 22:03:19 +08:00
Kimdiego2098
3faf0aa2fc 更新版本 2024-03-29 23:23:28 +08:00
Kimdiego2098
fd728dec5d 更新依赖包 2024-03-29 23:23:15 +08:00
Kimdiego2098
08b14b72d4 读写表达式更换为CS-Script实现 2024-03-29 23:15:52 +08:00
Diego2098
de2e005abf 更新版本 2024-03-27 22:17:55 +08:00
Diego2098
0fc75239a6 添加PreEvaluateVariableEnable配置,读取表达式/写入表达式中可以用变量名称获取全局变量的值,因性能问题默认关闭 2024-03-27 22:15:41 +08:00
Kimdiego2098
390fe30a0d 更新版本 2024-03-26 15:02:05 +08:00
Kimdiego2098
633f49fcd2 opcda导出节点excel表时通道名称错误 2024-03-26 15:01:57 +08:00
Kimdiego2098
30c0ba93b9 修复 s7 通过.n的方式读取字节中布尔量时,如果变量地址带有分号时出现的分包错误 2024-03-25 13:28:58 +08:00
Diego2098
e935fb9621 修正数组类型判断值变化方式 2024-03-24 23:08:55 +08:00
Kimdiego2098
5ce8bb1d08 修复首页刷新线程返回时,option还未赋值成功导致报错问题 2024-03-22 12:19:55 +08:00
Kimdiego2098
1acd12980a 调试页面显示异常堆栈 2024-03-16 16:59:12 +08:00
Kimdiego2098
683235dd8a 发布构建脚本重复错误 2024-03-15 10:53:13 +08:00
Kimdiego2098
65fe183ad4 冗余配置文件丢失时不再报空指针错误 2024-03-15 09:55:34 +08:00
Kimdiego2098
f39d5d355c 更新版本 2024-03-13 10:33:15 +08:00
Kimdiego2098
eccc8e0ff0 更新sqldb,删除不需要的转换 2024-03-13 10:25:26 +08:00
Kimdiego2098
dd4d8e775c 更新版本 2024-03-11 16:39:43 +08:00
Kimdiego2098
7a7f857b2f startUp调整注入顺序 2024-03-11 16:39:00 +08:00
Diego2098
10882b7d93 规范代码 2024-03-10 14:29:33 +08:00
Diego2098
e669b81005 发布构建时,默认删除PDB文件 2024-03-10 13:05:25 +08:00
Diego2098
28a81d9539 更新版本 2024-03-10 11:47:32 +08:00
Diego2098
6bf5e4a6b8 修改设备/变量 初始时间为unix 2024-03-10 11:46:05 +08:00
Diego2098
a51eee93f4 更新版本 2024-03-09 16:20:17 +08:00
Diego2098
bece2555c2 自动刷新图标时,启用echarts组件合并模式 2024-03-09 16:13:02 +08:00
Diego2098
d98d405009 更新touchsocket依赖正式版本 2024-03-09 15:19:19 +08:00
Diego2098
8d0881632c 业务设备初始默认状态为成功 2024-03-09 13:37:17 +08:00
Diego2098
e8b81da897 sqldb按选项建表 2024-03-09 13:19:35 +08:00
Diego2098
acf4fbf750 生产环境打印错误sql 2024-03-09 13:16:20 +08:00
Diego2098
b4f1921d33 更新版本 2024-03-09 11:32:26 +08:00
Diego2098
94b4816f53 修复sqldb查询接口错误,增加历史表-变量id字段 2024-03-09 11:29:04 +08:00
Kimdiego2098
b6ddafde3e 更新版本 2024-03-08 17:31:46 +08:00
Kimdiego2098
b01036818f 整理代码 2024-03-08 16:31:33 +08:00
Kimdiego2098
ad7da1a0c3 历史存储插件增加接口,增加历史查询方法 2024-03-08 16:27:45 +08:00
Kimdiego2098
1e0818d9d9 变量导入时,新增部分按行号排序 2024-03-08 16:27:19 +08:00
Kimdiego2098
a4686f01c3 更新touchsocket依赖 2024-03-08 13:22:40 +08:00
Kimdiego2098
84d76f9aab 更新版本 2024-03-07 19:23:05 +08:00
Kimdiego2098
b90bf5eb86 Revert "回退sqlsugar版本(sqldb分表问题)"
This reverts commit fe258f3fe5.
2024-03-07 18:47:04 +08:00
Kimdiego2098
fe258f3fe5 回退sqlsugar版本(sqldb分表问题) 2024-03-07 18:43:37 +08:00
Kimdiego2098
d339494594 更新版本 2024-03-07 15:03:17 +08:00
Kimdiego2098
adfaf13055 更新版本 2024-03-07 12:21:12 +08:00
Kimdiego2098
8abfeb5923 修复 sqldb oracle11 标识符过长 2024-03-07 12:11:20 +08:00
Kimdiego2098
c1a027a771 更新版本 2024-03-06 17:40:21 +08:00
Kimdiego2098
5f3094d79b 恢复误删代码 2024-03-06 12:49:58 +08:00
Kimdiego2098
925b81aca8 更新版本 2024-03-06 12:32:08 +08:00
Kimdiego2098
c0c8437966 OpcDa添加是否使用服务端时间选项 2024-03-06 12:31:43 +08:00
Kimdiego2098
1d27b2fc4a 表达式运行添加linq扩展方法,长度限制1000 2024-03-06 10:57:11 +08:00
Kimdiego2098
5da43e7808 更新版本 2024-03-05 16:55:12 +08:00
Kimdiego2098
5edbb558ae 更新版本 2024-03-04 13:12:47 +08:00
Kimdiego2098
7347cc1df2 json解析布尔值时,特殊忽略大小写 2024-03-04 12:43:47 +08:00
Kimdiego2098
20cac11b2a 磁盘使用率逻辑,缓存删除日志修改 2024-03-04 10:59:49 +08:00
Kimdiego2098
75c35c4ff8 更新版本 2024-03-04 00:10:43 +08:00
Diego2098
9d573512d0 更新版本 2024-03-03 23:49:47 +08:00
Diego2098
7921365853 更新版本 2024-03-03 23:03:02 +08:00
Diego2098
43263fd3b9 分离Variable类库 2024-03-03 17:43:37 +08:00
Diego2098
59042a5ead 修改echart背景颜色,去除多余的字体颜色 2024-03-02 13:39:17 +08:00
Kimdiego2098
91b14de807 文件编码覆盖 2024-03-01 18:54:36 +08:00
Kimdiego2098
81fab2be08 更新依赖包 2024-03-01 13:36:20 +08:00
Kimdiego2098
165b742782 更新版本 2024-03-01 13:33:49 +08:00
Kimdiego2098
76fef9c807 优化业务插件缓存逻辑 2024-03-01 13:33:43 +08:00
Kimdiego2098
e69ea0b9dc 更新版本 2024-02-28 17:41:02 +08:00
Kimdiego2098
98d3183f2b 修复sqldb历史表动态分表名称查询失效 2024-02-28 17:40:51 +08:00
Kimdiego2098
a29390a951 更新依赖包 2024-02-28 17:13:42 +08:00
Kimdiego2098
6291ce8617 modbusSlave运行时检查恢复启动 2024-02-28 17:08:31 +08:00
Kimdiego2098
c76b1b50a0 更新版本 2024-02-28 16:12:55 +08:00
Kimdiego2098
cc45e2aec0 更新网关双冗余 2024-02-28 16:12:38 +08:00
Kimdiego2098
17efebb8e8 更新版本 2024-02-28 16:05:50 +08:00
Kimdiego2098
5c94c733ee 整理代码 2024-02-28 16:05:18 +08:00
Kimdiego2098
156b89dd9c 更新双网关冗余 2024-02-28 16:04:04 +08:00
Kimdiego2098
34ba9f67e7 更新双网关冗余,sqldb支持历史表名称更改,更改为按周分表 2024-02-28 15:53:46 +08:00
Kimdiego2098
5ddaa6b872 双网关冗余(未完成) 2024-02-27 17:50:23 +08:00
Kimdiego2098
9043fa7f56 整理 2024-02-27 16:58:01 +08:00
Kimdiego2098
4c8e487dc9 双网关冗余(未完成) 2024-02-27 13:59:12 +08:00
Kimdiego2098
d3b87179aa 双网关冗余(未完成) 2024-02-26 19:49:19 +08:00
Kimdiego2098
2166de8331 修改Windows下UDP连接被重置错误10054代码 2024-02-26 12:57:48 +08:00
Diego2098
f0bc3f001f opcda nuget包不包含symbols 2024-02-25 15:31:48 +08:00
Diego2098
50448e7085 nuget包不需要发布源生成库 2024-02-25 15:11:15 +08:00
Diego2098
cd1d42353e 更新版本 2024-02-25 15:01:06 +08:00
Diego2098
5e588bf737 添加null判断 2024-02-25 14:59:17 +08:00
Kimdiego2098
7ff777d178 更新版本 2024-02-25 14:48:23 +08:00
Kimdiego2098
861621189a 底层变量特性实体支持数组 2024-02-25 14:39:08 +08:00
Diego2098
dcc00e08fd 整理代码 2024-02-24 23:32:51 +08:00
Diego2098
a1b8a47d4b 更新示例 2024-02-24 22:43:49 +08:00
Diego2098
1fd6b5e239 更改动态变量类缓存 2024-02-24 21:45:59 +08:00
Diego2098
f91e45bf44 整理代码 2024-02-24 18:42:45 +08:00
Kimdiego2098
0675a45592 更新版本 2024-02-24 18:23:41 +08:00
Kimdiego2098
0c7c6ae451 s7协议首次CR请求时,判断方式错误 2024-02-24 18:23:10 +08:00
Diego2098
cf089e8c4c 更新版本 2024-02-24 17:19:09 +08:00
Diego2098
90928ac679 更新版本 2024-02-24 17:14:57 +08:00
Diego2098
3bbcf71784 整理代码 2024-02-24 17:12:23 +08:00
Diego2098
222734775d 整理代码 2024-02-24 16:32:47 +08:00
Diego2098
f23ee7a6e0 整理代码 2024-02-24 16:08:37 +08:00
Diego2098
5b075aa6d5 更新底层变量类,添加源代码生成方法 2024-02-24 14:39:53 +08:00
Kimdiego2098
80cd6b693e 发行版本5.0.1.0 2024-02-23 13:09:25 +08:00
Kimdiego2098
04721a12b1 发行版本5.0.1.0 2024-02-23 13:03:53 +08:00
Kimdiego2098
64e22c0e46 取消默认PublishReadyToRun 2024-02-23 13:03:46 +08:00
Kimdiego2098
d5a70c5b08 Revert "发行版本5.0.1"
This reverts commit eaac7b6bcf.
2024-02-23 13:03:12 +08:00
Kimdiego2098
eaac7b6bcf 发行版本5.0.1 2024-02-23 12:58:25 +08:00
Kimdiego2098
b062a491cd 调整代码 2024-02-23 12:36:28 +08:00
Kimdiego2098
1e868517bb 默认启用PublishReadyToRun 2024-02-23 11:02:56 +08:00
Kimdiego2098
7b2a93a2d7 更新版本 2024-02-22 18:13:10 +08:00
Kimdiego2098
f57f0447c6 完善modbus写入保持寄存器某一位,比如400001.0的功能 2024-02-22 18:12:58 +08:00
Kimdiego2098
7126ff881e 更新版本 2024-02-22 17:52:32 +08:00
Kimdiego2098
e28da4b165 modbusTcp返回错误码时没有验证头部id 2024-02-22 17:52:20 +08:00
Kimdiego2098
92d9b91f7c 更新依赖包 2024-02-22 17:31:27 +08:00
Kimdiego2098
149c4a30c0 写入表达式支持json数组 2024-02-21 14:50:21 +08:00
Kimdiego2098
84e62062ec 表达式转换支持Json 2024-02-21 13:35:41 +08:00
Kimdiego2098
dc1fb74850 更新readme 2024-02-21 11:33:00 +08:00
Kimdiego2098
00c6010789 更新readme 2024-02-21 11:07:00 +08:00
Kimdiego2098
5d35c058e0 更新readme 2024-02-21 11:05:54 +08:00
Kimdiego2098
1522a521f6 更新readme 2024-02-21 10:59:53 +08:00
Kimdiego2098
6e11b885f9 同步代码 2024-02-21 09:38:34 +08:00
Kimdiego2098
442ae6e0e8 插件初始化失败时设置线程超时 2024-02-20 12:05:02 +08:00
Kimdiego2098
6b49e83464 opcua重连周期改为10s 2024-02-19 17:09:14 +08:00
Kimdiego2098
f1ecf13fe1 更新版本 2024-02-19 14:31:25 +08:00
Kimdiego2098
83d1c8582b 整理signalR代码 2024-02-19 14:31:14 +08:00
Kimdiego2098
179f6cd454 程序启动时清除在线用户统计 2024-02-19 13:42:28 +08:00
Kimdiego2098
91b1474ff0 更新文档 2024-02-19 09:44:55 +08:00
Kimdiego2098
15aabc88a1 更新文档 2024-02-18 18:26:46 +08:00
Kimdiego2098
afc0d3017d 修复等待池超限后没有恢复初始值的问题 2024-02-18 17:43:44 +08:00
Kimdiego2098
9e0b1dc8aa 更新文档 2024-02-18 16:05:18 +08:00
Kimdiego2098
55b482fd26 更新版本 2024-02-18 15:23:32 +08:00
Kimdiego2098
4f9c9a6566 发送方法更改为异步 2024-02-18 15:21:57 +08:00
Kimdiego2098
4725120ee9 添加历史cpu曲线过期时间 2024-02-18 15:04:37 +08:00
Kimdiego2098
a288f50fbb 演示环境默认填写帐户密码 2024-02-18 14:19:37 +08:00
Kimdiego2098
09cf2560a4 更新版本 2024-02-18 12:13:03 +08:00
Kimdiego2098
16353de7b1 修复LiteDB中的表达式缓存导致的内存泄露 2024-02-18 12:12:25 +08:00
Kimdiego2098
eb5834cb5c 更新版本 2024-02-18 10:00:40 +08:00
Kimdiego2098
3ef5736aed 更新依赖 2024-02-18 09:59:11 +08:00
Kimdiego2098
d2e7b77d16 Demo环境不再允许修改个人密码 2024-02-18 09:58:53 +08:00
Kimdiego2098
8f794bce75 更新文档 2024-02-18 09:35:24 +08:00
Kimdiego2098
c33196a50a 更新版本 2024-02-04 09:12:43 +08:00
Kimdiego2098
6e8b5b431f 更改种子数据解析方法 2024-02-04 09:09:29 +08:00
Kimdiego2098
8ca3ecf17f 更新版本 2024-02-02 15:44:12 +08:00
Kimdiego2098
91f7db59ea 更新依赖包 2024-02-02 15:44:02 +08:00
Kimdiego2098
a0b4501352 更新版本 2024-02-02 15:40:08 +08:00
Kimdiego2098
345047820a 更新依赖 2024-02-02 15:39:54 +08:00
Kimdiego2098
ac3525a953 更新版本 2024-02-02 15:15:32 +08:00
Kimdiego2098
c8c3f5b134 更新构建脚本 2024-02-02 15:14:37 +08:00
Kimdiego2098
51319c0718 mqttClient每次发布都作为遗嘱消息 2024-02-02 14:38:24 +08:00
Kimdiego2098
43399b8b47 mqttClient连接失败时缓存数据 2024-02-02 14:36:49 +08:00
Kimdiego2098
a6596042b7 修复上传业务缓存删除逻辑 2024-02-02 14:26:00 +08:00
Kimdiego2098
23ae85fc9c Revert "修复上传业务缓存删除逻辑"
This reverts commit 2da54862f1.
2024-02-02 14:25:21 +08:00
Kimdiego2098
2da54862f1 修复上传业务缓存删除逻辑 2024-02-02 14:24:49 +08:00
Kimdiego2098
f272fb0559 更新版本 2024-02-02 13:00:04 +08:00
Kimdiego2098
bd04e33586 底层通道设备列表更换为线程安全列表 2024-02-02 12:29:19 +08:00
Kimdiego2098
b09b9752ca mqttServer修复客户端连接时,发送初始数据分组错误 2024-02-02 12:16:43 +08:00
Kimdiego2098
a810a48158 更新dockerfile 2024-02-02 08:40:10 +08:00
Kimdiego2098
b4f5792aa8 串口流BeginRead更换为ReadAsync 2024-02-01 16:50:01 +08:00
Kimdiego2098
fdf0330b4f 更新版本 2024-02-01 12:20:11 +08:00
Kimdiego2098
ca73743082 调整服务启动顺序 2024-02-01 12:19:44 +08:00
Kimdiego2098
df0cde2cfd 定长字符串写入时,长度不足也覆盖剩余字节 2024-01-30 17:37:44 +08:00
Kimdiego2098
5a8421e807 更新版本 2024-01-30 14:33:57 +08:00
Kimdiego2098
025ac95d81 修复数据转换无默认构造导致的反序列化错误 2024-01-30 14:27:33 +08:00
Kimdiego2098
71b5824fdc 添加重启事件 2024-01-30 13:52:17 +08:00
Kimdiego2098
1a907c0be7 更新版本 2024-01-30 12:22:43 +08:00
Kimdiego2098
1635cabd32 更新版本 2024-01-30 11:56:58 +08:00
Kimdiego2098
27946a5b0f 调整日志文件路径 2024-01-30 11:56:26 +08:00
Kimdiego2098
e141822fd0 调整sqlsugar 2024-01-30 10:54:35 +08:00
Kimdiego2098
6326828a02 调整依赖 2024-01-30 10:16:35 +08:00
Kimdiego2098
96b5362491 添加modbus的字符串按字反转配置 2024-01-30 10:04:38 +08:00
Kimdiego2098
8ab91a51bc 调整瞬态服务构造 2024-01-30 09:42:15 +08:00
Kimdiego2098
35e7e7af18 更新版本 2024-01-29 18:28:15 +08:00
Kimdiego2098
0e248a7302 更新依赖包 2024-01-29 18:27:58 +08:00
Kimdiego2098
d5ce4d6600 调整代码 2024-01-29 17:55:40 +08:00
Kimdiego2098
2365bb5e87 sqlsugar版本固定5.1.4.122 2024-01-29 16:28:55 +08:00
Kimdiego2098
2230216a7e 调整代码 2024-01-29 14:32:33 +08:00
Kimdiego2098
54f896d25f 调整Task.Delay 2024-01-29 11:28:23 +08:00
Kimdiego2098
e47d239caf 调整种子数据 2024-01-29 09:13:49 +08:00
Kimdiego2098
ac259958d7 更新文档 2024-01-29 08:45:10 +08:00
Diego2098
0505ad88a6 修复mqttRpc写入数组时,字符串解析错误问题 2024-01-27 12:40:48 +08:00
Diego2098
b323de3383 添加属性默认值 2024-01-27 09:57:06 +08:00
Kimdiego2098
c0e023324b 更新文档 2024-01-26 11:51:35 +08:00
Kimdiego2098
495806d5e3 文档添加演示站点 2024-01-26 11:09:13 +08:00
Kimdiego2098
3a9f745a2d 更新Dlt645 nuget包文档 2024-01-26 10:43:19 +08:00
Kimdiego2098
7b15d114a3 适配窗体大小 2024-01-26 10:01:47 +08:00
Kimdiego2098
6ac0f72169 默认开启标签页缓存 2024-01-26 08:52:02 +08:00
Kimdiego2098
ff68030231 添加可空判断方法 2024-01-25 14:02:37 +08:00
Kimdiego2098
d34361b6dd 更新文档 2024-01-25 11:03:46 +08:00
Kimdiego2098
56c6ebe523 修复事务锁异常导致sqlite lock 2024-01-25 11:03:39 +08:00
Kimdiego2098
2c6d2e0eb4 更新文档 2024-01-24 16:56:01 +08:00
Kimdiego2098
8e64196a8f 去除MqttRpc主题的规则限制 2024-01-24 16:51:10 +08:00
Kimdiego2098
926d5faf21 更新文档 2024-01-24 16:15:33 +08:00
Kimdiego2098
18bad2af25 调整MqttRpc提示 2024-01-24 16:15:26 +08:00
Kimdiego2098
6be4dc4aac 更新版本 2024-01-24 15:14:27 +08:00
Kimdiego2098
6398a59dda 修复设备删除后,变量动态属性错误的问题 2024-01-24 15:06:36 +08:00
Kimdiego2098
48158b1db6 更新文档 2024-01-24 14:46:49 +08:00
Kimdiego2098
47fe519e54 更新文档 2024-01-24 14:36:22 +08:00
Kimdiego2098
7e06f19bbc 更新5.0.0.5 2024-01-24 12:19:29 +08:00
Kimdiego2098
0b66c1f0d6 添加using 2024-01-24 11:15:32 +08:00
Kimdiego2098
ff2742ffd8 删除字节转换类的copynew方法 2024-01-24 10:11:10 +08:00
Kimdiego2098
70c2992a5f 调整命名空间 2024-01-24 09:45:13 +08:00
Kimdiego2098
4ac4ee6874 调整命名空间 2024-01-24 08:50:53 +08:00
Kimdiego2098
865164a404 删除多余代码 2024-01-24 08:49:01 +08:00
Diego2098
f9c8069ab2 调整DTU配置,增加心跳回应 2024-01-23 21:32:47 +08:00
Diego2098
2fbf5140e5 调整DTU配置,增加心跳回应 2024-01-23 21:09:57 +08:00
Kimdiego2098
0126f8144a 调整mqtt在线状态判断 2024-01-23 18:06:22 +08:00
Kimdiego2098
71383d7482 调整日志读取策略 2024-01-23 17:23:36 +08:00
Kimdiego2098
4d3bfc5f42 调整封装方法 2024-01-23 15:51:08 +08:00
Kimdiego2098
c173d217de 添加重启后台事件 2024-01-23 08:50:08 +08:00
Kimdiego2098
d2da9a039f 更新5.0.0.4 2024-01-22 23:13:02 +08:00
Kimdiego2098
c915edd458 S7握手失败时直接关闭连接 2024-01-22 23:03:03 +08:00
Kimdiego2098
504948452e 更新TD引用 2024-01-22 22:12:17 +08:00
Kimdiego2098
3daa6c7a54 修复空指针错误 2024-01-22 21:53:59 +08:00
Kimdiego2098
10cd1580a5 调整命名 2024-01-22 21:13:59 +08:00
Kimdiego2098
5b0876e106 修复缓存item没有默认构造函数导致的錯誤 2024-01-22 11:38:16 +08:00
Kimdiego2098
cfcdeaff01 调整常量位置 2024-01-22 11:24:37 +08:00
Kimdiego2098
7c34f233fd 更新文档 2024-01-22 09:50:38 +08:00
Kimdiego2098
686146a7d9 修复导入插件错误 2024-01-22 08:38:48 +08:00
Kimdiego2098
44732d5977 更新5.0.0.3 2024-01-21 22:48:30 +08:00
Kimdiego2098
05c3794cf7 修复属性为可空类型是,excek导入失败的问题 2024-01-21 22:48:04 +08:00
Kimdiego2098
f0431a504a 更新版本5.0.0.2 2024-01-21 21:18:36 +08:00
Kimdiego2098
eccec85ea6 调整解析寄存器地址规则 2024-01-21 21:17:07 +08:00
Kimdiego2098
16ff538804 修复特殊方法执行主体错误 2024-01-21 20:42:20 +08:00
Kimdiego2098
f81e07eb6f 修复特殊方法检测为null的问题 2024-01-21 20:19:44 +08:00
Kimdiego2098
1cbd41ad87 更新文档 2024-01-21 16:50:16 +08:00
Kimdiego2098
d8567b8427 断开连接时 退出 等待数据返回 2024-01-21 16:43:10 +08:00
Kimdiego2098
afe6a1923b 断开连接时 退出 等待数据返回 2024-01-21 16:42:30 +08:00
Kimdiego2098
0f60f4754f 更新文档 2024-01-21 16:42:03 +08:00
Kimdiego2098
7e988d0401 更新文档 2024-01-21 16:08:23 +08:00
Kimdiego2098
d85813c229 更新文档 2024-01-21 16:07:56 +08:00
Kimdiego2098
12eb56809d 更新5.0 2024-01-21 15:38:31 +08:00
Kimdiego2098
d792172779 更新5.0 2024-01-21 15:38:28 +08:00
Kimdiego2098
011562ae73 修复变量 多字节解析顺序配置不生效 2024-01-12 09:50:41 +08:00
Kimdiego2098
71c4e36933 service中的客户端交互没有日志输出;modbusDTU添加定时清理 2024-01-10 12:11:55 +08:00
Kimdiego2098
6261982f6c OPCUA订阅null值时不判定离线 2023-12-29 16:53:05 +08:00
Kimdiego2098
4ac01e0ed0 修复插件外部上传,无法同步识别流的问题 2023-12-29 16:08:41 +08:00
Kimdiego2098
2dfe07f13e opc变量值为null时 不应影响变量质量戳状态 2023-12-27 22:27:13 +08:00
Kimdiego2098
7f4e4017ce 更新版本号 2023-12-12 22:42:56 +08:00
Kimdiego2098
635970f37b 更新版本号 2023-12-12 22:42:34 +08:00
Kimdiego2098
106e740220 修复导出变量偶发丢失上传属性的问题 2023-12-12 22:41:10 +08:00
Kimdiego2098
3e6420ba6f 整理上传插件代码 2023-12-12 22:40:42 +08:00
Diego2098
79be8010d5 Merge pull request #2 from allrightsreserved/master
分离数据库 和上传插件的父类
2023-12-12 21:09:44 +08:00
BadMan
0b6e679f3b 分离数据库 和上传插件的父类 2023-12-12 12:48:28 +08:00
Kimdiego2098
97c43ad2b9 更新依赖包 2023-12-11 21:19:51 +08:00
Kimdiego2098
cbf978745c 修复历史报警数据转储插件错误 2023-12-11 13:36:15 +08:00
Kimdiego2098
63dceada90 dateTimeExtension更改 2023-12-08 17:37:12 +08:00
Kimdiego2098
366aade8b4 整理代码文件 2023-12-08 17:08:57 +08:00
Kimdiego2098
aeb505e3d9 整理代码文件 2023-12-08 16:43:26 +08:00
Kimdiego2098
f9482e4773 Sqlsugar版本更新;
如果出现linux系统中报错sqlite错误,尝试安装依赖
# Debian/Ubuntu
apt-get install libsqlite3-mod-spatialite

# macOS
brew install libspatialite
2023-12-08 16:43:05 +08:00
Kimdiego2098
57dfc22ff7 更新版本号 2023-12-08 10:20:54 +08:00
Kimdiego2098
adc489b6ed 回退sqlsugar版本 2023-12-07 15:12:47 +08:00
Kimdiego2098
0623684315 nuget安装sqlite8.0.0 2023-12-07 14:34:14 +08:00
Kimdiego2098
68afccd859 修复OPC节点空间浏览窗口退出时报错的问题 2023-12-07 14:21:24 +08:00
Kimdiego2098
99eef8fb28 更新依赖包 2023-12-06 19:14:42 +08:00
Kimdiego2098
47e7685d39 串口代码整理 2023-12-06 18:54:33 +08:00
Kimdiego2098
b6ea596ade 整理代码 2023-12-06 18:35:52 +08:00
Kimdiego2098
44d60b469b 同步ts 2023-12-06 15:48:55 +08:00
Kimdiego2098
51087408df 同步ts 2023-12-06 15:16:54 +08:00
Kimdiego2098
96226d9e6e 同步ts 2023-12-06 14:56:12 +08:00
Kimdiego2098
28f0f62424 同步ts 2023-12-06 11:35:57 +08:00
Kimdiego2098
2e772a8cd4 同步touchsocket 2023-12-06 09:16:00 +08:00
Kimdiego2098
3fd192f0cf 变量表达式编辑 改为 多行文本框 2023-12-06 07:42:07 +08:00
Kimdiego2098
d16ae81961 更新demo;更新kafka 生成事件; 2023-12-04 20:28:36 +08:00
Kimdiego2098
211a8e093e 更新版本号 2023-12-01 21:23:51 +08:00
Kimdiego2098
84010a51d6 更改方法参数原;现由,分割 2023-12-01 21:22:27 +08:00
Kimdiego2098
e9700ea19b 更新依赖包 2023-12-01 19:55:17 +08:00
Kimdiego2098
e81ec68072 添加解决方案项 2023-11-30 17:44:26 +08:00
Kimdiego2098
6096e97708 modbusDtu更名 2023-11-30 10:47:37 +08:00
Kimdiego2098
6f302b66b4 添加ModbusRtu格式的DTU驱动 2023-11-30 10:16:26 +08:00
Kimdiego2098
b6e41890f7 同步TouchSocket 2023-11-30 10:16:20 +08:00
Kimdiego2098
be5332a048 添加离线后恢复间隔时间选项,添加重试次数选项 2023-11-29 20:47:23 +08:00
Kimdiego2098
4d72aeb0cd 修复种子数据带转义字符串时错误解析的问题 2023-11-29 19:04:56 +08:00
3818 changed files with 251372 additions and 205060 deletions

8
.gitignore vendored
View File

@@ -362,7 +362,7 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
/framework/*pro*
/framework/*Pro*
/src/*Pro*/
/src/*Pro*
/src/*pro*
/src/*pro*/

202
LICENSE Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Cachetribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023-present Diego
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023-present Diego
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

106
README.md
View File

@@ -1,38 +1,98 @@
# ThingsGateway
## 介绍

**NetCore** 跨平台边缘采集网关(工业设备采集)
## Introduction
**ThingsGateway** 存储库同时提供 [**设备采集驱动**](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)

A cross-platform, high-performance edge data collection gateway based on net9.

**ThingsGateway** 存储库同时提供 **基于Blazor的权限框架** 查看 **ThingsGateway - Admin**
## Documentation

[Documentation](https://thingsgateway.cn/).

[NuGet](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)

## 文档
## Demo
[ThingsGateway](https://diego2098.gitee.io/thingsgateway-docs/) 文档。

[Demo](http://47.119.161.158:5000/)

Account: **SuperAdmin**

Password: **111111**

**In the upper-right corner, switch to the IoT Gateway module in the personal popup box**
## 协议
## Docker
[ThingsGateway](https://gitee.com/diego2098/ThingsGateway) 采用 [Apache-2.0](https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE.zh) 开源协议。
```shell
## 演示
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway
[ThingsGateway演示地址](http://120.24.62.140:5000/)
账户 : **superAdmin**
密码 : **111111**
## 赞助
[ThingsGateway赞助途径](https://diego2098.gitee.io/thingsgateway-docs/docs/donate)
## 社区
QQ群605534569
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway_arm64
```
### Plugin List

#### Data Collection Plugins
| Plugin Name | Remarks |
| ----------- | ------------------------------------------------------------- |
| Modbus | Supports Rtu/Tcp message formats, with Serial/Tcp/Udp links |
| SiemensS7 | Siemens PLC S7 series |
| Dlt6452007 | Supports Serial/Tcp/Udp links |
| OpcDaMaster | Compiled for 64-bit |
| OpcUaMaster | Supports certificate login, object extension, Json read/write |
| Webhook | Webhook |
#### Business Plugins
| Plugin Name | Remarks |
| ---------------- | ------------------------------------------------------------------------------------------------- |
| ModbusSlave | Supports Rtu/Tcp message formats, with Serial/Tcp/Udp links, supports Rpc reverse writing |
| OpcUaServer | OpcUa server, supports Rpc reverse writing |
| MqttClient | Mqtt client, supports Rpc reverse writing, script-customizable upload content |
| MqttServer | Mqtt server, supports WebSocket, supports Rpc reverse writing, script-customizable upload content |
| KafkaProducer | Script-customizable upload content |
| RabbitMQProducer | Script-customizable upload content |
| SqlDB | Relational database storage, supports historical storage and real-time data updates |
| SqlHistoryAlarm | Alarm historical data relational database storage |
| TDengineDB | Time-series database storage |
| QuestDB | Time-series database storage |

## License

[License](https://thingsgateway.cn/docs/1)


## Sponsorship

[Sponsorship Approach](https://thingsgateway.cn/docs/1000)

## Community

QQ Group: 605534569 [Jump](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=NnBjPO-8kcNFzo_RzSbdICflb97u2O1i&authKey=V1MI3iJtpDMHc08myszP262kDykbx2Yev6ebE4Me0elTe0P0IFAmtU5l7Sy5w0jx&noverify=0&group_code=605534569)

## Pro Plugins

[Plugin List](https://thingsgateway.cn/docs/1001)

86
README.zh-CN.md Normal file
View File

@@ -0,0 +1,86 @@
# ThingsGateway
## 介绍
基于net9的跨平台高性能边缘采集网关
## 文档
[文档](https://thingsgateway.cn/)
[NuGet](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)
## 演示
[ThingsGateway演示地址](http://47.119.161.158:5000/)
账户 : **SuperAdmin**
密码 : **111111**
**右上角个人弹出框中,切换到物联网关模块**
## Docker
```shell
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway_arm64
```
### 插件列表
#### 采集插件
| 插件名称 | 备注 |
| ----------- | ------------------------------------- |
| Modbus | Rtu/Tcp报文格式支持串口/Tcp/Udp链路 |
| SiemensS7 | 西门子PLC S7系列 |
| Dlt6452007 | 支持串口/Tcp/Udp链路 |
| OpcDaMaster | 64位编译 |
| OpcUaMaster | 支持证书登录扩展对象Json读写 |
#### 业务插件
| 插件名称 | 备注 |
| ---------------- | ---------------------------------------------------------- |
| ModbusSlave | Rtu/Tcp报文格式支持串口/Tcp/Udp链路支持Rpc反写 |
| OpcUaServer | OpcUa服务端支持Rpc反写 |
| MqttClient | Mqtt客户端支持Rpc反写脚本自定义上传内容 |
| MqttServer | Mqtt服务端支持WebSocket支持Rpc反写脚本自定义上传内容 |
| KafkaProducer | 脚本自定义上传内容 |
| RabbitMQProducer | 脚本自定义上传内容 |
| SqlDB | 关系数据库存储,支持历史存储和实时数据更新 |
| SqlHistoryAlarm | 报警历史数据关系数据库存储 |
| TDengineDB | 时序数据库存储 |
| QuestDB | 时序数据库存储 |
| Webhook | Webhook |
## 协议
[版权声明](https://thingsgateway.cn/docs/1)
## 赞助
[赞助途径](https://thingsgateway.cn/docs/1000)
## 社区
QQ群605534569 [跳转](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=NnBjPO-8kcNFzo_RzSbdICflb97u2O1i&authKey=V1MI3iJtpDMHc08myszP262kDykbx2Yev6ebE4Me0elTe0P0IFAmtU5l7Sy5w0jx&noverify=0&group_code=605534569)
## Pro插件
[插件列表](https://thingsgateway.cn/docs/1001)
## 特别声明
ThingsGateway 项目已加入 [dotNET China](https://gitee.com/dotnetchina) 组织。<br/>
![dotnetchina](https://gitee.com/dotnetchina/home/raw/master/assets/dotnetchina-raw.png "dotNET China LOGO")

View File

@@ -1,20 +0,0 @@
<Project>
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFrameworks>net6.0;net8.0;</TargetFrameworks>
<Version>4.0.0.6</Version>
<LangVersion>latest</LangVersion>
<Authors>Diego</Authors>
<Product>ThingsGateway</Product>
<Copyright>© 2023-present Diego</Copyright>
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
<SignAssembly>True</SignAssembly>
<DelaySign>False</DelaySign>
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
</PropertyGroup>
</Project>

View File

@@ -1,101 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33927.249
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{4E66C22C-0636-4949-BF6A-9E3BBE1550BA}"
ProjectSection(SolutionItems) = preProject
admin\Directory.Build.props = admin\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "admin\ThingsGateway.Components\ThingsGateway.Components.csproj", "{0A891D8E-23B3-46AD-8D30-565EE5004F93}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "admin\ThingsGateway.Core\ThingsGateway.Core.csproj", "{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Core", "admin\ThingsGateway.Admin.Core\ThingsGateway.Admin.Core.csproj", "{5DA3D2BD-6768-4479-B52F-49E022EFF310}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Blazor", "admin\ThingsGateway.Admin.Blazor\ThingsGateway.Admin.Blazor.csproj", "{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Application", "admin\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{D6685A42-2712-417A-92C5-5EFF90B9FA94}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.ApiController", "admin\ThingsGateway.Admin.ApiController\ThingsGateway.Admin.ApiController.csproj", "{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}"
ProjectSection(SolutionItems) = preProject
web\Directory.Build.props = web\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Core", "web\ThingsGateway.Web.Core\ThingsGateway.Web.Core.csproj", "{D37EC028-EA46-4510-8261-6E780A906314}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Entry", "web\ThingsGateway.Web.Entry\ThingsGateway.Web.Entry.csproj", "{C5F662EB-991F-438D-BF61-EF87E7371C04}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{97B23D8B-C6C0-4746-A21F-C7B49354B284}"
ProjectSection(SolutionItems) = preProject
..\.gitignore = ..\.gitignore
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj", "{6961511A-8787-42AF-827D-B630B2AF4791}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "foundation", "foundation", "{268A1A81-2685-47E1-9986-5934A58A31A4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.Build.0 = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.Build.0 = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.Build.0 = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.Build.0 = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.Build.0 = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.Build.0 = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.Build.0 = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.Build.0 = Release|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6961511A-8787-42AF-827D-B630B2AF4791}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0A891D8E-23B3-46AD-8D30-565EE5004F93} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{5DA3D2BD-6768-4479-B52F-49E022EFF310} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{D6685A42-2712-417A-92C5-5EFF90B9FA94} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{D37EC028-EA46-4510-8261-6E780A906314} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{C5F662EB-991F-438D-BF61-EF87E7371C04} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{6961511A-8787-42AF-827D-B630B2AF4791} = {268A1A81-2685-47E1-9986-5934A58A31A4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C49B2D3E-6818-4E28-91B7-6E4E7E264BBB}
EndGlobalSection
EndGlobal

View File

@@ -1,288 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33927.249
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "foundation\ThingsGateway.foundation\ThingsGateway.Foundation.csproj", "{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "foundation", "foundation", "{0874CBC5-C583-4FAD-BA93-94571D446898}"
ProjectSection(SolutionItems) = preProject
foundation\Directory.Build.props = foundation\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.DLT645", "foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj", "{92963877-0185-45A5-A0EB-CEC0D55FF9B0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.Modbus", "foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj", "{24510CCE-0B60-4A03-9719-CF367C3528E9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.OPCDA", "foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj", "{566783A4-222B-46F5-AA12-0753997B3254}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.OPCUA", "foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj", "{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Adapter.Siemens", "foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj", "{9695B353-D773-40DD-B65E-7B10EB0C16EC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "demo", "demo", "{358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}"
ProjectSection(SolutionItems) = preProject
demo\Directory.Build.props = demo\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Photino", "demo\ThingsGateway.Foundation.Demo.Photino\ThingsGateway.Foundation.Demo.Photino.csproj", "{2192217C-CF77-422E-9E63-DF4003ABF01A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Rcl", "demo\ThingsGateway.Foundation.Demo.Rcl\ThingsGateway.Foundation.Demo.Rcl.csproj", "{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Demo.Winform", "demo\ThingsGateway.Foundation.Demo.Winform\ThingsGateway.Foundation.Demo.Winform.csproj", "{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gateway", "gateway", "{DFB97103-FC3A-4DC3-A327-DA8C65BDA607}"
ProjectSection(SolutionItems) = preProject
gateway\Directory.Build.props = gateway\Directory.Build.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{4E66C22C-0636-4949-BF6A-9E3BBE1550BA}"
ProjectSection(SolutionItems) = preProject
admin\Directory.Build.props = admin\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "admin\ThingsGateway.Components\ThingsGateway.Components.csproj", "{0A891D8E-23B3-46AD-8D30-565EE5004F93}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "admin\ThingsGateway.Core\ThingsGateway.Core.csproj", "{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Core", "admin\ThingsGateway.Admin.Core\ThingsGateway.Admin.Core.csproj", "{5DA3D2BD-6768-4479-B52F-49E022EFF310}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Blazor", "admin\ThingsGateway.Admin.Blazor\ThingsGateway.Admin.Blazor.csproj", "{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Application", "admin\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{D6685A42-2712-417A-92C5-5EFF90B9FA94}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.ApiController", "admin\ThingsGateway.Admin.ApiController\ThingsGateway.Admin.ApiController.csproj", "{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Core", "gateway\ThingsGateway.Gateway.Core\ThingsGateway.Gateway.Core.csproj", "{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Blazor", "gateway\ThingsGateway.Gateway.Blazor\ThingsGateway.Gateway.Blazor.csproj", "{69EA3D89-CB40-425A-8D70-5E4A33337BE5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Application", "gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj", "{90AB5C24-1AA3-4F58-9987-B307B92B5193}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.ApiController", "gateway\ThingsGateway.Gateway.ApiController\ThingsGateway.Gateway.ApiController.csproj", "{4C7A5A90-8292-413B-8848-419D9DCDE66F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}"
ProjectSection(SolutionItems) = preProject
web\Directory.Build.props = web\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Core", "web\ThingsGateway.Web.Core\ThingsGateway.Web.Core.csproj", "{D37EC028-EA46-4510-8261-6E780A906314}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Entry", "web\ThingsGateway.Web.Entry\ThingsGateway.Web.Entry.csproj", "{C5F662EB-991F-438D-BF61-EF87E7371C04}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugin", "plugin", "{E65490B8-D2E2-4693-B39C-15703B1EBFBB}"
ProjectSection(SolutionItems) = preProject
plugin\Directory.Build.props = plugin\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Modbus", "plugin\ThingsGateway.Plugin.Modbus\ThingsGateway.Plugin.Modbus.csproj", "{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Mqtt", "plugin\ThingsGateway.Plugin.Mqtt\ThingsGateway.Plugin.Mqtt.csproj", "{53C870AE-0249-4485-AE63-F8A16EA4BCB4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{97B23D8B-C6C0-4746-A21F-C7B49354B284}"
ProjectSection(SolutionItems) = preProject
..\.gitignore = ..\.gitignore
..\README.md = ..\README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Kafka", "plugin\ThingsGateway.Plugin.Kafka\ThingsGateway.Plugin.Kafka.csproj", "{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.SQLDB", "plugin\ThingsGateway.Plugin.SQLDB\ThingsGateway.Plugin.SQLDB.csproj", "{C102AB3A-377E-4753-AFA7-C13250D7DF00}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.QuestDB", "plugin\ThingsGateway.Plugin.QuestDB\ThingsGateway.Plugin.QuestDB.csproj", "{0DE1D254-0BD2-4D98-B939-5440BE5EB552}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.TDengineDB", "plugin\ThingsGateway.Plugin.TDengineDB\ThingsGateway.Plugin.TDengineDB.csproj", "{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.RabbitMQ", "plugin\ThingsGateway.Plugin.RabbitMQ\ThingsGateway.Plugin.RabbitMQ.csproj", "{A8E68E17-4EBF-4E4C-8272-B489329A68BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.Siemens", "plugin\ThingsGateway.Plugin.Siemens\ThingsGateway.Plugin.Siemens.csproj", "{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.DLT645", "plugin\ThingsGateway.Plugin.DLT645\ThingsGateway.Plugin.DLT645.csproj", "{AC4295F2-AB2F-4137-99EF-80FA5C83896B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OPCDA", "plugin\ThingsGateway.Plugin.OPCDA\ThingsGateway.Plugin.OPCDA.csproj", "{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.OPCUA", "plugin\ThingsGateway.Plugin.OPCUA\ThingsGateway.Plugin.OPCUA.csproj", "{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Plugin.SQLHisAlarm", "plugin\ThingsGateway.Plugin.SQLHisAlarm\ThingsGateway.Plugin.SQLHisAlarm.csproj", "{0947E6C0-6371-4483-B0ED-191FB5073151}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891}.Release|Any CPU.Build.0 = Release|Any CPU
{92963877-0185-45A5-A0EB-CEC0D55FF9B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92963877-0185-45A5-A0EB-CEC0D55FF9B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92963877-0185-45A5-A0EB-CEC0D55FF9B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92963877-0185-45A5-A0EB-CEC0D55FF9B0}.Release|Any CPU.Build.0 = Release|Any CPU
{24510CCE-0B60-4A03-9719-CF367C3528E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24510CCE-0B60-4A03-9719-CF367C3528E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24510CCE-0B60-4A03-9719-CF367C3528E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24510CCE-0B60-4A03-9719-CF367C3528E9}.Release|Any CPU.Build.0 = Release|Any CPU
{566783A4-222B-46F5-AA12-0753997B3254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{566783A4-222B-46F5-AA12-0753997B3254}.Debug|Any CPU.Build.0 = Debug|Any CPU
{566783A4-222B-46F5-AA12-0753997B3254}.Release|Any CPU.ActiveCfg = Release|Any CPU
{566783A4-222B-46F5-AA12-0753997B3254}.Release|Any CPU.Build.0 = Release|Any CPU
{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF}.Release|Any CPU.Build.0 = Release|Any CPU
{9695B353-D773-40DD-B65E-7B10EB0C16EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9695B353-D773-40DD-B65E-7B10EB0C16EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9695B353-D773-40DD-B65E-7B10EB0C16EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9695B353-D773-40DD-B65E-7B10EB0C16EC}.Release|Any CPU.Build.0 = Release|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2192217C-CF77-422E-9E63-DF4003ABF01A}.Release|Any CPU.Build.0 = Release|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB}.Release|Any CPU.Build.0 = Release|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325}.Release|Any CPU.Build.0 = Release|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.Build.0 = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.Build.0 = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.Build.0 = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.Build.0 = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.Build.0 = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.Build.0 = Release|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2}.Release|Any CPU.Build.0 = Release|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69EA3D89-CB40-425A-8D70-5E4A33337BE5}.Release|Any CPU.Build.0 = Release|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90AB5C24-1AA3-4F58-9987-B307B92B5193}.Release|Any CPU.Build.0 = Release|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C7A5A90-8292-413B-8848-419D9DCDE66F}.Release|Any CPU.Build.0 = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.Build.0 = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.Build.0 = Release|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603}.Release|Any CPU.Build.0 = Release|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53C870AE-0249-4485-AE63-F8A16EA4BCB4}.Release|Any CPU.Build.0 = Release|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825}.Release|Any CPU.Build.0 = Release|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C102AB3A-377E-4753-AFA7-C13250D7DF00}.Release|Any CPU.Build.0 = Release|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DE1D254-0BD2-4D98-B939-5440BE5EB552}.Release|Any CPU.Build.0 = Release|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4}.Release|Any CPU.Build.0 = Release|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8E68E17-4EBF-4E4C-8272-B489329A68BF}.Release|Any CPU.Build.0 = Release|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD}.Release|Any CPU.Build.0 = Release|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC4295F2-AB2F-4137-99EF-80FA5C83896B}.Release|Any CPU.Build.0 = Release|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC}.Release|Any CPU.Build.0 = Release|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812}.Release|Any CPU.Build.0 = Release|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0947E6C0-6371-4483-B0ED-191FB5073151}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2070116F-7A1B-47E2-A2F2-7BEC29ECE891} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{92963877-0185-45A5-A0EB-CEC0D55FF9B0} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{24510CCE-0B60-4A03-9719-CF367C3528E9} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{566783A4-222B-46F5-AA12-0753997B3254} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{BEFBC44A-E140-4E3E-AFBE-2DD8B98EB9BF} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{9695B353-D773-40DD-B65E-7B10EB0C16EC} = {0874CBC5-C583-4FAD-BA93-94571D446898}
{2192217C-CF77-422E-9E63-DF4003ABF01A} = {358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}
{DE376FAD-1E99-4CEE-96B2-08B1D1F3D1DB} = {358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}
{ACAA3F0D-CE2B-49F4-883A-ED23ADD9E325} = {358AE1E1-4DD6-4D1F-8935-1ACBB0111A01}
{0A891D8E-23B3-46AD-8D30-565EE5004F93} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{A712EAEE-94F2-4F01-8C1C-2EC802280DD7} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{5DA3D2BD-6768-4479-B52F-49E022EFF310} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{D6685A42-2712-417A-92C5-5EFF90B9FA94} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
{1A4D0B95-9FC5-4687-94E2-B6F86B5427F2} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{69EA3D89-CB40-425A-8D70-5E4A33337BE5} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{90AB5C24-1AA3-4F58-9987-B307B92B5193} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{4C7A5A90-8292-413B-8848-419D9DCDE66F} = {DFB97103-FC3A-4DC3-A327-DA8C65BDA607}
{D37EC028-EA46-4510-8261-6E780A906314} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{C5F662EB-991F-438D-BF61-EF87E7371C04} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
{ECF3A7A3-2363-4A38-BC78-8FF9A8564603} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{53C870AE-0249-4485-AE63-F8A16EA4BCB4} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{E4B8B8E6-FAE7-43BA-9A51-33A3CD9FB825} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{C102AB3A-377E-4753-AFA7-C13250D7DF00} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{0DE1D254-0BD2-4D98-B939-5440BE5EB552} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{C1911F84-6FDB-4DEC-8938-69B2E3901CC4} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{A8E68E17-4EBF-4E4C-8272-B489329A68BF} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{5FAFD46E-6B98-4C75-B1EB-085AA18F15FD} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{AC4295F2-AB2F-4137-99EF-80FA5C83896B} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{9DA9AED3-9572-4378-A2A6-4D792D67ADDC} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{FD4969DB-3CCE-4CCF-BAE4-1BE8A3F40812} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
{0947E6C0-6371-4483-B0ED-191FB5073151} = {E65490B8-D2E2-4693-B39C-15703B1EBFBB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C49B2D3E-6818-4E28-91B7-6E4E7E264BBB}
EndGlobalSection
EndGlobal

View File

@@ -1,25 +0,0 @@
extensions: .cs
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
extensions: .razor
@*
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
*@

View File

@@ -1,9 +0,0 @@
<Project>
<Import Project="$(SolutionDir)\Directory.Build.props" />
<PropertyGroup>
</PropertyGroup>
</Project>

View File

@@ -1,62 +0,0 @@
#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 Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel;
namespace ThingsGateway.Admin.ApiController;
/// <summary>
/// 后台登录控制器
/// </summary>
[ApiDescriptionSettings(CateGoryConst.ThingsGatewayAdmin, Order = 200)]
[Route("auth/b")]
[LoggingMonitor]
public class AuthController : IDynamicApiController
{
private readonly IAuthService _authService;
/// <summary>
/// <inheritdoc cref="AuthController"/>
/// </summary>
/// <param name="authService"></param>
public AuthController(IAuthService authService)
{
_authService = authService;
}
/// <summary>
/// 后台登录
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost("login")]
[Description(EventSubscriberConst.Login)]
public async Task<LoginOutput> LoginAsync(LoginInput input)
{
return await _authService.LoginAsync(input);
}
/// <summary>
/// 后台登出
/// </summary>
/// <returns></returns>
[HttpPost("logout")]
[Description(EventSubscriberConst.Logout)]
[Authorize]
public async Task LogoutAsync()
{
await _authService.LogoutAsync();
}
}

View File

@@ -1,67 +0,0 @@
#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 Microsoft.AspNetCore.Mvc;
namespace ThingsGateway.Admin.ApiController;
/// <summary>
/// 文件下载
/// </summary>
[ApiDescriptionSettings(CateGoryConst.ThingsGatewayAdmin, Order = 200)]
[Route("file")]
[LoggingMonitor]
public class FileController : IDynamicApiController
{
private readonly IOperateLogService _operateLogService;
private readonly IVisitLogService _visitLogService;
/// <summary>
/// <inheritdoc cref="FileController"/>
/// </summary>
public FileController(
IOperateLogService operateLogService,
IVisitLogService visitLogService
)
{
_operateLogService = operateLogService;
_visitLogService = visitLogService;
}
/// <summary>
/// 下载操作日志
/// </summary>
/// <returns></returns>
[HttpGet("operateLog")]
public async Task<IActionResult> DownloadOperateLogAsync([FromQuery] OperateLogInput input)
{
var memoryStream = await _operateLogService.ExportFileAsync(input);
var data = new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = $"operateLog{DateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx"
};
return data;
}
/// <summary>
/// 下载访问日志
/// </summary>
/// <returns></returns>
[HttpGet("visitLog")]
public async Task<IActionResult> DownloadVisitLogAsync([FromQuery] VisitLogInput input)
{
var memoryStream = await _visitLogService.ExportFileAsync(input);
var data = new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = $"operateLog{DateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx"
};
return data;
}
}

View File

@@ -1,63 +0,0 @@
#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 Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel;
namespace ThingsGateway.Admin.ApiController;
/// <summary>
/// OpenApi登录控制器
/// </summary>
[ApiDescriptionSettings(CateGoryConst.ThingsGatewayOpenApi, Order = 200)]
[Route("auth/openapi")]
[LoggingMonitor]
[Description("OpenApi登录")]
[Authorize(AuthenticationSchemes = "Bearer")]
public class OpenApiAuthController : IDynamicApiController
{
private readonly IOpenApiAuthService _authService;
/// <summary>
/// <inheritdoc cref="OpenApiAuthController"/>
/// </summary>
/// <param name="authService"></param>
public OpenApiAuthController(IOpenApiAuthService authService)
{
_authService = authService;
}
/// <summary>
/// OpenApi登录
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost("login")]
[Description(EventSubscriberConst.LoginOpenApi)]
public async Task<LoginOpenApiOutput> LoginOpenApiAsync(LoginOpenApiInput input)
{
return await _authService.LoginOpenApiAsync(input);
}
/// <summary>
/// 登出
/// </summary>
/// <returns></returns>
[HttpPost("logout")]
[Description(EventSubscriberConst.LogoutOpenApi)]
public async Task LogoutAsync()
{
await _authService.LogoutAsync();
}
}

View File

@@ -1,69 +0,0 @@
#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;
using Furion.SpecificationDocument;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Admin.ApiController;
/// <summary>
/// Swagger登录授权服务
/// </summary>
[ApiDescriptionSettings(CateGoryConst.ThingsGatewayAdmin, Order = 200)]
[Route("Swagger")]
public class SwaggerController : IDynamicApiController, IScoped
{
private readonly IConfigService _configService;
/// <summary>
/// <inheritdoc cref="SwaggerController"/>
/// </summary>
/// <param name="sysConfigService"></param>
public SwaggerController(IConfigService sysConfigService)
{
_configService = sysConfigService;
}
/// <summary>
/// Swagger登录检查
/// </summary>
/// <returns></returns>
[HttpPost("CheckUrl")]
[AllowAnonymous, NonUnify]
public async Task<int> SwaggerCheckUrlAsync()
{
var enable = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGERLOGIN_OPEN)).ConfigValue.ToBool(false);
return enable ? 401 : 200;
}
/// <summary>
/// Swagger登录
/// </summary>
/// <param name="auth"></param>
/// <returns></returns>
[HttpPost("SubmitUrl")]
[AllowAnonymous, NonUnify]
public async Task<int> SwaggerSubmitUrlAsync([FromForm] SpecificationAuth auth)
{
var userName = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGER_NAME)).ConfigValue;
var password = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGER_PASSWORD)).ConfigValue;
if (auth.UserName == userName && auth.Password == password)
{
return 200;
}
return 401;
}
}

View File

@@ -1,19 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using Furion.DynamicApiController;
global using System;
global using System.Threading.Tasks;
global using ThingsGateway.Admin.Application;
global using ThingsGateway.Foundation.Core;

View File

@@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,102 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Admin.ApiController</name>
</assembly>
<members>
<member name="T:ThingsGateway.Admin.ApiController.AuthController">
<summary>
后台登录控制器
</summary>
</member>
<member name="M:ThingsGateway.Admin.ApiController.AuthController.#ctor(ThingsGateway.Admin.Application.IAuthService)">
<summary>
<inheritdoc cref="T:ThingsGateway.Admin.ApiController.AuthController"/>
</summary>
<param name="authService"></param>
</member>
<member name="M:ThingsGateway.Admin.ApiController.AuthController.LoginAsync(ThingsGateway.Admin.Application.LoginInput)">
<summary>
后台登录
</summary>
<param name="input"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.ApiController.AuthController.LogoutAsync">
<summary>
后台登出
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Admin.ApiController.FileController">
<summary>
文件下载
</summary>
</member>
<member name="M:ThingsGateway.Admin.ApiController.FileController.#ctor(ThingsGateway.Admin.Application.IOperateLogService,ThingsGateway.Admin.Application.IVisitLogService)">
<summary>
<inheritdoc cref="T:ThingsGateway.Admin.ApiController.FileController"/>
</summary>
</member>
<member name="M:ThingsGateway.Admin.ApiController.FileController.DownloadOperateLogAsync(ThingsGateway.Admin.Application.OperateLogInput)">
<summary>
下载操作日志
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.ApiController.FileController.DownloadVisitLogAsync(ThingsGateway.Admin.Application.VisitLogInput)">
<summary>
下载访问日志
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Admin.ApiController.OpenApiAuthController">
<summary>
OpenApi登录控制器
</summary>
</member>
<member name="M:ThingsGateway.Admin.ApiController.OpenApiAuthController.#ctor(ThingsGateway.Admin.Application.IOpenApiAuthService)">
<summary>
<inheritdoc cref="T:ThingsGateway.Admin.ApiController.OpenApiAuthController"/>
</summary>
<param name="authService"></param>
</member>
<member name="M:ThingsGateway.Admin.ApiController.OpenApiAuthController.LoginOpenApiAsync(ThingsGateway.Admin.Application.LoginOpenApiInput)">
<summary>
OpenApi登录
</summary>
<param name="input"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.ApiController.OpenApiAuthController.LogoutAsync">
<summary>
登出
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Admin.ApiController.SwaggerController">
<summary>
Swagger登录授权服务
</summary>
</member>
<member name="M:ThingsGateway.Admin.ApiController.SwaggerController.#ctor(ThingsGateway.Admin.Application.IConfigService)">
<summary>
<inheritdoc cref="T:ThingsGateway.Admin.ApiController.SwaggerController"/>
</summary>
<param name="sysConfigService"></param>
</member>
<member name="M:ThingsGateway.Admin.ApiController.SwaggerController.SwaggerCheckUrlAsync">
<summary>
Swagger登录检查
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Admin.ApiController.SwaggerController.SwaggerSubmitUrlAsync(Furion.SpecificationDocument.SpecificationAuth)">
<summary>
Swagger登录
</summary>
<param name="auth"></param>
<returns></returns>
</member>
</members>
</doc>

View File

@@ -1,43 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 操作事件说明特性
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class OperDescAttribute : Attribute
{
/// <summary>
/// 操作记录标识
/// </summary>
/// <param name="description"></param>
/// <param name="catcategory"></param>
public OperDescAttribute(string description, string catcategory = LogConst.LOG_OPERATE)
{
Description = description;
Catcategory = catcategory;
}
/// <summary>
/// 分类
/// </summary>
public string Catcategory { get; }
/// <summary>
/// 说明
/// </summary>
public string Description { get; }
/// <summary>
/// 记录参数默认true
/// </summary>
public bool IsRecordPar { get; set; } = true;
}

View File

@@ -1,224 +0,0 @@
#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.Reflection;
using Furion.Reflection.Extensions;
using System.Reflection;
using System.Text;
using ThingsGateway.Foundation.Extension.String;
using UAParser;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// AOP处理操作日志
/// </summary>
public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
{
/// <summary>
/// 服务提供器可以用来解析服务Services.GetService()
/// </summary>
public IServiceProvider Services { get; set; }
/// <summary>
/// 当前服务实例
/// </summary>
public object Target { get; set; }
/// <summary>
/// 方法
/// </summary>
/// <param name="method"></param>
/// <param name="args"></param>
/// <returns></returns>
public override object Invoke(MethodInfo method, object[] args)
{
var desc = Target.GetCustomAttribute<OperDescAttribute>(method.ToString(), true);
if (desc == null)
{
return Invoke(method, args);
}
else
{
Exception exception = default;
object result = default;
try
{
result = Invoke(method, args);
}
catch (Exception ex)
{
exception = ex;
}
WriteOperLog(method, args, desc, result, exception);
if (exception != null)
{
throw exception;
}
return result;//返回结果
}
object Invoke(MethodInfo method, object[] args)
{
//如果不带返回值
if (method.ReturnType == typeof(void))
{
return method.Invoke(Target, args);//直接返回
}
else
{
var result = method.Invoke(Target, args);
return result;//返回结果
}
}
}
/// <summary>
/// 异步无返回值
/// </summary>
/// <param name="method"></param>
/// <param name="args"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override async Task InvokeAsync(MethodInfo method, object[] args)
{
var desc = method.GetActualCustomAttribute<OperDescAttribute>(Target, true);
if (desc == null)
{
var task = method.Invoke(Target, args) as Task;
await task;
}
else
{
Exception exception = default;
try
{
var task = method.Invoke(Target, args) as Task;
await task;
}
catch (Exception ex)
{
exception = ex;
}
WriteOperLog(method, args, desc, null, exception);
if (exception != null)
{
throw exception;
}
}
}
/// <summary>
/// 异步带返回值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="method"></param>
/// <param name="args"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override async Task<T> InvokeAsyncT<T>(MethodInfo method, object[] args)
{
var desc = method.GetActualCustomAttribute<OperDescAttribute>(Target, true);
if (desc == null)
{
var taskT = method.Invoke(Target, args) as Task<T>;
var result = await taskT;
return result;//返回结果
}
else
{
T result = default;
//写入操作日志
Exception exception = null;
try
{
var taskT = method.Invoke(Target, args) as Task<T>;
result = await taskT;
}
catch (Exception ex)
{
exception = ex;
}
WriteOperLog(method, args, desc, result, exception);
if (exception != null)
{
throw exception;
}
else
{
return result;//返回结果
}
}
}
private void WriteOperLog(MethodInfo method, object[] args, OperDescAttribute desc, object result, Exception exception)
{
//写入操作日志
var str = App.HttpContext?.Request?.Headers?.UserAgent;
ClientInfo clientInfo = null;
if (str.HasValue)
{
var uaParser = Parser.GetDefault();
clientInfo = uaParser.Parse(str);
}
StringBuilder stringBuilder = new();
if (desc.IsRecordPar)
{
var parameters = method.GetParameters();
var jsonParameters = parameters.Select((p, i) => $"\"{p.Name}\": {args[i].ToJsonString()}");
stringBuilder.Append('{');
stringBuilder.Append(string.Join(", ", jsonParameters));
stringBuilder.Append('}');
}
var paramJson = stringBuilder.ToString();
var resultJson = desc.IsRecordPar ? result?.ToJsonString() : null;
//操作日志表实体
var log = new SysOperateLog
{
Name = desc.Description,
Category = desc.Catcategory,
ExeStatus = LogConst.LOG_SUCCESS,
OpIp = App.HttpContext?.Connection?.RemoteIpAddress?.MapToIPv4().ToString(),
OpBrowser = clientInfo?.UA?.Family + clientInfo?.UA?.Major,
OpOs = clientInfo?.OS?.Family + clientInfo?.OS?.Major,
OpTime = DateTimeExtensions.CurrentDateTime,
OpAccount = UserManager.UserAccount,
ReqUrl = "",
ReqMethod = LogConst.LOG_REQMETHOD,
ResultJson = resultJson,
ClassName = method.ReflectedType.Name,
MethodName = method.Name,
ParamJson = paramJson,
VerificatId = UserManager.VerificatId.ToLong(),
};
//如果异常不为空
if (exception != null)
{
log.ExeStatus = LogConst.LOG_FAIL;//操作状态为失败
log.ExeMessage = exception.Source + ":" + exception.Message + Environment.NewLine + exception.StackTrace;
}
DbContext.Db.CopyNew().InsertableWithAttr(log).ExecuteCommand();//入库
}
}

View File

@@ -1,38 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 权限操作常量
/// </summary>
public class AdminConst
{
#region
/// <summary>
/// 禁用操作
/// </summary>
public const string Disable = "禁用";
/// <summary>
/// 启用操作
/// </summary>
public const string Enable = "启用";
/// <summary>
/// 用户授权操作
/// </summary>
public const string GrantRole = "授权";
#endregion
}

View File

@@ -1,83 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// Cache常量
/// </summary>
public class CacheConst
{
/// <summary>
/// 登录验证码缓存Key
/// </summary>
public const string LOGIN_CAPTCHA = "LOGIN_CAPTCHA";
/// <summary>
/// 配置缓存Key
/// </summary>
public const string SYS_CONFIGCATEGORY = "SYS_CONFIGCATEGORY";
#region OpenApi
/// <summary>
/// OpenApi用户表缓存Key
/// </summary>
public const string CACHE_OPENAPIUSER = "CACHE_OPENAPIUSER";
/// <summary>
/// OpenApi关系缓存Key
/// </summary>
public const string CACHE_OPENAPIUSERACCOUNT = "CACHE_OPENAPIUSERACCOUNT";
/// <summary>
/// UserVerificat缓存Key
/// </summary>
public const string CACHE_OPENAPIUSERVERIFICAT = "CACHE_OPENAPIUSERVERIFICAT";
/// <summary>
/// UserVerificat缓存Key
/// </summary>
public const string CACHE_USERVERIFICAT = "CACHE_USERVERIFICAT";
#endregion OpenApi
/// <summary>
/// 用户表缓存Key
/// </summary>
public const string CACHE_SYSUSER = "CACHE_SYSUSER";
/// <summary>
/// 用户表缓存Key
/// </summary>
public const string CAHCE_SYSUSERACCOUNT = "CAHCE_SYSUSERACCOUNT";
/// <summary>
/// 关系表缓存Key
/// </summary>
public const string CACHE_SYSRELATION = "CACHE_SYSRELATION";
/// <summary>
/// 资源表缓存Key
/// </summary>
public const string CACHE_SYSRESOURCE = "CACHE_SYSRESOURCE";
/// <summary>
/// 角色表缓存Key
/// </summary>
public const string CACHE_SYSROLE = "CACHE_SYSROLE";
}

View File

@@ -1,61 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 其他分类常量
/// </summary>
public static class CateGoryConst
{
/// <summary>
/// ThingsGateway.Admin
/// </summary>
public const string ThingsGatewayAdmin = "ThingsGateway.Admin";
/// <summary>
/// ThingsGateway.OpenApi
/// </summary>
public const string ThingsGatewayOpenApi = "ThingsGateway.OpenApi";
#region
/// <summary>
/// 用户主页
/// </summary>
public const string Relation_SYS_USER_DEFAULTRAZOR = "Relation_SYS_USER_DEFAULTRAZOR";
/// <summary>
/// 用户工作台数据
/// </summary>
public const string Relation_SYS_USER_WORKBENCH_DATA = "SYS_USER_WORKBENCH_DATA";
/// <summary>
/// 角色有哪些权限
/// </summary>
public const string Relation_SYS_ROLE_HAS_PERMISSION = "SYS_ROLE_HAS_PERMISSION";
/// <summary>
/// 角色有哪些资源
/// </summary>
public const string Relation_SYS_ROLE_HAS_RESOURCE = "SYS_ROLE_HAS_RESOURCE";
/// <summary>
/// 用户有哪些角色
/// </summary>
public const string Relation_SYS_USER_HAS_ROLE = "SYS_USER_HAS_ROLE";
#endregion
}

View File

@@ -1,96 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 配置常量
/// </summary>
public static class ConfigConst
{
/// <summary>
/// 系统固定配置
/// </summary>
public const string SYS_CONFIGBASEDEFAULT = "SYS_CONFIGBASEDEFAULT";
/// <summary>
/// 其他自定义配置
/// </summary>
public const string SYS_CONFIGOTHER = "SYS_CONFIGOTHER";
#region config
/// <summary>
/// 版权标识
/// </summary>
public const string CONFIG_COPYRIGHT = "CONFIG_COPYRIGHT";
/// <summary>
/// 版权跳转url
/// </summary>
public const string CONFIG_COPYRIGHT_URL = "CONFIG_COPYRIGHT_URL";
/// <summary>
/// 是否启用PageTab
/// </summary>
public const string CONFIG_PAGETAB = "CONFIG_PAGETAB";
/// <summary>
/// 登录验证码开关
/// </summary>
public const string CONFIG_CAPTCHA_OPEN = "CONFIG_CAPTCHA_OPEN";
/// <summary>
/// 默认用户密码
/// </summary>
public const string CONFIG_PASSWORD = "CONFIG_PASSWORD";
/// <summary>
/// 登录界面的介绍文本
/// </summary>
public const string CONFIG_REMARK = "CONFIG_REMARK";
/// <summary>
/// 单用户登录开关
/// </summary>
public const string CONFIG_SINGLE_OPEN = "CONFIG_SINGLE_OPEN";
/// <summary>
/// swagger用户
/// </summary>
public const string CONFIG_SWAGGER_NAME = "CONFIG_SWAGGER_NAME";
/// <summary>
/// swagger密码
/// </summary>
public const string CONFIG_SWAGGER_PASSWORD = "CONFIG_SWAGGER_PASSWORD";
/// <summary>
/// 系统标题
/// </summary>
public const string CONFIG_TITLE = "CONFIG_TITLE";
/// <summary>
/// 系统登录过期时间
/// </summary>
public const string CONFIG_VERIFICAT_EXPIRES = "CONFIG_VERIFICAT_EXPIRES";
/// <summary>
/// Swagger是否需要登录
/// </summary>
public const string CONFIG_SWAGGERLOGIN_OPEN = "CONFIG_SWAGGERLOGIN_OPEN";
#endregion
}

View File

@@ -1,47 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 事件总线常量
/// </summary>
public class EventSubscriberConst
{
/// <summary>
/// 清除用户缓存
/// </summary>
public const string ClearUserCache = "清除用户缓存";
/// <summary>
/// 页面登录
/// </summary>
public const string Login = "登录";
/// <summary>
/// OpenApi登录
/// </summary>
public const string LoginOpenApi = "OpenApi登录";
/// <summary>
/// 后台登出
/// </summary>
public const string Logout = "退出";
/// <summary>
/// OpenApi登出
/// </summary>
public const string LogoutOpenApi = "OpenApi退出";
}

View File

@@ -1,69 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 日志常量
/// </summary>
public class LogConst
{
#region
/// <summary>
/// 登录
/// </summary>
public const string LOG_LOGIN = "LOGIN";
/// <summary>
/// 登出
/// </summary>
public const string LOG_LOGOUT = "LOGOUT";
/// <summary>
/// 第三方登录
/// </summary>
public const string LOG_OPENAPILOGIN = "OPENAPILOGIN";
/// <summary>
/// 第三方登出
/// </summary>
public const string LOG_OPENAPILOGOUT = "OPENAPILOGOUT";
/// <summary>
/// 第三方操作来源
/// </summary>
public const string LOG_OPENAPIOPERATE = "OPENAPIOPERATE";
/// <summary>
/// 操作分类
/// </summary>
public const string LOG_OPERATE = "OPERATE";
/// <summary>
/// 内部操作来源
/// </summary>
public const string LOG_REQMETHOD = "BLAZORSERVER";
/// <summary>
/// 操作成功
/// </summary>
public const string LOG_SUCCESS = "SUCCESS";
/// <summary>
/// 操作失败
/// </summary>
public const string LOG_FAIL = "FAIL";
#endregion
}

View File

@@ -1,24 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Core;
/// <summary>
/// 资源表常量
/// </summary>
public class ResourceConst
{
/// <summary>
/// 系统内置编码
/// </summary>
public const string System = "system";
}

View File

@@ -1,44 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 角色常量
/// </summary>
public class RoleConst
{
/// <summary>
/// 超级管理员
/// </summary>
public const string SuperAdmin = "superAdmin";
#region
/// <summary>
/// 角色有哪些权限
/// </summary>
public const string Relation_SYS_ROLE_HAS_PERMISSION = "SYS_ROLE_HAS_PERMISSION";
/// <summary>
/// 角色有哪些资源
/// </summary>
public const string Relation_SYS_ROLE_HAS_RESOURCE = "SYS_ROLE_HAS_RESOURCE";
/// <summary>
/// 用户有哪些角色
/// </summary>
public const string Relation_SYS_USER_HAS_ROLE = "SYS_USER_HAS_ROLE";
#endregion
}

View File

@@ -1,24 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
global using Furion;
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Admin.Core;
global using ThingsGateway.Core;
global using ThingsGateway.Foundation.Core;

View File

@@ -1,68 +0,0 @@
#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.Schedule;
using Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IJobPersistence"/>
public class JobPersistence : IJobPersistence
{
private readonly IServiceScope _serviceScope;
/// <inheritdoc/>
public JobPersistence(IServiceScopeFactory serviceScopeFactory)
{
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
public void Dispose()
{
_serviceScope?.Dispose();
}
/// <inheritdoc/>
public void OnChanged(PersistenceContext context)
{
}
/// <summary>
/// 作业计划初始化通知
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public SchedulerBuilder OnLoading(SchedulerBuilder builder)
{
return builder;
}
/// <inheritdoc/>
public void OnTriggerChanged(PersistenceTriggerContext context)
{
}
/// <summary>
/// 作业调度服务启动时
/// </summary>
/// <returns></returns>
public IEnumerable<SchedulerBuilder> Preload()
{
// 获取所有定义的作业
var allJobs = App.EffectiveTypes.ScanToBuilders().ToList();
return allJobs;
}
}

View File

@@ -1,32 +0,0 @@
#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.Schedule;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 清理日志作业任务
/// </summary>
[JobDetail("job_log", Description = "清理访问/操作日志", GroupName = "default", Concurrent = false)]
[Daily(TriggerId = "trigger_log", Description = "清理访问/操作日志", RunOnStart = true)]
public class LogJob : IJob
{
/// <inheritdoc/>
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
{
var db = DbContext.Db.CopyNew();
var daysAgo = App.GetConfig<int?>("Logging:LogJob:DaysAgo") ?? 30;
await db.DeleteableWithAttr<SysVisitLog>().Where(u => u.CreateTime < DateTimeExtensions.CurrentDateTime.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除访问日志
await db.DeleteableWithAttr<SysOperateLog>().Where(u => u.CreateTime < DateTimeExtensions.CurrentDateTime.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除操作日志
}
}

View File

@@ -1,49 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 登录事件参数
/// </summary>
public class LoginOpenApiEvent
{
/// <summary>
/// 时间
/// </summary>
public DateTime DateTime = DateTimeExtensions.CurrentDateTime;
/// <summary>
/// 登录设备
/// </summary>
public AuthDeviceTypeEnum Device { get; set; }
/// <summary>
/// 过期时间(分)
/// </summary>
public int Expire { get; set; }
/// <summary>
/// Ip地址
/// </summary>
public string Ip { get; set; }
/// <summary>
/// 用户信息
/// </summary>
public OpenApiUser OpenApiUser { get; set; }
/// <summary>
/// 验证Id
/// </summary>
public long VerificatId { get; set; }
}

View File

@@ -1,52 +0,0 @@
#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;
using Furion.EventBus;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 认证模块事件总线
/// </summary>
public class OpenApiAuthEventSubscriber : IEventSubscriber, ISingleton
{
/// <summary>
/// 登录事件
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
[EventSubscribe(EventSubscriberConst.LoginOpenApi)]
public async Task LoginOpenApi(EventHandlerExecutingContext context)
{
LoginOpenApiEvent loginEvent = (LoginOpenApiEvent)context.Source.Payload;//获取参数
OpenApiUser openApiUser = loginEvent.OpenApiUser;
var db = DbContext.Db.CopyNew();
#region ,
db.Tracking(openApiUser);//创建跟踪,只更新修改字段
openApiUser.LastLoginDevice = openApiUser.LatestLoginDevice;
openApiUser.LastLoginIp = openApiUser.LatestLoginIp;
openApiUser.LastLoginTime = openApiUser.LatestLoginTime;
openApiUser.LatestLoginDevice = loginEvent.Device.ToString();
openApiUser.LatestLoginIp = loginEvent.Ip;
openApiUser.LatestLoginTime = loginEvent.DateTime;
#endregion ,
//更新用户信息
if (await db.UpdateableWithAttr(openApiUser).ExecuteCommandAsync() > 0)
{
App.GetService<MemoryCache>().Set(CacheConst.CACHE_OPENAPIUSER + openApiUser.Id, openApiUser, false); //更新Cache信息
}
}
}

View File

@@ -1,33 +0,0 @@
#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 System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 登录输入参数
/// </summary>
public class LoginOpenApiInput
{
/// <summary>
/// 账号
///</summary>
[Required(ErrorMessage = "账号不能为空"), MinLength(3, ErrorMessage = "账号不能少于4个字符")]
public string Account { get; set; }
/// <summary>
/// 密码
///</summary>
[Required(ErrorMessage = "密码不能为空"), MinLength(3, ErrorMessage = "密码不能少于3个字符")]
public string Password { get; set; }
}

View File

@@ -1,24 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 登录返回参数
/// </summary>
public class LoginOpenApiOutput : BaseLoginOutput
{
/// <summary>
/// TOKEN
/// </summary>
public string Token { get; set; }
}

View File

@@ -1,33 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 登录服务
/// </summary>
public interface IOpenApiAuthService : ITransient
{
/// <summary>
/// 登录
/// </summary>
/// <param name="input">登录参数</param>
/// <returns>Token信息</returns>
Task<LoginOpenApiOutput> LoginOpenApiAsync(LoginOpenApiInput input);
/// <summary>
/// 登出
/// </summary>
/// <returns></returns>
Task LogoutAsync();
}

View File

@@ -1,172 +0,0 @@
#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.DataEncryption;
using Furion.DependencyInjection;
using Furion.EventBus;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using ThingsGateway.Foundation.Extension.String;
using Yitter.IdGenerator;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IOpenApiAuthService"/>
public class OpenApiAuthService : IOpenApiAuthService, ITransient
{
private readonly IConfigService _configService;
private readonly IEventPublisher _eventPublisher;
private readonly IOpenApiUserService _openApiUserService;
private readonly IVerificatService _verificatService;
/// <inheritdoc cref="IOpenApiAuthService"/>
public OpenApiAuthService(
IEventPublisher eventPublisher,
IOpenApiUserService openApiUserService,
IVerificatService verificatService,
IConfigService configService)
{
_verificatService = verificatService;
_eventPublisher = eventPublisher;
_openApiUserService = openApiUserService;
_configService = configService;
}
/// <inheritdoc/>
public async Task<LoginOpenApiOutput> LoginOpenApiAsync(LoginOpenApiInput input)
{
var password = input.Password;
var userInfo = await _openApiUserService.GetUserByAccountAsync(input.Account);//获取用户信息
if (userInfo == null) throw Oops.Bah("用户不存在");//用户不存在
if (userInfo.Password != password) throw Oops.Bah("账号密码错误");//账号密码错误
return await PrivateLoginOpenApiAsync(userInfo);
}
/// <inheritdoc/>
public async Task LogoutAsync()
{
//获取用户信息
var userinfo = await _openApiUserService.GetUserByAccountAsync(UserManager.UserAccount);
if (userinfo != null)
{
LoginOpenApiEvent loginEvent = new()
{
Ip = App.HttpContext.GetRemoteIpAddressToIPv4(),
OpenApiUser = userinfo,
VerificatId = UserManager.VerificatId.ToLong(),
};
await RemoveVerificatFromCacheAsync(loginEvent);
}
}
private async Task<List<VerificatInfo>> GetVerificatInfos(long userId)
{
List<VerificatInfo> verificatInfos = await _verificatService.GetOpenApiVerificatIdAsync(userId);
return verificatInfos;
}
private async Task<LoginOpenApiOutput> PrivateLoginOpenApiAsync(OpenApiUser openApiUser)
{
if (openApiUser.UserEnable == false) throw Oops.Bah("账号已停用");//账号冻结
var sessionid = YitIdHelper.NextId();
var expire = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_VERIFICAT_EXPIRES)).ConfigValue.ToInt();
//生成Token
var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
{
{ClaimConst.UserId, openApiUser.Id},
{ClaimConst.Account, openApiUser.Account},
{ ClaimConst.VerificatId, sessionid.ToString()},
{ ClaimConst.IsOpenApi, true},
}, expire);
// 生成刷新Token令牌
var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, expire * 2);
// 设置Swagger自动登录
App.HttpContext.SigninToSwagger(accessToken);
// 设置响应报文头
App.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken);
//登录事件参数
var logingEvent = new LoginOpenApiEvent
{
Ip = App.HttpContext.GetRemoteIpAddressToIPv4(),
Device = AuthDeviceTypeEnum.Api,
Expire = expire,
OpenApiUser = openApiUser,
VerificatId = sessionid
};
await WriteVerificatToCacheAsync(logingEvent);//写入verificat到cache
await _eventPublisher.PublishAsync(EventSubscriberConst.LoginOpenApi, logingEvent); //发布登录事件总线
//返回结果
return new LoginOpenApiOutput { VerificatId = sessionid, Token = accessToken, Account = openApiUser.Account };
}
private async Task RemoveVerificatFromCacheAsync(LoginOpenApiEvent loginEvent)
{
//获取verificat列表
var verificatInfos = await GetVerificatInfos(loginEvent.OpenApiUser.Id);
if (verificatInfos != null)
{
//获取当前用户的verificat
var verificat = verificatInfos.Where(it => it.Id == loginEvent.VerificatId).FirstOrDefault();
if (verificat != null)
verificatInfos.Remove(verificat);
//更新verificat列表
await _verificatService.SetOpenApiVerificatIdAsync(loginEvent.OpenApiUser.Id, verificatInfos);
}
await App.HttpContext?.SignOutAsync();
App.HttpContext?.SignoutToSwagger();
}
private async Task WriteVerificatToCacheAsync(LoginOpenApiEvent loginEvent)
{
//获取verificat列表
List<VerificatInfo> verificatInfos = await GetVerificatInfos(loginEvent.OpenApiUser.Id);
var verificatTimeout = loginEvent.DateTime.AddMinutes(loginEvent.Expire);
//生成verificat信息
var verificatInfo = new VerificatInfo
{
Device = loginEvent.Device.ToString(),
Expire = loginEvent.Expire,
VerificatTimeout = verificatTimeout,
Id = loginEvent.VerificatId,
UserId = loginEvent.OpenApiUser.Id,
};
if (verificatInfos != null)
{
bool isSingle = false;//默认不开启单用户登录
var singleConfig = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SINGLE_OPEN);//获取系统单用户登录选项
if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBool(false);//如果配置不为空则设置单用户登录选项为系统配置的值
//判断是否单用户登录
if (isSingle)
{
verificatInfos = verificatInfos.ToList();//去掉当前登录类型的verificat
verificatInfos.Add(verificatInfo);//添加到列表
}
else
{
verificatInfos.Add(verificatInfo);
}
}
else
{
verificatInfos = new List<VerificatInfo> { verificatInfo };//直接就一个
}
//添加到verificat列表
await _verificatService.SetOpenApiVerificatIdAsync(loginEvent.OpenApiUser.Id, verificatInfos);
}
}

View File

@@ -1,45 +0,0 @@
#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 System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 会话分页查询
/// </summary>
public class OpenApiSessionPageInput : BasePageInput
{
/// <summary>
/// 账号
/// </summary>
[Description("账号")]
public string Account { get; set; }
/// <summary>
/// 最新登录IP
/// </summary>
[Description("最新登录IP")]
public string LatestLoginIp { get; set; }
}
/// <summary>
/// 退出参数
/// </summary>
public class OpenApiExitVerificatInput : BaseIdInput
{
/// <summary>
/// 验证ID列表
/// </summary>
[Required(ErrorMessage = "VerificatIds不能为空")]
public List<long> VerificatIds { get; set; }
}

View File

@@ -1,55 +0,0 @@
#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 System.ComponentModel;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 会话输出
/// </summary>
public class OpenApiSessionOutput : PrimaryKeyEntity
{
/// <summary>
/// 账号
///</summary>
[Description("账号")]
[DataTable(Order = 1, IsShow = true, Sortable = true)]
public virtual string Account { get; set; }
/// <summary>
/// 最新登录ip
///</summary>
[Description("最新登录ip")]
[DataTable(Order = 2, IsShow = true, Sortable = true)]
public string LatestLoginIp { get; set; }
/// <summary>
/// 最新登录时间
///</summary>
[Description("最新登录时间")]
[DataTable(Order = 3, IsShow = true, Sortable = true)]
public DateTime? LatestLoginTime { get; set; }
/// <summary>
/// 令牌数量
/// </summary>
[Description("令牌数量")]
[DataTable(Order = 4, IsShow = true, Sortable = false)]
public int VerificatCount { get; set; }
/// <summary>
/// 令牌信息集合
/// </summary>
[Description("令牌列表")]
public List<VerificatInfo> VerificatSignList { get; set; }
}

View File

@@ -1,40 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 会话管理服务
/// </summary>
public interface IOpenApiSessionService : ITransient
{
/// <summary>
/// 强退会话
/// </summary>
/// <param name="input">用户ID</param>
Task ExitSessionAsync(long input);
/// <summary>
/// 强退cookie
/// </summary>
/// <param name="input">cookie列表</param>
Task ExitVerificatAsync(OpenApiExitVerificatInput input);
/// <summary>
/// B端会话分页查询
/// </summary>
/// <param name="input">查询参数</param>
/// <returns>B端会话列表</returns>
Task<ISqlSugarPagedList<OpenApiSessionOutput>> PageAsync(OpenApiSessionPageInput input);
}

View File

@@ -1,106 +0,0 @@
#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;
using SqlSugar;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="IOpenApiSessionService"/>
/// </summary>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class OpenApiSessionService : DbRepository<OpenApiUser>, IOpenApiSessionService
{
private readonly IVerificatService _verificatService;
/// <inheritdoc cref="IOpenApiSessionService"/>
public OpenApiSessionService(IVerificatService verificatService)
{
_verificatService = verificatService;
}
/// <inheritdoc/>
[OperDesc("强退OPENAPI会话")]
public async Task ExitSessionAsync(long input)
{
//从列表中删除
await _verificatService.SetOpenApiVerificatIdAsync(input, new());
}
/// <inheritdoc/>
[OperDesc("强退OPENAPI令牌")]
public async Task ExitVerificatAsync(OpenApiExitVerificatInput input)
{
//获取该用户的verificat信息
List<VerificatInfo> verificatInfos = await _verificatService.GetOpenApiVerificatIdAsync(input.Id);
//当前需要踢掉用户的verificat
var setVerificats = verificatInfos.Where(it => !input.VerificatIds.Contains(it.Id)).ToList();
await _verificatService.SetOpenApiVerificatIdAsync(input.Id, setVerificats);//如果还有verificat则更新verificat
}
/// <summary>
/// 获取verificat剩余时间信息
/// </summary>
/// <param name="verificatInfos">verificat列表</param>
private static void GetVerificatInfos(ref List<VerificatInfo> verificatInfos)
{
verificatInfos = verificatInfos.ToList();
verificatInfos.ForEach(it =>
{
var now = DateTimeExtensions.CurrentDateTime;
it.VerificatRemain = now.GetDiffTime(it.VerificatTimeout);//获取时间差
var verificatSecond = it.VerificatTimeout.AddMinutes(-it.Expire).ToLong();//颁发时间转为时间戳
var timeoutSecond = it.VerificatTimeout.ToLong();//过期时间转为时间戳
});
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<OpenApiSessionOutput>> PageAsync(OpenApiSessionPageInput input)
{
var query = Context.Queryable<OpenApiUser>()
.WhereIF(!string.IsNullOrEmpty(input.Account), it => it.Account.Contains(input.Account))//根据账号查询
.WhereIF(!string.IsNullOrEmpty(input.LatestLoginIp), it => it.LatestLoginIp.Contains(input.LatestLoginIp))//根据IP查询
.OrderBy(it => it.LatestLoginTime, OrderByType.Desc)
.Select<OpenApiSessionOutput>()
.Mapper(async it =>
{
var verificatInfos = await _verificatService.GetVerificatIdAsync(it.Id);
if (verificatInfos != null)
{
GetVerificatInfos(ref verificatInfos);//获取剩余时间
it.VerificatCount = verificatInfos.Count;//令牌数量
it.VerificatSignList = verificatInfos;//令牌列表
}
else
{
it.VerificatSignList = new();
}
});
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
pageInfo.Records = pageInfo.Records.OrderByDescending(it => it.VerificatCount);
return pageInfo;
}
}

View File

@@ -1,148 +0,0 @@
#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 SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// Api授权资源树
/// </summary>
public class OpenApiPermissionTreeSelector
{
/// <summary>
/// 接口描述
/// </summary>
[Description("Api说明")]
public string ApiName { get; set; }
/// <summary>
/// 路由名称
/// </summary>
[Description("Api路径")]
public string ApiRoute { get; set; }
/// <summary>
/// 子节点
/// </summary>
public List<OpenApiPermissionTreeSelector> Children { get; set; } = new();
/// <summary>
/// ID
/// </summary>
public long Id { get; set; }
/// <summary>
/// 父ID
/// </summary>
public long ParentId { get; set; }
/// <summary>
/// 权限名称
/// </summary>
[Description("权限名称")]
public string PermissionName { get; set; }
/// <summary>
/// 多个树转列表
/// </summary>
public static List<OpenApiPermissionTreeSelector> TreeToList(IList<OpenApiPermissionTreeSelector> data)
{
List<OpenApiPermissionTreeSelector> list = new();
foreach (var item in data)
{
list.Add(item);
if (item.Children != null && item.Children.Count > 0)
{
list.AddRange(TreeToList(item.Children));
}
}
return list;
}
}
/// <summary>
/// 添加用户参数
/// </summary>
public class OpenApiUserAddInput : OpenApiUser
{
/// <summary>
/// 账号
/// </summary>
[Required(ErrorMessage = "账号不能为空"), MinLength(3, ErrorMessage = "账号不能少于4个字符")]
public override string Account { get; set; }
/// <summary>
/// 密码
/// </summary>
[Required(ErrorMessage = "密码不能为空"), MinLength(2, ErrorMessage = "密码不能少于3个字符")]
public override string Password { get; set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
public override bool UserEnable { get; set; } = true;
}
/// <summary>
/// 编辑用户参数
/// </summary>
public class OpenApiUserEditInput : OpenApiUser
{
/// <summary>
/// 账号
/// </summary>
[Required(ErrorMessage = "账号不能为空"), MinLength(3, ErrorMessage = "账号不能少于4个字符")]
public override string Account { get; set; }
/// <summary>
/// Id
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
/// <summary>
/// 密码
/// </summary>
[Required(ErrorMessage = "密码不能为空"), MinLength(2, ErrorMessage = "密码不能少于3个字符")]
public override string Password { get; set; }
}
/// <summary>
/// 用户分页查询参数
/// </summary>
public class OpenApiUserPageInput : BasePageInput
{
/// <summary>
/// 动态查询条件
/// </summary>
public Expressionable<SysUser> Expression { get; set; }
}
/// <summary>
/// 用户授权参数
/// </summary>
public class OpenApiUserGrantPermissionInput
{
/// <summary>
/// Id
/// </summary>
[Required(ErrorMessage = "Id不能为空")]
public long? Id { get; set; }
/// <summary>
/// 授权权限信息
/// </summary>
[Required(ErrorMessage = "PermissionList不能为空")]
public List<string> PermissionList { get; set; }
}

View File

@@ -1,104 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 用户服务
/// </summary>
public interface IOpenApiUserService : ITransient
{
/// <summary>
/// 添加用户
/// </summary>
/// <param name="input">添加参数</param>
/// <returns></returns>
Task AddAsync(OpenApiUserAddInput input);
/// <summary>
/// 删除用户
/// </summary>
/// <param name="input">Id列表</param>
/// <returns></returns>
Task DeleteAsync(params long[] input);
/// <summary>
/// 从cache中删除用户信息
/// </summary>
/// <param name="ids">用户ID列表</param>
void DeleteUserFromCache(params long[] ids);
/// <summary>
/// 禁用用户
/// </summary>
/// <param name="input">用户Id</param>
/// <returns></returns>
Task DisableUserAsync(long input);
/// <summary>
/// 编辑
/// </summary>
/// <param name="input">编辑参数</param>
/// <returns></returns>
Task EditAsync(OpenApiUserEditInput input);
/// <summary>
/// 启用用户
/// </summary>
/// <param name="input">用户Id</param>
/// <returns></returns>
Task EnableUserAsync(long input);
/// <summary>
///根据用户账号获取用户ID
/// </summary>
/// <param name="account">用户账号</param>
/// <returns></returns>
Task<long> GetIdByAccountAsync(string account);
/// <summary>
/// 根据账号获取用户信息
/// </summary>
/// <param name="account">用户名</param>
/// <returns>用户信息</returns>
Task<OpenApiUser> GetUserByAccountAsync(string account);
/// <summary>
/// 根据ID获取用户信息
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
Task<OpenApiUser> GetUsertByIdAsync(long Id);
/// <summary>
/// 给用户授权
/// </summary>
/// <param name="input">授权参数</param>
/// <returns></returns>
Task GrantRoleAsync(OpenApiUserGrantPermissionInput input);
/// <summary>
/// 获取用户拥有权限,返回的是服务方法名称
/// </summary>
/// <param name="input">用户ID</param>
/// <returns></returns>
Task<List<string>> OwnPermissionsAsync(BaseIdInput input);
/// <summary>
/// 用户分页查询
/// </summary>
/// <param name="input">查询参数</param>
/// <returns>用户分页列表</returns>
Task<ISqlSugarPagedList<OpenApiUser>> PageAsync(OpenApiUserPageInput input);
}

View File

@@ -1,284 +0,0 @@
#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.DataEncryption;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="IOpenApiUserService"/>
/// </summary>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
{
private readonly IVerificatService _verificatService;
private readonly IServiceScope _serviceScope;
/// <inheritdoc cref="IOpenApiUserService"/>
public OpenApiUserService(
IVerificatService verificatService, IServiceScopeFactory serviceScopeFactory
)
{
_verificatService = verificatService;
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
[OperDesc("添加用户")]
public async Task AddAsync(OpenApiUserAddInput input)
{
var account_Id = await GetIdByAccountAsync(input.Account);
if (account_Id > 0)
throw Oops.Bah($"存在重复的账号:{input.Account}");
var openApiUser = input.Adapt<OpenApiUser>();//实体转换
await InsertAsync(openApiUser);//添加数据
}
/// <inheritdoc/>
[OperDesc("删除用户")]
public async Task DeleteAsync(params long[] ids)
{
//获取所有ID
if (ids.Length > 0)
{
var result = await DeleteByIdsAsync(ids.Cast<object>().ToArray());
if (result)
{
//从列表中删除
foreach (var id in ids)
{
await _verificatService.SetOpenApiVerificatIdAsync(id, new());
}
DeleteUserFromCache(ids);
}
}
}
/// <inheritdoc />
public void DeleteUserFromCache(params long[] ids)
{
var userIds = ids.Select(it => it.ToString()).ToArray();//id转string列表
List<OpenApiUser> openApiUsers = new();
foreach (var item in userIds)
{
var user = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<OpenApiUser>(CacheConst.CACHE_OPENAPIUSER + item, false);//获取用户列表
openApiUsers.Add(user);
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_OPENAPIUSER + item);
}
openApiUsers = openApiUsers.Where(it => it != null).ToList();//过滤掉不存在的
if (openApiUsers.Count > 0)
{
var accounts = openApiUsers.Select(it => it.Account).ToArray();//账号集合
foreach (var item in accounts)
{
//删除账号
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_OPENAPIUSERACCOUNT + item);
}
}
}
/// <inheritdoc/>
[OperDesc("禁用用户")]
public async Task DisableUserAsync(long input)
{
var openApiUser = await GetUsertByIdAsync(input);//获取用户信息
if (openApiUser != null)
{
if (await UpdateAsync(it => new OpenApiUser { UserEnable = false }, it => it.Id == input))
{
await _verificatService.SetOpenApiVerificatIdAsync(input, new());
DeleteUserFromCache(input);//从cache删除用户信息
}
}
}
/// <inheritdoc/>
[OperDesc("编辑用户")]
public async Task EditAsync(OpenApiUserEditInput input)
{
await CheckInputAsync(input);//检查参数
var exist = await GetUsertByIdAsync(input.Id);//获取用户信息
if (exist != null)
{
var openApiUser = input.Adapt<OpenApiUser>();//实体转换
openApiUser.Password = DESCEncryption.Encrypt(openApiUser.Password, DESCKeyConst.DESCKey);
if (await Context.Updateable(openApiUser).IgnoreColumns(it =>
new
{
//忽略更新字段
it.LastLoginDevice,
it.LastLoginIp,
it.LastLoginTime,
it.LatestLoginDevice,
it.LatestLoginIp,
it.LatestLoginTime
}).ExecuteCommandAsync() > 0)//修改数据
DeleteUserFromCache(openApiUser.Id);//用户缓存到cache
}
//编辑操作可能会修改用户密码等信息,认证时需要实时获取用户并验证
}
/// <inheritdoc/>
[OperDesc("启用用户")]
public async Task EnableUserAsync(long input)
{
//设置状态为启用
if (await UpdateAsync(it => new OpenApiUser { UserEnable = true }, it => it.Id == input))
DeleteUserFromCache(input);//从cache删除用户信息
}
/// <inheritdoc/>
public async Task<long> GetIdByAccountAsync(string account)
{
//先从Cache拿
var userId = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<long>(CacheConst.CACHE_OPENAPIUSERACCOUNT + account, false);
if (userId == 0)
{
//单查获取用户账号对应ID
userId = await GetFirstAsync(it => it.Account == account, it => it.Id);
if (userId != 0)
{
//插入Cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_OPENAPIUSERACCOUNT + account, userId, false);
}
}
return userId;
}
/// <inheritdoc/>
public async Task<OpenApiUser> GetUserByAccountAsync(string account)
{
var userId = await GetIdByAccountAsync(account);//获取用户ID
if (userId > 0)
{
var openApiUser = await GetUsertByIdAsync(userId);//获取用户信息
if (openApiUser.Account == account)//这里做了比较用来限制大小写
return openApiUser;
else
return null;
}
else
{
return null;
}
}
/// <inheritdoc/>
public async Task<OpenApiUser> GetUsertByIdAsync(long Id)
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var openApiUser = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<OpenApiUser>(CacheConst.CACHE_OPENAPIUSER + Id.ToString(), true);
if (openApiUser == null)
{
openApiUser = await Context.Queryable<OpenApiUser>()
.Where(u => u.Id == Id)
.FirstAsync();
if (openApiUser != null)
{
//插入Cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_OPENAPIUSER + openApiUser.Id.ToString(), openApiUser, true);
}
}
return openApiUser;
}
/// <inheritdoc />
[OperDesc("用户授权")]
public async Task GrantRoleAsync(OpenApiUserGrantPermissionInput input)
{
var openApiUser = await GetUsertByIdAsync(input.Id.Value);//获取用户信息
if (openApiUser != null)
{
openApiUser.PermissionCodeList = input.PermissionList;
await CheckInputAsync(openApiUser);
if (await Context.Updateable(openApiUser).IgnoreColumns(it =>
new
{
//忽略更新字段
it.Password,
it.LastLoginDevice,
it.LastLoginIp,
it.LastLoginTime,
it.LatestLoginDevice,
it.LatestLoginIp,
it.LatestLoginTime
}).ExecuteCommandAsync() > 0)//修改数据
DeleteUserFromCache(input.Id.Value);//从cache删除用户信息
}
}
/// <inheritdoc/>
public async Task<List<string>> OwnPermissionsAsync(BaseIdInput input)
{
var openApiUser = await GetUsertByIdAsync(input.Id);//获取用户信息
return openApiUser.PermissionCodeList;
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<OpenApiUser>> PageAsync(OpenApiUserPageInput input)
{
var query = Context.Queryable<OpenApiUser>()
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), u => u.Account.Contains(input.SearchKey));//根据关键字查询
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
query = query.OrderBy(it => it.SortCode);//排序
query = query.OrderBy(u => u.Id);//排序
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
/// <summary>
/// 检查输入参数
/// </summary>
/// <param name="openApiUser"></param>
private async Task CheckInputAsync(OpenApiUser openApiUser)
{
//判断账号重复,直接从cache拿
var account_Id = await GetIdByAccountAsync(openApiUser.Account);
if (account_Id > 0 && account_Id != openApiUser.Id)
throw Oops.Bah($"存在重复的账号:{openApiUser.Account}");
//如果手机号不是空
if (!string.IsNullOrEmpty(openApiUser.Phone))
{
if (!openApiUser.Phone.MatchPhoneNumber())//验证手机格式
throw Oops.Bah($"手机号码:{openApiUser.Phone} 格式错误");
openApiUser.Phone = DESCEncryption.Encrypt(openApiUser.Phone, DESCKeyConst.DESCKey);
}
//如果邮箱不是空
if (!string.IsNullOrEmpty(openApiUser.Email))
{
var ismatch = openApiUser.Email.MatchEmail();//验证邮箱格式
if (!ismatch)
throw Oops.Bah($"邮箱:{openApiUser.Email} 格式错误");
if (await IsAnyAsync(it => it.Email == openApiUser.Email && it.Id != openApiUser.Id))
throw Oops.Bah($"存在重复的邮箱:{openApiUser.Email}");
}
}
}

View File

@@ -1,18 +0,0 @@
{
"RECORDS": [
{
"Id": 444657867911429,
"Category": "SYS_USER_HAS_ROLE",
"ObjectId": 212725263002001,
"TargetId": "212725263001001",
"ExtJson": null
},
{
"Id": 444657879060741,
"Category": "SYS_USER_HAS_ROLE",
"ObjectId": 201725263002001,
"TargetId": "212725263001002",
"ExtJson": null
}
]
}

View File

@@ -1,564 +0,0 @@
{
"RECORDS": [
{
"Id": "100",
"Title": "系统首页",
"Icon": "mdi-home-account",
"Name": "index",
"Component": "/index",
"Category": "SPA",
"Code": "system",
"ParentId": "0",
"SortCode": "1",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100001",
"Title": "权限管理",
"Icon": "mdi-account-hard-hat",
"Category": "MENU",
"Code": "system",
"ParentId": "0",
"SortCode": "4",
"TargetType": "None",
"IsDelete": "false",
"UpdateTime": "2023-02-26 00:55:23.977",
"UpdateUser": "superAdmin",
"UpdateUserId": "212725263002001"
},
{
"Id": "100001001",
"Title": "用户管理",
"Icon": "mdi-account-edit",
"Name": "sysUser",
"Component": "/admin/user",
"Category": "MENU",
"Code": "system",
"ParentId": "100001",
"SortCode": "1",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100001002",
"Title": "角色管理",
"Icon": "mdi-account-hard-hat",
"Name": "sysRole",
"Component": "/admin/role",
"Category": "MENU",
"Code": "system",
"ParentId": "100001",
"SortCode": "2",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100001003",
"Title": "菜单管理",
"Icon": "mdi-menu",
"Name": "sysMenu",
"Component": "/admin/menu",
"Category": "MENU",
"Code": "system",
"ParentId": "100001",
"SortCode": "3",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100002002",
"Title": "访问日志",
"Icon": "mdi-account-switch-outline",
"Name": "sysVislog",
"Component": "/admin/vislog",
"Category": "MENU",
"Code": "system",
"ParentId": "100002",
"SortCode": "2",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100002003",
"Title": "操作日志",
"Icon": "mdi-database-search-outline",
"Name": "sysOplog",
"Component": "/admin/oplog",
"Category": "MENU",
"Code": "system",
"ParentId": "100002",
"SortCode": "3",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100002010",
"Title": "定时看板",
"Icon": "mdi-database-cog-outline",
"Name": "schedulePage",
"Component": "/schedulePage",
"Category": "MENU",
"Code": "system",
"ParentId": "100002",
"SortCode": "4",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100002",
"Title": "系统运维",
"Icon": "mdi-cogs",
"Category": "MENU",
"Code": "system",
"ParentId": "0",
"SortCode": "5",
"TargetType": "None",
"IsDelete": "false",
"UpdateTime": "2023-02-26 00:55:33.503",
"UpdateUser": "superAdmin",
"UpdateUserId": "212725263002001"
},
{
"Id": "100002001",
"Title": "系统配置",
"Icon": "mdi-cog-transfer-outline",
"Name": "sysConfig",
"Component": "/admin/config",
"Category": "MENU",
"Code": "system",
"ParentId": "100002",
"SortCode": "1",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100003",
"Title": "第三方授权",
"Icon": "mdi-transit-transfer",
"Category": "MENU",
"Code": "system",
"ParentId": "0",
"SortCode": "6",
"TargetType": "None",
"IsDelete": "false",
"UpdateTime": "2023-02-26 00:55:29.094",
"UpdateUser": "superAdmin",
"UpdateUserId": "212725263002001"
},
{
"Id": "100003001",
"Title": "令牌列表",
"Icon": "mdi-transit-transfer",
"Name": "sysOpenApiSession",
"Component": "/admin/openapisession",
"Category": "MENU",
"Code": "system",
"ParentId": "100003",
"SortCode": "1",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100003002",
"Title": "授权用户",
"Icon": "mdi-transit-transfer",
"Name": "sysOpenApiUser",
"Component": "/admin/openapiuser",
"Category": "MENU",
"Code": "system",
"ParentId": "100003",
"SortCode": "2",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100003003",
"Title": "接口文档",
"Icon": "mdi-cog-transfer-outline",
"Name": "swaggerUrl",
"Component": "/api/index.html",
"Category": "MENU",
"Code": "system",
"ParentId": "100003",
"SortCode": "3",
"TargetType": "BLANK",
"IsDelete": "false"
},
{
"Id": "100002004",
"Title": "会话管理",
"Icon": "mdi-transit-transfer",
"Name": "session",
"Component": "/admin/session",
"Category": "MENU",
"Code": "system",
"ParentId": "100002",
"SortCode": "4",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100001001001",
"Title": "添加",
"Name": "add",
"Category": "BUTTON",
"Code": "sysuseradd",
"ParentId": "100001001",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001004",
"Title": "单页管理",
"Icon": "mdi-menu",
"Name": "sysSpa",
"Component": "/admin/spa",
"Category": "MENU",
"Code": "system",
"ParentId": "100001",
"SortCode": "4",
"TargetType": "SELF",
"IsDelete": "false"
},
{
"Id": "100001001002",
"Title": "编辑",
"Name": "edit",
"Category": "BUTTON",
"Code": "sysuseredit",
"ParentId": "100001001",
"SortCode": "2",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001001003",
"Title": "删除",
"Name": "delete",
"Category": "BUTTON",
"Code": "sysuserdelete",
"ParentId": "100001001",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001002001",
"Title": "添加",
"Name": "add",
"Category": "BUTTON",
"Code": "sysroleadd",
"ParentId": "100001002",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001002002",
"Title": "编辑",
"Name": "edit",
"Category": "BUTTON",
"Code": "sysroleedit",
"ParentId": "100001002",
"SortCode": "2",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001002003",
"Title": "删除",
"Name": "delete",
"Category": "BUTTON",
"Code": "sysroledelete",
"ParentId": "100001002",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001003001",
"Title": "添加",
"Name": "add",
"Category": "BUTTON",
"Code": "sysmenuadd",
"ParentId": "100001003",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001003002",
"Title": "编辑",
"Name": "edit",
"Category": "BUTTON",
"Code": "sysmenuedit",
"ParentId": "100001003",
"SortCode": "2",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001003003",
"Title": "删除",
"Name": "delete",
"Category": "BUTTON",
"Code": "sysmenudelete",
"ParentId": "100001003",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001004001",
"Title": "添加",
"Name": "add",
"Category": "BUTTON",
"Code": "sysspaadd",
"ParentId": "100001004",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001004002",
"Title": "编辑",
"Name": "edit",
"Category": "BUTTON",
"Code": "sysspaedit",
"ParentId": "100001004",
"SortCode": "2",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001004003",
"Title": "删除",
"Name": "delete",
"Category": "BUTTON",
"Code": "sysspadelete",
"ParentId": "100001004",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100002001001",
"Title": "添加",
"Name": "add",
"Category": "BUTTON",
"Code": "sysconfigadd",
"ParentId": "100002001",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100002001002",
"Title": "编辑",
"Name": "edit",
"Category": "BUTTON",
"Code": "sysconfigedit",
"ParentId": "100002001",
"SortCode": "2",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100002001003",
"Title": "删除",
"Name": "delete",
"Category": "BUTTON",
"Code": "sysconfigdelete",
"ParentId": "100002001",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100003002001",
"Title": "添加",
"Name": "add",
"Category": "BUTTON",
"Code": "openapiuseradd",
"ParentId": "100003002",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100003002002",
"Title": "编辑",
"Name": "edit",
"Category": "BUTTON",
"Code": "openapiuseredit",
"ParentId": "100003002",
"SortCode": "2",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100003002003",
"Title": "删除",
"Name": "delete",
"Category": "BUTTON",
"Code": "openapiuserdelete",
"ParentId": "100003002",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001001004",
"Title": "重置密码",
"Name": "resetpassword",
"Category": "BUTTON",
"Code": "sysuserresetpassword",
"ParentId": "100001001",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001001005",
"Title": "角色授权",
"Name": "perrole",
"Category": "BUTTON",
"Code": "sysuserperrole",
"ParentId": "100001001",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001002004",
"Title": "资源授权",
"Name": "perresuorce",
"Category": "BUTTON",
"Code": "sysroleperresuorce",
"ParentId": "100001002",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100001002005",
"Title": "用户授权",
"Name": "peruser",
"Category": "BUTTON",
"Code": "sysroleperuser",
"ParentId": "100001002",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100002004004",
"Title": "会话强退",
"Name": "exit",
"Category": "BUTTON",
"Code": "syssessionexit",
"ParentId": "100002004",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100002004005",
"Title": "令牌删除",
"Name": "verificatdelete",
"Category": "BUTTON",
"Code": "sysverificatdelete",
"ParentId": "100002004",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100003001004",
"Title": "会话强退",
"Name": "exit",
"Category": "BUTTON",
"Code": "openapisessionexit",
"ParentId": "100003001",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100003001005",
"Title": "令牌删除",
"Name": "verificatdelete",
"Category": "BUTTON",
"Code": "openapiverificatdelete",
"ParentId": "100003001",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100002002003",
"Title": "清空",
"Name": "clear",
"Category": "BUTTON",
"Code": "sysoplogclear",
"ParentId": "100002002",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100002003003",
"Title": "清空",
"Name": "clear",
"Category": "BUTTON",
"Code": "sysvislogclear",
"ParentId": "100002003",
"SortCode": "3",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100003002004",
"Title": "修改密码",
"Name": "editpassword",
"Category": "BUTTON",
"Code": "openapiusereditpassword",
"ParentId": "100003002",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "100003002005",
"Title": "授权Api",
"Name": "per",
"Category": "BUTTON",
"Code": "openapiuserper",
"ParentId": "100003002",
"SortCode": "1",
"TargetType": "None",
"IsDelete": "false"
},
{
"Id": "391545543004421",
"Title": "个人中心",
"Icon": "mdi-home-account",
"Component": "/usercenter",
"Category": "SPA",
"Code": "391545542885637",
"ParentId": "0",
"SortCode": "2",
"TargetType": "SELF",
"CreateTime": "2023-03-02 19:42:55.6049703",
"CreateUser": "superAdmin",
"CreateUserId": "212725263002001",
"IsDelete": "false",
"UpdateTime": "2023-03-02 19:46:13.3919053",
"UpdateUser": "superAdmin",
"UpdateUserId": "212725263002001"
}
]
}

View File

@@ -1,145 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 系统配置种子数据
/// </summary>
public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
{
/// <inheritdoc/>
public IEnumerable<SysConfig> SeedData()
{
List<SysConfig> configList = new List<SysConfig>
{
new SysConfig
{
Id = 22222222222222,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_SWAGGER_NAME,
ConfigValue = "admin",
Remark = "swagger账号",
SortCode = 1,
},
new SysConfig
{
Id = 22222222222223,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_SWAGGER_PASSWORD,
ConfigValue = "123456",
Remark = "swagger密码",
SortCode = 2,
},
new SysConfig
{
Id = 22222222222224,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_SWAGGERLOGIN_OPEN,
ConfigValue = "false",
Remark = "swagger开启登录",
SortCode = 3,
},
new SysConfig
{
Id = 22222222222226,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_TITLE,
ConfigValue = "ThingsGateway",
Remark = "标题",
SortCode = 5,
},
new SysConfig
{
Id = 22222222222228,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_COPYRIGHT,
ConfigValue = "ThingsGateway ©2023 Diego",
Remark = "系统版权",
SortCode = 6,
},
new SysConfig
{
Id = 22222222222299,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_COPYRIGHT_URL,
ConfigValue = "https://gitee.com/diego2098/ThingsGateway",
Remark = "系统版权链接地址",
SortCode = 7,
},
new SysConfig
{
Id = 22222222222229,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_PAGETAB,
ConfigValue = "true",
Remark = "开启标签页",
SortCode = 7,
},
new SysConfig
{
Id = 22222222222231,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_PASSWORD,
ConfigValue = "111111",
Remark = "默认用户密码",
SortCode = 8,
},
new SysConfig
{
Id = 22222222222227,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_VERIFICAT_EXPIRES,
ConfigValue = "14400",
Remark = "Verificat过期时间(分)",
SortCode = 9,
},
new SysConfig
{
Id = 22222222222232,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_SINGLE_OPEN,
ConfigValue = "false",
Remark = "单用户登录开关",
SortCode = 10,
},
new SysConfig
{
Id = 22222222222230,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_CAPTCHA_OPEN,
ConfigValue = "true",
Remark = "登录验证码开关",
SortCode = 11,
},
new SysConfig
{
Id = 22222222222225,
Category = ConfigConst.SYS_CONFIGBASEDEFAULT,
ConfigKey = ConfigConst.CONFIG_REMARK,
ConfigValue = "边缘采集网关",
Remark = "说明",
SortCode = 12,
}
};
return configList;
}
}

View File

@@ -1,25 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 关系表种子数据
/// </summary>
public class SysRelationSeedData : ISqlSugarEntitySeedData<SysRelation>
{
/// <inheritdoc/>
public IEnumerable<SysRelation> SeedData()
{
return SeedDataUtil.GetSeedData<SysRelation>("sys_relation.json");
}
}

View File

@@ -1,25 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 资源表种子数据
/// </summary>
public class SysResourceSeedData : ISqlSugarEntitySeedData<SysResource>
{
/// <inheritdoc/>
public IEnumerable<SysResource> SeedData()
{
return SeedDataUtil.GetSeedData<SysResource>("sys_resource.json");
}
}

View File

@@ -1,43 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 角色种子数据
/// </summary>
public class SysRoleSeedData : ISqlSugarEntitySeedData<SysRole>
{
/// <inheritdoc/>
public IEnumerable<SysRole> SeedData()
{
List<SysRole> configList = new List<SysRole>
{
new SysRole
{
Id = 212725263001001,
Code = RoleConst.SuperAdmin,
Name = "超级管理员",
SortCode = 1,
},
new SysRole
{
Id = 212725263001002,
Code = "admin",
Name = "业务管理员",
SortCode = 2,
},
};
return configList;
}
}

View File

@@ -1,45 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 用户表种子数据
/// </summary>
public class SysUserSeedData : ISqlSugarEntitySeedData<SysUser>
{
/// <inheritdoc/>
public IEnumerable<SysUser> SeedData()
{
List<SysUser> configList = new List<SysUser>
{
new SysUser
{
Id = 212725263002001,
Account = RoleConst.SuperAdmin,
Password = "111111",
UserEnable = true,
SortCode = 1,
},
new SysUser
{
Id = 201725263002001,
Account = "admin",
Password = "111111",
UserEnable = true,
SortCode = 2,
},
};
return configList;
}
}

View File

@@ -1,26 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 即时通讯集线器
/// </summary>
public interface ISysHub
{
/// <summary>
/// 退出登录
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
Task Logout(object context);
}

View File

@@ -1,112 +0,0 @@
#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.InstantMessaging;
using Microsoft.AspNetCore.Http.Connections.Features;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="ISysHub"/>
/// </summary>
[MapHub(HubConst.SysHubUrl)]
public class SysHub : Hub<ISysHub>
{
/// <summary>
/// 分隔符
/// </summary>
public const string Separate = "_s_e_p_a_r_a_t_e_";
private readonly ILogger<ISysHub> _logger;
private readonly IServiceScope _serviceScope;
/// <inheritdoc cref="ISysHub"/>
public SysHub(IServiceScopeFactory scopeFactory, ILogger<ISysHub> logger)
{
_serviceScope = scopeFactory.CreateScope();
_logger = logger;
}
/// <summary>
/// 连接
/// </summary>
/// <returns></returns>
public override async Task OnConnectedAsync()
{
var feature = Context.Features.Get<IHttpContextFeature>();
var VerificatId = feature.HttpContext.Request.Headers[ClaimConst.VerificatId].FirstOrDefault().ToLong();
var userIdentifier = Context.UserIdentifier;//自定义的Id
await UpdateVerificatAsync(userIdentifier, verificat: VerificatId);//更新cache
await base.OnConnectedAsync();
}
/// <summary>
/// 断开连接
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public override async Task OnDisconnectedAsync(Exception exception)
{
var userIdentifier = Context.UserIdentifier;//自定义的Id
await UpdateVerificatAsync(userIdentifier, false);//更新cache
await base.OnDisconnectedAsync(exception);
}
#region
/// <summary>
/// 更新cache
/// </summary>
/// <param name="userIdentifier">用户id</param>
/// <param name="verificat">上线时的验证id</param>
/// <param name="isConnect">是否是上线</param>
private async Task UpdateVerificatAsync(string userIdentifier, bool isConnect = true, long verificat = 0)
{
var userId = userIdentifier.Split(Separate)[0].ToLong();//分割取第一个
if (userId > 0)
{
var _verificatService = _serviceScope.ServiceProvider.GetService<IVerificatService>();
//获取cache当前用户的verificat信息列表
List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(userId);
if (verificatInfos != null)
{
if (isConnect)
{
//获取cache中当前verificat
var verificatInfo = verificatInfos.Where(it => it.Id == verificat).FirstOrDefault();
if (verificatInfo != null)
{
verificatInfo.ClientIds.Add(userIdentifier);//添加到客户端列表
await _verificatService.SetVerificatIdAsync(userId, verificatInfos);
}
}
else
{
//获取当前客户端ID所在的verificat信息
var verificatInfo = verificatInfos.Where(it => it.ClientIds.Contains(userIdentifier)).FirstOrDefault();
if (verificatInfo != null)
{
verificatInfo.ClientIds.RemoveWhere(it => it == userIdentifier);//从客户端列表删除
await _verificatService.SetVerificatIdAsync(userId, verificatInfos);
}
}
}
}
}
#endregion
}

View File

@@ -1,39 +0,0 @@
#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 Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// AppStartup启动类
/// </summary>
[AppStartup(9997)]
public class Startup : AppStartup
{
/// <summary>
/// 配置
/// </summary>
public void ConfigureServices(IServiceCollection services)
{
// 任务调度
services.AddSchedule(options =>
{
options.AddPersistence<JobPersistence>();
});
//事件总线
services.AddEventBus();
}
}

View File

@@ -1,53 +0,0 @@
#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;
using Furion.EventBus;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 认证模块事件总线
/// </summary>
public class AuthEventSubscriber : IEventSubscriber, ISingleton
{
/// <summary>
/// 登录事件
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
[EventSubscribe(EventSubscriberConst.Login)]
public async Task Login(EventHandlerExecutingContext context)
{
var loginEvent = (LoginEvent)context.Source.Payload;//获取参数
var sysUser = loginEvent.SysUser;
var db = DbContext.Db.CopyNew();
#region ,
db.Tracking(sysUser);//创建跟踪,只更新修改字段
sysUser.LastLoginDevice = sysUser.LatestLoginDevice;
sysUser.LastLoginIp = sysUser.LatestLoginIp;
sysUser.LastLoginTime = sysUser.LatestLoginTime;
sysUser.LatestLoginDevice = loginEvent.Device.ToString();
sysUser.LatestLoginIp = loginEvent.Ip;
sysUser.LatestLoginTime = loginEvent.DateTime;
#endregion ,
//更新用户信息
if (await db.UpdateableWithAttr(sysUser).ExecuteCommandAsync() > 0)
{
App.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSUSER + sysUser.Id, sysUser, false); //更新Cache信息
}
}
}

View File

@@ -1,59 +0,0 @@
#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;
using Furion.EventBus;
using Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 用户模块事件总线
/// </summary>
public class UserEventSubscriber : IEventSubscriber, ISingleton
{
private readonly IServiceProvider _services;
/// <summary>
/// <inheritdoc cref="UserEventSubscriber"/>
/// </summary>
/// <param name="services"></param>
public UserEventSubscriber(IServiceProvider services)
{
_services = services;
}
/// <summary>
/// 根据角色ID列表清除用户缓存
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
[EventSubscribe(EventSubscriberConst.ClearUserCache)]
public async Task DeleteUserCacheByRoleIds(EventHandlerExecutingContext context)
{
var roleIds = (List<long>)context.Source.Payload;//获取角色ID
// 创建新的作用域
using var scope = _services.CreateScope();
// 解析角色服务
var relationService = scope.ServiceProvider.GetRequiredService<IRelationService>();
//获取用户和角色关系
var relations = await relationService.GetRelationListByTargetIdListAndCategoryAsync(roleIds.Select(it => it.ToString()).ToList(), CateGoryConst.Relation_SYS_USER_HAS_ROLE);
if (relations.Count > 0)
{
var userIds = relations.Select(it => it.ObjectId).ToArray();//用户ID列表
// 解析用户服务
var userService = scope.ServiceProvider.GetRequiredService<ISysUserService>();
//从缓存中删除
userService.DeleteUserFromCache(userIds);
}
}
}

View File

@@ -1,240 +0,0 @@
#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.DataEncryption;
using Furion.EventBus;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System.Security.Claims;
using ThingsGateway.Foundation.Extension.String;
using Yitter.IdGenerator;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IAuthService"/>
public class AuthService : IAuthService
{
private readonly IConfigService _configService;
private readonly IEventPublisher _eventPublisher;
private readonly INoticeService _noticeService;
private readonly IServiceScope _serviceScope;
private readonly ISysUserService _userService;
private readonly IVerificatService _verificatService;
/// <inheritdoc cref="IAuthService"/>
public AuthService(
IEventPublisher eventPublisher,
ISysUserService userService,
IConfigService configService,
IVerificatService verificatService,
INoticeService noticeService, IServiceScopeFactory serviceScopeFactory
)
{
_eventPublisher = eventPublisher;
_userService = userService;
_configService = configService;
_verificatService = verificatService;
_noticeService = noticeService;
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
public ValidCodeOutput GetCaptchaInfo()
{
//生成验证码
var captchInfo = new Random().Next(1111, 9999).ToString();
//生成请求号并将验证码放入cache
var reqNo = YitIdHelper.NextId();
//插入cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.LOGIN_CAPTCHA + reqNo, captchInfo, TimeSpan.FromMinutes(1), false);
//返回验证码和请求号
return new ValidCodeOutput { CodeValue = captchInfo, ValidCodeReqNo = reqNo };
}
/// <inheritdoc/>
public async Task<SysUser> GetLoginUserAsync()
{
return await _userService.GetUserByIdAsync(UserManager.UserId);
}
/// <inheritdoc/>
public async Task<LoginOutput> LoginAsync(LoginInput input)
{
//判断是否有验证码
var sysBase = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_CAPTCHA_OPEN);
if (sysBase != null)//如果有这个配置项
{
if (sysBase.ConfigValue.ToBool(false))//如果需要验证码
{
//如果没填验证码,提示验证码不能为空
if (input.ValidCode.IsNullOrEmpty() || input.ValidCodeReqNo == 0) throw Oops.Bah("验证码不能为空").StatusCode(410);
ValidValidCode(input.ValidCode, input.ValidCodeReqNo);//校验验证码
}
}
var password = DESCEncryption.Decrypt(input.Password, DESCKeyConst.DESCKey); // 解密
var userInfo = await _userService.GetUserByAccountAsync(input.Account) ?? throw Oops.Bah("用户不存在");//获取用户信息
if (userInfo.Password != password) throw Oops.Bah("账号密码错误");//账号密码错误
return await LoginAsync(userInfo, input.Device);
}
/// <inheritdoc/>
public async Task LogoutAsync()
{
//获取用户信息
var userinfo = await _userService.GetUserByAccountAsync(UserManager.UserAccount);
if (userinfo != null)
{
LoginEvent loginEvent = new()
{
Ip = App.HttpContext.GetRemoteIpAddressToIPv4(),
SysUser = userinfo,
VerificatId = UserManager.VerificatId.ToLong(),
};
await RemoveVerificatAsync(loginEvent);//移除验证Id
}
}
/// <summary>
/// 校验验证码方法
/// </summary>
/// <param name="validCode">验证码</param>
/// <param name="validCodeReqNo">请求号</param>
/// <param name="isDelete">是否从Cache删除</param>
private void ValidValidCode(string validCode, long validCodeReqNo, bool isDelete = true)
{
var code = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<string>(CacheConst.LOGIN_CAPTCHA + validCodeReqNo, false);//从cache拿数据
if (isDelete) _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.LOGIN_CAPTCHA + validCodeReqNo);//删除验证码
if (code != null)//如果有
{
//验证码如果不匹配直接抛错误,这里忽略大小写
if (validCode.ToLower() != code.ToLower()) throw Oops.Bah("验证码错误");
}
else
{
throw Oops.Bah("验证码已过期");
}
}
/// <summary>
/// 执行B端登录
/// </summary>
/// <param name="sysUser">用户信息</param>
/// <param name="device">登录设备</param>
/// <returns></returns>
private async Task<LoginOutput> LoginAsync(SysUser sysUser, AuthDeviceTypeEnum device)
{
if (sysUser.UserEnable == false) throw Oops.Bah("账号已停用");//账号已停用
var sysBase = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_VERIFICAT_EXPIRES);
var sessionid = YitIdHelper.NextId();
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimConst.VerificatId, sessionid.ToString()));
identity.AddClaim(new Claim(ClaimConst.UserId, sysUser.Id.ToString()));
identity.AddClaim(new Claim(ClaimConst.Account, sysUser.Account));
identity.AddClaim(new Claim(ClaimConst.IsSuperAdmin, sysUser.RoleCodeList.Contains(RoleConst.SuperAdmin).ToString()));
identity.AddClaim(new Claim(ClaimConst.IsOpenApi, false.ToString()));
var config = sysBase.ConfigValue.ToInt(2880);
var diffTime = DateTimeExtensions.CurrentDateTime.AddMinutes(config);
await App.HttpContext.SignInAsync(new ClaimsPrincipal(identity), new AuthenticationProperties()
{
IsPersistent = true,
ExpiresUtc = diffTime,
});
//登录事件参数
var loginEvent = new LoginEvent
{
Ip = App.HttpContext.GetRemoteIpAddressToIPv4(),
Device = device,
Expire = config,
SysUser = sysUser,
VerificatId = sessionid,
};
await SetVerificatAsync(loginEvent);//写入verificat
await _eventPublisher.PublishAsync(EventSubscriberConst.Login, loginEvent); //发布登录事件总线
return new LoginOutput { VerificatId = sessionid, Account = sysUser.Account };
}
private async Task RemoveVerificatAsync(LoginEvent loginEvent)
{
//获取verificat列表
List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(loginEvent.SysUser.Id);
if (verificatInfos != null)
{
//获取当前用户的verificat
var verificat = verificatInfos.Where(it => it.Id == loginEvent.VerificatId).FirstOrDefault();
if (verificat != null)
verificatInfos.Remove(verificat);
//更新verificat列表
await _verificatService.SetVerificatIdAsync(loginEvent.SysUser.Id, verificatInfos);
}
await App.HttpContext?.SignOutAsync();
App.HttpContext?.SignoutToSwagger();
}
/// <summary>
/// 写入验证信息到缓存
/// </summary>
/// <param name="loginEvent"></param>
/// <returns></returns>
private async Task SetVerificatAsync(LoginEvent loginEvent)
{
//获取verificat列表
List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(loginEvent.SysUser.Id);
var verificatTimeout = loginEvent.DateTime.AddMinutes(loginEvent.Expire);
//生成verificat信息
var verificatInfo = new VerificatInfo
{
Device = loginEvent.Device.ToString(),
Expire = loginEvent.Expire,
VerificatTimeout = verificatTimeout,
Id = loginEvent.VerificatId,
UserId = loginEvent.SysUser.Id,
};
if (verificatInfos != null)
{
bool isSingle = false;//默认不开启单用户登录
var singleConfig = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SINGLE_OPEN);//获取系统单用户登录选项
if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBool(false);//如果配置不为空则设置单用户登录选项为系统配置的值
if (isSingle)//判断是否单用户登录
{
await _noticeService.LogoutAsync(loginEvent.SysUser.Id, verificatInfos.Where(it => it.Device == loginEvent.Device.ToString()).ToList(), "该账号已在别处登录!");//通知其他用户下线
verificatInfos = verificatInfos.Where(it => it.Device != loginEvent.Device.ToString()).ToList();//去掉当前登录类型
verificatInfos.Add(verificatInfo);//添加到列表
}
else
{
verificatInfos.Add(verificatInfo);
}
}
else
{
verificatInfos = new List<VerificatInfo> { verificatInfo };//直接就一个
}
//添加到verificat列表
await _verificatService.SetVerificatIdAsync(loginEvent.SysUser.Id, verificatInfos);
}
}

View File

@@ -1,78 +0,0 @@
#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 System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 登录输入参数
/// </summary>
public class LoginInput : ValidCodeInput
{
/// <summary>
/// 账号
///</summary>
[Required(ErrorMessage = "账号不能为空"), MinLength(3, ErrorMessage = "账号不能少于4个字符")]
public string Account { get; set; }
/// <summary>
/// 设备类型默认PC
/// </summary>
/// <example>0</example>
public AuthDeviceTypeEnum Device { get; set; } = AuthDeviceTypeEnum.PC;
/// <summary>
/// 密码
///</summary>
[Required(ErrorMessage = "密码不能为空"), MinLength(3, ErrorMessage = "密码不能少于3个字符")]
public string Password { get; set; }
}
/// <summary>
/// 验证码输入
/// </summary>
public class ValidCodeInput
{
/// <summary>
/// 验证码
/// </summary>
public string ValidCode { get; set; }
/// <summary>
/// 请求号
/// </summary>
public long ValidCodeReqNo { get; set; }
}
/// <summary>
/// 登录设备类型枚举
/// </summary>
public enum AuthDeviceTypeEnum
{
/// <summary>
/// PC端
/// </summary>
[Description("PC端")]
PC,
/// <summary>
/// 移动端
/// </summary>
[Description("移动端")]
APP,
/// <summary>
/// Api
/// </summary>
[Description("Api")]
Api,
}

View File

@@ -1,51 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 登录返回参数
/// </summary>
public class BaseLoginOutput
{
/// <summary>
/// 账号
/// </summary>
public string Account { get; set; }
/// <summary>
/// 验证ID
/// </summary>
public long VerificatId { get; set; }
}
/// <summary>
/// 验证码值返回
/// </summary>
public class ValidCodeOutput
{
/// <summary>
/// 验证码值
/// </summary>
public string CodeValue { get; set; }
/// <summary>
/// 验证码请求号
/// </summary>
public long ValidCodeReqNo { get; set; }
}
/// <summary>
/// 登录返回参数
/// </summary>
public class LoginOutput : BaseLoginOutput
{
}

View File

@@ -1,49 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 登录事件参数
/// </summary>
public class LoginEvent
{
/// <summary>
/// 时间
/// </summary>
public DateTime DateTime = DateTimeExtensions.CurrentDateTime;
/// <summary>
/// 登录设备
/// </summary>
public AuthDeviceTypeEnum Device { get; set; }
/// <summary>
/// 过期时间(分)
/// </summary>
public int Expire { get; set; }
/// <summary>
/// Ip地址
/// </summary>
public string Ip { get; set; }
/// <summary>
/// 用户信息
/// </summary>
public SysUser SysUser { get; set; }
/// <summary>
/// 验证Id
/// </summary>
public long VerificatId { get; set; }
}

View File

@@ -1,44 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 权限校验服务
/// </summary>
public interface IAuthService : ITransient
{
/// <summary>
/// 生成验证码
/// </summary>
/// <returns></returns>
ValidCodeOutput GetCaptchaInfo();
/// <summary>
/// 获取登录用户信息
/// </summary>
/// <returns></returns>
Task<SysUser> GetLoginUserAsync();
/// <summary>
/// 登录
/// </summary>
Task<LoginOutput> LoginAsync(LoginInput input);
/// <summary>
/// 退出登录
/// </summary>
/// <returns></returns>
Task LogoutAsync();
}

View File

@@ -1,163 +0,0 @@
#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;
using Furion.FriendlyException;
using Mapster;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="IButtonService"/>
/// </summary>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class ButtonService : DbRepository<SysResource>, IButtonService
{
private readonly IRelationService _relationService;
private readonly IResourceService _resourceService;
/// <inheritdoc cref="IButtonService"/>
public ButtonService(
IResourceService resourceService,
IRelationService relationService
)
{
_resourceService = resourceService;
_relationService = relationService;
}
/// <inheritdoc />
public async Task AddAsync(ButtonAddInput input)
{
await CheckInputAsync(input);//检查参数
var sysResource = input.Adapt<SysResource>();//实体转换
if (await InsertAsync(sysResource))//插入数据
_resourceService.RefreshCache(ResourceCategoryEnum.BUTTON);//刷新缓存
}
/// <inheritdoc />
[OperDesc("删除按钮")]
public async Task DeleteAsync(params long[] input)
{
//获取所有ID
var ids = input.ToList();
//获取所有按钮集合
var buttonList = await _resourceService.GetListByCategoryAsync(ResourceCategoryEnum.BUTTON);
#region
//获取所有菜单集合
var menuList = await _resourceService.GetListByCategoryAsync(ResourceCategoryEnum.MENU);
//获取按钮的父菜单id集合
var parentIds = buttonList.Where(it => ids.Contains(it.Id)).Select(it => it.ParentId.ToString()).ToList();
//获取关系表分类为SYS_ROLE_HAS_RESOURCE数据
var roleResources = await _relationService.GetRelationByCategoryAsync(CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);
//获取相关关系表数据
var relationList = roleResources
.Where(it => parentIds.Contains(it.TargetId))//目标ID是父ID中
.Where(it => it.ExtJson != null).ToList();//扩展信息不为空
//遍历关系表
relationList.ForEach(it =>
{
var relationRoleResuorce = it.ExtJson.FromJsonString<RelationRoleResuorce>();//拓展信息转实体
var buttonInfo = relationRoleResuorce.ButtonInfo;//获取按钮信息
if (buttonInfo.Count > 0)
{
var diffArr = buttonInfo.Where(it => !buttonInfo.Contains(it)).ToList(); //找出不同的元素(即交集的补集)
relationRoleResuorce.ButtonInfo = diffArr;//重新赋值按钮信息
it.ExtJson = relationRoleResuorce.ToJsonString();//重新赋值拓展信息
}
});
#endregion
//事务
var result = await itenant.UseTranAsync(async () =>
{
await DeleteByIdsAsync(ids.Cast<object>().ToArray());//删除按钮
if (relationList.Count > 0)
{
await Context.Updateable(relationList).UpdateColumns(it => it.ExtJson).ExecuteCommandAsync();//修改拓展信息
}
});
if (result.IsSuccess)//如果成功了
{
_resourceService.RefreshCache(ResourceCategoryEnum.BUTTON);//资源表按钮刷新缓存
}
else
{
throw Oops.Oh(result.ErrorMessage);
}
}
/// <inheritdoc />
[OperDesc("编辑按钮")]
public async Task EditAsync(ButtonEditInput input)
{
await CheckInputAsync(input);//检查参数
var sysResource = input.Adapt<SysResource>();//实体转换
//事务
var result = await itenant.UseTranAsync(async () =>
{
await UpdateAsync(sysResource); //更新按钮
});
if (result.IsSuccess)//如果成功了
{
_resourceService.RefreshCache(ResourceCategoryEnum.BUTTON);//资源表按钮刷新缓存
}
else
{
throw Oops.Oh(result.ErrorMessage);
}
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<SysResource>> PageAsync(ButtonPageInput input)
{
var query = Context.Queryable<SysResource>()
.Where(it => it.ParentId == input.ParentId && it.Category == ResourceCategoryEnum.BUTTON)
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Title.Contains(input.SearchKey) || it.Component.Contains(input.SearchKey));//根据关键字查询
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
query = query.OrderBy(it => it.SortCode);//排序
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
#region
/// <summary>
/// 检查输入参数
/// </summary>
/// <param name="sysResource"></param>
private async Task CheckInputAsync(SysResource sysResource)
{
//获取所有按钮和菜单
var buttonList = await _resourceService.GetListByCategorysAsync(new List<ResourceCategoryEnum> { ResourceCategoryEnum.BUTTON, ResourceCategoryEnum.MENU });
//判断code是否重复
if (buttonList.Any(it => it.Code == sysResource.Code && it.Id != sysResource.Id))
throw Oops.Bah($"存在重复的按钮编码:{sysResource.Code}");
//判断菜单是否存在
if (!buttonList.Any(it => it.Id == sysResource.ParentId))
throw Oops.Bah($"不存在的父级菜单:{sysResource.ParentId}");
sysResource.Category = ResourceCategoryEnum.BUTTON;//设置分类为按钮
}
#endregion
}

View File

@@ -1,61 +0,0 @@
#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 System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 添加按钮参数
/// </summary>
public class ButtonAddInput : SysResource
{
/// <summary>
/// 编码
/// </summary>
[Required(ErrorMessage = "Code不能为空")]
public override string Code { get; set; }
/// <summary>
/// 父ID
/// </summary>
[Required(ErrorMessage = "ParentId不能为空")]
public override long ParentId { get; set; }
/// <summary>
/// 标题
/// </summary>
[Required(ErrorMessage = "Title不能为空")]
public override string Title { get; set; }
}
/// <summary>
/// 按钮分页
/// </summary>
public class ButtonPageInput : BasePageInput
{
/// <summary>
/// 父ID
/// </summary>
[Required(ErrorMessage = "ParentId不能为空")]
public long? ParentId { get; set; }
}
/// <summary>
/// 按钮编辑
/// </summary>
public class ButtonEditInput : ButtonAddInput
{
/// <summary>
/// ID
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}

View File

@@ -1,51 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 权限按钮服务
/// </summary>
public interface IButtonService : ITransient
{
/// <summary>
/// 添加按钮
/// </summary>
/// <param name="input">添加参数</param>
/// <returns></returns>
Task AddAsync(ButtonAddInput input);
/// <summary>
/// 删除按钮
/// </summary>
/// <param name="input">删除参数</param>
/// <returns></returns>
Task DeleteAsync(params long[] input);
/// <summary>
/// 编辑按钮
/// </summary>
/// <param name="input">编辑参数</param>
/// <returns></returns>
Task EditAsync(ButtonEditInput input);
/// <summary>
/// 按钮分页查询
/// </summary>
/// <param name="input">查询条件</param>
/// <returns>按钮分页列表</returns>
Task<ISqlSugarPagedList<SysResource>> PageAsync(ButtonPageInput input);
}

View File

@@ -1,137 +0,0 @@
#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;
using Furion.FriendlyException;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IConfigService"/>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class ConfigService : DbRepository<SysConfig>, IConfigService
{
private readonly IServiceScope _serviceScope;
public ConfigService(IServiceScopeFactory serviceScopeFactory)
{
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
[OperDesc("编辑网关系统配置")]
public async Task EditBatchAsync(List<SysConfig> sysConfigs)
{
if (await UpdateRangeAsync(sysConfigs))
RefreshCache(sysConfigs.FirstOrDefault()?.Category);//刷新缓存
}
/// <inheritdoc/>
[OperDesc("添加配置项")]
public async Task AddAsync(ConfigAddInput input)
{
await CheckInputAsync(input);//检查
var sysConfig = input.Adapt<SysConfig>();//实体转换
if (await InsertAsync(sysConfig))//插入数据)
RefreshCache(input.Category);//刷新缓存
}
/// <inheritdoc/>
[OperDesc("删除配置项")]
public async Task DeleteAsync(params long[] input)
{
await AsDeleteable().Where(it => input.Contains(it.Id)).ExecuteCommandAsync();
RefreshCache(ConfigConst.SYS_CONFIGOTHER);//刷新缓存
}
/// <inheritdoc/>
[OperDesc("编辑配置项")]
public async Task EditAsync(ConfigEditInput input)
{
await CheckInputAsync(input);
var sysConfig = input.Adapt<SysConfig>();//实体转换
if (await UpdateAsync(sysConfig))//更新数据
RefreshCache(input.Category);//刷新缓存
}
/// <inheritdoc/>
public async Task<SysConfig> GetByConfigKeyAsync(string category, string configKey)
{
var configList = await GetListByCategoryAsync(category);//获取系统配置列表
return configList.FirstOrDefault(it => it.ConfigKey == configKey);//根据configkey获取对应值
}
/// <inheritdoc/>
public async Task<List<SysConfig>> GetListByCategoryAsync(string category)
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var configList = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysConfig>>(CacheConst.SYS_CONFIGCATEGORY + category, true);
if (configList == null)
{
//cache没有再去数据可拿
configList = await Context.Queryable<SysConfig>().Where(it => it.Category == category).OrderBy(it => it.SortCode).ToListAsync();//获取系统配置列表
if (configList.Count > 0)
{
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.SYS_CONFIGCATEGORY + category, configList, true);//如果不为空,插入cache
}
}
return configList;
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<SysConfig>> PageAsync(ConfigPageInput input)
{
var query = Context.Queryable<SysConfig>()
.Where(it => it.Category == ConfigConst.SYS_CONFIGOTHER)//自定义配置
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.ConfigKey.Contains(input.SearchKey) || it.ConfigKey.Contains(input.SearchKey));
//根据关键字查询
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
query = query.OrderBy(it => it.SortCode);//排序
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
#region
/// <summary>
/// 检查输入参数,并设置分类为自定义分类
/// </summary>
/// <param name="sysConfig"></param>
private async Task CheckInputAsync(SysConfig sysConfig)
{
var configs = await GetListByCategoryAsync(sysConfig.Category);//获取全部字典
var hasSameKey = configs.Any(it => it.ConfigKey == sysConfig.ConfigKey && it.Id != sysConfig.Id);
//判断是否从存在重复字典名
if (hasSameKey)
{
throw Oops.Bah($"存在重复的配置键:{sysConfig.ConfigKey}");
}
sysConfig.Category = ConfigConst.SYS_CONFIGOTHER;
}
/// <summary>
/// 刷新缓存
/// </summary>
/// <param name="category">分类</param>
/// <returns></returns>
private void RefreshCache(string category)
{
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.SYS_CONFIGCATEGORY + category);//cache删除
}
#endregion
}

View File

@@ -1,65 +0,0 @@
#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 System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 添加配置参数
/// </summary>
public class ConfigAddInput : SysConfig
{
/// <summary>
/// 分类
/// </summary>
[Required(ErrorMessage = "Category不能为空")]
public override string Category { get; set; } = ConfigConst.SYS_CONFIGOTHER;
/// <summary>
/// 配置键
/// </summary>
[Required(ErrorMessage = "configKey不能为空")]
public override string ConfigKey { get; set; }
/// <summary>
/// 配置值
/// </summary>
[Required(ErrorMessage = "ConfigValue不能为空")]
public override string ConfigValue { get; set; }
}
/// <summary>
/// 编辑配置参数
/// </summary>
public class ConfigEditInput : ConfigAddInput
{
/// <summary>
/// ID
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}
/// <summary>
/// 配置分页参数
/// </summary>
public class ConfigPageInput : BasePageInput
{
/// <summary>
/// 分类
/// </summary>
[Description("分类")]
public string Category { get; set; }
}

View File

@@ -1,70 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 系统配置服务
/// </summary>
public interface IConfigService : ITransient
{
/// <summary>
/// 批量编辑系统配置
/// </summary>
/// <param name="configs">配置列表</param>
/// <returns></returns>
Task EditBatchAsync(List<SysConfig> configs);
/// <summary>
/// 新增自定义配置
/// </summary>
/// <param name="input">新增参数</param>
/// <returns></returns>
Task AddAsync(ConfigAddInput input);
/// <summary>
/// 删除自定义配置
/// </summary>
/// <param name="input">删除</param>
/// <returns></returns>
Task DeleteAsync(params long[] input);
/// <summary>
/// 修改自定义配置
/// </summary>
/// <param name="input">修改参数</param>
/// <returns></returns>
Task EditAsync(ConfigEditInput input);
/// <summary>
/// 根据分类和配置键获配置
/// </summary>
/// <param name="category">分类</param>
/// <param name="configKey">配置键</param>
/// <returns>配置信息</returns>
Task<SysConfig> GetByConfigKeyAsync(string category, string configKey);
/// <summary>
/// 根据分类获取配置列表
/// </summary>
/// <param name="category">分类名称</param>
/// <returns>配置列表</returns>
Task<List<SysConfig>> GetListByCategoryAsync(string category);
/// <summary>
/// 分页查询自定义配置
/// </summary>
/// <param name="input">查询参数</param>
/// <returns>其他配置列表</returns>
Task<ISqlSugarPagedList<SysConfig>> PageAsync(ConfigPageInput input);
}

View File

@@ -1,38 +0,0 @@
#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.FriendlyException;
using Microsoft.AspNetCore.Components.Forms;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="IFileService"/>
/// </summary>
public class FileService : IFileService
{
/// <inheritdoc/>
public void ImportVerification(IBrowserFile file, int maxSzie = 300, string[] allowTypes = null)
{
if (file == null) throw Oops.Bah("文件不能为空");
if (file.Size > maxSzie * 1024 * 1024) throw Oops.Bah($"文件大小不允许超过{maxSzie}M");
var fileSuffix = Path.GetExtension(file.Name).ToLower().Split(".")[1]; // 文件后缀
string[] allowTypeS = allowTypes ?? new string[] { "xlsx" };//允许上传的文件类型
if (!allowTypeS.Contains(fileSuffix)) throw Oops.Bah(errorMessage: "文件格式错误");
}
}

View File

@@ -1,35 +0,0 @@
#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;
using Microsoft.AspNetCore.Components.Forms;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 文件管理服务
/// </summary>
public interface IFileService : ITransient
{
/// <summary>
/// 验证上传文件
/// </summary>
/// <param name="file">文件</param>
/// <param name="maxSzie">最大体积(M)</param>
/// <param name="allowTypes">允许上传类型</param>
void ImportVerification(IBrowserFile file, int maxSzie = 30, string[] allowTypes = null);
}

View File

@@ -1,91 +0,0 @@
#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 System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 添加菜单参数
/// </summary>
public class MenuAddInput : SysResource, IValidatableObject
{
/// <summary>
/// 路径
/// </summary>
public override string Component { get; set; }
/// <summary>
/// 图标
/// </summary>
[Required(ErrorMessage = "Icon不能为空")]
public override string Icon { get; set; }
/// <summary>
/// 父ID
/// </summary>
[Required(ErrorMessage = "ParentId不能为空")]
public override long ParentId { get; set; }
/// <summary>
/// 菜单类型
/// </summary>
public override TargetTypeEnum TargetType { get; set; } = TargetTypeEnum.SELF;
/// <summary>
/// 标题
/// </summary>
[Required(ErrorMessage = "Title不能为空")]
public override string Title { get; set; }
/// <summary>
/// 特殊验证
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//如果菜单类型是菜单
if (TargetType == TargetTypeEnum.SELF)
{
if (string.IsNullOrEmpty(Component))
yield return new ValidationResult("路径不能为空", new[] { nameof(Component) });
}
//设置分类为菜单
Category = ResourceCategoryEnum.MENU;
}
}
/// <summary>
/// 编辑菜单输入参数
/// </summary>
public class MenuEditInput : MenuAddInput
{
/// <summary>
/// ID
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}
/// <summary>
/// 菜单树查询参数
/// </summary>
public class MenuPageInput : BasePageInput
{
/// <summary>
/// 父ID
/// </summary>
[Required(ErrorMessage = "ParentId不能为空")]
public long ParentId { get; set; }
}

View File

@@ -1,56 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 菜单服务
/// </summary>
public interface IMenuService : ITransient
{
/// <summary>
/// 添加菜单
/// </summary>
/// <param name="input">添加参数</param>
/// <returns></returns>
Task AddAsync(MenuAddInput input);
/// <summary>
/// 删除菜单
/// </summary>
/// <param name="input">删除菜单参数</param>
/// <returns></returns>
Task DeleteAsync(params long[] input);
/// <summary>
/// 详情
/// </summary>
/// <param name="input">id</param>
/// <returns>详细信息</returns>
Task<SysResource> DetailAsync(BaseIdInput input);
/// <summary>
/// 编辑菜单
/// </summary>
/// <param name="input">菜单编辑参数</param>
/// <returns></returns>
Task EditAsync(MenuEditInput input);
/// <summary>
/// 根据模块获取菜单树
/// </summary>
/// <param name="input">菜单树查询参数</param>
/// <returns>菜单树列表</returns>
Task<List<SysResource>> TreeAsync(MenuPageInput input);
}

View File

@@ -1,166 +0,0 @@
#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;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="IMenuService"/>
/// </summary>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class MenuService : DbRepository<SysResource>, IMenuService
{
private readonly IRelationService _relationService;
private readonly IResourceService _resourceService;
private readonly IRoleService _roleService;
/// <inheritdoc cref="IMenuService"/>
public MenuService(IResourceService resourceService, IRelationService relationService, IRoleService roleService)
{
_roleService = roleService;
_resourceService = resourceService;
_relationService = relationService;
}
/// <inheritdoc />
[OperDesc("添加菜单")]
public async Task AddAsync(MenuAddInput input)
{
await CheckInputAsync(input);//检查参数
var sysResource = input.Adapt<SysResource>();//实体转换
if (await InsertAsync(sysResource))//插入数据
_resourceService.RefreshCache(ResourceCategoryEnum.MENU);//刷新菜单缓存
}
/// <inheritdoc />
[OperDesc("删除菜单")]
public async Task DeleteAsync(params long[] input)
{
//获取所有ID
var ids = input.ToList();
if (ids.Count > 0)
{
//获取所有菜单和按钮
var resourceList = await _resourceService.GetListByCategorysAsync(new List<ResourceCategoryEnum> { ResourceCategoryEnum.MENU, ResourceCategoryEnum.BUTTON });
//找到要删除的菜单
var sysResources = resourceList.Where(it => ids.Contains(it.Id)).ToList();
//查找内置菜单
var system = sysResources.Where(it => it.Code == ResourceConst.System).FirstOrDefault();
if (system != null)
throw Oops.Bah($"不可删除系统菜单:{system.Title}");
//需要删除的资源ID列表
var resourceIds = new List<long>();
//遍历菜单列表
sysResources.ForEach(it =>
{
//获取菜单所有子节点
var child = _resourceService.GetChildListById(resourceList, it.Id, false);
//将子节点ID添加到删除资源ID列表
resourceIds.AddRange(child.Select(it => it.Id).ToList());
resourceIds.Add(it.Id);//添加到删除资源ID列表
});
ids.AddRange(resourceIds);//添加到删除ID列表
//事务
var result = await itenant.UseTranAsync(async () =>
{
await DeleteByIdsAsync(ids.Cast<object>().ToArray());//删除菜单和按钮
await Context.Deleteable<SysRelation>()//关系表删除对应SYS_ROLE_HAS_RESOURCE
.Where(it => it.Category == CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE && resourceIds.Contains(SqlFunc.ToInt64(it.TargetId))).ExecuteCommandAsync();
});
if (result.IsSuccess)//如果成功了
{
_resourceService.RefreshCache(ResourceCategoryEnum.MENU);//资源表菜单刷新缓存
_resourceService.RefreshCache(ResourceCategoryEnum.BUTTON);//资源表按钮刷新缓存
_relationService.RefreshCache(CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);//关系表刷新缓存
}
else
{
//写日志
throw Oops.Oh(result.ErrorMessage);
}
}
}
/// <inheritdoc />
public async Task<SysResource> DetailAsync(BaseIdInput input)
{
var sysResources = await _resourceService.GetListByCategoryAsync(ResourceCategoryEnum.MENU);
var resource = sysResources.Where(it => it.Id == input.Id).FirstOrDefault();
return resource;
}
/// <inheritdoc />
[OperDesc("编辑菜单")]
public async Task EditAsync(MenuEditInput input)
{
await CheckInputAsync(input);//检查参数
var sysResource = input.Adapt<SysResource>();//实体转换
if (await UpdateAsync(sysResource))//更新数据
{
_resourceService.RefreshCache(ResourceCategoryEnum.MENU);//刷新菜单缓存
//需要更新资源权限,因为地址可能改变,页面权限需要更改
await _roleService.RefreshResourceAsync(input.Id);
}
}
/// <inheritdoc />
public async Task<List<SysResource>> TreeAsync(MenuPageInput input)
{
//获取所有菜单
var sysResources = await _resourceService.GetListByCategoryAsync(ResourceCategoryEnum.MENU);
sysResources = sysResources
.Where(it => it.ParentId == input.ParentId)
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Title == input.SearchKey)//根据关键字查找
.ToList();
//构建菜单树
var tree = _resourceService.ResourceListToTree(sysResources, input.ParentId);
return tree;
}
#region
/// <summary>
/// 检查输入参数
/// </summary>
/// <param name="sysResource"></param>
private async Task CheckInputAsync(SysResource sysResource)
{
//获取所有菜单列表
var menList = await _resourceService.GetListByCategoryAsync(ResourceCategoryEnum.MENU);
//判断是否有同级且同名的菜单
if (menList.Any(it => it.ParentId == sysResource.ParentId && it.Title == sysResource.Title && it.Id != sysResource.Id))
throw Oops.Bah($"存在重复的菜单名称:{sysResource.Title}");
if (sysResource.ParentId != 0)
{
//获取父级,判断父级ID正不正确
var parent = menList.Where(it => it.Id == sysResource.ParentId).FirstOrDefault();
if (parent != null)
{
if (parent.Id == sysResource.Id)
throw Oops.Bah($"上级菜单不能选择自己");
}
else
{
throw Oops.Bah($"上级菜单不存在:{sysResource.ParentId}");
}
}
}
#endregion
}

View File

@@ -1,30 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 通知服务
/// </summary>
public interface INoticeService : ITransient
{
/// <summary>
/// 通知用户下线
/// </summary>
/// <param name="userId">用户ID</param>
/// <param name="verificatInfos">验证列表</param>
/// <param name="message">消息内容</param>
/// <returns></returns>
Task LogoutAsync(long userId, List<VerificatInfo> verificatInfos, string message);
}

View File

@@ -1,43 +0,0 @@
#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 Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="INoticeService"/>
/// </summary>
public class NoticeService : INoticeService
{
private readonly IServiceScope _serviceScope;
public NoticeService(IServiceScopeFactory serviceScopeFactory)
{
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
public async Task LogoutAsync(long userId, List<VerificatInfo> verificatInfos, string message)
{
//客户端ID列表
var clientIds = new List<string>();
//遍历cancellationToken列表获取客户端ID列表
verificatInfos.ForEach(it =>
{
clientIds.AddRange(it.ClientIds);
});
//获取signalr实例
var signalr = _serviceScope.ServiceProvider.GetService<IHubContext<SysHub, ISysHub>>();
//发送其他客户端登录消息
await signalr.Clients.Users(clientIds).Logout(message);
}
}

View File

@@ -1,27 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 操作日志分页输入
/// </summary>
public class OperateLogPageInput : VisitLogPageInput
{
}
/// <summary>
/// 操作日志分页输入
/// </summary>
public class OperateLogInput : VisitLogInput
{
}

View File

@@ -1,47 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 操作日志服务
/// </summary>
public interface IOperateLogService : ITransient
{
/// <summary>
/// 根据分类删除操作日志
/// </summary>
/// <param name="category">分类名称</param>
/// <returns></returns>
Task DeleteAsync(params string[] category);
/// <summary>
/// 导出后台日志
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<MemoryStream> ExportFileAsync(List<SysOperateLog> input = null);
/// <summary>
/// 导出后台日志
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<MemoryStream> ExportFileAsync(OperateLogInput input);
/// <summary>
/// 操作日志分页查询
/// </summary>
/// <param name="input">查询参数</param>
/// <returns>分页列表</returns>
Task<ISqlSugarPagedList<SysOperateLog>> PageAsync(OperateLogPageInput input);
}

View File

@@ -1,105 +0,0 @@
#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;
using Mapster;
using MiniExcelLibs;
using SqlSugar;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="IOperateLogService"/>
/// </summary>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class OperateLogService : DbRepository<SysOperateLog>, IOperateLogService
{
/// <inheritdoc />
[OperDesc("删除操作日志")]
public async Task DeleteAsync(params string[] category)
{
await AsDeleteable().Where(it => category.Contains(it.Category)).ExecuteCommandAsync();
}
/// <inheritdoc/>
[OperDesc("导出操作日志", IsRecordPar = false)]
public async Task<MemoryStream> ExportFileAsync(List<SysOperateLog> input = null)
{
input ??= await GetListAsync();
//总数据
Dictionary<string, object> sheets = new();
List<Dictionary<string, object>> devExports = new();
foreach (var devData in input)
{
#region sheet
//变量页
var data = devData.GetType().GetProperties();
Dictionary<string, object> devExport = new();
foreach (var item in data)
{
//描述
var desc = item.FindDisplayAttribute();
//数据源增加
devExport.Add(desc ?? item.Name, item.GetValue(devData)?.ToString());
}
devExports.Add(devExport);
#endregion
}
sheets.Add("操作日志", devExports);
var memoryStream = new MemoryStream();
await memoryStream.SaveAsAsync(sheets);
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
/// <inheritdoc/>
[OperDesc("导出操作日志", IsRecordPar = false)]
public async Task<MemoryStream> ExportFileAsync(OperateLogInput input)
{
var query = GetPage(input.Adapt<OperateLogPageInput>());
var data = await query.ToListAsync();
return await ExportFileAsync(data);
}
/// <inheritdoc />
public async Task<ISqlSugarPagedList<SysOperateLog>> PageAsync(OperateLogPageInput input)
{
var query = GetPage(input);
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
private ISugarQueryable<SysOperateLog> GetPage(OperateLogPageInput input)
{
var query = Context.Queryable<SysOperateLog>()
.WhereIF(input.StartTime != null, a => a.OpTime >= input.StartTime.Value.ToLocalTime())
.WhereIF(input.EndTime != null, a => a.OpTime <= input.EndTime.Value.ToLocalTime())
.WhereIF(!string.IsNullOrEmpty(input.Account), it => it.OpAccount == input.Account)//根据账号查询
.WhereIF(!string.IsNullOrEmpty(input.Category), it => it.Category == input.Category)//根据分类查询
.WhereIF(!string.IsNullOrEmpty(input.ExeStatus), it => it.ExeStatus == input.ExeStatus)//根据结果查询
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Name.Contains(input.SearchKey) || it.OpIp.Contains(input.SearchKey));//根据关键字查询
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
query = query.OrderBy(it => it.Id, OrderByType.Desc);//排序
return query;
}
}

View File

@@ -1,97 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 关系服务
/// </summary>
public interface IRelationService : ITransient
{
/// <summary>
/// 获取关系表用户工作台
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>关系表数据</returns>
Task<SysRelation> GetWorkbenchAsync(long userId);
/// <summary>
/// 根据分类获取关系表信息
/// </summary>
/// <param name="category">分类名称</param>
/// <returns>关系表</returns>
Task<List<SysRelation>> GetRelationByCategoryAsync(string category);
/// <summary>
/// 通过对象ID和分类获取关系列表
/// </summary>
/// <param name="objectId">对象ID</param>
/// <param name="category">分类</param>
/// <returns></returns>
Task<List<SysRelation>> GetRelationListByObjectIdAndCategoryAsync(long objectId, string category);
/// <summary>
/// 通过对象ID列表和分类获取关系列表
/// </summary>
/// <param name="objectIds">对象ID</param>
/// <param name="category">分类</param>
/// <returns></returns>
Task<List<SysRelation>> GetRelationListByObjectIdListAndCategoryAsync(List<long> objectIds, string category);
/// <summary>
/// 通过目标ID和分类获取关系列表
/// </summary>
/// <param name="targetId">目标ID</param>
/// <param name="category">分类</param>
/// <returns></returns>
Task<List<SysRelation>> GetRelationListByTargetIdAndCategoryAsync(string targetId, string category);
/// <summary>
/// 通过目标ID列表和分类获取关系列表
/// </summary>
/// <param name="targetIds"></param>
/// <param name="category"></param>
/// <returns></returns>
Task<List<SysRelation>> GetRelationListByTargetIdListAndCategoryAsync(List<string> targetIds, string category);
/// <summary>
/// 更新缓存
/// </summary>
/// <param name="category">分类</param>
/// <returns></returns>
void RefreshCache(string category);
/// <summary>
/// 保存关系
/// </summary>
/// <param name="category">分类</param>
/// <param name="objectId">对象ID</param>
/// <param name="targetId">目标ID</param>
/// <param name="extJson">拓展信息</param>
/// <param name="clear">是否清除老的数据</param>
/// <param name="refreshCache">是否刷新缓存</param>
/// <returns></returns>
Task SaveRelationAsync(string category, long objectId, string targetId, string extJson, bool clear, bool refreshCache = true);
/// <summary>
/// 批量保存关系
/// </summary>
/// <param name="category">分类</param>
/// <param name="objectId">对象ID</param>
/// <param name="targetIds">目标ID列表</param>
/// <param name="extJsons">拓展信息列表</param>
/// <param name="clear">是否清除老的数据</param>
/// <returns></returns>
Task SaveRelationBatchAsync(string category, long objectId, List<string> targetIds, List<string> extJsons, bool clear);
}

View File

@@ -1,150 +0,0 @@
#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.FriendlyException;
using Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IRelationService"/>
public class RelationService : DbRepository<SysRelation>, IRelationService
{
private readonly IServiceScope _serviceScope;
public RelationService(IServiceScopeFactory serviceScopeFactory)
{
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
public async Task<List<SysRelation>> GetRelationByCategoryAsync(string category)
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var sysRelations = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysRelation>>(CacheConst.CACHE_SYSRELATION + category, true);
if (sysRelations == null)
{
//cache没有就去数据库拿
sysRelations = await GetListAsync(it => it.Category == category);
if (sysRelations.Count > 0)
{
//插入Cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSRELATION + category, sysRelations, true);
}
}
return sysRelations;
}
/// <inheritdoc/>
public async Task<List<SysRelation>> GetRelationListByObjectIdAndCategoryAsync(long objectId, string category)
{
var sysRelations = await GetRelationByCategoryAsync(category);
var result = sysRelations.Where(it => it.ObjectId == objectId).ToList();//获取关系集合
return result;
}
/// <inheritdoc/>
public async Task<List<SysRelation>> GetRelationListByObjectIdListAndCategoryAsync(List<long> objectIds, string category)
{
var sysRelations = await GetRelationByCategoryAsync(category);
var result = sysRelations.Where(it => objectIds.Contains(it.ObjectId)).ToList();//获取关系集合
return result;
}
/// <inheritdoc/>
public async Task<List<SysRelation>> GetRelationListByTargetIdAndCategoryAsync(string targetId, string category)
{
var sysRelations = await GetRelationByCategoryAsync(category);
var result = sysRelations.Where(it => it.TargetId == targetId).ToList();//获取关系集合
return result;
}
/// <inheritdoc/>
public async Task<List<SysRelation>> GetRelationListByTargetIdListAndCategoryAsync(List<string> targetIds, string category)
{
var sysRelations = await GetRelationByCategoryAsync(category);
var result = sysRelations.Where(it => targetIds.Contains(it.TargetId)).ToList();//获取关系集合
return result;
}
/// <inheritdoc/>
public async Task<SysRelation> GetWorkbenchAsync(long userId)
{
var sysRelations = await GetRelationByCategoryAsync(CateGoryConst.Relation_SYS_USER_WORKBENCH_DATA);
var result = sysRelations.FirstOrDefault(it => it.ObjectId == userId);//获取个人工作台
return result;
}
/// <inheritdoc/>
public void RefreshCache(string category)
{
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRELATION + category);//删除cache
}
/// <inheritdoc/>
public async Task SaveRelationAsync(string category, long objectId, string targetId, string extJson, bool clear, bool refreshCache = true)
{
var sysRelation = new SysRelation
{
ObjectId = objectId,
TargetId = targetId,
Category = category,
ExtJson = extJson
};
//事务
var result = await itenant.UseTranAsync(async () =>
{
if (clear)
await DeleteAsync(it => it.ObjectId == objectId && it.Category == category);//删除老的
await InsertAsync(sysRelation);//添加新的
});
if (result.IsSuccess)//如果成功了
{
if (refreshCache)
RefreshCache(category);
}
else
{
//写日志
throw Oops.Oh(result.ErrorMessage);
}
}
/// <inheritdoc/>
public async Task SaveRelationBatchAsync(string category, long objectId, List<string> targetIds, List<string> extJsons, bool clear)
{
var sysRelations = new List<SysRelation>();//要添加的列表
for (int i = 0; i < targetIds.Count; i++)
{
sysRelations.Add(new SysRelation
{
ObjectId = objectId,
TargetId = targetIds[i],
Category = category,
ExtJson = extJsons?[i]
});
}
var result = await itenant.UseTranAsync(async () =>
{
if (clear)
await DeleteAsync(it => it.ObjectId == objectId && it.Category == category);//删除老的
await InsertRangeAsync(sysRelations);//添加新的
});
if (result.IsSuccess)//如果成功了
{
RefreshCache(category);
}
else
{
throw Oops.Oh(result.ErrorMessage);
}
}
}

View File

@@ -1,72 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 角色按钮资源
/// </summary>
public class RoleGrantResourceButton
{
/// <summary>
/// 按钮id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
}
/// <summary>
/// 授权菜单类
/// </summary>
public class RoleGrantResourceMenu
{
/// <summary>
/// 菜单下按钮集合
/// </summary>
public List<RoleGrantResourceButton> Button { get; set; } = new List<RoleGrantResourceButton>();
/// <summary>
/// 菜单id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 父id
/// </summary>
public long ParentId { get; set; }
/// <summary>
/// 父名称
/// </summary>
public string ParentName { get; set; }
/// <summary>
/// 菜单名称
/// </summary>
public string Title { get; set; }
}
/// <summary>
/// Blazor Server的组件路由内容
/// </summary>
public class PermissionTreeSelector
{
/// <summary>
/// 路由名称
/// </summary>
public string ApiRoute { get; set; }
}

View File

@@ -1,98 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 资源服务
/// </summary>
public interface IResourceService : ITransient
{
/// <summary>
/// 获取所有的菜单和模块以及单页面列表,并按分类和排序码排序,不会形成树列表
/// </summary>
/// <returns>所有的菜单和模块以及单页面列表</returns>
Task<List<SysResource>> GetaMenuAndSpaListAsync();
/// <summary>
/// 获取子资源
/// </summary>
/// <param name="sysResources"></param>
/// <param name="resId"></param>
/// <param name="isContainOneself"></param>
/// <returns></returns>
List<SysResource> GetChildListById(List<SysResource> sysResources, long resId, bool isContainOneself = true);
/// <summary>
/// 获取ID获取Code列表
/// </summary>
/// <param name="ids">id列表</param>
/// <param name="category">分类</param>
/// <returns>Code列表</returns>
Task<List<string>> GetCodeByIdsAsync(List<long> ids, ResourceCategoryEnum category);
/// <summary>
/// 根据分类获取资源列表
/// </summary>
/// <param name="category">分类名称</param>
/// <returns>资源列表</returns>
Task<List<SysResource>> GetListByCategoryAsync(ResourceCategoryEnum category);
/// <summary>
/// 资源分类列表,如果是空的则获取全部资源
/// </summary>
/// <param name="categorys">资源分类列表</param>
/// <returns></returns>
Task<List<SysResource>> GetListByCategorysAsync(List<ResourceCategoryEnum> categorys = null);
/// <summary>
/// 获取资源所有下级
/// </summary>
/// <param name="resourceList">资源列表</param>
/// <param name="parentId">父ID</param>
/// <returns></returns>
List<SysResource> GetResourceChilden(List<SysResource> resourceList, long parentId);
/// <summary>
/// 获取上级
/// </summary>
/// <returns></returns>
List<SysResource> GetResourceParent(List<SysResource> resourceList, long parentId);
/// <summary>
/// 获取授权菜单
/// </summary>
/// <returns></returns>
Task<List<RoleGrantResourceMenu>> GetRoleGrantResourceMenusAsync();
/// <summary>
/// 刷新缓存
/// </summary>
/// <param name="category">分类名称</param>
/// <returns></returns>
void RefreshCache(ResourceCategoryEnum category);
/// <summary>
/// 构建菜单树形结构
/// </summary>
/// <param name="resourceList">菜单列表</param>
/// <param name="parentId">父ID</param>
/// <returns>菜单形结构</returns>
/// <inheritdoc/>
List<SysResource> ResourceListToTree(List<SysResource> resourceList, long parentId = 0);
/// <summary>
/// 多个树转列表
/// </summary>
/// <param name="data"></param>
List<SysResource> ResourceTreeToList(List<SysResource> data);
}

View File

@@ -1,269 +0,0 @@
#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 Mapster;
using Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IResourceService"/>
public class ResourceService : DbRepository<SysResource>, IResourceService
{
private readonly IServiceScope _serviceScope;
public ResourceService(IServiceScopeFactory serviceScopeFactory)
{
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
public async Task<List<SysResource>> GetaMenuAndSpaListAsync()
{
//获取所有的菜单以及单页面
var sysResources = await GetListByCategorysAsync((List<ResourceCategoryEnum>)new() { ResourceCategoryEnum.MENU, ResourceCategoryEnum.SPA });
return sysResources?.OrderBy(it => it.Category).ThenBy(it => it.SortCode).ToList();
}
/// <inheritdoc />
public List<SysResource> GetChildListById(List<SysResource> sysResources, long resId, bool isContainOneself = true)
{
//查找下级
var childLsit = GetResourceChilden(sysResources, resId);
if (isContainOneself)//如果包含自己
{
//获取自己
var self = sysResources.Where(it => it.Id == resId).FirstOrDefault();
if (self != null) childLsit.Insert(0, self);//如果不为空就插到第一个
}
return childLsit;
}
/// <inheritdoc />
public async Task<List<string>> GetCodeByIdsAsync(List<long> ids, ResourceCategoryEnum category)
{
//根据分类获取所有
var sysResources = await GetListByCategoryAsync(category);
return sysResources.Where(it => ids.Contains(it.Id)).Select(it => it.Code).ToList();
}
/// <inheritdoc />
public async Task<List<SysResource>> GetListByCategoryAsync(ResourceCategoryEnum category)
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var sysResources = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysResource>>(CacheConst.CACHE_SYSRESOURCE + category.ToString(), true);
if (sysResources == null)
{
//cache没有就去数据库拿
sysResources = await GetListAsync(it => it.Category == category);
if (sysResources.Count > 0)
{
//插入Cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSRESOURCE + category.ToString(), sysResources, true);
}
}
return sysResources;
}
/// <inheritdoc/>
public async Task<List<SysResource>> GetListByCategorysAsync(List<ResourceCategoryEnum> categoryList = null)
{
//定义结果
var sysResources = new List<SysResource>();
//定义资源分类列表,如果是空的则获取全部资源
categoryList = categoryList != null ? categoryList
: new List<ResourceCategoryEnum> { ResourceCategoryEnum.MENU, ResourceCategoryEnum.BUTTON, ResourceCategoryEnum.SPA };
//遍历列表
foreach (var category in categoryList)
{
//根据分类获取到资源列表
var data = await GetListByCategoryAsync(category);
//添加到结果集
sysResources.AddRange(data);
}
return sysResources;
}
/// <inheritdoc/>
public List<SysResource> GetResourceChilden(List<SysResource> resourceList, long parentId)
{
//找下级资源ID列表
var resources = resourceList.Where(it => it.ParentId == parentId).ToList();
if (resources.Count > 0)//如果数量大于0
{
var data = new List<SysResource>();
foreach (var item in resources)//遍历资源
{
var res = GetResourceChilden(resourceList, item.Id);
data.AddRange(res);//添加子节点;
data.Add(item);//添加到列表
}
return data;//返回结果
}
return new List<SysResource>();
}
/// <inheritdoc/>
public List<SysResource> GetResourceParent(List<SysResource> resourceList, long parentId)
{
//找上级资源ID列表
var resources = resourceList.Where(it => it.Id == parentId).FirstOrDefault();
if (resources != null)//如果数量大于0
{
var data = new List<SysResource>();
var parents = GetResourceParent(resourceList, resources.ParentId);
data.AddRange(parents);//添加子节点;
data.Add(resources);//添加到列表
return data;//返回结果
}
return new List<SysResource>();
}
/// <inheritdoc/>
public async Task<List<RoleGrantResourceMenu>> GetRoleGrantResourceMenusAsync()
{
var roleGrantResourceMenus = new List<RoleGrantResourceMenu>();//定义结果
List<SysResource> allMenuList = (await GetListByCategoryAsync(ResourceCategoryEnum.MENU));//获取所有菜单列表
List<SysResource> allButtonList = await GetListByCategoryAsync(ResourceCategoryEnum.BUTTON);//获取所有按钮列表
var parentMenuList = allMenuList.Where(it => it.ParentId == 0).ToList();//获取一级目录
//遍历一级目录
foreach (var parent in parentMenuList)
{
//如果是目录则去遍历下级
if (parent.TargetType == TargetTypeEnum.None)
{
//获取所有下级菜单
var menuList = GetChildListById(allMenuList, parent.Id, false);
//遍历下级菜单
foreach (var menu in menuList)
{
//如果菜单类型是菜单
if (menu.TargetType == TargetTypeEnum.SELF)
{
//获取菜单下按钮集合并转换成对应实体
var buttonList = allButtonList.Where(it => it.ParentId == menu.Id).ToList();
var buttons = buttonList.Adapt<List<RoleGrantResourceButton>>();
roleGrantResourceMenus.Add(new()
{
Id = menu.Id,
ParentId = parent.Id,
ParentName = parent.Title,
Title = GetRoleGrantResourceMenuTitle(parentMenuList, menu),//菜单名称需要特殊处理因为有二级菜单
Button = buttons
});
}
else if (menu.TargetType == TargetTypeEnum.BLANK || menu.TargetType == TargetTypeEnum.CALLBACK)//如果是内链或者外链
{
//直接加到资源列表
roleGrantResourceMenus.Add(new()
{
Id = menu.Id,
ParentId = parent.Id,
ParentName = parent.Title,
Title = menu.Title,
});
}
}
}
else
{
//否则就将自己加到一级目录里面
roleGrantResourceMenus.Add(new()
{
Id = parent.Id,
ParentId = parent.Id,
ParentName = parent.Title,
Title = parent.Title,
});
}
}
return roleGrantResourceMenus;
}
/// <inheritdoc/>
public void RefreshCache(ResourceCategoryEnum category)
{
//如果分类是空的
if (category == ResourceCategoryEnum.None)
{
//删除全部key
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.SPA.ToString());
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.BUTTON.ToString());
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.MENU.ToString());
}
else
{
//否则只删除一个Key
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + category.ToString());
}
}
/// <inheritdoc />
public List<SysResource> ResourceListToTree(List<SysResource> resourceList, long parentId = 0)
{
//找下级资源ID列表
var resources = resourceList
.Where(it => it.ParentId == parentId).OrderBy(it => it.SortCode).ToList();
if (resources.Count > 0)//如果数量大于0
{
var data = new List<SysResource>();
foreach (var item in resources)//遍历资源
{
var children = ResourceListToTree(resourceList, item.Id);//添加子节点
item.Children = children.Count > 0 ? children : null;
data.Add(item);//添加到列表
}
return data;//返回结果
}
return new List<SysResource>();
}
/// <inheritdoc />
public List<SysResource> ResourceTreeToList(List<SysResource> data)
{
List<SysResource> list = new();
foreach (var item in data)
{
list.Add(item);
if (item.Children != null && item.Children.Count > 0)
{
list.AddRange(ResourceTreeToList(item.Children));
}
}
return list;
}
/// <summary>
/// 获取授权菜单类菜单名称
/// </summary>
/// <param name="menuList">菜单列表</param>
/// <param name="menu">当前菜单</param>
/// <returns></returns>
private string GetRoleGrantResourceMenuTitle(List<SysResource> menuList, SysResource menu)
{
//查找菜单上级
var parentList = GetResourceParent(menuList, menu.ParentId);
//如果有父级菜单
if (parentList.Count > 0)
{
var titles = parentList.Select(it => it.Title).ToList();//提取出父级的name
var title = $"{string.Join("- ", titles)}-{menu.Title}";//根据-分割,转换成字符串并在最后加上菜单的title
return title;
}
else
{
return menu.Title;//原路返回
}
}
}

View File

@@ -1,82 +0,0 @@
#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 System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 角色授权资源参数
/// </summary>
public class GrantResourceInput : RoleOwnResourceOutput
{
/// <summary>
/// 授权资源信息
/// </summary>
[Required(ErrorMessage = "授权资源信息表不能为空")]
public override List<RelationRoleResuorce> GrantInfoList { get; set; }
/// <summary>
/// 角色Id
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}
/// <summary>
/// 角色授权用户参数
/// </summary>
public class GrantUserInput
{
/// <summary>
/// 授权权限信息
/// </summary>
[Required(ErrorMessage = "GrantInfoList不能为空")]
public List<long> GrantInfoList { get; set; }
/// <summary>
/// Id
/// </summary>
[Required(ErrorMessage = "Id不能为空")]
public long? Id { get; set; }
}
/// <summary>
/// 角色添加参数
/// </summary>
public class RoleAddInput : SysRole
{
/// <summary>
/// 名称
/// </summary>
[Required(ErrorMessage = "Name不能为空")]
public override string Name { get; set; }
}
/// <summary>
/// 角色编辑参数
/// </summary>
public class RoleEditInput : RoleAddInput
{
/// <summary>
/// Id
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}
/// <summary>
/// 角色查询参数
/// </summary>
public class RolePageInput : BasePageInput
{
}

View File

@@ -1,105 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 角色服务
/// </summary>
public interface IRoleService : ITransient
{
/// <summary>
/// 添加角色
/// </summary>
/// <param name="input">添加参数</param>
/// <returns></returns>
Task AddAsync(RoleAddInput input);
/// <summary>
/// 删除角色
/// </summary>
/// <param name="input">删除参数</param>
/// <returns></returns>
Task DeleteAsync(params long[] input);
/// <summary>
/// 编辑角色
/// </summary>
/// <param name="input">编辑角色</param>
/// <returns></returns>
Task EditAsync(RoleEditInput input);
/// <summary>
/// 根据用户ID获取用户角色Id集合
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns></returns>
Task<List<long>> GetRoleIdListByUserIdAsync(long userId);
/// <summary>
/// 根据用户ID获取用户角色集合
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns></returns>
Task<List<SysRole>> GetRoleListByUserIdAsync(long userId);
/// <summary>
/// 给角色授权资源
/// </summary>
/// <param name="input">授权参数</param>
/// <returns></returns>
Task GrantResourceAsync(GrantResourceInput input);
/// <summary>
/// 给角色授权用户
/// </summary>
/// <param name="input">授权信息</param>
/// <returns></returns>
Task GrantUserAsync(GrantUserInput input);
/// <summary>
/// 角色拥有资源
/// </summary>
/// <param name="input">角色id</param>
/// <returns>角色拥有资源信息</returns>
Task<RoleOwnResourceOutput> OwnResourceAsync(long input);
/// <summary>
/// 获取角色下的用户
/// </summary>
/// <param name="input">角色ID</param>
/// <returns></returns>
Task<List<long>> OwnUserAsync(long input);
/// <summary>
/// 分页查询角色
/// </summary>
/// <param name="input">查询参数</param>
/// <returns></returns>
Task<ISqlSugarPagedList<SysRole>> PageAsync(RolePageInput input);
/// <summary>
/// 刷新缓存
/// </summary>
/// <returns></returns>
void RefreshCache();
/// <summary>
/// 角色刷新资源
/// </summary>
Task RefreshResourceAsync(long? menuId = null);
/// <summary>
/// 角色选择器
/// </summary>
Task<List<SysRole>> RoleSelectorAsync(string searchKey = null);
}

View File

@@ -1,410 +0,0 @@
#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;
using Furion.EventBus;
using Furion.FriendlyException;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using ThingsGateway.Foundation.Extension.String;
using Yitter.IdGenerator;
namespace ThingsGateway.Admin.Application
{
/// <inheritdoc cref="IRoleService"/>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class RoleService : DbRepository<SysRole>, IRoleService
{
private readonly IEventPublisher _eventPublisher;
private readonly IRelationService _relationService;
private readonly IResourceService _resourceService;
private readonly IServiceScope _serviceScope;
/// <inheritdoc cref="IRoleService"/>
public RoleService(
IRelationService relationService,
IResourceService resourceService,
IEventPublisher eventPublisher,
IServiceScopeFactory serviceScopeFactory)
{
_relationService = relationService;
_resourceService = resourceService;
_eventPublisher = eventPublisher;
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc />
[OperDesc("添加角色")]
public async Task AddAsync(RoleAddInput input)
{
await CheckInput(input);//检查参数
var sysRole = input.Adapt<SysRole>();//实体转换
sysRole.Code = YitIdHelper.NextId().ToString();//赋值Code
if (await InsertAsync(sysRole))//插入数据
RefreshCache();//刷新缓存
}
/// <inheritdoc />
[OperDesc("删除角色")]
public async Task DeleteAsync(params long[] input)
{
//获取所有ID
var ids = input.ToList();
if (ids.Count > 0)
{
var sysRoles = await GetListAsync();//获取所有角色
var hasSuperAdmin = sysRoles.Any(it => it.Code == RoleConst.SuperAdmin && ids.Contains(it.Id));//判断是否有超级管理员
if (hasSuperAdmin) throw Oops.Bah($"不可删除系统内置超管角色");
//数据库是string所以这里转下
var targetIds = ids.Select(it => it.ToString()).ToList();
//定义删除的关系
var delRelations = new List<string> { CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE, CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION };
//事务
var result = await itenant.UseTranAsync(async () =>
{
await DeleteByIdsAsync(ids.Cast<object>().ToArray());//删除按钮
//删除关系表角色与资源关系,角色与权限关系
await Context.Deleteable<SysRelation>().Where(it => ids.Contains(it.ObjectId) && delRelations.Contains(it.Category)).ExecuteCommandAsync();
//删除关系表角色与用户关系
await Context.Deleteable<SysRelation>().Where(it => targetIds.Contains(it.TargetId) && it.Category == CateGoryConst.Relation_SYS_USER_HAS_ROLE).ExecuteCommandAsync();
});
if (result.IsSuccess)//如果成功了
{
RefreshCache();//刷新缓存
_relationService.RefreshCache(CateGoryConst.Relation_SYS_USER_HAS_ROLE);//关系表刷新SYS_USER_HAS_ROLE缓存
_relationService.RefreshCache(CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);//关系表刷新SYS_ROLE_HAS_RESOURCE缓存
_relationService.RefreshCache(CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION);//关系表刷新SYS_ROLE_HAS_PERMISSION缓存
await _eventPublisher.PublishAsync(EventSubscriberConst.ClearUserCache, ids);//清除角色下用户缓存
}
else
{
//写日志
throw Oops.Oh(result.ErrorMessage);
}
}
}
/// <inheritdoc />
[OperDesc("编辑角色")]
public async Task EditAsync(RoleEditInput input)
{
//判断是否超管
if (input.Code == RoleConst.SuperAdmin)
throw Oops.Bah($"不可编辑超管角色");
await CheckInput(input);//检查参数
var role = await GetFirstAsync(it => it.Id == input.Id);//获取角色
if (role != null)
{
var permissions = new List<SysRelation>();
var sysRole = input.Adapt<SysRole>();//实体转换
//事务
var result = await itenant.UseTranAsync(async () =>
{
await UpdateAsync(sysRole);//更新角色
if (permissions.Any())//如果有授权权限就更新
await Context.Updateable(permissions).ExecuteCommandAsync();
});
if (result.IsSuccess)//如果成功了
{
RefreshCache();//刷新缓存
if (permissions.Any())//如果有授权
_relationService.RefreshCache(CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION);//关系表刷新SYS_ROLE_HAS_PERMISSION缓存
await _eventPublisher.PublishAsync(EventSubscriberConst.ClearUserCache, new List<long> { input.Id });//清除角色下用户缓存
}
else
{
//写日志
throw Oops.Oh(result.ErrorMessage);
}
}
}
/// <summary>
/// 获取所有角色
/// </summary>
/// <returns></returns>
public override async Task<List<SysRole>> GetListAsync()
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var sysRoles = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysRole>>(CacheConst.CACHE_SYSROLE, true);
if (sysRoles == null)
{
//cache没有就去数据库拿
sysRoles = await base.GetListAsync();
if (sysRoles.Count > 0)
{
//插入Cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSROLE, sysRoles, true);
}
}
return sysRoles;
}
/// <inheritdoc/>
public async Task<List<long>> GetRoleIdListByUserIdAsync(long userId)
{
List<SysRole> cods = new();//角色代码集合
var roleList = await _relationService.GetRelationListByObjectIdAndCategoryAsync(userId, CateGoryConst.Relation_SYS_USER_HAS_ROLE);//根据用户ID获取角色ID
var roleIdList = roleList.Select(x => x.TargetId.ToLong()).ToList();//角色ID列表
return roleIdList;
}
/// <inheritdoc/>
public async Task<List<SysRole>> GetRoleListByUserIdAsync(long userId)
{
List<SysRole> cods = new();//角色代码集合
var roleList = await _relationService.GetRelationListByObjectIdAndCategoryAsync(userId, CateGoryConst.Relation_SYS_USER_HAS_ROLE);//根据用户ID获取角色ID
var roleIdList = roleList.Select(x => x.TargetId.ToLong()).ToList();//角色ID列表
if (roleIdList.Count > 0)
{
cods = await GetListAsync(it => roleIdList.Contains(it.Id));
}
return cods;
}
/// <inheritdoc />
[OperDesc("角色授权")]
public async Task GrantResourceAsync(GrantResourceInput input)
{
var menuIds = input.GrantInfoList.Select(it => it.MenuId).ToList();//菜单ID
var extJsons = input.GrantInfoList.Select(it => it.ToJsonString()).ToList();//拓展信息
var relationRoles = new List<SysRelation>();//要添加的角色资源和授权关系表
var sysRole = (await GetListAsync()).Where(it => it.Id == input.Id).FirstOrDefault();//获取角色
if (sysRole != null)
{
#region
//遍历角色列表
for (int i = 0; i < menuIds.Count; i++)
{
//将角色资源添加到列表
relationRoles.Add(new SysRelation
{
ObjectId = sysRole.Id,
TargetId = menuIds[i].ToString(),
Category = CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE,
ExtJson = extJsons?[i]
});
}
#endregion
#region
var relationRolePer = new List<SysRelation>();//要添加的角色有哪些权限列表
//获取菜单信息
var menus = await GetMenuByMenuIds(menuIds);
if (menus.Count > 0)
{
//获取权限授权树
var permissions = PermissionUtil.PermissionTreeSelector(menus.Select(it => it.Component).ToList());
permissions.ForEach(it =>
{
//新建角色权限关系
relationRolePer.Add(new SysRelation
{
ObjectId = sysRole.Id,
TargetId = it.ApiRoute,
Category = CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION,
ExtJson = new RelationRolePermission
{
ApiUrl = it.ApiRoute,
}.ToJsonString()
});
});
}
relationRoles.AddRange(relationRolePer);//合并列表
#endregion
#region
//事务
var result = await itenant.UseTranAsync(async () =>
{
//删除老的
await Context.Deleteable<SysRelation>().Where(it => it.ObjectId == sysRole.Id
&&
(it.Category == CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION
|| it.Category == CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE)
)
.ExecuteCommandAsync();
await Context.Insertable(relationRoles).ExecuteCommandAsync();
});
if (result.IsSuccess)//如果成功了
{
_relationService.RefreshCache(CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);//刷新关系缓存
_relationService.RefreshCache(CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION);//刷新关系缓存
await _eventPublisher.PublishAsync(EventSubscriberConst.ClearUserCache, new List<long> { input.Id });//发送事件清除角色下用户缓存
}
else
{
//写日志
throw Oops.Oh(result.ErrorMessage);
}
#endregion
}
}
/// <inheritdoc />
[OperDesc("用户授权")]
public async Task GrantUserAsync(GrantUserInput input)
{
var sysRelations = new List<SysRelation>();//关系列表
//遍历用户ID
input.GrantInfoList.ForEach(it =>
{
sysRelations.Add(new SysRelation
{
ObjectId = it,
TargetId = input.Id.ToString(),
Category = CateGoryConst.Relation_SYS_USER_HAS_ROLE
});
});
//事务
var result = await itenant.UseTranAsync(async () =>
{
//删除老的
await Context.Deleteable<SysRelation>().Where(it => it.TargetId == input.Id.ToString() && it.Category == CateGoryConst.Relation_SYS_USER_HAS_ROLE).ExecuteCommandAsync();
await Context.Insertable(sysRelations).ExecuteCommandAsync();//添加新的
});
if (result.IsSuccess)//如果成功了
{
_relationService.RefreshCache(CateGoryConst.Relation_SYS_USER_HAS_ROLE);//刷新关系表SYS_USER_HAS_ROLE缓存
await _eventPublisher.PublishAsync(EventSubscriberConst.ClearUserCache, new List<long> { input.Id.Value });//清除角色下用户缓存
}
else
{
//写日志
throw Oops.Oh(result.ErrorMessage);
}
}
/// <inheritdoc />
public async Task<RoleOwnResourceOutput> OwnResourceAsync(long input)
{
RoleOwnResourceOutput roleOwnResource = new() { Id = input };//定义结果集
List<RelationRoleResuorce> GrantInfoList = new();//已授权信息集合
//获取关系列表
var relations = await _relationService.GetRelationListByObjectIdAndCategoryAsync(input, CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);
//遍历关系表
relations.ForEach(it =>
{
//将扩展信息转为实体
var relationRole = it.ExtJson.FromJsonString<RelationRoleResuorce>();
GrantInfoList.Add(relationRole);//添加到已授权信息
});
roleOwnResource.GrantInfoList = GrantInfoList;//赋值已授权信息
return roleOwnResource;
}
/// <inheritdoc />
public async Task<List<long>> OwnUserAsync(long input)
{
//获取关系列表
var relations = await _relationService.GetRelationListByTargetIdAndCategoryAsync(input.ToString(), CateGoryConst.Relation_SYS_USER_HAS_ROLE);
return relations.Select(it => it.ObjectId).ToList();
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<SysRole>> PageAsync(RolePageInput input)
{
var query = Context.Queryable<SysRole>()
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Name.Contains(input.SearchKey));//根据关键字查询
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
query = query.OrderBy(it => it.SortCode);//排序
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
/// <inheritdoc />
public void RefreshCache()
{
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSROLE);//删除KEY
}
/// <inheritdoc />
public async Task RefreshResourceAsync(long? menuId = null)
{
var data = await GetListAsync();
foreach (var item in data)
{
var r1 = await OwnResourceAsync(item.Id);
if (menuId == null || r1.GrantInfoList.Any(a => a.MenuId == menuId))
{
await GrantResourceAsync(new GrantResourceInput() { Id = item.Id, GrantInfoList = r1.GrantInfoList });
}
}
}
/// <inheritdoc />
public async Task<List<SysRole>> RoleSelectorAsync(string searchKey = null)
{
var result = await Context.Queryable<SysRole>()
.WhereIF(!string.IsNullOrEmpty(searchKey), it => it.Name.Contains(searchKey))//根据关键字查询
.ToListAsync();
return result;
}
#region
/// <summary>
/// 检查输入参数
/// </summary>
/// <param name="sysRole"></param>
private async Task CheckInput(SysRole sysRole)
{
var sysRoles = await GetListAsync();//获取所有
var repeatName = sysRoles.Any(it => it.Name == sysRole.Name && it.Id != sysRole.Id);//是否有重复角色名称
if (repeatName)//如果有
{
throw Oops.Bah($"存在重复的角色:{sysRole.Name}");
}
}
/// <summary>
/// 根据菜单ID获取菜单
/// </summary>
/// <param name="menuIds"></param>
/// <returns></returns>
private async Task<List<SysResource>> GetMenuByMenuIds(List<long> menuIds)
{
//获取所有菜单
var menuList = await _resourceService.GetListByCategoryAsync(ResourceCategoryEnum.MENU);
//获取菜单信息
var menus = menuList.Where(it => menuIds.Contains(it.Id)).ToList();
return menus;
}
#endregion
}
}

View File

@@ -1,56 +0,0 @@
#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 System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 会话分页查询
/// </summary>
public class SessionPageInput : BasePageInput
{
/// <summary>
/// 账号
/// </summary>
[Description("账号")]
public string Account { get; set; }
/// <summary>
/// 最新登录IP
/// </summary>
[Description("最新登录IP")]
public string LatestLoginIp { get; set; }
/// <summary>
/// 姓名
/// </summary>
[Description("姓名")]
public string Name { get; set; }
}
/// <summary>
/// 退出参数
/// </summary>
public class ExitVerificatInput : BaseIdInput
{
/// <summary>
/// 验证ID列表
/// </summary>
[Required(ErrorMessage = "VerificatIds不能为空")]
public List<long> VerificatIds { get; set; }
/// <summary>
/// 用户Id
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}

View File

@@ -1,62 +0,0 @@
#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 System.ComponentModel;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 会话输出
/// </summary>
public class SessionOutput : PrimaryKeyEntity
{
/// <summary>
/// 账号
///</summary>
[Description("账号")]
[DataTable(Order = 1, IsShow = true, Sortable = true)]
public virtual string Account { get; set; }
/// <summary>
/// 最新登录ip
///</summary>
[Description("最新登录ip")]
[DataTable(Order = 3, IsShow = true, Sortable = true)]
public string LatestLoginIp { get; set; }
/// <summary>
/// 最新登录时间
///</summary>
[Description("最新登录时间")]
[DataTable(Order = 4, IsShow = true, Sortable = true)]
public DateTime? LatestLoginTime { get; set; }
/// <summary>
/// 在线状态
/// </summary>
[Description("在线状态")]
[DataTable(Order = 2, IsShow = true, Sortable = true)]
public bool OnlineStatus { get; set; }
/// <summary>
/// 令牌数量
/// </summary>
[Description("令牌数量")]
[DataTable(Order = 5, IsShow = true, Sortable = false)]
public int VerificatCount { get; set; }
/// <summary>
/// 令牌信息集合
/// </summary>
[Description("令牌列表")]
public List<VerificatInfo> VerificatSignList { get; set; }
}

View File

@@ -1,40 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 会话管理服务
/// </summary>
public interface ISessionService : ITransient
{
/// <summary>
/// 强退会话
/// </summary>
/// <param name="input">用户ID</param>
Task ExitSessionAsync(long input);
/// <summary>
/// 强退verificat
/// </summary>
/// <param name="input">verificat列表</param>
Task ExitVerificatAsync(ExitVerificatInput input);
/// <summary>
/// 会话分页查询
/// </summary>
/// <param name="input">查询参数</param>
/// <returns>会话列表</returns>
Task<ISqlSugarPagedList<SessionOutput>> PageAsync(SessionPageInput input);
}

View File

@@ -1,116 +0,0 @@
#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;
using SqlSugar;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="ISessionService"/>
/// </summary>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class SessionService : DbRepository<SysUser>, ISessionService
{
private readonly INoticeService _noticeService;
private readonly IVerificatService _verificatService;
/// <inheritdoc cref="ISessionService"/>
public SessionService(IVerificatService verificatService, INoticeService noticeService)
{
_verificatService = verificatService;
_noticeService = noticeService;
}
/// <inheritdoc/>
[OperDesc("强退会话")]
public async Task ExitSessionAsync(long input)
{
//verificat列表
List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(input);
//从列表中删除
await _verificatService.SetVerificatIdAsync(input, new());
var message = "您已被强制下线!";
await _noticeService.LogoutAsync(input, verificatInfos, message);//通知下线
}
/// <inheritdoc/>
[OperDesc("强退令牌")]
public async Task ExitVerificatAsync(ExitVerificatInput input)
{
//获取该用户的verificat信息
List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(input.Id);
//踢掉包含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);//通知下线
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<SessionOutput>> PageAsync(SessionPageInput input)
{
var query = Context.Queryable<SysUser>()
.WhereIF(!string.IsNullOrEmpty(input.Account), it => it.Account.Contains(input.Account))//根据账号查询
.WhereIF(!string.IsNullOrEmpty(input.LatestLoginIp), it => it.LatestLoginIp.Contains(input.LatestLoginIp))//根据IP查询
.OrderBy(it => it.LatestLoginTime, OrderByType.Desc)
.Select<SessionOutput>()
.Mapper(async it =>
{
var verificatInfos = await _verificatService.GetVerificatIdAsync(it.Id);
if (verificatInfos != null)
{
GetVerificatInfos(ref verificatInfos);//获取剩余时间
it.VerificatCount = verificatInfos.Count;//令牌数量
it.VerificatSignList = verificatInfos;//令牌列表
//如果有客户端ID就是在线
it.OnlineStatus = verificatInfos.Any(it => it.ClientIds.Count > 0);
}
else
{
it.VerificatSignList = new();
}
});
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
#region
/// <summary>
/// 获取verificat剩余时间信息
/// </summary>
private static void GetVerificatInfos(ref List<VerificatInfo> verificatInfos)
{
verificatInfos.ForEach(it =>
{
var now = DateTimeExtensions.CurrentDateTime;
it.VerificatRemain = now.GetDiffTime(it.VerificatTimeout);//获取时间差
var verificatSecond = it.VerificatTimeout.AddMinutes(-it.Expire).ToLong();//颁发时间转为时间戳
var timeoutSecond = it.VerificatTimeout.ToLong();//过期时间转为时间戳
});
}
#endregion
}

View File

@@ -1,67 +0,0 @@
#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 System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 单页输入参数
/// </summary>
public class SpaAddInput : SysResource
{
/// <summary>
/// 路径
/// </summary>
[Required(ErrorMessage = "Component不能为空")]
public override string Component { get; set; }
/// <summary>
/// 图标
/// </summary>
[Required(ErrorMessage = "Icon不能为空")]
public override string Icon { get; set; }
/// <summary>
/// 菜单类型
/// </summary>
public override TargetTypeEnum TargetType { get; set; } = TargetTypeEnum.SELF;
/// <summary>
/// 标题
/// </summary>
[Required(ErrorMessage = "Title不能为空")]
public override string Title { get; set; }
}
/// <summary>
/// 单页输入参数
/// </summary>
public class SpaPageInput : BasePageInput
{
/// <summary>
/// 跳转类型
/// </summary>
public TargetTypeEnum TargetType { get; set; }
}
/// <summary>
/// 单页修改参数
/// </summary>
public class SpaEditInput : SpaAddInput
{
/// <summary>
/// ID
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}

View File

@@ -1,49 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 单页服务
/// </summary>
public interface ISpaService : ITransient
{
/// <summary>
/// 添加单页
/// </summary>
/// <param name="input">添加参数</param>
/// <returns></returns>
Task AddAsync(SpaAddInput input);
/// <summary>
/// 删除单页
/// </summary>
/// <param name="input">删除参数</param>
/// <returns></returns>
Task DeleteAsync(params long[] input);
/// <summary>
/// 编辑单页
/// </summary>
/// <param name="input">编辑参数</param>
/// <returns></returns>
Task EditAsync(SpaEditInput input);
/// <summary>
/// 分页查询
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<ISqlSugarPagedList<SysResource>> PageAsync(SpaPageInput input);
}

View File

@@ -1,125 +0,0 @@
#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;
using Furion.FriendlyException;
using Mapster;
using Yitter.IdGenerator;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// <inheritdoc cref="ISpaService"/>
/// </summary>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class SpaService : DbRepository<SysResource>, ISpaService
{
private readonly IResourceService _resourceService;
/// <inheritdoc cref="ISpaService"/>
public SpaService(IResourceService resourceService)
{
this._resourceService = resourceService;
}
/// <inheritdoc />
[OperDesc("添加单页")]
public async Task AddAsync(SpaAddInput input)
{
CheckInput(input);//检查参数
input.Code = YitIdHelper.NextId().ToString();//code取随机值
var sysResource = input.Adapt<SysResource>();//实体转换
if (await InsertAsync(sysResource))//插入数据
_resourceService.RefreshCache(ResourceCategoryEnum.SPA);//刷新缓存
}
/// <inheritdoc />
[OperDesc("删除单页")]
public async Task DeleteAsync(params long[] input)
{
//获取所有ID
var ids = input.ToList();
if (ids.Count > 0)
{
//获取所有
var resourceList = await _resourceService.GetListByCategoryAsync(ResourceCategoryEnum.SPA);
//找到要删除的
var sysresources = resourceList.Where(it => ids.Contains(it.Id)).ToList();
//查找内置单页面
var system = sysresources.Where(it => it.Code == ResourceConst.System).FirstOrDefault();
if (system != null)
throw Oops.Bah($"不可删除系统内置单页面:{system.Title}");
//删除菜单
await DeleteAsync(sysresources);
_resourceService.RefreshCache(ResourceCategoryEnum.SPA);//刷新缓存
}
}
/// <inheritdoc />
[OperDesc("编辑单页")]
public async Task EditAsync(SpaEditInput input)
{
CheckInput(input);//检查参数
var sysResource = input.Adapt<SysResource>();//实体转换
if (await UpdateAsync(sysResource))//更新数据
_resourceService.RefreshCache(ResourceCategoryEnum.SPA);//刷新缓存
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<SysResource>> PageAsync(SpaPageInput input)
{
var query = Context.Queryable<SysResource>()
.Where(it => it.Category == ResourceCategoryEnum.SPA)//单页
.WhereIF(input.TargetType != 0, it => it.TargetType == input.TargetType)//根据菜单类型查询
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Title.Contains(input.SearchKey) || it.Component.Contains(input.SearchKey));//根据关键字查询
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
query = query.OrderBy(it => it.SortCode);//排序
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
#region
/// <summary>
/// 检查输入参数
/// </summary>
/// <param name="sysResource"></param>
private void CheckInput(SysResource sysResource)
{
//判断菜单类型
if (sysResource.TargetType == TargetTypeEnum.SELF)
{
if (string.IsNullOrEmpty(sysResource.Component))
{
throw Oops.Bah($"组件地址不能为空");
}
}
else if (sysResource.TargetType == TargetTypeEnum.BLANK)//如果是内链或者外链
{
sysResource.Component = null;
}
else
{
throw Oops.Bah($"单页类型错误:{sysResource.TargetType}");//都不是
}
//设置为单页
sysResource.Category = ResourceCategoryEnum.SPA;
}
#endregion
}

View File

@@ -1,76 +0,0 @@
#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 SqlSugar;
using System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 添加用户参数
/// </summary>
public class UserAddInput : SysUser
{
/// <summary>
/// 账号
/// </summary>
[Required(ErrorMessage = "账号不能为空"), MinLength(3, ErrorMessage = "账号不能少于4个字符")]
public override string Account { get; set; }
}
/// <summary>
/// 编辑用户参数
/// </summary>
public class UserEditInput : UserAddInput
{
/// <summary>
/// 账号
/// </summary>
[Required(ErrorMessage = "账号不能为空"), MinLength(3, ErrorMessage = "账号不能少于4个字符")]
public override string Account { get; set; }
/// <summary>
/// Id
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}
/// <summary>
/// 用户分页查询参数
/// </summary>
public class UserPageInput : BasePageInput
{
/// <summary>
/// 动态查询条件
/// </summary>
public Expressionable<SysUser> Expression { get; set; }
}
/// <summary>
/// 用户授权角色参数
/// </summary>
public class UserGrantRoleInput
{
/// <summary>
/// Id
/// </summary>
[Required(ErrorMessage = "Id不能为空")]
public long Id { get; set; }
/// <summary>
/// 授权权限信息
/// </summary>
[Required(ErrorMessage = "RoleIdList不能为空")]
public List<long> RoleIdList { get; set; }
}

View File

@@ -1,35 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人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.Application;
/// <summary>
/// 选择用户输出参数
/// </summary>
public class UserSelectorOutput
{
/// <summary>
/// 账号
/// </summary>
public string Account { get; set; }
/// <summary>
/// Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
}

View File

@@ -1,124 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 用户服务
/// </summary>
public interface ISysUserService : ITransient
{
/// <summary>
/// 添加用户
/// </summary>
/// <param name="input">添加参数</param>
/// <returns></returns>
Task AddAsync(UserAddInput input);
/// <summary>
/// 删除用户
/// </summary>
/// <param name="input">Id列表</param>
/// <returns></returns>
Task DeleteAsync(params long[] input);
/// <summary>
/// 从cache中删除用户信息
/// </summary>
/// <param name="ids">用户ID列表</param>
void DeleteUserFromCache(params long[] ids);
/// <summary>
/// 禁用用户
/// </summary>
/// <param name="input">用户Id</param>
/// <returns></returns>
Task DisableUserAsync(long input);
/// <summary>
/// 编辑
/// </summary>
/// <param name="input">编辑参数</param>
/// <returns></returns>
Task EditAsync(UserEditInput input);
/// <summary>
/// 启用用户
/// </summary>
/// <param name="input">用户Id</param>
/// <returns></returns>
Task EnableUserAsync(long input);
/// <summary>
/// 根据用户ID获取按钮ID集合
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<List<string>> GetButtonCodeListAsync(long userId);
/// <summary>
///根据用户账号获取用户ID
/// </summary>
/// <param name="account">用户账号</param>
/// <returns></returns>
Task<long> GetIdByAccountAsync(string account);
/// <summary>
/// 根据账号获取用户信息
/// </summary>
/// <param name="account">用户名</param>
/// <returns>用户信息</returns>
Task<SysUser> GetUserByAccountAsync(string account);
/// <summary>
/// 根据ID获取用户信息
/// </summary>
/// <param name="Id">用户ID</param>
/// <returns>用户信息</returns>
Task<SysUser> GetUserByIdAsync(long Id);
/// <summary>
/// 给用户授权角色
/// </summary>
/// <param name="input">授权参数</param>
/// <returns></returns>
Task GrantRoleAsync(UserGrantRoleInput input);
/// <summary>
/// 获取用户拥有角色
/// </summary>
/// <param name="input">用户ID</param>
/// <returns></returns>
Task<List<long>> OwnRoleAsync(BaseIdInput input);
/// <summary>
/// 用户分页查询
/// </summary>
/// <param name="input">查询参数</param>
/// <returns>用户分页列表</returns>
Task<ISqlSugarPagedList<SysUser>> PageAsync(UserPageInput input);
/// <summary>
/// 重置密码
/// </summary>
/// <param name="input">用户Id</param>
/// <returns></returns>
Task ResetPasswordAsync(long input);
/// <summary>
/// 用户选择器
/// </summary>
/// <returns></returns>
Task<List<UserSelectorOutput>> UserSelectorAsync(string searchKey);
}

View File

@@ -1,422 +0,0 @@
#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.DataEncryption;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="ISysUserService"/>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class SysUserService : DbRepository<SysUser>, ISysUserService
{
private readonly IConfigService _configService;
private readonly IRelationService _relationService;
private readonly IResourceService _resourceService;
private readonly IRoleService _roleService;
private readonly IVerificatService _verificatService;
private readonly IServiceScope _serviceScope;
/// <inheritdoc cref="ISysUserService"/>
public SysUserService(
IRelationService relationService,
IResourceService resourceService,
IVerificatService verificatService,
IRoleService roleService,
IConfigService configService,
IServiceScopeFactory serviceScopeFactory)
{
_relationService = relationService;
_resourceService = resourceService;
_roleService = roleService;
_configService = configService;
_verificatService = verificatService;
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
[OperDesc("添加用户")]
public async Task AddAsync(UserAddInput input)
{
await CheckInputAsync(input);//检查参数
var account_Id = await GetIdByAccountAsync(input.Account);
if (account_Id > 0)
throw Oops.Bah($"存在重复的账号:{input.Account}");
var sysUser = input.Adapt<SysUser>();//实体转换
//获取默认密码
sysUser.Password = await GetDefaultPassWord();//设置密码
sysUser.UserEnable = true;//默认状态
await InsertAsync(sysUser);//添加数据
}
/// <inheritdoc/>
[OperDesc("删除用户")]
public async Task DeleteAsync(params long[] ids)
{
//获取所有ID
if (ids.Length > 0)
{
var containsSuperAdmin = await IsAnyAsync(it => it.Account == RoleConst.SuperAdmin && ids.Contains(it.Id));//判断是否有超管
if (containsSuperAdmin)
throw Oops.Bah($"不可删除系统内置超管用户");
if (ids.Contains(UserManager.UserId))
throw Oops.Bah($"不可删除自己");
var result = await DeleteByIdsAsync(ids.Cast<object>().ToArray());
if (result)
{
//从列表中删除
foreach (var id in ids)
{
await _verificatService.SetVerificatIdAsync(id, new());
}
DeleteUserFromCache(ids);
}
}
}
/// <inheritdoc />
public void DeleteUserFromCache(params long[] ids)
{
List<SysUser> sysUsers = new();
foreach (var item in ids)
{
var user = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<SysUser>(CacheConst.CACHE_SYSUSER + item, false);//获取用户列表
sysUsers.Add(user);
//删除账号
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSUSER + item);
}
sysUsers = sysUsers.Where(it => it != null).ToList();//过滤掉不存在的
if (sysUsers.Count > 0)
{
var accounts = sysUsers.Select(it => it.Account).ToArray();//账号集合
foreach (var item in accounts)
{
//删除账号
_serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CAHCE_SYSUSERACCOUNT + item);
}
}
}
/// <inheritdoc/>
[OperDesc("禁用用户")]
public async Task DisableUserAsync(long input)
{
var sysUser = await GetUserByIdAsync(input);//获取用户信息
if (sysUser != null)
{
var isSuperAdmin = sysUser.Account == RoleConst.SuperAdmin;//判断是否有超管
if (isSuperAdmin)
throw Oops.Bah($"不可禁用系统内置超管用户账号");
CheckSelf(input, AdminConst.Disable);//判断是不是自己
//设置状态为禁用
if (await UpdateAsync(it => new SysUser { UserEnable = false }, it => it.Id == input))
{
//从列表中删除
await _verificatService.SetVerificatIdAsync(input, new());
DeleteUserFromCache(input);//从cache删除用户信息
}
}
}
/// <inheritdoc/>
[OperDesc("编辑用户")]
public async Task EditAsync(UserEditInput input)
{
await CheckInputAsync(input);//检查参数
var exist = await GetUserByIdAsync(input.Id);//获取用户信息
if (exist != null)
{
var isSuperAdmin = exist.Account == RoleConst.SuperAdmin;//判断是否有超管
if (isSuperAdmin && !UserManager.IsSuperAdmin)
throw Oops.Bah($"不可修改系统内置超管用户账号");
var sysUser = input.Adapt<SysUser>();//实体转换
if (await Context.Updateable(sysUser).IgnoreColumns(it =>
new
{
//忽略更新字段
it.Password,
it.LastLoginDevice,
it.LastLoginIp,
it.LastLoginTime,
it.LatestLoginDevice,
it.LatestLoginIp,
it.LatestLoginTime
}).ExecuteCommandAsync() > 0)//修改数据
DeleteUserFromCache(sysUser.Id);//用户缓存到cache
}
}
/// <inheritdoc/>
[OperDesc("启用用户")]
public async Task EnableUserAsync(long input)
{
CheckSelf(input, AdminConst.Enable);//判断是不是自己
//设置状态为启用
if (await UpdateAsync(it => new SysUser { UserEnable = true }, it => it.Id == input))
DeleteUserFromCache(input);//从cache删除用户信息
}
/// <inheritdoc/>
public async Task<List<string>> GetButtonCodeListAsync(long userId)
{
List<string> buttonCodeList = new();//按钮ID集合
//获取关系集合
var roleList = await _relationService.GetRelationListByObjectIdAndCategoryAsync(userId, CateGoryConst.Relation_SYS_USER_HAS_ROLE);
var roleIdList = roleList.Select(x => x.TargetId.ToLong()).ToList();//角色ID列表
if (roleIdList.Count > 0)//如果该用户有角色
{
List<long> buttonIdList = new();//按钮ID集合
var resourceList = await _relationService.GetRelationListByObjectIdListAndCategoryAsync(roleIdList, CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);//获取资源集合
resourceList.ForEach(it =>
{
if (!string.IsNullOrEmpty(it.ExtJson)) buttonIdList.AddRange(it.ExtJson.FromJsonString<RelationRoleResuorce>().ButtonInfo);//如果有按钮权限将按钮ID放到buttonIdList
});
if (buttonIdList.Count > 0)
{
buttonCodeList = await _resourceService.GetCodeByIdsAsync(buttonIdList, ResourceCategoryEnum.BUTTON);
}
}
return buttonCodeList;
}
/// <inheritdoc/>
public async Task<long> GetIdByAccountAsync(string account)
{
//先从Cache拿
var userId = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<long>(CacheConst.CAHCE_SYSUSERACCOUNT + account, false);
if (userId == 0)
{
//单查获取用户账号对应ID
userId = await GetFirstAsync(it => it.Account == account, it => it.Id);
if (userId != 0)
{
//插入Cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CAHCE_SYSUSERACCOUNT + account, userId, false);
}
}
return userId;
}
/// <inheritdoc/>
public async Task<List<string>> GetPermissionListByUserIdAsync(long userId)
{
var permissions = new List<string>();//权限集合
var roleIdList = await _relationService.GetRelationListByObjectIdAndCategoryAsync(userId, CateGoryConst.Relation_SYS_USER_HAS_ROLE);//根据用户ID获取角色ID
if (roleIdList.Count > 0)//如果角色ID不为空
{
//获取角色权限信息
var sysRelations = await _relationService.GetRelationListByObjectIdListAndCategoryAsync(roleIdList.Select(it => it.TargetId.ToLong()).ToList(), CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION);
var relationGroup = sysRelations.GroupBy(it => it.TargetId).ToList();//根据目标ID,也就是接口名分组,因为存在一个用户多个角色
//遍历分组
relationGroup.ForEach(it =>
{
HashSet<string> scopeSet = new();//定义不可重复列表
var relationList = it.ToList();//关系列表
relationList.ForEach(it =>
{
var rolePermission = it.ExtJson.FromJsonString<RelationRolePermission>();
scopeSet.Add(rolePermission.ApiUrl);
});
permissions.AddRange(scopeSet);//将改URL的权限集合加入权限集合列表
});
}
return permissions;
}
/// <inheritdoc/>
public async Task<SysUser> GetUserByAccountAsync(string account)
{
var userId = await GetIdByAccountAsync(account);//获取用户ID
if (userId > 0)
{
var sysUser = await GetUserByIdAsync(userId);//获取用户信息
if (sysUser.Account == account)//这里做了比较用来限制大小写
return sysUser;
else
return null;
}
else
{
return null;
}
}
/// <inheritdoc/>
public async Task<SysUser> GetUserByIdAsync(long Id)
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var sysUser = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<SysUser>(CacheConst.CACHE_SYSUSER + Id.ToString(), true);
if (sysUser == null)
{
sysUser = await Context.Queryable<SysUser>()
.Where(u => u.Id == Id)
.FirstAsync();
if (sysUser != null)
{
//获取按钮码
var buttonCodeList = await GetButtonCodeListAsync(sysUser.Id);
//获取角色码
var roleCodeList = await _roleService.GetRoleListByUserIdAsync(sysUser.Id);
//获取权限码
var permissionCodeList = await GetPermissionListByUserIdAsync(sysUser.Id);
//权限码赋值
sysUser.ButtonCodeList = buttonCodeList;
sysUser.RoleCodeList = roleCodeList.Select(it => it.Code).ToList();
sysUser.RoleIdList = roleCodeList.Select(it => it.Id).ToList();
sysUser.PermissionCodeList = permissionCodeList;
//插入Cache
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSUSER + sysUser.Id.ToString(), sysUser, true);
}
}
return sysUser;
}
/// <inheritdoc />
[OperDesc("用户授权")]
public async Task GrantRoleAsync(UserGrantRoleInput input)
{
var sysUser = await GetUserByIdAsync(input.Id);//获取用户信息
if (sysUser != null)
{
var isSuperAdmin = sysUser.Account == RoleConst.SuperAdmin;//判断是否有超管
if (isSuperAdmin)
throw Oops.Bah($"不能给超管分配角色");
CheckSelf(input.Id, AdminConst.GrantRole);//判断是不是自己
//给用户赋角色
await _relationService.SaveRelationBatchAsync(CateGoryConst.Relation_SYS_USER_HAS_ROLE, input.Id, input.RoleIdList.Select(it => it.ToString()).ToList(), null, true);
DeleteUserFromCache(input.Id);//从cache删除用户信息
}
}
/// <inheritdoc/>
public async Task<List<long>> OwnRoleAsync(BaseIdInput input)
{
var relations = await _relationService.GetRelationListByObjectIdAndCategoryAsync(input.Id, CateGoryConst.Relation_SYS_USER_HAS_ROLE);
return relations.Select(it => it.TargetId.ToLong()).ToList();
}
/// <inheritdoc/>
public async Task<ISqlSugarPagedList<SysUser>> PageAsync(UserPageInput input)
{
var query = Context.Queryable<SysUser>()
.WhereIF(input.Expression != null, input.Expression?.ToExpression())//动态查询
.WhereIF(!string.IsNullOrEmpty(input.SearchKey), u => u.Account.Contains(input.SearchKey))//根据关键字查询
.Mapper(u =>
{
u.Password = null;//密码清空
});
for (int i = input.SortField.Count - 1; i >= 0; i--)
{
query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
}
query = query.OrderBy(it => it.SortCode);//排序
query = query.OrderBy(u => u.Id);//排序
var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
return pageInfo;
}
/// <inheritdoc/>
[OperDesc("重置密码")]
public async Task ResetPasswordAsync(long input)
{
var password = await GetDefaultPassWord(true);//获取默认密码,这里不走Aop所以需要加密一下
//重置密码
if (await UpdateAsync(it => new SysUser { Password = password }, it => it.Id == input))
{
//从列表中删除
await _verificatService.SetVerificatIdAsync(input, new());
DeleteUserFromCache(input);//从cache删除用户信息
}
}
/// <inheritdoc/>
public async Task<List<UserSelectorOutput>> UserSelectorAsync(string searchKey)
{
var result = await Context.Queryable<SysUser>()
.WhereIF(!string.IsNullOrEmpty(searchKey), it => it.Account.Contains(searchKey))//根据关键字查询
.Select<UserSelectorOutput>()//映射成SysUserSelectorOutput
.ToListAsync();
return result;
}
#region
/// <summary>
/// 检查输入参数
/// </summary>
/// <param name="sysUser"></param>
private async Task CheckInputAsync(SysUser sysUser)
{
//判断账号重复,直接从cache拿
var account_Id = await GetIdByAccountAsync(sysUser.Account);
if (account_Id > 0 && account_Id != sysUser.Id)
throw Oops.Bah($"存在重复的账号:{sysUser.Account}");
//如果手机号不是空
if (!string.IsNullOrEmpty(sysUser.Phone))
{
if (!sysUser.Phone.MatchPhoneNumber())//验证手机格式
throw Oops.Bah($"手机号码:{sysUser.Phone} 格式错误");
sysUser.Phone = DESCEncryption.Encrypt(sysUser.Phone, DESCKeyConst.DESCKey);
}
//如果邮箱不是空
if (!string.IsNullOrEmpty(sysUser.Email))
{
var ismatch = sysUser.Email.MatchEmail();//验证邮箱格式
if (!ismatch)
throw Oops.Bah($"邮箱:{sysUser.Email} 格式错误");
if (await IsAnyAsync(it => it.Email == sysUser.Email && it.Id != sysUser.Id))
throw Oops.Bah($"存在重复的邮箱:{sysUser.Email}");
}
}
/// <summary>
/// 检查是否为自己
/// </summary>
private void CheckSelf(long id, string operate)
{
if (id == UserManager.UserId)//如果是自己
{
throw Oops.Bah($"禁止{operate}自己");
}
}
/// <summary>
/// 获取默认密码
/// </summary>
/// <returns></returns>
private async Task<string> GetDefaultPassWord(bool isSm4 = false)
{
//获取默认密码
var defaultPassword = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_PASSWORD)).ConfigValue;
return isSm4 ? DESCEncryption.Encrypt(defaultPassword, DESCKeyConst.DESCKey) : defaultPassword;//判断是否需要加密
}
#endregion
}

View File

@@ -1,59 +0,0 @@
#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 System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace ThingsGateway.Admin.Application;
/// <summary>
/// 编辑个人信息参数
/// </summary>
public class UpdateInfoInput : SysUser
{
/// <summary>
/// Id
/// </summary>
[MinValue(1, ErrorMessage = "Id不能为空")]
public override long Id { get; set; }
}
/// <summary>
/// 修改密码
/// </summary>
public class PasswordInfoInput : BaseIdInput, IValidatableObject
{
/// <summary>
/// 旧密码
/// </summary>
[Description("旧密码")]
[Required(ErrorMessage = "不能为空")]
public string OldPassword { get; set; }
/// <summary>
/// 新密码
/// </summary>
[Description("新密码")]
[Required(ErrorMessage = "不能为空")]
public string NewPassword { get; set; }
/// <summary>
/// 确认密码
/// </summary>
[Description("确认密码")]
[Required(ErrorMessage = "不能为空")]
public string ConfirmPassword { get; set; }
/// <inheritdoc/>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (NewPassword != ConfirmPassword)
yield return new ValidationResult("两次密码不一致", new[] { nameof(ConfirmPassword) });
}
}

View File

@@ -1,67 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 个人信息中心服务
/// </summary>
public interface IUserCenterService : ITransient
{
/// <summary>
/// 更改密码
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task EditPasswordAsync(PasswordInfoInput input);
/// <summary>
/// 获取个人主页
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<long> GetLoginDefaultRazorAsync(long userId);
/// <summary>
/// 获取个人首页快捷方式
/// </summary>
/// <returns></returns>
Task<List<long>> GetLoginWorkbenchAsync();
/// <summary>
/// 获取个人菜单
/// </summary>
/// <returns></returns>
Task<List<SysResource>> GetOwnMenuAsync(string UserAccount = null);
/// <summary>
/// 设置个人主页
/// </summary>
/// <param name="userId"></param>
/// <param name="defaultRazor"></param>
/// <returns></returns>
Task UpdateUserDefaultRazorAsync(long userId, long defaultRazor);
/// <summary>
/// 更新个人信息
/// </summary>
/// <param name="input">信息参数</param>
/// <returns></returns>
Task UpdateUserInfoAsync(UpdateInfoInput input);
/// <summary>
/// 编辑个人工作台
/// </summary>
/// <param name="input">工作台字符串</param>
/// <returns></returns>
Task UpdateWorkbenchAsync(List<long> input);
}

View File

@@ -1,214 +0,0 @@
#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.DataEncryption;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Mapster;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IUserCenterService"/>
[Injection(Proxy = typeof(OperDispatchProxy))]
public class UserCenterService : DbRepository<SysUser>, IUserCenterService
{
private readonly IRelationService _relationService;
private readonly IResourceService _resourceService;
private readonly ISysUserService _userService;
private readonly IVerificatService _verificatService;
/// <inheritdoc cref="IUserCenterService"/>
public UserCenterService(ISysUserService userService,
IRelationService relationService,
IResourceService resourceService,
IVerificatService verificatService
)
{
_userService = userService;
_relationService = relationService;
_resourceService = resourceService;
_verificatService = verificatService;
}
/// <inheritdoc/>
[OperDesc("修改密码")]
public async Task EditPasswordAsync(PasswordInfoInput input)
{
var password = DESCEncryption.Encrypt(input.ConfirmPassword, DESCKeyConst.DESCKey);
var user = await _userService.GetUserByIdAsync(input.Id);
if (user.Password != input.OldPassword)
throw Oops.Bah("旧密码不正确");
if (await UpdateAsync(it => new SysUser { Password = password }, it => it.Id == input.Id))
{
//从列表中删除
await _verificatService.SetVerificatIdAsync(input.Id, new());
_userService.DeleteUserFromCache(input.Id);//从cache删除用户信息
}
}
/// <inheritdoc />
public async Task<List<long>> GetLoginWorkbenchAsync()
{
//获取个人工作台信息
var sysRelation = await _relationService.GetWorkbenchAsync(UserManager.UserId);
if (sysRelation != null)
{
//如果有数据直接返回个人工作台
return sysRelation.ExtJson.FromJsonString<List<long>>();
}
else
{
return new();
}
}
/// <inheritdoc />
public async Task<long> GetLoginDefaultRazorAsync(long userId)
{
var sysRelations = await _relationService.GetRelationByCategoryAsync(CateGoryConst.Relation_SYS_USER_DEFAULTRAZOR);
var result = sysRelations.FirstOrDefault(it => it.ObjectId == userId);//获取个人工作台
if (result != null)
return result.ExtJson.FromJsonString<long>();
else
return 0;
}
/// <inheritdoc />
public async Task UpdateUserDefaultRazorAsync(long userId, long defaultRazor)
{
await _relationService.SaveRelationAsync(CateGoryConst.Relation_SYS_USER_DEFAULTRAZOR, userId, null, defaultRazor.ToJsonString(), true);
}
/// <inheritdoc />
public async Task<List<SysResource>> GetOwnMenuAsync(string UserAccount = null)
{
var result = new List<SysResource>();
//获取用户信息
var userInfo = await _userService.GetUserByAccountAsync(UserAccount ?? UserManager.UserAccount);
if (userInfo != null)
{
//获取所有的菜单和模块和菜单目录以及单页面列表,并按分类和排序码排序
var allMenuAndSpaList = await _resourceService.GetaMenuAndSpaListAsync();
List<SysResource> allMenuList = new();//菜单列表
List<SysResource> allSpaList = new();//单页列表
//遍历菜单集合
allMenuAndSpaList.ForEach(it =>
{
switch (it.Category)
{
case ResourceCategoryEnum.MENU://菜单
allMenuList.Add(it);//添加到菜单列表
break;
case ResourceCategoryEnum.SPA://单页
allSpaList.Add(it);//添加到单页列表
break;
}
});
//输出的用户权限菜单
List<SysResource> myMenus = new();
//管理员拥有全部权限
if (UserManager.IsSuperAdmin)
{
myMenus = allMenuList;
}
else
{
//获取角色所拥有的资源集合
var resourceList = await _relationService.GetRelationListByObjectIdListAndCategoryAsync(userInfo.RoleIdList, CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);
//定义菜单ID列表
HashSet<long> rolesMenuIdList = new();
//获取拥有权限的菜单Id集合
rolesMenuIdList.AddRange(resourceList.Select(r => r.TargetId.ToLong()).ToList());
//获取我的菜单列表
myMenus = allMenuList.Where(it => rolesMenuIdList.Contains(it.Id)).ToList();
}
// 对获取到的角色对应的菜单列表进行处理,获取父列表
var parentList = GetMyParentMenus(allMenuList, myMenus);
myMenus.AddRange(parentList);//合并列表
myMenus.Add(allSpaList.OrderBy(it => it.SortCode).FirstOrDefault());//第一个SPA会添加到菜单作为首页
//构建菜单树
result = _resourceService.ResourceListToTree(myMenus);
}
return result;
}
/// <inheritdoc />
[OperDesc("用户更新个人信息")]
public async Task UpdateUserInfoAsync(UpdateInfoInput input)
{
var newInput = input.Adapt<UpdateInfoInput>();
//如果手机号不是空
if (!string.IsNullOrEmpty(newInput.Phone))
{
if (!newInput.Phone.MatchPhoneNumber())//判断是否是手机号格式
throw Oops.Bah($"手机号码格式错误");
newInput.Phone = DESCEncryption.Encrypt(newInput.Phone, DESCKeyConst.DESCKey);
var any = await IsAnyAsync(it => it.Phone == newInput.Phone && it.Id != UserManager.UserId);//判断是否有重复的
if (any)
throw Oops.Bah($"系统已存在该手机号");
}
if (!string.IsNullOrEmpty(newInput.Email))
{
var match = newInput.Email.MatchEmail();
if (!match)
throw Oops.Bah($"邮箱格式错误");
}
//更新指定字段
var result = await UpdateAsync(it => new SysUser
{
Email = newInput.Email,
Phone = newInput.Phone,
}, it => it.Id == UserManager.UserId);
if (result)
_userService.DeleteUserFromCache(UserManager.UserId);//cache删除用户数据
}
/// <inheritdoc />
[OperDesc("用户更新工作台信息")]
public async Task UpdateWorkbenchAsync(List<long> input)
{
//关系表保存个人工作台
await _relationService.SaveRelationAsync(CateGoryConst.Relation_SYS_USER_WORKBENCH_DATA, UserManager.UserId, null, input.ToJsonString(), true);
}
#region
/// <summary>
/// 获取父菜单集合,已过滤掉同时存在的父节点
/// </summary>
/// <param name="allMenuList">所有菜单列表</param>
/// <param name="myMenus">我的菜单列表</param>
/// <returns></returns>
private List<SysResource> GetMyParentMenus(List<SysResource> allMenuList, List<SysResource> myMenus)
{
var parentList = new List<SysResource>();
myMenus.ForEach(it =>
{
//找到父ID对应的菜单
var parent = allMenuList.Where(r => r.Id == it.ParentId).FirstOrDefault();
if (parent != null && !parentList.Contains(parent) && !myMenus.Contains(parent))//如果不为空且夫列表里没有
{
parentList.Add(parent);//添加到父列表
}
});
return parentList;
}
#endregion
}

View File

@@ -1,48 +0,0 @@
#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 ThingsGateway.Admin.Application;
/// <summary>
/// 验证Id服务
/// </summary>
public interface IVerificatService : ITransient
{
/// <summary>
/// 获取验证ID
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<List<VerificatInfo>> GetOpenApiVerificatIdAsync(long userId);
/// <summary>
/// 获取验证ID
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<List<VerificatInfo>> GetVerificatIdAsync(long userId);
/// <summary>
/// 设置验证ID
/// </summary>
/// <param name="userId"></param>
/// <param name="values"></param>
Task SetOpenApiVerificatIdAsync(long userId, List<VerificatInfo> values);
/// <summary>
/// 设置验证ID
/// </summary>
/// <param name="userId"></param>
/// <param name="values"></param>
Task SetVerificatIdAsync(long userId, List<VerificatInfo> values);
}

View File

@@ -1,110 +0,0 @@
#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 Microsoft.Extensions.DependencyInjection;
namespace ThingsGateway.Admin.Application;
/// <inheritdoc cref="IVerificatService"/>
public class VerificatService : DbRepository<SysVerificat>, IVerificatService
{
private readonly IServiceScope _serviceScope;
public VerificatService(IServiceScopeFactory serviceScopeFactory)
{
_serviceScope = serviceScopeFactory.CreateScope();
}
/// <inheritdoc/>
public async Task<List<VerificatInfo>> GetOpenApiVerificatIdAsync(long userId)
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var data = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<VerificatInfo>>(CacheConst.CACHE_OPENAPIUSERVERIFICAT + userId, true);
if (data != null)
{
var infos = data.Where(it => it.VerificatTimeout > DateTimeExtensions.CurrentDateTime).ToList();//去掉登录超时的
if (infos.Count != data.Count)
await SetOpenApiVerificatIdAsync(userId, infos);
return infos;
}
else
{
var sys = await Context.Queryable<SysVerificat>().Where(it => it.Id == userId).FirstAsync();
if (sys != null)
{
var infos = sys.VerificatInfos.Where(it => it.VerificatTimeout > DateTimeExtensions.CurrentDateTime).ToList();//去掉登录超时的
await SetOpenApiVerificatIdAsync(userId, infos);
return infos;
}
return null;
}
}
/// <inheritdoc/>
public async Task<List<VerificatInfo>> GetVerificatIdAsync(long userId)
{
//先从Cache拿需要获取新的对象避免操作导致缓存中对象改变
var data = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<VerificatInfo>>(CacheConst.CACHE_USERVERIFICAT + userId, true);
if (data != null)
{
var infos = data.Where(it => it.VerificatTimeout > DateTimeExtensions.CurrentDateTime).ToList();//去掉登录超时的
if (infos.Count != data.Count)
await SetVerificatIdAsync(userId, infos);
return infos;
}
else
{
var sys = await Context.Queryable<SysVerificat>().Where(it => it.Id == userId).FirstAsync();
if (sys != null)
{
var infos = sys.VerificatInfos.Where(it => it.VerificatTimeout > DateTimeExtensions.CurrentDateTime).ToList();//去掉登录超时的
await SetVerificatIdAsync(userId, infos);
return infos;
}
}
return null;
}
/// <inheritdoc/>
public async Task SetOpenApiVerificatIdAsync(long userId, List<VerificatInfo> values)
{
SysVerificat sysverificat = new()
{
Id = userId,
VerificatInfos = values
};
//数据库变化后,更新缓存
var x = Context.Storageable(sysverificat).ToStorage();
var i1 = await x.AsInsertable.ExecuteCommandAsync();//不存在插入
var i2 = await x.AsUpdateable.ExecuteCommandAsync();//存在更新
if (i1 + i2 > 0)
{
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_OPENAPIUSERVERIFICAT + userId, values, false);
}
}
/// <inheritdoc/>
public async Task SetVerificatIdAsync(long userId, List<VerificatInfo> values)
{
SysVerificat sysverificat = new()
{
Id = userId,
VerificatInfos = values
};
//数据库变化后,更新缓存
var x = Context.Storageable(sysverificat).ToStorage();
var i1 = await x.AsInsertable.ExecuteCommandAsync();//不存在插入
var i2 = await x.AsUpdateable.ExecuteCommandAsync();//存在更新
if (i1 + i2 > 0)
{
_serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_USERVERIFICAT + userId, values, false);
}
}
}

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