Compare commits

...

566 Commits

Author SHA1 Message Date
Argo-Lenovo e4b2f70ae3 feat: 增加任务日志滚动条样式 2022-01-29 18:39:54 +08:00
Argo-Lenovo 41b0dce852 feat: 任务日志增加最大数功能 2022-01-29 16:03:57 +08:00
Argo-Lenovo 188470bc1d feat: 增加任务日志功能 2022-01-29 15:26:44 +08:00
Argo-Lenovo 92e3aa4c35 feat: 实现缓存清楚逻辑 2022-01-29 14:34:00 +08:00
Argo-Tianyi 5e136d1815 fix: 修复 Client 工程编译报错问题 2022-01-28 12:24:49 +08:00
Argo-Tianyi 7506665052 feat: 登录首页增加切换功能 2022-01-27 16:00:21 +08:00
Argo-Tianyi fc2f0e84b2 feat: 增加 AdminLoginFooter 组件用于切换登录页 2022-01-27 15:43:29 +08:00
Argo-Tianyi 6ba2ef3a96 feat: 增加码云高仿登录界面 2022-01-27 15:14:09 +08:00
Argo-Tianyi 2674c6278d feat: 增加登录首页切换功能 2022-01-27 13:42:48 +08:00
Argo-Tianyi 6e881fbff4 feat: 登录首页配置增加顺序 2022-01-27 13:31:59 +08:00
Argo-Tianyi 135f0615f5 refactor: 改造登录首页组件 2022-01-27 13:31:37 +08:00
Argo-Tianyi a53c0cd791 feat: 增加更新 DisplayName 逻辑 2022-01-27 12:53:36 +08:00
Argo-Tianyi 71d5ff0a24 chore: 更新依赖包 2022-01-27 12:53:18 +08:00
Argo-Tianyi acf4ed75dc feat: 用户服务增加缓存 2022-01-27 11:15:59 +08:00
Argo-Tianyi b6ddd637db feat: 用户服务增加缓存 2022-01-27 11:02:03 +08:00
Argo-Tianyi 383bec6e20 feat: 应用程序服务增加缓存 2022-01-27 10:51:59 +08:00
Argo-Tianyi 3f0839b12c feat: 角色服务增加缓存 2022-01-27 10:49:52 +08:00
Argo-Tianyi 3c99d1e76a feat: NavigationService 增加缓存 2022-01-27 10:45:34 +08:00
Argo-Tianyi 195802e87f refactor: 格式化代码 2022-01-27 01:45:38 +08:00
Argo-Tianyi 063390e255 refactor: 组服务增加缓存 2022-01-27 01:45:19 +08:00
Argo-Tianyi a987e8eda3 refactor: 角色服务增加缓存 2022-01-27 01:44:58 +08:00
Argo-Tianyi 919f543cbd chore: 更改命名空间 2022-01-27 01:15:32 +08:00
Argo-Tianyi 617c72771d revert: 移除 swagger 功能 2022-01-27 01:15:12 +08:00
Argo-Tianyi 82cc6befaa fix: 返回前台防止多次跳转 2022-01-27 00:18:11 +08:00
Argo-Tianyi 4035c96c83 feat: 更新 ICacheManager 服务 2022-01-26 20:47:07 +08:00
Argo-Tianyi 7465b7f890 fix: 修复首页一直跳转问题 2022-01-26 20:46:35 +08:00
Argo-Tianyi 5c7b29ee04 refactor: 格式化代码 2022-01-26 19:46:11 +08:00
Argo-Tianyi a946424275 chore: 更新命名空间 2022-01-26 19:37:07 +08:00
Argo-Tianyi 8de82f119f chore: 增加 LGPL 协议声明 2022-01-26 17:57:38 +08:00
zhangpeihang 979361b20c fix: 修改sql 2022-01-26 16:58:06 +08:00
Argo-Tianyi 540694a4e1 refactor: 获得应用程序首页逻辑增加 Define 条件 2022-01-26 16:39:12 +08:00
Argo-Tianyi 8b8d8d5111 refactor: 精简客户端数据业务层代码 2022-01-26 16:31:01 +08:00
zhangpeihang 58c4d6d5b2 feat: 配置实体 2022-01-26 15:40:33 +08:00
zhangpeihang 889f03189d refactor: 重构服务 2022-01-26 15:40:21 +08:00
zhangpeihang 7eb06c1df6 feat: 开启 EFCore 服务 2022-01-26 15:40:04 +08:00
zhangpeihang a549d87acd feat: 添加 RoleApp 中间表 2022-01-26 15:39:44 +08:00
zhangpeihang 88268b450b feat: 添加 Trace 服务 2022-01-26 15:39:09 +08:00
zhangpeihang 51ff64fb2a feat: 添加 Exception 服务 2022-01-26 15:38:35 +08:00
zhangpeihang 25197d9cb3 refactor: 修改 Dict 服务 2022-01-26 15:38:07 +08:00
zhangpeihang 3280d00472 feat: 添加 App 服务 2022-01-26 15:37:47 +08:00
zhangpeihang 5dc6bc066a chore: web 工程依赖 EFCore 2022-01-26 15:37:21 +08:00
zhangpeihang d09be53f2b refactor: 重构中间表 2022-01-26 15:36:55 +08:00
zhangpeihang b25d6df9a7 feat: 增加缓存服务 2022-01-26 15:36:35 +08:00
zhangpeihang 0df75c019f chore: 升级 bb 组件 2022-01-26 13:48:46 +08:00
zhangpeihang 2fb1e406d6 chore: 添加缓存依赖 2022-01-26 13:39:53 +08:00
zhangpeihang 1de338c6b7 refactor: 重构 EFCore 2022-01-26 13:39:39 +08:00
Argo-Tianyi 8c102946d7 feat: 增加获取后台地址方法 2022-01-25 00:40:15 +08:00
Argo-Tianyi 331f034d9b refactor: 移动 Context 初始化到 MainLayout 组件中 2022-01-25 00:39:47 +08:00
Argo-Tianyi 10e5b1d26c feat: 后台应用通过当前请求拼接前台地址 2022-01-25 00:08:29 +08:00
Argo-Tianyi 1a896cf994 refactor: 精简代码 2022-01-25 17:03:04 +08:00
Argo-Tianyi 2107b70d94 refactor: 根据最新依赖包更新 OnUpdate 回调 2022-01-23 21:20:08 +08:00
Argo-Tianyi f4490c3395 feat: 增加地理位置定位功能 2022-01-23 20:50:59 +08:00
Argo-Tianyi 50bc67c5d8 feat: 更新 IDict 接口 2022-01-24 01:35:43 +08:00
Argo-Tianyi 97836b447f chore: 更新依赖包 2022-01-24 00:07:28 +08:00
Argo-Tianyi 9d2c3dfdac feat: 网站设置触发 MainLayout 更新 UI 2022-01-24 02:00:26 +08:00
Argo-Tianyi 1ff9891331 fix: 修复前台用户头像后台链接 2022-01-24 01:13:29 +08:00
Argo-Tianyi 25fae681ae refactor: 移除字典表中菜单配置项 2022-01-24 01:06:43 +08:00
Argo-Tianyi e14b053c72 chore: 格式化文档更新配置文件 2022-01-24 00:48:34 +08:00
Argo-Tianyi 24fe9e7d35 feat: 增加系统上下文服务 2022-01-24 00:48:09 +08:00
Argo-Tianyi ebf60eabf7 feat: 更新获取菜单脚本 2022-01-24 00:47:46 +08:00
Argo-Tianyi b4aea5974c chore: 更新依赖 2022-01-24 00:47:19 +08:00
Argo-Tianyi 65756b458c db: 更新数据库 2022-01-24 00:46:37 +08:00
Argo-Tianyi 8536fadf2c feat: 移除转换器使用 PetaPoco 扩展程序集内置转化器 2022-01-24 00:46:22 +08:00
Argo-Tianyi f0a3c85f43 chore: 更新依赖包 2022-01-23 13:15:02 +08:00
Argo-Tianyi 3898d0c7d5 refactor: 更新路由大小写问题 2022-01-23 12:53:38 +08:00
Argo-Tianyi 434e7ab82b feat: 根据最新组件更改 SortList 为 SortString 2022-01-23 12:49:51 +08:00
Argo-Tianyi 0d609c41b0 feat: 登录日志增加默认 LoginTime 倒序排序功能 2022-01-21 12:30:16 +08:00
Argo-Tianyi d7b7bef4c2 chore: 移除 Tasks 组件 DEBUG 模式下日志输出问题 2022-01-21 12:25:35 +08:00
Argo-Tianyi 49ca3503eb fix: 修复菜单维护中图标垂直不居中问题 2022-01-21 12:25:14 +08:00
Argo-Tianyi 41e94ca677 feat: 增加 Debug 模式下禁用 Caching 设置 2022-01-21 12:24:52 +08:00
Argo-Tianyi 7411047ea3 refactor: 更新网站设置配置项顺序 2022-01-21 12:08:26 +08:00
Argo-Tianyi 71956f9a36 doc: 更新客户端配置项顺序 2022-01-21 12:08:09 +08:00
Argo-Tianyi 43fe7cf209 refactor: 健康检查数据显示重置 2022-01-21 12:00:33 +08:00
Argo-Tianyi d6d5ec0ee8 chore: 更新依赖包 2022-01-21 08:56:49 +08:00
Argo-Tianyi 32bad4adcb fix: 修复新建前台应用报错问题 2022-01-20 20:28:03 +08:00
Argo-Tianyi 1bf2e4141c feat: 更新网站设置前台应用配置功能 2022-01-20 20:25:15 +08:00
Argo-Tianyi e6d5cacefa feat: 增加 ClientApp 实体类 2022-01-20 20:24:48 +08:00
Argo-Tianyi f68ec04269 feat: 更新地理位置定位器设置 2022-01-20 15:26:57 +08:00
Argo-Tianyi 18ace08ea9 feat: 菜单行内分配按钮增加权限 2022-01-20 14:27:51 +08:00
Argo-Tianyi 658d616cfb feat: 健康检查增加检查中状态 2022-01-20 13:50:26 +08:00
Argo-Tianyi a602539ec5 feat: 重构代码 2022-01-20 13:22:25 +08:00
Argo-Tianyi 08b02e9579 feat: 重构 Block 授权逻辑 2022-01-20 13:17:46 +08:00
Argo-Tianyi 3e5de3e936 feat: 网站设置增加时否开启默认程序 2022-01-20 13:09:54 +08:00
Argo-Tianyi f0e3e60514 feat: 用户维护使用 AdminTable 组件 2022-01-20 13:09:19 +08:00
Argo 4182d86fd4 !101 feat(#I4RK0W): 合并分支
* Merge branch 'dev' into dev-frontApp
* fix: 完成保存默认应用功能
* refactor: 修改前台字典表方法名称
* refactor: 修改 Client 设置方法名称
* refactor: 调整前台设置ui
* refactor: 重构 Client 弹窗
* refactor: 重构添加 Client 功能
* feat: 添加 Client dialog 组件
* feat: 添加 Client 列表组件
* feat: 前台应用相关方法
2022-01-20 03:36:29 +00:00
Argo-Tianyi 36aa19dd6e feat: 增加登录帮助类用于获取默认导航页面 2022-01-20 10:52:11 +08:00
Argo-Tianyi f18229d58c refactor: 重构 GetHomeUrlByAppId 接口 2022-01-20 10:51:47 +08:00
zhangpeihang d77d4786aa feat: 用户页面添加按钮权限 2022-01-20 00:20:03 +08:00
zhangpeihang 503c1a4a2b feat: 生成 xml 文档 2022-01-20 00:16:49 +08:00
zhangpeihang 554614aa4a feat: 添加 swagger 配置 2022-01-20 00:16:48 +08:00
Argo-Tianyi 84e4c68413 feat: 增加地理位置定位功能 2022-01-19 15:41:43 +08:00
zhangpeihang 3a0525f11f feat: 基础 table 是否显示添加删除编辑按钮 2022-01-19 15:08:16 +08:00
zhangpeihang cacea459c1 feat: 添加 Card 是否显示 2022-01-19 15:07:39 +08:00
zhangpeihang 267d0e68bd feat: 添加代码块是否授权方法 2022-01-19 15:06:57 +08:00
zhangpeihang 05f0d1d344 db: 前台应用改为 appid 做为字典表分类 2022-01-19 10:39:15 +08:00
zhangpeihang 6840c1d851 refactor: 更新删除前台应用方法 2022-01-19 10:33:30 +08:00
zhangpeihang 35ed1f654f feat: 前台应用相关方法 2022-01-19 10:31:37 +08:00
Argo-Tianyi 6657c29c79 fix: 更新 Converter 使枚举转变成 Int 2022-01-18 20:02:00 +08:00
Argo-Tianyi f12b2d254a feat: 更新 Client 工程逻辑 2022-01-18 20:00:45 +08:00
Argo-Tianyi 18cbde111b feat: 访问日志路径使用相对路径 2022-01-17 21:02:14 +08:00
Argo-Tianyi e484961576 chore: 更新依赖 2022-01-17 21:01:51 +08:00
Argo-Tianyi df6098f1dc feat: 增加访问日志查询界面功能 2022-01-17 19:08:40 +08:00
Argo-Tianyi 7fd4a83b52 feat: 增加访问日志功能 2022-01-17 12:34:20 +08:00
Argo-Tianyi 2892a2780f feat: 增加访问日志 2022-01-17 12:33:46 +08:00
Argo-Tianyi 2a7c42071a refactor: 增加路由 2022-01-16 17:16:20 +08:00
Argo-Tianyi b04d45b624 refactor: 增加操作日志页面 2022-01-16 17:14:33 +08:00
Argo-Tianyi 09146b9acf feat: 增加 SQL 日志页面 2022-01-16 17:13:06 +08:00
Argo-Tianyi f5bc782097 feat: 增加访问日志页面 2022-01-16 17:11:27 +08:00
Argo-Tianyi 23e43ff248 refactor: 更新登录日志结果改用 Tag 组件 2022-01-16 12:21:10 +08:00
Argo-Tianyi 95bec59886 feat: 重构登录日志 2022-01-15 13:18:07 +08:00
Argo-Tianyi 4d98083434 feat: 增加客户端信息中间件 2022-01-15 13:07:55 +08:00
Argo-Tianyi 9f3777209c feat: 更新 ILogin 接口 2022-01-15 13:06:59 +08:00
Argo-Tianyi b8078fd505 feat: 移除对 Longbow.Web 依赖 2022-01-15 11:51:22 +08:00
Argo-Tianyi d0860e57a5 feat: 增加 IPAddress 扩展 2022-01-15 11:51:02 +08:00
Argo-Tianyi 22f5907bc4 fix: 修复编译错误 2022-01-15 00:35:32 +08:00
Argo-Tianyi c19cd5ca85 refactor: 尝试使用 Token 解决依赖问题改造 CacheManager 接口 2022-01-15 00:17:05 +08:00
zhangpeihang 943c620c55 feat: 添加登录日志自定义搜索 2022-01-15 00:07:26 +08:00
Argo-Tianyi b6cd8ddcdd refactor: 健康检查移除缓存 2022-01-14 23:36:19 +08:00
zhangpeihang d60bdd3bc8 feat: 添加登陆页面 2022-01-14 23:38:20 +08:00
zhangpeihang b391d109cd feat: 记录登录日志 2022-01-14 23:38:20 +08:00
zhangpeihang 5aab0908c4 feat: 添加日志接口 2022-01-14 23:38:19 +08:00
zhangpeihang aa11b1fa96 chore: 添加依赖 2022-01-14 23:38:18 +08:00
zhangpeihang 53a8eb614f refactor: 修改文件名称 2022-01-14 23:38:17 +08:00
Argo-Tianyi 0e64331bc3 refactor: 重构代码删除 CacheKeyChangeToken 2022-01-14 23:30:51 +08:00
Argo-Tianyi 8ec06d9199 refactor: 更改 IDict 方法为 ExistsAppId 2022-01-14 23:30:18 +08:00
zhangpeihang e7b8a9ef51 feat: 添加前台应用功能,未完成 2022-01-14 22:37:34 +08:00
Argo-Tianyi 7e66b50b79 db: 更新数据库 2022-01-14 21:35:20 +08:00
Argo-Tianyi 61ac109d2e feat: 准备实现 IChangeToken 类 2022-01-14 21:34:52 +08:00
Argo-Tianyi eb67bbf26e refacot: 精简代码 2022-01-14 21:34:31 +08:00
Argo-Tianyi 66f803c73b refactor: 更新删除头像提示 2022-01-14 18:19:10 +08:00
Argo-Tianyi a4599b835e refactor: 重构个人中心头像上传 2022-01-14 18:12:09 +08:00
zhangpeihang fb0d42b02e feat: 添加日志缓存功能 2022-01-14 13:36:45 +08:00
zhangpeihang 5bdb883947 feat: 增加地理位置设置 2022-01-14 11:41:55 +08:00
zhangpeihang cdeee4b3b2 feat: 增加自动锁屏设置 2022-01-14 10:53:15 +08:00
zhangpeihang 2a52d139a6 chore: 升级依赖 2022-01-14 10:52:52 +08:00
zhangpeihang 74cf29ad13 fix: 修复类型转换错误 2022-01-14 10:39:38 +08:00
zhangpeihang 86640d3b64 feat: 添加自动锁屏功能 2022-01-14 10:38:11 +08:00
zhangpeihang fcaa0244c2 feat: 添加登陆方式设置 2022-01-14 10:17:56 +08:00
zhangpeihang 7b2b7490fa feat: 增加网站功能设置 2022-01-14 09:49:09 +08:00
Argo-Tianyi 16ed058850 feat: 个人中心头像上传功能 2022-01-13 15:32:48 +08:00
Argo-Tianyi 926cd75cf6 feat: 完成个人中心网站样式功能 2022-01-13 13:46:28 +08:00
Argo-Tianyi 7c2935bb1b feat: 个人中心完成保存显示名称与更改密码功能 2022-01-13 13:37:43 +08:00
Argo-Tianyi 8b280cef15 refactor: 密码框改用 BootstrapPassword 组件 2022-01-13 12:44:48 +08:00
Argo-Tianyi d683f392f2 feat: 使用新的缓存组件 2022-01-13 10:56:24 +08:00
Argo-Tianyi 4695b8e17e feat: 更新缓存工程逻辑 2022-01-13 10:55:57 +08:00
Argo-Tianyi 01c2857be6 chore: Sugar 更新依赖包 2022-01-13 10:55:40 +08:00
Argo-Tianyi 5bd40bd487 fix: 更新 FreeSql 接口实现修复报错问题 2022-01-13 10:55:17 +08:00
Argo-Tianyi 0df8267cb2 feat: 增加缓存层 2022-01-12 23:25:08 +08:00
Argo-Tianyi 1317b2828f chore: 增加数据服务实现层 2022-01-12 22:41:44 +08:00
Argo-Tianyi 663580b8ae refactor: 移除基类 2022-01-12 22:41:15 +08:00
Argo-Tianyi 92f615c730 feat: 完成个人中心默认应用设置 2022-01-12 13:18:34 +08:00
Argo-Tianyi e79b2d3007 doc: 更新提示信息 2022-01-12 12:15:15 +08:00
Argo-Tianyi e148aa5c57 chore: 更新配置 2022-01-12 12:14:21 +08:00
Argo-Tianyi 57537d50d3 feat: 增加默认应用设置功能 2022-01-12 12:13:05 +08:00
Argo e25fecb164 !99 feat: 增加默认应用功能
* chore: 更新数据服务为 PetaPoco
* feat: 增加默认应用配置 api
* feat: 重命名服务
2022-01-12 03:22:42 +00:00
Argo-Tianyi 5096910ba3 refactor: 代码重构 2022-01-12 12:56:15 +08:00
Argo-Tianyi eb3ce91948 fix: 修复保存方法错误 2022-01-12 12:56:02 +08:00
Argo-Tianyi cf164c57c7 feat: 增加 SqlSugar ORM 示例 2022-01-12 12:55:43 +08:00
Argo-Tianyi 81ce2b70e0 fix: 修复脚本错误 2022-01-11 12:30:46 +08:00
Argo-Tianyi bb6aa0723e doc: 格式化代码 2022-01-11 10:09:36 +08:00
Argo-Tianyi 76fe5d7fcd feat: 更新登录时获取默认应用逻辑 2022-01-11 10:05:14 +08:00
Argo-Lenovo f712b0ab0e feat: 显示缓存 Clear 方法 2022-01-10 19:09:42 +08:00
Argo-Lenovo b281d05c5d chore: 重命名注入服务扩展方法 2022-01-10 19:09:22 +08:00
Argo-Tianyi bbf51ea3f4 feat: 增加异步缓存方法 2022-01-10 15:28:40 +08:00
Argo-Tianyi 70e42a8268 chore: 更新依赖包 2022-01-10 14:44:56 +08:00
Argo-Tianyi 9720ae85ef feat: 增加 ICacheManager 缓存管理类接口 2022-01-10 14:44:38 +08:00
Argo-Tianyi 78078e6d6f refactor: 重构保存类方法统一使用 SaveDict 方法 2022-01-10 13:14:49 +08:00
Argo-Tianyi 614d3d6b43 feat: 重构扩展类命名空间 2022-01-10 13:13:24 +08:00
Argo-Tianyi 19a2123cee feat: 增加返回首页菜单逻辑 2022-01-10 02:46:27 +08:00
Argo-Tianyi 11984e20e7 feat: 客户端登录后直接返回本应用 2022-01-10 01:54:15 +08:00
Argo-Tianyi c00895a848 db: 更改系统首页为系统配置 2022-01-10 01:23:32 +08:00
Argo-Tianyi fae54caea1 feat: 健康检查移除多选与显示 Empty 空数据 2022-01-09 20:45:46 +08:00
Argo-Tianyi b19a9cb955 chore: 更新依赖包到 6.2.6 2022-01-09 20:45:17 +08:00
Argo-Tianyi 78ab4ad0d0 refactor: 移除 UseInjectDataService 参数 2022-01-09 12:05:40 +08:00
Argo-Tianyi 4436a74b60 chore: 更新依赖包 6.2.4 2022-01-09 12:05:12 +08:00
Nine 5ee01d88be !98 feat(#I4PYQ2): add freesql support
* feat: 增加 PageIf 扩展精简代码
* feat: 支持高级搜索与自定义搜索
* feat: 完善菜单搜索与过滤功能
* chore: 增加 xml 注释
* feat: 菜单维护界面开启二级菜单
* chore: 更新依赖包
* feat: 健康检查单独开启 ShowLoading
* refactor: 格式化代码
* Merge branch 'master' into dev-blazor-freesql
* refactor: 更新代码注释
* refactor: 修复编译错误
* feat: 改用 petapoco 服务
* fix: 修复合并代码错误
* feat: 增加异常日志字段排序
* Merge remote-tracking branch 'origin/master' into dev-blazor-freesql
* fix: 修复插入命令并未执行
* feat: 添加 Exception 服务
* feat: 添加 Exception 服务
* feat: 添加 App 服务
* feat: 添加 Navigation 服务
* feat: 添加 Group 和 Role 服务
* feat: 添加中间表实体
* feat: 添加用户功能
* feat: 完善用户服务
* feat: 完善字典服务
* feat: 增加 GetUserByUserName 实现
* chore: 更新配置
* feat: 增加实体类映射
* feat: 移除 LongExtensions 扩展方法
* feat: 完善数据服务方法
* chore: 格式化代码
* refactor: 优化注册服务接口
* Merge remote-tracking branch 'origin/master' into dev-blazor-freesql
* feat: 初始化 FreeSql
2022-01-08 18:05:59 +00:00
Argo-Tianyi 57f78cc7f5 refactor: 更改扩展类为私有类 2022-01-09 00:55:44 +08:00
Argo-Tianyi d46602b4f7 chore: 更新依赖包 2022-01-09 00:40:42 +08:00
Argo-Tianyi 87438838b5 feat: 关闭健康检查工具栏 2022-01-07 13:05:43 +08:00
Argo-Tianyi 97eeba961a feat: 重构 AdminTable 内置编辑模板 2022-01-07 12:56:17 +08:00
Argo-Tianyi 88fbd32ee8 fix: 修复枚举类型入库操作转为 int 2022-01-07 12:29:08 +08:00
Argo-Tianyi d381ef1e51 fix: 修复 Client 工程编译错误 2022-01-07 12:28:44 +08:00
Argo-Lenovo b32e28ca2c feat: 移除 LongExtensions 扩展方法 2022-01-07 02:15:34 +08:00
Argo-Lenovo 15007cd2fc refactor: 优化 PetaPoco 数据服务接口 2022-01-07 01:14:06 +08:00
Argo-Tianyi 913f4db051 feat: 增加 Header 图标显示功能 2022-01-06 09:31:01 +08:00
Argo-Tianyi 06b3368a9f feat: 增加 Where 关键字 2022-01-06 09:00:15 +08:00
Argo-Tianyi bdae9766dc feat: 更新手机用户首次登录逻辑 2022-01-06 08:54:21 +08:00
Argo-Tianyi 0d0443fddb feat: 重构 AdminLogin 组件 2022-01-06 08:53:59 +08:00
Argo-Tianyi e1a6e7379d feat: 拆分登录组件 2022-01-06 06:45:10 +08:00
Argo-Tianyi 18bf30fe83 feat: 高级搜索条件使用 Equal 2022-01-06 04:10:38 +08:00
Argo-Tianyi c28ef26e8e feat: 菜单维护增加自定义高级搜索功能 2022-01-06 03:54:55 +08:00
Argo-Tianyi 808dc444b1 feat: 用户维护增加给定默认授权功能 2022-01-06 02:45:05 +08:00
Argo-Tianyi 4cb59e5d03 feat: 新建用户时增加判断 2022-01-06 01:54:30 +08:00
Argo-Tianyi f9e4efd84e feat: 微调登录界面 UI 采用客户端 js 验证后期移动到组件内 2022-01-06 01:06:47 +08:00
Argo-Tianyi 4e3f7cfab1 feat: 增加用户名密码错误提示功能 2022-01-05 23:05:05 +08:00
Argo-Tianyi f8870109c3 feat: 增加用户登录名称验证 2022-01-05 08:26:40 +08:00
Argo-Tianyi e0fd45f15a feat: 增加高级搜索支持 2022-01-05 05:50:48 +08:00
Argo-Tianyi f5f0a7b735 feat: 程序异常增加默认排序规则 2022-01-05 04:10:56 +08:00
Argo-Tianyi a7fe25c67d feat: 菜单用户增加默认排序规则 2022-01-05 04:10:39 +08:00
Argo-Tianyi 0323b5ca3b feat: DEBUG 模式下自动填充登录账号与密码 2022-01-05 03:47:06 +08:00
Argo-Tianyi ecff092ea4 feat: 更新依赖包支持多列排序 2022-01-05 03:46:41 +08:00
Argo-Tianyi 09de55a641 refactor: 格式化代码消除警告信息 2022-01-05 03:46:04 +08:00
Argo-Tianyi 7ce614554f chore: 更新依赖包 2022-01-04 08:33:40 +08:00
Argo-Tianyi 0e81c0e257 feat: 健康检查增加更新按钮 2022-01-04 08:21:09 +08:00
Argo-Tianyi 3ebfe8cd56 feat: 完善 Task 任务管理功能 2022-01-04 08:05:33 +08:00
Argo-Tianyi 23dd2d05df feat: 更新 TaskEditor 组件 2022-01-04 08:04:55 +08:00
Argo-Tianyi 794d90731a doc: 格式化文档 2022-01-04 04:04:20 +08:00
Argo-Tianyi 8e4066e6e2 feat: 健康检查结束后更新总时长与状态 2022-01-04 02:16:14 +08:00
Argo-Tianyi 1ddef32a83 feat: 增加 LogoutLink 组件 2022-01-04 01:58:42 +08:00
Argo-Tianyi cbb75e58d8 doc: 增加关于页面 2022-01-04 01:58:23 +08:00
Argo-Lenovo d3f73e62b1 feat: 增加折行 2022-01-03 12:29:45 +08:00
Argo-Lenovo 56733878da feat: 格式化文档 2022-01-03 12:27:22 +08:00
Argo-Lenovo b062a01afb feat: 更新数据为空时逻辑 2022-01-03 11:41:49 +08:00
Argo-Lenovo b51782e796 feat: 微调程序异常界面移除固定表头设置 2022-01-03 10:59:10 +08:00
Argo-Lenovo b18bc89175 feat: 任务管理设置为不固定表头 2022-01-03 10:54:31 +08:00
Argo-Tianyi 4b707e9bc4 chore: 更新 AdminService 到 Core 工程 Client 复用 2022-01-03 10:17:25 +08:00
Argo-Lenovo f87efc7c20 doc: 更改类名 2022-01-03 02:39:46 +08:00
Argo-Lenovo 9612e48bbb feat: 完善健康检查界面 2022-01-03 02:31:07 +08:00
Argo-Lenovo 383eaaf14e feat: 增加 HealthCheckDetails 组件 2022-01-03 02:30:45 +08:00
Argo-Tianyi c633dd4a81 feat: 增加健康检查页面 2022-01-03 00:15:56 +08:00
Argo-Tianyi 490c8f87eb refactor: 重构 GiteeClient 2022-01-03 00:15:30 +08:00
Argo-Tianyi 0bf9f2a4b5 feat: 增加健康检查 html 版本 2022-01-03 00:15:00 +08:00
Argo-Tianyi 441cdfb336 feat: 增加健康检查 2022-01-02 21:46:31 +08:00
Argo-Tianyi 86522a81a4 feat: 程序异常增加高级搜索功能 2022-01-02 19:29:14 +08:00
Argo-Tianyi 6bd7303d82 feat: 增加 AdminTable 参数 2022-01-02 17:09:52 +08:00
Argo-Tianyi ebbaba0f59 feat: 增加程序异常分页逻辑 2022-01-02 17:09:33 +08:00
Argo-Tianyi 93630f99b4 feat: 增加 Long 转型扩展 2022-01-02 17:08:58 +08:00
Argo-Tianyi c83725bfa1 refactor: 增加自定义异常处理逻辑 2022-01-02 16:13:36 +08:00
Argo-Tianyi 106d85acf4 chore: 更新解决方案配置文件 2022-01-02 13:49:17 +08:00
Argo-Tianyi 9e550a896c refactor: 使用 Error 作为 Exception 表实体类 2022-01-02 13:48:59 +08:00
Argo-Lenovo eab30a9a6d feat: 增加异常数据库日志功能 2022-01-02 13:33:39 +08:00
Argo-Lenovo 3c658dba46 refactor: 移动 AdminService 到 Web 工程 2022-01-02 13:20:20 +08:00
Argo-Lenovo 1a87ac25f5 feat: 增加数据库日志扩展 2022-01-02 13:05:25 +08:00
Argo-Lenovo 76a6628865 feat: Client 增加登出弹框功能 2022-01-02 12:06:26 +08:00
Argo-Lenovo 580055c688 refactor: 数据库异常更改日志等级为 Error 2022-01-02 11:36:50 +08:00
Argo-Lenovo 5d44d2c5ca chore: 移除对 Extensions 工程的依赖 2022-01-02 11:25:24 +08:00
Argo-Lenovo fc1a0f113f chore: 移除对 Extensions 工程的依赖 2022-01-02 11:25:00 +08:00
Argo-Lenovo 1e0203472e refactor: 移除 Extensions 工程 2022-01-02 11:24:31 +08:00
Argo-Tianyi e4cb1b4a9d refactor: 更新缓存逻辑 2022-01-01 20:26:27 +08:00
Argo-Tianyi b417eb04c8 refactor: 格式化文档 2022-01-01 20:26:08 +08:00
Argo-Tianyi e150e33bfe refactor: 移除 TabItemTextDictionary 参数 2022-01-01 20:25:56 +08:00
Argo-Lenovo d1d1811fd3 feat: 增加前台登录后自动跳转功能 2022-01-01 17:06:43 +08:00
Argo-Lenovo 17ae71c72e db: 更新系统菜单 2022-01-01 15:54:00 +08:00
Argo-Lenovo 57225c0937 feat: 更新系统演示保存结果弹窗功能 2022-01-01 15:44:08 +08:00
Argo-Lenovo 1086b7d6a1 feat: 网站设置功能更新 2022-01-01 15:40:13 +08:00
Argo-Lenovo 0e0f016cd9 feat: 完成网站标题页脚设置功能 2022-01-01 14:41:29 +08:00
Argo-Lenovo b72899b658 feat: 完成短信登录功能 2022-01-01 14:32:42 +08:00
Argo-Lenovo ee28d845f2 refactor: 移除 EFCore 的引用使用 PetaPoco 2022-01-01 14:05:44 +08:00
Argo-Tianyi bafa4f1aa4 chore: 更新项目启动配置 2022-01-01 12:19:14 +08:00
Argo-Tianyi ec02aeef82 chore: 更新依赖包 2022-01-01 11:00:07 +08:00
Argo-Tianyi 46641a8696 feat: 修复 Client 编译无法通过问题 2022-01-01 10:03:39 +08:00
Argo-Tianyi 310795568c feat: 增加 Extensions 工程 2022-01-01 10:03:22 +08:00
Argo-Tianyi 176ac6d4b1 feat: 增加 Cookie 缓存时长 2021-12-31 20:16:39 +08:00
Argo-Tianyi e1fcf586e5 feat: 更新字典服务增加 Cookie 缓存时长设置 2021-12-31 19:23:16 +08:00
Argo-Tianyi bd58a29fca feat: Card 增加阴影效果 2021-12-31 19:21:31 +08:00
Nine bc6ec6be12 !95 feat(#I4OWBZ): add EFCore support
* refactor: 修改方法签名
* refactor: GetAll 改为公开接口
* refactor: 移除枚举转换
* fix: 消除警告
* Merge remote-tracking branch 'origin/master' into dev-blazor-ef
* feat: 配置实体
* fix: 修复菜单获取不正确
* feat: 开启EF数据服务
* feat: 修复菜单导航
* chore: 格式化文档
* chore: 更新网站端口
* feat: 增加数据库日志任务
* feat: 增加任务管理
* feat: 增加保存健康检查方法
* feat: 完善EF数据服务
* feat: 开启EF数据服务
* chore: 升级EF包
* feat: 配置EF表关系
* feat: 添加 EFCore 服务
2021-12-31 06:41:51 +00:00
Argo-Tianyi 541a2714b7 chore: 更新包与项目依赖 2021-12-31 13:27:11 +08:00
Argo-Tianyi 3c7ce9cf24 feat: 增加 GetAll 接口实现自定义排序功能 2021-12-31 13:26:57 +08:00
Argo-Tianyi 2e11fce1fd feat: 更改数据库数据类型为整形 2021-12-30 19:55:35 +08:00
Argo-Tianyi ed8dcc9296 feat: 设置自动刷新 2021-12-30 19:55:12 +08:00
Argo-Tianyi bbe2631541 feat: 设置默认排序列 2021-12-30 13:48:35 +08:00
Argo-Tianyi 39aa8bfd1d doc: 格式化文档 2021-12-30 13:31:40 +08:00
Argo-Tianyi eea8838963 feat: 角色对菜单授权增加排序 2021-12-29 16:28:55 +08:00
Argo-Tianyi 7e7b9d0ec0 feat: 增加菜单默认排序规则 2021-12-29 15:31:11 +08:00
Argo-Tianyi 0a6317ec5c style: 增加 Card 阴影效果 2021-12-29 13:45:08 +08:00
Argo-Tianyi a5866b13b1 feat: 系统演示增加 Label 2021-12-29 13:44:50 +08:00
Argo-Tianyi 25af048f77 feat: 修复菜单导航 2021-12-29 12:25:37 +08:00
Argo-Tianyi c7b385cd67 chore: 格式化文档 2021-12-29 11:23:25 +08:00
Argo-Tianyi 08b194c33d chore: 更新网站端口 2021-12-29 11:23:03 +08:00
Argo-Tianyi 3ef333f6ec feat: 增加数据库日志任务 2021-12-29 11:22:36 +08:00
Argo-Tianyi 5a61625f6f feat: 增加任务管理 2021-12-29 11:21:56 +08:00
Argo-Tianyi edf691a506 feat: 增加保存健康检查方法 2021-12-29 11:21:19 +08:00
Argo-Tianyi 6703d510b2 feat: 增加任务管理界面 2021-12-26 13:35:07 +08:00
Argo-Tianyi 97503e4a81 feat: 增加任务界面 2021-12-26 13:07:07 +08:00
Argo-Tianyi 7768c9ea49 feat: 网站设置增加系统模式开关功能 2021-12-26 10:14:09 +08:00
Argo-Tianyi 915e2371b1 feat: 字典服务增加系统模式获取与保存方法 2021-12-26 10:13:40 +08:00
Argo-Tianyi 083bd15d91 feat: 增加网站设置 2021-12-25 20:44:34 +08:00
Argo-Tianyi d517d57163 refactor: 重构个人中心保存按钮显示名称 2021-12-25 20:44:13 +08:00
Argo-Tianyi ce74be1f6d feat: 增加获取登录页面方法 2021-12-25 20:43:34 +08:00
Argo-Tianyi ec83350830 feat: 菜单增加按应用排序 2021-12-25 18:58:31 +08:00
Argo-Tianyi 184b0e2a14 refactor: 微调操作列宽度 2021-12-25 18:56:08 +08:00
Argo-Tianyi 374392afb3 feat: 更新组件变量为 IsShow 2021-12-25 18:55:42 +08:00
Argo-Tianyi d716b340e6 feat: 移除 SubmitButton 组件 2021-12-25 18:54:58 +08:00
Argo-Tianyi 55f673cacc feat: 增加模型约束条件 2021-12-25 16:40:46 +08:00
Argo-Tianyi 2eced5eadd refactor: 使用 Css 表示主题 2021-12-25 16:02:09 +08:00
Argo-Tianyi 35339d7ebf refactor: 重构 AdminAlert 组件 2021-12-25 15:47:27 +08:00
Argo-Tianyi 99b6da65af feat: 增加主题 UI 2021-12-25 15:47:14 +08:00
Argo-Tianyi 1e95e722f9 feat: 增加 GetThemes 接口定义 2021-12-25 15:46:55 +08:00
Argo-Tianyi 0cdcb0eec9 feat: 增加保存 App UI 2021-12-25 15:04:33 +08:00
Argo-Tianyi db8da6b3ed feat: 增加修改密码 UI 2021-12-25 14:48:23 +08:00
Argo-Tianyi 927a9bfd90 refactor: 更新个人中心组件 2021-12-25 13:03:18 +08:00
Argo-Tianyi 874b45b29b feat: 增加 AdminCard 组件 2021-12-25 13:02:54 +08:00
Argo-Tianyi edf50b0a7a feat: 增加 SubmitButton 组件 2021-12-25 13:02:27 +08:00
Argo-Tianyi 9946294160 refactor: 重命名 BlazorTable 为 AdminTable 2021-12-25 12:46:47 +08:00
Argo-Tianyi d542c4675e chore: 更新项目依赖 2021-12-25 12:37:58 +08:00
Argo-Tianyi c15de686c0 feat: 增加 Profiles 页面 2021-12-25 12:37:05 +08:00
Argo-Tianyi dfb5fffcef refactor: 控制器移除 BootstrapAppContext 依赖 2021-12-25 12:36:33 +08:00
Argo-Tianyi b0a3a35396 refactor: 移除 UserStatus 属性 2021-12-25 12:35:59 +08:00
Argo-Tianyi 578bfc6710 feat: 增加 AdminAlert 组件 2021-12-25 12:35:29 +08:00
Argo-Tianyi 9912d73e70 chore: 重构依赖关系 2021-12-25 12:35:10 +08:00
Argo-Tianyi 5eaca5d5dc refactor: 更新字典转 List 扩展方法 2021-12-25 12:33:58 +08:00
Argo-Tianyi 90e06fedc2 refactor: App 接口移除重复 GetAll 方法统一使用 Dict 接口服务 2021-12-25 12:32:58 +08:00
Argo-Tianyi eadf199649 refactor: 移动 MenuExtensions 到 Web 层 2021-12-25 12:31:39 +08:00
Argo-Tianyi 289ed3f4a3 refactor: 重构代码修复 Table 不刷新问题 2021-12-24 13:33:58 +08:00
Argo-Tianyi 7fdef045ca chore: 开启 file-scope 命名空间 2021-12-23 22:15:21 +08:00
Argo-Tianyi a395512a24 feat: 更新手机登录逻辑 2021-12-23 12:36:48 +08:00
Argo-Tianyi ae746cd352 feat: 格式化短信服务 2021-12-23 12:36:11 +08:00
Argo-Tianyi 4b6b1e2d6e feat: IUser 增加手机登录逻辑 2021-12-23 12:35:37 +08:00
Argo-Tianyi 9ed1fd8f20 feat: 增加下发短息按钮 2021-12-22 18:34:02 +08:00
Argo-Tianyi fa3c2e4557 feat: 增加登出组件 2021-12-22 12:34:04 +08:00
Argo-Tianyi e903eac47b refactor: 消除警告信息 2021-12-22 12:33:51 +08:00
Argo-Tianyi 7ca930a12c refactor: 更改参数名称 2021-12-22 10:15:24 +08:00
Argo-Tianyi 2d9dc116d6 refactor: 精简按钮名称 2021-12-22 10:15:09 +08:00
Argo-Tianyi e4dea27c12 style: 微调菜单树样式 2021-12-22 02:21:51 +08:00
Argo-Tianyi ee8387f620 feat: 增加角色对菜单授权功能 2021-12-22 01:55:32 +08:00
Argo-Tianyi dee2e909a4 feat: 增加授权组件基类 2021-12-22 01:55:00 +08:00
Argo-Tianyi fe36e7d888 feat: 增加 SQL 语句执行输出 2021-12-22 00:20:59 +08:00
Argo-Tianyi 5eddf6ad24 feat: 开启骨架屏 2021-12-21 23:41:06 +08:00
Argo-Tianyi 4a3582748b feat: 增加枚举类型入库时 ToString 2021-12-21 23:40:50 +08:00
Argo-Tianyi fa6c0e302f refactor: 重构菜单获取数据改为异步 2021-12-21 23:40:17 +08:00
Argo-Tianyi ae88de413a fix: 修复 Lambda 表达式解析 2021-12-21 23:30:19 +08:00
Argo-Tianyi da261c6405 feat: 菜单维护增加类别 2021-12-21 15:16:50 +08:00
Argo-Tianyi 719c9ace72 feat: 微调菜单维护小箭头 2021-12-21 15:12:41 +08:00
Argo-Tianyi e385ad798b feat: 菜单维护增加 Lookup 功能 2021-12-21 14:40:15 +08:00
Argo-Tianyi 0b828ff38c feat: 增加菜单授权角色功能 2021-12-21 12:30:13 +08:00
Argo-Tianyi 77f1f2e0d9 feat: 增加角色对应用授权功能 2021-12-21 12:22:40 +08:00
Argo-Tianyi 570775ad1b feat: 增加角色对用户授权功能 2021-12-21 12:02:04 +08:00
Argo-Tianyi f2095cac40 feat: 增加角色对部门授权功能 2021-12-21 11:55:49 +08:00
Argo-Tianyi 6029e86072 feat: 更新 IRole 接口方法 2021-12-21 11:47:15 +08:00
Argo-Tianyi 30614bd223 feat(#I4NFRH): 增加部门服务
close https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues/I4NFRH
2021-12-21 11:35:30 +08:00
Argo-Tianyi 69e8428b2e chore: 增加授权弹窗 2021-12-21 10:36:06 +08:00
Argo-Tianyi c9396cc163 chore: 重命名接口名称 2021-12-21 10:34:09 +08:00
Argo-Lenovo d3eb00b93d feat: 完善角色维护菜单界面 2021-12-20 00:13:27 +08:00
Argo-Lenovo 4b3a61ed39 feat: 完善菜单维护界面 2021-12-20 00:13:02 +08:00
Argo-Lenovo fcee12335e feat: 完善部门维护界面 2021-12-20 00:12:45 +08:00
Argo-Lenovo accc58a6b0 refactor: 细化用户维护界面 2021-12-20 00:12:22 +08:00
Argo-Lenovo 840a78db95 feat: 增加操作列宽度设置 2021-12-20 00:11:58 +08:00
Argo-Lenovo f581e761e8 feat: 增加固定表头设置 2021-12-19 19:36:44 +08:00
Argo-Tianyi ab8508a0cb style: 增加 Tab 内表格滚动条样式 2021-12-19 19:17:24 +08:00
Argo-Tianyi fa3374a492 feat: 增加 Tab 标签页固定样式 2021-12-19 19:01:31 +08:00
Argo-Tianyi fa3d6ba274 doc: 增加网页组件 2021-12-19 17:46:38 +08:00
Argo-Tianyi 7b0902435c refactor: 增加 Tab 默认首页 2021-12-17 20:30:58 +08:00
Argo-Tianyi 7369db6778 chore: 客户端项目样式更新 2021-12-17 20:23:04 +08:00
Argo-Tianyi 85537a1dec chore: 更新配置文件 2021-12-17 20:20:29 +08:00
Argo-Tianyi d106b8eeb4 chore: 更改 Blazor 客户端示例 2021-12-17 19:26:47 +08:00
Argo-Tianyi e63226e755 chore: 更新依赖包 2021-12-17 15:09:14 +08:00
Argo-Tianyi 5037b16123 feat: Home 页面下增加授权 2021-12-17 13:50:49 +08:00
Argo-Tianyi 05cfdeefb3 feat: 增加未认证时不渲染页面逻辑 2021-12-17 13:28:57 +08:00
Argo-Tianyi 8b3ac481e9 refactor: 移除组件使用 BB 包 2021-12-17 13:28:18 +08:00
Argo-Tianyi 359a01e7ea refactor: 其他登录方式改用 Divider 组件 2021-12-17 10:55:12 +08:00
Argo-Tianyi 972c9da4cf feat: 更新 LinkButton 精简代码 2021-12-17 10:03:01 +08:00
Argo-Tianyi 0109e5fbb9 feat: 内置 fa 字体库 2021-12-17 10:02:34 +08:00
Argo-Tianyi 92bc630e4f refactor: 移除 captcha 库 2021-12-17 10:02:12 +08:00
Argo-Tianyi 8ae21413f4 feat: Layout 组件集成菜单授权方法 2021-12-16 20:15:05 +08:00
Argo-Tianyi 2c20e23ba3 feat: 更改方法为 GetAllMenus 2021-12-16 20:12:45 +08:00
Argo-Tianyi 892049c2cb feat: 增加手机登录 2021-12-16 15:18:43 +08:00
Argo-Tianyi 1d94e53866 feat: 改用表单提交方式进行用户鉴权 2021-12-16 14:52:02 +08:00
Argo-Tianyi 0df111ee42 feat: 母版页保存当前登录用户名与显示名称 2021-12-16 14:51:22 +08:00
Argo-Tianyi 61827b87eb feat: 更新登录逻辑 2021-12-16 14:05:38 +08:00
Argo-Tianyi f21df83abc feat: 增加 LinkButton 组件 2021-12-16 14:04:59 +08:00
Argo-Tianyi fd2fca1d90 feat: 增加 SwitchButton 组件 2021-12-16 14:04:45 +08:00
Argo-Tianyi ede1f1fead refactor: 代码重构 Users 页面 2021-12-15 22:34:55 +08:00
Argo-Tianyi 99477b8ede chore: 更新依赖包 2021-12-15 16:04:11 +08:00
Argo-Tianyi ac2df1436d feat: 移动 EFCore 配置到 Web 工程 2021-12-15 16:02:53 +08:00
Argo-Tianyi eaf36fec5e feat: 用户维护增加分配授权按钮逻辑 2021-12-15 14:59:58 +08:00
Argo-Tianyi 31c9c4de7b feat: Users 自定义菜单增加禁用功能 2021-12-15 14:20:19 +08:00
Argo-Tianyi 08d5e498a0 feat: 更新 Home 首页逻辑 2021-12-15 12:37:57 +08:00
Argo-Tianyi 54431a131d chore: 更新依赖包 2021-12-15 12:23:43 +08:00
Argo-Tianyi 32cc5c184a feat: 支持模糊查询 2021-12-15 12:20:00 +08:00
Argo-Tianyi 2232cd2eb9 feat: 增加显示名称功能 2021-12-15 10:31:35 +08:00
Argo-Tianyi b8f2851dab feat: MainLayout 增加登录用户信息 2021-12-15 10:17:19 +08:00
Argo-Tianyi 0b682fd3d7 feat: 更新接口定义 2021-12-15 10:16:42 +08:00
Argo-Tianyi 206368282d feat: 增加用户登录授权方法 2021-12-15 10:16:07 +08:00
Argo-Tianyi 9ed6fc4541 feat: 增加 UseBootstrapBlazorAdmin 中间件 2021-12-14 19:38:31 +08:00
Argo-Tianyi 5b8ca016c2 feat: 增加 ILogin 业务逻辑 2021-12-14 19:38:07 +08:00
Argo-Lenovo 3de89cd94e refactor: 移除 LoginView 方法 2021-12-14 18:41:54 +08:00
Argo-Lenovo 500f0f148e feat: 增加 Cookie 认证模块 2021-12-14 17:52:38 +08:00
Argo-Lenovo 33054356d0 refactor: 重构服务基类增加用户服务 2021-12-14 16:09:41 +08:00
Argo-Lenovo 0b1a110b22 chore: 增加包集成 Blazor 权限 2021-12-14 15:28:27 +08:00
Argo-Lenovo c0c417ca29 refactor: 更新扩展服务 2021-12-14 15:21:47 +08:00
Argo 647cc252d4 !93 feat(#I4ME4A): 增加模拟用户登录模块
* feat: 增加模拟账户登录逻辑
* feat: 增加认证服务模块
* feat: 增加重定向组件
* refactor: 增加后台文件
* wip: 临时提交
2021-12-14 04:50:25 +00:00
Argo-Tianyi affbfe1d88 feat: 更新自定义搜索模型增加 Display 标签 2021-12-13 15:17:35 +08:00
Argo-Tianyi b14d9d5752 feat: PetaPoco 增加对枚举类型搜索支持 2021-12-13 15:17:14 +08:00
Argo-Tianyi fea8e572fd style: 更新网站报错 z-index 值 2021-12-12 15:11:20 +08:00
Argo-Tianyi 4e8a7b2cdd refactor: 增加字典表高级搜索项 2021-12-12 15:11:00 +08:00
Argo-Tianyi bf4fedc544 refactor: 增加 Display 标签 2021-12-12 20:54:40 +08:00
Argo-Tianyi b0651c755e feat: 菜单表更改成枚举类型 2021-12-12 20:07:04 +08:00
Argo-Tianyi 513dce940f refactor: 增加可为空类型逻辑 2021-12-12 19:03:09 +08:00
Argo-Tianyi 334a1efbd9 feat: 增加枚举类型转化器 2021-12-12 18:58:35 +08:00
Argo-Tianyi bee6c5b895 chore: 更新数据库 2021-12-12 18:58:15 +08:00
Argo-Tianyi 5bc293dd50 feat: 增加字符串转枚举转化器 2021-12-12 18:58:04 +08:00
Argo-Tianyi 4260dd6888 refactor: 字典表增加枚举类型 2021-12-12 18:57:39 +08:00
Argo-Tianyi 17fac05da1 refactor: 增加列忽略列配置 2021-12-12 10:56:53 +08:00
Argo-Tianyi ee5558d817 chore: 更新组件依赖微调侧边栏菜单样式 2021-12-11 16:28:22 +08:00
Argo-Tianyi 1ccd30b337 chore: 更新项目配置信息 2021-12-11 14:41:32 +08:00
Argo-Tianyi 8ed5a6981f refactor: 代码重构 2021-12-11 14:27:47 +08:00
Argo-Tianyi 27e25c9907 chore: 更新命名空间 2021-12-11 14:24:36 +08:00
Argo-Tianyi ead25a3390 chore: 更改 Interface 工程为 Core 2021-12-11 14:21:53 +08:00
Argo-Tianyi 801ea3a957 refactor: 更新依赖包增加 EF 扩展 2021-12-11 14:09:48 +08:00
Argo-Tianyi 67942d615b feat: 增加 Users 2021-12-11 14:06:01 +08:00
Argo-Tianyi 311195f86d refactor: 增加过滤条件 2021-12-11 14:05:38 +08:00
Argo-Tianyi 1085708123 feat: 增加 PetaPoco Mapper 移除 Models 对 ORM 的耦合 2021-12-11 13:54:23 +08:00
Argo-Tianyi 5845c87e69 feat: 重构模型移除对 ORM 的依赖 2021-12-11 13:53:57 +08:00
Argo-Tianyi 3deea2b478 chore: 增加 xml 文件忽略规则 2021-12-11 12:08:00 +08:00
zhangpeihang 63680b0b6f wip: 去掉 PetaPoco 服务 2021-12-11 11:59:16 +08:00
zhangpeihang 6cc1ccaa5a feat: EFCore 数据服务实现 2021-12-11 11:58:23 +08:00
Argo-Tianyi 80c7f9aa8c chore: 更改 PetaPoco 工程名称服务下沉 2021-12-11 10:42:54 +08:00
Argo-Tianyi f4ba67baf9 chore: 增加接口类工程 2021-12-11 10:21:35 +08:00
Argo-Tianyi 16d3d52005 chore: 增加 Models 工程 2021-12-11 09:54:10 +08:00
Argo-Tianyi 33ed7abc0d refactor: 增加字典服务 2021-12-11 09:30:04 +08:00
Argo-Tianyi 816019e202 chore: 更新依赖组件 2021-12-11 00:18:08 +08:00
Argo-Tianyi d9da2119a6 chore: 增加菜单服务 2021-12-11 00:52:43 +08:00
Argo-Tianyi 0675e5de8c chore: 重构工程 2021-12-11 12:01:13 +08:00
Argo 4e4a6a61e0 !92 feat(#I4M1N3): 增加 Blazor 工程准备集成 BootstrapBlazor 组件库
* chore: 更新过滤解决方案文件
* refactor: 重新整理项目结构
* refactor: 改用 Update 方法
* refactor: 代码重构
* chore: 移除不使用的组件
* chore: 更新数据服务
* wip: 临时提交
* chore: 首页更新路由
* chore: 增加过滤项目文件
* feat: 更新菜单组件
* refactor: 移除不用的组件
* feat: 增加 BootstrapAppContext 服务
* refactor: 移除命名空间
* !91 feat(#I4LVUZ): 增加用户维护界面
* !90 feat(#I4LVUW): 增加字典表维护页面
* feat: 初始化 Blazor 版本
2021-12-10 13:36:08 +00:00
Argo-Tianyi 5c3be3a19f refactor: 增加 Gitee 接口默认配置 2021-11-07 12:10:34 +08:00
Argo-Tianyi 03ceefcd11 refactor: 重构 Gitee 健康检查 2021-11-07 12:10:07 +08:00
Argo-Tianyi edac104fbc refactor: 消除二义性错误 2021-10-21 12:54:56 +08:00
Argo-Tianyi 42d56b9dbc doc: 更改组织名称 2021-10-08 15:29:06 +08:00
Argo-Tianyi 24baec9cea doc: 修复 ccflow 链接错误 2021-08-15 02:35:35 +08:00
Argo-Tianyi 4204cf2e19 refactor: 消除警告信息 2021-08-15 02:35:20 +08:00
Argo-Tianyi 2308252fd9 chore: 升级 sdk 5.0.9 2021-08-15 02:35:06 +08:00
Argo-Tianyi 1b1481e86a Squashed commit of the following:
commit aa22b359cd73bfda5382cbb73c31747fcdd7d1f6
Author: Argo-Tianyi <argo@163.com>
Date:   Fri Aug 13 17:48:49 2021 +0800

    doc: 更新链接

commit 1367f17e8dd993ffcff85e55260b558aa4585a80
Author: Argo-Tianyi <argo@163.com>
Date:   Fri Aug 13 17:46:16 2021 +0800

    doc: 增加圆角样式

commit 22fb22f76968723092da8406e184548b53ba6026
Author: Argo-Tianyi <argo@163.com>
Date:   Fri Aug 13 17:44:40 2021 +0800

    doc: 更新 ccflow 链接

commit 11fabfdeca4491cb5865f4d97355b53a799a8480
Author: Argo-Tianyi <argo@163.com>
Date:   Fri Aug 13 17:44:19 2021 +0800

    doc: client 增加 ccflow 广告

commit 7aeefaf530f59590876c8bb61c08d87f8c7fad52
Author: Argo-Tianyi <argo@163.com>
Date:   Fri Aug 13 17:25:19 2021 +0800

    doc: add ccflow AD
2021-08-13 17:49:19 +08:00
Argo-Tianyi a755e68ee6 doc: 更新演示网站地址 2021-08-12 09:27:00 +08:00
Argo-Tianyi 0028688ffb chore: 更新项目依赖 2021-08-08 14:55:07 +08:00
Argo-Tianyi 500d564cd6 chore: add scripts for github actions 2021-08-08 14:27:44 +08:00
Argo-Tianyi c0fb0a7beb chore: update dockerfile 2021-08-08 14:25:50 +08:00
Argo-Tianyi d79ad95f6f Merge branch 'dev-wip' into master
# Conflicts:
#	src/client/Bootstrap.Client.DataAccess/Bootstrap.Client.DataAccess.csproj
2021-08-08 14:15:52 +08:00
Argo-Tianyi f78a64ee4e doc: update readme md 2021-08-08 12:30:48 +08:00
Argo-Tianyi cad6b19f02 chore: 更新依赖组件包 2021-08-08 12:29:45 +08:00
Argo-Tianyi c4da4cc9dc test: 修复失败的单元测试 2021-07-25 21:40:47 +08:00
Argo-Tianyi e1b1c3cbb1 refactor: 修复单元测试 2021-07-25 21:40:37 +08:00
Argo-Tianyi 4a2e077dce fix: 修复 Widget 头像图表路径不正确问题 2021-07-25 21:40:28 +08:00
Argo-Tianyi 64033be9f2 fix: 修复图标问题 2021-07-25 21:40:18 +08:00
Argo-Tianyi ac7ce48a8c core: 移除 BB 工程使用包 2021-07-25 21:40:09 +08:00
Argo-Tianyi 5524b909a9 chore: 更新 json 请求相关方法 2021-07-25 21:40:01 +08:00
Argo-Tianyi ddaeee11c7 chore: bump dependence version to latest 2021-07-25 21:39:52 +08:00
Argo-Tianyi a3e6697500 chore: 增加模拟用户 admin 设置 2021-07-25 21:39:43 +08:00
Argo-Tianyi 429c9ed6f1 chore: 移除 Linux.Dockerfile 2021-07-25 21:39:34 +08:00
Argo-Tianyi 0a1302dbc6 feat: 多层菜单支持 2021-07-25 21:39:26 +08:00
Argo-Tianyi 198c016099 refactor: 移除 NotAuthorized 代码 2021-07-25 21:39:17 +08:00
Argo-Tianyi 6dfcc4b90c doc: update readme.md 2021-07-18 19:21:22 +08:00
Argo-Tianyi 2c1334a4a9 doc: 增加驰骋工作流链接 2021-07-17 00:57:23 +08:00
Argo-Tianyi 4d15c8ffa4 doc: 集成 ccflow 工作流 2021-07-17 00:54:51 +08:00
Argo-Tianyi 0442af36ab test: 修复失败的单元测试 2021-07-02 22:22:12 +08:00
Argo-Tianyi a7c1789eb2 refactor: 修复单元测试 2021-07-02 22:05:00 +08:00
Argo-Tianyi b12d75f2cd fix: 修复 Widget 头像图表路径不正确问题 2021-07-02 20:59:12 +08:00
Argo-Tianyi 0157c571ad fix: 修复图标问题 2021-07-02 20:58:55 +08:00
Argo-Tianyi 2819af41e2 core: 移除 BB 工程使用包 2021-06-16 10:18:41 +08:00
Argo-Tianyi 3ba8bd4ba8 chore: 更新 json 请求相关方法 2021-06-01 16:17:07 +08:00
Argo-Tianyi 45a70fe238 chore: bump dependence version to latest 2021-05-29 09:24:28 +08:00
Argo-Tianyi 5daeab89dd chore: 增加模拟用户 admin 设置 2021-05-29 09:19:12 +08:00
Argo-Tianyi 1f2865807a chore: 移除 Linux.Dockerfile 2021-05-28 21:26:52 +08:00
Argo-Tianyi d31b056292 feat: 多层菜单支持 2021-05-25 20:00:52 +08:00
Argo-Tianyi d9a80affcf refactor: 移除 NotAuthorized 代码 2021-05-25 14:35:17 +08:00
Argo-Tianyi b6f0e08257 refactor: 精简代码移动 NotAuthorized 到 razor 文件中 2021-05-25 14:34:46 +08:00
Argo 361037cdbd !88 feat(#I3S4R1): 增加未授权自动跳转功能
* feat: 增加未授权自动跳转功能
* refactor: 重构代码
2021-05-20 12:26:53 +08:00
Argo 4b39a2da63 !87 feat(#I3RQ9N): 增加 blazor 客户端项目模板
* feat: 增加路由
* feat: 增加用户显示名功能
* chore: 更新 AppId
* feat: 增加 BA 权限认证
* feat: 增加 BA 认证集成
* refactor: 重构代码消除警告信息
* chore: 增加资源文件
* feat: 增加 Layout 布局
* feat: 增加默认命名空间与授权
* feat: 增加 RedirectToLogin 组件
* refactor: 更新网站 logo
* refactor: 删除不用的文件
* refactor: 增加 blazor 相关工程
* refactor: 移动 Blazor 工程到 blazor 目录下
* feat: 增加 blazor 工程
* chore: 更新依赖组件
* chore: 移动框架版本约束到 props 文件中
* chore: props 文件缩进格式化
2021-05-18 09:13:21 +08:00
Argo-Cloud d95e066b7d chore: 依赖组件升级到最新版 2021-04-05 19:23:47 +08:00
Argo-Cloud bb55697dda feat: 增加 Git 版本获取 api 2021-04-05 19:18:39 +08:00
Argo-Cloud ed072c229d feat: add Exceptionless 2021-04-05 19:14:35 +08:00
Argo-Cloud 80f5c1be1f fix: 修复 Blazor 模式无法打开问题 2021-03-12 01:47:17 +08:00
Argo-Cloud 6a3b006cc1 refactor: 更新依赖到最新版本 2021-03-12 01:46:53 +08:00
Argo-Cloud 6fe9de3ac9 refactor: 更新 api 默认参数值 2021-03-11 11:24:35 +08:00
Argo-Cloud d97e0c5ba5 docs: 更新 readme 文件 2021-03-10 00:04:55 +08:00
Argo-Cloud 59852d3bd3 docs: 更新开源地址链接 2021-03-09 17:23:52 +08:00
Argo-Unicom 9a288c91de chore: 更新依赖 2021-03-01 19:14:45 +08:00
Argo-Unicom 6270102c99 docs: 格式化文档 2021-03-01 19:14:35 +08:00
Argo-Unicom 2ab14c25d1 chore: 增加统计脚本 2021-02-28 10:51:03 +08:00
Argo-Unicom 6d814a2e2d chore: 更新依赖组件 2021-02-18 11:57:13 +08:00
Argo-Unicom 1b59098fa4 chore: 更新 github action sdk 版本 2021-02-12 11:51:18 +08:00
Argo-Unicom d83a96ed63 chore: 更新依赖组件 2021-02-12 11:49:45 +08:00
Argo-Clound 88607e9419 chore: 更新依赖组件 2021-01-28 15:37:15 +08:00
Argo-Clound a04d2213c4 chore: 更新依赖组件版本 2021-01-27 17:37:56 +08:00
Argo-Cloud cc3af1218c fix: 修复表头显示英文问题 2021-01-22 22:26:24 +08:00
Argo-Cloud 32071fe0ad chore: 更新依赖组件版本 2021-01-14 12:24:09 +08:00
Argo 14d3413f1e !85 chore: 更新 readme.md 文件
* chore: 更改奖杯地址
* chore: 更改奖杯图片大小
* chore: 更新项目奖杯图片
2021-01-12 11:56:59 +08:00
Argo-Cloud 534a3a80f0 refactor: 增加 static 关键字 2021-01-02 21:45:48 +08:00
Argo-Cloud 23c9db651c chore: 更新依赖组件到最新版 2021-01-02 21:45:02 +08:00
Argo-Cloud 2f2bb8f440 chore: 升级依赖组件到最新版 2020-12-26 12:57:52 +08:00
Argo-Cloud 49b33137e6 refactor: 更改 Layout 母版页 2020-12-25 01:55:39 +08:00
Argo-Cloud 531cafc11c refactor: 调整文件位置 2020-12-25 01:49:15 +08:00
Argo-Cloud 7762b36e37 chore: 项目依赖增加 BootstrapBlazor 2020-12-25 01:11:40 +08:00
Argo-Cloud 30fd07591e chore: 格式化项目文件缩进 2020-12-25 01:10:32 +08:00
Argo-Cloud dcfe691fd3 fix(#I29S4F): 修复 MongoDB 用户名比对导致保存失败问题
#Issues
https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues/I29S4F
2020-12-20 16:26:06 +08:00
Argo-Tencent 549cd8ff48 build: 更新 action 脚本 2020-12-14 00:06:41 +08:00
Argo-Tencent 76b7043bdf doc: 更改域名 2020-12-14 21:51:16 +08:00
Argo-Cloud b513d19b60 docker: 更新 linux dockerfile 2020-11-20 11:52:47 +08:00
Argo Zhang e800937321
docker: 更新 dockerfile 2020-11-20 10:21:08 +08:00
Argo-Cloud 1c0e5f05d5 fix: 修复 BaiDu138Svr 单元测试 2020-11-19 20:32:52 +08:00
Argo-Cloud 2e13e2c5b7 doc: 更新演示网站为 admin.blazor.zone 2020-11-19 17:33:25 +08:00
Argo-Cloud 582b5a0aee refactor: 更新项目依赖 2020-11-18 22:08:20 +08:00
Argo-Cloud bab4abe978 refactor: 更新部署脚本 2020-11-18 17:07:14 +08:00
Argo-Cloud 988e71402c refactor: MongoDB 消除警告信息 2020-11-18 17:04:44 +08:00
Argo-Cloud 5728ee8983 test: 更新单元测试增加 Exception Put 方法代码覆盖 2020-11-18 17:01:29 +08:00
Argo-Cloud 763061caf8 test: 消除单元测试警告信息 2020-11-18 14:50:30 +08:00
Argo-Cloud 2da0738339 refactor: DataAccess 消灭警告信息 2020-11-18 14:50:15 +08:00
Argo-Cloud 986c6c7ab4 refactor: 消除 Admin 工程警告信息 2020-11-18 14:49:55 +08:00
Argo-Cloud cebb4e7beb refactor: Admin 项目升级到 NET 5.0 2020-11-18 12:27:05 +08:00
Argo-Cloud 829bbcd588 refactor: Client 项目升级到 NET5.0 2020-11-18 12:26:38 +08:00
Argo-Cloud f608d88c9d build: 更新 CI 运行环境 2020-11-18 12:26:06 +08:00
Argo-Cloud cea0a9744f refactor: 单元测试升级到 net5.0 2020-11-15 00:09:08 +08:00
Argo-Cloud 7150e86473 refactor: Admin 项目升级到 net5.0 2020-11-15 00:08:34 +08:00
Argo-Cloud 3f49c7fecd refactor: client 项目升级到 net5.0 2020-11-15 00:07:55 +08:00
Argo-Cloud 188709e4a5 fix(#I22OLG): MongtoDB 更新密码判断条件错误
#Issue
https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues/I22OLG
2020-10-26 17:48:23 +08:00
Argo-Cloud 23015c318a refactor: 更新 MongoDB 用户名查找时忽略大小写 2020-10-26 17:33:47 +08:00
Argo-Cloud ec87210310 fix(#I22OG7): 修复 MongoDB 无法更改用户密码问题
#Issue
https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues/I22OG7
2020-10-26 17:33:03 +08:00
Argo-PD 94ffea202f doc: 增加 Fur 互链 2020-10-08 01:53:08 +08:00
一事冇诚 4814786ab3 !84 修复用户输入错误用户名或密码错误,登录页面变成默认样式问题
* fix(#I1JTDF): 修复用户输入错误用户名或密码错误,登录页面变成默认样式问题
2020-08-06 15:21:01 +08:00
Argo-PD 9e963aba7b db: 更新数据库脚本增加浏览器操作系统等字段大小为 2000 2020-08-06 12:11:27 +08:00
Argo-PD c911fd99b2 refactor: 移除 pragma 代码 2020-07-31 23:41:31 +08:00
Argo Window10 0a94117088 doc: 增加配置项示例 2020-07-04 15:04:50 +08:00
Argo Window10 e9dc4404ca refactor: Gitee Webhook 回调 AppVeyor 支持多个节点 2020-07-04 14:52:34 +08:00
Argo Window10 db5b324eec refactor: 重命名类 2020-07-04 06:58:38 +08:00
Argo Window10 c5ccfef7d0 feat: 增加私有 Appveyor Webhook 调用接口 2020-07-04 06:45:37 +08:00
Argo-SHCX fde8231177 fix(Client:MongoDB): 修复MongoDB 客户端 App 值为 'BA' 2020-05-20 14:47:59 +08:00
Argo Zhang 045b5861e7
fix(#I1FEC1): 修复用户维护页面更新显示名称不同步问题
#Comment
comment #I1FEC1

#Issue
close https://gitee.com/LongbowEnterprise/dashboard/issues?id=I1FEC1
2020-04-24 14:45:27 +08:00
Argo Zhang 004e591076
db: 更改 MySQL 脚本
#Comment
SQL 日志字段更改为 Text 类型
2020-04-18 16:23:46 +08:00
Argo-PD 842827ad22 feat(BC): 增加弹窗出现 Table 示例代码 2020-04-18 10:39:16 +08:00
Argo Zhang 4131b5e51d
style: 微调样式设置 nav 控制范围 2020-04-10 21:45:18 +08:00
Argo-PD 78c82af2dc script: 更新多选时提示信息内容 2020-04-05 20:12:24 +08:00
Argo Zhang 612331e5e9
feat: 增加邮件黑名单功能 2020-04-05 13:40:56 +08:00
Argo Zhang e20e51a3b1
doc: 更新前台介绍网页 2020-04-03 12:34:48 +08:00
Argo Zhang 09a3f34f12
feat: OAuth 认证支持多库操作 2020-04-03 11:57:09 +08:00
Argo Zhang 393e3ee1d6
fix(#I1DIKG): 前台地址通过配置支持绝对路径
#Comment
comment #I1DIKG

#Issue
close https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues/I1DIKG
2020-04-03 08:51:06 +08:00
Argo Zhang 144151fc0c
doc: 更新 readme.md 文件
#Comment
更新捐助码适配高清图片
2020-03-29 01:29:51 +08:00
Argo Zhang 7b6dac9bd5
doc: 捐助二维码使用 Pictures 仓库的连接图片 2020-03-27 18:19:53 +08:00
Argo Zhang e0563c17c8
Merge branch 'master' into dev
# Conflicts:
#	src/client/Bootstrap.Client/Controllers/ToolsController.cs
2020-03-27 14:52:27 +08:00
Argo b6324ba2b9 !83 重构代码:Client 工程重构邮件发送机制
Merge pull request !83 from Argo/dev-scripts
2020-03-27 14:50:45 +08:00
Argo-PD 62e3d6b54a refactor: 重构邮件发送机制 2020-03-27 14:40:58 +08:00
Argo-PD 23c20628d9 refactor: 移除 MailClient 配置项
#Comment
测试邮件与正式邮件配置项使用同一个
2020-03-27 12:52:20 +08:00
Argo-PD 861dbee3b0 doc: 增加 fork 配置提交模板文档 2020-03-27 12:51:16 +08:00
Argo Zhang f9937cd32c
doc: 更新二维码大小 2020-03-26 18:55:45 +08:00
Argo Zhang d3e93c7c7b
doc: 更新捐助二维码 2020-03-23 22:43:15 +08:00
Argo Zhang be7a2f80bd
doc: 更新捐助二维码 2020-03-20 20:23:57 +08:00
Argo Zhang 33641b85d8
feat: Blazor 多 Tabs 挂架脚本功能增强 2020-03-20 12:10:50 +08:00
Argo 2422950925 !82 增加功能:合并分支到 master
Merge pull request !82 from Argo/dev
2020-03-20 10:48:30 +08:00
Argo a0b25da459 !81 修复BUG:修复 Client 示例页面无法打开问题
Merge pull request !81 from Argo/publish
2020-03-20 10:46:17 +08:00
Argo a242a2b395 !80 增加功能:Blazor 网站设置增加前台站点等设置
Merge pull request !80 from Argo/dev-settings
2020-03-20 10:41:17 +08:00
Argo Zhang fb40cfff10
fix: Client 演示工程无法打开 Home/Dummy 视图错误 2020-03-19 14:14:06 +08:00
Argo Zhang e50cda5478
refactor: Blazor 网站设置增加后台登录地址配置 2020-03-19 11:32:13 +08:00
Argo-PD d003d2aaac build: Cache 组件升级到 3.1.4 提高 GetOrAdd 性能 2020-03-18 19:59:15 +08:00
Argo-PD a3c07e0392 test: 移除冗余代码 2020-03-18 19:42:32 +08:00
Argo Zhang 1cae5ea56d
db: 设置系统设置演示系统默认为 0 关闭 2020-03-18 19:36:09 +08:00
Argo Zhang b268c4a9e1
refactor: 增加侧滑块验证码图床路径 2020-03-18 17:15:40 +08:00
Argo Zhang d5fbb09d77
db: 增加 Admin-LTE 风格登录界面 2020-03-18 17:15:39 +08:00
Argo Zhang d10e2ec4fa
test: 增加 Login-TEC 视图单元测试 2020-03-18 17:00:35 +08:00
Argo Zhang c0b601130b
refactor: 微调 Admin-LTE 风格登录界面 2020-03-18 16:56:45 +08:00
Argo 159fa782c0 !79 AdminLTE风格登录页
Merge pull request !79 from finally44177/master
2020-03-18 16:23:27 +08:00
Argo Zhang 8c076f95bd
fix(#I1C06B): 网站设置后台网站标题与页脚
#Comment
comment #I1C06B

#Issue
close https://gitee.com/LongbowEnterprise/dashboard?issue_id=I1C06B
2020-03-18 16:15:14 +08:00
guoxiaojing db9acc1cde AdminLTE登录风格 2020-03-18 15:40:10 +08:00
Argo Zhang 635e3cdcb7
build: Cache 组件升级到 3.1.3 2020-03-17 12:27:14 +08:00
Argo bf1459a778 !78 增加功能:增加一个科技动感登录界面
* db: 增加 MongoDB 科技动感界面脚本
* refactor: 增加科技动感登录界面
* feat: 增加绿色登录界面
* test: 增加登录界面单元测试
* db: 增加蓝色登录首页
* feat: 增加蓝色登录界面
* refactor: 修正路径问题
2020-03-15 12:44:46 +08:00
Argo Zhang efb02ff3bb
style: 移动端隐藏 Login-Footer 2020-03-14 16:01:08 +08:00
Argo Zhang bcf426bfda
refactor: 登录页面增加 Login-Footer 2020-03-14 15:30:15 +08:00
Argo Zhang e83c02e161
test: 修正单元测试顺序代码 2020-03-14 14:58:22 +08:00
Argo Zhang 9ae9d5ccf4
test: 更改登录单元测试登录首页 2020-03-14 14:52:34 +08:00
Argo Zhang d42bfba824
build: Appveyor dev 分支增加单元测试 2020-03-14 14:45:24 +08:00
Argo Zhang a320208253
fix: MongoDB 脚本文件丢失逗号 2020-03-14 14:43:03 +08:00
Argo Zhang 03cc7d445c
fix(#I1BMCY): 修复 JWT 认证 Token 配置不生效问题
#Comment
comment #I1BMCY

#Issue
close https://gitee.com/LongbowEnterprise/dashboard/issues?id=I1BMCY
2020-03-14 13:34:10 +08:00
Argo a9ae7ed140 !77 增加功能:网站设置增加登录界面切换功能
Merge pull request !77 from Argo/dev-login
2020-03-13 23:19:33 +08:00
Argo Zhang 2e08a6b26b
refactor: 增加登录页切换链接 2020-03-13 23:15:05 +08:00
Argo Zhang 19206c564a
feat: 网站设置增加登录界面配置 2020-03-13 22:31:43 +08:00
Argo Zhang be1c6919be
db: 增加登录页面初始化数据 2020-03-13 18:45:37 +08:00
Argo Zhang f163b1becf
feat: 增加高仿码云登录界面 2020-03-13 15:32:26 +08:00
Argo Zhang 368401f35a
feat: 配置文件增加 JWT Token 颁发配置项 2020-03-13 11:08:55 +08:00
Argo Zhang f27843d493
feat: 前台应用配置增加了网站图标与 Icon 的设置 2020-03-13 10:59:16 +08:00
1210 changed files with 37776 additions and 1669 deletions

View File

@ -16,7 +16,7 @@ indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8-bom
[*.{json,yml,xml}]
[*.{json,yml,xml,csproj,props}]
indent_size = 2
###############################
# .NET Coding Conventions #
@ -123,9 +123,13 @@ csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
csharp_style_namespace_declarations=file_scoped:silent
###############################
# VB Coding Conventions #
###############################
[*.vb]
# Modifier preferences
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
[*.cs]
# Add file header
file_header_template = Copyright (c) Argo Zhang (argo@163.com). All rights reserved.\nLicensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.\nWebsite: https://admin.blazor.zone

View File

@ -14,6 +14,6 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.100
dotnet-version: 5.0.103
- name: Build with dotnet
run: dotnet build src/admin/Bootstrap.Admin/ --configuration Release

View File

@ -12,4 +12,4 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Build the Docker image
run: docker build . --file src/admin/Bootstrap.Admin/Linux.Dockerfile --tag ba:$(date +%s)
run: docker build . --file src/admin/Bootstrap.Admin/Dockerfile --tag ba:$(date +%s)

5
.gitignore vendored
View File

@ -85,7 +85,6 @@ StyleCopReport.xml
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
@ -348,10 +347,10 @@ ASALocalRun/
# Net Core Keys
**/[Kk]eys/*.xml
Bootstrap.*.xml
Bootstrap*.xml
###### -- Custom Ignore Section, Make sure all files you add to the git repo are below this line -- ######
# Coverage
coverage*.xml
tools/
tools/

View File

@ -0,0 +1,20 @@
{
"solution": {
"path": "BootstrapAdmin.sln",
"projects": [
"src\\blazor\\admin\\BootstrapAdmin.Caching\\BootstrapAdmin.Caching.csproj",
"src\\blazor\\admin\\BootstrapAdmin.DataAccess.Models\\BootstrapAdmin.DataAccess.Models.csproj",
"src\\blazor\\admin\\BootstrapAdmin.DataAccess.PetaPoco\\BootstrapAdmin.DataAccess.PetaPoco.csproj",
"src\\blazor\\admin\\BootstrapAdmin.Web.Core\\BootstrapAdmin.Web.Core.csproj",
"src\\blazor\\admin\\BootstrapAdmin.Web\\BootstrapAdmin.Web.csproj",
"src\\blazor\\client\\BootstrapClient.DataAccess\\BootstrapClient.DataAccess.PetaPoco.csproj",
"src\\blazor\\client\\BootstrapClient.Shared\\BootstrapClient.Web.Shared.csproj",
"src\\blazor\\client\\BootstrapClient.Web.Core\\BootstrapClient.Web.Core.csproj",
"src\\blazor\\client\\BootstrapClient.Web.Models\\BootstrapClient.DataAccess.Models.csproj",
"src\\blazor\\client\\BootstrapClient.Web\\BootstrapClient.Web.csproj",
"src\\mvc\\admin\\Bootstrap.Admin\\Bootstrap.Admin.csproj",
"src\\mvc\\admin\\Bootstrap.DataAccess\\Bootstrap.DataAccess.csproj",
"test\\UnitTest\\UnitTest.csproj"
]
}
}

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29215.179
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLServer", "SQLServer", "{87319AF5-7C40-4362-B67C-35F9DD737DB4}"
ProjectSection(SolutionItems) = preProject
@ -10,15 +10,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLServer", "SQLServer", "{
db\SqlServer\Install.sql = db\SqlServer\Install.sql
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Admin", "src\admin\Bootstrap.Admin\Bootstrap.Admin.csproj", "{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Admin", "src\mvc\admin\Bootstrap.Admin\Bootstrap.Admin.csproj", "{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "db", "db", "{586410F2-C1F0-47CD-AB28-2CF506DED2C8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client", "src\client\Bootstrap.Client\Bootstrap.Client.csproj", "{C82A6E45-AB90-43D1-8429-5CBE953D8151}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client", "src\mvc\client\Bootstrap.Client\Bootstrap.Client.csproj", "{C82A6E45-AB90-43D1-8429-5CBE953D8151}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess", "src\admin\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj", "{8D62BE79-BE13-43C8-969B-C9B00B3C84B7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess", "src\mvc\admin\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj", "{8D62BE79-BE13-43C8-969B-C9B00B3C84B7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLite", "SQLite", "{523515EC-2AD7-4282-9AF4-9D20371183B0}"
ProjectSection(SolutionItems) = preProject
@ -26,7 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLite", "SQLite", "{523515
db\SQLite\Install.sql = db\SQLite\Install.sql
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess.MongoDB", "src\admin\Bootstrap.DataAccess.MongoDB\Bootstrap.DataAccess.MongoDB.csproj", "{8336F096-4B4A-4710-A1FA-0F5E44CD8D26}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess.MongoDB", "src\mvc\admin\Bootstrap.DataAccess.MongoDB\Bootstrap.DataAccess.MongoDB.csproj", "{8336F096-4B4A-4710-A1FA-0F5E44CD8D26}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MongoDB", "MongoDB", "{A06A0AD8-A246-4329-B024-7174AE4A3EDE}"
ProjectSection(SolutionItems) = preProject
@ -57,9 +57,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Postgresql", "Postgresql",
db\Postgresql\install.sql = db\Postgresql\install.sql
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess", "src\client\Bootstrap.Client.DataAccess\Bootstrap.Client.DataAccess.csproj", "{843811A2-FE49-410F-BF9F-9F1FB14A1DEE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess", "src\mvc\client\Bootstrap.Client.DataAccess\Bootstrap.Client.DataAccess.csproj", "{843811A2-FE49-410F-BF9F-9F1FB14A1DEE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess.MongoDB", "src\client\Bootstrap.Client.DataAccess.MongoDB\Bootstrap.Client.DataAccess.MongoDB.csproj", "{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess.MongoDB", "src\mvc\client\Bootstrap.Client.DataAccess.MongoDB\Bootstrap.Client.DataAccess.MongoDB.csproj", "{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6AD32A76-F3AA-423E-96EA-E5CC679934D1}"
EndProject
@ -74,10 +74,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{E057452E-0
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{85574E7C-7D58-4135-AB4B-76678552D271}"
ProjectSection(SolutionItems) = preProject
src\admin\Bootstrap.Admin\Dockerfile = src\admin\Bootstrap.Admin\Dockerfile
src\admin\Bootstrap.Admin\Linux.Dockerfile = src\admin\Bootstrap.Admin\Linux.Dockerfile
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "srcipts", "srcipts", "{72C103DB-E1D3-449F-97C2-DF12CA111FD4}"
EndProject
@ -121,6 +117,54 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Oracle", "Oracle", "{41E078
db\Oracle\Install.sql = db\Oracle\Install.sql
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "git", "git", "{64EACBD1-23DD-4168-BEED-55D47DB1A8BB}"
ProjectSection(SolutionItems) = preProject
scripts\git\commit_msg_template.txt = scripts\git\commit_msg_template.txt
scripts\git\readme.md = scripts\git\readme.md
scripts\git\run.cmd = scripts\git\run.cmd
scripts\git\run.sh = scripts\git\run.sh
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "blazor", "blazor", "{DAE3826B-AAAB-468A-9A06-2F56EF5C0767}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github", "github", "{C07631B9-5E5E-417A-9A16-3C88956D574E}"
ProjectSection(SolutionItems) = preProject
.github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\docker.yml = .github\workflows\docker.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mvc", "mvc", "{C996F427-DA93-49D6-9804-4E665D195FC2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{45ADEF9B-C8BD-4224-9E12-F6716E85A22C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{55A2459A-6BDE-4493-B2C0-5BE1673E99EE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.Web", "src\blazor\admin\BootstrapAdmin.Web\BootstrapAdmin.Web.csproj", "{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.DataAccess.EFCore", "src\blazor\admin\BootstrapAdmin.DataAccess.EFCore\BootstrapAdmin.DataAccess.EFCore.csproj", "{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.DataAccess.Models", "src\blazor\admin\BootstrapAdmin.DataAccess.Models\BootstrapAdmin.DataAccess.Models.csproj", "{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.DataAccess.PetaPoco", "src\blazor\admin\BootstrapAdmin.DataAccess.PetaPoco\BootstrapAdmin.DataAccess.PetaPoco.csproj", "{20D03C52-0F8B-47B6-BCA8-CF0812F82722}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.Web.Core", "src\blazor\admin\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj", "{DA143654-C258-410D-B5DC-FE446ED99CE4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.DataAccess.PetaPoco", "src\blazor\client\BootstrapClient.DataAccess\BootstrapClient.DataAccess.PetaPoco.csproj", "{640F598B-6586-4AD6-B544-78CFF2602DFB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web.Shared", "src\blazor\client\BootstrapClient.Shared\BootstrapClient.Web.Shared.csproj", "{93770088-3463-427B-9CD8-88B8D7945C83}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web", "src\blazor\client\BootstrapClient.Web\BootstrapClient.Web.csproj", "{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootStarpAdmin.DataAccess.FreeSql", "src\blazor\admin\BootStarpAdmin.DataAccess.FreeSql\BootStarpAdmin.DataAccess.FreeSql.csproj", "{11122D97-B349-4A3E-B7DD-73B8B363C47C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootStarpAdmin.DataAccess.SqlSugar", "src\blazor\admin\BootStarpAdmin.DataAccess.SqlSugar\BootStarpAdmin.DataAccess.SqlSugar.csproj", "{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web.Core", "src\blazor\client\BootstrapClient.Web.Core\BootstrapClient.Web.Core.csproj", "{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.DataAccess.Models", "src\blazor\client\BootstrapClient.Web.Models\BootstrapClient.DataAccess.Models.csproj", "{CC3DF23A-2880-438F-BDEB-DB093E919ABA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.Caching", "src\blazor\admin\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj", "{ADD20515-1C1C-418B-84F6-8B05A7AA315B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -155,6 +199,58 @@ Global
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Release|Any CPU.Build.0 = Release|Any CPU
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Release|Any CPU.Build.0 = Release|Any CPU
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Release|Any CPU.Build.0 = Release|Any CPU
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Release|Any CPU.Build.0 = Release|Any CPU
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Release|Any CPU.Build.0 = Release|Any CPU
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Release|Any CPU.Build.0 = Release|Any CPU
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Release|Any CPU.Build.0 = Release|Any CPU
{93770088-3463-427B-9CD8-88B8D7945C83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93770088-3463-427B-9CD8-88B8D7945C83}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93770088-3463-427B-9CD8-88B8D7945C83}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93770088-3463-427B-9CD8-88B8D7945C83}.Release|Any CPU.Build.0 = Release|Any CPU
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Release|Any CPU.Build.0 = Release|Any CPU
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Release|Any CPU.Build.0 = Release|Any CPU
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Release|Any CPU.Build.0 = Release|Any CPU
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Release|Any CPU.Build.0 = Release|Any CPU
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Release|Any CPU.Build.0 = Release|Any CPU
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -163,7 +259,7 @@ Global
{87319AF5-7C40-4362-B67C-35F9DD737DB4} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
{C82A6E45-AB90-43D1-8429-5CBE953D8151} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} = {C996F427-DA93-49D6-9804-4E665D195FC2}
{8D62BE79-BE13-43C8-969B-C9B00B3C84B7} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
{523515EC-2AD7-4282-9AF4-9D20371183B0} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{8336F096-4B4A-4710-A1FA-0F5E44CD8D26} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
@ -173,12 +269,30 @@ Global
{6F61C2AC-84D4-48A9-8A48-680657CC8175} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{843811A2-FE49-410F-BF9F-9F1FB14A1DEE} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
{E03B7391-B52F-4449-B400-5CD9DE01F085} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{E03B7391-B52F-4449-B400-5CD9DE01F085} = {C996F427-DA93-49D6-9804-4E665D195FC2}
{C6F2DCA0-7941-4C28-9328-2D495F5DCB00} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
{FDCFC3E3-14CF-40B2-9FE5-5BC239AAC110} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
{5F732D4E-133B-4DA6-811B-C369CDC3FB89} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
{68F7C160-3FB2-4129-8F89-96F78B2DA0A9} = {FDCFC3E3-14CF-40B2-9FE5-5BC239AAC110}
{41E078CA-F005-4B66-B440-FD7EB731AD61} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{64EACBD1-23DD-4168-BEED-55D47DB1A8BB} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
{DAE3826B-AAAB-468A-9A06-2F56EF5C0767} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{C996F427-DA93-49D6-9804-4E665D195FC2} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{45ADEF9B-C8BD-4224-9E12-F6716E85A22C} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
{55A2459A-6BDE-4493-B2C0-5BE1673E99EE} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{20D03C52-0F8B-47B6-BCA8-CF0812F82722} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{DA143654-C258-410D-B5DC-FE446ED99CE4} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{640F598B-6586-4AD6-B544-78CFF2602DFB} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
{93770088-3463-427B-9CD8-88B8D7945C83} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
{11122D97-B349-4A3E-B7DD-73B8B363C47C} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
{CC3DF23A-2880-438F-BDEB-DB093E919ABA} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
{ADD20515-1C1C-418B-84F6-8B05A7AA315B} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {221EAE38-5F75-4391-9A48-E462A9F3B8FC}

View File

@ -11,17 +11,17 @@
<Target Condition=" $(IsWebProject) == true Or $(IsTestProject) == true" Name="PostBuild" AfterTargets="PostBuildEvent">
<Message Text="Copy lic file -> $(TargetDir)" Importance="high" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
</Target>
<Target Condition=" $(IsWebProject) == true " Name="PostPublish" AfterTargets="Publish">
<Message Text="Publish lic file -> $(PublishDir)" Importance="high" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
<Message Text="Publish db file -> $(PublishDir)" Importance="high" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
</Target>
</Project>

View File

@ -5,19 +5,19 @@
---
##### Version & Coverage
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://ba.sdgxgz.com/api/Gitee/Releases)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://admin.blazor.zone/api/Gitee/Releases?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
[![Coveralls](https://img.shields.io/coveralls/github/ArgoZhang/BootstrapAdmin/master.svg?logo=ReverbNation&logoColor=green&label=coveralls)](https://coveralls.io/github/ArgoZhang/BootstrapAdmin)
[![Codecov](https://img.shields.io/codecov/c/gh/argozhang/bootstrapadmin/master.svg?logo=codecov&label=codecov)](https://codecov.io/gh/argozhang/bootstrapadmin/branch/master)
##### Gitee
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
[![Build Status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master)
[![Test](https://img.shields.io/appveyor/tests/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master/tests)
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://ba.sdgxgz.com/api/Gitee/Issues)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://ba.sdgxgz.com/api/Gitee/Pulls)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://admin.blazor.zone/api/Gitee/Issues?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://admin.blazor.zone/api/Gitee/Pulls?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
##### GitHub
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
[![master status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master)
[![Test](https://img.shields.io/appveyor/tests/argozhang/bootstrapadmin/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master/tests)
[![Github build](https://img.shields.io/github/workflow/status/ArgoZhang/BootstrapAdmin/Auto%20Build%20CI/master?label=master&logoColor=green&logo=github)](https://github.com/ArgoZhang/BootstrapAdmin/actions?query=workflow%3A%22Auto+Build+CI%22+branch%3Amaster)
@ -60,7 +60,7 @@ Departments Authorize Users
For more information, please click [wiki](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D)
### Database
**MSSQL/Oracle/SQLite/MySql/MariaDB/Postgresql/Firebird/MongoDB**
**MSSQL/Oracle/SQLite/MySql/MariaDB/Firebird/MongoDB**
For more information, please click [wiki](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/数据库连接配置?sort_id=1333482)
@ -122,7 +122,7 @@ For more information, please click [wiki](https://gitee.com/LongbowEnterprise/Bo
## Online Demonstration
[![website1](https://img.shields.io/badge/linux-http://ba.zylweb.cn-success.svg?logo=buzzfeed&logoColor=green)](http://ba.zylweb.cn)
[![website2](https://img.shields.io/badge/linux-http://ba.sdgxgz.com-success.svg?logo=buzzfeed&logoColor=green)](http://ba.sdgxgz.com)
[![website2](https://img.shields.io/badge/linux-http://admin.blazor.zone-success.svg?logo=buzzfeed&logoColor=green)](http://admin.blazor.zone)
### Login
Administrator: Admin/123789
@ -154,7 +154,7 @@ Please click [wikis](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E
[![Gitee license](https://img.shields.io/github/license/argozhang/bootstrapadmin.svg?logo=git&logoColor=red)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/blob/master/LICENSE)
## GVP award
[View](https://images.gitee.com/uploads/images/2019/0516/124055_96cc9f8d_554725.png "GiteeGVP.png")
[View](https://images.gitee.com/uploads/images/2021/0112/112021_9d570be1_554725.png "GiteeGVP.png")
## Screenshots

View File

@ -5,19 +5,19 @@
---
##### Version & Coverage
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://ba.sdgxgz.com/api/Gitee/Releases)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://admin.blazor.zone/api/Gitee/Releases?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
[![Coveralls](https://img.shields.io/coveralls/github/ArgoZhang/BootstrapAdmin/master.svg?logo=ReverbNation&logoColor=green&label=coveralls)](https://coveralls.io/github/ArgoZhang/BootstrapAdmin?branch=master)
[![Codecov](https://img.shields.io/codecov/c/gh/argozhang/bootstrapadmin/master.svg?logo=codecov&label=codecov)](https://codecov.io/gh/argozhang/bootstrapadmin/branch/master)
##### Gitee
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
[![Build Status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master)
[![Test](https://img.shields.io/appveyor/tests/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master/tests)
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://ba.sdgxgz.com/api/Gitee/Issues)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://ba.sdgxgz.com/api/Gitee/Pulls)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://admin.blazor.zone/api/Gitee/Issues?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://admin.blazor.zone/api/Gitee/Pulls?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
##### GitHub
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
[![master status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master)
[![Test](https://img.shields.io/appveyor/tests/argozhang/bootstrapadmin/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master/tests)
[![Github build](https://img.shields.io/github/workflow/status/ArgoZhang/BootstrapAdmin/Auto%20Build%20CI/master?label=master&logoColor=green&logo=github)](https://github.com/ArgoZhang/BootstrapAdmin/actions?query=workflow%3A%22Auto+Build+CI%22+branch%3Amaster)
@ -29,6 +29,15 @@
使用 NET Core + Bootstrap + PetaPoco + HTML 5 + jQuery 构建的后台管理平台
**BootstrapAdmin****开源驰骋 ccflow** 达成如下协议.
1. 驰骋工作流引擎、表单引擎、快速开发平台系统采用 `GPL` 协议.
2. 驰骋 `.net` 版本成为 `ccflow`, `java` 版本成为 `jflow` 两个版本代码 100% 开源.
3. 与 BootstrapAdmin 签订服务合同的并且付费的 BootstrapAdmin 客户使用ccflow不开源系统代码受到法律保护.
4. 驰骋 BPM 代码下载地址: [传送门](http://ccflow.org/down.htm?from=argo)
<a href='http://ccflow.org/?from=argo' target=_blank ><img src='https://images.gitee.com/uploads/images/2021/0718/172630_7ebb560a_554725.png' /></a>
### 特别说明
**BootstrapAdmin** 无需二次开发,要做的仅仅是与前台系统集成,前台系统模板工程为 **Bootstrap.Client**
项目原始出发点是把权限系统从业务系统中剥离出来,项目开发专注于功能,详细配置说明请点击 [查看文档](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E7%B3%BB%E7%BB%9F%E9%9B%86%E6%88%90)
@ -66,6 +75,10 @@
数据库支持列表如下:
**MSSQL/Oracle/SQLite/MySql/MariaDB/Postgresql/Firebird/MongoDB**
### 工作流
**驰骋工作流** 进行深度集成,欢迎访问其主页 [传送门](http://ccflow.org/?from=argo)
### 浏览器支持
![chrome](https://img.shields.io/badge/chrome->%3D4.5-success.svg?logo=google%20chrome&logoColor=red)
@ -116,7 +129,7 @@
## 开发环境搭建
1. 安装 .net core sdk [官方网址](http://www.microsoft.com/net/download)
2. 安装 Visual Studio 2019 以上 [官方网址](https://visualstudio.microsoft.com/vs/getting-started/)
2. 安装 Visual Studio 2019 最新版 [官方网址](https://visualstudio.microsoft.com/vs/getting-started/)
3. 获取本项目代码 [BootstrapAdmin](https://gitee.com/LongbowEnterprise/BootstrapAdmin)
环境搭建教程 [详细说明](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B?sort_id=1333477)
@ -128,8 +141,7 @@
2. SqlServer
3. MySql
4. Oracle
5. PostgresSql
6. MongoDB
5. MongoDB
数据库配置 [详细说明](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/数据库连接配置?sort_id=1333482)
@ -138,7 +150,7 @@
## 演示地址
[![website1](https://img.shields.io/badge/linux-http://ba.zylweb.cn-success.svg?logo=buzzfeed&logoColor=green)](http://ba.zylweb.cn)
[![website2](https://img.shields.io/badge/linux-http://ba.sdgxgz.com-success.svg?logo=buzzfeed&logoColor=green)](http://ba.sdgxgz.com)
[![website2](https://img.shields.io/badge/linux-http://admin.blazor.zone-success.svg?logo=buzzfeed&logoColor=green)](http://admin.blazor.zone)
### 登录用户名与密码
管理账号Admin/123789
@ -170,7 +182,7 @@ docker pull reg.qiniu.com/argozhang/ba
[![Gitee license](https://img.shields.io/github/license/argozhang/bootstrapadmin.svg?logo=git&logoColor=red)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/blob/master/LICENSE)
## GVP 奖杯
[查看照片](https://images.gitee.com/uploads/images/2019/0516/124055_96cc9f8d_554725.png "GiteeGVP.png")
![项目奖杯](https://images.gitee.com/uploads/images/2021/0112/112021_9d570be1_554725.png "GVP.png")
## 项目截图
@ -203,4 +215,4 @@ docker pull reg.qiniu.com/argozhang/ba
如果这个项目对您有所帮助,请扫下方二维码打赏一杯咖啡。
![WeChat](https://gitee.com/LongbowEnterprise/Pictures/raw/master/WeChat/WeChat.png "微信扫码")
<img src="https://gitee.com/LongbowEnterprise/Pictures/raw/master/WeChat/BarCode@2x.png" width="382px;" />

View File

@ -1,4 +1,4 @@
version: 3.1.{build}
version: 5.0.{build}
branches:
only:
- release
@ -33,7 +33,7 @@ test_script:
- ps: >-
.\scripts\appveyor\appveyor.test.ps1
artifacts:
- path: src\admin\Bootstrap.Admin\bin\release\netcoreapp3.1\publish\
- path: src\admin\Bootstrap.Admin\bin\release\net5.0\publish\
name: BootstrapAdmin
type: WebDeployPackage
deploy:

View File

@ -359,5 +359,41 @@
"Name": "网站图标",
"Code": "/favicon.png",
"Define": NumberInt(1)
},
{
"Category": "系统首页",
"Name": "高仿码云",
"Code": "Login-Gitee",
"Define": NumberInt(0)
},
{
"Category": "系统首页",
"Name": "蓝色清新",
"Code": "Login-Blue",
"Define": NumberInt(0)
},
{
"Category": "系统首页",
"Name": "系统默认",
"Code": "Login",
"Define": NumberInt(0)
},
{
"Category": "系统首页",
"Name": "科技动感",
"Code": "Login-Tec",
"Define": NumberInt(0)
},
{
"Category": "系统首页",
"Name": "Admin-LTE",
"Code": "Login-LTE",
"Define": NumberInt(0)
},
{
"Category": "网站设置",
"Name": "登录界面",
"Code": "Login",
"Define": NumberInt(0)
}
];

View File

@ -77,6 +77,15 @@ INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('网站设置', '默认
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('网站设置', '后台地址', 'http://localhost:50852', 0);
-- 系统登录首页设置
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '高仿码云', 'Login-Gitee', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '蓝色清新', 'Login-Blue', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '系统默认', 'Login', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '科技动感', 'Login-Tec', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', 'Admin-LTE', 'Login-LTE', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('网站设置', '登录界面', 'Login', 0);
DELETE FROM Navigations Where Category = '0';
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '个人中心', 20, 'fa fa-suitcase', '~/Admin/Profiles', '0');

View File

@ -178,10 +178,10 @@ CREATE TABLE Traces(
UserName VARCHAR (50) NOT NULL,
LogTime DATETIME NOT NULL,
IP VARCHAR (15) NOT NULL,
Browser VARCHAR (50),
OS VARCHAR (50),
Browser VARCHAR (2000),
OS VARCHAR (2000),
City VARCHAR (50),
RequestUrl VARCHAR (500) NOT NULL,
RequestUrl VARCHAR (2000) NOT NULL,
UserAgent VARCHAR (2000) NULL,
Referer VARCHAR (2000)
);
@ -189,6 +189,6 @@ CREATE TABLE Traces(
CREATE TABLE DBLogs (
ID INTEGER PRIMARY KEY Auto_increment,
UserName VARCHAR (50) NULL,
`SQL` VARCHAR (2000) NOT NULL,
`SQL` Text NOT NULL,
LogTime DATETIME NOT NULL
);

View File

@ -76,6 +76,15 @@ INSERT INTO Dicts (Id, Category, Name, Code, Define) Values (SEQ_DICTS_ID.NEXTVA
INSERT INTO Dicts (Id, Category, Name, Code, Define) Values (SEQ_DICTS_ID.NEXTVAL, '网站设置', '默认应用程序', '0', 0);
INSERT INTO Dicts (Id, Category, Name, Code, Define) Values (SEQ_DICTS_ID.NEXTVAL, '网站设置', '后台地址', 'http://localhost:50852', 0);
-- 系统登录首页设置
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '高仿码云', 'Login-Gitee', 0);
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '蓝色清新', 'Login-Blue', 0);
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '系统默认', 'Login', 0);
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '科技动感', 'Login-Tec', 0);
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', 'Admin-LTE', 'Login-LTE', 0);
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '网站设置', '登录界面', 'Login', 0);
DELETE FROM Navigations Where Category = '0';
INSERT INTO Navigations (Id, ParentId, Name, "ORDER", Icon, Url, Category) Values (SEQ_NAVIGATIONS_ID.NEXTVAL, 0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
INSERT INTO Navigations (Id, ParentId, Name, "ORDER", Icon, Url, Category) Values (SEQ_NAVIGATIONS_ID.NEXTVAL, 0, '个人中心', 20, 'fa fa-suitcase', '~/Admin/Profiles', '0');

View File

@ -178,10 +178,10 @@ CREATE TABLE Traces(
UserName NVARCHAR2 (50) NOT NULL,
LogTime DATE NOT NULL,
IP NVARCHAR2 (15) NOT NULL,
Browser NVARCHAR2 (50),
OS NVARCHAR2 (50),
Browser NVARCHAR2 (2000),
OS NVARCHAR2 (2000),
City NVARCHAR2 (50),
RequestUrl NVARCHAR2 (500) NOT NULL,
RequestUrl NVARCHAR2 (2000) NOT NULL,
UserAgent NVARCHAR2 (2000),
Referer NVARCHAR2 (2000)
);

View File

@ -178,10 +178,10 @@ CREATE TABLE Traces(
UserName VARCHAR (50) NOT NULL,
LogTime DATE NOT NULL,
IP VARCHAR (15) NOT NULL,
Browser VARCHAR (50),
OS VARCHAR (50),
Browser VARCHAR (2000),
OS VARCHAR (2000),
City VARCHAR (50),
RequestUrl VARCHAR (500) NOT NULL,
RequestUrl VARCHAR (2000) NOT NULL,
UserAgent VARCHAR (2000) NULL,
Referer VARCHAR (2000)
);

View File

@ -5,8 +5,6 @@ INSERT INTO Users (UserName, Password, PassSalt, DisplayName, RegisterTime, Appr
INSERT INTO Users (UserName, Password, PassSalt, DisplayName, RegisterTime, ApprovedTime, ApprovedBy, [Description], [App]) values ('User', 'tXG/yNffpnm6cThrCH7wf6jN1ic3VHvLoY4OrzKtrZ4=', 'c5cIrRMn8XjB84M/D/X7Lg9uUqQFmYNEdxb/4HWH8OLa4pNZ', '测试账号', datetime(CURRENT_TIMESTAMP, 'localtime'), datetime(CURRENT_TIMESTAMP, 'localtime'), 'system', '系统默认创建', 'Demo');
DELETE From Dicts Where Define = 0;
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('菜单', '系统菜单', '0', 0);
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('菜单', '外部菜单', '1', 0);
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('应用程序', '后台管理', 'BA', 0);
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '网站标题', '后台管理系统', 0);
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '网站页脚', '2016 © 通用后台管理系统', 0);
@ -81,6 +79,15 @@ INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '后台地址', 'http://localhost:50852', 0);
-- 系统登录首页设置
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统首页', '2-高仿码云', 'Login-Gitee', 0);
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统首页', '3-蓝色清新', 'Login-Blue', 0);
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统首页', '1-系统默认', 'Login', 1);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '科技动感', '4-Login-Tec', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', 'Admin-LTE', '5-Login-LTE', 0);
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '登录界面', 'Login', 0);
DELETE FROM Navigations Where Category = '0';
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '个人中心', 20, 'fa fa-suitcase', '~/Admin/Profiles', '0');

View File

@ -178,10 +178,10 @@ CREATE TABLE Traces(
UserName VARCHAR (50) NOT NULL COLLATE NOCASE,
LogTime DATETIME NOT NULL,
IP VARCHAR (15) NOT NULL,
Browser VARCHAR (50),
OS VARCHAR (50),
Browser VARCHAR (2000),
OS VARCHAR (2000),
City VARCHAR (50),
RequestUrl VARCHAR (500) NOT NULL,
RequestUrl VARCHAR (2000) NOT NULL,
UserAgent VARCHAR (2000),
Referer VARCHAR (2000)
);

View File

@ -81,6 +81,15 @@ INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'网站设
INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'网站设置', N'后台地址', 'http://localhost:50852', 0)
-- 系统登录首页设置
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'高仿码云', N'Login-Gitee', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'蓝色清新', N'Login-Blue', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'系统默认', N'Login', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'科技动感', N'Login-Tec', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'Admin-LTE', N'Login-LTE', 0);
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'网站设置', N'登录界面', N'Login', 0);
DELETE FROM Navigations Where Category = N'0'
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'后台管理', 10, N'fa fa-gear', N'~/Admin/Index', N'0')
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'个人中心', 20, N'fa fa-suitcase', N'~/Admin/Profiles', N'0')

View File

@ -564,10 +564,10 @@ CREATE TABLE [dbo].[Traces](
[UserName] [varchar](50) NOT NULL,
[LogTime] [datetime] NOT NULL,
[Ip] [varchar](15) NOT NULL,
[Browser] [varchar](50) NULL,
[OS] [varchar](50) NULL,
[Browser] [varchar](2000) NULL,
[OS] [varchar](2000) NULL,
[City] [nvarchar](50) NULL,
[RequestUrl] [nvarchar](500) NOT NULL,
[RequestUrl] [nvarchar](2000) NOT NULL,
[UserAgent] [varchar](2000) NULL,
[Referer] [nvarchar](2000) NULL,
CONSTRAINT [PK_Traces] PRIMARY KEY CLUSTERED

View File

@ -70,12 +70,9 @@ function reportCodecov() {
}
}
$branch = $($env:APPVEYOR_REPO_BRANCH)
if ($branch -ne "dev") {
installDB
installCoveralls
installCodecov
runUnitTest
reportCoveralls
reportCodecov
}
installDB
installCoveralls
installCodecov
runUnitTest
reportCoveralls
reportCodecov

View File

@ -0,0 +1,42 @@
fix(#BUGID): 简要描述
#Comment
comment #BUGID
#Issue
close link fix https://gitee.com/LongbowEnterprise/dashboard/issues?id=BUGID
# 样式 : feat(location): 接入登录API
#
# 登录功能与服务器对接
#
<type>(<scope>): <subject>
<body>
<footer>
#其中 type 的值可以有
# feat: 新功能
# fix: 修复bug
# doc: 文档改变
# style: 代码格式改变
# refactor: 某个已有功能重构
# perf: 性能优化
# test: 增加测试
# build: 改变了build工具 如 更新 props 文件
# revert: 撤销上一次的 commit
# db: 数据库文件或者脚本更改
# script: 辅助脚本改变
#
#scope: 用来说明此次修改的影响范围
# all: 表示影响面大 ,如修改了网络框架 会对真个程序产生影响
# location: 表示影响小,某个小小的功能
# module: 表示会影响某个模块 如登录模块、首页模块 、用户管理模块等等
#
#subject: 用来简要描述本次改动,概述就好了
#
#body: 具体的修改信息 应该尽量详细
#
#footer: 放置写备注啥的,如果是 bug 可以把bug id放入
#

32
scripts/git/readme.md Normal file
View File

@ -0,0 +1,32 @@
## 提交模板配置
### Windows Fork
Windows 版本的 Fork 提供了提交模板 commit message template功能配置步骤如下
#### git 配置文件
1. 拷贝仓库 `scripts\git\commit_msg_template.txt` 文件到当前用户根目录下 `C:\Users\[用户名]\.commit_msg_template.txt`
2. 配置 git 全局配置文件 `C:\Users\[用户名]\.gitconfig` (此文件为隐藏文件)
3. 更新 commit 配置项
```log
[commit]
template = /Users/argo/.commit_msg_template.txt
```
注意原始文件不是 . 开头拷贝到跟目录下为 . 开头文件名(点号开头文件默认为隐藏文件)
#### Fork 配置步骤
1. 打开要配置的仓库
2. 点击菜单栏第二个 **仓库** 菜单Repository
3. 下拉菜单中选中最后一个菜单项 **仓库设置** 子菜单Settings for this repository
如下图所示
![输入图片说明](https://images.gitee.com/uploads/images/2020/0327/123310_1b9b4af3_554725.png "Screen Shot 2020-03-27 at 12.30.38.png")
4. 切换到 **提交模板** 面板Commit Template
5. 勾选使用 **全局配置文件** Use global git configuration file
下面的文本框内即出现提交模板内容

3
scripts/git/run.cmd Normal file
View File

@ -0,0 +1,3 @@
@echo off
copy commit_msg_template.txt "%USERPROFILE%\.commit_msg_template.txt" /y

3
scripts/git/run.sh Normal file
View File

@ -0,0 +1,3 @@
#! /bin/bash
cp commit_msg_template.txt "../../.git/commit_msg_template1.txt"

View File

@ -4,10 +4,10 @@ cd ~/BootstrapAdmin
git pull
dotnet publish src/admin/Bootstrap.Admin -c Release
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/netcoreapp3.1/publish/appsettings*.json
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/netcoreapp3.1/publish/BootstrapAdmin.db
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/net5.0/publish/appsettings*.json
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/net5.0/publish/BootstrapAdmin.db
systemctl stop ba.admin
\cp -fr ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/netcoreapp3.1/publish/* /usr/local/ba/admin/
\cp -fr ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/net5.0/publish/* /usr/local/ba/admin/
systemctl start ba.admin
systemctl status ba.admin -l

View File

@ -4,8 +4,8 @@ cd ~/BootstrapAdmin
git pull
dotnet publish src/client/Bootstrap.Client -c Release
rm -f ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/netcoreapp3.1/publish/appsettings*.json
rm -f ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/net5.0/publish/appsettings*.json
systemctl stop ba.client
\cp -fr ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/netcoreapp3.1/publish/* /usr/local/ba/client/
\cp -fr ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/net5.0/publish/* /usr/local/ba/client/
systemctl start ba.client
systemctl status ba.client -l

View File

@ -2,12 +2,16 @@
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageProjectUrl>https://gitee.com/LongbowEnterprise/BootstrapAdmin</PackageProjectUrl>
<RepositoryUrl>https://gitee.com/LongbowEnterprise/BootstrapAdmin.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Nullable>enable</Nullable>
<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
</Project>

View File

@ -1,144 +0,0 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Specialized;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace Bootstrap.Admin.Controllers.Api
{
/// <summary>
/// Gitee 网站信息接口类
/// </summary>
[Route("api/[controller]/[action]")]
[ApiController]
[AllowAnonymous]
public class GiteeController : ControllerBase
{
/// <summary>
/// 获取 Gitee 网站 Issues 信息
/// </summary>
/// <param name="client"></param>
/// <param name="userName"></param>
/// <param name="repoName"></param>
/// <param name="label"></param>
/// <param name="color"></param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> Issues([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "LongbowEnterprise", [FromQuery]string? repoName = "BootstrapAdmin", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
{
var ret = await GetJsonAsync($"https://gitee.com/{userName}/{repoName}/issues", url => client.HttpClient.GetStringAsync(url), content =>
{
var regex = Regex.Matches(content, "<div class='ui mini circular label'>([\\d]+)</div>", RegexOptions.IgnoreCase);
var labels = new string[] { "open", "progressing", "closed", "rejected" };
var result = string.IsNullOrEmpty(content) ? new string[] { "unknown" } : regex.Select((m, i) => $"{labels[i]} {m.Groups[1].Value}");
return string.Join(" ", result);
});
color = ret.StartsWith("open 0 progressing 0", StringComparison.OrdinalIgnoreCase) ? "success" : color;
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
}
/// <summary>
/// 获取 Gitee 网站 Pulls 信息
/// </summary>
/// <param name="client"></param>
/// <param name="userName"></param>
/// <param name="repoName"></param>
/// <param name="label"></param>
/// <param name="color"></param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> Pulls([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "LongbowEnterprise", [FromQuery]string? repoName = "BootstrapAdmin", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
{
var ret = await GetJsonAsync($"https://gitee.com/{userName}/{repoName}/pulls", url => client.HttpClient.GetStringAsync(url), content =>
{
var regex = Regex.Matches(content, "<div class='ui mini circular label'>([\\d]+)</div>", RegexOptions.IgnoreCase);
var labels = new string[] { "open", "merged", "closed" };
var result = string.IsNullOrEmpty(content) ? new string[] { "unknown" } : regex.Select((m, i) => $"{labels[i]} {m.Groups[1].Value}");
return string.Join(" ", result);
});
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
}
/// <summary>
/// 获取 Gitee 网站 Releases 信息
/// </summary>
/// <param name="client"></param>
/// <param name="userName"></param>
/// <param name="repoName"></param>
/// <param name="label"></param>
/// <param name="color"></param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> Releases([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "LongbowEnterprise", [FromQuery]string? repoName = "BootstrapAdmin", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
{
var ret = await GetJsonAsync($"https://gitee.com/{userName}/{repoName}/releases", url => client.HttpClient.GetStringAsync(url), content =>
{
var regex = Regex.Match(content, $"<a href=\"/{userName}/{repoName}/releases/([^\\s]+)\" target=\"_blank\">", RegexOptions.IgnoreCase);
return string.IsNullOrEmpty(content) ? "unknown" : regex.Groups[1].Value;
});
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
}
/// <summary>
/// 获取 Gitee 网站 Builds 信息
/// </summary>
/// <param name="client"></param>
/// <param name="userName"></param>
/// <param name="projName"></param>
/// <param name="branchName"></param>
/// <param name="label"></param>
/// <param name="color"></param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> Builds([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "ArgoZhang", [FromQuery]string? projName = "bootstrapadmin", [FromQuery]string? branchName = "master", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
{
var ret = await GetJsonAsync($"https://ci.appveyor.com/api/projects/{userName}/{projName}/branch/{branchName}", url => client.HttpClient.GetAsJsonAsync<AppveyorBuildResult>(url, null, new CancellationTokenSource(10000).Token), content =>
{
return content == null ? "unknown" : content.Build.Version;
});
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
}
private async static Task<string> GetJsonAsync<T>(string url, Func<string, Task<T>> requestUrl, Func<T, string> callback)
{
var ret = "unresponsive";
try
{
var resq = await requestUrl(url);
ret = callback(resq);
}
catch (OperationCanceledException)
{
}
catch (Exception ex)
{
ex.Log(new NameValueCollection()
{
["Url"] = url
});
}
return ret;
}
private class AppveyorBuildResult
{
/// <summary>
/// Appveyor 编译版本实例
/// </summary>
public Build Build { get; set; } = new Build();
}
private class Build
{
/// <summary>
/// Build 版本信息
/// </summary>
public string Version { get; set; } = "";
}
}
}

View File

@ -1,19 +0,0 @@
#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
#For more information, please see https://aka.ms/containercompat
FROM microsoft/dotnet:3.1-aspnetcore-runtime-nanoserver-1903 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/dotnet:3.1-sdk-nanoserver-1903 AS build
WORKDIR /src
COPY . .
WORKDIR "src/admin/Bootstrap.Admin"
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Bootstrap.Admin.dll"]

View File

@ -1,12 +0,0 @@
using Bootstrap.Admin.Pages.Shared;
namespace Bootstrap.Admin.Pages.Components
{
/// <summary>
/// LgbInputText 组件
/// </summary>
public class LgbInputText : LgbInput<string>
{
}
}

View File

@ -1,37 +0,0 @@
using Bootstrap.Admin.Pages.Components;
using Microsoft.Extensions.DependencyInjection;
using System.ComponentModel;
namespace Microsoft.AspNetCore.Components.Forms
{
/// <summary>
///
/// </summary>
public static class FieldIdentifierExtensions
{
/// <summary>
///
/// </summary>
/// <param name="fieldIdentifier"></param>
/// <returns></returns>
public static string GetDisplayName(this FieldIdentifier fieldIdentifier)
{
var cacheKey = (Type: fieldIdentifier.Model.GetType(), FieldName: fieldIdentifier.FieldName);
if (!DisplayNamesExtensions.TryGetValue(cacheKey, out var dn))
{
if (BootstrapAdminEditContextDataAnnotationsExtensions.TryGetValidatableProperty(fieldIdentifier, out var propertyInfo))
{
var displayNameAttribute = propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true);
if (displayNameAttribute.Length > 0)
{
dn = ((DisplayNameAttribute)displayNameAttribute[0]).DisplayName;
// add display name into cache
DisplayNamesExtensions.GetOrAdd((fieldIdentifier.Model.GetType(), fieldIdentifier.FieldName), key => dn);
}
}
}
return dn ?? cacheKey.FieldName;
}
}
}

View File

@ -1,12 +0,0 @@
using Longbow.Web.SignalR;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// 后台任务消息Hub
/// </summary>
public class TaskLogHub : SignalRHub
{
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bootstrap.Security" Version="3.1.0" />
<PackageReference Include="MongoDB.Driver" Version="2.10.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj" />
</ItemGroup>
</Project>

View File

@ -1,28 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bootstrap.Security.DataAccess" Version="3.1.1" />
<PackageReference Include="Bootstrap.Security.Mvc" Version="3.1.2-beta01" />
<PackageReference Include="Longbow" Version="3.1.0" />
<PackageReference Include="Longbow.AlipayAuth" Version="3.1.0" />
<PackageReference Include="Longbow.Cache" Version="3.1.2-beta-02" />
<PackageReference Include="Longbow.Data" Version="3.1.0" />
<PackageReference Include="Longbow.GiteeAuth" Version="3.1.0" />
<PackageReference Include="Longbow.GitHubAuth" Version="3.1.0" />
<PackageReference Include="Longbow.OAuth" Version="3.1.1" />
<PackageReference Include="Longbow.PetaPoco" Version="1.0.2" />
<PackageReference Include="Longbow.Security.Cryptography" Version="1.3.0" />
<PackageReference Include="Longbow.Tasks" Version="3.1.1" />
<PackageReference Include="Longbow.TencentAuth" Version="3.1.1" />
<PackageReference Include="Longbow.Web" Version="3.1.1" />
<PackageReference Include="Longbow.WeChatAuth" Version="3.1.2" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="3.1.2" />
<PackageReference Include="PetaPoco.Extensions" Version="3.1.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />
</ItemGroup>
</Project>

View File

@ -1 +0,0 @@
<lgb><token>d9DQpRTdULRQDYkciXU+R2LrcHSPdJY+9eip5weQTVQfgX6m0sETBCqW5ymQ/A7lrEXkKHXmJpO9rs9xy3rpDX5FJ+wF1o66HROA28Arh26APC55IcL23n+ImKyZPEUHupHvPGZ0rrGPy18A6GTn65IrsfqFS2vyr5yrmnjssgA=</token></lgb>

View File

@ -0,0 +1,15 @@
<Project>
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Diagnostics.CodeAnalysis" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj" />
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
<PackageReference Include="FreeSql.Provider.Sqlite" Version="3.0.100" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,67 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapBlazor.Components;
using FreeSql;
using FreeSql.Internal.Model;
namespace BootStarpAdmin.DataAccess.FreeSql.Extensions;
/// <summary>
///
/// </summary>
static class FilterExtensions
{
public static ISelect<TModel> PageIf<TModel>(this ISelect<TModel> source, int pageIndex, int pageItems, bool isPage) => isPage
? source.Page(pageIndex, pageItems)
: source;
/// <summary>
///
/// </summary>
/// <param name="filters"></param>
/// <returns></returns>
public static DynamicFilterInfo ToDynamicFilter(this IEnumerable<IFilterAction> filters)
{
var ret = new DynamicFilterInfo() { Filters = new List<DynamicFilterInfo>() };
// 处理 过滤 高级搜索 自定义搜索
foreach (var filter in filters)
{
var item = new DynamicFilterInfo() { Filters = new List<DynamicFilterInfo>() };
var actions = filter.GetFilterConditions();
foreach (var f in actions)
{
item.Logic = f.FilterLogic.ToDynamicFilterLogic();
item.Filters.Add(new DynamicFilterInfo()
{
Field = f.FieldKey,
Value = f.FieldValue,
Operator = f.FilterAction.ToDynamicFilterOperator()
});
}
ret.Filters.Add(item);
}
return ret;
}
private static DynamicFilterLogic ToDynamicFilterLogic(this FilterLogic logic) => logic switch
{
FilterLogic.And => DynamicFilterLogic.And,
_ => DynamicFilterLogic.Or
};
private static DynamicFilterOperator ToDynamicFilterOperator(this FilterAction action) => action switch
{
FilterAction.Equal => DynamicFilterOperator.Equal,
FilterAction.NotEqual => DynamicFilterOperator.NotEqual,
FilterAction.Contains => DynamicFilterOperator.Contains,
FilterAction.NotContains => DynamicFilterOperator.NotContains,
FilterAction.GreaterThan => DynamicFilterOperator.GreaterThan,
FilterAction.GreaterThanOrEqual => DynamicFilterOperator.GreaterThanOrEqual,
FilterAction.LessThan => DynamicFilterOperator.LessThan,
FilterAction.LessThanOrEqual => DynamicFilterOperator.LessThanOrEqual,
_ => throw new System.NotSupportedException()
};
}

View File

@ -0,0 +1,60 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Models;
using BootstrapAdmin.DataAccess.Models;
namespace BootStarpAdmin.DataAccess.FreeSql.Extensions;
static class FreeSqlExtensions
{
public static void Mapper(this IFreeSql freeSql)
{
freeSql.CodeFirst.ConfigEntity<Navigation>(i =>
{
i.Name("Navigations");
i.Property(n => n.HasChildren).IsIgnore(true);
});
freeSql.CodeFirst.ConfigEntity<User>(i =>
{
i.Name("Users");
i.Property(n => n.NewPassword).IsIgnore(true);
i.Property(n => n.ConfirmPassword).IsIgnore(true);
i.Property(n => n.Period).IsIgnore(true);
i.Property(n => n.IsReset).IsIgnore(true);
});
freeSql.CodeFirst.ConfigEntity<Group>(i =>
{
i.Name("Groups");
});
freeSql.CodeFirst.ConfigEntity<Role>(i =>
{
i.Name("Roles");
});
freeSql.CodeFirst.ConfigEntity<Error>(i =>
{
i.Name("Exceptions");
});
freeSql.CodeFirst.ConfigEntity<UserRole>(i =>
{
i.Name("UserRole");
i.Property(s => s.ID).IsIgnore(true);
});
freeSql.CodeFirst.ConfigEntity<NavigationRole>(i =>
{
i.Name("NavigationRole");
i.Property(s => s.ID).IsIgnore(true);
});
freeSql.CodeFirst.ConfigEntity<UserGroup>(i =>
{
i.Name("UserGroup");
i.Property(s => s.ID).IsIgnore(true);
});
freeSql.CodeFirst.ConfigEntity<RoleGroup>(i =>
{
i.Name("RoleGroup");
i.Property(s => s.ID).IsIgnore(true);
});
}
}

View File

@ -0,0 +1,50 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Extensions;
using BootStarpAdmin.DataAccess.FreeSql.Service;
using BootstrapAdmin.Web.Core;
using BootstrapBlazor.Components;
using FreeSql;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// FreeSql ORM 注入服务扩展类
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// 注入 FreeSql 数据服务类
/// </summary>
/// <param name="services"></param>
/// <param name="freeSqlBuilder"></param>
/// <returns></returns>
public static IServiceCollection AddFreeSql(this IServiceCollection services, Action<IServiceProvider, FreeSqlBuilder> freeSqlBuilder)
{
services.TryAddSingleton<IFreeSql>(provider =>
{
var builder = new FreeSqlBuilder();
freeSqlBuilder(provider, builder);
var instance = builder.Build();
instance.Mapper();
return instance;
});
// 增加数据服务
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
// 增加业务服务
services.AddSingleton<IApp, AppService>();
services.AddSingleton<IDict, DictService>();
services.AddSingleton<IException, ExceptionService>();
services.AddSingleton<IGroup, GroupService>();
services.AddSingleton<ILogin, LoginService>();
services.AddSingleton<INavigation, NavigationService>();
services.AddSingleton<IRole, RoleService>();
services.AddSingleton<IUser, UserService>();
return services;
}
}

View File

@ -0,0 +1,14 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
class NavigationRole
{
public string? ID { get; set; }
public string? NavigationID { get; set; }
public string? RoleID { get; set; }
}

View File

@ -0,0 +1,12 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
class RoleApp
{
public string? RoleID { get; set; }
public string? AppID { get; set; }
}

View File

@ -0,0 +1,14 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
class RoleGroup
{
public string? ID { get; set; }
public string? RoleID { get; set; }
public string? GroupID { get; set; }
}

View File

@ -0,0 +1,14 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
class UserGroup
{
public string? ID { get; set; }
public string? UserID { get; set; }
public string? GroupID { get; set; }
}

View File

@ -0,0 +1,14 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
class UserRole
{
public string? ID { get; set; }
public string? UserID { get; set; }
public string? RoleID { get; set; }
}

View File

@ -0,0 +1,36 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Models;
using BootstrapAdmin.Web.Core;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class AppService : IApp
{
private IFreeSql FreeSql { get; }
public AppService(IFreeSql freeSql) => FreeSql = freeSql;
public List<string> GetAppsByRoleId(string? roleId) => FreeSql.Ado.Query<string>("select AppID from RoleApp where RoleID = @roleId", new { roleId });
public bool SaveAppsByRoleId(string? roleId, IEnumerable<string> appIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from RoleApp where RoleID = @roleId", new { roleId });
FreeSql.Insert(appIds.Select(g => new RoleApp { AppID = g, RoleID = roleId })).ExecuteAffrows();
ret = true;
});
}
catch (Exception)
{
throw;
}
return ret;
}
}

View File

@ -0,0 +1,68 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Extensions;
using BootstrapBlazor.Components;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
{
private IFreeSql FreeSql { get; }
public DefaultDataService(IFreeSql freeSql) => FreeSql = freeSql;
/// <summary>
/// 删除方法
/// </summary>
/// <param name="models"></param>
/// <returns></returns>
public override async Task<bool> DeleteAsync(IEnumerable<TModel> models)
{
await FreeSql.Delete<TModel>(models).ExecuteAffrowsAsync();
return true;
}
/// <summary>
/// 保存方法
/// </summary>
/// <param name="model"></param>
/// <param name="changedType"></param>
/// <returns></returns>
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
{
if (changedType == ItemChangedType.Add)
{
await FreeSql.Insert<TModel>(model).ExecuteAffrowsAsync();
}
else if (changedType == ItemChangedType.Update)
{
await FreeSql.Update<TModel>(model).ExecuteAffrowsAsync();
}
return true;
}
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions option)
{
var ret = new QueryData<TModel>()
{
IsSorted = true,
IsFiltered = true,
IsSearch = true,
IsAdvanceSearch = option.AdvanceSearchs.Any() || option.CustomerSearchs.Any()
};
ret.Items = FreeSql.Select<TModel>()
.WhereDynamicFilter(option.Searchs.ToDynamicFilter())
.WhereDynamicFilter(option.Filters
.Concat(option.AdvanceSearchs)
.Concat(option.CustomerSearchs)
.ToDynamicFilter())
.OrderByPropertyNameIf(option.SortOrder != SortOrder.Unset, option.SortName, option.SortOrder == SortOrder.Asc)
.Count(out var count)
.PageIf(option.PageIndex, option.PageItems, option.IsPage)
.ToList();
ret.TotalCount = Convert.ToInt32(count);
return Task.FromResult(ret);
}
}

View File

@ -0,0 +1,197 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Caching;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Longbow.Security.Cryptography;
using Microsoft.Extensions.Configuration;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class DictService : IDict
{
private const string DictServiceCacheKey = "DictService-GetAll";
private IFreeSql FreeSql { get; }
private string? AppId { get; set; }
public DictService(IFreeSql freeSql, IConfiguration configuration)
{
FreeSql = freeSql;
AppId = configuration.GetValue("AppId", "BA");
}
public bool AuthenticateDemo(string code)
{
var ret = false;
if (!string.IsNullOrEmpty(code))
{
var dicts = GetAll();
var salt = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "授权盐值" && d.Define == EnumDictDefine.System)?.Code;
var authCode = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "哈希结果" && d.Define == EnumDictDefine.System)?.Code;
if (!string.IsNullOrEmpty(salt))
{
ret = LgbCryptography.ComputeHash(code, salt) == authCode;
}
}
return ret;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<Dict> GetAll() => CacheManager.GetOrAdd<List<Dict>>(DictServiceCacheKey, entry => FreeSql.Select<Dict>().ToList());
public Dictionary<string, string> GetApps()
{
var dicts = GetAll();
return dicts.Where(d => d.Category == "应用程序").Select(s => new KeyValuePair<string, string>(s.Code, s.Name)).ToDictionary(i => i.Key, i => i.Value);
}
public int GetCookieExpiresPeriod()
{
var dicts = GetAll();
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "Cookie保留时长" && d.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(code, out var ret);
return ret;
}
public string GetCurrentLogin()
{
var dicts = GetAll();
return dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "登录界面" && d.Define == EnumDictDefine.System)?.Code ?? "Login";
}
public Dictionary<string, string> GetLogins()
{
var dicts = GetAll();
return dicts.Where(d => d.Category == "系统首页").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).OrderBy(i => i.Value).ToDictionary(i => i.Key, i => i.Value);
}
public string? GetNotificationUrl(string appId) => GetUrlByName(appId, "系统通知地址");
public string? GetProfileUrl(string appId) => GetUrlByName(appId, "个人中心地址");
public string? GetSettingsUrl(string appId) => GetUrlByName(appId, "系统设置地址");
public Dictionary<string, string> GetThemes()
{
var dicts = GetAll();
return dicts.Where(d => d.Category == "网站样式").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
}
public string GetWebFooter()
{
var dicts = GetAll();
var title = "网站页脚";
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
if (!string.IsNullOrEmpty(name))
{
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站页脚") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站页脚");
title = dict?.Code ?? "网站标题";
}
return title;
}
public string GetWebTitle()
{
var dicts = GetAll();
var title = "网站标题";
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
if (!string.IsNullOrEmpty(name))
{
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站标题") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站标题");
title = dict?.Code ?? "网站标题";
}
return title;
}
public bool IsDemo()
{
var dicts = GetAll();
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "演示系统" && d.Define == EnumDictDefine.System)?.Code ?? "0";
return code == "1";
}
public string RetrieveIconFolderPath()
{
var dicts = GetAll();
return dicts.FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == EnumDictDefine.System)?.Code ?? "images/uploder/";
}
private bool SaveDict(Dict dict)
{
var ret = FreeSql.Update<Dict>().Where(s => s.Category == dict.Category && s.Name == dict.Name).Set(s => s.Code, dict.Code).ExecuteAffrows() > 0;
if (ret)
{
// 更新缓存
CacheManager.Clear(DictServiceCacheKey);
}
return ret;
}
public bool SaveCookieExpiresPeriod(int expiresPeriod) => SaveDict(new Dict { Category = "网站设置", Name = "Cookie保留时长", Code = expiresPeriod.ToString() });
public bool SaveDemo(bool isDemo) => SaveDict(new Dict { Category = "网站设置", Name = "演示系统", Define = EnumDictDefine.System, Code = isDemo ? "1" : "0" });
public bool SaveHealthCheck(bool enable = true) => SaveDict(new Dict { Category = "网站设置", Name = "演示系统", Define = EnumDictDefine.System, Code = enable ? "1" : "0" });
public bool SaveLogin(string login) => SaveDict(new Dict { Category = "网站设置", Name = "登录界面", Code = login });
public bool SaveTheme(string theme) => SaveDict(new Dict { Category = "网站设置", Name = "使用样式", Code = theme });
public bool SaveWebFooter(string footer) => SaveDict(new Dict { Category = "网站设置", Name = "网站页脚", Code = footer });
public bool SaveWebTitle(string title) => SaveDict(new Dict { Category = "网站设置", Name = "网站标题", Code = title });
private string? GetUrlByName(string appId, string dictName)
{
string? url = null;
var dicts = GetAll();
var appName = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == appId && d.Define == EnumDictDefine.System)?.Name;
if (!string.IsNullOrEmpty(appName))
{
url = dicts.FirstOrDefault(d => d.Category == appName && d.Name == dictName && d.Define == EnumDictDefine.Customer)?.Code;
}
return url;
}
/// <summary>
/// 通过指定 appId 获得配置首页地址
/// </summary>
/// <param name="appId"></param>
/// <returns></returns>
public string? GetHomeUrlByAppId(string appId)
{
string? url = null;
var dicts = GetAll();
// appId 为空时读取前台列表取第一个应用作为默认应用
url = dicts.FirstOrDefault(d => d.Category == "应用首页" && d.Name.Equals(appId, StringComparison.OrdinalIgnoreCase) && d.Define == EnumDictDefine.System)?.Code;
return url;
}
public bool SavDefaultApp(bool enabled)
{
throw new NotImplementedException();
}
public bool GetEnableDefaultApp()
{
throw new NotImplementedException();
}
public string GetIconFolderPath()
{
throw new NotImplementedException();
}
public string GetDefaultIcon()
{
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,64 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class ExceptionService : IException
{
private IFreeSql FreeSql { get; }
public ExceptionService(IFreeSql freeSql) => FreeSql = freeSql;
public (IEnumerable<Error> Items, int ItemsCount) GetAll(string? searchText, ExceptionFilter filter, int pageIndex, int pageItems, List<string> sortList)
{
var items = FreeSql.Select<Error>();
if (!string.IsNullOrEmpty(searchText))
{
items.Where($"ErrorPage Like %@searchText% or Message Like %@searchText% or StackTrace Like %@searchText%", new { searchText });
}
if (!string.IsNullOrEmpty(filter.Category))
{
items.Where("Category = @Category", new { filter.Category });
}
if (!string.IsNullOrEmpty(filter.UserId))
{
items.Where("UserId Like %@UserId%", new { filter.UserId });
}
if (!string.IsNullOrEmpty(filter.ErrorPage))
{
items.Where("ErrorPage Like %{ErrorPage}%", new { filter.ErrorPage });
}
items.Where("LogTime >= @Star and LogTime <= @End", new { filter.Star, filter.End });
if (sortList.Any())
{
items.OrderBy(string.Join(", ", sortList));
}
else
{
items.OrderBy("UserId, ErrorPage, Logtime desc");
}
var errors = items.Count(out var count).Page(pageIndex, pageItems).ToList();
return (errors, Convert.ToInt32(count));
}
public bool Log(Error exception)
{
try
{
FreeSql.Insert(exception).ExecuteAffrows();
}
catch { }
return true;
}
}

View File

@ -0,0 +1,60 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class GroupService : IGroup
{
private IFreeSql FreeSql { get; }
public GroupService(IFreeSql freeSql) => FreeSql = freeSql;
public List<Group> GetAll() => FreeSql.Select<Group>().ToList();
public List<string> GetGroupsByRoleId(string? roleId) => FreeSql.Ado.Query<string>("select GroupID from RoleGroup where RoleID = @roleId", new { roleId });
public List<string> GetGroupsByUserId(string? userId) => FreeSql.Ado.Query<string>("select GroupID from UserGroup where UserID = @userId", new { userId });
public bool SaveGroupsByRoleId(string? roleId, IEnumerable<string> groupIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from RoleGroup where RoleID = @roleId", new { roleId });
FreeSql.Insert(groupIds.Select(g => new RoleGroup { GroupID = g, RoleID = roleId })).ExecuteAffrows();
ret = true;
});
}
catch (Exception)
{
throw;
}
return ret;
}
public bool SaveGroupsByUserId(string? userId, IEnumerable<string> groupIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from UserGroup where UserID = @userId", new { userId });
FreeSql.Insert(groupIds.Select(g => new UserGroup { GroupID = g, UserID = userId }));
ret = true;
});
}
catch (Exception)
{
throw;
}
return ret;
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Web.Core;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class LoginService : ILogin
{
public Task<bool> Log(string userName, bool result)
{
return Task.FromResult(true);
}
}

View File

@ -0,0 +1,42 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class NavigationService : INavigation
{
private IFreeSql FreeSql { get; }
public NavigationService(IFreeSql freeSql) => FreeSql = freeSql;
public List<Navigation> GetAllMenus(string userName)
{
return FreeSql.Ado.Query<Navigation>($"select n.ID, n.ParentId, n.Name, n.[order], n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application, ln.Name as ParentName from Navigations n inner join Dicts d on n.Category = d.Code and d.Category = @Category and d.Define = @Define left join Navigations ln on n.ParentId = ln.ID inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = @UserName union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = @UserName union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = @UserName and r.RoleName = @RoleName)) nav on n.ID = nav.NavigationID ORDER BY n.Application, n.[order]", new { UserName = userName, Category = "菜单", RoleName = "Administrators", Define = EnumDictDefine.System });
}
public List<string> GetMenusByRoleId(string? roleId) => FreeSql.Ado.Query<string>("select NavigationID from NavigationRole where RoleID = @roleId", new { roleId });
public bool SaveMenusByRoleId(string? roleId, List<string> menuIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from NavigationRole where RoleID = @roleId", new { roleId });
FreeSql.Insert(menuIds.Select(g => new NavigationRole { NavigationID = g, RoleID = roleId })).ExecuteAffrows();
ret = true;
});
}
catch (Exception)
{
throw;
}
return ret;
}
}

View File

@ -0,0 +1,84 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class RoleService : IRole
{
private IFreeSql FreeSql { get; }
public RoleService(IFreeSql freeSql) => FreeSql = freeSql;
public List<Role> GetAll()
{
return FreeSql.Select<Role>().ToList();
}
public List<string> GetRolesByGroupId(string? groupId) => FreeSql.Ado.Query<string>("select RoleID from RoleGroup where GroupID = @groupId", new { groupId });
public List<string> GetRolesByMenuId(string? menuId) => FreeSql.Ado.Query<string>("select RoleID from NavigationRole where NavigationID = @menuId", new { menuId });
public List<string> GetRolesByUserId(string? userId) => FreeSql.Ado.Query<string>("select RoleID from UserRole where UserID = @userId", new { userId });
public bool SaveRolesByGroupId(string? groupId, IEnumerable<string> roleIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from RoleGroup where GroupID = @groupId", new { groupId });
FreeSql.Insert(roleIds.Select(g => new RoleGroup { RoleID = g, GroupID = groupId })).ExecuteAffrows();
ret = true;
});
}
catch (Exception)
{
throw;
}
return ret;
}
public bool SaveRolesByMenuId(string? menuId, IEnumerable<string> roleIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from NavigationRole where NavigationID = @menuId", new { menuId });
FreeSql.Insert(roleIds.Select(g => new NavigationRole { RoleID = g, NavigationID = menuId })).ExecuteAffrows();
ret = true;
});
}
catch (Exception)
{
throw;
}
return ret;
}
public bool SaveRolesByUserId(string? userId, IEnumerable<string> roleIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from UserRole where UserID = @userId", new { userId });
FreeSql.Insert(roleIds.Select(g => new UserRole { RoleID = g, UserID = userId })).ExecuteAffrows();
});
ret = true;
}
catch (Exception)
{
throw;
}
return ret;
}
}

View File

@ -0,0 +1,230 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.FreeSql.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Longbow.Security.Cryptography;
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
class UserService : IUser
{
private IFreeSql FreeSql { get; }
public UserService(IFreeSql freeSql) => FreeSql = freeSql;
public bool Authenticate(string userName, string password)
{
var user = FreeSql.Select<User>().Where(s => s.ApprovedTime != null && s.UserName == userName).ToOne(s => new User
{
DisplayName = s.DisplayName,
PassSalt = s.PassSalt,
Password = s.Password
});
var isAuth = false;
if (user != null && !string.IsNullOrEmpty(user.PassSalt))
{
isAuth = user.Password == LgbCryptography.ComputeHash(password, user.PassSalt);
}
return isAuth;
}
public List<User> GetAll()
{
return FreeSql.Select<User>().ToList();
}
public List<string> GetApps(string userName)
{
return FreeSql.Ado.Query<string>($"select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @UserName union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join Groups g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @UserName) r on ra.RoleId = r.ID union select Code from Dicts where Category = @Category and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @UserName and r.RoleName = @RoleName union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join Groups g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @UserName and r.RoleName = @RoleName)", new { UserName = userName, Category = "应用程序", RoleName = "Administrators" }).ToList();
}
/// <summary>
/// 通过用户名获得指定的前台 AppId
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public string? GetAppIdByUserName(string userName) => FreeSql.Select<User>().Where(s => s.UserName == userName).ToOne(s => s.App);
public string? GetDisplayName(string? userName)
{
return FreeSql.Select<User>().Where(s => s.UserName == userName).ToOne(s => s.DisplayName);
}
public List<string> GetRoles(string userName)
{
return FreeSql.Ado.Query<string>($"select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = @userName union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join Groups g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName = @userName", new { userName }).ToList();
}
public User? GetUserByUserName(string? userName) => string.IsNullOrEmpty(userName) ? null : FreeSql.Select<User>().Where(i => i.UserName == userName).ToOne();
public List<string> GetUsersByGroupId(string? groupId)
{
return FreeSql.Ado.Query<string>("select UserID from UserGroup where GroupID = @groupId", new { groupId }).ToList();
}
public List<string> GetUsersByRoleId(string? roleId)
{
return FreeSql.Ado.Query<string>("select UserID from UserRole where RoleID = @roleId", new { roleId }).ToList();
}
public bool SaveUser(string userName, string displayName, string password)
{
var salt = LgbCryptography.GenerateSalt();
var pwd = LgbCryptography.ComputeHash(password, salt);
var user = FreeSql.Select<User>().Where(s => s.UserName == userName).ToOne();
bool ret = default;
if (user == null)
{
// 开始事务
FreeSql.Transaction(() =>
{
user = new User()
{
Id = "0",
ApprovedBy = "System",
ApprovedTime = DateTime.Now,
DisplayName = "手机用户",
UserName = userName,
Icon = "default.jpg",
Description = "系统默认创建",
PassSalt = salt,
Password = pwd
};
FreeSql.Insert(user).ExecuteAffrows();
// 授权 Default 角色
FreeSql.Ado.ExecuteNonQuery("insert into UserRole (UserID, RoleID) select ID, (select ID from Roles where RoleName = 'Default') RoleId from Users where UserName = @userName", new { userName });
ret = true;
});
}
else
{
user.DisplayName = displayName;
user.PassSalt = salt;
user.Password = pwd;
FreeSql.Update<User>(user);
ret = true;
}
return ret;
}
public bool SaveUsersByGroupId(string? groupId, IEnumerable<string> userIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from UserGroup where GroupId = @groupId", new { groupId });
FreeSql.Insert(userIds.Select(g => new UserGroup { UserID = g, GroupID = groupId })).ExecuteAffrows();
});
ret = true;
}
catch (Exception)
{
throw;
}
return ret;
}
public bool SaveUsersByRoleId(string? roleId, IEnumerable<string> userIds)
{
var ret = false;
try
{
FreeSql.Transaction(() =>
{
FreeSql.Ado.ExecuteNonQuery("delete from UserRole where RoleID = @roleId", new { roleId });
FreeSql.Insert(userIds.Select(g => new UserRole { UserID = g, RoleID = roleId })).ExecuteAffrows();
ret = true;
});
}
catch (Exception)
{
throw;
}
return ret;
}
/// <summary>
///
/// </summary>
/// <param name="phone"></param>
/// <param name="code"></param>
/// <param name="appId"></param>
/// <param name="roles"></param>
/// <returns></returns>
public bool TryCreateUserByPhone(string phone, string code, string appId, ICollection<string> roles)
{
var ret = false;
try
{
var salt = LgbCryptography.GenerateSalt();
var pwd = LgbCryptography.ComputeHash(code, salt);
var user = FreeSql.Select<User>().Where(s => s.UserName == phone).ToOne();
if (user == null)
{
FreeSql.Transaction(() =>
{
user = new User()
{
ApprovedBy = "Mobile",
ApprovedTime = DateTime.Now,
DisplayName = "手机用户",
UserName = phone,
Icon = "default.jpg",
Description = "手机用户",
PassSalt = salt,
Password = LgbCryptography.ComputeHash(code, salt),
App = appId
};
FreeSql.Insert(user).ExecuteAffrows();
// Authorization
var roleIds = FreeSql.Ado.Query<string>("select ID from Roles where RoleName in (@roles)", new { roles });
FreeSql.Insert(roleIds.Select(g => new UserRole { RoleID = g, UserID = user.Id }));
});
}
else
{
user.PassSalt = salt;
user.Password = pwd;
FreeSql.Update<User>(user).ExecuteAffrows();
}
ret = true;
}
catch (Exception)
{
throw;
}
return ret;
}
public bool SaveApp(string userName, string app)
{
throw new NotImplementedException();
}
public bool ChangePassword(string userName, string password, string newPassword)
{
throw new NotImplementedException();
}
public bool SaveDisplayName(string userName, string displayName)
{
throw new NotImplementedException();
}
public bool SaveTheme(string userName, string theme)
{
throw new NotImplementedException();
}
public bool SaveLogo(string userName, string? logo)
{
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
<PackageReference Include="SqlSugarCore" Version="5.0.5.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,47 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootStarpAdmin.DataAccess.SqlSugar.Service;
using BootstrapBlazor.Components;
using Microsoft.Extensions.DependencyInjection.Extensions;
using SqlSugar;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// FreeSql ORM 注入服务扩展类
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// 注入 FreeSql 数据服务类
/// </summary>
/// <param name="services"></param>
/// <param name="sqlSugarBuilder"></param>
/// <returns></returns>
public static IServiceCollection AddSqlSugar(this IServiceCollection services, Action<IServiceProvider, ConnectionConfig> sqlSugarBuilder)
{
services.TryAddSingleton<ISqlSugarClient>(provider =>
{
var builder = new ConnectionConfig();
builder.IsAutoCloseConnection = true;
sqlSugarBuilder(provider, builder);
return new SqlSugarClient(builder);
});
// 增加数据服务
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
// 增加业务服务
//services.AddSingleton<IApp, AppService>();
//services.AddSingleton<IDict, DictService>();
//services.AddSingleton<IException, ExceptionService>();
//services.AddSingleton<IGroup, GroupService>();
//services.AddSingleton<ILogin, LoginService>();
//services.AddSingleton<INavigation, NavigationService>();
//services.AddSingleton<IRole, RoleService>();
//services.AddSingleton<IUser, UserService>();
return services;
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootStarpAdmin.DataAccess.SqlSugar.Extensions;
static class SqlSugarExtensions
{
}

View File

@ -0,0 +1,69 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapBlazor.Components;
using SqlSugar;
namespace BootStarpAdmin.DataAccess.SqlSugar.Service;
class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
{
private ISqlSugarClient Client { get; }
public DefaultDataService(ISqlSugarClient client) => Client = client;
/// <summary>
/// 删除方法
/// </summary>
/// <param name="models"></param>
/// <returns></returns>
public override async Task<bool> DeleteAsync(IEnumerable<TModel> models)
{
await Client.Deleteable<TModel>(models).ExecuteCommandAsync();
return true;
}
/// <summary>
/// 保存方法
/// </summary>
/// <param name="model"></param>
/// <param name="changedType"></param>
/// <returns></returns>
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
{
if (changedType == ItemChangedType.Add)
{
await Client.Insertable<TModel>(model).ExecuteCommandAsync();
}
else if (changedType == ItemChangedType.Update)
{
await Client.Updateable<TModel>(model).ExecuteCommandAsync();
}
return true;
}
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions option)
{
var ret = new QueryData<TModel>()
{
IsSorted = true,
IsFiltered = true,
IsSearch = true,
IsAdvanceSearch = option.AdvanceSearchs.Any() || option.CustomerSearchs.Any()
};
if (option.IsPage)
{
var count = 0;
ret.Items = Client.Queryable<TModel>()
.ToPageList(option.PageIndex, option.PageItems, ref count);
ret.TotalCount = count;
}
else
{
ret.Items = Client.Queryable<TModel>()
.ToList();
}
return Task.FromResult(ret);
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,38 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Caching.Services;
using Microsoft.Extensions.Caching.Memory;
namespace BootstrapAdmin.Caching;
/// <summary>
/// 缓存管理类
/// </summary>
public static class CacheManager
{
[NotNull]
private static ICacheManager? Cache { get; set; }
/// <summary>
/// 由服务调用
/// </summary>
/// <param name="cache"></param>
internal static void Init(ICacheManager cache) => Cache = cache;
/// <summary>
/// 获得或者新建数据
/// </summary>
/// <typeparam name="TItem"></typeparam>
/// <param name="key"></param>
/// <param name="valueFactory"></param>
/// <returns></returns>
public static TItem GetOrAdd<TItem>(string key, Func<ICacheEntry, TItem> valueFactory) => Cache.GetOrAdd(key, valueFactory);
/// <summary>
/// 清除指定键值缓存项
/// </summary>
/// <param name="key"></param>
public static void Clear(string? key = null) => Cache.Clear(key);
}

View File

@ -0,0 +1,34 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Caching;
using BootstrapAdmin.Caching.Services;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
///
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// 注入 ICacheManager 服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddCacheManager(this IServiceCollection services)
{
services.AddMemoryCache();
services.TryAddSingleton<ICacheManager>(provider =>
{
var cache = provider.GetRequiredService<IMemoryCache>();
var cacheManager = new DefaultCacheManager(cache);
CacheManager.Init(cacheManager);
return cacheManager;
});
return services;
}
}

View File

@ -0,0 +1,37 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using Microsoft.Extensions.Caching.Memory;
namespace BootstrapAdmin.Caching;
/// <summary>
/// CacheManager 接口类
/// </summary>
public interface ICacheManager
{
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="factory"></param>
/// <returns></returns>
T GetOrAdd<T>(string key, Func<ICacheEntry, T> factory);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> factory);
/// <summary>
///
/// </summary>
/// <param name="key"></param>
void Clear(string? key = null);
}

View File

@ -0,0 +1,79 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Primitives;
namespace BootstrapAdmin.Caching.Services;
class DefaultCacheManager : ICacheManager
{
[NotNull]
private IMemoryCache? Cache { get; set; }
/// <summary>
///
/// </summary>
public DefaultCacheManager(IMemoryCache cache) => Cache = cache;
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="factory"></param>
/// <returns></returns>
public T GetOrAdd<T>(string key, Func<ICacheEntry, T> factory) => Cache.GetOrCreate(key, entry =>
{
HandlerEntry(key, entry);
return factory(entry);
});
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="factory"></param>
/// <returns></returns>
public Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> factory) => Cache.GetOrCreate(key, entry =>
{
HandlerEntry(key, entry);
return factory(entry);
});
private static void HandlerEntry(string key, ICacheEntry entry, IChangeToken? token = null)
{
if (token != null)
{
entry.AddExpirationToken(token);
}
// 内置缓存策略 缓存相对时间 10 分钟
if (entry.AbsoluteExpiration == null && entry.SlidingExpiration == null && !entry.ExpirationTokens.Any())
{
#if DEBUG
entry.SlidingExpiration = TimeSpan.FromMilliseconds(100);
#else
entry.SlidingExpiration = TimeSpan.FromMinutes(10);
#endif
}
entry.RegisterPostEvictionCallback((key, value, reason, state) =>
{
});
}
public void Clear(string? key)
{
if (!string.IsNullOrEmpty(key))
{
Cache.Remove(key);
}
else if (Cache is MemoryCache c)
{
c.Compact(100);
}
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj" />
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,95 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.EFCore.Models;
using BootstrapAdmin.DataAccess.Models;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore
{
/// <summary>
///
/// </summary>
public class BootstrapAdminContext : DbContext
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="options"></param>
public BootstrapAdminContext(DbContextOptions<BootstrapAdminContext> options) : base(options)
{
}
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<Dict>? Dicts { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<User>? Users { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<Role>? Roles { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<UserRole>? UserRole { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<Navigation>? Navigations { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<NavigationRole>? NavigationRole { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<Group>? Groups { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<UserGroup>? UserGroup { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<RoleGroup>? RoleGroup { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
public DbSet<RoleApp>? RoleApp { get; set; }
/// <summary>
///
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
EntityConfiguration.Configure(modelBuilder);
}
}
}

View File

@ -0,0 +1,62 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.EntityFrameworkCore.ValueGeneration;
namespace BootstrapAdmin.DataAccess.EFCore;
/// <summary>
///
/// </summary>
public static class EntityConfiguration
{
/// <summary>
///
/// </summary>
/// <param name="builder"></param>
public static void Configure(this ModelBuilder builder)
{
var converter = new ValueConverter<string?, int>(
v => Convert.ToInt32(v),
v => v.ToString(),
new ConverterMappingHints(valueGeneratorFactory: (p, t) => new GuidStringGenerator()));
builder.Entity<User>().ToTable("Users");
builder.Entity<User>().Ignore(u => u.Period);
builder.Entity<User>().Ignore(u => u.NewPassword);
builder.Entity<User>().Ignore(u => u.ConfirmPassword);
builder.Entity<User>().Ignore(u => u.IsReset);
builder.Entity<User>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
builder.Entity<Role>().ToTable("Roles");
builder.Entity<Role>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
builder.Entity<Navigation>().ToTable("Navigations");
builder.Entity<Navigation>().Property(s => s.Id).HasConversion(converter!).ValueGeneratedOnAdd();
builder.Entity<Navigation>().Ignore(s => s.HasChildren);
builder.Entity<Dict>().ToTable("Dicts");
builder.Entity<Dict>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
builder.Entity<Group>().ToTable("Groups");
builder.Entity<Group>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
builder.Entity<Error>().ToTable("Exceptions");
builder.Entity<LoginLog>().ToTable("LoginLogs");
builder.Entity<Trace>().ToTable("Traces");
}
}
internal class GuidStringGenerator : ValueGenerator
{
public override bool GeneratesTemporaryValues => false;
protected override object? NextValue(EntityEntry entry) => "0";
}

View File

@ -0,0 +1,62 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.EFCore;
using BootstrapAdmin.DataAccess.EFCore.Services;
using BootstrapAdmin.Web.Core;
using BootstrapBlazor.Components;
using Microsoft.EntityFrameworkCore;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
///
/// </summary>
public static class ServicesExtensions
{
/// <summary>
///
/// </summary>
/// <param name="services"></param>
/// <param name="optionConfigure"></param>
/// <param name="lifetime"></param>
/// <returns></returns>
public static IServiceCollection AddEFCoreDataAccessServices(this IServiceCollection services, Action<IServiceProvider, DbContextOptionsBuilder> optionConfigure, ServiceLifetime lifetime = ServiceLifetime.Singleton)
{
services.AddDbContextFactory<BootstrapAdminContext>(optionConfigure, lifetime);
services.AddServices();
return services;
}
/// <summary>
///
/// </summary>
/// <param name="services"></param>
/// <param name="optionConfigure"></param>
/// <param name="lifetime"></param>
/// <returns></returns>
public static IServiceCollection AddEFCoreDataAccessServices(this IServiceCollection services, Action<DbContextOptionsBuilder> optionConfigure, ServiceLifetime lifetime = ServiceLifetime.Singleton)
{
services.AddDbContextFactory<BootstrapAdminContext>(optionConfigure, lifetime);
services.AddServices();
return services;
}
private static IServiceCollection AddServices(this IServiceCollection services)
{
// 增加数据服务
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
// 增加缓存服务
services.AddCacheManager();
services.AddSingleton<INavigation, NavigationService>();
services.AddSingleton<IDict, DictService>();
services.AddSingleton<IUser, UserService>();
services.AddSingleton<IRole, RoleService>();
services.AddSingleton<IGroup, GroupService>();
services.AddSingleton<ILogin, LoginService>();
return services;
}
}

View File

@ -0,0 +1,21 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootstrapAdmin.DataAccess.EFCore.Models;
/// <summary>
///
/// </summary>
public class NavigationRole
{
/// <summary>
///
/// </summary>
public string? NavigationId { get; set; }
/// <summary>
///
/// </summary>
public string? RoleId { get; set; }
}

View File

@ -0,0 +1,21 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootstrapAdmin.DataAccess.EFCore.Models;
/// <summary>
///
/// </summary>
public class RoleApp
{
/// <summary>
///
/// </summary>
public string? AppID { get; set; }
/// <summary>
///
/// </summary>
public string? RoleID { get; set; }
}

View File

@ -0,0 +1,21 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootstrapAdmin.DataAccess.EFCore.Models;
/// <summary>
///
/// </summary>
public class RoleGroup
{
/// <summary>
///
/// </summary>
public string? RoleId { get; set; }
/// <summary>
///
/// </summary>
public string? GroupId { get; set; }
}

View File

@ -0,0 +1,21 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootstrapAdmin.DataAccess.EFCore.Models;
/// <summary>
///
/// </summary>
public class UserGroup
{
/// <summary>
///
/// </summary>
public string? UserId { get; set; }
/// <summary>
///
/// </summary>
public string? GroupId { get; set; }
}

View File

@ -0,0 +1,21 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootstrapAdmin.DataAccess.EFCore.Models;
/// <summary>
///
/// </summary>
public class UserRole
{
/// <summary>
///
/// </summary>
public string? UserId { get; set; }
/// <summary>
///
/// </summary>
public string? RoleId { get; set; }
}

View File

@ -0,0 +1,60 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.EFCore.Models;
using BootstrapAdmin.Web.Core;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
///
/// </summary>
public class AppService : IApp
{
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
/// <param name="dbFactory"></param>
public AppService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<string> GetAppsByRoleId(string? roleId)
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.RoleApp.Where(s => s.RoleID == roleId).Select(s => s.AppID!).AsNoTracking().ToList();
}
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <param name="appIds"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool SaveAppsByRoleId(string? roleId, IEnumerable<string> appIds)
{
var ret = false;
try
{
using var dbcontext = DbFactory.CreateDbContext();
dbcontext.Database.ExecuteSqlRaw("delete from RoleApp where RoleID = {0}", roleId!);
dbcontext.AddRange(appIds.Select(g => new RoleApp { AppID = g, RoleID = roleId }));
ret = dbcontext.SaveChanges() > 0;
}
catch (Exception)
{
throw;
}
return ret;
}
}

View File

@ -0,0 +1,94 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapBlazor.Components;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
/// EFCore ORM 的 IDataService 接口实现
/// </summary>
class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
{
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
/// 构造函数
/// </summary>
public DefaultDataService(IDbContextFactory<BootstrapAdminContext> factory) => DbFactory = factory;
/// <summary>
/// 删除方法
/// </summary>
/// <param name="models"></param>
/// <returns></returns>
public override async Task<bool> DeleteAsync(IEnumerable<TModel> models)
{
// 通过模型获取主键列数据
// 支持批量删除
var context = DbFactory.CreateDbContext();
context.RemoveRange(models);
return await context.SaveChangesAsync() > 0;
}
/// <summary>
/// 保存方法
/// </summary>
/// <param name="model"></param>
/// <param name="changedType"></param>
/// <returns></returns>
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
{
var context = DbFactory.CreateDbContext();
if (changedType == ItemChangedType.Add)
{
context.Entry(model).State = EntityState.Added;
}
else
{
context.Entry(model).State = EntityState.Modified;
}
return await context.SaveChangesAsync() > 0;
}
/// <summary>
/// 查询方法
/// </summary>
/// <param name="option"></param>
/// <returns></returns>
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions option)
{
var context = DbFactory.CreateDbContext();
var ret = new QueryData<TModel>()
{
IsSorted = true,
IsFiltered = true,
IsSearch = true
};
var filters = option.Filters.Concat(option.Searchs).Concat(option.CustomerSearchs);
if (option.IsPage)
{
var items = context.Set<TModel>()
.Where(filters.GetFilterLambda<TModel>(), filters.Any())
.Sort(option.SortName!, option.SortOrder, !string.IsNullOrEmpty(option.SortName))
.Count(out var count)
.Page((option.PageIndex - 1) * option.PageItems, option.PageItems);
ret.TotalCount = count;
ret.Items = items;
}
else
{
var items = context.Set<TModel>()
.Where(filters.GetFilterLambda<TModel>(), filters.Any())
.Sort(option.SortName!, option.SortOrder, !string.IsNullOrEmpty(option.SortName))
.Count(out var count);
ret.TotalCount = count;
ret.Items = items;
}
return Task.FromResult(ret);
}
}

View File

@ -0,0 +1,465 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Caching;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using BootstrapBlazor.Components;
using Longbow.Security.Cryptography;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System.Data.Common;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
class DictService : IDict
{
private const string DictServiceCacheKey = "DictService-GetAll";
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
private string AppId { get; set; }
/// <summary>
///
/// </summary>
/// <param name="factory"></param>
/// <param name="configuration"></param>
public DictService(IDbContextFactory<BootstrapAdminContext> factory, IConfiguration configuration)
{
DbFactory = factory;
AppId = configuration.GetValue("AppId", "BA");
}
public List<Dict> GetAll()
{
using var context = DbFactory.CreateDbContext();
return CacheManager.GetOrAdd(DictServiceCacheKey, entry => context.Dicts.AsNoTracking().ToList());
}
public Dictionary<string, string> GetApps()
{
var dicts = GetAll();
return dicts.Where(d => d.Category == "应用程序").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
}
public Dictionary<string, string> GetLogins()
{
var dicts = GetAll();
return dicts.Where(d => d.Category == "系统首页").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
}
public Dictionary<string, string> GetThemes()
{
var dicts = GetAll();
return dicts.Where(d => d.Category == "网站样式").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
}
public string GetWebFooter()
{
var dicts = GetAll();
var title = "网站页脚";
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
if (!string.IsNullOrEmpty(name))
{
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站页脚") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站页脚");
title = dict?.Code ?? "网站标题";
}
return title;
}
public string GetWebTitle()
{
var dicts = GetAll();
var title = "网站标题";
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
if (!string.IsNullOrEmpty(name))
{
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站标题") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站标题");
title = dict?.Code ?? "网站标题";
}
return title;
}
public bool IsDemo()
{
var dicts = GetAll();
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "演示系统" && d.Define == EnumDictDefine.System)?.Code ?? "0";
return code == "1";
}
public bool SaveDemo(bool isDemo) => SaveDict(new Dict
{
Category = "网站设置",
Name = "演示系统",
Code = isDemo ? "1" : "0",
Define = EnumDictDefine.System
});
public bool AuthenticateDemo(string code)
{
var ret = false;
if (!string.IsNullOrEmpty(code))
{
var dicts = GetAll();
var salt = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "授权盐值" && d.Define == EnumDictDefine.System)?.Code;
var authCode = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "哈希结果" && d.Define == EnumDictDefine.System)?.Code;
if (!string.IsNullOrEmpty(salt))
{
ret = LgbCryptography.ComputeHash(code, salt) == authCode;
}
}
return ret;
}
public bool SaveHealthCheck(bool enable = true) => SaveDict(new Dict
{
Category = "网站设置",
Name = "健康检查",
Code = enable ? "1" : "0",
Define = EnumDictDefine.System
});
public int GetCookieExpiresPeriod()
{
var dicts = GetAll();
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "Cookie保留时长" && d.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(code, out var ret);
return ret;
}
public string GetCurrentLogin()
{
var dicts = GetAll();
return dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "登录界面" && d.Define == EnumDictDefine.System)?.Code ?? "Login";
}
public bool SaveLogin(string login) => SaveDict(new Dict { Category = "网站设置", Name = "登录界面", Code = login });
public bool SaveTheme(string theme) => SaveDict(new Dict { Category = "网站设置", Name = "使用样式", Code = theme });
public bool SaveWebTitle(string title) => SaveDict(new Dict { Category = "网站设置", Name = "网站标题", Code = title });
public bool SaveWebFooter(string footer) => SaveDict(new Dict { Category = "网站设置", Name = "网站页脚", Code = footer });
public bool SaveCookieExpiresPeriod(int expiresPeriod) => SaveDict(new Dict { Category = "网站设置", Name = "Cookie保留时长", Code = expiresPeriod.ToString() });
public string? GetProfileUrl(string appId) => GetUrlByName(appId, "个人中心地址");
public string? GetSettingsUrl(string appId) => GetUrlByName(appId, "系统设置地址");
public string? GetNotificationUrl(string appId) => GetUrlByName(appId, "系统通知地址");
public string? GetIpLocatorName()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "IP地理位置接口" && s.Define == EnumDictDefine.System)?.Code;
}
public string? GetIpLocatorUrl(string? name)
{
var dicts = GetAll();
return string.IsNullOrWhiteSpace(name) ? null : dicts.FirstOrDefault(s => s.Category == "地理位置" && s.Name == name && s.Define == EnumDictDefine.System)?.Code;
}
public bool SavDefaultApp(bool enabled) => SaveDict(new Dict
{
Category = "网站设置",
Name = "默认应用程序",
Code = enabled ? "1" : "0",
Define = EnumDictDefine.System
});
public string GetIconFolderPath()
{
var dicts = GetAll();
return dicts.FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == EnumDictDefine.System)?.Code ?? "/images/uploder/";
}
public string GetDefaultIcon()
{
var dicts = GetAll();
return dicts.FirstOrDefault(d => d.Name == "头像文件" && d.Category == "头像地址" && d.Define == EnumDictDefine.System)?.Code ?? "default.jpg";
}
public string? GetHomeUrlByAppId(string appId)
{
var dicts = GetAll();
return dicts.FirstOrDefault(d => d.Category == "应用首页" && d.Name.Equals(appId, StringComparison.OrdinalIgnoreCase) && d.Define == EnumDictDefine.System)?.Code;
}
public bool GetEnableDefaultApp()
{
var dicts = GetAll();
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "默认应用程序")?.Code ?? "0";
return code == "1";
}
public bool GetAppSiderbar()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "侧边栏状态" && s.Define == EnumDictDefine.System)?.Code == "1";
}
public bool SaveAppSiderbar(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "侧边栏状态", Code = value ? "1" : "0" });
public bool GetAppTitle()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "卡片标题状态" && s.Define == EnumDictDefine.System)?.Code == "1";
}
public bool SaveAppTitle(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "卡片标题状态", Code = value ? "1" : "0" });
public bool GetAppFixHeader()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "固定表头" && s.Define == EnumDictDefine.System)?.Code == "1";
}
public bool SaveAppFixHeader(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "固定表头", Code = value ? "1" : "0" });
public bool GetAppHealthCheck()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "健康检查" && s.Define == EnumDictDefine.System)?.Code == "1";
}
public bool SaveAppHealthCheck(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "健康检查", Code = value ? "1" : "0" });
public bool GetAppMobileLogin()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "短信验证码登录" && s.Define == EnumDictDefine.System)?.Code == "1";
}
public bool SaveAppMobileLogin(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "短信验证码登录", Code = value ? "1" : "0" });
public bool GetAppOAuthLogin()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "OAuth 认证登录" && s.Define == EnumDictDefine.System)?.Code == "1";
}
public bool SaveAppOAuthLogin(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "OAuth 认证登录", Code = value ? "1" : "0" });
public bool GetAutoLockScreen()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "自动锁屏" && s.Define == EnumDictDefine.System)?.Code == "1";
}
public bool SaveAutoLockScreen(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "自动锁屏", Code = value ? "1" : "0" });
public int GetAutoLockScreenInterval()
{
var dicts = GetAll();
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "自动锁屏时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(value, out var ret);
return ret;
}
public bool SaveAutoLockScreenInterval(int value) => SaveDict(new Dict { Category = "网站设置", Name = "自动锁屏时长", Code = value.ToString() });
public Dictionary<string, string> GetIpLocators()
{
var dicts = GetAll();
return dicts.Where(d => d.Category == "地理位置服务").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).OrderBy(i => i.Value).ToDictionary(i => i.Key, i => i.Value);
}
public string? GetIpLocator()
{
var dicts = GetAll();
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "IP地理位置接口" && s.Define == EnumDictDefine.System)?.Code;
}
public bool SaveCurrentIp(string value) => SaveDict(new Dict { Category = "网站设置", Name = "IP地理位置接口", Code = value });
public int GetCookieExpired()
{
var dicts = GetAll();
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "Cookie保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(value, out var ret);
return ret;
}
public bool SaveCookieExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "Cookie保留时长", Code = value.ToString() });
public int GetExceptionExpired()
{
var dicts = GetAll();
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "程序异常保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(value, out var ret);
return ret; ;
}
public bool SaveExceptionExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "程序异常保留时长", Code = value.ToString() });
public int GetOperateExpired()
{
var dicts = GetAll();
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "操作日志保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(value, out var ret);
return ret; ;
}
public bool SaveOperateExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "操作日志保留时长", Code = value.ToString() });
public int GetLoginExpired()
{
var dicts = GetAll();
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "登录日志保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(value, out var ret);
return ret; ;
}
public bool SaveLoginExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "登录日志保留时长", Code = value.ToString() });
public int GetAccessExpired()
{
var dicts = GetAll();
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "访问日志保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(value, out var ret);
return ret; ;
}
public bool SaveAccessExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "访问日志保留时长", Code = value.ToString() });
public int GetIPCacheExpired()
{
var dicts = GetAll();
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "IP请求缓存时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
_ = int.TryParse(value, out var ret);
return ret; ;
}
public bool SaveIPCacheExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "IP请求缓存时长", Code = value.ToString() });
public Dictionary<string, string>? GetClients()
{
var dicts = GetAll();
return dicts.Where(s => s.Category == "应用程序" && s.Code != "BA").ToDictionary(s => s.Name, s => s.Code);
}
public string GetClientUrl(string name)
{
var dicts = GetAll();
return dicts.Where(s => s.Category == "应用首页" && s.Name == name).FirstOrDefault()?.Code ?? "";
}
public bool ExistsAppId(string appId)
{
var dicts = GetAll();
return dicts.Exists(s => s.Category == "应用程序" && s.Code == appId);
}
public bool SaveClient(ClientApp client)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = false;
if (!string.IsNullOrEmpty(client.AppId))
{
DeleteClient(client.AppId);
try
{
var items = new List<Dict>()
{
new Dict { Category = "应用程序", Name = client.AppName, Code = client.AppId, Define = EnumDictDefine.System },
new Dict { Category = "应用首页", Name = client.AppId, Code = client.HomeUrl, Define = EnumDictDefine.System },
new Dict { Category = client.AppId, Name = "网站页脚", Code = client.Footer, Define = EnumDictDefine.Customer },
new Dict { Category = client.AppId, Name = "网站标题", Code = client.Title, Define = EnumDictDefine.Customer },
new Dict { Category = client.AppId, Name = "favicon", Code = client.Favicon, Define = EnumDictDefine.Customer },
new Dict { Category = client.AppId, Name = "网站图标", Code = client.Icon, Define = EnumDictDefine.Customer },
new Dict { Category = client.AppId, Name = "个人中心地址", Code = client.ProfileUrl, Define = EnumDictDefine.Customer },
new Dict { Category = client.AppId, Name = "系统设置地址", Code = client.SettingsUrl, Define = EnumDictDefine.Customer },
new Dict { Category = client.AppId, Name = "系统通知地址", Code = client.NotificationUrl, Define = EnumDictDefine.Customer }
};
dbcontext.AddRange(items);
dbcontext.SaveChanges();
ret = true;
}
catch (DbException)
{
throw;
}
}
return ret;
}
public ClientApp GetClient(string appId)
{
var dicts = GetAll();
return new ClientApp()
{
AppId = appId,
AppName = dicts.FirstOrDefault(s => s.Category == "应用程序" && s.Code == appId)?.Name,
HomeUrl = dicts.FirstOrDefault(s => s.Category == "应用首页" && s.Name == appId)?.Code,
ProfileUrl = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "个人中心地址")?.Code,
SettingsUrl = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "系统设置地址")?.Code,
NotificationUrl = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "系统通知地址")?.Code,
Title = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "网站标题")?.Code,
Footer = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "网站页脚")?.Code,
Icon = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "网站图标")?.Code,
Favicon = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "favicon")?.Code,
};
}
public bool DeleteClient(string appId)
{
using var dbcontext = DbFactory.CreateDbContext();
bool ret;
try
{
dbcontext.Database.BeginTransaction();
dbcontext.Database.ExecuteSqlRaw("delete Dicts where Category={0} and Name={1} and Define={2}", "应用首页", appId, EnumDictDefine.System);
dbcontext.Database.ExecuteSqlRaw("delete Dicts where Category={0} and Name={1} and Define={2}", "应用程序", appId, EnumDictDefine.System);
dbcontext.Database.ExecuteSqlRaw("delete Dicts where Category=@{0} and Name in ({1})", new
{
Category = appId,
Names = new List<string>
{
"网站标题",
"网站页脚",
"favicon",
"网站图标",
"个人中心地址",
"系统设置地址",
"系统通知地址"
}
});
dbcontext.Database.CommitTransaction();
ret = true;
}
catch (Exception)
{
dbcontext.Database.RollbackTransaction();
throw;
}
return ret;
}
private bool SaveDict(Dict dict)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = dbcontext.Database.ExecuteSqlRaw("update Dicts set Code = {1} where Category = {2} and Name = {0}", new[] { dict.Name, dict.Code, dict.Category }!) > 0;
if (ret)
{
// 更新缓存
CacheManager.Clear(DictServiceCacheKey);
}
return ret;
}
private string? GetUrlByName(string appId, string dictName)
{
string? url = null;
var dicts = GetAll();
var appName = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == appId && d.Define == EnumDictDefine.System)?.Name;
if (!string.IsNullOrEmpty(appName))
{
url = dicts.FirstOrDefault(d => d.Category == appName && d.Name == dictName && d.Define == EnumDictDefine.Customer)?.Code;
}
return url;
}
}

View File

@ -0,0 +1,87 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
///
/// </summary>
public class ExceptionService : IException
{
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
/// <param name="dbFactory"></param>
public ExceptionService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
/// <summary>
///
/// </summary>
/// <param name="searchText"></param>
/// <param name="filter"></param>
/// <param name="pageIndex"></param>
/// <param name="pageItems"></param>
/// <param name="sortList"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public (IEnumerable<Error> Items, int ItemsCount) GetAll(string? searchText, ExceptionFilter filter, int pageIndex, int pageItems, List<string> sortList)
{
using var dbcontext = DbFactory.CreateDbContext();
var items = dbcontext.Set<Error>();
if (!string.IsNullOrEmpty(searchText))
{
items.Where(s => s.Message!.Contains(searchText) || s.StackTrace!.Contains(searchText) || s.ErrorPage!.Contains(searchText));
}
if (!string.IsNullOrEmpty(filter.Category))
{
items.Where(s => s.Category!.Contains(filter.Category));
}
if (!string.IsNullOrEmpty(filter.UserId))
{
items.Where(s => s.UserId!.Contains(filter.UserId));
}
if (!string.IsNullOrEmpty(filter.ErrorPage))
{
items.Where(s => s.ErrorPage!.Contains(filter.ErrorPage));
}
items.Where(s => s.LogTime >= filter.Star && s.LogTime <= filter.End);
if (sortList.Any())
{
items.Sort(sortList);
}
else
{
items.OrderByDescending(s => s.LogTime);
}
var data = items.Take(pageItems).Skip(pageItems * (pageIndex - 1)).AsNoTracking().ToList();
return (data, items.Count());
}
/// <summary>
///
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool Log(Error exception)
{
using var dbcontext = DbFactory.CreateDbContext();
dbcontext.Add(exception);
return dbcontext.SaveChanges() > 0;
}
}

View File

@ -0,0 +1,156 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Caching;
using BootstrapAdmin.DataAccess.EFCore.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Primitives;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
///
/// </summary>
public class GroupService : IGroup, IDisposable
{
private const string GroupServiceGetAllCacheKey = "GroupService-GetAll";
private const string GroupServiceGetGroupsByUserIdCacheKey = "GroupService-GetGroupsByUserId";
private const string GroupServiceGetGroupsByRoleIdCacheKey = "GroupService-GetGroupsByRoleId";
private CancellationTokenSource? GetGroupsByUserIdCancellationTokenSource { get; set; }
private CancellationTokenSource? GetGroupsByRoleIdCancellationTokenSource { get; set; }
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
/// <param name="dbFactory"></param>
public GroupService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<Group> GetAll()
{
using var dbcontext = DbFactory.CreateDbContext();
return CacheManager.GetOrAdd(GroupServiceGetAllCacheKey, entry => dbcontext.Groups.AsNoTracking().ToList());
}
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public List<string> GetGroupsByRoleId(string? roleId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByRoleIdCacheKey}-{roleId}", entry =>
{
using var dbcontext = DbFactory.CreateDbContext();
GetGroupsByRoleIdCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(10));
var token = new CancellationChangeToken(GetGroupsByRoleIdCancellationTokenSource.Token);
entry.ExpirationTokens.Add(token);
return dbcontext.RoleGroup.Where(s => s.RoleId == roleId).Select(s => s.GroupId!).ToList();
});
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public List<string> GetGroupsByUserId(string? userId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByUserIdCacheKey}-{userId}", entry =>
{
using var dbcontext = DbFactory.CreateDbContext();
GetGroupsByUserIdCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(10));
var token = new CancellationChangeToken(GetGroupsByUserIdCancellationTokenSource.Token);
entry.ExpirationTokens.Add(token);
return dbcontext.Set<UserGroup>().FromSqlRaw("select GroupID from UserGroup where UserID = {0}", userId!).Select(s => s.GroupId!).ToList();
});
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <param name="groupIds"></param>
/// <returns></returns>
public bool SaveGroupsByRoleId(string? roleId, IEnumerable<string> groupIds)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = false;
try
{
dbcontext.Database.ExecuteSqlRaw("delete from RoleGroup where RoleID = {0}", roleId!);
dbcontext.AddRange(groupIds.Select(g => new RoleGroup { GroupId = g, RoleId = roleId }));
dbcontext.SaveChanges();
ret = true;
}
catch (Exception)
{
throw;
}
if (ret)
{
// reset cache
GetGroupsByRoleIdCancellationTokenSource?.Cancel();
}
return ret;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="groupIds"></param>
/// <returns></returns>
public bool SaveGroupsByUserId(string? userId, IEnumerable<string> groupIds)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = false;
try
{
dbcontext.Database.ExecuteSqlRaw("delete from UserGroup where UserID = {0}", userId!);
dbcontext.AddRange(groupIds.Select(g => new UserGroup { GroupId = g, UserId = userId }));
dbcontext.SaveChanges();
ret = true;
}
catch (Exception)
{
throw;
}
if (ret)
{
GetGroupsByUserIdCancellationTokenSource?.Cancel();
}
return ret;
}
private void Dispose(bool disposing)
{
if (disposing)
{
GetGroupsByRoleIdCancellationTokenSource?.Cancel();
GetGroupsByRoleIdCancellationTokenSource?.Dispose();
GetGroupsByUserIdCancellationTokenSource?.Cancel();
GetGroupsByUserIdCancellationTokenSource?.Dispose();
}
}
/// <summary>
///
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}

View File

@ -0,0 +1,53 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
///
/// </summary>
public class LoginService : ILogin
{
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
public LoginService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="IP"></param>
/// <param name="OS"></param>
/// <param name="browser"></param>
/// <param name="address"></param>
/// <param name="userAgent"></param>
/// <param name="result"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool Log(string userName, string? IP, string? OS, string? browser, string? address, string? userAgent, bool result)
{
using var dbcontext = DbFactory.CreateDbContext();
var loginUser = new LoginLog()
{
UserName = userName,
LoginTime = DateTime.Now,
Ip = IP,
City = address,
OS = OS,
Browser = browser,
UserAgent = userAgent,
Result = result ? "登录成功" : "登录失败"
};
dbcontext.Add(loginUser);
return dbcontext.SaveChanges() > 0;
}
}

View File

@ -0,0 +1,68 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Caching;
using BootstrapAdmin.DataAccess.EFCore.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services
{
/// <summary>
///
/// </summary>
class NavigationService : INavigation
{
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
/// <param name="factory"></param>
public NavigationService(IDbContextFactory<BootstrapAdminContext> factory) => DbFactory = factory;
/// <summary>
/// 获得指定用户名可访问的所有菜单集合
/// </summary>
/// <param name="userName">当前用户名</param>
/// <returns>未层次化的菜单集合</returns>
public List<Navigation> GetAllMenus(string userName)
{
return CacheManager.GetOrAdd($"{nameof(NavigationService)}-{nameof(GetAllMenus)}-{userName}", entry =>
{
using var context = DbFactory.CreateDbContext();
return context.Set<Navigation>().FromSqlRaw("select n.ID, n.ParentId, n.Name, n.[order], n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application from Navigations n inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = {0} union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = {0} union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = {0} and r.RoleName = {1})) nav on n.ID = nav.NavigationID ORDER BY n.Application, n.[order]", new[] { userName, "Administrators" }).AsNoTracking().ToList();
});
}
public List<string> GetMenusByRoleId(string? roleId)
{
using var context = DbFactory.CreateDbContext();
return context.NavigationRole.Where(s => s.RoleId == roleId).Select(s => s.NavigationId!).AsNoTracking().ToList();
}
public bool SaveMenusByRoleId(string? roleId, List<string> menuIds)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = false;
try
{
dbcontext.Database.ExecuteSqlRaw("delete from NavigationRole where RoleID = {0}", roleId!);
dbcontext.Set<NavigationRole>().AddRange(menuIds.Select(g => new NavigationRole { NavigationId = g, RoleId = roleId }));
dbcontext.SaveChanges();
ret = true;
CacheManager.Clear($"{nameof(NavigationService)}-{nameof(GetAllMenus)}-*");
}
catch (Exception)
{
throw;
}
return ret;
}
}
}

View File

@ -0,0 +1,167 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.Caching;
using BootstrapAdmin.DataAccess.EFCore.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
///
/// </summary>
public class RoleService : IRole
{
private const string RoleServiceGetAllCacheKey = "RoleService-GetAll";
private const string RoleServiceGetRolesByUserIdCacheKey = "RoleService-GetRolesByUserId";
private const string RoleServiceGetRolesByGroupIdCacheKey = "RoleService-GetRolesByGroupId";
private CancellationTokenSource? GetRolesByUserIdCancellationTokenSource { get; set; }
private CancellationTokenSource? GetRolesByGroupIdCancellationTokenSource { get; set; }
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
/// <param name="dbFactory"></param>
public RoleService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<Role> GetAll()
{
return CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry =>
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.Roles.ToList();
});
}
/// <summary>
///
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>
public List<string> GetRolesByGroupId(string? groupId)
{
return CacheManager.GetOrAdd($"{RoleServiceGetRolesByGroupIdCacheKey}-{groupId}", entry =>
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.RoleGroup.Where(s => s.GroupId == groupId).Select(s => s.RoleId!).AsNoTracking().ToList();
});
}
/// <summary>
///
/// </summary>
/// <param name="menuId"></param>
/// <returns></returns>
public List<string> GetRolesByMenuId(string? menuId)
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.NavigationRole.Where(s => s.NavigationId == menuId).Select(s => s.RoleId!).AsNoTracking().ToList();
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public List<string> GetRolesByUserId(string? userId)
{
return CacheManager.GetOrAdd($"{RoleServiceGetRolesByUserIdCacheKey}-{userId}", entry =>
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.UserRole.Where(s => s.UserId == userId).Select(s => s.RoleId!).AsNoTracking().ToList();
});
}
/// <summary>
///
/// </summary>
/// <param name="groupId"></param>
/// <param name="roleIds"></param>
/// <returns></returns>
public bool SaveRolesByGroupId(string? groupId, IEnumerable<string> roleIds)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = false;
try
{
dbcontext.Database.ExecuteSqlRaw("delete from RoleGroup where GroupID = {0}", groupId!);
dbcontext.AddRange(roleIds.Select(g => new RoleGroup { RoleId = g, GroupId = groupId }));
dbcontext.SaveChanges();
ret = true;
}
catch (Exception)
{
throw;
}
return ret;
}
/// <summary>
///
/// </summary>
/// <param name="menuId"></param>
/// <param name="roleIds"></param>
/// <returns></returns>
public bool SaveRolesByMenuId(string? menuId, IEnumerable<string> roleIds)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = false;
try
{
dbcontext.Database.ExecuteSqlRaw("delete from NavigationRole where NavigationID = {0}", menuId!);
dbcontext.AddRange(roleIds.Select(g => new NavigationRole { RoleId = g, NavigationId = menuId }));
dbcontext.SaveChanges();
ret = true;
}
catch (Exception)
{
throw;
}
return ret;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="roleIds"></param>
/// <returns></returns>
public bool SaveRolesByUserId(string? userId, IEnumerable<string> roleIds)
{
using var dbcontext = DbFactory.CreateDbContext();
var ret = false;
try
{
dbcontext.Database.ExecuteSqlRaw("delete from UserRole where UserID = {0}", userId!);
dbcontext.AddRange(roleIds.Select(g => new UserRole { RoleId = g, UserId = userId }));
dbcontext.SaveChanges();
ret = true;
}
catch (Exception)
{
throw;
}
return ret;
}
}

View File

@ -0,0 +1,87 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
///
/// </summary>
public class TraceService : ITrace
{
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
/// <param name="dbFactory"></param>
public TraceService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
/// <summary>
///
/// </summary>
/// <param name="searchText"></param>
/// <param name="filter"></param>
/// <param name="pageIndex"></param>
/// <param name="pageItems"></param>
/// <param name="sortList"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public (IEnumerable<Trace> Items, int ItemsCount) GetAll(string? searchText, TraceFilter filter, int pageIndex, int pageItems, List<string> sortList)
{
using var dbcontext = DbFactory.CreateDbContext();
var items = dbcontext.Set<Trace>();
if (!string.IsNullOrEmpty(searchText))
{
items.Where(s => s.UserName!.Contains(searchText) || s.Ip!.Contains(searchText) || s.RequestUrl!.Contains(searchText));
}
if (!string.IsNullOrEmpty(filter.UserName))
{
items.Where(s => s.UserName!.Contains(filter.UserName));
}
if (!string.IsNullOrEmpty(filter.Ip))
{
items.Where(s => s.Ip!.Contains(filter.Ip));
}
if (!string.IsNullOrEmpty(filter.RequestUrl))
{
items.Where(s => s.RequestUrl!.Contains(filter.RequestUrl));
}
items.Where(s => s.LogTime >= filter.Star && s.LogTime <= filter.End);
if (sortList.Any())
{
items.Sort(sortList);
}
else
{
items.OrderByDescending(s => s.LogTime);
}
var data = items.Take(pageItems).Skip(pageItems * (pageIndex - 1)).AsNoTracking().ToList();
return (data, items.Count());
}
/// <summary>
///
/// </summary>
/// <param name="trace"></param>
/// <exception cref="NotImplementedException"></exception>
public void Log(Trace trace)
{
using var dbcontext = DbFactory.CreateDbContext();
dbcontext.Add(trace);
dbcontext.SaveChanges();
}
}

View File

@ -0,0 +1,323 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.EFCore.Models;
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using Longbow.Security.Cryptography;
using Microsoft.EntityFrameworkCore;
namespace BootstrapAdmin.DataAccess.EFCore.Services;
/// <summary>
///
/// </summary>
public class UserService : IUser
{
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
/// <summary>
///
/// </summary>
/// <param name="factory"></param>
public UserService(IDbContextFactory<BootstrapAdminContext> factory) => DbFactory = factory;
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<User> GetAll()
{
using var context = DbFactory.CreateDbContext();
return context.Users.AsNoTracking().ToList();
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool Authenticate(string userName, string password)
{
var isAuth = false;
using var context = DbFactory.CreateDbContext();
var user = context.Users.Where(s => s.ApprovedTime != null).FirstOrDefault(x => x.UserName == userName);
if (user != null && !string.IsNullOrEmpty(user.PassSalt))
{
isAuth = user.Password == LgbCryptography.ComputeHash(password, user.PassSalt);
}
return isAuth;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public List<string> GetApps(string userName)
{
using var context = DbFactory.CreateDbContext();
return context.Dicts.FromSqlRaw("select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = {0} union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join [Groups] g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = {0}) r on ra.RoleId = r.ID union select Code from Dicts where Category = {1} and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = {0} and r.RoleName = {2} union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join [Groups] g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = {0} and r.RoleName = {2})", new[] { userName, "应用程序", "Administrators" }).Select(s => s.Code).AsNoTracking().ToList();
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public string? GetDisplayName(string? userName)
{
using var context = DbFactory.CreateDbContext();
return string.IsNullOrEmpty(userName) ? "" : context.Users.FirstOrDefault(s => s.UserName == userName)?.DisplayName;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public List<string> GetRoles(string userName)
{
using var context = DbFactory.CreateDbContext();
return context.Roles.FromSqlRaw("select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = {0} union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join [Groups] g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName = {0}", userName).Select(s => s.RoleName).AsNoTracking().ToList();
}
/// <summary>
///
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>
public List<string> GetUsersByGroupId(string? groupId)
{
using var context = DbFactory.CreateDbContext();
return context.UserGroup.Where(s => s.GroupId == groupId).Select(s => s.UserId!).AsNoTracking().ToList();
}
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public List<string> GetUsersByRoleId(string? roleId)
{
using var context = DbFactory.CreateDbContext();
return context.UserRole.Where(s => s.RoleId == roleId).Select(s => s.UserId!).AsNoTracking().ToList();
}
/// <summary>
///
/// </summary>
/// <param name="groupId"></param>
/// <param name="userIds"></param>
/// <returns></returns>
public bool SaveUsersByGroupId(string? groupId, IEnumerable<string> userIds)
{
using var dbcontext = DbFactory.CreateDbContext();
dbcontext.Database.ExecuteSqlRaw("delete from UserGroup where GroupId = {0}", groupId!);
dbcontext.AddRange(userIds.Select(g => new UserGroup { UserId = g, GroupId = groupId }));
dbcontext.SaveChanges();
return true;
}
/// <summary>
///
/// </summary>
/// <param name="roleId"></param>
/// <param name="userIds"></param>
/// <returns></returns>
public bool SaveUsersByRoleId(string? roleId, IEnumerable<string> userIds)
{
using var dbcontext = DbFactory.CreateDbContext();
dbcontext.Database.ExecuteSqlRaw("delete from UserRole where RoleID = {0}", roleId!);
dbcontext.AddRange(userIds.Select(g => new UserRole { UserId = g, RoleId = roleId }));
dbcontext.SaveChanges();
return true;
}
/// <summary>
///
/// </summary>
/// <param name="phone"></param>
/// <param name="code"></param>
/// <param name="appId"></param>
/// <param name="roles"></param>
/// <returns></returns>
public bool TryCreateUserByPhone(string phone, string code, string appId, ICollection<string> roles)
{
var ret = false;
using var dbcontext = DbFactory.CreateDbContext();
var salt = LgbCryptography.GenerateSalt();
var pwd = LgbCryptography.ComputeHash(code, salt);
var user = GetAll().FirstOrDefault(user => user.UserName == phone);
if (user == null)
{
user = new User()
{
ApprovedBy = "Mobile",
ApprovedTime = DateTime.Now,
DisplayName = "手机用户",
UserName = phone,
Icon = "default.jpg",
Description = "手机用户",
App = appId
};
dbcontext.Add(user);
// Authorization
var roleIds = dbcontext.Roles.Where(s => roles.Contains(s.RoleName)).Select(s => s.Id).ToList();
dbcontext.AddRange(roleIds.Select(g => new { RoleID = g, UserID = user.Id }));
ret = dbcontext.SaveChanges() > 0;
}
return ret;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public User? GetUserByUserName(string? userName)
{
User? user = null;
if (userName != null)
{
using var dbcontext = DbFactory.CreateDbContext();
user = dbcontext.Set<User>().FirstOrDefault(s => s.UserName == userName);
}
return user;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public string? GetAppIdByUserName(string userName)
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.Set<User>().FirstOrDefault(s => s.UserName == userName)?.App;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="newPassword"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool ChangePassword(string userName, string password, string newPassword)
{
var ret = false;
if (Authenticate(userName, password))
{
using var dbcontext = DbFactory.CreateDbContext();
var passSalt = LgbCryptography.GenerateSalt();
password = LgbCryptography.ComputeHash(newPassword, passSalt);
string sql = "update Users set Password = {0}, PassSalt = {1} where UserName = {2}";
ret = dbcontext.Database.ExecuteSqlRaw(sql, new[] { password, passSalt, userName }) > 0;
}
return ret;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="displayName"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool SaveDisplayName(string userName, string displayName)
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.Database.ExecuteSqlRaw("update Users set DisplayName = {1} where UserName = {0}", userName, displayName!) > 0;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="theme"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool SaveTheme(string userName, string theme)
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.Database.ExecuteSqlRaw("update Users set Css = {1} where UserName = {0}", userName, theme) > 0;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="logo"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool SaveLogo(string userName, string? logo)
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.Database.ExecuteSqlRaw("update Users set Icon = {1} where UserName = {0}", userName, logo ?? "") > 0;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="app"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool SaveApp(string userName, string app)
{
using var dbcontext = DbFactory.CreateDbContext();
return dbcontext.Database.ExecuteSqlRaw("update Users Set App = {1} Where UserName = {0}", userName, app) > 0;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="displayName"></param>
/// <param name="password"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool SaveUser(string userName, string displayName, string password)
{
using var dbcontext = DbFactory.CreateDbContext();
var salt = LgbCryptography.GenerateSalt();
var pwd = LgbCryptography.ComputeHash(password, salt);
var user = GetAll().FirstOrDefault(s => s.UserName == userName);
bool ret;
if (user == null)
{
user = new User()
{
ApprovedBy = "System",
ApprovedTime = DateTime.Now,
DisplayName = "手机用户",
UserName = userName,
Icon = "default.jpg",
Description = "系统默认创建",
PassSalt = salt,
Password = pwd
};
dbcontext.Add(user);
// 授权 Default 角色
dbcontext.Database.ExecuteSqlRaw("insert into UserRole (UserID, RoleID) select ID, (select ID from Roles where RoleName = 'Default') RoleId from Users where UserName = {0}", userName);
ret = dbcontext.SaveChanges() > 0;
}
else
{
user.DisplayName = displayName;
user.PassSalt = salt;
user.Password = pwd;
dbcontext.Update(user);
ret = true;
}
return ret;
}
}

View File

@ -0,0 +1,167 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel.DataAnnotations;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
///
/// </summary>
public class AppInfo
{
/// <summary>
///
/// </summary>
[Display(Name = "系统名称")]
[Required(ErrorMessage = "{0}不可为空")]
[NotNull]
public string? Title { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "网站页脚")]
[Required(ErrorMessage = "{0}不可为空")]
[NotNull]
public string? Footer { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "登录首页")]
[NotNull]
public string? Login { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "后台地址")]
[NotNull]
public string? AuthUrl { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "网站主题")]
[NotNull]
public string? Theme { get; set; }
/// <summary>
/// 是否开启默认应用功能
/// </summary>
[Display(Name = "默认应用")]
public bool EnableDefaultApp { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "系统演示")]
public bool IsDemo { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "侧边栏设置")]
public bool SiderbarSetting { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "标题设置")]
public bool TitleSetting { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "固定表头")]
public bool FixHeaderSetting { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "健康检查")]
public bool HealthCheckSetting { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "手机登录")]
public bool MobileLogin { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "OAuth认证")]
public bool OAuthLogin { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "自动锁屏")]
public bool AutoLock { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "时长间隔(秒)")]
[Required(ErrorMessage = "{0}不可为空")]
public int Interval { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "地理位置定位器")]
public string? IpLocator { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "异常日志(月)")]
[Required(ErrorMessage = "{0}不可为空")]
public int ExceptionExpired { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "操作日志(月)")]
[Required(ErrorMessage = "{0}不可为空")]
public int OperateExpired { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "操作日志(月)")]
[Required(ErrorMessage = "{0}不可为空")]
public int LoginExpired { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "访问日志(月)")]
[Required(ErrorMessage = "{0}不可为空")]
public int AccessExpired { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "Cookie")]
[Required(ErrorMessage = "{0}不可为空")]
public int CookieExpired { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "IP 缓存(分)")]
[Required(ErrorMessage = "{0}不可为空")]
public int IPCacheExpired { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "授权码")]
[Required(ErrorMessage = "{0}不可为空")]
[NotNull]
public string? AuthCode { get; set; }
}

View File

@ -0,0 +1,3 @@
<Project Sdk="Microsoft.NET.Sdk">
</Project>

View File

@ -0,0 +1,36 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// 后台数据库脚本执行日志实体类
/// </summary>
public class DBLog
{
/// <summary>
/// 获得/设置 主键ID
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获得/设置 当前登陆名
/// </summary>
[DisplayName("所属用户")]
public string? UserName { get; set; }
/// <summary>
/// 获得/设置 数据库执行脚本
/// </summary>
[DisplayName("脚本内容")]
public string SQL { get; set; } = "";
/// <summary>
/// 获取/设置 用户角色关联状态 checked 标示已经关联 '' 标示未关联
/// </summary>
[DisplayName("执行时间")]
public DateTime LogTime { get; set; }
}

View File

@ -0,0 +1,49 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// 字典配置项
/// </summary>
[Table("Dicts")]
public class Dict
{
/// <summary>
/// 获得/设置 字典主键 数据库自增列
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获得/设置 字典标签
/// </summary>
[Required(ErrorMessage = "{0}不可为空")]
[Display(Name = "字典标签")]
public string? Category { get; set; }
/// <summary>
/// 获得/设置 字典名称
/// </summary>
[Required(ErrorMessage = "{0}不可为空")]
[Display(Name = "字典名称")]
[NotNull]
public string? Name { get; set; }
/// <summary>
/// 获得/设置 字典字典值
/// </summary>
[Required(ErrorMessage = "{0}不可为空")]
[Display(Name = "字典代码")]
[NotNull]
public string? Code { get; set; }
/// <summary>
/// 获得/设置 字典定义值 0 表示系统使用1 表示用户自定义 默认为 1
/// </summary>
[Display(Name = "字典类型")]
public EnumDictDefine Define { get; set; } = EnumDictDefine.Customer;
}

View File

@ -0,0 +1,25 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// 字典定义值 0 表示系统使用1 表示用户自定义 默认为 1
/// </summary>
public enum EnumDictDefine
{
/// <summary>
/// 系统使用
/// </summary>
[Description("系统使用")]
System,
/// <summary>
/// 用户自定义
/// </summary>
[Description("自定义")]
Customer
}

View File

@ -0,0 +1,25 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// 菜单分类 0 表示系统菜单 1 表示用户自定义菜单
/// </summary>
public enum EnumNavigationCategory
{
/// <summary>
/// 系统使用
/// </summary>
[Description("后台菜单")]
System,
/// <summary>
/// 用户自定义
/// </summary>
[Description("前台菜单")]
Customer
}

View File

@ -0,0 +1,29 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// 资源类型枚举 0 表示菜单 1 表示资源 2 表示按钮
/// </summary>
public enum EnumResource
{
/// <summary>
///
/// </summary>
[Description("菜单")]
Navigation,
/// <summary>
///
/// </summary>
[Description("资源")]
Resource,
/// <summary>
///
/// </summary>
[Description("代码块")]
Block
}

View File

@ -0,0 +1,71 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// 异常实体类
/// </summary>
public class Error
{
/// <summary>
/// 获得/设置 主键
/// </summary>
public string? Id { get; set; }
/// <summary>
///
/// </summary>
[DisplayName("应用程序")]
public string? AppDomainName { get; set; }
/// <summary>
/// 获得/设置 用户请求页面地址
/// </summary>
[DisplayName("请求网址")]
public string? ErrorPage { get; set; }
/// <summary>
/// 获得/设置 用户 ID
/// </summary>
[DisplayName("用户名")]
public string? UserId { get; set; }
/// <summary>
/// 获得/设置 用户 IP
/// </summary>
[DisplayName("登录主机")]
public string? UserIp { get; set; }
/// <summary>
/// 获得/设置 异常类型
/// </summary>
[DisplayName("异常类型")]
public string? ExceptionType { get; set; }
/// <summary>
/// 获得/设置 异常错误描述信息
/// </summary>
[DisplayName("异常描述")]
public string? Message { get; set; }
/// <summary>
/// 获得/设置 异常堆栈信息
/// </summary>
public string? StackTrace { get; set; }
/// <summary>
/// 获得/设置 日志时间戳
/// </summary>
[DisplayName("记录时间")]
public DateTime LogTime { get; set; }
/// <summary>
/// 获得/设置 分类信息
/// </summary>
[DisplayName("分类信息")]
public string? Category { get; set; }
}

View File

@ -0,0 +1,44 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel.DataAnnotations;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// Group 实体类
/// </summary>
public class Group
{
/// <summary>
/// 获得/设置 主键 ID
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获得/设置 群组名称
/// </summary>
[Display(Name = "群组名称")]
[NotNull]
public string? GroupName { get; set; }
/// <summary>
/// 获得/设置 群组编码
/// </summary>
[Display(Name = "群组编码")]
[NotNull]
public string? GroupCode { get; set; }
/// <summary>
/// 获得/设置 群组描述
/// </summary>
[Display(Name = "群组描述")]
public string? Description { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString() => $"{GroupName} ({GroupCode})";
}

View File

@ -0,0 +1,73 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// 登录用户信息实体类
/// </summary>
public class LoginLog
{
/// <summary>
/// 获得/设置 Id
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获得/设置 用户名
/// </summary>
[DisplayName("登录名称")]
[NotNull]
public string? UserName { get; set; }
/// <summary>
/// 获得/设置 登录时间
/// </summary>
[DisplayName("登录时间")]
public DateTime LoginTime { get; set; }
/// <summary>
/// 获得/设置 登录IP地址
/// </summary>
[DisplayName("主机")]
[NotNull]
public string? Ip { get; set; }
/// <summary>
/// 获得/设置 登录浏览器
/// </summary>
[DisplayName("浏览器")]
[NotNull]
public string? Browser { get; set; }
/// <summary>
/// 获得/设置 登录操作系统
/// </summary>
[DisplayName("操作系统")]
[NotNull]
public string? OS { get; set; }
/// <summary>
/// 获得/设置 登录地点
/// </summary>
[DisplayName("登录地点")]
[NotNull]
public string? City { get; set; }
/// <summary>
/// 获得/设置 登录是否成功
/// </summary>
[DisplayName("登录结果")]
[NotNull]
public string? Result { get; set; }
/// <summary>
/// 获得/设置 用户 UserAgent
/// </summary>
[DisplayName("登录名称")]
[NotNull]
public string? UserAgent { get; set; }
}

View File

@ -0,0 +1,79 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel.DataAnnotations;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// Bootstrap Admin 后台管理菜单相关操作实体类
/// </summary>
public class Navigation
{
/// <summary>
/// 获得/设置 菜单主键ID
/// </summary>
[NotNull]
public string? Id { set; get; }
/// <summary>
/// 获得/设置 父级菜单ID 默认为 0
/// </summary>
public string ParentId { set; get; } = "0";
/// <summary>
/// 获得/设置 菜单名称
/// </summary>
[Display(Name = "名称")]
[NotNull]
public string? Name { get; set; }
/// <summary>
/// 获得/设置 菜单序号
/// </summary>
[Display(Name = "序号")]
public int Order { get; set; }
/// <summary>
/// 获得/设置 菜单图标
/// </summary>
[Display(Name = "图标")]
public string? Icon { get; set; }
/// <summary>
/// 获得/设置 菜单URL地址
/// </summary>
[NotNull]
[Display(Name = "地址")]
public string? Url { get; set; }
/// <summary>
/// 获得/设置 菜单分类, 0 表示系统菜单 1 表示用户自定义菜单
/// </summary>
[Display(Name = "类别")]
public EnumNavigationCategory Category { get; set; }
/// <summary>
/// 获得/设置 链接目标
/// </summary>
[Display(Name = "目标")]
public string? Target { get; set; }
/// <summary>
/// 获得/设置 是否为资源文件, 0 表示菜单 1 表示资源 2 表示按钮
/// </summary>
[Display(Name = "类型")]
public EnumResource IsResource { get; set; }
/// <summary>
/// 获得/设置 所属应用程序此属性由BA后台字典表分配
/// </summary>
[Display(Name = "所属应用")]
public string? Application { get; set; }
/// <summary>
///
/// </summary>
public bool HasChildren { get; set; }
}

View File

@ -0,0 +1,32 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
/// Role 实体类
/// </summary>
public class Role
{
/// <summary>
/// 获得/设置 角色主键ID
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获得/设置 角色名称
/// </summary>
[DisplayName("角色名称")]
[NotNull]
public string? RoleName { get; set; }
/// <summary>
/// 获得/设置 角色描述
/// </summary>
[DisplayName("角色描述")]
[NotNull]
public string? Description { get; set; }
}

View File

@ -0,0 +1,70 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel.DataAnnotations;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
///
/// </summary>
public class Trace
{
/// <summary>
///
/// </summary>
public string? Id { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "登录用户")]
public string? UserName { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "操作时间")]
public DateTime LogTime { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "登录主机")]
public string? Ip { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "浏览器")]
public string? Browser { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "操作系统")]
public string? OS { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "操作地点")]
public string? City { get; set; }
/// <summary>
///
/// </summary>
[Display(Name = "操作页面")]
public string? RequestUrl { get; set; }
/// <summary>
///
/// </summary>
public string? UserAgent { get; set; }
/// <summary>
///
/// </summary>
public string? Referer { get; set; }
}

View File

@ -0,0 +1,166 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using System.ComponentModel.DataAnnotations;
namespace BootstrapAdmin.DataAccess.Models;
/// <summary>
///
/// </summary>
public class User
{
/// <summary>
/// 获得/设置 系统登录用户名
/// </summary>
[Display(Name = "登录名称")]
[Required(ErrorMessage = "{0}不可为空")]
[RegularExpression("^[a-zA-Z0-9_@.]*$", ErrorMessage = "")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? UserName { get; set; }
/// <summary>
/// 获得/设置 用户显示名称
/// </summary>
[Display(Name = "显示名称")]
[Required(ErrorMessage = "{0}不可为空")]
[MaxLength(20, ErrorMessage = "{0}不能超过 20 个字符")]
[NotNull]
public string? DisplayName { get; set; }
/// <summary>
/// 获得/设置 用户头像图标路径
/// </summary>
[Display(Name = "用户头像")]
public string? Icon { get; set; }
/// <summary>
/// 获得/设置 用户设置样式表名称
/// </summary>
[Display(Name = "主题")]
public string? Css { get; set; }
/// <summary>
/// 获得/设置 用户默认登陆 App 标识
/// </summary>
[Display(Name = "默认 APP")]
[NotNull]
public string? App { get; set; }
/// <summary>
/// 获得/设置 用户主键ID
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获取/设置 密码
/// </summary>
[Display(Name = "密码")]
[Required(ErrorMessage = "{0}不可为空")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? Password { get; set; }
/// <summary>
/// 获取/设置 密码盐
/// </summary>
public string? PassSalt { get; set; }
/// <summary>
/// 获得/设置 用户注册时间
/// </summary>
[Display(Name = "注册时间")]
public DateTime RegisterTime { get; set; } = DateTime.Now;
/// <summary>
/// 获得/设置 用户被批复时间
/// </summary>
[Display(Name = "授权时间")]
public DateTime? ApprovedTime { get; set; }
/// <summary>
/// 获得/设置 用户批复人
/// </summary>
[Display(Name = "授权人")]
public string? ApprovedBy { get; set; }
/// <summary>
/// 获得/设置 用户的申请理由
/// </summary>
[Display(Name = "说明")]
[NotNull]
public string? Description { get; set; }
/// <summary>
/// 获得/设置 通知描述 2分钟内为刚刚
/// </summary>
public string? Period { get; set; }
/// <summary>
/// 获得/设置 新密码
/// </summary>
[Display(Name = "新密码")]
[Required(ErrorMessage = "{0}不可为空")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? NewPassword { get; set; }
/// <summary>
/// 获得/设置 新密码
/// </summary>
[Display(Name = "确认密码")]
[Required(ErrorMessage = "{0}不可为空")]
[Compare("NewPassword", ErrorMessage = "{0}与{1}不一致")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? ConfirmPassword { get; set; }
/// <summary>
/// 获得/设置 是否重置密码
/// </summary>
public int IsReset { get; set; }
/// <summary>
/// 获得/设置 默认格式为 DisplayName (UserName)
/// </summary>
/// <returns></returns>
public override string ToString() => $"{DisplayName} ({UserName})";
}
/// <summary>
/// 用户状态枚举类型
/// </summary>
public enum UserStates
{
/// <summary>
/// 更改密码
/// </summary>
ChangePassword,
/// <summary>
/// 更改样式
/// </summary>
ChangeTheme,
/// <summary>
/// 更改显示名称
/// </summary>
ChangeDisplayName,
/// <summary>
/// 审批用户
/// </summary>
ApproveUser,
/// <summary>
/// 拒绝用户
/// </summary>
RejectUser,
/// <summary>
/// 保存默认应用
/// </summary>
SaveApp
}

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.1" />
<PackageReference Include="PetaPoco.Extensions" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj" />
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,77 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using PetaPoco;
using System.Reflection;
namespace BootstrapAdmin.DataAccess.PetaPoco;
class BootstrapAdminConventionMapper : ConventionMapper
{
/// <summary>
///
/// </summary>
/// <param name="pocoType"></param>
/// <returns></returns>
public override TableInfo GetTableInfo(Type pocoType)
{
var ti = base.GetTableInfo(pocoType);
ti.AutoIncrement = true;
// 支持 Oracle 数据库
ti.SequenceName = $"SEQ_{ti.TableName.ToUpperInvariant()}_ID";
ti.TableName = pocoType.Name switch
{
"Error" => "Exceptions",
_ => $"{pocoType.Name}s"
};
return ti;
}
/// <summary>
///
/// </summary>
/// <param name="pocoProperty"></param>
/// <returns></returns>
public override ColumnInfo GetColumnInfo(PropertyInfo pocoProperty) => pocoProperty.DeclaringType?.Name switch
{
nameof(Models.User) => GetUserColumnInfo(pocoProperty),
nameof(Models.Navigation) => GetNavigationColumnInfo(pocoProperty),
_ => base.GetColumnInfo(pocoProperty)
};
private ColumnInfo GetUserColumnInfo(PropertyInfo pocoProperty)
{
var ci = base.GetColumnInfo(pocoProperty);
var resultColumns = new List<string>
{
nameof(Models.User.NewPassword),
nameof(Models.User.ConfirmPassword),
nameof(Models.User.Period),
nameof(Models.User.IsReset)
};
ci.ResultColumn = resultColumns.Any(c => c == ci.ColumnName);
return ci;
}
private ColumnInfo GetNavigationColumnInfo(PropertyInfo pocoProperty)
{
var ci = base.GetColumnInfo(pocoProperty);
var resultColumns = new List<string>
{
nameof(Models.Navigation.HasChildren)
};
ci.ResultColumn = resultColumns.Any(c => c == ci.ColumnName);
return ci;
}
public override Func<object?, object?> GetFromDbConverter(PropertyInfo targetProperty, Type sourceType) => targetProperty.PropertyType.IsEnum && sourceType == typeof(string)
? new NumberToEnumConverter(targetProperty.PropertyType).ConvertFromDb
: base.GetFromDbConverter(targetProperty, sourceType);
public override Func<object?, object?> GetToDbConverter(PropertyInfo targetProperty) => targetProperty.PropertyType.IsEnum
? new NumberToEnumConverter(targetProperty.PropertyType).ConvertToDb
: base.GetToDbConverter(targetProperty);
}

View File

@ -0,0 +1,175 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapBlazor.Components;
using PetaPoco;
using System.Linq.Expressions;
using System.Reflection;
namespace BootstrapAdmin.Web.Extensions;
/// <summary>
/// PetaPoco 数据操作扩展类
/// </summary>
static class DatabaseExtensions
{
/// <summary>
///
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <returns></returns>
public static Task<List<TModel>> FetchAsync<TModel>(this IDatabase db, QueryPageOptions options)
{
var sql = db.ProcessQuery<TModel>(options);
return db.FetchAsync<TModel>(sql);
}
/// <summary>
///
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <returns></returns>
public static Task<Page<TModel>> PageAsync<TModel>(this IDatabase db, QueryPageOptions options)
{
var sql = db.ProcessQuery<TModel>(options);
return db.PageAsync<TModel>(options.PageIndex, options.PageItems, sql);
}
private static Sql ProcessQuery<TModel>(this IDatabase db, QueryPageOptions options)
{
var sql = new Sql();
// 处理模糊查询
if (options.Searchs.Any())
{
var searchTextSql = new Sql();
AnalysisExpression(options.Searchs.GetFilterLambda<TModel>(FilterLogic.Or), db, searchTextSql);
sql.Append(searchTextSql.ToString().Replace("\nAND", "OR"), searchTextSql.Arguments);
}
// 处理高级搜索
if (options.AdvanceSearchs.Any())
{
AnalysisExpression(options.AdvanceSearchs.GetFilterLambda<TModel>(), db, sql);
}
// 处理自定义搜索与过滤
var filters = options.Filters.Concat(options.CustomerSearchs);
if (filters.Any())
{
AnalysisExpression(filters.GetFilterLambda<TModel>(), db, sql);
}
// 支持多列排序
var sortName = options.SortName;
var sortOrder = options.SortOrder;
if (!string.IsNullOrEmpty(sortName) && sortOrder != SortOrder.Unset)
{
sql.OrderBy(sortOrder == SortOrder.Asc ? sortName : $"{sortName} desc");
}
else if (options.SortList != null && options.SortList.Any())
{
sql.OrderBy(string.Join(",", options.SortList));
}
return sql;
}
private static void AnalysisExpression(Expression expression, IDatabase db, Sql sql)
{
switch (expression.NodeType)
{
case ExpressionType.Lambda:
if (expression is LambdaExpression exp)
{
AnalysisExpression(exp.Body, db, sql);
}
break;
case ExpressionType.AndAlso:
if (expression is BinaryExpression andExp)
{
AnalysisExpression(andExp.Left, db, sql);
AnalysisExpression(andExp.Right, db, sql);
}
break;
case ExpressionType.OrElse:
if (expression is BinaryExpression orExp)
{
AnalysisExpression(orExp.Left, db, sql);
AnalysisExpression(orExp.Right, db, sql);
}
break;
case ExpressionType.Call:
if (expression is MethodCallExpression callExp)
{
if (callExp.Method.Name == "Contains")
{
if (callExp.Object is MemberExpression callLeft)
{
var callColName = GetColumnName(callLeft.Member) ?? callLeft.Member.Name;
var p = (callExp.Arguments[0] as ConstantExpression)?.Value;
if (p != null)
{
sql.Where($"{db.Provider.EscapeSqlIdentifier(callColName)} like @0", $"%{p}%");
}
}
}
}
break;
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
if (expression is BinaryExpression binaryExp)
{
MemberExpression? left = null;
if (binaryExp.Left is MethodCallExpression methodLeft && methodLeft.Method.Name == "ToString" && methodLeft.Object is MemberExpression p && p.Type.IsEnum)
{
// 枚举转字符串
left = p;
}
else if (binaryExp.Left is MemberExpression m)
{
left = m;
}
if (left != null)
{
// 查找 PetaPoco.Column 标签
var columnName = GetColumnName(left.Member) ?? left.Member.Name;
// 查找操作符右侧
if (binaryExp.Right is ConstantExpression right)
{
var v = right.Value;
if (v != null)
{
var val = v.GetType().IsEnum ? (int)v : v;
var operatorExp = GetOperatorExpression(expression);
sql.Where($"{db.Provider.EscapeSqlIdentifier(columnName)} {operatorExp} @0", val);
}
}
}
}
break;
}
}
private static string? GetColumnName(MemberInfo member) => member.CustomAttributes
.FirstOrDefault(i => i.AttributeType == typeof(ColumnAttribute))?.NamedArguments
.FirstOrDefault(i => i.MemberName == "Name").TypedValue.Value?.ToString();
private static string GetOperatorExpression(Expression expression) => expression.NodeType switch
{
ExpressionType.Equal => "=",
ExpressionType.NotEqual => "!=",
ExpressionType.GreaterThan => ">",
ExpressionType.GreaterThanOrEqual => ">=",
ExpressionType.LessThan => "<",
ExpressionType.LessThanOrEqual => "<=",
_ => ""
};
}

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