From 5eac21fffe8fe6998649c7ebab0612957ad67d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9B=BD=E4=B8=9C?= <531035580@qq.com> Date: Wed, 13 Sep 2023 15:02:19 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fix(signalr):=20=E4=BF=AE=E5=A4=8D=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E4=B9=8B=E5=90=8E=E5=AF=86=E7=A0=81=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E6=B6=88=E6=81=AF=E6=94=B6=E4=B8=8D=E5=88=B0?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hub/SimpleHub.cs | 4 ++-- .../EventSubscriber/AuthEventSubscriber.cs | 23 +++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/api/SimpleAdmin/SimpleAdmin.Plugin/SimpleAdmin.Plugin.SignalR/Hub/SimpleHub.cs b/api/SimpleAdmin/SimpleAdmin.Plugin/SimpleAdmin.Plugin.SignalR/Hub/SimpleHub.cs index c76457a..28a4c08 100644 --- a/api/SimpleAdmin/SimpleAdmin.Plugin/SimpleAdmin.Plugin.SignalR/Hub/SimpleHub.cs +++ b/api/SimpleAdmin/SimpleAdmin.Plugin/SimpleAdmin.Plugin.SignalR/Hub/SimpleHub.cs @@ -8,7 +8,7 @@ namespace SimpleAdmin.Plugin.SignalR; /// /// /// -//[Authorize] +[Authorize] [MapHub("/hubs/simple")] [Authorize] public class SimpleHub : Hub @@ -98,4 +98,4 @@ public class SimpleHub : Hub } #endregion 方法 -} \ No newline at end of file +} diff --git a/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs b/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs index 6eb0f6a..b8bf346 100644 --- a/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs +++ b/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs @@ -74,15 +74,16 @@ public class AuthEventSubscriber : IEventSubscriber, ISingleton if (pwdRemind) { var pwdRemindDay = loginPolicy.First(x => x.ConfigKey == DevConfigConst.PWD_REMIND_DAY).ConfigValue.ToInt();//获取密码提醒时间 - if (DateTime.Now - pwdRemindUpdateTime > TimeSpan.FromDays(pwdRemindDay)) + if (DateTime.Now - pwdRemindUpdateTime < TimeSpan.FromDays(pwdRemindDay)) { - await messageService.Send(new MessageSendInput() + // 调用异步方法,延迟执行 DoSomething 方法 + await DelayedExecutionAsync(4000, () => messageService.Send(new MessageSendInput() { Subject = subject, Content = $"已超过{pwdRemindDay}天未修改密码,请及时修改密码", Category = CateGoryConst.Message_INFORM, ReceiverIdList = new List() { sysUser.Id } - }); + }).Wait()); } sysUser.PwdRemindUpdateTime = DateTime.Now;//设置提醒时密码时间为当前时间,避免重复提醒 } @@ -167,4 +168,18 @@ public class AuthEventSubscriber : IEventSubscriber, ISingleton var noticeService = _namedServiceProvider.GetService(noticeComponent);//获取服务 return noticeService; } -} \ No newline at end of file + + /// + /// 延迟执行 + /// + /// 毫秒 + /// 方法 + private async Task DelayedExecutionAsync(int millisecondsDelay, Action actionToExecute) + { + // 延迟指定的时间 + await Task.Delay(millisecondsDelay); + + // 执行目标方法 + actionToExecute.Invoke(); + } +} -- Gitee From 1d20592a2fee90e4c0efdf14ecebbbd2ebd80b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9B=BD=E4=B8=9C?= <531035580@qq.com> Date: Wed, 13 Sep 2023 15:10:29 +0800 Subject: [PATCH 2/9] =?UTF-8?q?fix(AuthEventSubscriber):=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=88=A4=E6=96=AD=E6=94=B9=E4=B8=BA=E6=AD=A3=E5=B8=B8?= =?UTF-8?q?=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs b/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs index b8bf346..19aec4f 100644 --- a/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs +++ b/api/SimpleAdmin/SimpleAdmin.System/EventSubscriber/AuthEventSubscriber.cs @@ -74,7 +74,7 @@ public class AuthEventSubscriber : IEventSubscriber, ISingleton if (pwdRemind) { var pwdRemindDay = loginPolicy.First(x => x.ConfigKey == DevConfigConst.PWD_REMIND_DAY).ConfigValue.ToInt();//获取密码提醒时间 - if (DateTime.Now - pwdRemindUpdateTime < TimeSpan.FromDays(pwdRemindDay)) + if (DateTime.Now - pwdRemindUpdateTime > TimeSpan.FromDays(pwdRemindDay)) { // 调用异步方法,延迟执行 DoSomething 方法 await DelayedExecutionAsync(4000, () => messageService.Send(new MessageSendInput() -- Gitee From 3c88ce17f5e8f1d6c63b1c7547ea5f6b726c2cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9B=BD=E4=B8=9C?= <531035580@qq.com> Date: Thu, 14 Sep 2023 14:20:30 +0800 Subject: [PATCH 3/9] =?UTF-8?q?fix(=E7=99=BB=E5=BD=95=E8=AE=A4=E8=AF=81):?= =?UTF-8?q?=20=E5=AF=86=E7=A0=81=E9=94=99=E8=AF=AF=E6=AC=A1=E6=95=B0?= =?UTF-8?q?=E8=BF=87=E5=A4=9A=E4=B9=8B=E5=90=8E=E5=BA=94=E8=AF=A5=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E9=94=81=E5=AE=9A=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/Auth/Auth/AuthService.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/api/SimpleAdmin/SimpleAdmin.System/Services/Auth/Auth/AuthService.cs b/api/SimpleAdmin/SimpleAdmin.System/Services/Auth/Auth/AuthService.cs index 4661a3e..1c90f69 100644 --- a/api/SimpleAdmin/SimpleAdmin.System/Services/Auth/Auth/AuthService.cs +++ b/api/SimpleAdmin/SimpleAdmin.System/Services/Auth/Auth/AuthService.cs @@ -9,11 +9,8 @@ public class AuthService : IAuthService private readonly ISysUserService _userService; private readonly IRoleService _roleService; - public AuthService(ISimpleCacheService simpleCacheService, - IEventPublisher eventPublisher, - IConfigService configService, - ISysUserService userService, - IRoleService roleService) + public AuthService(ISimpleCacheService simpleCacheService, IEventPublisher eventPublisher, IConfigService configService, + ISysUserService userService, IRoleService roleService) { _simpleCacheService = simpleCacheService; _eventPublisher = eventPublisher; @@ -60,8 +57,6 @@ public class AuthService : IAuthService return reqNo; } - - /// public async Task Login(LoginInput input, LoginClientTypeEnum loginClientType) { @@ -164,6 +159,7 @@ public class AuthService : IAuthService var errorCountCache = _simpleCacheService.Get(key);//获取登录错误次数 if (errorCountCache >= errorCount) { + _simpleCacheService.SetExpire(key, TimeSpan.FromMinutes(lockTime));//设置缓存 throw Oops.Bah($"密码错误次数过多,请{lockTime}分钟后再试"); } } @@ -422,4 +418,4 @@ public class AuthService : IAuthService } #endregion 方法 -} \ No newline at end of file +} -- Gitee From 116859e30ef7c1f656b1adf8aa1344c74e9989a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9B=BD=E4=B8=9C?= <531035580@qq.com> Date: Tue, 19 Sep 2023 11:37:09 +0800 Subject: [PATCH 4/9] =?UTF-8?q?fix(BaseEntity):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=B9=8B=E5=90=8Ecreateorgid=E4=B8=BA0?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/SimpleAdmin/SimpleAdmin.SqlSugar/Entity/BaseEntity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/SimpleAdmin/SimpleAdmin.SqlSugar/Entity/BaseEntity.cs b/api/SimpleAdmin/SimpleAdmin.SqlSugar/Entity/BaseEntity.cs index 90bad68..a2a7b14 100644 --- a/api/SimpleAdmin/SimpleAdmin.SqlSugar/Entity/BaseEntity.cs +++ b/api/SimpleAdmin/SimpleAdmin.SqlSugar/Entity/BaseEntity.cs @@ -74,6 +74,6 @@ public abstract class DataEntityBase : BaseEntity /// /// 创建者部门Id /// - [SugarColumn(ColumnDescription = "创建者部门Id")] + [SugarColumn(ColumnDescription = "创建者部门Id", IsOnlyIgnoreUpdate = true, IsNullable = true)] public virtual long CreateOrgId { get; set; } -} \ No newline at end of file +} -- Gitee From 6a0c64cf249c6b69a317021f4dde5a26c76a2a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9B=BD=E4=B8=9C?= <531035580@qq.com> Date: Tue, 19 Sep 2023 11:55:27 +0800 Subject: [PATCH 5/9] =?UTF-8?q?perf(CodeFirstUtils):=20=E4=BC=98=E5=8C=96c?= =?UTF-8?q?odefirst=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleAdmin.SqlSugar/Utils/CodeFirstUtils.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api/SimpleAdmin/SimpleAdmin.SqlSugar/Utils/CodeFirstUtils.cs b/api/SimpleAdmin/SimpleAdmin.SqlSugar/Utils/CodeFirstUtils.cs index 20e6c83..6705e91 100644 --- a/api/SimpleAdmin/SimpleAdmin.SqlSugar/Utils/CodeFirstUtils.cs +++ b/api/SimpleAdmin/SimpleAdmin.SqlSugar/Utils/CodeFirstUtils.cs @@ -16,12 +16,15 @@ public static class CodeFirstUtils /// 程序集名称 public static void CodeFirst(BaseOptions options, string assemblyName) { + var appName = assemblyName.Split(",")[0]; if (options.InitTable)//如果需要初始化表结构 { + Console.WriteLine($"开始初始化{appName}数据库表结构"); InitTable(assemblyName); } if (options.InitSeedData) { + Console.WriteLine($"开始初始化{appName}数据库种子数据"); InitSeedData(assemblyName); } } @@ -34,7 +37,8 @@ public static class CodeFirstUtils private static void InitTable(string assemblyName) { // 获取所有实体表-初始化表结构 - var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false) && u.Assembly.FullName == assemblyName); + var entityTypes = App.EffectiveTypes.Where(u => + !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false) && u.Assembly.FullName == assemblyName); if (!entityTypes.Any()) return;//没有就退出 foreach (var entityType in entityTypes) { @@ -190,4 +194,4 @@ public static class CodeFirstUtils var sc = pi.GetCustomAttributes(false).FirstOrDefault(u => u.IsJson == true); return sc != null; } -} \ No newline at end of file +} -- Gitee From 09e1c09a3c074bcabd94747599bc0b95887507e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9B=BD=E4=B8=9C?= <531035580@qq.com> Date: Wed, 20 Sep 2023 09:14:13 +0800 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0xml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/SimpleAdmin/SimpleAdmin.System/SimpleAdmin.System.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/SimpleAdmin/SimpleAdmin.System/SimpleAdmin.System.xml b/api/SimpleAdmin/SimpleAdmin.System/SimpleAdmin.System.xml index 3a6c6a5..ee835db 100644 --- a/api/SimpleAdmin/SimpleAdmin.System/SimpleAdmin.System.xml +++ b/api/SimpleAdmin/SimpleAdmin.System/SimpleAdmin.System.xml @@ -1304,6 +1304,13 @@ + + + 延迟执行 + + 毫秒 + 方法 + 事件总线常量 -- Gitee From 6bec51631950a68ec2166c5e3848b5891d4e7cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=91=E6=9E=97=E5=AF=BA=E9=A9=BB=E5=8C=97=E5=9B=BA?= =?UTF-8?q?=E5=B1=B1=E5=8A=9E=E4=BA=8B=E5=A4=84=E5=A4=A7=E7=A5=9E=E7=88=B6?= =?UTF-8?q?=E7=8E=8B=E5=96=87=E5=98=9B?= <531035580@qq.com> Date: Wed, 20 Sep 2023 09:21:04 +0800 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0nginx=E7=9A=84htt?= =?UTF-8?q?ps=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/webSimpleAdminHttps.conf | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 web/webSimpleAdminHttps.conf diff --git a/web/webSimpleAdminHttps.conf b/web/webSimpleAdminHttps.conf new file mode 100644 index 0000000..e4d8a3f --- /dev/null +++ b/web/webSimpleAdminHttps.conf @@ -0,0 +1,69 @@ +server { + listen 81; #端口 + listen 444 ssl; #ssl端口 + ssl on; + server_name youdomain.com; #域名 + + ssl_certificate /www/cert/youdomain.com_bundle.pem; #ssl证书文件 + ssl_certificate_key /www/cert/youdomain.com.key; #ssl证书文件 + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + #上面的根据需求修改 + #ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #安全链接可选的加密协议 + ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; #这里不用v1增加了v1.3 + ssl_prefer_server_ciphers on; #使用服务器端的首选算法 + + location / { + #proxy_pass http:127.0.0.1:81; + root /www/youprojectpath; + try_files $uri $uri/ @router; + index index.html index.htm; + error_page 405 =200 http://$host$request_uri; + } + + # 压缩chunk-vendors.js,加快首次加载速度 + gzip on; + gzip_min_length 1k; + gzip_comp_level 9; + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; + gzip_vary on; + gzip_disable "MSIE [1-6]\."; + + # 代理后端接口 + location /api/ { + # host 修改为真实的域名和端口 + proxy_set_header Host $http_host; + # 客户端真实ip + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # 客户端真实协议(http/https) + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://127.0.0.1:5566; # 转发请求的地址 + rewrite ^/api/(.*)$ /$1 break; + } + + location /hubs/ { + # host 修改为真实的域名和端口 + proxy_set_header Host $http_host; + # 客户端真实ip + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # 客户端真实协议(http/https) + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://127.0.0.1:5566; # 转发请求的地址 + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + + location @router { + rewrite ^.*$ /index.html last; + } + + error_page 500 502 503 504 /50x.html; + error_page 497 301 https://$http_host$request_uri; #这个我也不知道原理 反正能跳转到https + + location = /50x.html { + root html; + } + +} \ No newline at end of file -- Gitee From f643b58133493818ec850026f8999484c604b1dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9B=BD=E4=B8=9C?= <531035580@qq.com> Date: Wed, 27 Sep 2023 11:28:11 +0800 Subject: [PATCH 8/9] =?UTF-8?q?fix:=20=E8=BF=9B=E8=A1=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E5=90=8E=EF=BC=8C=E6=9B=B4=E6=96=B0=E6=97=B6?= =?UTF-8?q?=E9=97=B4/=E6=9B=B4=E6=96=B0=E7=94=A8=E6=88=B7=20=E7=AD=89?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E6=B2=A1=E6=9C=89=E5=AE=9E=E6=97=B6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=9A=84=E9=97=AE=E9=A2=98#I84PQ9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/System/User/SysUserService.cs | 39 ++++++++++++------- .../System/UserCenter/UserCenterService.cs | 18 ++++----- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/api/SimpleAdmin/SimpleAdmin.System/Services/System/User/SysUserService.cs b/api/SimpleAdmin/SimpleAdmin.System/Services/System/User/SysUserService.cs index 49034e6..4bcb146 100644 --- a/api/SimpleAdmin/SimpleAdmin.System/Services/System/User/SysUserService.cs +++ b/api/SimpleAdmin/SimpleAdmin.System/Services/System/User/SysUserService.cs @@ -159,12 +159,14 @@ public class SysUserService : DbRepository, ISysUserService var roleIdList = roleList.Select(x => x.TargetId.ToLong()).ToList();//角色ID列表 if (roleIdList.Count > 0)//如果该用户有角色 { - resourceList = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList, CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);//获取资源集合 + resourceList = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList, + CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);//获取资源集合 } } resourceList.ForEach(it => { - if (!string.IsNullOrEmpty(it.ExtJson)) buttonIdList.AddRange(it.ExtJson.ToJsonEntity().ButtonInfo);//如果有按钮权限,将按钮ID放到buttonIdList + if (!string.IsNullOrEmpty(it.ExtJson)) + buttonIdList.AddRange(it.ExtJson.ToJsonEntity().ButtonInfo);//如果有按钮权限,将按钮ID放到buttonIdList }); if (buttonIdList.Count > 0) { @@ -177,14 +179,17 @@ public class SysUserService : DbRepository, ISysUserService public async Task> GetPermissionListByUserId(long userId, long orgId) { var permissions = new List();//权限集合 - var sysRelations = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.Relation_SYS_USER_HAS_PERMISSION);//根据用户ID获取用户权限 + var sysRelations = + await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.Relation_SYS_USER_HAS_PERMISSION);//根据用户ID获取用户权限 if (sysRelations.Count == 0)//如果有表示用户单独授权了不走用户角色 { - var roleIdList = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.Relation_SYS_USER_HAS_ROLE);//根据用户ID获取角色ID + var roleIdList = + await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.Relation_SYS_USER_HAS_ROLE);//根据用户ID获取角色ID if (roleIdList.Count > 0)//如果角色ID不为空 { //获取角色权限信息 - sysRelations = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList.Select(it => it.TargetId.ToLong()).ToList(), CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION); + sysRelations = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList.Select(it => it.TargetId.ToLong()).ToList(), + CateGoryConst.Relation_SYS_ROLE_HAS_PERMISSION); } } var relationGroup = sysRelations.GroupBy(it => it.TargetId).ToList();//根据目标ID,也就是接口名分组,因为存在一个用户多个角色 @@ -440,7 +445,7 @@ public class SysUserService : DbRepository, ISysUserService throw Oops.Bah($"不可禁用系统内置超管用户账号"); CheckSelf(input.Id, SimpleAdminConst.Disable);//判断是不是自己 //设置状态为禁用 - if (await UpdateAsync(it => new SysUser + if (await UpdateSetColumnsTrueAsync(it => new SysUser { UserStatus = DevDictConst.COMMON_STATUS_DISABLED }, it => it.Id == input.Id)) @@ -453,7 +458,7 @@ public class SysUserService : DbRepository, ISysUserService { CheckSelf(input.Id, SimpleAdminConst.Enable);//判断是不是自己 //设置状态为启用 - if (await UpdateAsync(it => new SysUser + if (await UpdateSetColumnsTrueAsync(it => new SysUser { UserStatus = DevDictConst.COMMON_STATUS_ENABLE }, it => it.Id == input.Id)) @@ -465,7 +470,7 @@ public class SysUserService : DbRepository, ISysUserService { var password = await GetDefaultPassWord(true);//获取默认密码,这里不走Aop所以需要加密一下 //重置密码 - if (await UpdateAsync(it => new SysUser + if (await UpdateSetColumnsTrueAsync(it => new SysUser { Password = password }, it => it.Id == input.Id)) @@ -483,7 +488,8 @@ public class SysUserService : DbRepository, ISysUserService throw Oops.Bah($"不能给超管分配角色"); CheckSelf(input.Id, SimpleAdminConst.GrantRole);//判断是不是自己 //给用户赋角色 - await _relationService.SaveRelationBatch(CateGoryConst.Relation_SYS_USER_HAS_ROLE, input.Id, input.RoleIdList.Select(it => it.ToString()).ToList(), null, true); + await _relationService.SaveRelationBatch(CateGoryConst.Relation_SYS_USER_HAS_ROLE, input.Id, + input.RoleIdList.Select(it => it.ToString()).ToList(), null, true); DeleteUserFromRedis(input.Id);//从redis删除用户信息 } } @@ -553,7 +559,8 @@ public class SysUserService : DbRepository, ISysUserService { var relatioRep = ChangeRepository>();//切换仓储 await relatioRep.DeleteAsync(it => - it.ObjectId == sysUser.Id && (it.Category == CateGoryConst.Relation_SYS_USER_HAS_PERMISSION || it.Category == CateGoryConst.Relation_SYS_USER_HAS_RESOURCE)); + it.ObjectId == sysUser.Id && (it.Category == CateGoryConst.Relation_SYS_USER_HAS_PERMISSION + || it.Category == CateGoryConst.Relation_SYS_USER_HAS_RESOURCE)); await relatioRep.InsertRangeAsync(relationRoles);//添加新的 }); if (result.IsSuccess)//如果成功了 @@ -581,7 +588,8 @@ public class SysUserService : DbRepository, ISysUserService { var apiUrls = input.GrantInfoList.Select(it => it.ApiUrl).ToList();//apiurl列表 var extJsons = input.GrantInfoList.Select(it => it.ToJson()).ToList();//拓展信息 - await _relationService.SaveRelationBatch(CateGoryConst.Relation_SYS_USER_HAS_PERMISSION, input.Id, apiUrls, extJsons, true);//添加到数据库 + await _relationService.SaveRelationBatch(CateGoryConst.Relation_SYS_USER_HAS_PERMISSION, input.Id, apiUrls, extJsons, + true);//添加到数据库 DeleteUserFromRedis(input.Id); } } @@ -633,12 +641,15 @@ public class SysUserService : DbRepository, ISysUserService updatePositionJsonUser.Add(position); }); //定义删除的关系 - var delRelations = new List { CateGoryConst.Relation_SYS_USER_HAS_RESOURCE, CateGoryConst.Relation_SYS_USER_HAS_PERMISSION, CateGoryConst.Relation_SYS_USER_HAS_ROLE }; + var delRelations = new List + { + CateGoryConst.Relation_SYS_USER_HAS_RESOURCE, CateGoryConst.Relation_SYS_USER_HAS_PERMISSION, CateGoryConst.Relation_SYS_USER_HAS_ROLE + }; //事务 var result = await itenant.UseTranAsync(async () => { //清除该用户作为主管信息 - await UpdateAsync(it => new SysUser + await UpdateSetColumnsTrueAsync(it => new SysUser { DirectorId = null }, it => ids.Contains(it.DirectorId.Value)); @@ -1025,4 +1036,4 @@ public class SysUserService : DbRepository, ISysUserService } #endregion 方法 -} \ No newline at end of file +} diff --git a/api/SimpleAdmin/SimpleAdmin.System/Services/System/UserCenter/UserCenterService.cs b/api/SimpleAdmin/SimpleAdmin.System/Services/System/UserCenter/UserCenterService.cs index 877148b..7a2f90f 100644 --- a/api/SimpleAdmin/SimpleAdmin.System/Services/System/UserCenter/UserCenterService.cs +++ b/api/SimpleAdmin/SimpleAdmin.System/Services/System/UserCenter/UserCenterService.cs @@ -44,7 +44,8 @@ public class UserCenterService : DbRepository, IUserCenterService var resourceList = await _relationService.GetRelationListByObjectIdAndCategory(userInfo.Id, CateGoryConst.Relation_SYS_USER_HAS_RESOURCE); if (resourceList.Count == 0)//如果没有就获取角色的 //获取角色所拥有的资源集合 - resourceList = await _relationService.GetRelationListByObjectIdListAndCategory(userInfo.RoleIdList, CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE); + resourceList = await _relationService.GetRelationListByObjectIdListAndCategory(userInfo.RoleIdList, + CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE); //定义菜单ID列表 var menuIdList = new HashSet(); @@ -188,7 +189,7 @@ public class UserCenterService : DbRepository, IUserCenterService } //更新指定字段 - var result = await UpdateAsync(it => new SysUser + var result = await UpdateSetColumnsTrueAsync(it => new SysUser { Name = input.Name, Email = input.Email, @@ -213,7 +214,7 @@ public class UserCenterService : DbRepository, IUserCenterService var newSignature = signatureArray[0] + "," + newBase64String;//赋值新的签名 //更新签名 - var result = await UpdateAsync(it => new SysUser + var result = await UpdateSetColumnsTrueAsync(it => new SysUser { Signature = newSignature }, it => it.Id == UserManager.UserId); @@ -225,7 +226,8 @@ public class UserCenterService : DbRepository, IUserCenterService public async Task UpdateWorkbench(UpdateWorkbenchInput input) { //关系表保存个人工作台 - await _relationService.SaveRelation(CateGoryConst.Relation_SYS_USER_WORKBENCH_DATA, UserManager.UserId, null, input.WorkbenchData, true); + await _relationService.SaveRelation(CateGoryConst.Relation_SYS_USER_WORKBENCH_DATA, UserManager.UserId, null, input.WorkbenchData, + true); } /// @@ -262,8 +264,7 @@ public class UserCenterService : DbRepository, IUserCenterService // if (similarity > 80) // throw Oops.Bah($"新密码请勿与旧密码过于相似"); newPassword = CryptogramUtil.Sm4Encrypt(newPassword);//SM4加密 - userInfo.Password = newPassword; - await Context.Updateable(userInfo).UpdateColumns(it => new { it.Password }).ExecuteCommandAsync();//修改密码 + await UpdateSetColumnsTrueAsync(it => new SysUser() { Password = newPassword }, it => it.Id == userInfo.Id); _userService.DeleteUserFromRedis(UserManager.UserId);//redis删除用户数据 } @@ -279,8 +280,7 @@ public class UserCenterService : DbRepository, IUserCenterService fileStream.Close(); var base64String = Convert.ToBase64String(bytes);//转base64 var avatar = base64String.ToImageBase64();//转图片 - userInfo.Avatar = avatar; - await Context.Updateable(userInfo).UpdateColumns(it => new { it.Avatar }).ExecuteCommandAsync();//修改密码 + await UpdateSetColumnsTrueAsync(it => new SysUser() { Avatar = avatar }, it => it.Id == userInfo.Id); _userService.DeleteUserFromRedis(UserManager.UserId);//redis删除用户数据 return avatar; } @@ -435,4 +435,4 @@ public class UserCenterService : DbRepository, IUserCenterService } #endregion 方法 -} \ No newline at end of file +} -- Gitee From 137fd7595ed2abd335f4534e5bbf29ecd1b9a2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=91=E6=9E=97=E5=AF=BA=E9=A9=BB=E5=8C=97=E5=9B=BA?= =?UTF-8?q?=E5=B1=B1=E5=8A=9E=E4=BA=8B=E5=A4=84=E5=A4=A7=E7=A5=9E=E7=88=B6?= =?UTF-8?q?=E7=8E=8B=E5=96=87=E5=98=9B?= <531035580@qq.com> Date: Fri, 3 Nov 2023 10:20:56 +0800 Subject: [PATCH 9/9] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 127 ++++++++++-------- .../SimpleAdmin.Web.Entry/Program.cs | 8 +- 2 files changed, 77 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 1e24dc6..140465b 100644 --- a/README.md +++ b/README.md @@ -4,23 +4,28 @@
- + +
### 如果您觉得有帮助,请点右上角 "Star" 支持一下谢谢 -## 🎨框架介绍🎨 -🪶SimpleAdmin是一个小而美的通用业务型后台管理系统,专为解决开发过程中的痛点难点而生。Vue3+Vite+Vuex+JS,并在此基础上增加更人性化功能,后端基于.NET6/7+Furion,ORM采用Sqlsugar+单例模式,插件式开发。采用RBAC+多机构的权限管理模式,实现全网最灵活的接口级别数据权限控制,集成国密加解密,导入导出、导入导出、批量修改等常用插件。后端代码注释覆盖率>90%,并配备超牛皮的代码生成器和超详细的手摸手教学文档,非常适合二次开发。将日常开发中的业务场景和框架紧密结合,并坚持以人为本,以业务为中心,做到开箱即用,代码简洁、易扩展,注释详细,文档齐全,让你的开发少走弯路。 +## 🎨 框架介绍 🎨 + +🪶SimpleAdmin 是一个小而美的通用业务型后台管理系统,专为解决开发过程中的痛点难点而生。Vue3+Vite+Vuex+JS,并在此基础上增加更人性化功能,后端基于.NET6/7+Furion,ORM 采用 Sqlsugar+单例模式,插件式开发。采用 RBAC+多机构的权限管理模式,实现全网最灵活的接口级别数据权限控制,集成国密加解密,导入导出、导入导出、批量修改等常用插件。后端代码注释覆盖率>90%,并配备超牛皮的代码生成器和超详细的手摸手教学文档,非常适合二次开发。将日常开发中的业务场景和框架紧密结合,并坚持以人为本,以业务为中心,做到开箱即用,代码简洁、易扩展,注释详细,文档齐全,让你的开发少走弯路。 + +## 🐥 选择 SimpleAdmin 的 N 个理由 🐥 -## 🐥选择SimpleAdmin的N个理由🐥 +#### 📕 前端采用 Vue3+JavaScript -#### 📕前端采用Vue3+JavaScript -本系统是基于前端Vue3+Vite+Vuex+JS,。市面上主流的Vue3框架大部分都是采用`TypeScript`开发,虽然是官方推荐,但是也增加了一些学习成本,如果您之前使用的事vue2+js的开发方式,那么再使用本系统就非常的好上手,也不用担心vue2打包之后第一次加载巨慢的问题。 +本系统是基于前端 Vue3+Vite+Vuex+JS,。市面上主流的 Vue3 框架大部分都是采用`TypeScript`开发,虽然是官方推荐,但是也增加了一些学习成本,如果您之前使用的事 vue2+js 的开发方式,那么再使用本系统就非常的好上手,也不用担心 vue2 打包之后第一次加载巨慢的问题。 +#### 📗 后台基于 Furion 脚手架 + +后端基于 Furion 脚手架搭建。Furion 是目前.NET 最好用的后端框架之一,有着全网最详细的使用文档和说明,作为新手或二次开发也能很快的上手,你想要的功能基本都能在 Furion 中找到。而且只要提 issues 作者基本上都能快速解答,没有后顾之忧。 + +##### 🍎 Furion 框架特点 -#### 📗后台基于Furion脚手架 -后端基于Furion脚手架搭建。Furion是目前.NET最好用的后端框架之一,有着全网最详细的使用文档和说明,作为新手或二次开发也能很快的上手,你想要的功能基本都能在Furion中找到。而且只要提issues作者基本上都能快速解答,没有后顾之忧。 -##### 🍎 Furion框架特点 - 全新面貌:基于 `.NET5/6/7+` 平台,没有历史包袱 - 极少依赖:框架只依赖两个第三方包 - 极易入门:只需要一个 `Inject()` 即可完成配置 @@ -34,84 +39,95 @@ 源码地址:[https://gitee.com/dotnetchina/Furion](https://gitee.com/dotnetchina/Furion) -#### 🍭ORM基于Sqlsugar -SqlSugar是一款老牌.NET开源ORM框架,由果糖大数据科技团队维护和更新 ,开箱即用 -最易上手的ORM框架,本系统也是基于Sqlsugar单例模式+CodeFirst+仓储的结构,无需担心作用域问题,直接爽撸! +#### 🍭ORM 基于 Sqlsugar + +SqlSugar 是一款老牌.NET 开源 ORM 框架,由果糖大数据科技团队维护和更新 ,开箱即用 +最易上手的 ORM 框架,本系统也是基于 Sqlsugar 单例模式+CodeFirst+仓储的结构,无需担心作用域问题,直接爽撸! 文档地址:[https://www.donet5.com/Home/Doc](https://www.donet5.com/Home/Doc) 源码地址:[https://gitee.com/dotnetchina/SqlSugar](https://gitee.com/dotnetchina/SqlSugar) -#### 🎮真·插件式开发,代码更灵活,架构更清晰 +#### 🎮 真·插件式开发,代码更灵活,架构更清晰 + 引入插件式开发的概念,除项目主体外,每个业务层都可以是独立的,一些拓展性功能采用插件的方式创建在独立的类库中,每一层都可以单独设置初始化表数据结构和种子数据,这样的话我们想要用哪个功能就引用该功能的项目,如果功能有问题我们也能快速定位到代码的位置,非常方便,也使得项目架构变得非常清晰,代码更灵活了,避免后期功能越来越多导致项目成为屎山。 -#### 📘极致缓存,系统快人一步 +#### 📘 极致缓存,系统快人一步 + 本系统使用了大量的缓存操作,一些基础配置和用户权限信息都放在了缓存中,用户首次登录后,下次再登录接口耗时实测`10-30ms`。 -系统同时支持MemeryCache和Redis分布式缓存,Redis客户端使用的是我基于[NewLife.Redis](https://github.com/NewLifeX/NewLife.Redis)二次封装的[SimpleRedis](https://gitee.com/zxzyjs/SimpleRedis.git)。简化了注入操作,更方便使用。 +系统同时支持 MemeryCache 和 Redis 分布式缓存,Redis 客户端使用的是我基于[NewLife.Redis](https://github.com/NewLifeX/NewLife.Redis)二次封装的[SimpleRedis](https://gitee.com/zxzyjs/SimpleRedis.git)。简化了注入操作,更方便使用。 + +##### 🍎NewLife.Redis 特性 -##### 🍎NewLife.Redis特性 -* 在ZTO大数据实时计算广泛应用,200多个Redis实例稳定工作一年多,每天处理近1亿包裹数据,日均调用量80亿次 -* 低延迟,Get/Set操作平均耗时200~600us(含往返网络通信) -* 大吞吐,自带连接池,最大支持1000并发 -* 高性能,支持二进制序列化 +- 在 ZTO 大数据实时计算广泛应用,200 多个 Redis 实例稳定工作一年多,每天处理近 1 亿包裹数据,日均调用量 80 亿次 +- 低延迟,Get/Set 操作平均耗时 200~600us(含往返网络通信) +- 大吞吐,自带连接池,最大支持 1000 并发 +- 高性能,支持二进制序列化 #### 👮RBAC+多机构的权限管理模式+权限及时刷新 -作为一个后台管理系统,一个权限管理框架,权限设计作为一个管理系统的灵魂,是一个系统好不好用的关键。本系统是采用RBAC+多机构的权限管理模式,一个机构下有多个角色,每个角色有不同的菜单和权限,可以将不同角色分配给不同的用户,这样每个用户都会拥有他所属角色的权限。当然,一个用户也可以拥有多个角色的权限,除此之外还支持给用户单独授权,让用户脱离所有角色之外,实现灵活再灵活的权限控制。并且当角色或用户的权限被修改之后,后端会立即刷新,前端只需刷新页面就能更新被重新赋予的权限,无需重新登录。 +作为一个后台管理系统,一个权限管理框架,权限设计作为一个管理系统的灵魂,是一个系统好不好用的关键。本系统是采用 RBAC+多机构的权限管理模式,一个机构下有多个角色,每个角色有不同的菜单和权限,可以将不同角色分配给不同的用户,这样每个用户都会拥有他所属角色的权限。当然,一个用户也可以拥有多个角色的权限,除此之外还支持给用户单独授权,让用户脱离所有角色之外,实现灵活再灵活的权限控制。并且当角色或用户的权限被修改之后,后端会立即刷新,前端只需刷新页面就能更新被重新赋予的权限,无需重新登录。 -#### 🧱接口级别的数据范围权限 -目前在我接触的大部分管理系统中,数据权限这块都不太尽如人意,要么只有接口权限没有数据权限,要么有数据权限但是用起来不是特别顺手而且还有BUG,针对以上痛点和难点结合业务场景,本系统实现全网最灵活的接口级别数据范围权限控制,可以指定某个角色的某个接口的数据权限范围,非常的灵活。 +#### 🧱 接口级别的数据范围权限 +目前在我接触的大部分管理系统中,数据权限这块都不太尽如人意,要么只有接口权限没有数据权限,要么有数据权限但是用起来不是特别顺手而且还有 BUG,针对以上痛点和难点结合业务场景,本系统实现全网最灵活的接口级别数据范围权限控制,可以指定某个角色的某个接口的数据权限范围,非常的灵活。 在系统中,获取数据权限非常简单,只需一个方法搞定。 + ```cs //获取数据范围 var dataScope = await _sysUserService.GetLoginUserApiDataScope(); ``` -#### 📈启动及运行 -您是否有过在使用其他框架时,光是从`启动`到`运行`都会遇到各种奇奇怪怪的问题?并且使用过程中也是各种奇奇怪怪的bug,发到群里也没人解决,非常影响开发效率。本系统做到了`启动即运行`,就算是小白只要照着文档操作,也能非常容易的上手项目。就目前使用的反馈来看,业务占据大多数,系统问题只占很少的一部分,如果您在使用过程中遇到问题,或者发现bug,可以直接发issues描述您的问题,只要是系统bug第一时间修复。或者您对当前系统有什么建议或意见,也欢迎您提出,只要是符合大部分业务场景的都会考虑支持。我们也有和谐内部的qq/微信交流群,没有像其他系统qq群一样每天都是一堆启动报错问题,页面错误问题,有的只是系统功能的讨论和优化方案。 -#### 🍢支持多种主键类型 -系统默认采用`long`类型的`雪花ID`作为系统主键,但是在交流过程中发现,部分小伙伴使用`string`类型或者`guid`作为系统主键,还有的是部分老系统用的是string类型,但是simpleadmin确是`long`类型,所以根据这个业务场景,本框架也支持`String`类型的系统主键,只需要拉取对应的`stringid`分支即可,完全不需要另外去修改代码,并且也能和master分支进行最新的同步。 +#### 📈 启动及运行 + +您是否有过在使用其他框架时,光是从`启动`到`运行`都会遇到各种奇奇怪怪的问题?并且使用过程中也是各种奇奇怪怪的 bug,发到群里也没人解决,非常影响开发效率。本系统做到了`启动即运行`,就算是小白只要照着文档操作,也能非常容易的上手项目。就目前使用的反馈来看,业务占据大多数,系统问题只占很少的一部分,如果您在使用过程中遇到问题,或者发现 bug,可以直接发 issues 描述您的问题,只要是系统 bug 第一时间修复。或者您对当前系统有什么建议或意见,也欢迎您提出,只要是符合大部分业务场景的都会考虑支持。我们也有和谐内部的 qq/微信交流群,没有像其他系统 qq 群一样每天都是一堆启动报错问题,页面错误问题,有的只是系统功能的讨论和优化方案。 -#### 📞支持Mqtt/Signalr的即时通讯 -作为前后端分离项目,前后端交互是一个非常重要的功能。目前主流框架都是通过Socket实现,本系统自然也是实现了基于Signalr的前后端交互,并在此基础上实现了基于MQTT的前后端交互功能,MQTT相比socket业务场景更多更灵活,在物联网方向有着非常多的应用。.NET应用在工业物联网方向也是有很多的岗位,学习MQTT还是非常有必要的。 +#### 🍢 支持多种主键类型 -MQTT客户端使用的是我基于[NewLife.MQTT](https://github.com/NewLifeX/NewLife.MQTT)二次封装的[SimpleMQTT](https://gitee.com/zxzyjs/SimpleMQTT.git)。采用单例模式,可以动态的添加和删除mqtt客户端,非常好用。 +系统默认采用`long`类型的`雪花ID`作为系统主键,但是在交流过程中发现,部分小伙伴使用`string`类型或者`guid`作为系统主键,还有的是部分老系统用的是 string 类型,但是 simpleadmin 确是`long`类型,所以根据这个业务场景,本框架也支持`String`类型的系统主键,只需要拉取对应的`stringid`分支即可,完全不需要另外去修改代码,并且也能和 master 分支进行最新的同步。 + +#### 📞 支持 Mqtt/Signalr 的即时通讯 + +作为前后端分离项目,前后端交互是一个非常重要的功能。目前主流框架都是通过 Socket 实现,本系统自然也是实现了基于Signalr的前后端交互,并在此基础上实现了基于MQTT的前后端交互功能,MQTT 相比 socket 业务场景更多更灵活,在物联网方向有着非常多的应用。.NET 应用在工业物联网方向也是有很多的岗位,学习 MQTT 还是非常有必要的。 + +MQTT 客户端使用的是我基于[NewLife.MQTT](https://github.com/NewLifeX/NewLife.MQTT)二次封装的[SimpleMQTT](https://gitee.com/zxzyjs/SimpleMQTT.git)。采用单例模式,可以动态的添加和删除 mqtt 客户端,非常好用。 文档地址:[https://www.cnblogs.com/huguodong/p/16991947.html](https://www.cnblogs.com/huguodong/p/16991947.html) -#### 🔧代码生成器 -大部分项目里,其实有很多代码是重复的,几乎每个模块都有 CRUD 增删改查的功能,而这些功能的实现代码往往是大同小异的。如果这些功能都要自己去手写,非常无聊枯燥,浪费时间且效率很低,还可能会写错。代码生成功能通过选择数据库表,完成单表的增删改查管理功能,还支持树形结构的表的生成可以生成包括前端、后端、和SQL语句,支持预览的同时还支持ZIP压缩包和直接生成到项目两种模式,解放你的双手,大大减少了重复代码的编写,无需复制提升开发效率。 +#### 🔧 代码生成器 +大部分项目里,其实有很多代码是重复的,几乎每个模块都有 CRUD 增删改查的功能,而这些功能的实现代码往往是大同小异的。如果这些功能都要自己去手写,非常无聊枯燥,浪费时间且效率很低,还可能会写错。代码生成功能通过选择数据库表,完成单表的增删改查管理功能,还支持树形结构的表的生成可以生成包括前端、后端、和 SQL 语句,支持预览的同时还支持 ZIP 压缩包和直接生成到项目两种模式,解放你的双手,大大减少了重复代码的编写,无需复制提升开发效率。 -#### 🎺常用功能组件化 -在系统一些常用的功能直接封装成vue组件,如批量导入,批量导出,批量删除,批量编辑等,只需按照规范传入相应参数就可以很好的实现功能,减少了很多不必要的前端代码。最典型的就是批量导入组件,只需传入api接口,通过后端接口自动生成表头,并实现字段级别的错误信息提示和预览,大数据支持分段导入,非常好用。 +#### 🎺 常用功能组件化 +在系统一些常用的功能直接封装成 vue 组件,如批量导入,批量导出,批量删除,批量编辑等,只需按照规范传入相应参数就可以很好的实现功能,减少了很多不必要的前端代码。最典型的就是批量导入组件,只需传入 api 接口,通过后端接口自动生成表头,并实现字段级别的错误信息提示和预览,大数据支持分段导入,非常好用。 + +#### 📖 最详细的注释和手摸手教学文档,开发效率直线提升 -#### 📖最详细的注释和手摸手教学文档,开发效率直线提升 作为一个开源项目,如何让使用者看懂代码是非常重要的,很多作者会忽视这一点,导致我们阅读其代码的时候很难理解其为什么要这么写,如果没有详细的文档,想要二次开发需要花精力去研究源码。而本系统完全不用担心这个问题,后端源码注释覆盖率超过90%
,每一个方法,每一步都有详细的解释和说明,并且推出了手摸手教学文档(博客园),目的就是让使用者能够轻易上手,就算不是自己的代码,根据注释和文档也能轻易看懂和二次开发,不用每天在群里问一些非常基础的问题,节约了大量的开发时间。 - - ## 分支说明 -- master -正式稳定版本,具体版本升级内容看更新标签 +- js + js 版本,具体版本升级内容看更新标签 -- dev -开发的分支(代码可能随时会推,不保证运行和使用) +- master + 正式稳定版本,具体版本升级内容看更新标签 + +- dev + 开发的分支(代码可能随时会推,不保证运行和使用) - stringid -字符串类型主键分支,系统主键用string类型的使用此分支 + 字符串类型主键分支,系统主键用 string 类型的使用此分支 -## 🎈相关连接🎈 +## 🎈 相关连接 🎈 更新日志:[点击查看](https://gitee.com/zxzyjs/SimpleAdmin/commits/master) @@ -119,16 +135,17 @@ MQTT客户端使用的是我基于[NewLife.MQTT](https://github.com/NewLifeX/New 常见问题合集:[https://www.cnblogs.com/huguodong/p/17021241.html](https://www.cnblogs.com/huguodong/p/17021241.html) -## 🔖友情链接🔖 +## 🔖 友情链接 🔖 + - 👉 Furion:[https://dotnetchina.gitee.io/furion](https://dotnetchina.gitee.io/furion) -- 👉 SqlSugar:[https://www.donet5.com/Doc/1/1180](https://www.donet5.com/Doc/1/1180) -- 👉 NewLife:[https://www.newlifex.com/](https://www.newlifex.com/) -- 👉 IdGenerator:[https://github.com/yitter/idgenerator](https://github.com/yitter/idgenerator) -- 👉 Masuit.Tools:[https://gitee.com/masuit/Masuit.Tools](https://gitee.com/masuit/Masuit.Tools) -- 👉 Emqx:[https://www.emqx.com/zh](https://www.emqx.com/zh) -- 👉 MagicodesIE: [https://github.com/dotnetcore/Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE) - -## 👏鸣谢👏 +- 👉 SqlSugar:[https://www.donet5.com/Doc/1/1180](https://www.donet5.com/Doc/1/1180) +- 👉 NewLife:[https://www.newlifex.com/](https://www.newlifex.com/) +- 👉 IdGenerator:[https://github.com/yitter/idgenerator](https://github.com/yitter/idgenerator) +- 👉 Masuit.Tools:[https://gitee.com/masuit/Masuit.Tools](https://gitee.com/masuit/Masuit.Tools) +- 👉 Emqx:[https://www.emqx.com/zh](https://www.emqx.com/zh) +- 👉 MagicodesIE: [https://github.com/dotnetcore/Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE) + +## 👏 鸣谢 👏 - 感谢 JetBrains 提供的免费开源 License: @@ -136,13 +153,15 @@ MQTT客户端使用的是我基于[NewLife.MQTT](https://github.com/NewLifeX/New

-## 🤌赞助🤌 +## 🤌 赞助 🤌 + ``` 如果对您有帮助,请点击右上角⭐Star关注或扫码捐赠,感谢支持开源! ``` + -## 💾版权声明💾 +## 💾 版权声明 💾 - 后端源码完全免费开源商用。 - 前端源码因版权问题不能开源,后续准备替换掉之后再开源。 diff --git a/api/SimpleAdmin/SimpleAdmin.Web.Entry/Program.cs b/api/SimpleAdmin/SimpleAdmin.Web.Entry/Program.cs index 0d14181..4b5c387 100644 --- a/api/SimpleAdmin/SimpleAdmin.Web.Entry/Program.cs +++ b/api/SimpleAdmin/SimpleAdmin.Web.Entry/Program.cs @@ -1,11 +1,11 @@ using System.Drawing; -Console.WriteLine(@"Դַ: https://gitee.com/zxzyjs/SimpleAdmin"); -Console.WriteLine(@"ʾַ: http://153.101.199.83:12802/login"); +Console.WriteLine(@"源码地址: https://gitee.com/zxzyjs/SimpleAdmin"); +Console.WriteLine(@"演示地址: http://153.101.199.83:12801/login"); Console.WriteLine(@"QQ:531035580"); -Console.WriteLine("ûлڣֻм򵥡ȶЧ"); +Console.WriteLine("没有花里胡哨,只有简单、稳定、灵活、高效"); Colorful.Console.WriteAsciiAlternating("SimpleAdmin", new Colorful.FrequencyBasedColorAlternator(3, Color.Yellow, Color.GreenYellow)); Serve.Run(RunOptions.Default.ConfigureBuilder(builder => { builder.WebHost.UseUrls(builder.Configuration["AppSettings:Urls"]); -})); \ No newline at end of file +})); -- Gitee