diff --git a/.gitignore b/.gitignore index fa852bd173e755dd27e77a2bceca2ad3a74f9651..3dab4af7f94855f5ffdf0cc3df38374a8c1cc2a3 100644 --- a/.gitignore +++ b/.gitignore @@ -16,11 +16,15 @@ bin-release/ # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` # should NOT be excluded as they contain compiler settings and other important # information for Eclipse / Flash Builder. -/backend/Dilon.Web.Entry/wwwroot /backend/Dilon.Web.Entry/Logs /backend/.vs +/backend/.idea /backend/Dilon.Web.Entry/publish /backend/Dilon.Database.Migrations/Migrations /backend/Dilon.Web.Entry/Properties/PublishProfiles /backend/Dilon.Core/Dilon.Core.csproj.user /backend/Dilon.Web.Entry/Dilon.Web.Entry.csproj.user +/.vs +/.idea +/backend/Dilon.Web.Entry/templates +/backend/Dilon.Web.Entry/wwwroot/Upload diff --git a/LICENSE b/LICENSE index 261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64..79b452bdd5e8c3ba4f5252959d39ebfb0f939c11 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ Version 2.0, January 2004 http://www.apache.org/licenses/ - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright © 2021 Admin.NET, Dilon Co.,Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 798d0dda69c0de520d90d895fdae0369371012f3..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# Admin.NET - -#### Description -基于.NET 5实现的通用权限管理平台。高效快速开发,前后端分离模式,代码简洁,开箱即用。后台基于Furion框架,极易入门、极速开发、极易维护,数据源随意切换并自带租户功能。前端使用AntDesign-Vue-Pro + Vue2.0开发,紧跟前沿技术。 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index ee0a4130bb447747139a5b9de4c1c12d3e84444e..25ef5d91eab1b4b61fe00c06f2e55e5939115fc4 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,27 @@

- logo + logo

Admin.NET

前后端分离架构,开箱即用,紧随前沿技术

+
+ +[![star](https://gitee.com/zuohuaijun/Admin.NET/badge/star.svg?theme=dark)](https://gitee.com/zuohuaijun/Admin.NET/stargazers) +[![fork](https://gitee.com/zuohuaijun/Admin.NET/badge/fork.svg?theme=dark)](https://gitee.com/zuohuaijun/Admin.NET/members) +[![star](https://gitee.com/dotnetchina/Furion/badge/star.svg?theme=gvp)](https://gitee.com/dotnetchina/Furion/stargazers) +[![star](https://gitee.com/xiaonuobase/snowy/badge/star.svg?theme=gray)](https://gitee.com/xiaonuobase/snowy/stargazers) +[![GitHub license](https://img.shields.io/badge/license-Apache2-yellow)](https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) + +
+ ### 🍟 概述 -* 基于.NET5实现的通用权限管理平台(RBAC模式)。整合最新技术高效快速开发,前后端分离模式,开箱即用。 -* 后台基于Furion框架,多租户、分库读写分离、缓存、数据校验、鉴权、动态API、gRPC等众多黑科技集一身。 -前端Antd-Vue-Pro + Vue2.X开发,紧跟前沿技术,前端自带字典翻译。 +* 基于.NET 5实现的通用权限管理平台(RBAC模式)。整合最新技术高效快速开发,前后端分离模式,开箱即用。 +* 前端基于小诺Vue(antd)框架,整体RBAC基础数据结构+API接口风格采用小诺vue版本模式。 +* 后台基于Furion框架,EFCore、多租户、分库读写分离、缓存、数据校验、鉴权、动态API、gRPC等众多黑科技集一身。 * 模块化架构设计,层次清晰,业务层推荐写到单独模块,框架升级不影响业务! * 核心模块包括:用户、角色、职位、组织机构、菜单、字典、日志、多应用管理、文件管理、定时任务等功能。 * 代码量少、通俗易懂、功能强大、易扩展,轻松开发从现在开始! @@ -20,13 +30,23 @@ 如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,获取第一时间更新,谢谢! ``` +### 😎 衍生版本 + +【Admin.NET】隆重推出SqlSugar版本 + +- 👉 SqlSugar版本:[https://gitee.com/zhengguojing/admin-net-sqlsugar](https://gitee.com/zhengguojing/admin-net-sqlsugar) + +`如果集成其他ORM,请参照各自操作使用说明。系统默认EFCore不会处理其他ORM实体等,请自行处理。` + ### 🥞 更新日志 更新日志 [点击查看](https://gitee.com/zuohuaijun/Admin.NET/commits/master) ### ⚡ 近期计划 -- [ ] 集成代码生成器 +- [x] 集成多租户功能 +- [x] 集成代码生成器 +- [x] 集成导入导出 - [ ] 在线用户及黑名单 - [ ] 邮件发送 - [ ] 短信发送 @@ -36,9 +56,10 @@ ### 🍿 在线体验 -~~体验地址:[http://dilon.zicp.net:55221/](http://dilon.zicp.net:55221/)(用户名:superAdmin,密码:123456)~~ - -`【个人电脑临时部署,偶尔在线,可以试试看】` +- 体验地址:[http://39.107.123.76:82/](http://39.107.123.76:82/) +- 开发者租户:用户名:superAdmin,密码:123456 +- 公司1租户: 公司1租户管理员(用户名:admin1 密码:123456),公司1租户普通用户(用户名:zuohuaijun1 密码:123456) + ### 🍄 快速启动 @@ -72,6 +93,16 @@ + + + + + + + + + + ### 🍖 详细功能 @@ -87,13 +118,13 @@ 9. 访问日志、用户的登录和退出日志的查看和管理。 10. 操作日志、用户的操作业务的日志的查看和管理。 11. 服务监控、服务器的运行状态,CPU、内存、网络等信息数据的查看。 -12. 在线用户、当前系统在线用户的查看。【正在实现中...】 +12. 在线用户、当前系统在线用户的查看。 13. 公告管理、系统的公告的管理。 -14. 文件管理、文件的上传下载查看等操作,文件可使用本地存储,阿里云oss,腾讯cos接入,支持拓展。【目前只支持本地存储...】 +14. 文件管理、文件的上传下载查看等操作,文件可使用本地存储,阿里云oss,腾讯cos接入,支持拓展。 15. 定时任务、定时任务的维护,通过cron表达式控制任务的执行频率。 -16. 系统配置、系统运行的参数的维护,参数的配置与系统运行机制息息相关。【完善中...】 -17. 邮件发送、发送邮件功能。【正在实现中...】 -18. 短信发送、短信发送功能,可使用阿里云sms,腾讯云sms,支持拓展。【正在实现中...】 +16. 系统配置、系统运行的参数的维护,参数的配置与系统运行机制息息相关。 +17. 邮件发送、发送邮件功能。 +18. 短信发送、短信发送功能,可使用阿里云sms,腾讯云sms,支持拓展。 ### 👀 数据库切换 @@ -110,7 +141,7 @@ 1. Dilon.EntityFramework.Core 项目安装 ``` Microsoft.EntityFrameworkCore.SqlServer ``` 2. DefaultDbContext.cs 指定 DbProvider , ```[AppDbContext("DefaultConnection", DbProvider.SqlServer)]``` 3. dbsettings.json 配置 "DefaultConnection": ```"Server=localhost;Database=Dilon;User=sa;Password=000000;MultipleActiveResultSets=True;"``` -4. 打开程序包管理器控制台,默认项目Dilon.Database.Migrations 执行命令:```Add-Migration Init和update-database``` +4. 打开程序包管理器控制台,默认项目Dilon.Database.Migrations 执行命令:```Add-Migration Init 和 update-database``` ``` 提示:其他类型数据库依次类推,首先添加EF的Core版包,然后指定数据库类型,修改数据库连接字符串,执行EF命令即可。 @@ -118,14 +149,18 @@ ### 🥦 补充说明 -* 基于.NET5平台Furion开发框架与小诺VUE版本相结合,实时跟随基架升级而升级! +* 基于.NET 5平台 Furion 开发框架与小诺 Vue 版本相结合,实时跟随基架升级而升级! * 持续集百家所长,完善与丰富本框架基础设施,为.NET生态增加一种选择! * 后期会推出基于此框架的相关应用场景案例,提供给大家使用! * 有问题讨论的小伙伴可加群一起学习讨论。 QQ群【87333204】 Admin.NET ### 💐 特别鸣谢 -- 👉Furion: [https://dotnetchina.gitee.io/furion](https://dotnetchina.gitee.io/furion) -- 👉 xiaonuo:[https://gitee.com/xiaonuobase/xiaonuo-vue](https://gitee.com/xiaonuobase/xiaonuo-vue) +- 👉 Furion: [https://dotnetchina.gitee.io/furion](https://dotnetchina.gitee.io/furion) +- 👉 xiaonuo:[https://gitee.com/xiaonuobase/snowy](https://gitee.com/xiaonuobase/snowy) +- 👉 k-form-design:[https://gitee.com/kcz66/k-form-design](https://gitee.com/kcz66/k-form-design) +- 👉 MiniExcel:[https://gitee.com/dotnetchina/MiniExcel](https://gitee.com/dotnetchina/MiniExcel) +- 👉 SqlSugar:[https://gitee.com/dotnetchina/SqlSugar](https://gitee.com/dotnetchina/SqlSugar) + -如果对您有帮助,您可以点 "Star" 支持一下,这样才有持续下去的动力,谢谢! +如果对您有帮助,您可以点 "Star" 支持一下,这样才有持续下去的动力,谢谢!!! diff --git a/backend/Dilon.Application/Dilon.Application.csproj b/backend/Dilon.Application/Dilon.Application.csproj index 9f5b37470c8239ced9844cd144b72462c94f2f83..abd537ac851a7cfda84dc9a96b87321c80f81741 100644 --- a/backend/Dilon.Application/Dilon.Application.csproj +++ b/backend/Dilon.Application/Dilon.Application.csproj @@ -22,7 +22,7 @@ - + diff --git a/backend/Dilon.Application/Dilon.Application.csproj.user b/backend/Dilon.Application/Dilon.Application.csproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/backend/Dilon.Application/Dilon.Application.csproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/backend/Dilon.Application/Dilon.Application.xml b/backend/Dilon.Application/Dilon.Application.xml index 7b3a41d8de767822259c381255ed45790560ea5f..d1774e47c15ae875e84f882e0ca585e2b97b287c 100644 --- a/backend/Dilon.Application/Dilon.Application.xml +++ b/backend/Dilon.Application/Dilon.Application.xml @@ -4,10 +4,178 @@ Dilon.Application + + + 代码生成实体测试(EF) + + + + + 名称 + + + + + 昵称 + + + + + 生日 + + + + + 年龄 + + + + + SqlSugar实体 + + + + + 雪花Id + + + + + 名称 + + + + + 年龄 + + + + + 创建时间 + + + + + 代码生成业务服务 + + + + + 分页查询代码生成业务 + + + + + + + 增加代码生成业务 + + + + + + + 删除代码生成业务 + + + + + + + 更新代码生成业务 + + + + + + + 获取代码生成业务 + + + + + + + 获取代码生成业务列表 + + + + + + + 代码生成业务输入参数 + + + + + 名称 + + + + + 昵称 + + + + + 生日 + + + + + 年龄 + + + + + Id主键 + + + + + Id主键 + + + + + 代码生成业务输出参数 + + + + + 名称 + + + + + 昵称 + + + + + 生日 + + + + + 年龄 + + + + + Id主键 + + - 事例 + 业务服务及集成SqlSugar用法事例 + + + + + 测试方法 + diff --git a/backend/Dilon.Application/Entity/CodeGenTest.cs b/backend/Dilon.Application/Entity/CodeGenTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..601062c83e563ca285958c143908ab977c132bda --- /dev/null +++ b/backend/Dilon.Application/Entity/CodeGenTest.cs @@ -0,0 +1,39 @@ +using Dilon.Core; +using Microsoft.EntityFrameworkCore; +using System; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Dilon.Application +{ + /// + /// 代码生成实体测试(EF) + /// + [Table("code_gen_test")] + [Comment("代码生成业务")] + public class CodeGenTest : DEntityBase + { + /// + /// 名称 + /// + [Comment("名称")] + public string Name { get; set; } + + /// + /// 昵称 + /// + [Comment("昵称")] + public string NickName { get; set; } + + /// + /// 生日 + /// + [Comment("生日")] + public DateTimeOffset Birthday { get; set; } + + /// + /// 年龄 + /// + [Comment("年龄")] + public int Age { get; set; } + } +} diff --git a/backend/Dilon.Application/Entity/Test.cs b/backend/Dilon.Application/Entity/Test.cs new file mode 100644 index 0000000000000000000000000000000000000000..9f15c349c158608c0333745fc85892684f393870 --- /dev/null +++ b/backend/Dilon.Application/Entity/Test.cs @@ -0,0 +1,35 @@ +using SqlSugar; +using System; + +namespace Dilon.Application +{ + /// + /// SqlSugar实体 + /// + [SugarTable("Test", TableDescription = "我的业务表")] + public class Test + { + /// + /// 雪花Id + /// + [SugarColumn(IsPrimaryKey = true)] + public long Id { get; set; } + + /// + /// 名称 + /// + [SugarColumn(ColumnDataType = "Nvarchar(32)")] + public string Name { get; set; } + + /// + /// 年龄 + /// + public int Age { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(IsNullable = true)] + public DateTimeOffset CreateTime { get; set; } + } +} diff --git a/backend/Dilon.Application/README.md b/backend/Dilon.Application/README.md index b559d9ca3e7e6fa07d654c3c803a8a3e11ef0a4b..11a79cda6841dcc0ff2556e43e92203244703df6 100644 --- a/backend/Dilon.Application/README.md +++ b/backend/Dilon.Application/README.md @@ -1,2 +1,3 @@ -原则上服务应该放在Application层次,考虑将咱自己的业务层直接写在Application里面好些,后续升级后,咱大家直接升级就行了,减少冲突! - +1、原则上服务应该放在Application层次,考虑将咱自己的业务层直接写在Application里面好些,后续升级后,咱大家直接升级就行了,减少冲突! +2、系统默认ORM为EF Core,如果觉得不趁手,可以自行更换 +3、在此应用层默认集成了SqlSugar,其他ORM类同,可以多个ORM并行开发,熟悉哪个用哪个 diff --git a/backend/Dilon.Application/Service/TestService.cs b/backend/Dilon.Application/Service/TestService.cs index 197e1cba05c80673e290798dddd5508b5cc75644..ef260bd11f906443dcbb8931c40ec681493cb574 100644 --- a/backend/Dilon.Application/Service/TestService.cs +++ b/backend/Dilon.Application/Service/TestService.cs @@ -1,21 +1,76 @@ -using Furion.DependencyInjection; +using Dilon.Core; +using Furion.DependencyInjection; using Furion.DynamicApiController; +using Furion.Snowflake; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Dilon.Application { /// - /// 事例 + /// 业务服务及集成SqlSugar用法事例 /// public class TestService : ITestService, IDynamicApiController, ITransient { - public TestService() - { + //private readonly ISqlSugarRepository _testRep; + //private readonly SqlSugarClient _db; // SqlSugar对象 + public TestService(/*ISqlSugarRepository sqlSugarRep*/) + { + //_testRep = sqlSugarRep; + //_db = (SqlSugarClient)_testRep.Context; } + /// + /// 测试方法 + /// + /// + [HttpPost("/test")] public string GetDescription() { return "Admin.NET"; } + + ///// + ///// 增加数据 + ///// + ///// + //[HttpPost("/test/add")] + //public async Task AddTestAsync() + //{ + // var test = new Test() + // { + // Id = IDGenerator.NextId(), + // Name = "Admin.NET", + // Age = 1, + // CreateTime = DateTimeOffset.Now + // }; + // await _testRep.InsertAsync(test); + // // _db.Insertable(test).ExecuteCommand(); + //} + + ///// + ///// 查询所有 + ///// + ///// + //[HttpPost("/test/page")] + //public async Task> GetTestListAsync() + //{ + // return await _testRep.Entities.ToListAsync(); + //} + + ///// + ///// 查询系统用户 + ///// + ///// + //[HttpPost("/test/userPage")] + //public async Task GetUserListAsync() + //{ + // return await _db.Queryable().ToListAsync(); + //} } } diff --git a/backend/Dilon.Application/Startup.cs b/backend/Dilon.Application/Startup.cs new file mode 100644 index 0000000000000000000000000000000000000000..d3b6b4bd91db5d7b1248dbcd613ff88bc6c2c097 --- /dev/null +++ b/backend/Dilon.Application/Startup.cs @@ -0,0 +1,31 @@ +using Furion; +using Microsoft.Extensions.DependencyInjection; +using SqlSugar; +using System.Linq; + +namespace Dilon.Application +{ + public class Startup : AppStartup + { + public void ConfigureServices(IServiceCollection services) + { + //services.AddSqlSugar(new ConnectionConfig + //{ + // ConnectionString = App.Configuration["ConnectionStrings:DefaultConnection"], + // DbType = DbType.Sqlite, + // IsAutoCloseConnection = true, + // InitKeyType = InitKeyType.Attribute + //}, + //db => + //{ + // // db.DbMaintenance.CreateDatabase(); + // // db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(Test)); + + // db.Aop.OnLogExecuting = (sql, pars) => + // { + // App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + string.Join(",", pars?.Select(it => it.ParameterName + ":" + it.Value))); + // }; + //}); + } + } +} diff --git a/backend/Dilon.Core/Cache/ICache.cs b/backend/Dilon.Core/Cache/ICache.cs index e96f065f19ac2c172f695aaa795c5ae62d6a202e..0b2f693db319ad59b08385cb141cb718f469d6d1 100644 --- a/backend/Dilon.Core/Cache/ICache.cs +++ b/backend/Dilon.Core/Cache/ICache.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace Dilon.Core @@ -103,5 +104,11 @@ namespace Dilon.Core /// 有效期 /// Task SetAsync(string key, object value, TimeSpan expire); + + /// + /// 获取所有缓存 + /// + /// + List GetAllKeys(); } } diff --git a/backend/Dilon.Core/Cache/MemoryCache.cs b/backend/Dilon.Core/Cache/MemoryCache.cs index 0d96f07988b90f43cc2ead9bca18f2e8f0dc4f4b..bf9722a19def42d3237ce0426660b5b02687b7f0 100644 --- a/backend/Dilon.Core/Cache/MemoryCache.cs +++ b/backend/Dilon.Core/Cache/MemoryCache.cs @@ -45,14 +45,10 @@ namespace Dilon.Core if (string.IsNullOrEmpty(pattern)) return default; - pattern = Regex.Replace(pattern, @"\{.*\}", "(.*)"); - - var keys = GetAllKeys().Where(k => Regex.IsMatch(k, pattern)); - - if (keys != null && keys.Count() > 0) - { + //pattern = Regex.Replace(pattern, @"\{*.\}", "(.*)"); + var keys = GetAllKeys().Where(k => k.StartsWith(pattern)); + if (keys != null && keys.Any()) return await DelAsync(keys.ToArray()); - } return default; } @@ -111,7 +107,7 @@ namespace Dilon.Core return Task.FromResult(true); } - private List GetAllKeys() + public List GetAllKeys() { const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache); diff --git a/backend/Dilon.Core/Cache/RedisCache.cs b/backend/Dilon.Core/Cache/RedisCache.cs index 39df0754a69fa3b9044cca0b69130d7b74c88c6a..e98a2a5aa8ac05e9d736b9f81505a7bea70ced21 100644 --- a/backend/Dilon.Core/Cache/RedisCache.cs +++ b/backend/Dilon.Core/Cache/RedisCache.cs @@ -1,6 +1,8 @@ using Furion.DependencyInjection; using Microsoft.Extensions.Options; using System; +using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -32,8 +34,7 @@ namespace Dilon.Core if (string.IsNullOrEmpty(pattern)) return default; - pattern = Regex.Replace(pattern, @"\{.*\}", "*"); - + //pattern = Regex.Replace(pattern, @"\{.*\}", "*"); var keys = (await RedisHelper.KeysAsync(pattern)); if (keys != null && keys.Length > 0) { @@ -92,5 +93,10 @@ namespace Dilon.Core { return RedisHelper.SetAsync(key, value, expire); } + + public List GetAllKeys() + { + return RedisHelper.Keys("").ToList(); + } } } \ No newline at end of file diff --git a/backend/Dilon.Core/Captcha/ClickWord/ClickWordCaptcha.cs b/backend/Dilon.Core/Captcha/ClickWord/ClickWordCaptcha.cs index e2d951b79822e5cf76527a0fe0df1e2d9118041e..be81deb0b57beae8cab12402a89d2edb538d2226 100644 --- a/backend/Dilon.Core/Captcha/ClickWord/ClickWordCaptcha.cs +++ b/backend/Dilon.Core/Captcha/ClickWord/ClickWordCaptcha.cs @@ -1,6 +1,7 @@ -using Furion.DependencyInjection; -using Furion.FriendlyException; +using Furion; +using Furion.DependencyInjection; using Furion.JsonSerialization; +using Furion.Snowflake; using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; @@ -44,19 +45,14 @@ namespace Dilon.Core Color[] colorArray = { Color.Black, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple }; - string bgImagesDir = Path.Combine(AppContext.BaseDirectory, "Captcha/ClickWord/Data", "Image"); + string bgImagesDir = Path.Combine(App.WebHostEnvironment.WebRootPath, "Captcha/Image"); string[] bgImagesFiles = Directory.GetFiles(bgImagesDir); - if (bgImagesFiles == null || bgImagesFiles.Length == 0) - throw Oops.Oh("背景图片文件丢失"); - // 字体来自:https://www.zcool.com.cn/special/zcoolfonts/ - string fontsDir = Path.Combine(AppContext.BaseDirectory, "Captcha/ClickWord/Data", "Font"); + string fontsDir = Path.Combine(App.WebHostEnvironment.WebRootPath, "Captcha/Font"); string[] fontFiles = new DirectoryInfo(fontsDir)?.GetFiles() ?.Where(m => m.Extension.ToLower() == ".ttf") ?.Select(m => m.FullName).ToArray(); - if (fontFiles == null || fontFiles.Length == 0) - throw Oops.Oh("字体文件丢失"); int imgIndex = random.Next(bgImagesFiles.Length); string randomImgFile = bgImagesFiles[imgIndex]; @@ -88,12 +84,15 @@ namespace Dilon.Core { // (int, int) percentPos = ToPercentPos((width, height), (_x, _y)); // 添加正确答案 位置数据 - rtnResult.repData.point.Add(new PointPosModel() + if (random.Next(0, 3).Equals(1) || (code_length - i).Equals(rightCodeLength - rtnResult.repData.point.Count)) { - X = _x, //percentPos.Item1, - Y = _y //percentPos.Item2, - }); - words.Add(word); + rtnResult.repData.point.Add(new PointPosModel() + { + X = _x, //percentPos.Item1, + Y = _y //percentPos.Item2, + }); + words.Add(word); + } } g.DrawString(word, f, b, _x, _y); } @@ -105,7 +104,7 @@ namespace Dilon.Core bitmap.Dispose(); ms.Dispose(); rtnResult.repData.originalImageBase64 = Convert.ToBase64String(ms.GetBuffer()); //"data:image/jpg;base64," + - rtnResult.repData.token = Guid.NewGuid().ToString("N"); + rtnResult.repData.token = IDGenerator.NextId().ToString(); // 缓存验证码正确位置集合 var cacheOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(30)); @@ -152,17 +151,44 @@ namespace Dilon.Core /// public string RandomCode(int number) { - var str = "左怀军天地玄黄宇宙洪荒日月盈昃辰宿列张寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈剑号巨阙珠称夜光果珍李柰菜重芥姜海咸河淡鳞潜羽翔龙师火帝鸟官人皇始制文字乃服衣裳推位让国有虞陶唐吊民伐罪周发殷汤坐朝问道垂拱平章爱育黎首臣伏戎羌遐迩体率宾归王"; - char[] str_char_arrary = str.ToArray(); + char[] str_char_arrary = new char[] { '赵', '钱', '孙', '李', '周', '吴', '郑', '王', '冯', '陈', '褚', '卫', '蒋', '沈', '韩', '杨', + '朱', '秦', '尤', '许', '何', '吕', '施', '张', '孔', '曹', '严', '华', '金', '魏', '陶', '姜', '戚', '谢', '邹', '喻', '柏', '水', + '窦', '章', '云', '苏', '潘', '葛', '奚', '范', '彭', '郎', '鲁', '韦', '昌', '马', '苗', '凤', '花', '方', '任', '袁', '柳', '鲍', + '史', '唐', '费', '薛', '雷', '贺', '倪', '汤', '滕', '殷', '罗', '毕', '郝', '安', '常', '傅', '卞', '齐', '元', '顾', '孟', '平', + '黄', '穆', '萧', '尹', '姚', '邵', '湛', '汪', '祁', '毛', '狄', '米', '伏', '成', '戴', '谈', '宋', '茅', '庞', '熊', '纪', '舒', + '屈', '项', '祝', '董', '梁', '杜', '阮', '蓝', '闵', '季', '贾', '路', '娄', '江', '童', '颜', '郭', '梅', '盛', '林', '钟', '徐', + '邱', '骆', '高', '夏', '蔡', '田', '樊', '胡', '凌', '霍', '虞', '万', '支', '柯', '管', '卢', '莫', '柯', '房', '裘', '缪', '解', + '应', '宗', '丁', '宣', '邓', '单', '杭', '洪', '包', '诸', '左', '石', '崔', '吉', '龚', '程', '嵇', '邢', '裴', '陆', '荣', '翁', + '荀', '于', '惠', '甄', '曲', '封', '储', '仲', '伊', '宁', '仇', '甘', '武', '符', '刘', '景', '詹', '龙', '叶', '幸', '司', '黎', + '溥', '印', '怀', '蒲', '邰', '从', '索', '赖', '卓', '屠', '池', '乔', '胥', '闻', '莘', '党', '翟', '谭', '贡', '劳', '逄', '姬', + '申', '扶', '堵', '冉', '宰', '雍', '桑', '寿', '通', '燕', '浦', '尚', '农', '温', '别', '庄', '晏', '柴', '瞿', '阎', '连', '习', + '容', '向', '古', '易', '廖', '庾', '终', '步', '都', '耿', '满', '弘', '匡', '国', '文', '寇', '广', '禄', '阙', '东', '欧', '利', + '师', '巩', '聂', '关', '荆', + '伟', '刚', '勇', '毅', '俊', '峰', '强', '军', '平', '保', '东', '文', '辉', '力', '明', '永', '健', '世', '广', '志', '义', '兴', + '良', '海', '山', '仁', '波', '宁', '贵', '福', '生', '龙', '元', '全', '国', '胜', '学', '祥', '才', '发', '武', '新', '利', '清', + '飞', '彬', '富', '顺', '信', '子', '杰', '涛', '昌', '成', '康', '星', '光', '天', '达', '安', '岩', '中', '茂', '进', '林', '有', + '坚', '和', '彪', '博', '诚', '先', '敬', '震', '振', '壮', '会', '思', '群', '豪', '心', '邦', '承', '乐', '绍', '功', '松', '善', + '厚', '庆', '磊', '民', '友', '裕', '河', '哲', '江', '超', '浩', '亮', '政', '谦', '亨', '奇', '固', '之', '轮', '翰', '朗', '伯', + '宏', '言', '若', '鸣', '朋', '斌', '梁', '栋', '维', '启', '克', '伦', '翔', '旭', '鹏', '泽', '晨', '辰', '士', '以', '建', '家', + '致', '树', '炎', '德', '行', '时', '泰', '盛', '雄', '琛', '钧', '冠', '策', '腾', '楠', '榕', '风', '航', '弘', '秀', '娟', '英', + '华', '慧', '巧', '美', '娜', '静', '淑', '惠', '珠', '翠', '雅', '芝', '玉', '萍', '红', '娥', '玲', '芬', '芳', '燕', '彩', '春', + '菊', '兰', '凤', '洁', '梅', '琳', '素', '云', '莲', '真', '环', '雪', '荣', '爱', '妹', '霞', '香', '月', '莺', '媛', '艳', '瑞', + '凡', '佳', '嘉', '琼', '勤', '珍', '贞', '莉', '桂', '娣', '叶', '璧', '璐', '娅', '琦', '晶', '妍', '茜', '秋', '珊', '莎', '锦', + '黛', '青', '倩', '婷', '姣', '婉', '娴', '瑾', '颖', '露', '瑶', '怡', '婵', '雁', '蓓', '纨', '仪', '荷', '丹', '蓉', '眉', '君', + '琴', '蕊', '薇', '菁', '梦', '岚', '苑', '婕', '馨', '瑗', '琰', '韵', '融', '园', '艺', '咏', '卿', '聪', '澜', '纯', '毓', '悦', + '昭', '冰', '爽', '琬', '茗', '羽', '希', '欣', '飘', '育', '滢', '馥', '筠', '柔', '竹', '霭', '凝', '晓', '欢', '霄', '枫', '芸', + '菲', '寒', '伊', '亚', '宜', '可', '姬', '舒', '影', '荔', '枝', '丽', '阳', '妮', '宝', '贝', '初', '程', '梵', '罡', '恒', '鸿', + '桦', '骅', '剑', '娇', '纪', '宽', '苛', '灵', '玛', '媚', '琪', '晴', '容', '睿', '烁', '堂', '唯', '威', '韦', '雯', '苇', '萱', + '阅', '彦', '宇', '雨', '洋', '忠', '宗', '曼', '紫', '逸', '贤', '蝶', '菡', '绿', '蓝', '儿', '翠', '烟' }; Random rand = new Random(); - HashSet hs = new HashSet(); + HashSet hs = new HashSet(); bool randomBool = true; while (randomBool) { if (hs.Count == number) break; int rand_number = rand.Next(str_char_arrary.Length); - hs.Add(str_char_arrary[rand_number].ToString()); + hs.Add(str_char_arrary[rand_number]); } return string.Join("", hs); } @@ -184,7 +210,7 @@ namespace Dilon.Core return res; } - var userVCodePos = JSON.GetJsonSerializer().Deserialize>(input.PointJson); + var userVCodePos = JSON.Deserialize>(input.PointJson); if (userVCodePos == null || userVCodePos.Count < rightVCodePos.Count) { res.repCode = "6111"; @@ -192,7 +218,7 @@ namespace Dilon.Core return res; } - int allowOffset = 20; // 允许的偏移量(点触容错) + int allowOffset = 25; // 允许的偏移量(点触容错) for (int i = 0; i < userVCodePos.Count; i++) { var xOffset = userVCodePos[i].X - rightVCodePos[i].X; diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/10.jpg b/backend/Dilon.Core/Captcha/ClickWord/Data/Image/10.jpg deleted file mode 100644 index 93fed9887bdb03fe3e9202fe6011f200258956b9..0000000000000000000000000000000000000000 Binary files a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/10.jpg and /dev/null differ diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/11.jpg b/backend/Dilon.Core/Captcha/ClickWord/Data/Image/11.jpg deleted file mode 100644 index 51c56e1d2e0eb3cbf249a5af5bac0d695e308e60..0000000000000000000000000000000000000000 Binary files a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/11.jpg and /dev/null differ diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/12.jpg b/backend/Dilon.Core/Captcha/ClickWord/Data/Image/12.jpg deleted file mode 100644 index e50ac9021b2da348a6dadb7cbd62625d0922b6d8..0000000000000000000000000000000000000000 Binary files a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/12.jpg and /dev/null differ diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/9.jpg b/backend/Dilon.Core/Captcha/ClickWord/Data/Image/9.jpg deleted file mode 100644 index 548f36bf0b0912a9f241df8af0627b7cad0f4d7f..0000000000000000000000000000000000000000 Binary files a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/9.jpg and /dev/null differ diff --git a/backend/Dilon.Core/Const/ClaimConst.cs b/backend/Dilon.Core/Const/ClaimConst.cs index 0bda0cbbea67d33fa6581c6371bbeb81019f89fe..d9bc93dc06bbf038eb78543a7958a2440e6667cc 100644 --- a/backend/Dilon.Core/Const/ClaimConst.cs +++ b/backend/Dilon.Core/Const/ClaimConst.cs @@ -22,5 +22,10 @@ /// public const string CLAINM_SUPERADMIN = "SuperAdmin"; + /// + /// 是否超级管理 + /// + public const string TENANT_ID = "TenantId"; + } } diff --git a/backend/Dilon.Core/Const/CommonConst.cs b/backend/Dilon.Core/Const/CommonConst.cs index 93e433d1a712b745444af0d391189477edfda6b6..7b304b4bdb39e1fbe752fdd233d802354c9a0436 100644 --- a/backend/Dilon.Core/Const/CommonConst.cs +++ b/backend/Dilon.Core/Const/CommonConst.cs @@ -10,26 +10,26 @@ /// /// 用户缓存 /// - public const string CACHE_KEY_USER = "_user"; + public const string CACHE_KEY_USER = "user_"; /// /// 菜单缓存 /// - public const string CACHE_KEY_MENU = "_menu"; + public const string CACHE_KEY_MENU = "menu_"; /// /// 权限缓存 /// - public const string CACHE_KEY_PERMISSION = "_permission"; + public const string CACHE_KEY_PERMISSION = "permission_"; /// /// 数据范围缓存 /// - public const string CACHE_KEY_DATASCOPE = "_datascope"; + public const string CACHE_KEY_DATASCOPE = "datascope_"; /// /// 验证码缓存 /// - public const string CACHE_KEY_CODE = "_code"; + public const string CACHE_KEY_CODE = "vercode_"; } } diff --git a/backend/Dilon.Core/Dilon.Core.csproj b/backend/Dilon.Core/Dilon.Core.csproj index adb6eb1b19180f1333e330a5cbf51a5edae9a23f..3868329820002cc3c524b049ea8a58af2898b8a4 100644 --- a/backend/Dilon.Core/Dilon.Core.csproj +++ b/backend/Dilon.Core/Dilon.Core.csproj @@ -24,93 +24,25 @@ - - - - - - - + + + + + + + + - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + + + + + PreserveNewest diff --git a/backend/Dilon.Core/Dilon.Core.xml b/backend/Dilon.Core/Dilon.Core.xml index b14d58a58ee9256fc9e5802b40853d5069e2bc7b..3bb722adb1bf62412d5f3084f780f465fe19ede7 100644 --- a/backend/Dilon.Core/Dilon.Core.xml +++ b/backend/Dilon.Core/Dilon.Core.xml @@ -130,6 +130,12 @@ 有效期 + + + 获取所有缓存 + + + 内存缓存 @@ -273,6 +279,11 @@ 是否超级管理 + + + 是否超级管理 + + 默认密码 @@ -303,6 +314,16 @@ 验证码缓存 + + + 自定义租户基类实体 + + + + + 租户id + + 自定义实体基类 @@ -313,11 +334,6 @@ 主键Id - - - 租户Id - - 创建时间 @@ -333,11 +349,21 @@ 创建者Id + + + 创建者名称 + + 修改者Id + + + 修改者名称 + + 软删除 @@ -374,94 +400,119 @@ 排序 - + 代码生成表 - + 作者姓名 - - - 类名 - - - + 是否移除表前缀 - + 生成方式 - + 数据库表名 - + - 包名 + 命名空间 - + - 业务名(业务代码包名称) + 业务名 - + - 功能名(数据库表名称) + 代码生成字段配置表 - + - 文件信息表 + 代码生成主表ID - + - 文件存储位置(1:阿里云,2:腾讯云,3:minio,4:本地) + 数据库字段名 - + - 文件仓库 + 字段描述 - + - 文件名称(上传时候的文件名) + .NET数据类型 - + - 文件后缀 + 作用类型(字典) - + - 文件大小kb + 字典code - + - 文件大小信息,计算后的 + 列表是否缩进(字典) - + - 存储到bucket的名称(文件唯一标识id) + 是否必填(字典) - + - 存储路径 + 是否是查询条件 + + + + + 查询方式 + + + + + 列表显示 + + + + + 增改 + + + + + 主外键 + + + + + 数据库中类型(物理类型) + + + + + 是否通用字段 @@ -639,7 +690,7 @@ - 员工id + 员工Id @@ -674,7 +725,7 @@ - 员工id + 员工Id @@ -692,6 +743,51 @@ 一对一引用(职位) + + + 文件信息表 + + + + + 文件存储位置(1:阿里云,2:腾讯云,3:minio,4:本地) + + + + + 文件仓库 + + + + + 文件名称(上传时候的文件名) + + + + + 文件后缀 + + + + + 文件大小kb + + + + + 文件大小信息,计算后的 + + + + + 存储到bucket的名称(文件唯一标识id) + + + + + 存储路径 + + 系统操作/审计日志表 @@ -737,19 +833,69 @@ 操作方式:新增、更新、删除 - + - 操作日志表 + 异常日志 - + + + 操作人 + + + 名称 - + + + 类名 + + + + + 方法名 + + + + + 异常名称 + + + + + 异常信息 + + + + + 异常源 + + + + + 堆栈信息 + + + + + 参数对象 + + + + + 异常时间 + + + + + 操作日志表 + + + - 操作类型(0其他 1增加 2删除 3编辑)(见LogAnnotionOpTypeEnum) + 名称 @@ -764,7 +910,7 @@ - ip + IP @@ -869,7 +1015,7 @@ - 访问类型(字典 1登入 2登出) + 访问类型 @@ -1049,7 +1195,7 @@ - 通知公告id + 通知公告Id @@ -1074,7 +1220,7 @@ - 第三方平台的用户唯一id + 第三方平台的用户唯一Id @@ -1365,55 +1511,82 @@ 一对一引用(系统菜单) - + - 定时任务 + 租户表 - + - 任务名称 + 公司名称 - dilon - + - 任务分组 + 管理员名称 - dilon - + - 开始时间 + 主机 - + - 结束时间 + 电子邮箱 - null - + - Cron表达式 + 电话 - - + + + 数据库连接 + + + + + 架构 + + + + + 备注 + + + + + 定时任务 + + + - 执行次数(默认无限循环) + 任务名称 - 10 + dilon - 执行间隔时间,单位秒(如果有Cron,则IntervalSecond失效) + 执行间隔时间(单位秒) 5 - + + + Cron表达式 + + + + + + 定时器类型 + + + - 触发器类型 + 执行次数 @@ -1440,7 +1613,7 @@ - 描述 + 备注 @@ -1455,7 +1628,7 @@ - 密码(采用MD5加密) + 密码(默认MD5加密) @@ -1578,7 +1751,7 @@ - 系统用户Id + 用户Id @@ -1606,9 +1779,14 @@ 超级管理员 + + + 管理员 + + - 非管理员 + 普通账号 @@ -1631,6 +1809,81 @@ 删除 + + + 数据操作类型 + + + + + 其它 + + + + + 增加 + + + + + 删除 + + + + + 编辑 + + + + + 更新 + + + + + 查询 + + + + + 详情 + + + + + 树 + + + + + 导入 + + + + + 导出 + + + + + 授权 + + + + + 强退 + + + + + 清空 + + + + + 修改状态 + + 全部数据 @@ -1781,6 +2034,11 @@ 附属机构下有员工禁止删除 + + + 只能增加下级机构 + + 字典类型不存在 @@ -1926,34 +2184,64 @@ 演示环境禁止修改数据 - + - 已存在同名或同编码项目 + 已存在同名或同主机租户 - + - 已存在相同证件号码人员 + 该表代码模板已经生成过 - + - 检测数据不存在 + 该类型不存在 - + - 文件存储位置 + 该字段不存在 - + - 阿里云 + 该类型不是枚举类型 - + - 腾讯云 + 该实体不存在 + + + + + 已存在同名或同编码项目 + + + + + 已存在相同证件号码人员 + + + + + 检测数据不存在 + + + + + 文件存储位置 + + + + + 阿里云 + + + + + 腾讯云 @@ -1986,79 +2274,241 @@ 未知 - + - 日志操作类型 + HTTP状态码 - + - 其它 + 客户端可能继续其请求 - + - 增加 + 正在更改协议版本或协议 - + - 删除 + 请求成功,且请求的信息包含在响应中 - + - 编辑 + 请求导致在响应被发送前创建新资源 - + - 更新 + 请求已被接受做进一步处理 - + - 查询 + 返回的元信息来自缓存副本而不是原始服务器,因此可能不正确 - + - 详情 + 已成功处理请求并且响应已被设定为无内容 - + - 树 + 客户端应重置(或重新加载)当前资源 - + - 导入 + 响应是包括字节范围的 GET请求所请求的部分响应 - + - 导出 + 请求的信息有多种表示形式,默认操作是将此状态视为重定向 - + - 授权 + 请求的信息已移到 Location头中指定的 URI 处 - + - 强退 + 请求的信息位于 Location 头中指定的 URI 处 - + - 清空 + 将客户端自动重定向到 Location 头中指定的 URI - + - 修改状态 + 客户端的缓存副本是最新的 + + + + + 请求应使用位于 Location 头中指定的 URI 的代理服务器 + + + + + 服务器未能识别请求 + + + + + 请求的资源要求身份验证 + + + + + 需要付费 + + + + + 服务器拒绝满足请求 + + + + + 请求的资源不在服务器上 + + + + + 请求的资源上不允许请求方法(POST或 GET) + + + + + 客户端已用 Accept 头指示将不接受资源的任何可用表示形式 + + + + + 请求的代理要求身份验证 + Proxy-authenticate 头包含如何执行身份验证的详细信息 + + + + + 客户端没有在服务器期望请求的时间内发送请求 + + + + + 由于服务器上的冲突而未能执行请求 + + + + + 请求的资源不再可用 + + + + + 缺少必需的 Content-length + + + + + 为此请求设置的条件失败,且无法执行此请求 + 条件是用条件请求标头(如 If-Match、If-None-Match 或 If-Unmodified-Since)设置的。 + + + + + 请求太大,服务器无法处理 + + + + + URI 太长 + + + + + 请求是不支持的类型 + + + + + 无法返回从资源请求的数据范围,因为范围的开头在资源的开头之前,或因为范围的结尾在资源的结尾之后 + + + + + 服务器未能符合Expect头中给定的预期值 + + + + + 服务器拒绝处理客户端使用当前协议发送的请求,但是可以接受其使用升级后的协议发送的请求 + + + + + 服务器上发生了一般错误 + + + + + 服务器不支持请求的函数 + + + + + 中间代理服务器从另一代理或原始服务器接收到错误响应 + + + + + 服务器暂时不可用,通常是由于过多加载或维护 + + + + + 中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时 + + + + + 服务器不支持请求的HTTP版本 + + + + + 登陆类型 + + + + + 登陆 + + + + + 登出 + + + + + 注册 + + + + + 改密 + + + + + 三方授权登陆 @@ -2161,6 +2611,81 @@ 已读 + + + 查询类型的枚举 + + + + + 等于 + + + + + 模糊 + + + + + 大于 + + + + + 小于 + + + + + 不等于 + + + + + 大于等于 + + + + + 小于等于 + + + + + 不为空 + + + + + http请求类型 + + + + + 无 + + + + + GET请求 + + + + + POST请求 + + + + + PUT请求 + + + + + DELETE请求 + + 菜单激活类型 @@ -2202,6 +2727,69 @@ + + + 枚举扩展 + + + + + 获取枚举对象Key与名称的字典(缓存) + + + + + + + 获取枚举对象Key与名称的字典 + + + + + + + 获取枚举类型key与描述的字典(缓存) + + + + + + + + 获取枚举类型key与描述的字典(没有描述则获取name) + + + + + + + + 从程序集中查找指定枚举类型 + + + + + + + + 从程序集中加载所有枚举类型 + + + + + + + 通用输入帮助类 + + + + + 排序方式(默认降序) + + + 是否降序 + + 通用输入扩展参数(带权限) @@ -2252,6 +2840,21 @@ 搜索结束时间 + + + 排序字段 + + + + + 排序方法,默认升序,否则降序(配合antd前端,约定参数为 Ascend,Dscend) + + + + + 降序排序(不要问我为什么是descend不是desc,前端约定参数就是这样) + + 小诺分页列表结果 @@ -2270,14 +2873,6 @@ - - - 处理输出状态码 - - - - - 成功返回值 @@ -2295,6 +2890,15 @@ + + + 处理输出状态码 + + + + + + RESTful风格---XIAONUO返回格式 @@ -2532,14 +3136,6 @@ - - - 扩展机构种子数据 - - - - - 系统员工职位表种子数据 @@ -2605,12 +3201,7 @@ - - - 系统角色表种子数据 - - - + 种子数据 @@ -2618,6 +3209,40 @@ + + + 种子数据 + + + + + + + + 种子数据 + + + + + + + + 系统角色表种子数据 + + + + + 种子数据 + + + + + + + + 租户种子数据 + + 系统任务调度表种子数据 @@ -2700,6 +3325,11 @@ 系统应用参数 + + + 应用Id + + 名称 @@ -2964,6 +3594,29 @@ 数据范围(机构)信息 + + + 注册输入参数 + + + + + 用户名 + + superAdmin + + + + 公司名 + + superAdmin + + + + 密码 + + 123456 + 系统缓存服务 @@ -3029,6 +3682,13 @@ + + + 删除某特征关键字缓存 + + + + 设置缓存 @@ -3052,54 +3712,439 @@ + + + 代码生成详细配置服务 + + + + + 代码生成详细配置列表 + + + + + + + 增加 + + + + + + + 删除 + + + + + + + 更新 + + + + + + + 详情 + + + + + + + 批量增加 + + + + + + + 数据类型转显示类型 + + + + 代码生成器服务 - + + + 分页查询 + + + + + + + 增加 + + + + + + + 删除 + + + + + + + 更新 + + + + + + + 详情 + + + + + + + 获取数据库表(实体)集合 + + + + + + 获取数据表列(实体属性)集合 + + + + + + 代码生成_本地项目 + + + + + + 获取模板文件路径集合 + + + + + + 设置生成文件路径 + + + + + + + 代码生成详细配置参数 + + + + + 主键 + + + + + 代码生成主表ID + + + + + 数据库字段名 + + + + + 字段描述 + + + + + .NET类型 + + + + + 作用类型(字典) + + + + + 字典code + + + + + 列表是否缩进(字典) + + + + + 是否必填(字典) + + + + + 是否是查询条件 + + + + + 查询方式 + + + + + 列表显示 + + + + + 增改 + + + + + 主外键 + + + + + 数据库中类型(物理类型) + + + + + 是否是通用字段 + + + + + 代码生成参数类 + + + + + 作者姓名 + + + + + 类名 + + + + + 是否移除表前缀 + + + + + 生成方式 + + + + + 数据库表名 + + + + + 命名空间 + + + + + 业务名(业务代码包名称) + + + + + 功能名(数据库表名称) + + + + + 数据库表名 + + + + + 业务名(业务代码包名称) + + + + + 命名空间 + + + + + 作者姓名 + + + + + 生成方式 + + + + + 代码生成器Id + + + + + 代码生成器Id + + + 代码生成参数类 - + + + 代码生成器Id + + + 作者姓名 - + 类名 - + 是否移除表前缀 - + + + 生成方式 + + + + + 数据库表名 + + + + + 包名 + + + + + 业务名(业务代码包名称) + + + + + 功能名(数据库表名称) + + + + + 数据库表列 + + + + + 字段名 + + + + + 数据库中类型 + + + + + 字段描述 + + + + + 主外键 + + + + + 数据库表列表参数 + + + + + 表名(字母形式的) + + + + + 创建时间 + + + + + 更新时间 + + + + + 表名称描述(注释)(功能名) + + + + + 作者姓名 + + + + + 是否移除表前缀 + + + + + 生成方式 + + + + + 数据库表名 + + + - 生成方式 + 数据库表名(经过组装的) - + - 数据库表名 + 代码包名 - + - 包名 + 生成时间(string类型的) - + - 业务名(业务代码包名称) + 数据库表中字段集合 - + - 功能名(数据库表名称) + 业务名 @@ -3236,6 +4281,12 @@ + + + 获取日志写入间隔和数量 + + + 字典值参数 @@ -3306,6 +4357,11 @@ 字典值参数 + + + 字典Id + + 字典类型与字典值构造的树 @@ -3761,6 +4817,67 @@ + + + 获取子机构用户 + + + + + + + 枚举输入参数 + + + + + 枚举类型名称 + + + + + 实体名称 + + + + + 字段名称 + + + + + 枚举输出参数 + + + + + 字典Id + + + + + 字典值 + + + + + 枚举值服务 + + + + + 通过枚举类型获取枚举值集合 + + + + + + + 通过实体字段类型获取相关集合(目前仅支持枚举类型) + + + + 上传文件参数 @@ -3816,6 +4933,11 @@ 上传文件参数 + + + 文件Id + + 文件服务 @@ -3899,19 +5021,59 @@ - + - 请求日志参数 + 异常日志参数 - + + + 操作人 + + + 名称 - + + + 类名 + + + + + 方法名 + + + + + 异常名称 + + + + + 异常信息 + + + + + 异常时间 + + + + + 异常日志参数 + + + + + 请求日志参数 + + + - 操作类型(0其他 1增加 2删除 3编辑)(见LogAnnotionOpTypeEnum) + 名称 @@ -4036,7 +5198,7 @@ - 访问类型(字典 1登入 2登出) + 访问类型 @@ -4054,6 +5216,24 @@ 访问日志参数 + + + 异常日志服务 + + + + + 分页查询异常日志 + + + + + + + 清空异常日志 + + + 操作日志服务 @@ -4698,7 +5878,7 @@ 通知公告用户 - + 增加 @@ -4707,7 +5887,7 @@ - + 更新 @@ -4723,7 +5903,7 @@ - + 设置通知公告读取状态 @@ -4956,6 +6136,12 @@ + + + 获取所有的机构组织Id集合 + + + 获取用户数据范围(机构Id集合) @@ -5312,319 +6498,352 @@ - + - 任务调度参数 + 租户参数 - + - 任务名称 + 公司名称 - dilon - + - 任务分组 + 管理员名称 - dilon - + - 开始时间 + 主机 - + - 结束时间 + 电子邮箱 - null - + - Cron表达式 + 电话号码 - - + - 执行次数(默认无限循环) + 模式 - 10 - + - 执行间隔时间,单位秒(如果有Cron,则IntervalSecond失效) + 数据库连接 - 5 - + - 触发器类型 + 备注 - + - 请求url + 创建时间 - + - 请求参数(Post,Put请求用) + 公司名称 - + - Headers(可以包含如:Authorization授权认证) - 格式:{"Authorization":"userpassword.."} + 管理员名称 - + - 请求类型 + 主机名称 - 2 - + - 描述 + 数据库连接 - + - 任务状态 + 电子邮箱 - + - 任务Id + 租户Id - + - 任务信息---任务详情 + 租户Id - + - 任务名称 + 租户参数 - + - 任务组名 + 租户Id - + - 下次执行时间 + 名称 - + - 上次执行时间 + 名称 - + - 开始时间 + 主机 - + - 结束时间 + 电子邮箱 - + - 上次执行的异常信息 + 电话号码 - + - 任务状态 + 模式 - + - 描述 + 数据库连接 - + - 显示状态 + 备注 - + - 时间间隔 + 创建时间 - + - 请求地址 + 租户服务 - + - 请求类型 + 分页查询租户 + + - + - 已经执行的次数 + 增加租户 + + - + - 任务调度中心 + 新增租户时,初始化数据 + - + - 开启调度器 + 删除租户 + - + - 停止调度器 + 更新租户 + + - + - 添加一个工作任务 + 获取租户 - + - 暂停任务 + 授权租户管理员角色菜单 - + - 删除任务 + 获取租户管理员角色拥有菜单Id集合 - + - 恢复运行暂停的任务 + 重置租户管理员密码 - + - 查询任务 + 获取租户管理员用户 - + - + - 立即执行 + 任务调度参数 - - - + - 获取任务日志 + 任务名称 - - - + - 获取任务运行次数 + 执行间隔时间(单位秒) - - + 5 - + - 获取所有任务详情 + Cron表达式 - - + - 从数据库里面获取所有任务并初始化 + 定时器类型 - + - 创建类型Simple的触发器 + 执行次数 - - - + - 创建类型Cron的触发器 + 请求url + + + + + 请求参数(Post,Put请求用) + + + + + Headers(可以包含如:Authorization授权认证) + 格式:{"Authorization":"userpassword.."} + + + + + 请求类型 + + + + + 备注 - - - + - 任务调度相关常量 + 任务Id - + - 请求url RequestUrl + 任务信息---任务详情 - + - 请求参数 RequestParameters + Id - + - Headers(可以包含:Authorization授权认证) + 任务名称 - + - 请求类型 RequestType + 执行间隔时间(单位秒) - + - 日志 LogList + Cron表达式 - + - 异常 Exception + 定时器类型 - + 执行次数 - + - 任务结束时间 + 请求url - + - http请求类型 + 请求参数(Post,Put请求用) + + + + + Headers(可以包含如:Authorization授权认证) + 格式:{"Authorization":"userpassword.."} + + + + + 请求类型 + + 2 + + + + 备注 + + + + + 定时器状态 - + - 触发器类型 + 异常信息 @@ -5632,28 +6851,28 @@ 任务调度服务 - + 分页获取任务列表 - + 增加任务 - + 删除任务 - + 修改任务 @@ -5667,20 +6886,33 @@ - + 停止任务 - + 启动任务 + + + 新增定时任务 + + + + + + 初始化定时任务 + + + + AuthToken参数 @@ -6047,11 +7279,18 @@ - 用户导出(未实现) + 用户导出 + + + 用户导入 + + + + 根据用户Id获取用户 @@ -6185,6 +7424,19 @@ + + + 反射工具 + + + + + 获取字段特性 + + + + + 树基类 diff --git a/backend/Dilon.Core/Entity/DBEntityTenant.cs b/backend/Dilon.Core/Entity/DBEntityTenant.cs new file mode 100644 index 0000000000000000000000000000000000000000..d899b77325b89b36f69f5d5a0ed864957a0d633b --- /dev/null +++ b/backend/Dilon.Core/Entity/DBEntityTenant.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; + +namespace Dilon.Core.Entity +{ + /// + /// 自定义租户基类实体 + /// + public abstract class DBEntityTenant : DEntityBase + { + /// + /// 租户id + /// + [Comment("租户id")] + public virtual long? TenantId { get; set; } + } +} diff --git a/backend/Dilon.Core/Entity/DEntityBase.cs b/backend/Dilon.Core/Entity/DEntityBase.cs index 50e7135b2d709dbb1f68b42f636487d8a1585405..e9d6801aac770cdfc3e1601d3c34e87a33fa054f 100644 --- a/backend/Dilon.Core/Entity/DEntityBase.cs +++ b/backend/Dilon.Core/Entity/DEntityBase.cs @@ -1,4 +1,5 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -16,38 +17,52 @@ namespace Dilon.Core /// [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] + [Comment("Id主键")] public virtual long Id { get; set; } - /// - /// 租户Id - /// - [JsonIgnore] - public virtual Guid? TenantId { get; set; } - /// /// 创建时间 /// + [Comment("创建时间")] public virtual DateTimeOffset? CreatedTime { get; set; } /// /// 更新时间 /// + [Comment("更新时间")] public virtual DateTimeOffset? UpdatedTime { get; set; } /// /// 创建者Id /// + [Comment("创建者Id")] public virtual long? CreatedUserId { get; set; } + /// + /// 创建者名称 + /// + [Comment("创建者名称")] + [MaxLength(20)] + public virtual string CreatedUserName { get; set; } + /// /// 修改者Id /// + [Comment("修改者Id")] public virtual long? UpdatedUserId { get; set; } + /// + /// 修改者名称 + /// + [Comment("修改者名称")] + [MaxLength(20)] + public virtual string UpdatedUserName { get; set; } + /// /// 软删除 /// [JsonIgnore, FakeDelete(true)] - public virtual bool IsDeleted { get; set; } + [Comment("软删除标记")] + public virtual bool IsDeleted { get; set; } = false; } } diff --git a/backend/Dilon.Core/Entity/SysApp.cs b/backend/Dilon.Core/Entity/SysApp.cs index aab29d944e5b0b4c39f18450692e2dc8d2bf90c1..447e534a977904982203bd2364759835d6fa8cc1 100644 --- a/backend/Dilon.Core/Entity/SysApp.cs +++ b/backend/Dilon.Core/Entity/SysApp.cs @@ -1,5 +1,5 @@ -using Furion.Snowflake; -using System; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -8,40 +8,41 @@ namespace Dilon.Core /// 系统应用表 /// [Table("sys_app")] + [Comment("系统应用表")] public class SysApp : DEntityBase { - public SysApp() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 名称 /// + [Comment("名称")] + [Required, MaxLength(20)] public string Name { get; set; } /// /// 编码 /// + [Comment("编码")] + [Required, MaxLength(50)] public string Code { get; set; } /// /// 是否默认激活(Y-是,N-否),只能有一个系统默认激活 /// 用户登录后默认展示此系统菜单 /// + [Comment("是否默认激活")] + [MaxLength(5)] public string Active { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + [Comment("状态")] + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 排序 /// + [Comment("排序")] public int Sort { get; set; } } } diff --git a/backend/Dilon.Core/Entity/SysCodeGen.cs b/backend/Dilon.Core/Entity/SysCodeGen.cs index 983eee1cefae01563e05dd2d06dc89145e3d0f8a..1ab18823df91f803537396a228c9c9627e5a84de 100644 --- a/backend/Dilon.Core/Entity/SysCodeGen.cs +++ b/backend/Dilon.Core/Entity/SysCodeGen.cs @@ -1,60 +1,56 @@ -using Furion.Snowflake; -using System; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace Dilon.Core.Entity +namespace Dilon.Core { /// /// 代码生成表 /// [Table("sys_code_gen")] + [Comment("代码生成表")] public class SysCodeGen : DEntityBase { - public SysCodeGen() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - } - /// /// 作者姓名 /// + [Comment("作者姓名")] + [MaxLength(20)] public string AuthorName { get; set; } - /// - /// 类名 - /// - public string ClassName { get; set; } - /// /// 是否移除表前缀 /// + [Comment("是否移除表前缀")] + [MaxLength(5)] public string TablePrefix { get; set; } /// /// 生成方式 /// + [Comment("生成方式")] + [MaxLength(20)] public string GenerateType { get; set; } /// /// 数据库表名 /// + [Comment("数据库表名")] + [MaxLength(100)] public string TableName { get; set; } /// - /// 包名 + /// 命名空间 /// - public string PackageName { get; set; } + [Comment("命名空间")] + [MaxLength(100)] + public string NameSpace { get; set; } /// - /// 业务名(业务代码包名称) + /// 业务名 /// + [Comment("业务名")] + [MaxLength(100)] public string BusName { get; set; } - - /// - /// 功能名(数据库表名称) - /// - public string TableComment { get; set; } } } diff --git a/backend/Dilon.Core/Entity/SysCodeGenConfig.cs b/backend/Dilon.Core/Entity/SysCodeGenConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..1ee21be7e8c96718e4183b6d066e80e99a106900 --- /dev/null +++ b/backend/Dilon.Core/Entity/SysCodeGenConfig.cs @@ -0,0 +1,118 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Dilon.Core +{ + /// + /// 代码生成字段配置表 + /// + [Table("sys_code_gen_config")] + [Comment("代码生成字段配置表")] + public class SysCodeGenConfig : DEntityBase + { + /// + /// 代码生成主表ID + /// + [Comment("代码生成主表ID")] + public long CodeGenId { get; set; } + + /// + /// 数据库字段名 + /// + [Comment("数据库字段名")] + [Required, MaxLength(100)] + public string ColumnName { get; set; } + + /// + /// 字段描述 + /// + [Comment("字段描述")] + [MaxLength(100)] + public string ColumnComment { get; set; } + + /// + /// .NET数据类型 + /// + [Comment(".NET数据类型")] + [MaxLength(50)] + public string NetType { get; set; } + + /// + /// 作用类型(字典) + /// + [Comment("作用类型")] + [MaxLength(50)] + public string EffectType { get; set; } + + /// + /// 字典code + /// + [Comment("字典Code")] + [MaxLength(50)] + public string DictTypeCode { get; set; } + + /// + /// 列表是否缩进(字典) + /// + [Comment("列表是否缩进")] + [MaxLength(5)] + public string WhetherRetract { get; set; } + + /// + /// 是否必填(字典) + /// + [Comment("是否必填")] + [MaxLength(5)] + public string WhetherRequired { get; set; } + + /// + /// 是否是查询条件 + /// + [Comment("是否是查询条件")] + [MaxLength(5)] + public string QueryWhether { get; set; } + + /// + /// 查询方式 + /// + [Comment("查询方式")] + [MaxLength(10)] + public string QueryType { get; set; } + + /// + /// 列表显示 + /// + [Comment("列表显示")] + [MaxLength(5)] + public string WhetherTable { get; set; } + + /// + /// 增改 + /// + [Comment("增改")] + [MaxLength(5)] + public string WhetherAddUpdate { get; set; } + + /// + /// 主外键 + /// + [Comment("主外键")] + [MaxLength(5)] + public string ColumnKey { get; set; } + + /// + /// 数据库中类型(物理类型) + /// + [Comment("数据库中类型")] + [MaxLength(50)] + public string DataType { get; set; } + + /// + /// 是否通用字段 + /// + [Comment("是否通用字段")] + [MaxLength(5)] + public string WhetherCommon { get; set; } + } +} diff --git a/backend/Dilon.Core/Entity/SysConfig.cs b/backend/Dilon.Core/Entity/SysConfig.cs index 7c0f8ab238e4c2bbd9eb932127588b49eb2dafc5..bb58acc608db7778ebb0e1a20229c28dd92e8b4e 100644 --- a/backend/Dilon.Core/Entity/SysConfig.cs +++ b/backend/Dilon.Core/Entity/SysConfig.cs @@ -1,9 +1,9 @@ using Dilon.Core.Service; using Furion; using Furion.DatabaseAccessor; -using Furion.Snowflake; using Microsoft.EntityFrameworkCore; using System; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -12,49 +12,55 @@ namespace Dilon.Core /// 参数配置表 /// [Table("sys_config")] + [Comment("参数配置表")] public class SysConfig : DEntityBase, IEntityChangedListener { - public SysConfig() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 名称 /// + [Comment("名称")] + [Required, MaxLength(50)] public string Name { get; set; } /// /// 编码 /// + [Comment("编码")] + [Required, MaxLength(50)] public string Code { get; set; } /// /// 属性值 /// + [Comment("属性值")] + [MaxLength(50)] public string Value { get; set; } /// /// 是否是系统参数(Y-是,N-否) /// + [Comment("是否是系统参数")] + [MaxLength(5)] public string SysFlag { get; set; } /// /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + [Comment("状态")] + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 常量所属分类的编码,来自于“常量的分类”字典 /// + [Comment("常量所属分类的编码")] + [MaxLength(50)] public string GroupCode { get; set; } /// diff --git a/backend/Dilon.Core/Entity/SysDictData.cs b/backend/Dilon.Core/Entity/SysDictData.cs index 6c8fc56fc11dd15ecdf80cfd4934d501d5190b7d..3827daa878365d4ba9b3b0c40017038ef33b6eba 100644 --- a/backend/Dilon.Core/Entity/SysDictData.cs +++ b/backend/Dilon.Core/Entity/SysDictData.cs @@ -1,5 +1,5 @@ -using Furion.Snowflake; -using System; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -8,45 +8,47 @@ namespace Dilon.Core /// 字典值表 /// [Table("sys_dict_data")] + [Comment("字典值表")] public class SysDictData : DEntityBase { - public SysDictData() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 字典类型Id /// + [Comment("字典类型Id")] public long TypeId { get; set; } /// /// 值 /// + [Comment("值")] + [MaxLength(100)] public string Value { get; set; } /// /// 编码 /// + [Comment("编码")] + [MaxLength(50)] public string Code { get; set; } /// /// 排序 /// + [Comment("排序")] public int Sort { get; set; } /// /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + [Comment("状态")] + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 所属类型 diff --git a/backend/Dilon.Core/Entity/SysDictType.cs b/backend/Dilon.Core/Entity/SysDictType.cs index bea631285d211a017dbf8ce522fe2f9b6dc7a174..831b4903d13cc056a93e17f94e563e9af6fd17b3 100644 --- a/backend/Dilon.Core/Entity/SysDictType.cs +++ b/backend/Dilon.Core/Entity/SysDictType.cs @@ -1,9 +1,9 @@ using Furion.DatabaseAccessor; -using Furion.Snowflake; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -12,40 +12,41 @@ namespace Dilon.Core /// 字典类型表 /// [Table("sys_dict_type")] + [Comment("字典类型表")] public class SysDictType : DEntityBase, IEntityTypeBuilder { - public SysDictType() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 名称 /// + [Comment("名称")] + [Required, MaxLength(50)] public string Name { get; set; } /// /// 编码 /// + [Comment("编码")] + [Required, MaxLength(50)] public string Code { get; set; } /// /// 排序 /// + [Comment("排序")] public int Sort { get; set; } /// /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + [Comment("状态")] + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 字典数据 @@ -54,7 +55,9 @@ namespace Dilon.Core public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator) { - entityBuilder.HasMany(x => x.SysDictDatas).WithOne(x => x.SysDictType).HasForeignKey(x => x.TypeId); + entityBuilder.HasMany(x => x.SysDictDatas) + .WithOne(x => x.SysDictType) + .HasForeignKey(x => x.TypeId); } } } diff --git a/backend/Dilon.Core/Entity/SysEmp.cs b/backend/Dilon.Core/Entity/SysEmp.cs index bdb24bde536916605fab946f4e747fd7df2f8d94..5a31051d3b08b7496a42264c4cbce9dd7aa5969b 100644 --- a/backend/Dilon.Core/Entity/SysEmp.cs +++ b/backend/Dilon.Core/Entity/SysEmp.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -11,26 +12,34 @@ namespace Dilon.Core /// 员工表 /// [Table("sys_emp")] + [Comment("员工表")] public class SysEmp : IEntity, IEntityTypeBuilder { /// /// 用户Id /// + [DatabaseGenerated(DatabaseGeneratedOption.None)] + [Comment("用户Id")] public long Id { get; set; } /// /// 工号 /// + [Comment("工号")] + [MaxLength(30)] public string JobNum { get; set; } /// /// 机构Id /// + [Comment("机构Id")] public long OrgId { get; set; } /// /// 机构名称 /// + [Comment("机构名称")] + [MaxLength(50)] public string OrgName { get; set; } /// diff --git a/backend/Dilon.Core/Entity/SysEmpExtOrgPos.cs b/backend/Dilon.Core/Entity/SysEmpExtOrgPos.cs index 9877b3ba0a380b5dc9501014046f804817901d84..0730bba80261da3de3679074ae2e8e02a27dfa48 100644 --- a/backend/Dilon.Core/Entity/SysEmpExtOrgPos.cs +++ b/backend/Dilon.Core/Entity/SysEmpExtOrgPos.cs @@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -10,11 +11,13 @@ namespace Dilon.Core /// 员工附属机构职位表 /// [Table("sys_emp_ext_org_pos")] - public class SysEmpExtOrgPos : IEntity, IEntityTypeBuilder + [Comment("员工附属机构职位表")] + public class SysEmpExtOrgPos : IEntity, IEntityTypeBuilder, IEntitySeedData { /// - /// 员工id + /// 员工Id /// + [Comment("员工Id")] public long SysEmpId { get; set; } /// @@ -25,6 +28,7 @@ namespace Dilon.Core /// /// 机构Id /// + [Comment("机构Id")] public long SysOrgId { get; set; } /// @@ -35,6 +39,7 @@ namespace Dilon.Core /// /// 职位Id /// + [Comment("职位Id")] public long SysPosId { get; set; } /// @@ -44,7 +49,19 @@ namespace Dilon.Core public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator) { - entityBuilder.HasNoKey(); + entityBuilder.HasKey(c => new { c.SysEmpId, c.SysOrgId, c.SysPosId }); + } + + public IEnumerable HasData(DbContext dbContext, Type dbContextLocator) + { + return new[] + { + new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910539, SysPosId = 142307070910547 }, + new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910540, SysPosId = 142307070910548 }, + new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910541, SysPosId = 142307070910549 }, + new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910542, SysPosId = 142307070910550 }, + new SysEmpExtOrgPos { SysEmpId = 142307070910553, SysOrgId = 142307070910542, SysPosId = 142307070910547 } + }; } } } diff --git a/backend/Dilon.Core/Entity/SysEmpPos.cs b/backend/Dilon.Core/Entity/SysEmpPos.cs index d9df3c7dcc07780e8972b3d2129ae3b2d8c3283d..9380a4bdf11413262a1375094f2c2b6563befae1 100644 --- a/backend/Dilon.Core/Entity/SysEmpPos.cs +++ b/backend/Dilon.Core/Entity/SysEmpPos.cs @@ -1,4 +1,5 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -7,11 +8,13 @@ namespace Dilon.Core /// 员工职位表 /// [Table("sys_emp_pos")] + [Comment("员工职位表")] public class SysEmpPos : IEntity { /// - /// 员工id + /// 员工Id /// + [Comment("员工Id")] public long SysEmpId { get; set; } /// @@ -22,6 +25,7 @@ namespace Dilon.Core /// /// 职位Id /// + [Comment("职位Id")] public long SysPosId { get; set; } /// diff --git a/backend/Dilon.Core/Entity/SysFile.cs b/backend/Dilon.Core/Entity/SysFile.cs index 948161d2f05d4d4fd501a63f05083f7785945b68..4f5e0575d251ec4cbe88e12b84fcfede94507675 100644 --- a/backend/Dilon.Core/Entity/SysFile.cs +++ b/backend/Dilon.Core/Entity/SysFile.cs @@ -1,60 +1,68 @@ -using Furion.Snowflake; -using System; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace Dilon.Core.Entity.System +namespace Dilon.Core { /// /// 文件信息表 /// [Table("sys_file")] + [Comment("文件信息表")] public class SysFile : DEntityBase { - public SysFile() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - } - /// /// 文件存储位置(1:阿里云,2:腾讯云,3:minio,4:本地) /// + [Comment("文件存储位置")] public int FileLocation { get; set; } /// /// 文件仓库 /// + [Comment("文件仓库")] + [MaxLength(100)] public string FileBucket { get; set; } /// /// 文件名称(上传时候的文件名) /// + [Comment("文件名称")] + [MaxLength(100)] public string FileOriginName { get; set; } /// /// 文件后缀 /// + [Comment("文件后缀")] + [MaxLength(100)] public string FileSuffix { get; set; } /// /// 文件大小kb /// + [Comment("文件大小kb")] public long FileSizeKb { get; set; } /// /// 文件大小信息,计算后的 /// + [Comment("文件大小信息")] + [MaxLength(100)] public string FileSizeInfo { get; set; } /// /// 存储到bucket的名称(文件唯一标识id) /// + [Comment("存储到bucket的名称")] + [MaxLength(100)] public string FileObjectName { get; set; } /// /// 存储路径 /// + [Comment("存储路径")] + [MaxLength(100)] public string FilePath { get; set; } } } diff --git a/backend/Dilon.Core/Entity/SysLogAudit.cs b/backend/Dilon.Core/Entity/SysLogAudit.cs index c773bd60fd2acf1428d320fa4af99f0c0b85585f..002c4d1746f28832e76ec09f82ad5b83eaf8a6a2 100644 --- a/backend/Dilon.Core/Entity/SysLogAudit.cs +++ b/backend/Dilon.Core/Entity/SysLogAudit.cs @@ -1,5 +1,7 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -8,46 +10,58 @@ namespace Dilon.Core /// 系统操作/审计日志表 /// [Table("sys_log_audit")] + [Comment("审计日志表")] public class SysLogAudit : EntityBase { /// /// 表名 /// + [Comment("表名")] + [MaxLength(50)] public string TableName { get; set; } /// /// 列名 /// + [Comment("列名")] + [MaxLength(50)] public string ColumnName { get; set; } /// /// 新值 /// + [Comment("新值")] public string NewValue { get; set; } /// /// 旧值 /// + [Comment("旧值")] public string OldValue { get; set; } /// /// 操作时间 /// + [Comment("操作时间")] public DateTimeOffset CreatedTime { get; set; } /// /// 操作人Id /// + [Comment("操作人Id")] public long UserId { get; set; } /// /// 操作人名称 /// + [Comment("操作人名称")] + [MaxLength(20)] public string UserName { get; set; } /// /// 操作方式:新增、更新、删除 /// - public string Operate { get; set; } + [Comment("操作方式")] + public DataOpType Operate { get; set; } } -} +} \ No newline at end of file diff --git a/backend/Dilon.Core/Entity/SysLogEx.cs b/backend/Dilon.Core/Entity/SysLogEx.cs new file mode 100644 index 0000000000000000000000000000000000000000..d2354ad7d150333e02076a5333bd8665ec23dbbf --- /dev/null +++ b/backend/Dilon.Core/Entity/SysLogEx.cs @@ -0,0 +1,84 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; + +namespace Dilon.Core +{ + /// + /// 异常日志 + /// + [Table("sys_log_ex")] + [Comment("异常日志表")] + public class SysLogEx : EntityBase + { + /// + /// 操作人 + /// + [Comment("操作人")] + [MaxLength(20)] + public string Account { get; set; } + + /// + /// 名称 + /// + [Comment("名称")] + [MaxLength(100)] + public string Name { get; set; } + + /// + /// 类名 + /// + [Comment("类名")] + [MaxLength(100)] + public string ClassName { get; set; } + + /// + /// 方法名 + /// + [Comment("方法名")] + [MaxLength(100)] + public string MethodName { get; set; } + + /// + /// 异常名称 + /// + [Comment("异常名称")] + public string ExceptionName { get; set; } + + /// + /// 异常信息 + /// + [MaxLength(2000)] + [Comment("异常信息")] + public string ExceptionMsg { get; set; } + + /// + /// 异常源 + /// + [MaxLength(2000)] + [Comment("异常源")] + public string ExceptionSource { get; set; } + + /// + /// 堆栈信息 + /// + [MaxLength(5000)] + [Comment("堆栈信息")] + public string StackTrace { get; set; } + + /// + /// 参数对象 + /// + [MaxLength(5000)] + [Comment("参数对象")] + public string ParamsObj { get; set; } + + /// + /// 异常时间 + /// + [Comment("异常时间")] + public DateTimeOffset ExceptionTime { get; set; } + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Entity/SysLogOp.cs b/backend/Dilon.Core/Entity/SysLogOp.cs index d0888d03cdb2aa0a639336a300208be921eb7d97..ca7f9e7409edae14d6b46f66462050d52cedf358 100644 --- a/backend/Dilon.Core/Entity/SysLogOp.cs +++ b/backend/Dilon.Core/Entity/SysLogOp.cs @@ -1,5 +1,7 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -8,91 +10,113 @@ namespace Dilon.Core /// 操作日志表 /// [Table("sys_log_op")] + [Comment("操作日志表")] public class SysLogOp : EntityBase { /// /// 名称 /// + [Comment("名称")] + [MaxLength(100)] public string Name { get; set; } - /// - /// 操作类型(0其他 1增加 2删除 3编辑)(见LogAnnotionOpTypeEnum) - /// - public int? OpType { get; set; } - /// /// 是否执行成功(Y-是,N-否) /// - public string Success { get; set; } + [Comment("是否执行成功")] + public YesOrNot Success { get; set; } /// /// 具体消息 /// + [Comment("具体消息")] public string Message { get; set; } /// - /// ip + /// IP /// + [Comment("IP")] + [MaxLength(20)] public string Ip { get; set; } /// /// 地址 /// + [Comment("地址")] + [MaxLength(100)] public string Location { get; set; } /// /// 浏览器 /// + [Comment("浏览器")] + [MaxLength(100)] public string Browser { get; set; } /// /// 操作系统 /// + [Comment("操作系统")] + [MaxLength(100)] public string Os { get; set; } /// /// 请求地址 /// + [Comment("请求地址")] + [MaxLength(100)] public string Url { get; set; } /// /// 类名称 /// + [Comment("类名称")] + [MaxLength(100)] public string ClassName { get; set; } /// /// 方法名称 /// + [Comment("方法名称")] + [MaxLength(100)] public string MethodName { get; set; } /// /// 请求方式(GET POST PUT DELETE) /// + [Comment("请求方式")] + [MaxLength(10)] public string ReqMethod { get; set; } /// /// 请求参数 /// + [Comment("请求参数")] public string Param { get; set; } /// /// 返回结果 /// + [Comment("返回结果")] public string Result { get; set; } /// /// 耗时(毫秒) /// + [Comment("耗时")] public long ElapsedTime { get; set; } /// /// 操作时间 /// + [Comment("操作时间")] public DateTimeOffset OpTime { get; set; } /// /// 操作人 /// + [Comment("操作人")] + [MaxLength(20)] public string Account { get; set; } } } diff --git a/backend/Dilon.Core/Entity/SysLogVis.cs b/backend/Dilon.Core/Entity/SysLogVis.cs index 74fa83e4a9ffcbf5a08b9a35118ede21b0fdb9c3..deaaeaec36445ab7757bd7a4ca8421e2b0d61a3e 100644 --- a/backend/Dilon.Core/Entity/SysLogVis.cs +++ b/backend/Dilon.Core/Entity/SysLogVis.cs @@ -1,5 +1,7 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -8,56 +10,73 @@ namespace Dilon.Core /// 访问日志表 /// [Table("sys_log_vis")] + [Comment("访问日志表")] public class SysLogVis : EntityBase { /// /// 名称 /// + [Comment("名称")] + [MaxLength(100)] public string Name { get; set; } /// /// 是否执行成功(Y-是,N-否) /// - public string Success { get; set; } + [Comment("是否执行成功")] + public YesOrNot Success { get; set; } /// /// 具体消息 /// + [Comment("具体消息")] public string Message { get; set; } /// /// IP /// + [Comment("IP")] + [MaxLength(20)] public string Ip { get; set; } /// /// 地址 /// + [Comment("地址")] + [MaxLength(100)] public string Location { get; set; } /// /// 浏览器 /// + [Comment("浏览器")] + [MaxLength(100)] public string Browser { get; set; } /// /// 操作系统 /// + [Comment("操作系统")] + [MaxLength(100)] public string Os { get; set; } /// - /// 访问类型(字典 1登入 2登出) + /// 访问类型 /// - public int? VisType { get; set; } + [Comment("访问类型")] + public LoginType VisType { get; set; } /// /// 访问时间 /// + [Comment("访问时间")] public DateTimeOffset VisTime { get; set; } /// /// 访问人 /// + [Comment("访问人")] + [MaxLength(20)] public string Account { get; set; } } } \ No newline at end of file diff --git a/backend/Dilon.Core/Entity/SysMenu.cs b/backend/Dilon.Core/Entity/SysMenu.cs index d12745e967215247f06eb8ed67eb1b9b5208ca3e..cda0c26f053ec8e4a449c9b0ae68afbe54f493f4 100644 --- a/backend/Dilon.Core/Entity/SysMenu.cs +++ b/backend/Dilon.Core/Entity/SysMenu.cs @@ -1,5 +1,4 @@ -using Furion.Snowflake; -using System; +using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -10,105 +9,126 @@ namespace Dilon.Core /// 菜单表 /// [Table("sys_menu")] + [Comment("菜单表")] public class SysMenu : DEntityBase { - public SysMenu() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 父Id /// + [Comment("父Id")] public long Pid { get; set; } /// /// 父Ids /// + [Comment("父Ids")] public string Pids { get; set; } /// /// 名称 /// + [Comment("名称")] + [Required, MaxLength(20)] public string Name { get; set; } /// /// 编码 /// + [Comment("编码")] + [Required, MaxLength(50)] public string Code { get; set; } /// /// 菜单类型(字典 0目录 1菜单 2按钮) /// + [Comment("菜单类型")] public int Type { get; set; } /// /// 图标 /// + [Comment("图标")] + [MaxLength(20)] public string Icon { get; set; } /// /// 路由地址 /// + [Comment("路由地址")] + [MaxLength(100)] public string Router { get; set; } /// /// 组件地址 /// + [Comment("组件地址")] + [MaxLength(100)] public string Component { get; set; } /// /// 权限标识 /// + [Comment("权限标识")] + [MaxLength(100)] public string Permission { get; set; } /// /// 应用分类(应用编码) /// + [Comment("应用分类")] + [MaxLength(50)] public string Application { get; set; } /// /// 打开方式(字典 0无 1组件 2内链 3外链) /// - public int OpenType { get; set; } + [Comment("打开方式")] + public int OpenType { get; set; } = 0; /// /// 是否可见(Y-是,N-否) /// - public string Visible { get; set; } + [Comment("是否可见")] + [MaxLength(5)] + public string Visible { get; set; } = "Y"; /// /// 内链地址 /// + [Comment("内链地址")] + [MaxLength(100)] public string Link { get; set; } /// /// 重定向地址 /// + [Comment("重定向地址")] + [MaxLength(100)] public string Redirect { get; set; } /// /// 权重(字典 1系统权重 2业务权重) /// - public int Weight { get; set; } + [Comment("权重")] + public int Weight { get; set; } = 2; /// /// 排序 /// - public int Sort { get; set; } + [Comment("排序")] + public int Sort { get; set; } = 100; /// /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 多对多(角色) diff --git a/backend/Dilon.Core/Entity/SysNotice.cs b/backend/Dilon.Core/Entity/SysNotice.cs index 97ce3d77aaac80f192922a44ad185e00ab472165..65eccfaf897a91c9d9a8f27f90f94a61341c9707 100644 --- a/backend/Dilon.Core/Entity/SysNotice.cs +++ b/backend/Dilon.Core/Entity/SysNotice.cs @@ -1,5 +1,6 @@ -using Furion.Snowflake; +using Microsoft.EntityFrameworkCore; using System; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -8,63 +9,71 @@ namespace Dilon.Core /// 通知公告表 /// [Table("sys_notice")] + [Comment("通知公告表")] public class SysNotice : DEntityBase { - public SysNotice() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - } - /// /// 标题 /// + [Comment("标题")] + [Required, MaxLength(20)] public string Title { get; set; } /// /// 内容 /// + [Comment("内容")] + [Required] public string Content { get; set; } /// /// 类型(字典 1通知 2公告) /// + [Comment("类型")] public int Type { get; set; } /// /// 发布人Id /// + [Comment("发布人Id")] public long PublicUserId { get; set; } /// /// 发布人姓名 /// + [Comment("发布人姓名")] + [MaxLength(20)] public string PublicUserName { get; set; } /// /// 发布机构Id /// + [Comment("发布机构Id")] public long PublicOrgId { get; set; } /// /// 发布机构名称 /// + [Comment("发布机构名称")] + [MaxLength(50)] public string PublicOrgName { get; set; } /// /// 发布时间 /// + [Comment("发布时间")] public DateTimeOffset PublicTime { get; set; } /// /// 撤回时间 /// + [Comment("撤回时间")] public DateTimeOffset CancelTime { get; set; } /// /// 状态(字典 0草稿 1发布 2撤回 3删除) /// - public int Status { get; set; } + [Comment("状态")] + public NoticeStatus Status { get; set; } } } diff --git a/backend/Dilon.Core/Entity/SysNoticeUser.cs b/backend/Dilon.Core/Entity/SysNoticeUser.cs index 4901bdea72ace714516cbdf360d20031f5ad7629..9504d5cfcf1f451fd2dd66d219b8f9a4dc4a7df1 100644 --- a/backend/Dilon.Core/Entity/SysNoticeUser.cs +++ b/backend/Dilon.Core/Entity/SysNoticeUser.cs @@ -10,27 +10,32 @@ namespace Dilon.Core /// 通知公告用户表 /// [Table("sys_notice_user")] + [Comment("通知公告用户表")] public class SysNoticeUser : IEntity, IEntityTypeBuilder { /// - /// 通知公告id + /// 通知公告Id /// + [Comment("通知公告Id")] public long NoticeId { get; set; } /// /// 用户Id /// + [Comment("用户Id")] public long UserId { get; set; } /// /// 阅读时间 /// + [Comment("阅读时间")] public DateTimeOffset ReadTime { get; set; } /// /// 状态(字典 0未读 1已读) /// - public int ReadStatus { get; set; } + [Comment("状态")] + public NoticeUserStatus ReadStatus { get; set; } public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator) { diff --git a/backend/Dilon.Core/Entity/SysOauthUser.cs b/backend/Dilon.Core/Entity/SysOauthUser.cs index 99beecc65ed156983a15ddb5707834ec807dd905..118c12fc14d8090713ed6ff5b0a789aa2935ecb0 100644 --- a/backend/Dilon.Core/Entity/SysOauthUser.cs +++ b/backend/Dilon.Core/Entity/SysOauthUser.cs @@ -1,5 +1,5 @@ -using Furion.Snowflake; -using System; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -8,73 +8,88 @@ namespace Dilon.Core /// Oauth登录用户表 /// [Table("sys_oauth_user")] + [Comment("Oauth登录用户表")] public class SysOauthUser : DEntityBase { - public SysOauthUser() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - } - /// - /// 第三方平台的用户唯一id + /// 第三方平台的用户唯一Id /// + [Comment("UUID")] + [MaxLength(50)] public string Uuid { get; set; } /// /// 用户授权的token /// + [Comment("Token")] public string AccessToken { get; set; } /// /// 昵称 /// + [Comment("昵称")] + [MaxLength(20)] public string NickName { get; set; } /// /// 头像 /// + [Comment("头像")] public string Avatar { get; set; } /// /// 性别 /// + [Comment("性别")] + [MaxLength(5)] public string Gender { get; set; } /// /// 电话 /// + [Comment("电话")] + [MaxLength(20)] public string Phone { get; set; } /// /// 邮箱 /// + [Comment("邮箱")] + [MaxLength(20)] public string Email { get; set; } /// /// 位置 /// + [Comment("位置")] + [MaxLength(50)] public string Location { get; set; } /// /// 用户网址 /// + [Comment("用户网址")] public string Blog { get; set; } /// /// 所在公司 /// + [Comment("所在公司")] + [MaxLength(50)] public string Company { get; set; } /// /// 用户来源 /// + [Comment("用户来源")] + [MaxLength(20)] public string Source { get; set; } /// /// 用户备注(各平台中的用户个人介绍) /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } } } \ No newline at end of file diff --git a/backend/Dilon.Core/Entity/SysOrg.cs b/backend/Dilon.Core/Entity/SysOrg.cs index 24e8f525935b6a6c983db848da55a997b73741b7..f5ccc6c4a079658954c9469308307585623391a0 100644 --- a/backend/Dilon.Core/Entity/SysOrg.cs +++ b/backend/Dilon.Core/Entity/SysOrg.cs @@ -1,6 +1,7 @@ -using Furion.Snowflake; -using System; +using Dilon.Core.Entity; +using Microsoft.EntityFrameworkCore; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -9,60 +10,67 @@ namespace Dilon.Core /// 组织机构表 /// [Table("sys_org")] - public class SysOrg : DEntityBase + [Comment("组织机构表")] + public class SysOrg : DBEntityTenant { - public SysOrg() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 父Id /// + [Comment("父Id")] public long Pid { get; set; } /// /// 父Ids /// + [Comment("父Ids")] public string Pids { get; set; } /// /// 名称 /// + [Comment("名称")] + [Required, MaxLength(30)] public string Name { get; set; } /// /// 编码 /// + [Comment("编码")] + [Required, MaxLength(50)] public string Code { get; set; } /// /// 联系人 /// + [Comment("联系人")] + [MaxLength(20)] public string Contacts { get; set; } /// /// 电话 /// + [Comment("电话")] + [MaxLength(20)] public string Tel { get; set; } /// /// 排序 /// + [Comment("排序")] public int Sort { get; set; } /// /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + [Comment("状态")] + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 多对多(用户) diff --git a/backend/Dilon.Core/Entity/SysPos.cs b/backend/Dilon.Core/Entity/SysPos.cs index e6d4dd3d66b8b73da60da21efbf8e1fa18db5709..6cfbe708e01c053f05e81e2d03547716359718fe 100644 --- a/backend/Dilon.Core/Entity/SysPos.cs +++ b/backend/Dilon.Core/Entity/SysPos.cs @@ -1,6 +1,7 @@ -using Furion.Snowflake; -using System; +using Dilon.Core.Entity; +using Microsoft.EntityFrameworkCore; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -9,40 +10,41 @@ namespace Dilon.Core /// 职位表 /// [Table("sys_pos")] - public class SysPos : DEntityBase + [Comment("职位表")] + public class SysPos : DBEntityTenant { - public SysPos() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 名称 /// + [Comment("名称")] + [Required, MaxLength(20)] public string Name { get; set; } /// /// 编码 /// + [Comment("编码")] + [Required, MaxLength(50)] public string Code { get; set; } /// /// 排序 /// + [Comment("排序")] public int Sort { get; set; } /// /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + [Comment("状态")] + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 多对多(员工) diff --git a/backend/Dilon.Core/Entity/SysRole.cs b/backend/Dilon.Core/Entity/SysRole.cs index 2c355499952b245689ae81d669ff193d30bcad7e..8be5da41540289365eb37a9e05ca403f1a66cb6d 100644 --- a/backend/Dilon.Core/Entity/SysRole.cs +++ b/backend/Dilon.Core/Entity/SysRole.cs @@ -1,5 +1,5 @@ -using Furion.DatabaseAccessor; -using Furion.Snowflake; +using Dilon.Core.Entity; +using Furion.DatabaseAccessor; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; @@ -13,45 +13,47 @@ namespace Dilon.Core /// 角色表 /// [Table("sys_role")] - public class SysRole : DEntityBase, IEntityTypeBuilder + [Comment("角色表")] + public class SysRole : DBEntityTenant, IEntityTypeBuilder { - public SysRole() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 名称 /// + [Comment("名称")] + [Required, MaxLength(20)] public string Name { get; set; } /// /// 编码 /// + [Comment("编码")] + [Required, MaxLength(50)] public string Code { get; set; } /// /// 排序 /// + [Comment("排序")] public int Sort { get; set; } /// /// 数据范围类型(字典 1全部数据 2本部门及以下数据 3本部门数据 4仅本人数据 5自定义数据) /// + [Comment("数据范围类型")] public int DataScopeType { get; set; } /// /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + [Comment("状态")] + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 多对多(用户) @@ -91,7 +93,9 @@ namespace Dilon.Core /// public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator) { - entityBuilder.HasMany(p => p.SysOrgs).WithMany(p => p.SysRoles).UsingEntity( + entityBuilder.HasMany(p => p.SysOrgs) + .WithMany(p => p.SysRoles) + .UsingEntity( u => u.HasOne(c => c.SysOrg).WithMany(c => c.SysRoleDataScopes).HasForeignKey(c => c.SysOrgId), u => u.HasOne(c => c.SysRole).WithMany(c => c.SysRoleDataScopes).HasForeignKey(c => c.SysRoleId), u => @@ -99,7 +103,9 @@ namespace Dilon.Core u.HasKey(c => new { c.SysRoleId, c.SysOrgId }); }); - entityBuilder.HasMany(p => p.SysMenus).WithMany(p => p.SysRoles).UsingEntity( + entityBuilder.HasMany(p => p.SysMenus) + .WithMany(p => p.SysRoles) + .UsingEntity( u => u.HasOne(c => c.SysMenu).WithMany(c => c.SysRoleMenus).HasForeignKey(c => c.SysMenuId), u => u.HasOne(c => c.SysRole).WithMany(c => c.SysRoleMenus).HasForeignKey(c => c.SysRoleId), u => diff --git a/backend/Dilon.Core/Entity/SysRoleDataScope.cs b/backend/Dilon.Core/Entity/SysRoleDataScope.cs index 4505ab7e4c7d7f1e8a61f23506a9f81a848612b5..eeb186f65c1749c2dfe61ac63a0400e3efc4508b 100644 --- a/backend/Dilon.Core/Entity/SysRoleDataScope.cs +++ b/backend/Dilon.Core/Entity/SysRoleDataScope.cs @@ -1,4 +1,5 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -7,11 +8,13 @@ namespace Dilon.Core /// 角色数据范围表 /// [Table("sys_role_data_scope")] + [Comment("角色数据范围表")] public class SysRoleDataScope : IEntity { /// /// 角色Id /// + [Comment("角色Id")] public long SysRoleId { get; set; } /// @@ -22,6 +25,7 @@ namespace Dilon.Core /// /// 机构Id /// + [Comment("机构Id")] public long SysOrgId { get; set; } /// diff --git a/backend/Dilon.Core/Entity/SysRoleMenu.cs b/backend/Dilon.Core/Entity/SysRoleMenu.cs index 02afd3a97407717c38ba8af004d9523ec5eb7779..57fde8ccee5745fc2aa6ad48752338f0e05028f9 100644 --- a/backend/Dilon.Core/Entity/SysRoleMenu.cs +++ b/backend/Dilon.Core/Entity/SysRoleMenu.cs @@ -1,4 +1,5 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -7,11 +8,13 @@ namespace Dilon.Core /// 角色菜单表 /// [Table("sys_role_menu")] + [Comment("角色菜单表")] public class SysRoleMenu : IEntity { /// /// 角色Id /// + [Comment("角色Id")] public long SysRoleId { get; set; } /// @@ -22,6 +25,7 @@ namespace Dilon.Core /// /// 菜单Id /// + [Comment("菜单Id")] public long SysMenuId { get; set; } /// diff --git a/backend/Dilon.Core/Entity/SysTenant.cs b/backend/Dilon.Core/Entity/SysTenant.cs new file mode 100644 index 0000000000000000000000000000000000000000..20de04f8c945615c491bc34d13e7204e60baaf21 --- /dev/null +++ b/backend/Dilon.Core/Entity/SysTenant.cs @@ -0,0 +1,71 @@ +using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Dilon.Core +{ + /// + /// 租户表 + /// + [Table("sys_tenant")] + [Comment("租户表")] + public class SysTenant : DEntityBase, IEntity + { + /// + /// 公司名称 + /// + [Comment("公司名称")] + [Required, MaxLength(30)] + public string Name { get; set; } + + /// + /// 管理员名称 + /// + [Comment("管理员名称")] + [Required, MaxLength(20)] + public string AdminName { get; set; } + + /// + /// 主机 + /// + [Comment("主机")] + [MaxLength(100)] + public string Host { get; set; } + + /// + /// 电子邮箱 + /// + [Comment("电子邮箱")] + [MaxLength(20)] + public string Email { get; set; } + + /// + /// 电话 + /// + [Comment("电话")] + [MaxLength(20)] + public string Phone { get; set; } + + /// + /// 数据库连接 + /// + [Comment("数据库连接")] + [MaxLength(200)] + public string Connection { get; set; } + + /// + /// 架构 + /// + [Comment("架构")] + [MaxLength(50)] + public string Schema { get; set; } + + /// + /// 备注 + /// + [Comment("备注")] + [MaxLength(100)] + public string Remark { get; set; } + } +} diff --git a/backend/Dilon.Core/Entity/SysTimer.cs b/backend/Dilon.Core/Entity/SysTimer.cs index 9f1d895d0701b23b1bbc28e75602d1f87eb816d4..08585db081194ed4b519fce9ed715ae2d17a6227 100644 --- a/backend/Dilon.Core/Entity/SysTimer.cs +++ b/backend/Dilon.Core/Entity/SysTimer.cs @@ -1,6 +1,6 @@ -using Dilon.Core.Service; -using Furion.Snowflake; -using System; +using Furion.TaskScheduler; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -9,86 +9,76 @@ namespace Dilon.Core /// 定时任务 /// [Table("sys_timer")] + [Comment("定时任务表")] public class SysTimer : DEntityBase { - public SysTimer() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - } - /// /// 任务名称 /// /// dilon + [Comment("任务名称")] + [Required, MaxLength(20)] public string JobName { get; set; } /// - /// 任务分组 - /// - /// dilon - public string JobGroup { get; set; } - - /// - /// 开始时间 + /// 执行间隔时间(单位秒) /// - public DateTimeOffset BeginTime { get; set; } = DateTimeOffset.Now; - - /// - /// 结束时间 - /// - /// null - public DateTimeOffset? EndTime { get; set; } + /// 5 + [Comment("间隔时间")] + public int? Interval { get; set; } = 5; /// /// Cron表达式 /// /// + [Comment("Cron表达式")] + [MaxLength(20)] public string Cron { get; set; } /// - /// 执行次数(默认无限循环) - /// - /// 10 - public int? RunNumber { get; set; } - - /// - /// 执行间隔时间,单位秒(如果有Cron,则IntervalSecond失效) + /// 定时器类型 /// - /// 5 - public int? Interval { get; set; } = 5; + [Comment("定时器类型")] + public SpareTimeTypes TimerType { get; set; } = SpareTimeTypes.Interval; /// - /// 触发器类型 + /// 执行次数 /// - public TriggerTypeEnum TriggerType { get; set; } = TriggerTypeEnum.Simple; + [Comment("执行次数")] + public int? RunNumber { get; set; } /// /// 请求url /// + [Comment("请求url")] + [MaxLength(200)] public string RequestUrl { get; set; } /// /// 请求参数(Post,Put请求用) /// + [Comment("请求参数")] public string RequestParameters { get; set; } /// /// Headers(可以包含如:Authorization授权认证) /// 格式:{"Authorization":"userpassword.."} /// + [Comment("Headers")] public string Headers { get; set; } /// /// 请求类型 /// /// 2 + [Comment("请求类型")] public RequestTypeEnum RequestType { get; set; } = RequestTypeEnum.Post; /// - /// 描述 + /// 备注 /// + [Comment("备注")] + [MaxLength(100)] public string Remark { get; set; } } } diff --git a/backend/Dilon.Core/Entity/SysUser.cs b/backend/Dilon.Core/Entity/SysUser.cs index 3d533bfd8e16981386ce0664cda457d62018a823..691f5cdf9b07ed07e9825a8a3e12dc1d6114fc73 100644 --- a/backend/Dilon.Core/Entity/SysUser.cs +++ b/backend/Dilon.Core/Entity/SysUser.cs @@ -1,5 +1,5 @@ -using Furion.DatabaseAccessor; -using Furion.Snowflake; +using Dilon.Core.Entity; +using Furion.DatabaseAccessor; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; @@ -13,16 +13,9 @@ namespace Dilon.Core /// 用户表 /// [Table("sys_user")] - public class SysUser : DEntityBase, IEntityTypeBuilder + [Comment("用户表")] + public class SysUser : DBEntityTenant, IEntityTypeBuilder { - public SysUser() - { - Id = IDGenerator.NextId(); - CreatedTime = DateTimeOffset.Now; - IsDeleted = false; - Status = (int)CommonStatus.ENABLE; - } - /// /// 账号 /// @@ -31,10 +24,10 @@ namespace Dilon.Core public string Account { get; set; } /// - /// 密码(采用MD5加密) + /// 密码(默认MD5加密) /// [Comment("密码")] - [Required] + [Required, MaxLength(50)] public string Password { get; set; } /// @@ -67,34 +60,34 @@ namespace Dilon.Core /// 性别-男_1、女_2 /// [Comment("性别-男_1、女_2")] - public int Sex { get; set; } + public Gender Sex { get; set; } /// /// 邮箱 /// [Comment("邮箱")] - [MaxLength(30)] + [MaxLength(20)] public string Email { get; set; } /// /// 手机 /// [Comment("手机")] - [MaxLength(30)] + [MaxLength(20)] public string Phone { get; set; } /// /// 电话 /// [Comment("电话")] - [MaxLength(30)] + [MaxLength(20)] public string Tel { get; set; } /// /// 最后登录IP /// [Comment("最后登录IP")] - [MaxLength(30)] + [MaxLength(20)] public string LastLoginIp { get; set; } /// @@ -107,13 +100,13 @@ namespace Dilon.Core /// 管理员类型-超级管理员_1、非管理员_2 /// [Comment("管理员类型-超级管理员_1、非管理员_2")] - public int AdminType { get; set; } + public AdminType AdminType { get; set; } /// /// 状态-正常_0、停用_1、删除_2 /// [Comment("状态-正常_0、停用_1、删除_2")] - public int Status { get; set; } + public CommonStatus Status { get; set; } = CommonStatus.ENABLE; /// /// 多对多(角色) diff --git a/backend/Dilon.Core/Entity/SysUserDataScope.cs b/backend/Dilon.Core/Entity/SysUserDataScope.cs index 89ba881c29568cb14d7ae631f2d554b59c70fcf1..c471a78a8de5f4f42bdd6ad8d26d26108e523b38 100644 --- a/backend/Dilon.Core/Entity/SysUserDataScope.cs +++ b/backend/Dilon.Core/Entity/SysUserDataScope.cs @@ -1,4 +1,5 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -7,11 +8,13 @@ namespace Dilon.Core /// 用户数据范围表 /// [Table("sys_user_data_scope")] + [Comment("用户数据范围表")] public class SysUserDataScope : IEntity { /// /// 用户Id /// + [Comment("用户Id")] public long SysUserId { get; set; } /// @@ -22,6 +25,7 @@ namespace Dilon.Core /// /// 机构Id /// + [Comment("机构Id")] public long SysOrgId { get; set; } /// diff --git a/backend/Dilon.Core/Entity/SysUserRole.cs b/backend/Dilon.Core/Entity/SysUserRole.cs index 1bd2ad3b14c46a93210086307f1aa3a7f6806ba3..844ed7c39eaad50527a6c1ae15eb717cfe397811 100644 --- a/backend/Dilon.Core/Entity/SysUserRole.cs +++ b/backend/Dilon.Core/Entity/SysUserRole.cs @@ -1,4 +1,5 @@ using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations.Schema; namespace Dilon.Core @@ -7,11 +8,13 @@ namespace Dilon.Core /// 用户角色表 /// [Table("sys_user_role")] + [Comment("用户角色表")] public class SysUserRole : IEntity { /// - /// 系统用户Id + /// 用户Id /// + [Comment("用户Id")] public long SysUserId { get; set; } /// @@ -22,6 +25,7 @@ namespace Dilon.Core /// /// 系统角色Id /// + [Comment("角色Id")] public long SysRoleId { get; set; } /// diff --git a/backend/Dilon.Core/Enum/AdminType.cs b/backend/Dilon.Core/Enum/AdminType.cs index 6b0ebd95d7c1d9b6cb548f8ec8894d8ce7448663..aef6f7668649600cb31f8f96a51cddf4ecd86a7b 100644 --- a/backend/Dilon.Core/Enum/AdminType.cs +++ b/backend/Dilon.Core/Enum/AdminType.cs @@ -14,9 +14,15 @@ namespace Dilon.Core SuperAdmin = 1, /// - /// 非管理员 + /// 管理员 /// - [Description("非管理员")] - None = 2 + [Description("管理员")] + Admin = 2, + + /// + /// 普通账号 + /// + [Description("普通账号")] + None = 3 } } diff --git a/backend/Dilon.Core/Enum/LogOpType.cs b/backend/Dilon.Core/Enum/DataOpType.cs similarity index 95% rename from backend/Dilon.Core/Enum/LogOpType.cs rename to backend/Dilon.Core/Enum/DataOpType.cs index d3cf3e8810e145a5cc0bacf8f0854a75a93d149b..bd31e0c4c6147e017be4b29e934598eaebc1474f 100644 --- a/backend/Dilon.Core/Enum/LogOpType.cs +++ b/backend/Dilon.Core/Enum/DataOpType.cs @@ -1,9 +1,9 @@ namespace Dilon.Core { /// - /// 日志操作类型 + /// 数据操作类型 /// - public enum LogOpType + public enum DataOpType { /// /// 其它 diff --git a/backend/Dilon.Core/Enum/ErrorCode.cs b/backend/Dilon.Core/Enum/ErrorCode.cs index 40ff9a0b50d5d8e67dcbe251b1144a1f19ccd013..740e73b81a6f7fd041e09b0d7d30f0852c65f0cb 100644 --- a/backend/Dilon.Core/Enum/ErrorCode.cs +++ b/backend/Dilon.Core/Enum/ErrorCode.cs @@ -152,6 +152,12 @@ namespace Dilon.Core [ErrorCodeItemMetadata("附属机构下有员工禁止删除")] D2005, + /// + /// 只能增加下级机构 + /// + [ErrorCodeItemMetadata("只能增加下级机构")] + D2006, + /// /// 字典类型不存在 /// @@ -320,13 +326,48 @@ namespace Dilon.Core [ErrorCodeItemMetadata("任务调度不存在")] D1101, - /// /// 演示环境禁止修改数据 /// [ErrorCodeItemMetadata("演示环境禁止修改数据")] D1200, + /// + /// 已存在同名或同主机租户 + /// + [ErrorCodeItemMetadata("已存在同名或同主机租户")] + D1300, + + /// + /// 该表代码模板已经生成过 + /// + [ErrorCodeItemMetadata("该表代码模板已经生成过")] + D1400, + + /// + /// 该类型不存在 + /// + [ErrorCodeItemMetadata("该类型不存在")] + D1501, + + /// + /// 该字段不存在 + /// + [ErrorCodeItemMetadata("该字段不存在")] + D1502, + + /// + /// 该类型不是枚举类型 + /// + [ErrorCodeItemMetadata("该类型不是枚举类型")] + D1503, + + /// + /// 该实体不存在 + /// + [ErrorCodeItemMetadata("该实体不存在")] + D1504, + /// /// 已存在同名或同编码项目 /// diff --git a/backend/Dilon.Core/Enum/HttpStatusCode.cs b/backend/Dilon.Core/Enum/HttpStatusCode.cs new file mode 100644 index 0000000000000000000000000000000000000000..d7077fca4e03cbdc34dd2dba06c38c11e2580766 --- /dev/null +++ b/backend/Dilon.Core/Enum/HttpStatusCode.cs @@ -0,0 +1,252 @@ +using System.ComponentModel; + +namespace Dilon.Core +{ + /// + /// HTTP状态码 + /// + public enum HttpStatusCode + { + /// + /// 客户端可能继续其请求 + /// + [Description("继续")] + Continue = 100, + + /// + /// 正在更改协议版本或协议 + /// + [Description("交换协议")] + SwitchingProtocols = 101, + + /// + /// 请求成功,且请求的信息包含在响应中 + /// + [Description("OK")] + OK = 200, + + /// + /// 请求导致在响应被发送前创建新资源 + /// + [Description("已创建")] + Created = 201, + + /// + /// 请求已被接受做进一步处理 + /// + [Description("接收")] + Accepted = 202, + + /// + /// 返回的元信息来自缓存副本而不是原始服务器,因此可能不正确 + /// + [Description("非认证信息")] + NonAuthoritativeInformation = 203, + + /// + /// 已成功处理请求并且响应已被设定为无内容 + /// + [Description("无内容")] + NoContent = 204, + + /// + /// 客户端应重置(或重新加载)当前资源 + /// + [Description("重置内容")] + ResetContent = 205, + + /// + /// 响应是包括字节范围的 GET请求所请求的部分响应 + /// + [Description("部分内容")] + PartialContent = 206, + + /// + /// 请求的信息有多种表示形式,默认操作是将此状态视为重定向 + /// + [Description("多路选择")] + MultipleChoices = 300, + + /// + /// 请求的信息已移到 Location头中指定的 URI 处 + /// + [Description("永久转移")] + MovedPermanently = 301, + + /// + /// 请求的信息位于 Location 头中指定的 URI 处 + /// + [Description("暂时转移")] + Found = 302, + + /// + /// 将客户端自动重定向到 Location 头中指定的 URI + /// + [Description("参见其它")] + SeeOther = 303, + + /// + /// 客户端的缓存副本是最新的 + /// + [Description("未修改")] + NotModified = 304, + + /// + /// 请求应使用位于 Location 头中指定的 URI 的代理服务器 + /// + [Description("使用代理")] + UseProxy = 305, + + /// + /// 服务器未能识别请求 + /// + [Description("错误请求")] + BadRequest = 400, + + /// + /// 请求的资源要求身份验证 + /// + [Description("未认证")] + Unauthorized = 401, + + /// + /// 需要付费 + /// + [Description("需要付费")] + PaymentRequired = 402, + + /// + /// 服务器拒绝满足请求 + /// + [Description("禁止")] + Forbidden = 403, + + /// + /// 请求的资源不在服务器上 + /// + [Description("未找到")] + NotFound = 404, + + /// + /// 请求的资源上不允许请求方法(POST或 GET) + /// + [Description("请求方法不允许")] + MethodNotAllowed = 405, + + /// + /// 客户端已用 Accept 头指示将不接受资源的任何可用表示形式 + /// + [Description("不接受")] + NotAcceptable = 406, + + /// + /// 请求的代理要求身份验证 + /// Proxy-authenticate 头包含如何执行身份验证的详细信息 + /// + [Description("需要代理认证")] + ProxyAuthenticationRequired = 407, + + /// + /// 客户端没有在服务器期望请求的时间内发送请求 + /// + [Description("请求超时")] + RequestTimeout = 408, + + /// + /// 由于服务器上的冲突而未能执行请求 + /// + [Description("冲突")] + Conflict = 409, + + /// + /// 请求的资源不再可用 + /// + [Description("失败")] + Gone = 410, + + /// + /// 缺少必需的 Content-length + /// + [Description("缺少Content-length头")] + LengthRequired = 411, + + /// + /// 为此请求设置的条件失败,且无法执行此请求 + /// 条件是用条件请求标头(如 If-Match、If-None-Match 或 If-Unmodified-Since)设置的。 + /// + [Description("条件失败")] + PreconditionFailed = 412, + + /// + /// 请求太大,服务器无法处理 + /// + [Description("请求实体太大")] + RequestEntityTooLarge = 413, + + /// + /// URI 太长 + /// + [Description("请求URI太长")] + RequestUriTooLong = 414, + + /// + /// 请求是不支持的类型 + /// + [Description("不支持的媒体类型")] + UnsupportedMediaType = 415, + + /// + /// 无法返回从资源请求的数据范围,因为范围的开头在资源的开头之前,或因为范围的结尾在资源的结尾之后 + /// + [Description("数据范围不匹配")] + RequestedRangeNotSatisfiable = 416, + + /// + /// 服务器未能符合Expect头中给定的预期值 + /// + [Description("服务器与Expect头不匹配")] + ExpectationFailed = 417, + + /// + /// 服务器拒绝处理客户端使用当前协议发送的请求,但是可以接受其使用升级后的协议发送的请求 + /// + [Description("当前协议不受支持")] + UpgradeRequired = 426, + + /// + /// 服务器上发生了一般错误 + /// + [Description("服务器内部错误")] + InternalServerError = 500, + + /// + /// 服务器不支持请求的函数 + /// + [Description("未实现")] + NotImplemented = 501, + + /// + /// 中间代理服务器从另一代理或原始服务器接收到错误响应 + /// + [Description("网关失败")] + BadGateway = 502, + + /// + /// 服务器暂时不可用,通常是由于过多加载或维护 + /// + [Description("服务器维护")] + ServiceUnavailable = 503, + + /// + /// 中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时 + /// + [Description("网关超时")] + GatewayTimeout = 504, + + /// + /// 服务器不支持请求的HTTP版本 + /// + [Description("HTTP版本不支持")] + HttpVersionNotSupported = 505 + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Enum/LoginType.cs b/backend/Dilon.Core/Enum/LoginType.cs new file mode 100644 index 0000000000000000000000000000000000000000..2a7dade929fd4f90d8b4c7f0ae4aa477e8cac901 --- /dev/null +++ b/backend/Dilon.Core/Enum/LoginType.cs @@ -0,0 +1,40 @@ +using System.ComponentModel; + +namespace Dilon.Core +{ + /// + /// 登陆类型 + /// + public enum LoginType + { + /// + /// 登陆 + /// + [Description("登陆")] + LOGIN = 0, + + /// + /// 登出 + /// + [Description("登出")] + LOGOUT = 1, + + /// + /// 注册 + /// + [Description("注册")] + REGISTER = 2, + + /// + /// 改密 + /// + [Description("改密")] + CHANGEPASSWORD = 3, + + /// + /// 三方授权登陆 + /// + [Description("授权登陆")] + AUTHORIZEDLOGIN = 4 + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Enum/QueryTypeEnum.cs b/backend/Dilon.Core/Enum/QueryTypeEnum.cs new file mode 100644 index 0000000000000000000000000000000000000000..cc68646042fec27bbbf4ee6e38bc4e7102a47fc7 --- /dev/null +++ b/backend/Dilon.Core/Enum/QueryTypeEnum.cs @@ -0,0 +1,58 @@ +using System.ComponentModel; + +namespace Dilon.Core +{ + /// + /// 查询类型的枚举 + /// + public enum QueryTypeEnum + { + /// + /// 等于 + /// + [Description("等于")] + eq = 0, + + /// + /// 模糊 + /// + [Description("模糊")] + like = 1, + + /// + /// 大于 + /// + [Description("大于")] + gt = 2, + + /// + /// 小于 + /// + [Description("小于")] + lt = 3, + + /// + /// 不等于 + /// + [Description("不等于")] + ne = 4, + + /// + /// 大于等于 + /// + [Description("大于等于")] + ge = 5, + + /// + /// 小于等于 + /// + [Description("小于等于")] + le = 6, + + /// + /// 不为空 + /// + [Description("不为空")] + isNotNull = 7 + } +} diff --git a/backend/Dilon.Core/Enum/RequestTypeEnum.cs b/backend/Dilon.Core/Enum/RequestTypeEnum.cs new file mode 100644 index 0000000000000000000000000000000000000000..e5a4cda436340a9bfe044380c38810d631100676 --- /dev/null +++ b/backend/Dilon.Core/Enum/RequestTypeEnum.cs @@ -0,0 +1,33 @@ +namespace Dilon.Core +{ + /// + /// http请求类型 + /// + public enum RequestTypeEnum + { + /// + /// 无 + /// + None = 0, + + /// + /// GET请求 + /// + Get = 1, + + /// + /// POST请求 + /// + Post = 2, + + /// + /// PUT请求 + /// + Put = 3, + + /// + /// DELETE请求 + /// + Delete = 4 + } +} diff --git a/backend/Dilon.Core/Extension/EnumExtensions.cs b/backend/Dilon.Core/Extension/EnumExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..365d69363ad2aac697ecec9b7eb8a22f8f27393f --- /dev/null +++ b/backend/Dilon.Core/Extension/EnumExtensions.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using Furion.FriendlyException; + +namespace Dilon.Core +{ + /// + /// 枚举扩展 + /// + public static class EnumExtensions + { + // 枚举显示字典缓存 + private static readonly ConcurrentDictionary> EnumDisplayValueDict = new(); + + // 枚举值字典缓存 + private static readonly ConcurrentDictionary> EnumNameValueDict = new(); + + // 枚举类型缓存 + private static ConcurrentDictionary _enumTypeDict = null; + + + /// + /// 获取枚举对象Key与名称的字典(缓存) + /// + /// + /// + public static Dictionary GetEnumDictionary(Type enumType) + { + if (!enumType.IsEnum) + throw Oops.Oh(ErrorCode.D1503); + + // 查询缓存 + Dictionary enumDic = EnumNameValueDict.ContainsKey(enumType) ? EnumNameValueDict[enumType] : new Dictionary(); + if (enumDic.Count == 0) + { + // 取枚举类型的Key/Value字典集合 + enumDic = GetEnumDictionaryItems(enumType); + + // 缓存 + EnumNameValueDict[enumType] = enumDic; + } + return enumDic; + } + + /// + /// 获取枚举对象Key与名称的字典 + /// + /// + /// + private static Dictionary GetEnumDictionaryItems(Type enumType) + { + // 获取类型的字段,初始化一个有限长度的字典 + FieldInfo[] enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); + Dictionary enumDic = new(enumFields.Length); + + // 遍历字段数组获取key和name + foreach (FieldInfo enumField in enumFields) + { + int intValue = (int)enumField.GetValue(enumType); + enumDic[intValue] = enumField.Name; + } + return enumDic; + } + + /// + /// 获取枚举类型key与描述的字典(缓存) + /// + /// + /// + /// + public static Dictionary GetEnumDescDictionary(Type enumType) + { + if (!enumType.IsEnum) + throw Oops.Oh(ErrorCode.D1503); + + // 查询缓存 + Dictionary enumDic = EnumDisplayValueDict.ContainsKey(enumType) ? EnumDisplayValueDict[enumType] : new Dictionary(); + if (enumDic.Count == 0) + { + // 取枚举类型的Key/Value字典集合 + enumDic = GetEnumDescDictionaryItems(enumType); + + // 缓存 + EnumDisplayValueDict[enumType] = enumDic; + } + return enumDic; + } + + /// + /// 获取枚举类型key与描述的字典(没有描述则获取name) + /// + /// + /// + /// + private static Dictionary GetEnumDescDictionaryItems(Type enumType) + { + // 获取类型的字段,初始化一个有限长度的字典 + FieldInfo[] enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); + Dictionary enumDic = new(enumFields.Length); + + // 遍历字段数组获取key和name + foreach (FieldInfo enumField in enumFields) + { + int intValue = (int)enumField.GetValue(enumType); + var desc = enumField.GetDescriptionValue(); + enumDic[intValue] = desc != null && !string.IsNullOrEmpty(desc.Description) ? desc.Description : enumField.Name; + } + return enumDic; + } + + /// + /// 从程序集中查找指定枚举类型 + /// + /// + /// + /// + public static Type TryToGetEnumType(Assembly assembly, string typeName) + { + // 枚举缓存为空则重新加载枚举类型字典 + _enumTypeDict ??= LoadEnumTypeDict(assembly); + + // 按名称查找 + if (_enumTypeDict.ContainsKey(typeName)) + { + return _enumTypeDict[typeName]; + } + return null; + } + + /// + /// 从程序集中加载所有枚举类型 + /// + /// + /// + private static ConcurrentDictionary LoadEnumTypeDict(Assembly assembly) + { + // 取程序集中所有类型 + Type[] typeArray = assembly.GetTypes(); + + // 过滤非枚举类型,转成字典格式并返回 + Dictionary dict = typeArray.Where(o => o.IsEnum).ToDictionary(o => o.Name, o => o); + ConcurrentDictionary enumTypeDict = new(dict); + return enumTypeDict; + } + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Extension/PageInputOrder.cs b/backend/Dilon.Core/Extension/PageInputOrder.cs new file mode 100644 index 0000000000000000000000000000000000000000..28f5ad1bd4e8dc3a69552f97c71bcf474dae3eb0 --- /dev/null +++ b/backend/Dilon.Core/Extension/PageInputOrder.cs @@ -0,0 +1,27 @@ +namespace Dilon.Core +{ + /// + /// 通用输入帮助类 + /// + public class PageInputOrder + { + /// + /// 排序方式(默认降序) + /// + /// + /// 是否降序 + /// + public static string OrderBuilder(PageInputBase pageInput, bool descSort = true) + { + // 约定默认每张表都有Id排序 + var orderStr = descSort ? "Id Desc" : "Id Asc"; + + // 排序是否可用-排序字段和排序顺序都为非空才启用排序 + if (!string.IsNullOrEmpty(pageInput.SortField) && !string.IsNullOrEmpty(pageInput.SortOrder)) + { + orderStr = $"{pageInput.SortField} {(pageInput.SortOrder == pageInput.DescStr ? "Desc" : "Asc")}"; + } + return orderStr; + } + } +} diff --git a/backend/Dilon.Core/Extension/XnInputBase.cs b/backend/Dilon.Core/Extension/XnInputBase.cs index e77d2919ee66a254459c41ac71373fc0033f31f7..c8247f077c80f0aa4faca626fcf68aa1737b72ca 100644 --- a/backend/Dilon.Core/Extension/XnInputBase.cs +++ b/backend/Dilon.Core/Extension/XnInputBase.cs @@ -52,5 +52,20 @@ namespace Dilon.Core /// 搜索结束时间 /// public virtual string SearchEndTime { get; set; } + + /// + /// 排序字段 + /// + public virtual string SortField { get; set; } + + /// + /// 排序方法,默认升序,否则降序(配合antd前端,约定参数为 Ascend,Dscend) + /// + public virtual string SortOrder { get; set; } + + /// + /// 降序排序(不要问我为什么是descend不是desc,前端约定参数就是这样) + /// + public virtual string DescStr { get; set; } = "descend"; } } diff --git a/backend/Dilon.Core/Extension/XnRestfulResultProvider.cs b/backend/Dilon.Core/Extension/XnRestfulResultProvider.cs index da1dbc6ffd01a736fc2129fc159651a525298d5e..13c477bec1356a2e0a92812dfa148fd12b93d0e4 100644 --- a/backend/Dilon.Core/Extension/XnRestfulResultProvider.cs +++ b/backend/Dilon.Core/Extension/XnRestfulResultProvider.cs @@ -38,46 +38,6 @@ namespace Dilon.Core }); } - /// - /// 处理输出状态码 - /// - /// - /// - /// - public async Task OnResponseStatusCodes(HttpContext context, int statusCode) - { - switch (statusCode) - { - // 处理 401 状态码 - case StatusCodes.Status401Unauthorized: - await context.Response.WriteAsJsonAsync(new XnRestfulResult - { - Code = StatusCodes.Status401Unauthorized, - Success = false, - Data = null, - Message = "401 未经授权", - Extras = UnifyContext.Take(), - Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - }); - break; - // 处理 403 状态码 - case StatusCodes.Status403Forbidden: - await context.Response.WriteAsJsonAsync(new XnRestfulResult - { - Code = StatusCodes.Status403Forbidden, - Success = false, - Data = null, - Message = "403 禁止访问", - Extras = UnifyContext.Take(), - Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - }); - break; - - default: - break; - } - } - /// /// 成功返回值 /// @@ -104,6 +64,7 @@ namespace Dilon.Core }); } + /// /// 验证失败返回值 /// @@ -124,6 +85,50 @@ namespace Dilon.Core Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }); } + + /// + /// 处理输出状态码 + /// + /// + /// + /// + /// + public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultStatusCodesOptions options) + { + // 设置响应状态码 + UnifyContext.SetResponseStatusCodes(context, statusCode, options); + + switch (statusCode) + { + // 处理 401 状态码 + case StatusCodes.Status401Unauthorized: + await context.Response.WriteAsJsonAsync(new XnRestfulResult + { + Code = StatusCodes.Status401Unauthorized, + Success = false, + Data = null, + Message = "401 未经授权", + Extras = UnifyContext.Take(), + Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + }); + break; + // 处理 403 状态码 + case StatusCodes.Status403Forbidden: + await context.Response.WriteAsJsonAsync(new XnRestfulResult + { + Code = StatusCodes.Status403Forbidden, + Success = false, + Data = null, + Message = "403 禁止访问", + Extras = UnifyContext.Take(), + Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + }); + break; + + default: + break; + } + } } /// diff --git a/backend/Dilon.Core/Filter/LogExceptionHandler.cs b/backend/Dilon.Core/Filter/LogExceptionHandler.cs index 62dcd12f8c1926e6f98a8957aafdccd7fa96d7aa..986892226f45768112372b2109f0c0d6d3726eba 100644 --- a/backend/Dilon.Core/Filter/LogExceptionHandler.cs +++ b/backend/Dilon.Core/Filter/LogExceptionHandler.cs @@ -1,6 +1,11 @@ -using Furion.DependencyInjection; +using Furion; +using Furion.DatabaseAccessor.Extensions; +using Furion.DependencyInjection; using Furion.FriendlyException; using Microsoft.AspNetCore.Mvc.Filters; +using Serilog; +using System; +using System.Security.Claims; using System.Threading.Tasks; namespace Dilon.Core @@ -10,11 +15,28 @@ namespace Dilon.Core /// public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton { - public Task OnExceptionAsync(ExceptionContext context) + public async Task OnExceptionAsync(ExceptionContext context) { - // 写日志 + // 取用户上下文 + var userContext = App.User; - return Task.CompletedTask; + // 异常日志入库 + await new SysLogEx + { + Account = userContext?.FindFirstValue(ClaimConst.CLAINM_ACCOUNT), + Name = userContext?.FindFirstValue(ClaimConst.CLAINM_NAME), + ClassName = context.Exception.TargetSite.DeclaringType?.FullName, + MethodName = context.Exception.TargetSite.Name, + ExceptionName = context.Exception.Message, + ExceptionMsg = context.Exception.Message, + ExceptionSource = context.Exception.Source, + StackTrace = context.Exception.StackTrace, + ParamsObj = context.Exception.TargetSite.GetParameters().ToString(), + ExceptionTime = DateTimeOffset.Now + }.InsertAsync(); + + // 异常日志写文件 + Log.Error(context.Exception.ToString()); } } } diff --git a/backend/Dilon.Core/Filter/RequestActionFilter.cs b/backend/Dilon.Core/Filter/RequestActionFilter.cs index 54e719ded0872d790b71b2353306f2df0e02790e..bb796a89b445c5376710e389c4b15baf563bc079 100644 --- a/backend/Dilon.Core/Filter/RequestActionFilter.cs +++ b/backend/Dilon.Core/Filter/RequestActionFilter.cs @@ -1,9 +1,9 @@ using Furion.DatabaseAccessor.Extensions; +using Furion.JsonSerialization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using System; -using System.ComponentModel; using System.Diagnostics; using System.Security.Claims; using System.Threading.Tasks; @@ -29,32 +29,30 @@ namespace Dilon.Core // 判断是否请求成功(没有异常就是请求成功) var isRequestSucceed = actionContext.Exception == null; - - var clent = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]); + var headers = httpContext.Request.Headers; + var clientInfo = headers.ContainsKey("User-Agent") ? Parser.GetDefault().Parse(headers["User-Agent"]) : null; var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; - var descAtt = Attribute.GetCustomAttribute(actionDescriptor.MethodInfo, typeof(DescriptionAttribute)) as DescriptionAttribute; + // _ = Attribute.GetCustomAttribute(actionDescriptor.MethodInfo, typeof(DescriptionAttribute)) as DescriptionAttribute; - //var sysOpLog = new SysLogOp - //{ - // Name = descAtt != null ? descAtt.Description : actionDescriptor.ActionName, - // OpType = 1, - // Success = isRequestSucceed ? YesOrNot.Y.ToString() : YesOrNot.N.ToString(), - // //Message = isRequestSucceed ? "成功" : "失败", - // Ip = httpContext.GetRemoteIpAddressToIPv4(), - // Location = httpRequest.GetRequestUrlAddress(), - // Browser = clent.UA.Family + clent.UA.Major, - // Os = clent.OS.Family + clent.OS.Major, - // Url = httpRequest.Path, - // ClassName = context.Controller.ToString(), - // MethodName = actionDescriptor.ActionName, - // ReqMethod = httpRequest.Method, - // //Param = JsonSerializerUtility.Serialize(context.ActionArguments), - // //Result = JsonSerializerUtility.Serialize(actionContext.Result), - // ElapsedTime = sw.ElapsedMilliseconds, - // OpTime = DateTimeOffset.Now, - // Account = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_ACCOUNT) - //}; - //await sysOpLog.InsertAsync(); + // 请求日志入库 + await new SysLogOp + { + Name = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_NAME), + Success = isRequestSucceed ? YesOrNot.Y : YesOrNot.N, + Ip = httpContext.GetRemoteIpAddressToIPv4(), + Location = httpRequest.GetRequestUrlAddress(), + Browser = clientInfo?.UA.Family + clientInfo?.UA.Major, + Os = clientInfo?.OS.Family + clientInfo?.OS.Major, + Url = httpRequest.Path, + ClassName = context.Controller.ToString(), + MethodName = actionDescriptor.ActionName, + ReqMethod = httpRequest.Method, + Param = JSON.Serialize(context.ActionArguments.Count < 1 ? "" : context.ActionArguments), + //Result = JSON.Serialize(actionContext.Result), // 序列化异常,比如验证码 + ElapsedTime = sw.ElapsedMilliseconds, + OpTime = DateTimeOffset.Now, + Account = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_ACCOUNT) + }.InsertAsync(); } } } diff --git a/backend/Dilon.Core/Manager/UserManager.cs b/backend/Dilon.Core/Manager/UserManager.cs index 07830bd6e6601e3c0ea0b56c1bb701c2256da977..e4bccb35fabd41ff89bdd0836281d6f809566fb0 100644 --- a/backend/Dilon.Core/Manager/UserManager.cs +++ b/backend/Dilon.Core/Manager/UserManager.cs @@ -37,7 +37,7 @@ namespace Dilon.Core public SysUser User { - get => _sysUserRep.Find(UserId); + get => _sysUserRep.FirstOrDefault(u => u.Id == UserId); } public UserManager(IRepository sysUserRep, diff --git a/backend/Dilon.Core/SeedData/SysAppSeedData.cs b/backend/Dilon.Core/SeedData/SysAppSeedData.cs index 70643978eaee564e57762aa5fdd73cf5fd1868fa..09dffa7e351104a58570b38157cea8bd7e9db7b1 100644 --- a/backend/Dilon.Core/SeedData/SysAppSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysAppSeedData.cs @@ -20,8 +20,10 @@ namespace Dilon.Core { return new[] { - new SysApp{Id=142307070898245, Name="系统管理", Code="system", Active="Y", Status=0, Sort=100 }, - new SysApp{Id=142307070902341, Name="系统工具", Code="system_tool", Active="N", Status=0, Sort=100 } + new SysApp{Id=142307070898245, Name="平台管理", Code="system", Active="Y", Status=0, Sort=100 }, + new SysApp{Id=142307070922826, Name="运营管理", Code="platform", Active="N", Status=0, Sort=200 }, + new SysApp{Id=142307070902341, Name="系统管理", Code="manage", Active="N", Status=0, Sort=300 }, + new SysApp{Id=142307070922869, Name="业务应用", Code="busiapp", Active="N", Status=0, Sort=400 }, }; } } diff --git a/backend/Dilon.Core/SeedData/SysConfigSeedData.cs b/backend/Dilon.Core/SeedData/SysConfigSeedData.cs index ee67f1e898614965f27f7a846beab51ce6331749..4abe36e905402779e032ca7fe2c06aebb1565404 100644 --- a/backend/Dilon.Core/SeedData/SysConfigSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysConfigSeedData.cs @@ -56,4 +56,4 @@ namespace Dilon.Core }; } } -} +} \ No newline at end of file diff --git a/backend/Dilon.Core/SeedData/SysDictDataSeedData.cs b/backend/Dilon.Core/SeedData/SysDictDataSeedData.cs index 85de0a51bdcdc3aa505ca15b6c544629201f36ba..18a9ccdcf3fe15937a65778cde2c650dc1ce0f66 100644 --- a/backend/Dilon.Core/SeedData/SysDictDataSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysDictDataSeedData.cs @@ -90,7 +90,48 @@ namespace Dilon.Core new SysDictData{Id=142307070906479, TypeId=142307070910538, Value="GET", Code="1", Sort=100, Remark="GET", Status=0 }, new SysDictData{Id=142307070906480, TypeId=142307070910538, Value="POST", Code="2", Sort=100, Remark="POST", Status=0 }, new SysDictData{Id=142307070906481, TypeId=142307070910538, Value="PUT", Code="3", Sort=100, Remark="PUT", Status=0 }, - new SysDictData{Id=142307070906482, TypeId=142307070910538, Value="DELETE", Code="4", Sort=100, Remark="DELETE", Status=0 } + new SysDictData{Id=142307070906482, TypeId=142307070910538, Value="DELETE", Code="4", Sort=100, Remark="DELETE", Status=0 }, + + new SysDictData{Id=142307070922830, TypeId=142307070922827, Value="输入框", Code="input", Sort=100, Remark="输入框", Status=0 }, + new SysDictData{Id=142307070922831, TypeId=142307070922827, Value="时间选择", Code="datepicker", Sort=100, Remark="时间选择", Status=0 }, + new SysDictData{Id=142307070922832, TypeId=142307070922827, Value="下拉框", Code="select", Sort=100, Remark="下拉框", Status=0 }, + new SysDictData{Id=142307070922833, TypeId=142307070922827, Value="单选框", Code="radio", Sort=100, Remark="单选框", Status=0 }, + new SysDictData{Id=142307070922834, TypeId=142307070922827, Value="开关", Code="switch", Sort=100, Remark="开关", Status=0 }, + new SysDictData{Id=142307070922835, TypeId=142307070922827, Value="多选框", Code="checkbox", Sort=100, Remark="多选框", Status=0 }, + new SysDictData{Id=142307070922836, TypeId=142307070922827, Value="数字输入框", Code="inputnumber", Sort=100, Remark="数字输入框", Status=0 }, + new SysDictData{Id=142307070922837, TypeId=142307070922827, Value="文本域", Code="textarea", Sort=100, Remark="文本域", Status=0 }, + + new SysDictData{Id=142307070922838, TypeId=142307070922828, Value="等于", Code="==", Sort=1, Remark="等于", Status=0 }, + new SysDictData{Id=142307070922839, TypeId=142307070922828, Value="模糊", Code="like", Sort=2, Remark="模糊", Status=0 }, + new SysDictData{Id=142307070922840, TypeId=142307070922828, Value="大于", Code=">", Sort=3, Remark="大于", Status=0 }, + new SysDictData{Id=142307070922841, TypeId=142307070922828, Value="小于", Code="<", Sort=4, Remark="小于", Status=0 }, + new SysDictData{Id=142307070922842, TypeId=142307070922828, Value="不等于", Code="!=", Sort=5, Remark="不等于", Status=0 }, + new SysDictData{Id=142307070922843, TypeId=142307070922828, Value="大于等于", Code=">=", Sort=6, Remark="大于等于", Status=0 }, + new SysDictData{Id=142307070922844, TypeId=142307070922828, Value="小于等于", Code="<=", Sort=7, Remark="小于等于", Status=0 }, + new SysDictData{Id=142307070922845, TypeId=142307070922828, Value="不为空", Code="isNotNull", Sort=8, Remark="不为空", Status=0 }, + + new SysDictData{Id=142307070922851, TypeId=142307070922829, Value="int", Code="int", Sort=100, Remark="int", Status=0 }, + new SysDictData{Id=142307070922846, TypeId=142307070922829, Value="long", Code="long", Sort=100, Remark="long", Status=0 }, + new SysDictData{Id=142307070922847, TypeId=142307070922829, Value="string", Code="string", Sort=100, Remark="string", Status=0 }, + new SysDictData{Id=142307070922850, TypeId=142307070922829, Value="bool", Code="bool", Sort=100, Remark="bool", Status=0 }, + new SysDictData{Id=142307070922852, TypeId=142307070922829, Value="double", Code="double", Sort=100, Remark="double", Status=0 }, + new SysDictData{Id=142307070922848, TypeId=142307070922829, Value="DateTime", Code="DateTime", Sort=100, Remark="DateTime", Status=0 }, + new SysDictData{Id=142307070922861, TypeId=142307070922829, Value="float", Code="float", Sort=100, Remark="float", Status=0 }, + new SysDictData{Id=142307070922862, TypeId=142307070922829, Value="decimal", Code="decimal", Sort=100, Remark="decimal", Status=0 }, + new SysDictData{Id=142307070922863, TypeId=142307070922829, Value="Guid", Code="Guid", Sort=100, Remark="Guid", Status=0 }, + new SysDictData{Id=142307070922864, TypeId=142307070922829, Value="DateTimeOffset", Code="DateTimeOffset", Sort=100, Remark="DateTimeOffset", Status=0 }, + + //new SysDictData{Id=142307070922854, TypeId=142307070922853, Value="int", Code="int", Sort=100, Remark="int", Status=0 }, + //new SysDictData{Id=142307070922855, TypeId=142307070922853, Value="long", Code="long", Sort=100, Remark="long", Status=0 }, + //new SysDictData{Id=142307070922856, TypeId=142307070922853, Value="string", Code="string", Sort=100, Remark="string", Status=0 }, + //new SysDictData{Id=142307070922858, TypeId=142307070922853, Value="bool", Code="bool", Sort=100, Remark="boolean", Status=0 }, + //new SysDictData{Id=142307070922859, TypeId=142307070922853, Value="double", Code="double", Sort=100, Remark="double", Status=0 }, + //new SysDictData{Id=142307070922860, TypeId=142307070922853, Value="DateTime", Code="DateTime", Sort=100, Remark="DateTime", Status=0 }, + //new SysDictData{Id=142307070922865, TypeId=142307070922853, Value="float", Code="float", Sort=100, Remark="float", Status=0 }, + //new SysDictData{Id=142307070922866, TypeId=142307070922853, Value="decimal", Code="decimal", Sort=100, Remark="decimal", Status=0 }, + //new SysDictData{Id=142307070922867, TypeId=142307070922853, Value="Guid", Code="Guid", Sort=100, Remark="Guid", Status=0 }, + //new SysDictData{Id=142307070922868, TypeId=142307070922853, Value="DateTimeOffset", Code="DateTimeOffset", Sort=100, Remark="DateTimeOffset", Status=0 }, + }; } } diff --git a/backend/Dilon.Core/SeedData/SysDictTypeSeedData.cs b/backend/Dilon.Core/SeedData/SysDictTypeSeedData.cs index 3d5219921a6bae40210705d34fddbfc5000d182e..38f875eaa5bf8bd899e5e819b6df7934e02f6db1 100644 --- a/backend/Dilon.Core/SeedData/SysDictTypeSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysDictTypeSeedData.cs @@ -38,7 +38,10 @@ namespace Dilon.Core new SysDictType{Id=142307070910535, Name="通知公告状态", Code="notice_status", Sort=100, Remark="通知公告状态", Status=0 }, new SysDictType{Id=142307070910536, Name="是否boolean", Code="yes_true_false", Sort=100, Remark="是否boolean", Status=0 }, new SysDictType{Id=142307070910537, Name="代码生成方式", Code="code_gen_create_type", Sort=100, Remark="代码生成方式", Status=0 }, - new SysDictType{Id=142307070910538, Name="请求方式", Code="request_type", Sort=100, Remark="请求方式", Status=0 } + new SysDictType{Id=142307070910538, Name="请求方式", Code="request_type", Sort=100, Remark="请求方式", Status=0 }, + new SysDictType{Id=142307070922827, Name="代码生成作用类型", Code="code_gen_effect_type", Sort=100, Remark="代码生成作用类型", Status=0 }, + new SysDictType{Id=142307070922828, Name="代码生成查询类型", Code="code_gen_query_type", Sort=100, Remark="代码生成查询类型", Status=0 }, + new SysDictType{Id=142307070922829, Name="代码生成.NET类型", Code="code_gen_net_type", Sort=100, Remark="代码生成.NET类型", Status=0 }, }; } } diff --git a/backend/Dilon.Core/SeedData/SysEmpPosSeedData.cs b/backend/Dilon.Core/SeedData/SysEmpPosSeedData.cs index 98b5240117797127907da4fdae51b2a8226c0ccd..605914c1ed529860e88d02ef052c1c5ff372f4e9 100644 --- a/backend/Dilon.Core/SeedData/SysEmpPosSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysEmpPosSeedData.cs @@ -23,7 +23,17 @@ namespace Dilon.Core new SysEmpPos{SysEmpId=142307070910551, SysPosId=142307070910547 }, new SysEmpPos{SysEmpId=142307070910551, SysPosId=142307070910548 }, new SysEmpPos{SysEmpId=142307070910552, SysPosId=142307070910549 }, - new SysEmpPos{SysEmpId=142307070910553, SysPosId=142307070910547 } + new SysEmpPos{SysEmpId=142307070910553, SysPosId=142307070910547 }, + + new SysEmpPos{SysEmpId=142307070910554, SysPosId=142307070910551 }, + new SysEmpPos{SysEmpId=142307070910554, SysPosId=142307070910552 }, + new SysEmpPos{SysEmpId=142307070910555, SysPosId=142307070910553 }, + new SysEmpPos{SysEmpId=142307070910555, SysPosId=142307070910551 }, + + new SysEmpPos{SysEmpId=142307070910557, SysPosId=142307070910555 }, + new SysEmpPos{SysEmpId=142307070910557, SysPosId=142307070910556 }, + new SysEmpPos{SysEmpId=142307070910558, SysPosId=142307070910557 }, + new SysEmpPos{SysEmpId=142307070910559, SysPosId=142307070910555 } }; } } diff --git a/backend/Dilon.Core/SeedData/SysEmpSeedData.cs b/backend/Dilon.Core/SeedData/SysEmpSeedData.cs index 7f1bc5283acda63c471428721b5b2adedc4b7ea3..a7a2022879d00ae13613cecfacab7d30aa0d409a 100644 --- a/backend/Dilon.Core/SeedData/SysEmpSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysEmpSeedData.cs @@ -22,7 +22,15 @@ namespace Dilon.Core { new SysEmp{Id=142307070910551, JobNum="D1001", OrgId=142307070910539, OrgName="华夏集团" }, new SysEmp{Id=142307070910552, JobNum="D1002", OrgId=142307070910539, OrgName="华夏集团" }, - new SysEmp{Id=142307070910553, JobNum="D1003", OrgId=142307070910539, OrgName="华夏集团" } + new SysEmp{Id=142307070910553, JobNum="D1003", OrgId=142307070910539, OrgName="华夏集团" }, + + new SysEmp{Id=142307070910554, JobNum="D1001", OrgId=142307070910547, OrgName="租户1公司" }, + new SysEmp{Id=142307070910555, JobNum="D1002", OrgId=142307070910547, OrgName="租户1公司" }, + new SysEmp{Id=142307070910556, JobNum="D1003", OrgId=142307070910547, OrgName="租户1公司" }, + + new SysEmp{Id=142307070910557, JobNum="D1001", OrgId=142307070910548, OrgName="租户2公司" }, + new SysEmp{Id=142307070910558, JobNum="D1002", OrgId=142307070910548, OrgName="租户2公司" }, + new SysEmp{Id=142307070910559, JobNum="D1003", OrgId=142307070910548, OrgName="租户2公司" } }; } } diff --git a/backend/Dilon.Core/SeedData/SysMenuSeedData.cs b/backend/Dilon.Core/SeedData/SysMenuSeedData.cs index e9016823b06e160dcab30ef184699e3967bcc188..d5e9ea5dfd97ababd5f3d3a07c8473e1bf685419 100644 --- a/backend/Dilon.Core/SeedData/SysMenuSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysMenuSeedData.cs @@ -20,46 +20,55 @@ namespace Dilon.Core { return new[] { - new SysMenu{Id=142307070910560, Pid=0, Pids="[0],", Name="主控面板", Code="system_index", Type=0, Icon="home", Router="/", Component="RouteView", Application="system", OpenType=0, Visible="Y", Redirect="/analysis", Weight=1, Sort=1, Status=0 }, - new SysMenu{Id=142307070910561, Pid=142307070910560, Pids="[0],[142307070910560],", Name="分析页", Code="system_index_dashboard", Type=1, Router="analysis", Component="system/dashboard/Analysis", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910562, Pid=142307070910560, Pids="[0],[142307070910560],", Name="工作台", Code="system_index_workplace", Type=1, Router="workplace", Component="system/dashboard/Workplace", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307000914633, Pid=0, Pids="[0],", Name="组织架构", Code="sys_mgr", Type=0, Icon="team", Router="/sys", Component="PageView", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910581, Pid=142307000914633, Pids="[0],[142307000914633],", Name="机构管理", Code="sys_org_mgr", Type=1, Router="/org", Component="system/org/index", Application="manage", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910582, Pid=142307070910581, Pids="[0],[142307000914633],[142307070910581],", Name="机构查询", Code="sys_org_mgr_page", Type=2, Permission="sysOrg:page", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910583, Pid=142307070910581, Pids="[0],[142307000914633],[142307070910581],", Name="机构列表", Code="sys_org_mgr_list", Type=2, Permission="sysOrg:list", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910584, Pid=142307070910581, Pids="[0],[142307000914633],[142307070910581],", Name="机构增加", Code="sys_org_mgr_add", Type=2, Permission="sysOrg:add", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910585, Pid=142307070910581, Pids="[0],[142307000914633],[142307070910581],", Name="机构编辑", Code="sys_org_mgr_edit", Type=2, Permission="sysOrg:edit", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910586, Pid=142307070910581, Pids="[0],[142307000914633],[142307070910581],", Name="机构删除", Code="sys_org_mgr_delete", Type=2, Permission="sysOrg:delete", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070910587, Pid=142307070910581, Pids="[0],[142307000914633],[142307070910581],", Name="机构详情", Code="sys_org_mgr_detail", Type=2, Permission="sysOrg:detail", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910588, Pid=142307070910581, Pids="[0],[142307000914633],[142307070910581],", Name="机构树", Code="sys_org_mgr_tree", Type=2, Permission="sysOrg:tree", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070910589, Pid=142307000914633, Pids="[0],[142307000914633],", Name="职位管理", Code="sys_pos_mgr", Type=1, Router="/pos", Component="system/pos/index", Application="manage", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070910590, Pid=142307070910589, Pids="[0],[142307000914633],[142307070910589],", Name="职位查询", Code="sys_pos_mgr_page", Type=2, Permission="sysPos:page", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910591, Pid=142307070910589, Pids="[0],[142307000914633],[142307070910589],", Name="职位列表", Code="sys_pos_mgr_list", Type=2, Permission="sysPos:list", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914629, Pid=142307070910589, Pids="[0],[142307000914633],[142307070910589],", Name="职位增加", Code="sys_pos_mgr_add", Type=2, Permission="sysPos:add", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914630, Pid=142307070910589, Pids="[0],[142307000914633],[142307070910589],", Name="职位编辑", Code="sys_pos_mgr_edit", Type=2, Permission="sysPos:edit", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070914631, Pid=142307070910589, Pids="[0],[142307000914633],[142307070910589],", Name="职位删除", Code="sys_pos_mgr_delete", Type=2, Permission="sysPos:delete", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914632, Pid=142307070910589, Pids="[0],[142307000914633],[142307070910589],", Name="职位详情", Code="sys_pos_mgr_detail", Type=2, Permission="sysPos:detail", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910563, Pid=0, Pids="[0],", Name="组织架构", Code="sys_mgr", Type=0, Icon="team", Router="/sys", Component="PageView", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910564, Pid=142307070910563, Pids="[0],[142307070910563],", Name="用户管理", Code="sys_user_mgr", Type=1, Router="/mgr_user", Component="system/user/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910565, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户查询", Code="sys_user_mgr_page", Type=2, Permission="sysUser:page", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910566, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户编辑", Code="sys_user_mgr_edit", Type=2, Permission="sysUser:edit", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910567, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户增加", Code="sys_user_mgr_add", Type=2, Permission="sysUser:add", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070910568, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户删除", Code="sys_user_mgr_delete", Type=2, Permission="sysUser:delete", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070910569, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户详情", Code="sys_user_mgr_detail", Type=2, Permission="sysUser:detail", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910570, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户导出", Code="sys_user_mgr_export", Type=2, Permission="sysUser:export", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910571, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户选择器", Code="sys_user_mgr_selector", Type=2, Permission="sysUser:selector", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910572, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户授权角色", Code="sys_user_mgr_grant_role", Type=2, Permission="sysUser:grantRole", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910573, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户拥有角色", Code="sys_user_mgr_own_role", Type=2, Permission="sysUser:ownRole", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910574, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户授权数据", Code="sys_user_mgr_grant_data", Type=2, Permission="sysUser:grantData", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910575, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户拥有数据", Code="sys_user_mgr_own_data", Type=2, Permission="sysUser:ownData", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910576, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户更新信息", Code="sys_user_mgr_update_info", Type=2, Permission="sysUser:updateInfo", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910577, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户修改密码", Code="sys_user_mgr_update_pwd", Type=2, Permission="sysUser:updatePwd", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910578, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户修改状态", Code="sys_user_mgr_change_status", Type=2, Permission="sysUser:changeStatus", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910579, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户修改头像", Code="sys_user_mgr_update_avatar", Type=2, Permission="sysUser:updateAvatar", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070910580, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户重置密码", Code="sys_user_mgr_reset_pwd", Type=2, Permission="sysUser:resetPwd", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070918777, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户登录信息", Code="sys_user_mgr_login", Type=2, Permission="getLoginUser", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910581, Pid=142307070910563, Pids="[0],[142307070910563],", Name="机构管理", Code="sys_org_mgr", Type=1, Router="/org", Component="system/org/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910582, Pid=142307070910581, Pids="[0],[142307070910563],[142307070910581],", Name="机构查询", Code="sys_org_mgr_page", Type=2, Permission="sysOrg:page", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910583, Pid=142307070910581, Pids="[0],[142307070910563],[142307070910581],", Name="机构列表", Code="sys_org_mgr_list", Type=2, Permission="sysOrg:list", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910584, Pid=142307070910581, Pids="[0],[142307070910563],[142307070910581],", Name="机构增加", Code="sys_org_mgr_add", Type=2, Permission="sysOrg:add", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910585, Pid=142307070910581, Pids="[0],[142307070910563],[142307070910581],", Name="机构编辑", Code="sys_org_mgr_edit", Type=2, Permission="sysOrg:edit", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910586, Pid=142307070910581, Pids="[0],[142307070910563],[142307070910581],", Name="机构删除", Code="sys_org_mgr_delete", Type=2, Permission="sysOrg:delete", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070910587, Pid=142307070910581, Pids="[0],[142307070910563],[142307070910581],", Name="机构详情", Code="sys_org_mgr_detail", Type=2, Permission="sysOrg:detail", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910588, Pid=142307070910581, Pids="[0],[142307070910563],[142307070910581],", Name="机构树", Code="sys_org_mgr_tree", Type=2, Permission="sysOrg:tree", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070910589, Pid=142307070910563, Pids="[0],[142307070910563],", Name="职位管理", Code="sys_pos_mgr", Type=1, Router="/pos", Component="system/pos/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070910590, Pid=142307070910589, Pids="[0],[142307070910563],[142307070910589],", Name="职位查询", Code="sys_pos_mgr_page", Type=2, Permission="sysPos:page", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070910591, Pid=142307070910589, Pids="[0],[142307070910563],[142307070910589],", Name="职位列表", Code="sys_pos_mgr_list", Type=2, Permission="sysPos:list", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914629, Pid=142307070910589, Pids="[0],[142307070910563],[142307070910589],", Name="职位增加", Code="sys_pos_mgr_add", Type=2, Permission="sysPos:add", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914630, Pid=142307070910589, Pids="[0],[142307070910563],[142307070910589],", Name="职位编辑", Code="sys_pos_mgr_edit", Type=2, Permission="sysPos:edit", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070914631, Pid=142307070910589, Pids="[0],[142307070910563],[142307070910589],", Name="职位删除", Code="sys_pos_mgr_delete", Type=2, Permission="sysPos:delete", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914632, Pid=142307070910589, Pids="[0],[142307070910563],[142307070910589],", Name="职位详情", Code="sys_pos_mgr_detail", Type=2, Permission="sysPos:detail", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910563, Pid=0, Pids="[0],", Name="权限管理", Code="auth_manager", Type=0, Icon="safety-certificate", Router="/auth", Component="PageView", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910564, Pid=142307070910563, Pids="[0],[142307070910563],", Name="用户管理", Code="sys_user_mgr", Type=1, Router="/mgr_user", Component="system/user/index", Application="manage", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910565, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户查询", Code="sys_user_mgr_page", Type=2, Permission="sysUser:page", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910566, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户编辑", Code="sys_user_mgr_edit", Type=2, Permission="sysUser:edit", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910567, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户增加", Code="sys_user_mgr_add", Type=2, Permission="sysUser:add", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070910568, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户删除", Code="sys_user_mgr_delete", Type=2, Permission="sysUser:delete", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070910569, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户详情", Code="sys_user_mgr_detail", Type=2, Permission="sysUser:detail", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910570, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户导出", Code="sys_user_mgr_export", Type=2, Permission="sysUser:export", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910571, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户选择器", Code="sys_user_mgr_selector", Type=2, Permission="sysUser:selector", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910572, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户授权角色", Code="sys_user_mgr_grant_role", Type=2, Permission="sysUser:grantRole", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910573, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户拥有角色", Code="sys_user_mgr_own_role", Type=2, Permission="sysUser:ownRole", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910574, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户授权数据", Code="sys_user_mgr_grant_data", Type=2, Permission="sysUser:grantData", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910575, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户拥有数据", Code="sys_user_mgr_own_data", Type=2, Permission="sysUser:ownData", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910576, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户更新信息", Code="sys_user_mgr_update_info", Type=2, Permission="sysUser:updateInfo", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910577, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户修改密码", Code="sys_user_mgr_update_pwd", Type=2, Permission="sysUser:updatePwd", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910578, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户修改状态", Code="sys_user_mgr_change_status", Type=2, Permission="sysUser:changeStatus", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910579, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户修改头像", Code="sys_user_mgr_update_avatar", Type=2, Permission="sysUser:updateAvatar", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070910580, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户重置密码", Code="sys_user_mgr_reset_pwd", Type=2, Permission="sysUser:resetPwd", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070918777, Pid=142307070910564, Pids="[0],[142307070910563],[142307070910564],", Name="用户登录信息", Code="sys_user_mgr_login", Type=2, Permission="getLoginUser", Application="manage", OpenType=0, Visible="N", Weight=1, Sort=100, Status=CommonStatus.DISABLE }, + new SysMenu{Id=142307070914651, Pid=142307070910563, Pids="[0],[142307070910563],", Name="角色管理", Code="sys_role_mgr", Type=1, Router="/role", Component="system/role/index", Application="manage", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070914652, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色查询", Code="sys_role_mgr_page", Type=2, Permission="sysRole:page", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914653, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色增加", Code="sys_role_mgr_add", Type=2, Permission="sysRole:add", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914654, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色编辑", Code="sys_role_mgr_edit", Type=2, Permission="sysRole:edit", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914655, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色删除", Code="sys_role_mgr_delete", Type=2, Permission="sysRole:delete", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914656, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色详情", Code="sys_role_mgr_detail", Type=2, Permission="sysRole:detail", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914657, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色下拉", Code="sys_role_mgr_drop_down", Type=2, Permission="sysRole:dropDown", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914658, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色授权菜单", Code="sys_role_mgr_grant_menu", Type=2, Permission="sysRole:grantMenu", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914659, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色拥有菜单", Code="sys_role_mgr_own_menu", Type=2, Permission="sysRole:ownMenu", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914660, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色授权数据", Code="sys_role_mgr_grant_data", Type=2, Permission="sysRole:grantData", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914661, Pid=142307070914651, Pids="[0],[142307070910563],[142307070914651],", Name="角色拥有数据", Code="sys_role_mgr_own_data", Type=2, Permission="sysRole:ownData", Application="manage", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914633, Pid=0, Pids="[0],", Name="权限管理", Code="auth_manager", Type=0, Icon="safety-certificate", Router="/auth", Component="PageView", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070914633, Pid=0, Pids="[0],", Name="平台管理", Code="auth_manager", Type=0, Icon="safety-certificate", Router="/auth", Component="PageView", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070914634, Pid=142307070914633, Pids="[0],[142307070914633],", Name="应用管理", Code="sys_app_mgr", Type=1, Router="/app", Component="system/app/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070914635, Pid=142307070914634, Pids="[0],[142307070914633],[142307070914634],", Name="应用查询", Code="sys_app_mgr_page", Type=2, Permission="sysApp:page", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070914636, Pid=142307070914634, Pids="[0],[142307070914633],[142307070914634],", Name="应用列表", Code="sys_app_mgr_list", Type=2, Permission="sysApp:list", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, @@ -77,17 +86,6 @@ namespace Dilon.Core new SysMenu{Id=142307070914648, Pid=142307070914642, Pids="[0],[142307070914633],[142307070914642],", Name="菜单授权树", Code="sys_menu_mgr_grant_tree", Type=2, Permission="sysMenu:treeForGrant", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070914649, Pid=142307070914642, Pids="[0],[142307070914633],[142307070914642],", Name="菜单树", Code="sys_menu_mgr_tree", Type=2, Permission="sysMenu:tree", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070914650, Pid=142307070914642, Pids="[0],[142307070914633],[142307070914642],", Name="菜单切换", Code="sys_menu_mgr_change", Type=2, Permission="sysMenu:change", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914651, Pid=142307070914633, Pids="[0],[142307070914633],", Name="角色管理", Code="sys_role_mgr", Type=1, Router="/role", Component="system/role/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0}, - new SysMenu{Id=142307070914652, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色查询", Code="sys_role_mgr_page", Type=2, Permission="sysRole:page", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914653, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色增加", Code="sys_role_mgr_add", Type=2, Permission="sysRole:add", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914654, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色编辑", Code="sys_role_mgr_edit", Type=2, Permission="sysRole:edit", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914655, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色删除", Code="sys_role_mgr_delete", Type=2, Permission="sysRole:delete", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914656, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色详情", Code="sys_role_mgr_detail", Type=2, Permission="sysRole:detail", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914657, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色下拉", Code="sys_role_mgr_drop_down", Type=2, Permission="sysRole:dropDown", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914658, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色授权菜单", Code="sys_role_mgr_grant_menu", Type=2, Permission="sysRole:grantMenu", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914659, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色拥有菜单", Code="sys_role_mgr_own_menu", Type=2, Permission="sysRole:ownMenu", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914660, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色授权数据", Code="sys_role_mgr_grant_data", Type=2, Permission="sysRole:grantData", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070914661, Pid=142307070914651, Pids="[0],[142307070914633],[142307070914651],", Name="角色拥有数据", Code="sys_role_mgr_own_data", Type=2, Permission="sysRole:ownData", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070914662, Pid=0, Pids="[0],", Name="开发管理", Code="system_tools", Type=0, Icon="euro", Router="/tools", Component="PageView", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070914663, Pid=142307070914662, Pids="[0],[142307070914662],", Name="系统配置", Code="system_tools_config", Type=1, Router="/config", Component="system/config/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, @@ -121,7 +119,7 @@ namespace Dilon.Core new SysMenu{Id=142307070918728, Pid=142307070914678, Pids="[0],[142307070914662],[142307070914678],", Name="字典值编辑", Code="sys_dict_mgr_dict_edit", Type=2, Permission="sysDictData:edit", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070918729, Pid=142307070914678, Pids="[0],[142307070914662],[142307070914678],", Name="字典值详情", Code="sys_role_mgr_grant_data", Type=2, Permission="sysDictData:detail", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070918730, Pid=142307070914678, Pids="[0],[142307070914662],[142307070914678],", Name="字典值修改状态", Code="sys_dict_mgr_dict_change_status", Type=2, Permission="sysDictData:changeStatus", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070918731, Pid=142307070914662, Pids="[0],[142307070914662],", Name="接口文档", Code="sys_swagger_mgr", Type=1, Router="/swagger", Component="Iframe", Application="system", OpenType=2, Visible="Y", Link="http://127.0.0.1:5566/", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070918731, Pid=142307070914662, Pids="[0],[142307070914662],", Name="接口文档", Code="sys_swagger_mgr", Type=1, Router="/swagger", Component="Iframe", Application="system", OpenType=2, Visible="Y", Link="http://localhost:5566/", Weight=1, Sort=100, Status=0}, new SysMenu{Id=142307070918732, Pid=0, Pids="[0],", Name="日志管理", Code="sys_log_mgr", Type=0, Icon="read", Router="/log", Component="PageView", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070918733, Pid=142307070918732, Pids="[0],[142307070918732],", Name="访问日志", Code="sys_log_mgr_vis_log", Type=1, Router="/vislog", Component="system/log/vislog/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, @@ -130,6 +128,9 @@ namespace Dilon.Core new SysMenu{Id=142307070918736, Pid=142307070918732, Pids="[0],[142307070918732],", Name="操作日志", Code="sys_log_mgr_op_log", Type=1, Router="/oplog", Component="system/log/oplog/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0}, new SysMenu{Id=142307070918737, Pid=142307070918736, Pids="[0],[142307070918732],[142307070918736],", Name="操作日志查询", Code="sys_log_mgr_op_log_page", Type=2, Permission="sysOpLog:page", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070918738, Pid=142307070918736, Pids="[0],[142307070918732],[142307070918736],", Name="操作日志清空", Code="sys_log_mgr_op_log_delete", Type=2, Permission="sysOpLog:delete", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070911739, Pid=142307070918732, Pids="[0],[142307070918732],", Name="异常日志", Code="sys_log_mgr_ex_log", Type=1, Router="/exlog", Component="system/log/exlog/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0}, + new SysMenu{Id=142307070911740, Pid=142307070911739, Pids="[0],[142307070918732],[142307070911739],", Name="异常日志查询", Code="sys_log_mgr_ex_log_page", Type=2, Permission="sysExLog:page", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070911741, Pid=142307070911739, Pids="[0],[142307070918732],[142307070911739],", Name="异常日志清空", Code="sys_log_mgr_ex_log_delete", Type=2, Permission="sysExLog:delete", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070918739, Pid=0, Pids="[0],", Name="系统监控", Code="sys_monitor_mgr", Type=0, Icon="deployment-unit", Router="/monitor", Component="PageView", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070918740, Pid=142307070918739, Pids="[0],[142307070918739],", Name="服务监控", Code="sys_monitor_mgr_machine_monitor", Type=1, Router="/machine", Component="system/machine/index", Application="system", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, @@ -172,7 +173,22 @@ namespace Dilon.Core new SysMenu{Id=142307070918774, Pid=142307070918766, Pids="[0],[142307070918765],[142307070918766],", Name="定时任务启动", Code="sys_timers_mgr_start", Type=2, Permission="sysTimers:start", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, new SysMenu{Id=142307070918775, Pid=142307070918766, Pids="[0],[142307070918765],[142307070918766],", Name="定时任务关闭", Code="sys_timers_mgr_stop", Type=2, Permission="sysTimers:stop", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, - new SysMenu{Id=142307070918776, Pid=0, Pids="[0],", Name="代码生成", Code="code_gen", Type=1, Icon="thunderbolt", Router="/codeGenerate/index", Component="gen/codeGenerate/index", Application="system_tool", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070918776, Pid=0, Pids="[0],", Name="代码生成", Code="code_gen", Type=1, Icon="thunderbolt", Router="/codeGenerate/index", Component="gen/codeGenerate/index", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922870, Pid=0, Pids="[0],", Name="表单设计", Code="form_design", Type=1, Icon="robot", Router="/formDesign/index", Component="system/formDesign/index", Application="system", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + + new SysMenu{Id=142307070918782, Pid=0, Pids="[0],", Name="SaaS租户", Code="sys_tenant", Type=1, Icon="switcher", Router="/tenant", Component="PageView", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070918783, Pid=142307070918782, Pids="[0],[142307070918782],", Name="租户管理", Code="sys_tenant_mgr", Type=1, Router="/tenant", Component="system/tenant/index", Application="platform", OpenType=1, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922821, Pid=142307070918783, Pids="[0],[142307070918782],[142307070918783],", Name="租户查询", Code="sys_tenant_mgr_page", Type=2, Permission="sysTenant:page", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922822, Pid=142307070918783, Pids="[0],[142307070918782],[142307070918783],", Name="租户详情", Code="sys_tenant_mgr_detail", Type=2, Permission="sysTenant:detail", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922823, Pid=142307070918783, Pids="[0],[142307070918782],[142307070918783],", Name="租户增加", Code="sys_tenant_mgr_add", Type=2, Permission="sysTenant:add", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922824, Pid=142307070918783, Pids="[0],[142307070918782],[142307070918783],", Name="租户删除", Code="sys_tenant_mgr_delete", Type=2, Permission="sysTenant:delete", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922825, Pid=142307070918783, Pids="[0],[142307070918782],[142307070918783],", Name="租户编辑", Code="sys_tenant_mgr_edit", Type=2, Permission="sysTenant:edit", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922826, Pid=142307070918783, Pids="[0],[142307070918782],[142307070918783],", Name="授权租户菜单", Code="sys_tenant_mgr_grant_menu", Type=2, Permission="sysTenant:grantMenu", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070922827, Pid=142307070918783, Pids="[0],[142307070918782],[142307070918783],", Name="重置租户密码", Code="sys_tenant_mgr_reset_pwd", Type=2, Permission="sysTenant:resetPwd", Application="platform", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + + new SysMenu{Id=142307070910560, Pid=0, Pids="[0],", Name="主控面板", Code="system_index", Type=0, Icon="home", Router="/", Component="RouteView", Application="busiapp", OpenType=0, Visible="Y", Redirect="/analysis", Weight=1, Sort=1, Status=0 }, + new SysMenu{Id=142307070910561, Pid=142307070910560, Pids="[0],[142307070910560],", Name="分析页", Code="system_index_dashboard", Type=1, Router="analysis", Component="system/dashboard/Analysis", Application="busiapp", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, + new SysMenu{Id=142307070910562, Pid=142307070910560, Pids="[0],[142307070910560],", Name="工作台", Code="system_index_workplace", Type=1, Router="workplace", Component="system/dashboard/Workplace", Application="busiapp", OpenType=0, Visible="Y", Weight=1, Sort=100, Status=0 }, }; } diff --git a/backend/Dilon.Core/SeedData/SysOrgSeedData.cs b/backend/Dilon.Core/SeedData/SysOrgSeedData.cs index 16ab9f778b0997198d63ad9a7810a51760dc7ea3..ee3f94a7db92b3db02ff9c23b4f1a8d5119880c4 100644 --- a/backend/Dilon.Core/SeedData/SysOrgSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysOrgSeedData.cs @@ -20,14 +20,16 @@ namespace Dilon.Core { return new[] { - new SysOrg{Id=142307070910539, Pid=0, Pids="[0],", Name="华夏集团", Code="hxjt", Sort=100, Remark="华夏集团", Status=0 }, - new SysOrg{Id=142307070910540, Pid=142307070910539, Pids="[0],[142307070910539],", Name="华夏集团北京分公司", Code="hxjt_bj", Sort=100, Remark="华夏集团北京分公司", Status=0 }, - new SysOrg{Id=142307070910541, Pid=142307070910539, Pids="[0],[142307070910539],", Name="华夏集团成都分公司", Code="hxjt_cd", Sort=100, Remark="华夏集团成都分公司", Status=0 }, - new SysOrg{Id=142307070910542, Pid=142307070910540, Pids="[0],[142307070910539],[142307070910540],", Name="研发部", Code="hxjt_bj_yfb", Sort=100, Remark="华夏集团北京分公司研发部", Status=0 }, - new SysOrg{Id=142307070910543, Pid=142307070910540, Pids="[0],[142307070910539],[142307070910540],", Name="企划部", Code="hxjt_bj_qhb", Sort=100, Remark="华夏集团北京分公司企划部", Status=0 }, - new SysOrg{Id=142307070910544, Pid=142307070910541, Pids="[0],[142307070910539],[142307070910541],", Name="市场部", Code="hxjt_cd_scb", Sort=100, Remark="华夏集团成都分公司市场部", Status=0 }, - new SysOrg{Id=142307070910545, Pid=142307070910541, Pids="[0],[142307070910539],[142307070910541],", Name="财务部", Code="hxjt_cd_cwb", Sort=100, Remark="华夏集团成都分公司财务部", Status=0 }, - new SysOrg{Id=142307070910546, Pid=142307070910544, Pids="[0],[142307070910539],[142307070910541],[142307070910544],", Name="市场部二部", Code="hxjt_cd_scb_2b", Sort=100, Remark="华夏集团成都分公司市场部二部", Status=0 } + new SysOrg{TenantId=142307070918780, Id=142307070910539, Pid=0, Pids="[0],", Name="华夏集团", Code="hxjt", Sort=100, Remark="华夏集团", Status=0 }, + new SysOrg{TenantId=142307070918780, Id=142307070910540, Pid=142307070910539, Pids="[0],[142307070910539],", Name="华夏集团北京分公司", Code="hxjt_bj", Sort=100, Remark="华夏集团北京分公司", Status=0 }, + new SysOrg{TenantId=142307070918780, Id=142307070910541, Pid=142307070910539, Pids="[0],[142307070910539],", Name="华夏集团成都分公司", Code="hxjt_cd", Sort=100, Remark="华夏集团成都分公司", Status=0 }, + new SysOrg{TenantId=142307070918780, Id=142307070910542, Pid=142307070910540, Pids="[0],[142307070910539],[142307070910540],", Name="研发部", Code="hxjt_bj_yfb", Sort=100, Remark="华夏集团北京分公司研发部", Status=0 }, + new SysOrg{TenantId=142307070918780, Id=142307070910543, Pid=142307070910540, Pids="[0],[142307070910539],[142307070910540],", Name="企划部", Code="hxjt_bj_qhb", Sort=100, Remark="华夏集团北京分公司企划部", Status=0 }, + new SysOrg{TenantId=142307070918780, Id=142307070910544, Pid=142307070910541, Pids="[0],[142307070910539],[142307070910541],", Name="市场部", Code="hxjt_cd_scb", Sort=100, Remark="华夏集团成都分公司市场部", Status=0 }, + new SysOrg{TenantId=142307070918780, Id=142307070910545, Pid=142307070910541, Pids="[0],[142307070910539],[142307070910541],", Name="财务部", Code="hxjt_cd_cwb", Sort=100, Remark="华夏集团成都分公司财务部", Status=0 }, + new SysOrg{TenantId=142307070918780, Id=142307070910546, Pid=142307070910544, Pids="[0],[142307070910539],[142307070910541],[142307070910544],", Name="市场部二部", Code="hxjt_cd_scb_2b", Sort=100, Remark="华夏集团成都分公司市场部二部", Status=0 }, + new SysOrg{TenantId=142307070918781, Id=142307070910547, Pid=0, Pids="[0],", Name="租户1公司", Code="gsmc", Sort=100, Remark="公司名称", Status=0 }, + new SysOrg{TenantId=142307070918782, Id=142307070910548, Pid=0, Pids="[0],", Name="租户2公司", Code="gsmc", Sort=100, Remark="公司名称", Status=0 }, }; } } diff --git a/backend/Dilon.Core/SeedData/SysPosSeedData.cs b/backend/Dilon.Core/SeedData/SysPosSeedData.cs index 1d00272e7c5a2018108ae7a8dd08f264ff2c76d4..32ce887ce917a8e22bfcb7ea1f0413f0a0b2344b 100644 --- a/backend/Dilon.Core/SeedData/SysPosSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysPosSeedData.cs @@ -20,10 +20,20 @@ namespace Dilon.Core { return new[] { - new SysPos{Id=142307070910547, Name="总经理", Code="zjl", Sort=100, Remark="总经理", Status=0 }, - new SysPos{Id=142307070910548, Name="副总经理", Code="fzjl", Sort=101, Remark="副总经理", Status=0 }, - new SysPos{Id=142307070910549, Name="部门经理", Code="bmjl", Sort=102, Remark="部门经理", Status=0 }, - new SysPos{Id=142307070910550, Name="工作人员", Code="gzry", Sort=103, Remark="工作人员", Status=0 } + new SysPos{TenantId=142307070918780, Id=142307070910547, Name="总经理", Code="zjl", Sort=100, Remark="总经理", Status=0 }, + new SysPos{TenantId=142307070918780, Id=142307070910548, Name="副总经理", Code="fzjl", Sort=101, Remark="副总经理", Status=0 }, + new SysPos{TenantId=142307070918780, Id=142307070910549, Name="部门经理", Code="bmjl", Sort=102, Remark="部门经理", Status=0 }, + new SysPos{TenantId=142307070918780, Id=142307070910550, Name="工作人员", Code="gzry", Sort=103, Remark="工作人员", Status=0 }, + + new SysPos{TenantId=142307070918781, Id=142307070910551, Name="总经理", Code="zjl", Sort=100, Remark="总经理", Status=0 }, + new SysPos{TenantId=142307070918781, Id=142307070910552, Name="副总经理", Code="fzjl", Sort=101, Remark="副总经理", Status=0 }, + new SysPos{TenantId=142307070918781, Id=142307070910553, Name="部门经理", Code="bmjl", Sort=102, Remark="部门经理", Status=0 }, + new SysPos{TenantId=142307070918781, Id=142307070910554, Name="工作人员", Code="gzry", Sort=103, Remark="工作人员", Status=0 }, + + new SysPos{TenantId=142307070918782, Id=142307070910555, Name="总经理", Code="zjl", Sort=100, Remark="总经理", Status=0 }, + new SysPos{TenantId=142307070918782, Id=142307070910556, Name="副总经理", Code="fzjl", Sort=101, Remark="副总经理", Status=0 }, + new SysPos{TenantId=142307070918782, Id=142307070910557, Name="部门经理", Code="bmjl", Sort=102, Remark="部门经理", Status=0 }, + new SysPos{TenantId=142307070918782, Id=142307070910558, Name="工作人员", Code="gzry", Sort=103, Remark="工作人员", Status=0 } }; } } diff --git a/backend/Dilon.Core/SeedData/SysRoleMenuSeedData.cs b/backend/Dilon.Core/SeedData/SysRoleMenuSeedData.cs new file mode 100644 index 0000000000000000000000000000000000000000..e10ecb13d7670b584fca32c74ba5a83a1f0f9419 --- /dev/null +++ b/backend/Dilon.Core/SeedData/SysRoleMenuSeedData.cs @@ -0,0 +1,73 @@ +using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace Dilon.Core.SeedData +{ + public class SysRoleMenuSeedData : IEntitySeedData + { + /// + /// 种子数据 + /// + /// + /// + /// + public IEnumerable HasData(DbContext dbContext, Type dbContextLocator) + { + return new[] + { + // 租户管理员角色默认有系统管理和业务应用菜单 + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910563 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910581 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910582 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910583 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910584 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910585 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910586 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910587 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910588 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910589 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910590 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910591 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914629 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914630 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914631 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914632 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307000914633 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910564 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910565 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910566 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910567 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910568 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910569 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910570 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910571 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910572 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910573 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910574 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910575 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910576 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910577 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910578 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910579 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910580 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070918777 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914651 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914652 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914653 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914654 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914655 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914656 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914657 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914658 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914659 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914660 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070914661 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910560 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910561 }, + new SysRoleMenu{ SysRoleId=142307070910556, SysMenuId=142307070910562 } + }; + } + } +} diff --git a/backend/Dilon.Core/SeedData/SysRoleSeedData.cs b/backend/Dilon.Core/SeedData/SysRoleSeedData.cs index 0bf52081b304c7287d25a0996b518deaab44735f..fc63615b6b0a8b3b043c6540311eb2d32602a96a 100644 --- a/backend/Dilon.Core/SeedData/SysRoleSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysRoleSeedData.cs @@ -20,8 +20,11 @@ namespace Dilon.Core { return new[] { - new SysRole{Id=142307070910554, Name="系统管理员", Code="sys_manager_role", Sort=100, DataScopeType=1, Remark="系统管理员", Status=0 }, - new SysRole{Id=142307070910555, Name="普通用户", Code="common_role", Sort=101, DataScopeType=5, Remark="普通用户", Status=0 } + new SysRole{TenantId=142307070918780, Id=142307070910554, Name="系统管理员", Code="sys_manager_role", Sort=100, DataScopeType=1, Remark="系统管理员", Status=0 }, + new SysRole{TenantId=142307070918780, Id=142307070910555, Name="普通用户", Code="common_role", Sort=101, DataScopeType=5, Remark="普通用户", Status=0 }, + + new SysRole{TenantId=142307070918781, Id=142307070910556, Name="系统管理员", Code="sys_manager_role", Sort=100, DataScopeType=5, Remark="系统管理员", Status=0 }, + new SysRole{TenantId=142307070918781, Id=142307070910557, Name="普通用户", Code="common_role", Sort=101, DataScopeType=5, Remark="普通用户", Status=0 }, }; } } diff --git a/backend/Dilon.Core/SeedData/SysTenantSeedData.cs b/backend/Dilon.Core/SeedData/SysTenantSeedData.cs new file mode 100644 index 0000000000000000000000000000000000000000..d32e231419a80204072c1f936b8a0142211b4b71 --- /dev/null +++ b/backend/Dilon.Core/SeedData/SysTenantSeedData.cs @@ -0,0 +1,42 @@ +using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace Dilon.Core +{ + /// + /// 租户种子数据 + /// + public class SysTenantSeedData : IEntitySeedData + { + public IEnumerable HasData(DbContext dbContext, Type dbContextLocator) + { + return new List + { + new SysTenant + { + Id = 142307070918780, + Name = "平台开发", + Email = "515096995@163.com", + AdminName = "SuperAdmin", + Phone = "18020030720", + Host = "", + Connection = "", + CreatedTime = DateTime.Parse("2021-04-03 00:00:00"), + }, + new SysTenant + { + Id = 142307070918781, + Name = "公司1租户", + Email = "zuohuaijun@163.com", + AdminName = "Admin", + Phone = "18020030720", + Host = "", + Connection = "", + CreatedTime = DateTime.Parse("2021-04-03 00:00:00"), + } + }; + } + } +} diff --git a/backend/Dilon.Core/SeedData/SysTimerSeedData.cs b/backend/Dilon.Core/SeedData/SysTimerSeedData.cs index d251c3ac3f5b6f85cd0902d7afac17d77aecb96c..da1bdd4225012aeadc74556d2f65ce64cfe5cd21 100644 --- a/backend/Dilon.Core/SeedData/SysTimerSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysTimerSeedData.cs @@ -1,5 +1,6 @@ using Dilon.Core.Service; using Furion.DatabaseAccessor; +using Furion.TaskScheduler; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; @@ -21,7 +22,7 @@ namespace Dilon.Core { return new[] { - new SysTimer{Id=142307070910556, JobName="百度api", JobGroup="默认分组", BeginTime=DateTimeOffset.Parse("2021-03-21 00:00:00+08:00"), Interval=5, TriggerType=TriggerTypeEnum.Simple, RequestUrl="https://www.baidu.com", RequestType=RequestTypeEnum.Post, IsDeleted=false }, + new SysTimer{Id=142307070910556, JobName="百度api", Interval=5, TimerType=SpareTimeTypes.Interval, RequestUrl="https://www.baidu.com", RequestType=RequestTypeEnum.Post, IsDeleted=false }, }; } } diff --git a/backend/Dilon.Core/SeedData/SysEmpExtOrgPosSeedData.cs b/backend/Dilon.Core/SeedData/SysUserDataScopeSeedData.cs similarity index 31% rename from backend/Dilon.Core/SeedData/SysEmpExtOrgPosSeedData.cs rename to backend/Dilon.Core/SeedData/SysUserDataScopeSeedData.cs index ba6d02ccce204150d21b82e2a0e61133eafcdf0a..cbdf125b6730baece30437a8266f1626c426f9d8 100644 --- a/backend/Dilon.Core/SeedData/SysEmpExtOrgPosSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysUserDataScopeSeedData.cs @@ -3,25 +3,21 @@ using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; -namespace Dilon.Core +namespace Dilon.Core.SeedData { - class SysEmpExtOrgPosSeedData : IEntitySeedData + public class SysUserDataScopeSeedData : IEntitySeedData { /// - /// 扩展机构种子数据 + /// 种子数据 /// /// /// /// - public IEnumerable HasData(DbContext dbContext, Type dbContextLocator) + public IEnumerable HasData(DbContext dbContext, Type dbContextLocator) { return new[] { - new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910539, SysPosId = 142307070910547 }, - new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910540, SysPosId = 142307070910548 }, - new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910541, SysPosId = 142307070910549 }, - new SysEmpExtOrgPos { SysEmpId = 142307070910551, SysOrgId = 142307070910542, SysPosId = 142307070910550 }, - new SysEmpExtOrgPos { SysEmpId = 142307070910552, SysOrgId = 142307070910539, SysPosId = 142307070910547 } + new SysUserDataScope{SysUserId=142307070910554, SysOrgId=142307070910547 } }; } } diff --git a/backend/Dilon.Core/SeedData/SysUserRoleSeedData.cs b/backend/Dilon.Core/SeedData/SysUserRoleSeedData.cs new file mode 100644 index 0000000000000000000000000000000000000000..abb1d2de084069b465b8e0d9a06231a09317da98 --- /dev/null +++ b/backend/Dilon.Core/SeedData/SysUserRoleSeedData.cs @@ -0,0 +1,25 @@ +using Furion.DatabaseAccessor; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace Dilon.Core.SeedData +{ + public class SysUserRoleSeedData : IEntitySeedData + { + /// + /// 种子数据 + /// + /// + /// + /// + public IEnumerable HasData(DbContext dbContext, Type dbContextLocator) + { + return new[] + { + // 租户管理员默认管理员角色 + new SysUserRole{SysUserId=142307070910554, SysRoleId=142307070910556 } + }; + } + } +} diff --git a/backend/Dilon.Core/SeedData/SysUserSeedData.cs b/backend/Dilon.Core/SeedData/SysUserSeedData.cs index 0f90be64fa5914a4e3f46376e52868b0c6853f1b..479a0094eb42abd1113994ec191fd97e3539b609 100644 --- a/backend/Dilon.Core/SeedData/SysUserSeedData.cs +++ b/backend/Dilon.Core/SeedData/SysUserSeedData.cs @@ -20,9 +20,12 @@ namespace Dilon.Core { return new[] { - new SysUser{Id=142307070910551, Account="superAdmin", Name="superAdmin", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=1, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=1, IsDeleted=false }, - new SysUser{Id=142307070910552, Account="admin", Name="admin", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=1, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=2, IsDeleted=false }, - new SysUser{Id=142307070910553, Account="zuohuaijun", Name="zuohuaijun", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=2, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=1, IsDeleted=false } + new SysUser{TenantId=142307070918780, Id=142307070910551, Account="superAdmin", Name="superAdmin", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=AdminType.SuperAdmin, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=Gender.MALE, IsDeleted=false }, + new SysUser{TenantId=142307070918780, Id=142307070910552, Account="admin", Name="admin", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=AdminType.SuperAdmin, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=Gender.MALE, IsDeleted=false }, + new SysUser{TenantId=142307070918780, Id=142307070910553, Account="zuohuaijun", Name="zuohuaijun", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=AdminType.None, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=Gender.MALE, IsDeleted=false }, + + new SysUser{TenantId=142307070918781, Id=142307070910554, Account="zuohuaijun@163.com", Name="admin", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=AdminType.Admin, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=Gender.MALE, IsDeleted=false }, + new SysUser{TenantId=142307070918781, Id=142307070910556, Account="dilon@163.com", Name="dilon", Password="e10adc3949ba59abbe56e057f20f883e", AdminType=AdminType.None, Birthday=DateTimeOffset.Parse("1986-07-26 00:00:00"), Phone="18020030720", Sex=Gender.MALE, IsDeleted=false }, }; } } diff --git a/backend/Dilon.Core/Service/App/Dto/AppInput.cs b/backend/Dilon.Core/Service/App/Dto/AppInput.cs index 034a7633cd4bc7454ce291bf9530c54e56ed1f01..e3aac6f2898e8408604f5ae2f3b80c4b4f02bb46 100644 --- a/backend/Dilon.Core/Service/App/Dto/AppInput.cs +++ b/backend/Dilon.Core/Service/App/Dto/AppInput.cs @@ -26,7 +26,7 @@ namespace Dilon.Core.Service /// /// 状态(字典 0正常 1停用 2删除) /// - public int Status { get; set; } + public CommonStatus Status { get; set; } /// /// 排序 diff --git a/backend/Dilon.Core/Service/App/Dto/AppOutput.cs b/backend/Dilon.Core/Service/App/Dto/AppOutput.cs index 13506c5279d364ddb162309d910ac720b048733b..cfef3b78cad3c340295a47d06cbda0f2d0dc7aad 100644 --- a/backend/Dilon.Core/Service/App/Dto/AppOutput.cs +++ b/backend/Dilon.Core/Service/App/Dto/AppOutput.cs @@ -5,6 +5,11 @@ /// public class AppOutput { + /// + /// 应用Id + /// + public long Id { get; set; } + /// /// 名称 /// diff --git a/backend/Dilon.Core/Service/App/SysAppService.cs b/backend/Dilon.Core/Service/App/SysAppService.cs index 0d9e3dd18d0cda7559be525c315d2f566a4d39f0..5e0919db6e3b02180dd3ef62412737d9eb38474f 100644 --- a/backend/Dilon.Core/Service/App/SysAppService.cs +++ b/backend/Dilon.Core/Service/App/SysAppService.cs @@ -1,4 +1,4 @@ -using Furion.DatabaseAccessor; +using Furion.DatabaseAccessor; using Furion.DatabaseAccessor.Extensions; using Furion.DependencyInjection; using Furion.DynamicApiController; @@ -97,7 +97,7 @@ namespace Dilon.Core.Service } var app = input.Adapt(); - await app.InsertNowAsync(); + await app.InsertAsync(); } /// @@ -114,7 +114,7 @@ namespace Dilon.Core.Service if (hasMenu) throw Oops.Oh(ErrorCode.D5002); - await app.DeleteNowAsync(); + await app.DeleteAsync(); } /// @@ -131,13 +131,13 @@ namespace Dilon.Core.Service if (input.Active == YesOrNot.Y.ToString()) { - isExist = await _sysAppRep.DetachedEntities.AnyAsync(u => u.Active == input.Active); + isExist = await _sysAppRep.DetachedEntities.AnyAsync(u => u.Active == input.Active && u.Id != input.Id); if (isExist) throw Oops.Oh(ErrorCode.D5001); } var app = input.Adapt(); - await app.UpdateExcludeNowAsync(new[] { nameof(SysApp.Status) }, true); + await app.UpdateExcludeAsync(new[] { nameof(SysApp.Status) }, true); } /// diff --git a/backend/Dilon.Core/Service/Auth/AuthService.cs b/backend/Dilon.Core/Service/Auth/AuthService.cs index f86ef8fd54f15fb1d4a12497a847396d5a8f5e08..a7f0d3e7c461ca4fb00e86c0ae8ccb17661d5b03 100644 --- a/backend/Dilon.Core/Service/Auth/AuthService.cs +++ b/backend/Dilon.Core/Service/Auth/AuthService.cs @@ -24,13 +24,14 @@ namespace Dilon.Core.Service [ApiDescriptionSettings(Name = "Auth", Order = 160)] public class AuthService : IAuthService, IDynamicApiController, ITransient { - private readonly IRepository _sysUserRep; // 用户表仓储 private readonly IHttpContextAccessor _httpContextAccessor; + + private readonly IRepository _sysUserRep; // 用户表仓储 private readonly IUserManager _userManager; // 用户管理 - private readonly ISysUserService _sysUserService; // 系统用户服务 - private readonly ISysEmpService _sysEmpService; // 系统员工服务 - private readonly ISysRoleService _sysRoleService; // 系统角色服务 + private readonly ISysUserService _sysUserService; // 系统用户服务 + private readonly ISysEmpService _sysEmpService; // 系统员工服务 + private readonly ISysRoleService _sysRoleService; // 系统角色服务 private readonly ISysMenuService _sysMenuService; // 系统菜单服务 private readonly ISysAppService _sysAppService; // 系统应用服务 private readonly IClickWordCaptcha _captchaHandle;// 验证码服务 @@ -67,17 +68,17 @@ namespace Dilon.Core.Service /// [HttpPost("/login")] [AllowAnonymous] - public async Task LoginAsync([Required] LoginInput input) + public string LoginAsync([Required] LoginInput input) { // 获取加密后的密码 var encryptPasswod = MD5Encryption.Encrypt(input.Password); - // 判断用户名和密码是否正确 - var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPasswod)); + // 判断用户名和密码是否正确 忽略全局过滤器 + var user = _sysUserRep.Where(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPasswod), null, true).FirstOrDefault(); _ = user ?? throw Oops.Oh(ErrorCode.D1000); // 验证账号是否被冻结 - if (user.Status == (int)CommonStatus.DISABLE) + if (user.Status == CommonStatus.DISABLE) throw Oops.Oh(ErrorCode.D1017); // 生成Token令牌 @@ -85,6 +86,7 @@ namespace Dilon.Core.Service var accessToken = JWTEncryption.Encrypt(new Dictionary { { ClaimConst.CLAINM_USERID, user.Id }, + { ClaimConst.TENANT_ID, user.TenantId }, { ClaimConst.CLAINM_ACCOUNT, user.Account }, { ClaimConst.CLAINM_NAME, user.Name }, { ClaimConst.CLAINM_SUPERADMIN, user.AdminType }, @@ -116,7 +118,8 @@ namespace Dilon.Core.Service var loginOutput = user.Adapt(); loginOutput.LastLoginTime = user.LastLoginTime = DateTimeOffset.Now; - loginOutput.LastLoginIp = user.LastLoginIp = httpContext.GetRemoteIpAddressToIPv4(); + var ip = httpContext.Request.Headers["X-Real-IP"].FirstOrDefault(); + loginOutput.LastLoginIp = user.LastLoginIp = string.IsNullOrEmpty(user.LastLoginIp) ? httpContext.GetRemoteIpAddressToIPv4() : ip; //var ipInfo = IpTool.Search(loginOutput.LastLoginIp); //loginOutput.LastLoginAddress = ipInfo.Country + ipInfo.Province + ipInfo.City + "[" + ipInfo.NetworkOperator + "][" + ipInfo.Latitude + ipInfo.Longitude + "]"; @@ -143,20 +146,21 @@ namespace Dilon.Core.Service // 菜单信息 if (loginOutput.Apps.Count > 0) { - var defaultActiveAppCode = loginOutput.Apps.FirstOrDefault(u => u.Active == YesOrNot.Y.ToString()).Code; // loginOutput.Apps[0].Code; + var activeApp = loginOutput.Apps.FirstOrDefault(u => u.Active == YesOrNot.Y.ToString()); + var defaultActiveAppCode = activeApp != null ? activeApp.Code : loginOutput.Apps.FirstOrDefault().Code; loginOutput.Menus = await _sysMenuService.GetLoginMenusAntDesign(userId, defaultActiveAppCode); } - // 增加登录日志 + // 登录日志入库 await new SysLogVis { - Name = "登录", - Success = YesOrNot.Y.ToString(), + Name = loginOutput.Name, + Success = YesOrNot.Y, Message = "登录成功", Ip = loginOutput.LastLoginIp, Browser = loginOutput.LastLoginBrowser, Os = loginOutput.LastLoginOs, - VisType = 1, + VisType = LoginType.LOGIN, VisTime = loginOutput.LastLoginTime, Account = loginOutput.Account }.InsertAsync(); @@ -171,16 +175,19 @@ namespace Dilon.Core.Service [HttpGet("/logout")] public async Task LogoutAsync() { + var user = _userManager.User; _httpContextAccessor.SignoutToSwagger(); //_httpContextAccessor.HttpContext.Response.Headers["access-token"] = "invalid token"; // 增加退出日志 await new SysLogVis { - Name = "退出", - Success = YesOrNot.Y.ToString(), + Name = user.Name, + Success = YesOrNot.Y, Message = "退出成功", - VisType = 2 + VisType = LoginType.LOGOUT, + VisTime = DateTimeOffset.Now, + Account = user.Account }.InsertAsync(); await Task.CompletedTask; @@ -192,7 +199,7 @@ namespace Dilon.Core.Service /// [HttpGet("/getCaptchaOpen")] [AllowAnonymous] - public async Task GetCaptchaOpen() + public async Task GetCaptchaOpen() { return await _sysConfigService.GetCaptchaOpenFlag(); } diff --git a/backend/Dilon.Core/Service/Auth/Dto/RegistInput.cs b/backend/Dilon.Core/Service/Auth/Dto/RegistInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..afd556e6fcc524f9f1306fdc854cdf0c4da925a0 --- /dev/null +++ b/backend/Dilon.Core/Service/Auth/Dto/RegistInput.cs @@ -0,0 +1,33 @@ +using Furion.DependencyInjection; +using System.ComponentModel.DataAnnotations; + +namespace Dilon.Core.Service.Auth.Dto +{ + /// + /// 注册输入参数 + /// + [SkipScan] + public class RegistInput + { + /// + /// 用户名 + /// + /// superAdmin + [Required(ErrorMessage = "用户名不能为空"), MinLength(3, ErrorMessage = "用户名不能少于3位字符")] + public string Email { get; set; } + + /// + /// 公司名 + /// + /// superAdmin + [Required(ErrorMessage = "公司不能为空"), MinLength(3, ErrorMessage = "公司不能少于3位字符")] + public string CompanyName { get; set; } + + /// + /// 密码 + /// + /// 123456 + [Required(ErrorMessage = "密码不能为空"), MinLength(5, ErrorMessage = "密码不能少于5位字符")] + public string Password { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/Auth/IAuthService.cs b/backend/Dilon.Core/Service/Auth/IAuthService.cs index 1994d931ce8b1d56f204dd053215c50930fc1d74..07b15dca39985bff4a8a549b13ab189a64110ccd 100644 --- a/backend/Dilon.Core/Service/Auth/IAuthService.cs +++ b/backend/Dilon.Core/Service/Auth/IAuthService.cs @@ -6,9 +6,9 @@ namespace Dilon.Core.Service public interface IAuthService { Task GetCaptcha(); - Task GetCaptchaOpen(); + Task GetCaptchaOpen(); Task GetLoginUserAsync(); - Task LoginAsync([Required] LoginInput input); + string LoginAsync([Required] LoginInput input); Task LogoutAsync(); Task VerificationCode(ClickWordCaptchaInput input); } diff --git a/backend/Dilon.Core/Service/Cache/ISysCacheService.cs b/backend/Dilon.Core/Service/Cache/ISysCacheService.cs index 4c1ef41d13b18c439f0372d373f39da744c608ef..a514d2b887d32c84d746deaf345795f81f127a53 100644 --- a/backend/Dilon.Core/Service/Cache/ISysCacheService.cs +++ b/backend/Dilon.Core/Service/Cache/ISysCacheService.cs @@ -6,6 +6,7 @@ namespace Dilon.Core.Service public interface ISysCacheService { Task DelAsync(string key); + Task DelByPatternAsync(string key); List GetAllCacheKeys(); Task> GetDataScope(long userId); Task> GetMenu(long userId, string appCode); diff --git a/backend/Dilon.Core/Service/Cache/SysCacheService.cs b/backend/Dilon.Core/Service/Cache/SysCacheService.cs index 6d054677b36193837d46c2f9add274735762a386..8e06d19db3267b2739779f90ba483520e08d7ad9 100644 --- a/backend/Dilon.Core/Service/Cache/SysCacheService.cs +++ b/backend/Dilon.Core/Service/Cache/SysCacheService.cs @@ -32,7 +32,7 @@ namespace Dilon.Core.Service /// public async Task> GetDataScope(long userId) { - var cacheKey = $"{userId}" + CommonConst.CACHE_KEY_DATASCOPE; + var cacheKey = CommonConst.CACHE_KEY_DATASCOPE + $"{userId}"; return await _cache.GetAsync>(cacheKey); } @@ -45,7 +45,7 @@ namespace Dilon.Core.Service [NonAction] public async Task SetDataScope(long userId, List dataScopes) { - var cacheKey = $"{userId}" + CommonConst.CACHE_KEY_DATASCOPE; + var cacheKey = CommonConst.CACHE_KEY_DATASCOPE + $"{userId}"; await _cache.SetAsync(cacheKey, dataScopes); } @@ -57,7 +57,7 @@ namespace Dilon.Core.Service /// public async Task> GetMenu(long userId, string appCode) { - var cacheKey = $"{userId}-{appCode}" + CommonConst.CACHE_KEY_MENU; + var cacheKey = CommonConst.CACHE_KEY_MENU + $"{userId}-{appCode}"; return await _cache.GetAsync>(cacheKey); } @@ -71,7 +71,7 @@ namespace Dilon.Core.Service [NonAction] public async Task SetMenu(long userId, string appCode, List menus) { - var cacheKey = $"{userId}-{appCode}" + CommonConst.CACHE_KEY_MENU; + var cacheKey = CommonConst.CACHE_KEY_MENU + $"{userId}-{appCode}"; await _cache.SetAsync(cacheKey, menus); } @@ -82,7 +82,7 @@ namespace Dilon.Core.Service /// public async Task> GetPermission(long userId) { - var cacheKey = $"{userId}" + CommonConst.CACHE_KEY_PERMISSION; + var cacheKey = CommonConst.CACHE_KEY_PERMISSION + $"{userId}"; return await _cache.GetAsync>(cacheKey); } @@ -95,7 +95,7 @@ namespace Dilon.Core.Service [NonAction] public async Task SetPermission(long userId, List permissions) { - var cacheKey = $"{userId}" + CommonConst.CACHE_KEY_PERMISSION; + var cacheKey = CommonConst.CACHE_KEY_PERMISSION + $"{userId}"; await _cache.SetAsync(cacheKey, permissions); } @@ -105,11 +105,9 @@ namespace Dilon.Core.Service /// public List GetAllCacheKeys() { - const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; - var entries = _cache.GetType().GetField("_entries", flags).GetValue(_cache); - if (entries.GetType().GetProperty("Keys").GetValue(entries) is not ICollection cacheItems) return new List(); - return cacheItems.Where(u => !u.ToString().StartsWith("mini-profiler")) - .Select(u => u.ToString()).ToList(); + var cacheItems = _cache.GetAllKeys(); + if (cacheItems == null) return new List(); + return cacheItems.Where(u => !u.ToString().StartsWith("mini-profiler")).Select(u => u).ToList(); } /// @@ -123,6 +121,17 @@ namespace Dilon.Core.Service return Task.FromResult(true); } + /// + /// 删除某特征关键字缓存 + /// + /// + /// + public Task DelByPatternAsync(string key) + { + _cache.DelByPatternAsync(key); + return Task.FromResult(true); + } + /// /// 设置缓存 /// diff --git a/backend/Dilon.Core/Service/CodeGen/CodeGenConfigService.cs b/backend/Dilon.Core/Service/CodeGen/CodeGenConfigService.cs new file mode 100644 index 0000000000000000000000000000000000000000..94339539395ca54c63984a73a302233f22d59338 --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/CodeGenConfigService.cs @@ -0,0 +1,207 @@ +using Furion.DatabaseAccessor; +using Furion.DatabaseAccessor.Extensions; +using Furion.DependencyInjection; +using Furion.DynamicApiController; +using Mapster; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + /// + /// 代码生成详细配置服务 + /// + [ApiDescriptionSettings(Name = "CodeGenConfig", Order = 100)] + public class CodeGenConfigService : ICodeGenConfigService, IDynamicApiController, ITransient + { + private readonly IRepository _sysCodeGenConfigRep; // 代码生成详细配置仓储 + + public CodeGenConfigService(IRepository sysCodeGenConfigRep) + { + _sysCodeGenConfigRep = sysCodeGenConfigRep; + } + + /// + /// 代码生成详细配置列表 + /// + /// + /// + + [HttpGet("/sysCodeGenerateConfig/list")] + public async Task> List([FromQuery] CodeGenConfig input) + { + return await _sysCodeGenConfigRep.DetachedEntities.Where(u => u.CodeGenId == input.CodeGenId && u.WhetherCommon != YesOrNot.Y.ToString()) + .Select(u => u.Adapt()).ToListAsync(); + } + + /// + /// 增加 + /// + /// + /// + [NonAction] + public async Task Add(CodeGenConfig input) + { + var codeGenConfig = input.Adapt(); + await codeGenConfig.InsertAsync(); + } + + /// + /// 删除 + /// + /// + /// + [NonAction] + public async Task Delete(long codeGenId) + { + var codeGenConfigList = await _sysCodeGenConfigRep.Where(u => u.CodeGenId == codeGenId).ToListAsync(); + codeGenConfigList.ForEach(u => + { + u.Delete(); + }); + } + + /// + /// 更新 + /// + /// + /// + [HttpPost("/sysCodeGenerateConfig/edit")] + public async Task Update(List inputList) + { + if (inputList == null || inputList.Count < 1) return; + inputList.ForEach(u => + { + var codeGenConfig = u.Adapt(); + codeGenConfig.Update(true); + }); + await Task.CompletedTask; + } + + /// + /// 详情 + /// + /// + /// + [HttpGet("/sysCodeGenerateConfig/detail")] + public async Task Detail(CodeGenConfig input) + { + return await _sysCodeGenConfigRep.FirstOrDefaultAsync(u => u.Id == input.Id); + } + + /// + /// 批量增加 + /// + /// + /// + [NonAction] + public void AddList(List tableColumnOuputList, SysCodeGen codeGenerate) + { + if (tableColumnOuputList == null) return; + + foreach (var tableColumn in tableColumnOuputList) + { + var codeGenConfig = new SysCodeGenConfig(); + + var YesOrNo = YesOrNot.Y.ToString(); + if (Convert.ToBoolean(tableColumn.ColumnKey)) + { + YesOrNo = YesOrNot.N.ToString(); + } + + if (IsCommonColumn(tableColumn.ColumnName)) + { + codeGenConfig.WhetherCommon = YesOrNot.Y.ToString(); + YesOrNo = YesOrNot.N.ToString(); + } + else + { + codeGenConfig.WhetherCommon = YesOrNot.N.ToString(); + } + + codeGenConfig.CodeGenId = codeGenerate.Id; + codeGenConfig.ColumnName = tableColumn.ColumnName; + codeGenConfig.ColumnComment = tableColumn.ColumnComment; + codeGenConfig.NetType = ConvertDataType(tableColumn.DataType); + codeGenConfig.WhetherRetract = YesOrNot.N.ToString(); + + codeGenConfig.WhetherRequired = YesOrNot.N.ToString(); + codeGenConfig.QueryWhether = YesOrNo; + codeGenConfig.WhetherAddUpdate = YesOrNo; + codeGenConfig.WhetherTable = YesOrNo; + + codeGenConfig.ColumnKey = tableColumn.ColumnKey; + + codeGenConfig.DataType = tableColumn.DataType; + codeGenConfig.EffectType = DataTypeToEff(codeGenConfig.NetType); + codeGenConfig.QueryType = "=="; // QueryTypeEnum.eq.ToString(); + + codeGenConfig.InsertAsync(); + } + } + + /// + /// 数据类型转显示类型 + /// + /// + /// + private static string DataTypeToEff(string dataType) + { + if (string.IsNullOrEmpty(dataType)) return ""; + return dataType switch + { + "string" => "input", + "int" => "inputnumber", + "long" => "input", + "float" => "input", + "double" => "input", + "decimal" => "input", + "bool" => "switch", + "Guid" => "input", + "DateTime" => "datepicker", + "DateTimeOffset" => "datepicker", + _ => "input", + }; + } + + // 转换.NET数据类型 + [NonAction] + public string ConvertDataType(string dataType) + { + if (string.IsNullOrEmpty(dataType)) return ""; + if (dataType.StartsWith("System.Nullable")) + dataType = new Regex(@"(?i)(?<=\[)(.*)(?=\])").Match(dataType).Value; // 中括号[]里面值 + + switch (dataType) + { + case "System.Guid": return "Guid"; + case "System.String": return "string"; + case "System.Int32": return "int"; + case "System.Int64": return "long"; + case "System.Single": return "float"; + case "System.Double": return "double"; + case "System.Decimal": return "decimal"; + case "System.Boolean": return "bool"; + case "System.DateTime": return "DateTime"; + case "System.DateTimeOffset": return "DateTimeOffset"; + case "System.Byte": return "byte"; + case "System.Byte[]": return "byte[]"; + default: + break; + } + return dataType; + } + + // 是否通用字段 + private static bool IsCommonColumn(string columnName) + { + var columnList = new List() { "CreatedTime", "UpdatedTime", "CreatedUserId", "CreatedUserName", "UpdatedUserId", "UpdatedUserName", "IsDeleted" }; + return columnList.Contains(columnName); + } + } +} diff --git a/backend/Dilon.Core/Service/CodeGen/CodeGenService.cs b/backend/Dilon.Core/Service/CodeGen/CodeGenService.cs index 29f909a7f9510410d7d4befa82e6856e991a0361..82b59454539c7472959c5352cc8b07d5ffc13288 100644 --- a/backend/Dilon.Core/Service/CodeGen/CodeGenService.cs +++ b/backend/Dilon.Core/Service/CodeGen/CodeGenService.cs @@ -1,6 +1,18 @@ -using Furion.DependencyInjection; +using Furion; +using Furion.DatabaseAccessor; +using Furion.DatabaseAccessor.Extensions; +using Furion.DependencyInjection; using Furion.DynamicApiController; +using Furion.FriendlyException; +using Furion.ViewEngine; +using Mapster; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace Dilon.Core.Service.CodeGen { @@ -8,11 +20,338 @@ namespace Dilon.Core.Service.CodeGen /// 代码生成器服务 /// [ApiDescriptionSettings(Name = "CodeGen", Order = 100)] - public class CodeGenService : IDynamicApiController, ITransient + public class CodeGenService : ICodeGenService, IDynamicApiController, ITransient { - public CodeGenService() + private readonly IRepository _sysCodeGenRep; // 代码生成器仓储 + private readonly ICodeGenConfigService _codeGenConfigService; + private readonly IViewEngine _viewEngine; + + private readonly IRepository _sysMenuRep; // 菜单表仓储 + + public CodeGenService(IRepository sysCodeGenRep, + ICodeGenConfigService codeGenConfigService, + IViewEngine viewEngine, + IRepository sysMenuRep) + { + _sysCodeGenRep = sysCodeGenRep; + _codeGenConfigService = codeGenConfigService; + _viewEngine = viewEngine; + _sysMenuRep = sysMenuRep; + } + + /// + /// 分页查询 + /// + /// + /// + [HttpGet("/codeGenerate/page")] + public async Task QueryCodeGenPageList([FromQuery] CodeGenInput input) + { + var tableName = !string.IsNullOrEmpty(input.TableName?.Trim()); + var codeGens = await _sysCodeGenRep.DetachedEntities + .Where((tableName, u => EF.Functions.Like(u.TableName, $"%{input.TableName.Trim()}%"))) + .ToPagedListAsync(input.PageNo, input.PageSize); + return XnPageResult.PageResult(codeGens); + } + + /// + /// 增加 + /// + /// + /// + [HttpPost("/codeGenerate/add")] + public async Task AddCodeGen(AddCodeGenInput input) + { + var isExist = await _sysCodeGenRep.DetachedEntities.AnyAsync(u => u.TableName == input.TableName); + if (isExist) + throw Oops.Oh(ErrorCode.D1400); + + var codeGen = input.Adapt(); + var newCodeGen = await codeGen.InsertNowAsync(); + + // 加入配置表中 + _codeGenConfigService.AddList(GetColumnList(input), newCodeGen.Entity); + } + + /// + /// 删除 + /// + /// + /// + [HttpPost("/codeGenerate/delete")] + public async Task DeleteCodeGen(List inputs) + { + if (inputs == null || inputs.Count < 1) return; + + var codeGenConfigTaskList = new List(); + inputs.ForEach(u => + { + _sysCodeGenRep.Delete(u.Id); + + // 删除配置表中 + codeGenConfigTaskList.Add(_codeGenConfigService.Delete(u.Id)); + }); + await Task.WhenAll(codeGenConfigTaskList); + } + + /// + /// 更新 + /// + /// + /// + [HttpPost("/codeGenerate/edit")] + public async Task UpdateCodeGen(UpdateCodeGenInput input) + { + var isExist = await _sysCodeGenRep.DetachedEntities.AnyAsync(u => u.TableName == input.TableName && u.Id != input.Id); + if (isExist) + throw Oops.Oh(ErrorCode.D1400); + + var codeGen = input.Adapt(); + await codeGen.UpdateAsync(); + } + + /// + /// 详情 + /// + /// + /// + [HttpGet("/codeGenerate/detail")] + public async Task GetCodeGen([FromQuery] QueryCodeGenInput input) + { + return await _sysCodeGenRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id); + } + + /// + /// 获取数据库表(实体)集合 + /// + /// + + [HttpGet("/codeGenerate/InformationList")] + public List GetTableList() + { + return Db.GetDbContext().Model.GetEntityTypes().Select(u => new TableOutput + { + TableName = u.GetDefaultTableName(), + TableComment = u.GetComment() + }).ToList(); + } + + /// + /// 获取数据表列(实体属性)集合 + /// + /// + [NonAction] + public List GetColumnList([FromQuery] AddCodeGenInput input) + { + // 获取实体类型属性 + var entityType = Db.GetDbContext().Model.GetEntityTypes().FirstOrDefault(u => u.ClrType.Name == input.TableName); + if (entityType == null) return null; + + // 获取原始类型属性 + var type = entityType.ClrType; + if (type == null) return null; + + // 按原始类型的顺序获取所有实体类型属性(不包含导航属性,会返回null) + return type.GetProperties() + .Select(propertyInfo => entityType.FindProperty(propertyInfo.Name)) + .Where(p => p != null) + .Select(p => new TableColumnOuput + { + ColumnName = p.Name, + ColumnKey = p.IsKey().ToString(), + DataType = p.PropertyInfo.PropertyType.ToString(), + ColumnComment = p.GetComment() + }).ToList(); + } + + /// + /// 代码生成_本地项目 + /// + /// + [HttpPost("/codeGenerate/runLocal")] + public async Task RunLocal(SysCodeGen input) + { + var templatePathList = GetTemplatePathList(); + var targetPathList = GetTargetPathList(input); + for (var i = 0; i < templatePathList.Count; i++) + { + var tContent = File.ReadAllText(templatePathList[i]); + + var tableFieldList = await _codeGenConfigService.List(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合 + if (i >= 4) // 适应前端首字母小写 + { + tableFieldList.ForEach(u => + { + u.ColumnName = u.ColumnName.Substring(0, 1).ToLower() + u.ColumnName[1..]; + }); + } + var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesOrNot.Y.ToString()).ToList(); // 前端查询集合 + var tResult = _viewEngine.RunCompileFromCached(tContent, new + { + input.AuthorName, + input.BusName, + input.NameSpace, + ClassName = input.TableName, + QueryWhetherList = queryWhetherList, + TableField = tableFieldList + }); + + var dirPath = new DirectoryInfo(targetPathList[i]).Parent.FullName; + if (!Directory.Exists(dirPath)) + Directory.CreateDirectory(dirPath); + File.WriteAllText(targetPathList[i], tResult, Encoding.UTF8); + } + + await AddMenu(input.TableName, input.BusName); + } + + private async Task AddMenu(string className, string busName) + { + // 先删除该表已生成的菜单列表 + var menus = await _sysMenuRep.DetachedEntities.Where(u => u.Code.StartsWith("dilon_" + className.ToLower())).ToListAsync(); + menus.ForEach(u => + { + u.Delete(); + }); + + // 目录 + var menuType0 = new SysMenu + { + Pid = 0, + Pids = "[0],", + Name = busName + "管理", + Code = "dilon_" + className.ToLower(), + Type = 1, + Icon = "robot", + Router = "/" + className.ToLower(), + Component = "PageView", + Application = "busapp" + }; + var pid0 = _sysMenuRep.InsertNowAsync(menuType0).GetAwaiter().GetResult().Entity.Id; + + // 菜单 + var menuType1 = new SysMenu + { + Pid = pid0, + Pids = "[0],[" + pid0 + "],", + Name = busName + "管理", + Code = "dilon_" + className.ToLower() + "_mgr", + Type = 1, + Router = "/" + className.ToLower(), + Component = "main/" + className + "/index", + Application = "busapp", + OpenType = 1 + }; + var pid1 = _sysMenuRep.InsertNowAsync(menuType1).GetAwaiter().GetResult().Entity.Id; + + // 按钮-page + var menuType2 = new SysMenu + { + Pid = pid1, + Pids = "[0],[" + pid0 + "],[" + pid1 + "],", + Name = busName + "查询", + Code = "dilon_" + className.ToLower() + "_mgr_page", + Type = 2, + Permission = className + ":page", + Application = "busapp", + }.InsertAsync(); + + // 按钮-detail + var menuType2_1 = new SysMenu + { + Pid = pid1, + Pids = "[0],[" + pid0 + "],[" + pid1 + "],", + Name = busName + "详情", + Code = "dilon_" + className.ToLower() + "_mgr_detail", + Type = 2, + Permission = className + ":detail", + Application = "busapp", + }.InsertAsync(); + + // 按钮-add + var menuType2_2 = new SysMenu + { + Pid = pid1, + Pids = "[0],[" + pid0 + "],[" + pid1 + "],", + Name = busName + "增加", + Code = "dilon_" + className.ToLower() + "_mgr_add", + Type = 2, + Permission = className + ":add", + Application = "busapp", + }.InsertAsync(); + + // 按钮-delete + var menuType2_3 = new SysMenu + { + Pid = pid1, + Pids = "[0],[" + pid0 + "],[" + pid1 + "],", + Name = busName + "删除", + Code = "dilon_" + className.ToLower() + "_mgr_delete", + Type = 2, + Permission = className + ":delete", + Application = "busapp", + }.InsertAsync(); + + // 按钮-edit + var menuType2_4 = new SysMenu + { + Pid = pid1, + Pids = "[0],[" + pid0 + "],[" + pid1 + "],", + Name = busName + "编辑", + Code = "dilon_" + className.ToLower() + "_mgr_edit", + Type = 2, + Permission = className + ":edit", + Application = "busapp", + }.InsertAsync(); + } + + /// + /// 获取模板文件路径集合 + /// + /// + private List GetTemplatePathList() + { + var templatePath = App.WebHostEnvironment.WebRootPath + @"\Template\"; + return new List() { + templatePath + "Service.cs.vm", + templatePath + "IService.cs.vm", + templatePath + "Input.cs.vm", + templatePath + "Output.cs.vm", + templatePath + "index.vue.vm", + templatePath + "addForm.vue.vm", + templatePath + "editForm.vue.vm", + templatePath + "manage.js.vm", + }; + } + + /// + /// 设置生成文件路径 + /// + /// + /// + private List GetTargetPathList(SysCodeGen input) { + var backendPath = new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.FullName + @"\Dilon.Application\Service\" + input.TableName + @"\"; + var servicePath = backendPath + input.TableName + "Service.cs"; + var iservicePath = backendPath + "I" + input.TableName + "Service.cs"; + var inputPath = backendPath + @"Dto\" + input.TableName + "Input.cs"; + var outputPath = backendPath + @"Dto\" + input.TableName + "Output.cs"; + var frontendPath = new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName + @"\frontend\src\views\main\"; + var indexPath = frontendPath + input.TableName + @"\index.vue"; + var addFormPath = frontendPath + input.TableName + @"\addForm.vue"; + var editFormPath = frontendPath + input.TableName + @"\editForm.vue"; + var apiJsPath = new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName + @"\frontend\src\api\modular\main\" + input.TableName + "Manage.js"; + return new List() { + servicePath, + iservicePath, + inputPath, + outputPath, + indexPath, + addFormPath, + editFormPath, + apiJsPath + }; } } } diff --git a/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenConfig.cs b/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..be4eeac72cc5176507575e07f88905826299cf17 --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenConfig.cs @@ -0,0 +1,88 @@ +namespace Dilon.Core.Service +{ + /// + /// 代码生成详细配置参数 + /// + public class CodeGenConfig + { + /// + /// 主键 + /// + public long Id { get; set; } + + /// + /// 代码生成主表ID + /// + public long CodeGenId { get; set; } + + /// + /// 数据库字段名 + /// + public string ColumnName { get; set; } + + /// + /// 字段描述 + /// + public string ColumnComment { get; set; } + + /// + /// .NET类型 + /// + public string NetType { get; set; } + + /// + /// 作用类型(字典) + /// + public string EffectType { get; set; } + + /// + /// 字典code + /// + public string DictTypeCode { get; set; } + + /// + /// 列表是否缩进(字典) + /// + public string WhetherRetract { get; set; } + + /// + /// 是否必填(字典) + /// + public string WhetherRequired { get; set; } + + /// + /// 是否是查询条件 + /// + public string QueryWhether { get; set; } + + /// + /// 查询方式 + /// + public string QueryType { get; set; } + + /// + /// 列表显示 + /// + public string WhetherTable { get; set; } + + /// + /// 增改 + /// + public string WhetherAddUpdate { get; set; } + + /// + /// 主外键 + /// + public string ColumnKey { get; set; } + + /// + /// 数据库中类型(物理类型) + /// + public string DataType { get; set; } + + /// + /// 是否是通用字段 + /// + public string WhetherCommon { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenInput.cs b/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenInput.cs index 8df7999774560728fe987c4581be786a933bc5b6..ff1d0a3d35faa980db4ad4f003fb4b4d7724d8a7 100644 --- a/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenInput.cs +++ b/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenInput.cs @@ -1,48 +1,124 @@ -namespace Dilon.Core.Service.CodeGen.Dto +using System.ComponentModel.DataAnnotations; + +namespace Dilon.Core.Service { /// /// 代码生成参数类 /// - public class CodeGenInput + public class CodeGenInput : XnInputBase { /// /// 作者姓名 /// - public string AuthorName { get; set; } + public virtual string AuthorName { get; set; } /// /// 类名 /// - public string ClassName { get; set; } + public virtual string ClassName { get; set; } /// /// 是否移除表前缀 /// - public string TablePrefix { get; set; } + public virtual string TablePrefix { get; set; } /// /// 生成方式 /// - public string GenerateType { get; set; } + public virtual string GenerateType { get; set; } /// /// 数据库表名 /// - public string TableName { get; set; } + public virtual string TableName { get; set; } /// - /// 包名 + /// 命名空间 /// - public string PackageName { get; set; } + public virtual string NameSpace { get; set; } /// /// 业务名(业务代码包名称) /// - public string BusName { get; set; } + public virtual string BusName { get; set; } /// /// 功能名(数据库表名称) /// - public string TableComment { get; set; } + public virtual string TableComment { get; set; } + } + + public class AddCodeGenInput : CodeGenInput + { + /// + /// 数据库表名 + /// + [Required(ErrorMessage = "数据库表名不能为空")] + public override string TableName { get; set; } + + /// + /// 业务名(业务代码包名称) + /// + [Required(ErrorMessage = "业务名不能为空")] + public override string BusName { get; set; } + + /// + /// 命名空间 + /// + [Required(ErrorMessage = "命名空间不能为空")] + public override string NameSpace { get; set; } + + /// + /// 作者姓名 + /// + [Required(ErrorMessage = "作者姓名不能为空")] + public override string AuthorName { get; set; } + + ///// + ///// 类名 + ///// + //[Required(ErrorMessage = "类名不能为空")] + //public override string ClassName { get; set; } + + ///// + ///// 是否移除表前缀 + ///// + //[Required(ErrorMessage = "是否移除表前缀不能为空")] + //public override string TablePrefix { get; set; } + + /// + /// 生成方式 + /// + [Required(ErrorMessage = "生成方式不能为空")] + public override string GenerateType { get; set; } + + ///// + ///// 功能名(数据库表名称) + ///// + //[Required(ErrorMessage = "数据库表名不能为空")] + //public override string TableComment { get; set; } + } + + public class DeleteCodeGenInput + { + /// + /// 代码生成器Id + /// + [Required(ErrorMessage = "代码生成器Id不能为空")] + public long Id { get; set; } + } + + public class UpdateCodeGenInput : CodeGenInput + { + /// + /// 代码生成器Id + /// + [Required(ErrorMessage = "代码生成器Id不能为空")] + public long Id { get; set; } + } + + public class QueryCodeGenInput : DeleteCodeGenInput + { + } } diff --git a/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenOutput.cs b/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenOutput.cs new file mode 100644 index 0000000000000000000000000000000000000000..57474403f1f4830671d4706ce9c9d2e187ec1da8 --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/Dto/CodeGenOutput.cs @@ -0,0 +1,53 @@ +namespace Dilon.Core.Service +{ + /// + /// 代码生成参数类 + /// + public class CodeGenOutput + { + /// + /// 代码生成器Id + /// + public long Id { get; set; } + + /// + /// 作者姓名 + /// + public string AuthorName { get; set; } + + /// + /// 类名 + /// + public string ClassName { get; set; } + + /// + /// 是否移除表前缀 + /// + public string TablePrefix { get; set; } + + /// + /// 生成方式 + /// + public string GenerateType { get; set; } + + /// + /// 数据库表名 + /// + public string TableName { get; set; } + + /// + /// 包名 + /// + public string PackageName { get; set; } + + /// + /// 业务名(业务代码包名称) + /// + public string BusName { get; set; } + + /// + /// 功能名(数据库表名称) + /// + public string TableComment { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/CodeGen/Dto/TableColumnOuput.cs b/backend/Dilon.Core/Service/CodeGen/Dto/TableColumnOuput.cs new file mode 100644 index 0000000000000000000000000000000000000000..18415f95faeb1f331b983cca0730b6b3916fab38 --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/Dto/TableColumnOuput.cs @@ -0,0 +1,28 @@ +namespace Dilon.Core.Service +{ + /// + /// 数据库表列 + /// + public class TableColumnOuput + { + /// + /// 字段名 + /// + public string ColumnName { get; set; } + + /// + /// 数据库中类型 + /// + public string DataType { get; set; } + + /// + /// 字段描述 + /// + public string ColumnComment { get; set; } + + /// + /// 主外键 + /// + public string ColumnKey { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/CodeGen/Dto/TableOutput.cs b/backend/Dilon.Core/Service/CodeGen/Dto/TableOutput.cs new file mode 100644 index 0000000000000000000000000000000000000000..a32f3f2345538e93f574848e4f078fcce9588a41 --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/Dto/TableOutput.cs @@ -0,0 +1,28 @@ +namespace Dilon.Core.Service +{ + /// + /// 数据库表列表参数 + /// + public class TableOutput + { + /// + /// 表名(字母形式的) + /// + public string TableName { get; set; } + + /// + /// 创建时间 + /// + public string CreateTime { get; set; } + + /// + /// 更新时间 + /// + public string UpdateTime { get; set; } + + /// + /// 表名称描述(注释)(功能名) + /// + public string TableComment { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/CodeGen/Dto/XnCodeGenOutput.cs b/backend/Dilon.Core/Service/CodeGen/Dto/XnCodeGenOutput.cs new file mode 100644 index 0000000000000000000000000000000000000000..68d03bf6c0cacacbea60c60bb75585955e889798 --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/Dto/XnCodeGenOutput.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; + +namespace Dilon.Core.Service +{ + public class XnCodeGenOutput + { + /// + /// 作者姓名 + /// + public string AuthorName { get; set; } + + /// + /// 是否移除表前缀 + /// + public string TablePrefix { get; set; } + + /// + /// 生成方式 + /// + public string GenerateType { get; set; } + + /// + /// 数据库表名 + /// + public string TableName { get; set; } + + /// + /// 数据库表名(经过组装的) + /// + public string TableNameAss { get; set; } + + /// + /// 代码包名 + /// + public string PackageName { get; set; } + + /// + /// 生成时间(string类型的) + /// + public string CreateTimestring { get; set; } + + /// + /// 数据库表中字段集合 + /// + public List ConfigList { get; set; } + + /// + /// 业务名 + /// + public string BusName { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/CodeGen/ICodeGenConfigService.cs b/backend/Dilon.Core/Service/CodeGen/ICodeGenConfigService.cs new file mode 100644 index 0000000000000000000000000000000000000000..7f45ff87ed301f8089bfd1f00a68b0ba225ad0dd --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/ICodeGenConfigService.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + public interface ICodeGenConfigService + { + Task Add(CodeGenConfig input); + void AddList(List tableColumnOuputList, SysCodeGen codeGenerate); + string ConvertDataType(string dataType); + Task Delete(long codeGenId); + Task Detail(CodeGenConfig input); + Task> List([FromQuery] CodeGenConfig input); + Task Update(List inputList); + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/CodeGen/ICodeGenService.cs b/backend/Dilon.Core/Service/CodeGen/ICodeGenService.cs new file mode 100644 index 0000000000000000000000000000000000000000..9dbef41bd238e8e10d910f2e6f53b2feca15c054 --- /dev/null +++ b/backend/Dilon.Core/Service/CodeGen/ICodeGenService.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Dilon.Core.Service.CodeGen +{ + public interface ICodeGenService + { + Task AddCodeGen(AddCodeGenInput input); + Task DeleteCodeGen(List inputs); + Task GetCodeGen([FromQuery] QueryCodeGenInput input); + List GetColumnList(AddCodeGenInput input); + List GetTableList(); + Task QueryCodeGenPageList([FromQuery] CodeGenInput input); + Task RunLocal(SysCodeGen input); + Task UpdateCodeGen(UpdateCodeGenInput input); + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Config/ISysConfigService.cs b/backend/Dilon.Core/Service/Config/ISysConfigService.cs index 506762117781737c26ba7700ef9d48a35c233790..3b8a894372febf4a1bd4a747ed1768ad3b21e369 100644 --- a/backend/Dilon.Core/Service/Config/ISysConfigService.cs +++ b/backend/Dilon.Core/Service/Config/ISysConfigService.cs @@ -14,5 +14,6 @@ namespace Dilon.Core.Service Task GetDemoEnvFlag(); Task GetCaptchaOpenFlag(); Task UpdateConfigCache(string code, object value); + Task<(int interval, int quantity)> GetLogWritingConfiguration(); } } \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Config/SysConfigService.cs b/backend/Dilon.Core/Service/Config/SysConfigService.cs index e32d6c225c8afdf60b66099bd40a384c2fcb5f5d..d5b1b4c4fa2feacc83c8794e7ebf5e79f3c5d49d 100644 --- a/backend/Dilon.Core/Service/Config/SysConfigService.cs +++ b/backend/Dilon.Core/Service/Config/SysConfigService.cs @@ -41,7 +41,7 @@ namespace Dilon.Core.Service .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")), (code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")), (groupCode, u => EF.Functions.Like(u.Code, $"%{input.GroupCode.Trim()}%"))) - .Where(u => u.Status != (int)CommonStatus.DELETED).OrderBy(u => u.GroupCode) + .Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.GroupCode) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(configs); } @@ -54,7 +54,7 @@ namespace Dilon.Core.Service [HttpGet("/sysConfig/list")] public async Task GetConfigList([FromQuery] ConfigInput input) { - return await _sysConfigRep.DetachedEntities.Where(u => u.Status != (int)CommonStatus.DELETED).ToListAsync(); + return await _sysConfigRep.DetachedEntities.Where(u => u.Status != CommonStatus.DELETED).ToListAsync(); } /// @@ -70,7 +70,7 @@ namespace Dilon.Core.Service throw Oops.Oh(ErrorCode.D9000); var config = input.Adapt(); - await config.InsertNowAsync(); + await config.InsertAsync(); } /// @@ -86,7 +86,7 @@ namespace Dilon.Core.Service if (config.SysFlag == YesOrNot.Y.ToString()) throw Oops.Oh(ErrorCode.D9001); - await config.DeleteNowAsync(); + await config.DeleteAsync(); } /// @@ -102,7 +102,7 @@ namespace Dilon.Core.Service throw Oops.Oh(ErrorCode.D9000); var config = input.Adapt(); - await config.UpdateNowAsync(ignoreNullValues: true); + await config.UpdateAsync(ignoreNullValues: true); } /// @@ -132,7 +132,7 @@ namespace Dilon.Core.Service } return value; } - + /// /// 更新配置缓存 /// @@ -164,5 +164,20 @@ namespace Dilon.Core.Service var value = await GetConfigCache("DILON_CAPTCHA_OPEN"); return bool.Parse(value); } + + /// + /// 获取日志写入间隔和数量 + /// + /// + public async Task<(int interval, int quantity)> GetLogWritingConfiguration() + { + // 获取间隔 + var interval = await GetConfigCache("DILON_LOG_WRITE_INTERVAL") ?? 5000; + + // 获取数量 + var quantity = await GetConfigCache("DILON_NUMBER_OF_SINGLE_LOG_WRITES") ?? 20; + + return (int.Parse(interval), int.Parse(quantity)); + } } -} +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Dict/Dto/DictDataInput.cs b/backend/Dilon.Core/Service/Dict/Dto/DictDataInput.cs index 1b3893783d4a4ea9935872a180f5ddf966e913fa..fecb782d94ad7e820de800418c7d90cbe913c504 100644 --- a/backend/Dilon.Core/Service/Dict/Dto/DictDataInput.cs +++ b/backend/Dilon.Core/Service/Dict/Dto/DictDataInput.cs @@ -1,4 +1,4 @@ -using Furion.DataValidation; +using Furion.DataValidation; using System.ComponentModel.DataAnnotations; namespace Dilon.Core.Service @@ -36,7 +36,7 @@ namespace Dilon.Core.Service /// /// 状态(字典 0正常 1停用 2删除) /// - public virtual int Status { get; set; } + public virtual CommonStatus Status { get; set; } } public class QueryDictDataListInput diff --git a/backend/Dilon.Core/Service/Dict/Dto/DictDataOutput.cs b/backend/Dilon.Core/Service/Dict/Dto/DictDataOutput.cs index 8410d5c90a2e5affafa811935f4ae2330f06be03..f19daff7dbc7ee69c57773b13b3c0b91bcbb41fb 100644 --- a/backend/Dilon.Core/Service/Dict/Dto/DictDataOutput.cs +++ b/backend/Dilon.Core/Service/Dict/Dto/DictDataOutput.cs @@ -5,6 +5,9 @@ /// public class DictDataOutput : DictDataInput { - + /// + /// 字典Id + /// + public virtual long Id { get; set; } } } diff --git a/backend/Dilon.Core/Service/Dict/Dto/DictTypeInput.cs b/backend/Dilon.Core/Service/Dict/Dto/DictTypeInput.cs index f353855aed947872733b08e0bf7217af40e31fcd..afc244c59ce3c264fb4c451bc93cfb886654dfe8 100644 --- a/backend/Dilon.Core/Service/Dict/Dto/DictTypeInput.cs +++ b/backend/Dilon.Core/Service/Dict/Dto/DictTypeInput.cs @@ -30,7 +30,7 @@ namespace Dilon.Core.Service /// /// 状态(字典 0正常 1停用 2删除) /// - public virtual int Status { get; set; } + public virtual CommonStatus Status { get; set; } } public class AddDictTypeInput : DictTypeInput diff --git a/backend/Dilon.Core/Service/Dict/SysDictDataService.cs b/backend/Dilon.Core/Service/Dict/SysDictDataService.cs index 7bb72c45e61cb8e66d2f297ddaae7004d1af5c52..904adc2878c8501c1b15ae7c869ecaa8bc682f5d 100644 --- a/backend/Dilon.Core/Service/Dict/SysDictDataService.cs +++ b/backend/Dilon.Core/Service/Dict/SysDictDataService.cs @@ -39,7 +39,7 @@ namespace Dilon.Core.Service .Where(u => u.TypeId == input.TypeId) .Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")), (value, u => EF.Functions.Like(u.Value, $"%{input.Value.Trim()}%"))) - .Where(u => u.Status != (int)CommonStatus.DELETED).OrderBy(u => u.Sort) + .Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort) .Select(u => u.Adapt()) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(dictDatas); @@ -52,7 +52,7 @@ namespace Dilon.Core.Service [HttpGet("/sysDictData/list")] public async Task GetDictDataList([FromQuery] QueryDictDataListInput input) { - return await _sysDictDataRep.DetachedEntities.Where(u => u.TypeId == input.TypeId).Where(u => u.Status != (int)CommonStatus.DELETED).OrderBy(u => u.Sort).ToListAsync(); + return await _sysDictDataRep.DetachedEntities.Where(u => u.TypeId == input.TypeId).Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort).ToListAsync(); } /// @@ -81,7 +81,7 @@ namespace Dilon.Core.Service var dictData = await _sysDictDataRep.FirstOrDefaultAsync(u => u.Id == input.Id); if (dictData == null) throw Oops.Oh(ErrorCode.D3004); - await dictData.DeleteNowAsync(); + await dictData.DeleteAsync(); } /// @@ -139,7 +139,7 @@ namespace Dilon.Core.Service public async Task GetDictDataListByDictTypeId(long dictTypeId) { return await _sysDictDataRep.DetachedEntities.Where(u => u.SysDictType.Id == dictTypeId) - .Where(u => u.Status != (int)CommonStatus.DELETED).OrderBy(u => u.Sort) + .Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort) .Select(u => new { u.Code, diff --git a/backend/Dilon.Core/Service/Dict/SysDictTypeService.cs b/backend/Dilon.Core/Service/Dict/SysDictTypeService.cs index f96f8d6649753d119b6c08aebc5e48ed49488ed4..76836d753ed398f647094bfcd27c25e61f960563 100644 --- a/backend/Dilon.Core/Service/Dict/SysDictTypeService.cs +++ b/backend/Dilon.Core/Service/Dict/SysDictTypeService.cs @@ -42,7 +42,7 @@ namespace Dilon.Core.Service var dictTypes = await _sysDictTypeRep.DetachedEntities .Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")), (name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%"))) - .Where(u => u.Status != (int)CommonStatus.DELETED).OrderBy(u => u.Sort) + .Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(dictTypes); } @@ -54,7 +54,7 @@ namespace Dilon.Core.Service [HttpGet("/sysDictType/list")] public async Task GetDictTypeList() { - return await _sysDictTypeRep.DetachedEntities.Where(u => u.Status != (int)CommonStatus.DELETED).ToListAsync(); + return await _sysDictTypeRep.DetachedEntities.Where(u => u.Status != CommonStatus.DELETED).ToListAsync(); } /// @@ -100,7 +100,7 @@ namespace Dilon.Core.Service var dictDatas = await _sysDictDataService.GetDictDataListByDictTypeId(input.Id); //_sysDictDataService.DeleteByTypeId(input.Id); if (dictDatas != null && dictDatas.Count > 0) throw Oops.Oh(ErrorCode.D3002); - await dictType.DeleteNowAsync(); + await dictType.DeleteAsync(); } /// diff --git a/backend/Dilon.Core/Service/Emp/ISysEmpService.cs b/backend/Dilon.Core/Service/Emp/ISysEmpService.cs index ebdbf91c785733bdb224680dedcbe36edb2118ac..08d6d94b3a41f2dc5144845e7e3cd36ef37465cc 100644 --- a/backend/Dilon.Core/Service/Emp/ISysEmpService.cs +++ b/backend/Dilon.Core/Service/Emp/ISysEmpService.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Dilon.Core.Service { @@ -10,5 +11,6 @@ namespace Dilon.Core.Service Task GetEmpOrgId(long empId); Task HasOrgEmp(long orgId); Task UpdateEmpOrgInfo(long orgId, string orgName); + Task> HasOrgEmp(List orgIds); } } \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Emp/SysEmpExtOrgPosService.cs b/backend/Dilon.Core/Service/Emp/SysEmpExtOrgPosService.cs index a493e53dd5c12d146477a2ae4a4704c0a9f2a51b..6173825a5cd4438cbe50394e404e2b1b13573b61 100644 --- a/backend/Dilon.Core/Service/Emp/SysEmpExtOrgPosService.cs +++ b/backend/Dilon.Core/Service/Emp/SysEmpExtOrgPosService.cs @@ -24,20 +24,23 @@ namespace Dilon.Core.Service /// 保存或编辑附属机构相关信息 /// /// + [UnitOfWork] public async Task AddOrUpdate(long empId, List extIdList) { // 先删除 await DeleteEmpExtInfoByUserId(empId); + var tasks = new List(); extIdList.ForEach(u => { - new SysEmpExtOrgPos + tasks.Add(new SysEmpExtOrgPos { SysEmpId = empId, SysOrgId = u.OrgId, SysPosId = u.PosId - }.InsertNow(); + }.InsertAsync()); }); + await Task.WhenAll(tasks); } /// @@ -90,7 +93,7 @@ namespace Dilon.Core.Service var empExtOrgPos = await _sysEmpExtOrgPosRep.Where(u => u.SysEmpId == empId).ToListAsync(); empExtOrgPos.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } } diff --git a/backend/Dilon.Core/Service/Emp/SysEmpPosService.cs b/backend/Dilon.Core/Service/Emp/SysEmpPosService.cs index 9ac6bdb1469ac64946cf54d55c6b70f42169898f..382b3e8e8b80493345b615a6de598ff6bdb688a4 100644 --- a/backend/Dilon.Core/Service/Emp/SysEmpPosService.cs +++ b/backend/Dilon.Core/Service/Emp/SysEmpPosService.cs @@ -26,6 +26,7 @@ namespace Dilon.Core.Service /// 员工Id(用户Id) /// 职位id集合 /// + [UnitOfWork] public async Task AddOrUpdate(long empId, List posIdList) { // 先删除 @@ -37,7 +38,7 @@ namespace Dilon.Core.Service { SysEmpId = empId, SysPosId = u - }.InsertNow(); + }.Insert(); }); } @@ -77,7 +78,7 @@ namespace Dilon.Core.Service var empPos = await _sysEmpPosRep.Where(u => u.SysEmpId == empId).ToListAsync(); empPos.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } } diff --git a/backend/Dilon.Core/Service/Emp/SysEmpService.cs b/backend/Dilon.Core/Service/Emp/SysEmpService.cs index b07a14596739f5b906372ef1b4d168baa50c6fda..f09fc5d512beb8dd6a2e9e363e4b9164bbdb5255 100644 --- a/backend/Dilon.Core/Service/Emp/SysEmpService.cs +++ b/backend/Dilon.Core/Service/Emp/SysEmpService.cs @@ -3,6 +3,8 @@ using Furion.DatabaseAccessor.Extensions; using Furion.DependencyInjection; using Mapster; using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace Dilon.Core.Service @@ -47,6 +49,7 @@ namespace Dilon.Core.Service /// 增加或编辑员工相关信息 /// /// + [UnitOfWork] public async Task AddOrUpdate(EmpOutput2 sysEmpParam) { // 先删除员工信息 @@ -58,7 +61,7 @@ namespace Dilon.Core.Service // 再新增新员工信息 var emp = sysEmpParam.Adapt(); - await _sysEmpRep.InsertNowAsync(emp); + await _sysEmpRep.InsertAsync(emp); // 更新附属机构职位信息 await _sysEmpExtOrgPosService.AddOrUpdate(emp.Id, sysEmpParam.ExtIds); @@ -97,11 +100,12 @@ namespace Dilon.Core.Service /// /// /// + [UnitOfWork] public async Task DeleteEmpInfoByUserId(long empId) { // 删除员工信息 var emp = await _sysEmpRep.FirstOrDefaultAsync(u => u.Id == empId); - await emp.DeleteNowAsync(); + await emp.DeleteAsync(); // 级联删除对应的员工-附属信息 await _sysEmpExtOrgPosService.DeleteEmpExtInfoByUserId(empId); @@ -119,5 +123,15 @@ namespace Dilon.Core.Service { return (await _sysEmpRep.FirstOrDefaultAsync(u => u.Id == empId, false)).OrgId; } + + /// + /// 获取子机构用户 + /// + /// + /// + public async Task> HasOrgEmp(List orgIds) + { + return await _sysEmpRep.DetachedEntities.Where(u => orgIds.Contains(u.OrgId)).ToListAsync(); + } } } diff --git a/backend/Dilon.Core/Service/Enum/Dto/EnumDataInput.cs b/backend/Dilon.Core/Service/Enum/Dto/EnumDataInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..2c8b18c7a075f28c964e1ec5bd1b4f41191b2145 --- /dev/null +++ b/backend/Dilon.Core/Service/Enum/Dto/EnumDataInput.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; + +namespace Dilon.Core.Service +{ + /// + /// 枚举输入参数 + /// + public class EnumDataInput + { + /// + /// 枚举类型名称 + /// + [Required(ErrorMessage = "枚举类型不能为空")] + public string EnumName { get; set; } + } + + public class QueryEnumDataInput + { + /// + /// 实体名称 + /// + [Required(ErrorMessage = "实体名称不能为空")] + public string EntityName { get; set; } + + /// + /// 字段名称 + /// + [Required(ErrorMessage = "字段名称不能为空")] + public string FieldName { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/Enum/Dto/EnumDataOutput.cs b/backend/Dilon.Core/Service/Enum/Dto/EnumDataOutput.cs new file mode 100644 index 0000000000000000000000000000000000000000..adb7f9fd3714e155344100411e12927a21df2078 --- /dev/null +++ b/backend/Dilon.Core/Service/Enum/Dto/EnumDataOutput.cs @@ -0,0 +1,18 @@ +namespace Dilon.Core.Service +{ + /// + /// 枚举输出参数 + /// + public class EnumDataOutput + { + /// + /// 字典Id + /// + public string Code { get; set; } + + /// + /// 字典值 + /// + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Enum/ISysEnumDataService.cs b/backend/Dilon.Core/Service/Enum/ISysEnumDataService.cs new file mode 100644 index 0000000000000000000000000000000000000000..130f6ad3cf789ae974b1bd210fce58c6ed4e6747 --- /dev/null +++ b/backend/Dilon.Core/Service/Enum/ISysEnumDataService.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + public interface ISysEnumDataService + { + Task GetEnumDataList([FromQuery] EnumDataInput input); + Task GetEnumDataListByField([FromQuery] QueryEnumDataInput input); + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Enum/SysEnumDataService.cs b/backend/Dilon.Core/Service/Enum/SysEnumDataService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b95a7f7c235ebd03331028a90cb80c260b31ed0d --- /dev/null +++ b/backend/Dilon.Core/Service/Enum/SysEnumDataService.cs @@ -0,0 +1,68 @@ +using Furion; +using Furion.DatabaseAccessor; +using Furion.DependencyInjection; +using Furion.DynamicApiController; +using Furion.FriendlyException; +using Microsoft.AspNetCore.Mvc; +using System.Linq; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + /// + /// 枚举值服务 + /// + [ApiDescriptionSettings(Name = "EnumData")] + public class SysEnumDataService : ISysEnumDataService, IDynamicApiController, ITransient + { + /// + /// 通过枚举类型获取枚举值集合 + /// + /// + /// + [HttpGet("/sysEnumData/list")] + public async Task GetEnumDataList([FromQuery] EnumDataInput input) + { + // 查找枚举 + var enumType = App.EffectiveTypes.FirstOrDefault(t => t.IsEnum && t.Name == input.EnumName); + if (enumType == null) + throw Oops.Oh(ErrorCode.D1502).StatusCode(405); + + // 获取枚举的Key和描述 + return await Task.Run(() => + EnumExtensions.GetEnumDescDictionary(enumType) + .Select(x => new EnumDataOutput + { + Code = x.Key.ToString(), + Value = x.Value + })); + } + + /// + /// 通过实体字段类型获取相关集合(目前仅支持枚举类型) + /// + /// + /// + [HttpGet("/sysEnumData/listByFiled")] + public async Task GetEnumDataListByField([FromQuery] QueryEnumDataInput input) + { + // 获取实体类型属性 + var entityType = Db.GetDbContext().Model.GetEntityTypes().FirstOrDefault(u => u.ClrType.Name == input.EntityName); + if (entityType == null) throw Oops.Oh(ErrorCode.D1504); + + // 获取字段类型 + var fieldType = entityType.GetProperties().FirstOrDefault(p => p.Name == input.FieldName)?.ClrType; + if (fieldType is not { IsEnum: true }) + throw Oops.Oh(ErrorCode.D1503); + + // 获取枚举的Key和描述 + return await Task.Run(() => + EnumExtensions.GetEnumDescDictionary(fieldType) + .Select(x => new EnumDataOutput + { + Code = x.Key.ToString(), + Value = x.Value + })); + } + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/File/Dto/FileOutput.cs b/backend/Dilon.Core/Service/File/Dto/FileOutput.cs index 11355f0f85d09aba46a436096c948c1884ceb8de..42ece740bd2f9c6fd6ac79b9a9d908a50849fd3d 100644 --- a/backend/Dilon.Core/Service/File/Dto/FileOutput.cs +++ b/backend/Dilon.Core/Service/File/Dto/FileOutput.cs @@ -5,5 +5,9 @@ /// public class FileOutput : FileInput { + /// + /// 文件Id + /// + public long Id { get; set; } } } diff --git a/backend/Dilon.Core/Service/File/ISysFileService.cs b/backend/Dilon.Core/Service/File/ISysFileService.cs index 48496d10f5f10db7520ad0ee0a7a5cc5c7c05bac..9dfdc6192e5066d6caca3fd76738c64b16169328 100644 --- a/backend/Dilon.Core/Service/File/ISysFileService.cs +++ b/backend/Dilon.Core/Service/File/ISysFileService.cs @@ -1,5 +1,4 @@ -using Dilon.Core.Entity.System; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/backend/Dilon.Core/Service/File/SysFileService.cs b/backend/Dilon.Core/Service/File/SysFileService.cs index e3dc14e79a6706c445e80d120810c7d6b26bf412..4fa000f7703d85bd429063a2cf54891d368c7937 100644 --- a/backend/Dilon.Core/Service/File/SysFileService.cs +++ b/backend/Dilon.Core/Service/File/SysFileService.cs @@ -1,5 +1,4 @@ -using Dilon.Core.Entity.System; -using Furion; +using Furion; using Furion.DatabaseAccessor; using Furion.DatabaseAccessor.Extensions; using Furion.DependencyInjection; @@ -11,6 +10,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -63,7 +63,7 @@ namespace Dilon.Core.Service [HttpGet("/sysFileInfo/list")] public async Task> GetFileInfoList([FromQuery] FileOutput input) { - return await _sysFileInfoRep.AsQueryable().ToListAsync(); + return await _sysFileInfoRep.DetachedEntities.ToListAsync(); } /// @@ -79,7 +79,7 @@ namespace Dilon.Core.Service { await file.DeleteAsync(); - var filePath = App.WebHostEnvironment.WebRootPath + file.FileBucket + file.FileObjectName; + var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, file.FileBucket, file.FileObjectName); if (File.Exists(filePath)) File.Delete(filePath); } @@ -130,7 +130,7 @@ namespace Dilon.Core.Service public async Task DownloadFileInfo([FromQuery] QueryFileInoInput input) { var file = await GetFileInfo(input); - var filePath = App.WebHostEnvironment.WebRootPath + file.FileBucket + file.FileObjectName; + var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, file.FileBucket, file.FileObjectName); var fileName = HttpUtility.UrlEncode(file.FileOriginName, Encoding.GetEncoding("UTF-8")); return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName }; } @@ -180,11 +180,11 @@ namespace Dilon.Core.Service var fileSuffix = Path.GetExtension(file.FileName).ToLower(); // 文件后缀 var finalName = fileId + fileSuffix; // 生成文件的最终名称 - var filePath = App.WebHostEnvironment.WebRootPath + pathType; + var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, pathType); if (!Directory.Exists(filePath)) Directory.CreateDirectory(filePath); - using (var stream = File.Create(filePath + finalName)) + using (var stream = File.Create(Path.Combine(filePath, finalName))) { await file.CopyToAsync(stream); } diff --git a/backend/Dilon.Core/Service/Log/Dto/ExLogInput.cs b/backend/Dilon.Core/Service/Log/Dto/ExLogInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..2cb3bc5956af2d99270b812a63e9faec88bcf5a0 --- /dev/null +++ b/backend/Dilon.Core/Service/Log/Dto/ExLogInput.cs @@ -0,0 +1,47 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Dilon.Core.Service +{ + /// + /// 异常日志参数 + /// + public class ExLogInput : PageInputBase + { + /// + /// 操作人 + /// + public string Account { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 类名 + /// + public string ClassName { get; set; } + + /// + /// 方法名 + /// + public string MethodName { get; set; } + + /// + /// 异常名称 + /// + public string ExceptionName { get; set; } + + /// + /// 异常信息 + /// + [MaxLength(2000)] + public string ExceptionMsg { get; set; } + + /// + /// 异常时间 + /// + public DateTimeOffset ExceptionTime { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/Log/Dto/ExLogOutput.cs b/backend/Dilon.Core/Service/Log/Dto/ExLogOutput.cs new file mode 100644 index 0000000000000000000000000000000000000000..7feb0657c60e704e7d911047222478ef505860e8 --- /dev/null +++ b/backend/Dilon.Core/Service/Log/Dto/ExLogOutput.cs @@ -0,0 +1,10 @@ +namespace Dilon.Core.Service +{ + /// + /// 异常日志参数 + /// + public class ExLogOutput : ExLogInput + { + + } +} diff --git a/backend/Dilon.Core/Service/Log/Dto/OpLogInput.cs b/backend/Dilon.Core/Service/Log/Dto/OpLogInput.cs index 58547b6624782a5c4099d554c677b74c725ce36d..d0a0f2ff08e8e13abd70a45e084a5f4bb20d4976 100644 --- a/backend/Dilon.Core/Service/Log/Dto/OpLogInput.cs +++ b/backend/Dilon.Core/Service/Log/Dto/OpLogInput.cs @@ -12,15 +12,10 @@ namespace Dilon.Core.Service /// public string Name { get; set; } - /// - /// 操作类型(0其他 1增加 2删除 3编辑)(见LogAnnotionOpTypeEnum) - /// - public int? OpType { get; set; } - /// /// 是否执行成功(Y-是,N-否) /// - public string Success { get; set; } + public YesOrNot Success { get; set; } /// /// 具体消息 @@ -92,4 +87,4 @@ namespace Dilon.Core.Service /// public string Account { get; set; } } -} +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Log/Dto/VisLogInput.cs b/backend/Dilon.Core/Service/Log/Dto/VisLogInput.cs index 5607e489703e5ccb640fb946280bed38eab39476..03620892cea59a54d6ce7084c8f1da9690c28bfe 100644 --- a/backend/Dilon.Core/Service/Log/Dto/VisLogInput.cs +++ b/backend/Dilon.Core/Service/Log/Dto/VisLogInput.cs @@ -15,7 +15,7 @@ namespace Dilon.Core.Service /// /// 是否执行成功(Y-是,N-否) /// - public string Success { get; set; } + public YesOrNot Success { get; set; } /// /// 具体消息 @@ -43,9 +43,9 @@ namespace Dilon.Core.Service public string Os { get; set; } /// - /// 访问类型(字典 1登入 2登出) + /// 访问类型 /// - public int? VisType { get; set; } + public LoginType VisType { get; set; } /// /// 访问时间 @@ -57,4 +57,4 @@ namespace Dilon.Core.Service /// public string Account { get; set; } } -} +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Log/ISysExLogService.cs b/backend/Dilon.Core/Service/Log/ISysExLogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..28db5258712fa48d3d09edc0add0bfc13f14894a --- /dev/null +++ b/backend/Dilon.Core/Service/Log/ISysExLogService.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + public interface ISysExLogService + { + Task ClearExLog(); + Task QueryExLogPageList([FromQuery] ExLogInput input); + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Log/SysExLogService.cs b/backend/Dilon.Core/Service/Log/SysExLogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..0f1b301acd01917955cd178339a8e5bc3a956916 --- /dev/null +++ b/backend/Dilon.Core/Service/Log/SysExLogService.cs @@ -0,0 +1,64 @@ +using Furion.DatabaseAccessor; +using Furion.DatabaseAccessor.Extensions; +using Furion.DependencyInjection; +using Furion.DynamicApiController; +using Mapster; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + /// + /// 异常日志服务 + /// + [ApiDescriptionSettings(Name = "ExLog", Order = 100)] + public class SysExLogService : ISysExLogService, IDynamicApiController, ITransient + { + private readonly IRepository _sysExLogRep; // 操作日志表仓储 + + public SysExLogService(IRepository sysExLogRep) + { + _sysExLogRep = sysExLogRep; + } + + /// + /// 分页查询异常日志 + /// + /// + /// + [HttpGet("/sysExLog/page")] + public async Task QueryExLogPageList([FromQuery] ExLogInput input) + { + var name = !string.IsNullOrEmpty(input.Name?.Trim()); + var className = !string.IsNullOrEmpty(input.ClassName?.Trim()); + var methodName = !string.IsNullOrEmpty(input.MethodName?.Trim()); + var exceptionMsg = !string.IsNullOrEmpty(input.ExceptionMsg?.Trim()); + var searchBeginTime = !string.IsNullOrEmpty(input.SearchBeginTime?.Trim()); + var exLogs = await _sysExLogRep.DetachedEntities + .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%"))) + .Where(className, u => u.ClassName == input.ClassName) + .Where(methodName, u => u.MethodName == input.MethodName) + .Where(exceptionMsg, u => EF.Functions.Like(u.ExceptionMsg, $"%{input.ExceptionMsg.Trim()}%")) + .Where(searchBeginTime, u => u.ExceptionTime >= DateTime.Parse(input.SearchBeginTime.Trim()) && + u.ExceptionTime <= DateTime.Parse(input.SearchEndTime.Trim())) + .OrderByDescending(u => u.Id) + .Select(u => u.Adapt()) + .ToPagedListAsync(input.PageNo, input.PageSize); + return XnPageResult.PageResult(exLogs); + } + + /// + /// 清空异常日志 + /// + /// + [HttpPost("/sysExLog/delete")] + public async Task ClearExLog() + { + var opLogs = await _sysExLogRep.Entities.ToListAsync(); + opLogs.ForEach(u => { u.Delete(); }); + } + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Log/SysOpLogService.cs b/backend/Dilon.Core/Service/Log/SysOpLogService.cs index 47c7734cfe0711ca6797dd9b74bdb2a94d43bbda..86e8634b1ef7d3324e5b8cb85ecb24e44c3fbd43 100644 --- a/backend/Dilon.Core/Service/Log/SysOpLogService.cs +++ b/backend/Dilon.Core/Service/Log/SysOpLogService.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System; using System.Linq; +using System.Linq.Dynamic.Core; using System.Threading.Tasks; namespace Dilon.Core.Service @@ -17,7 +18,7 @@ namespace Dilon.Core.Service [ApiDescriptionSettings(Name = "OpLog", Order = 100)] public class SysOpLogService : ISysOpLogService, IDynamicApiController, ITransient { - private readonly IRepository _sysOpLogRep; // 操作日志表仓储 + private readonly IRepository _sysOpLogRep; // 操作日志表仓储 public SysOpLogService(IRepository sysOpLogRep) { @@ -33,14 +34,14 @@ namespace Dilon.Core.Service public async Task QueryOpLogPageList([FromQuery] OpLogInput input) { var name = !string.IsNullOrEmpty(input.Name?.Trim()); - var success = !string.IsNullOrEmpty(input.Success?.Trim()); + var success = !string.IsNullOrEmpty(input.Success.ToString()); var searchBeginTime = !string.IsNullOrEmpty(input.SearchBeginTime?.Trim()); var opLogs = await _sysOpLogRep.DetachedEntities .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%"))) - .Where(input.OpType > 0, u => u.OpType == input.OpType) - .Where(success, u => u.Success == input.Success.Trim()) + .Where(success, u => u.Success == input.Success) .Where(searchBeginTime, u => u.OpTime >= DateTime.Parse(input.SearchBeginTime.Trim()) && u.OpTime <= DateTime.Parse(input.SearchEndTime.Trim())) + .OrderBy(PageInputOrder.OrderBuilder(input)) // 封装了任意字段排序示例 .Select(u => u.Adapt()) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(opLogs); @@ -54,10 +55,7 @@ namespace Dilon.Core.Service public async Task ClearOpLog() { var opLogs = await _sysOpLogRep.Entities.ToListAsync(); - opLogs.ForEach(u => - { - u.Delete(); - }); + opLogs.ForEach(u => { u.Delete(); }); } } -} +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Log/SysVisLogService.cs b/backend/Dilon.Core/Service/Log/SysVisLogService.cs index 35659d89a8a998d611573c487a2b9b3930d7330d..5695493beb14f84f7bac427bccad410d5956d6e3 100644 --- a/backend/Dilon.Core/Service/Log/SysVisLogService.cs +++ b/backend/Dilon.Core/Service/Log/SysVisLogService.cs @@ -17,7 +17,7 @@ namespace Dilon.Core.Service [ApiDescriptionSettings(Name = "VisLog", Order = 100)] public class SysVisLogService : ISysVisLogService, IDynamicApiController, ITransient { - private readonly IRepository _sysVisLogRep; // 访问日志表仓储 + private readonly IRepository _sysVisLogRep; // 访问日志表仓储 public SysVisLogService(IRepository sysVisLogRep) { @@ -33,14 +33,15 @@ namespace Dilon.Core.Service public async Task QueryVisLogPageList([FromQuery] VisLogInput input) { var name = !string.IsNullOrEmpty(input.Name?.Trim()); - var success = !string.IsNullOrEmpty(input.Success?.Trim()); + var success = !string.IsNullOrEmpty(input.Success.ToString()); var searchBeginTime = !string.IsNullOrEmpty(input.SearchBeginTime?.Trim()); var visLogs = await _sysVisLogRep.DetachedEntities .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%"))) .Where(input.VisType > 0, u => u.VisType == input.VisType) - .Where(success, u => u.Success == input.Success.Trim()) - .Where(searchBeginTime, u => u.VisTime >= DateTime.Parse(input.SearchBeginTime.Trim()) && - u.VisTime <= DateTime.Parse(input.SearchEndTime.Trim())) + .Where(success, u => u.Success == input.Success) + .Where(searchBeginTime, u => u.VisTime >= DateTime.Parse(input.SearchBeginTime.Trim()) && + u.VisTime <= DateTime.Parse(input.SearchEndTime.Trim())) + .OrderByDescending(u => u.Id) .Select(u => u.Adapt()) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(visLogs); @@ -54,10 +55,7 @@ namespace Dilon.Core.Service public async Task ClearVisLog() { var visLogs = await _sysVisLogRep.Entities.ToListAsync(); - visLogs.ForEach(u => - { - u.Delete(); - }); + visLogs.ForEach(u => { u.Delete(); }); } } } diff --git a/backend/Dilon.Core/Service/Menu/SysMenuService.cs b/backend/Dilon.Core/Service/Menu/SysMenuService.cs index 554d2c45017cceee30a6cd2f83394280a5968d6e..bfc9ab7dc2fb24e7317601215014981b8661ea4e 100644 --- a/backend/Dilon.Core/Service/Menu/SysMenuService.cs +++ b/backend/Dilon.Core/Service/Menu/SysMenuService.cs @@ -1,4 +1,4 @@ -using Furion.DatabaseAccessor; +using Furion.DatabaseAccessor; using Furion.DatabaseAccessor.Extensions; using Furion.DependencyInjection; using Furion.DynamicApiController; @@ -50,12 +50,22 @@ namespace Dilon.Core.Service var permissions = await _sysCacheService.GetPermission(userId); // 先从缓存里面读取 if (permissions == null || permissions.Count < 1) { - var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId); - var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList); - permissions = await _sysMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.Id)) - .Where(u => u.Type == (int)MenuType.BTN) - .Where(u => u.Status == (int)CommonStatus.ENABLE) - .Select(u => u.Permission).ToListAsync(); + if (!_userManager.SuperAdmin) + { + var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId); + var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList); + permissions = await _sysMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.Id)) + .Where(u => u.Type == (int)MenuType.BTN) + .Where(u => u.Status == (int)CommonStatus.ENABLE) + .Select(u => u.Permission).ToListAsync(); + } + else + { + permissions = await _sysMenuRep.DetachedEntities + .Where(u => u.Type == (int)MenuType.BTN) + .Where(u => u.Status == (int)CommonStatus.ENABLE) + .Select(u => u.Permission).ToListAsync(); + } await _sysCacheService.SetPermission(userId, permissions); // 缓存结果 } return permissions; @@ -74,7 +84,7 @@ namespace Dilon.Core.Service if (antDesignTreeNodes == null || antDesignTreeNodes.Count < 1) { var sysMenuList = new List(); - // 管理员则展示所有系统权重菜单,不能展示业务权重菜单 + // 管理员则展示所有系统菜单 if (_userManager.SuperAdmin) { sysMenuList = await _sysMenuRep.DetachedEntities @@ -227,7 +237,10 @@ namespace Dilon.Core.Service var menu = input.Adapt(); menu.Pids = await CreateNewPids(input.Pid); menu.Status = (int)CommonStatus.ENABLE; - await menu.InsertNowAsync(); + await menu.InsertAsync(); + + // 清除缓存 + await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU); } /// @@ -236,20 +249,23 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysMenu/delete")] + [UnitOfWork] public async Task DeleteMenu(DeleteMenuInput input) { - var childIdList = await _sysMenuRep.DetachedEntities.Where(u => EF.Functions.Like(u.Pids, $"%[{input.Id}]%")) + var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString())) .Select(u => u.Id).ToListAsync(); childIdList.Add(input.Id); var menus = await _sysMenuRep.Where(u => childIdList.Contains(u.Id)).ToListAsync(); menus.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); - // 级联删除该菜单及子菜单对应的角色-菜单表信息 await _sysRoleMenuService.DeleteRoleMenuListByMenuIdList(childIdList); + + // 清除缓存 + await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU); } /// @@ -260,6 +276,7 @@ namespace Dilon.Core.Service [HttpPost("/sysMenu/edit"),] public async Task UpdateMenu(UpdateMenuInput input) { + // Pid和Id不能一致,一致会导致无限递归 if (input.Id == input.Pid) throw Oops.Oh(ErrorCode.D4006); @@ -269,6 +286,11 @@ namespace Dilon.Core.Service // 校验参数 CheckMenuParam(input); + // 如果是编辑,父id不能为自己的子节点 + var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString())) + .Select(u => u.Id).ToListAsync(); + if (childIdList.Contains(input.Pid)) + throw Oops.Oh(ErrorCode.D4006); var oldMenu = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id); @@ -327,7 +349,10 @@ namespace Dilon.Core.Service // 更新当前菜单 oldMenu = input.Adapt(); oldMenu.Pids = newPids; - await oldMenu.UpdateNowAsync(ignoreNullValues: true); + await oldMenu.UpdateAsync(ignoreNullValues: true); + + // 清除缓存 + await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU); } /// @@ -375,7 +400,7 @@ namespace Dilon.Core.Service public async Task TreeForGrant([FromQuery] MenuInput input) { var menuIdList = new List(); - if (_userManager.SuperAdmin) + if (!_userManager.SuperAdmin) { var roleIdList = await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId); menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList); @@ -405,7 +430,7 @@ namespace Dilon.Core.Service [NonAction] public async Task HasMenu(string appCode) { - return await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Application == appCode && u.Status != (int)CommonStatus.DELETED); + return await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Application == appCode && u.Status != CommonStatus.DELETED); } /// diff --git a/backend/Dilon.Core/Service/Notice/Dto/NoticeDetailOutput.cs b/backend/Dilon.Core/Service/Notice/Dto/NoticeDetailOutput.cs index 6fbc8ae084a0634c6af1d3a4b4a5d4de0379fa14..42e8565a159fa007b7be4461f14a67bee330f929 100644 --- a/backend/Dilon.Core/Service/Notice/Dto/NoticeDetailOutput.cs +++ b/backend/Dilon.Core/Service/Notice/Dto/NoticeDetailOutput.cs @@ -34,7 +34,7 @@ namespace Dilon.Core.Service /// /// 状态(字典 0未读 1已读) /// - public int ReadStatus { get; set; } + public NoticeUserStatus ReadStatus { get; set; } /// /// 阅读时间 diff --git a/backend/Dilon.Core/Service/Notice/Dto/NoticeInput.cs b/backend/Dilon.Core/Service/Notice/Dto/NoticeInput.cs index d13a066548e7078ea186df873aa6c1ebcb2ee065..f5f0ff6690b0a7cf071114d40a21f4b73bf3e236 100644 --- a/backend/Dilon.Core/Service/Notice/Dto/NoticeInput.cs +++ b/backend/Dilon.Core/Service/Notice/Dto/NoticeInput.cs @@ -26,7 +26,7 @@ namespace Dilon.Core.Service /// /// 状态(字典 0草稿 1发布 2撤回 3删除) /// - public virtual int Status { get; set; } + public virtual NoticeStatus Status { get; set; } /// /// 通知到的人 @@ -58,7 +58,7 @@ namespace Dilon.Core.Service /// 状态(字典 0草稿 1发布 2撤回 3删除) /// [Required(ErrorMessage = "状态不能为空")] - public override int Status { get; set; } + public override NoticeStatus Status { get; set; } /// /// 通知到的人 @@ -96,6 +96,6 @@ namespace Dilon.Core.Service /// 状态(字典 0草稿 1发布 2撤回 3删除) /// [Required(ErrorMessage = "状态不能为空")] - public int Status { get; set; } + public NoticeStatus Status { get; set; } } } diff --git a/backend/Dilon.Core/Service/Notice/ISysNoticeUserService.cs b/backend/Dilon.Core/Service/Notice/ISysNoticeUserService.cs index ffc8dd64566734cf5d3a235d816e1392be40ffda..34f0d11a6711da40e8a8e47d4d17db6f0a10b31c 100644 --- a/backend/Dilon.Core/Service/Notice/ISysNoticeUserService.cs +++ b/backend/Dilon.Core/Service/Notice/ISysNoticeUserService.cs @@ -5,9 +5,12 @@ namespace Dilon.Core.Service.Notice { public interface ISysNoticeUserService { - Task Add(long noticeId, List noticeUserIdList, int noticeUserStatus); + Task Add(long noticeId, List noticeUserIdList, NoticeUserStatus noticeUserStatus); + Task> GetNoticeUserListByNoticeId(long noticeId); - Task Read(long noticeId, long userId, int status); - Task Update(long noticeId, List noticeUserIdList, int noticeUserStatus); + + Task Read(long noticeId, long userId, NoticeUserStatus status); + + Task Update(long noticeId, List noticeUserIdList, NoticeUserStatus noticeUserStatus); } } \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Notice/SysNoticeService.cs b/backend/Dilon.Core/Service/Notice/SysNoticeService.cs index e3f0828650883de5601967dc6302178a0e7b3e19..35ef16f613ad3c9b239a1728f7127691493412f6 100644 --- a/backend/Dilon.Core/Service/Notice/SysNoticeService.cs +++ b/backend/Dilon.Core/Service/Notice/SysNoticeService.cs @@ -50,7 +50,7 @@ namespace Dilon.Core.Service.Notice .Where(searchValue, u => EF.Functions.Like(u.Title, $"%{input.SearchValue.Trim()}%") || EF.Functions.Like(u.Content, $"%{input.SearchValue.Trim()}%")) .Where(input.Type > 0, u => u.Type == input.Type) - .Where(u => u.Status != (int)NoticeStatus.DELETED) + .Where(u => u.Status != NoticeStatus.DELETED) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(notices); } @@ -63,19 +63,19 @@ namespace Dilon.Core.Service.Notice [HttpPost("/sysNotice/add")] public async Task AddNotice(AddNoticeInput input) { - if (input.Status != (int)NoticeStatus.DRAFT && input.Status != (int)NoticeStatus.PUBLIC) + if (input.Status != NoticeStatus.DRAFT && input.Status != NoticeStatus.PUBLIC) throw Oops.Oh(ErrorCode.D7000); var notice = input.Adapt(); await UpdatePublicInfo(notice); // 如果是发布,则设置发布时间 - if (input.Status == (int)NoticeStatus.PUBLIC) + if (input.Status == NoticeStatus.PUBLIC) notice.PublicTime = DateTimeOffset.Now; var newItem = await notice.InsertNowAsync(); // 通知到的人 var noticeUserIdList = input.NoticeUserIdList; - var noticeUserStatus = (int)NoticeUserStatus.UNREAD; + var noticeUserStatus = NoticeUserStatus.UNREAD; await _sysNoticeUserService.Add(newItem.Entity.Id, noticeUserIdList, noticeUserStatus); } @@ -88,7 +88,7 @@ namespace Dilon.Core.Service.Notice public async Task DeleteNotice(DeleteNoticeInput input) { var notice = await _sysNoticeRep.FirstOrDefaultAsync(u => u.Id == input.Id); - if (notice.Status != (int)NoticeStatus.DRAFT && notice.Status != (int)NoticeStatus.CANCEL) // 只能删除草稿和撤回的 + if (notice.Status != NoticeStatus.DRAFT && notice.Status != NoticeStatus.CANCEL) // 只能删除草稿和撤回的 throw Oops.Oh(ErrorCode.D7001); //notice.Status = (int)NoticeStatus.DELETED; @@ -103,24 +103,24 @@ namespace Dilon.Core.Service.Notice [HttpPost("/sysNotice/edit")] public async Task UpdateNotice(UpdateNoticeInput input) { - if (input.Status != (int)NoticeStatus.DRAFT && input.Status != (int)NoticeStatus.PUBLIC) + if (input.Status != NoticeStatus.DRAFT && input.Status != NoticeStatus.PUBLIC) throw Oops.Oh(ErrorCode.D7000); // 非草稿状态 - if (input.Status != (int)NoticeStatus.DRAFT) + if (input.Status != NoticeStatus.DRAFT) throw Oops.Oh(ErrorCode.D7002); var notice = input.Adapt(); - if (input.Status == (int)NoticeStatus.PUBLIC) + if (input.Status == NoticeStatus.PUBLIC) { notice.PublicTime = DateTimeOffset.Now; await UpdatePublicInfo(notice); } - await notice.UpdateNowAsync(); + await notice.UpdateAsync(); // 通知到的人 var noticeUserIdList = input.NoticeUserIdList; - var noticeUserStatus = (int)NoticeUserStatus.UNREAD; + var noticeUserStatus = NoticeUserStatus.UNREAD; await _sysNoticeUserService.Update(input.Id, noticeUserIdList, noticeUserStatus); } @@ -157,8 +157,8 @@ namespace Dilon.Core.Service.Notice noticeResult.NoticeUserIdList = noticeUserIdList; noticeResult.NoticeUserReadInfoList = noticeUserReadInfoList; // 如果该条通知公告为已发布,则将当前用户的该条通知公告设置为已读 - if (notice.Status == (int)NoticeStatus.PUBLIC) - await _sysNoticeUserService.Read(notice.Id, _userManager.UserId, (int)NoticeUserStatus.READ); + if (notice.Status == NoticeStatus.PUBLIC) + await _sysNoticeUserService.Read(notice.Id, _userManager.UserId, NoticeUserStatus.READ); return noticeResult; } @@ -171,21 +171,21 @@ namespace Dilon.Core.Service.Notice public async Task ChangeStatus(ChangeStatusNoticeInput input) { // 状态应为撤回或删除或发布 - if (input.Status != (int)NoticeStatus.CANCEL && input.Status != (int)NoticeStatus.DELETED && input.Status != (int)NoticeStatus.PUBLIC) + if (input.Status != NoticeStatus.CANCEL && input.Status != NoticeStatus.DELETED && input.Status != NoticeStatus.PUBLIC) throw Oops.Oh(ErrorCode.D7000); var notice = await _sysNoticeRep.FirstOrDefaultAsync(u => u.Id == input.Id); notice.Status = input.Status; - if (input.Status == (int)NoticeStatus.CANCEL) + if (input.Status == NoticeStatus.CANCEL) { notice.CancelTime = DateTimeOffset.Now; } - else if (input.Status == (int)NoticeStatus.PUBLIC) + else if (input.Status == NoticeStatus.PUBLIC) { notice.PublicTime = DateTimeOffset.Now; } - await notice.UpdateNowAsync(); + await notice.UpdateAsync(); } /// @@ -197,11 +197,11 @@ namespace Dilon.Core.Service.Notice public async Task ReceivedNoticePageList([FromQuery] NoticeInput input) { var searchValue = !string.IsNullOrEmpty(input.SearchValue?.Trim()); - var notices = await _sysNoticeRep.DetachedEntities.Join(_sysNoticeUserRep.AsQueryable(), u => u.Id, e => e.NoticeId, (u, e) => new { u, e }) + var notices = await _sysNoticeRep.DetachedEntities.Join(_sysNoticeUserRep.DetachedEntities, u => u.Id, e => e.NoticeId, (u, e) => new { u, e }) .Where(u => u.e.UserId == _userManager.UserId) .Where(searchValue, u => EF.Functions.Like(u.u.Title, $"%{input.SearchValue.Trim()}%") || EF.Functions.Like(u.u.Content, $"%{input.SearchValue.Trim()}%")) .Where(input.Type > 0, u => u.u.Type == input.Type) - .Where(u => u.u.Status != (int)NoticeStatus.DELETED) + .Where(u => u.u.Status != NoticeStatus.DELETED) .Select(u => u.u.Adapt()) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(notices); diff --git a/backend/Dilon.Core/Service/Notice/SysNoticeUserService.cs b/backend/Dilon.Core/Service/Notice/SysNoticeUserService.cs index 1e653e64d923de75aeb952029e0e4d406312618f..0873a9b9134ed6028564a132f564dc404c869bfe 100644 --- a/backend/Dilon.Core/Service/Notice/SysNoticeUserService.cs +++ b/backend/Dilon.Core/Service/Notice/SysNoticeUserService.cs @@ -27,18 +27,16 @@ namespace Dilon.Core.Service.Notice /// /// /// - public Task Add(long noticeId, List noticeUserIdList, int noticeUserStatus) + public Task Add(long noticeId, List noticeUserIdList, NoticeUserStatus noticeUserStatus) { - var noticeUsers = new List>(); noticeUserIdList.ForEach(u => { - var noticeUser = new SysNoticeUser + new SysNoticeUser { NoticeId = noticeId, UserId = u, ReadStatus = noticeUserStatus - }; - noticeUser.Insert(); + }.InsertAsync(); }); return Task.CompletedTask; } @@ -50,7 +48,7 @@ namespace Dilon.Core.Service.Notice /// /// /// - public async Task Update(long noticeId, List noticeUserIdList, int noticeUserStatus) + public async Task Update(long noticeId, List noticeUserIdList, NoticeUserStatus noticeUserStatus) { var noticeUsers = await _sysNoticeUserRep.Where(u => u.NoticeId == noticeId).ToListAsync(); noticeUsers.ForEach(u => @@ -78,7 +76,7 @@ namespace Dilon.Core.Service.Notice /// /// /// - public async Task Read(long noticeId, long userId, int status) + public async Task Read(long noticeId, long userId, NoticeUserStatus status) { var noticeUser = await _sysNoticeUserRep.FirstOrDefaultAsync(u => u.NoticeId == noticeId && u.UserId == userId); if (noticeUser != null) diff --git a/backend/Dilon.Core/Service/Org/ISysOrgService.cs b/backend/Dilon.Core/Service/Org/ISysOrgService.cs index 06c25276ae73fae8bebbbd0a1ef0edd7bd214604..13152e37f4c8690d35c5566b16af4b26992e22ae 100644 --- a/backend/Dilon.Core/Service/Org/ISysOrgService.cs +++ b/backend/Dilon.Core/Service/Org/ISysOrgService.cs @@ -14,6 +14,7 @@ namespace Dilon.Core.Service Task GetOrgTree([FromQuery] OrgInput input); Task QueryOrgPageList([FromQuery] PageOrgInput input); Task UpdateOrg(UpdateOrgInput input); + Task> GetAllDataScopeIdList(); Task> GetUserDataScopeIdList(); } } \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Org/SysOrgService.cs b/backend/Dilon.Core/Service/Org/SysOrgService.cs index fe82779c78bc85364bd11961db53b04253eb7937..03b43ccea6daacd1f262ca9d6a55fe973aefa64d 100644 --- a/backend/Dilon.Core/Service/Org/SysOrgService.cs +++ b/backend/Dilon.Core/Service/Org/SysOrgService.cs @@ -21,7 +21,7 @@ namespace Dilon.Core.Service { private readonly IRepository _sysOrgRep; // 组织机构表仓储 private readonly IUserManager _userManager; - + private readonly ISysCacheService _sysCacheService; private readonly ISysEmpService _sysEmpService; private readonly ISysEmpExtOrgPosService _sysEmpExtOrgPosService; private readonly ISysRoleDataScopeService _sysRoleDataScopeService; @@ -29,6 +29,7 @@ namespace Dilon.Core.Service public SysOrgService(IRepository sysOrgRep, IUserManager userManager, + ISysCacheService sysCacheService, ISysEmpService sysEmpService, ISysEmpExtOrgPosService sysEmpExtOrgPosService, ISysRoleDataScopeService sysRoleDataScopeService, @@ -36,6 +37,7 @@ namespace Dilon.Core.Service { _sysOrgRep = sysOrgRep; _userManager = userManager; + _sysCacheService = sysCacheService; _sysEmpService = sysEmpService; _sysEmpExtOrgPosService = sysEmpExtOrgPosService; _sysRoleDataScopeService = sysRoleDataScopeService; @@ -61,7 +63,7 @@ namespace Dilon.Core.Service (pId, u => EF.Functions.Like(u.Pids, $"%[{input.Pid.Trim()}]%") || u.Id == long.Parse(input.Pid.Trim()))) // 根据父机构id查询 .Where(dataScopeList.Count > 0, u => dataScopeList.Contains(u.Id)) // 非管理员范围限制 - .Where(u => u.Status != (int)CommonStatus.DELETED).OrderBy(u => u.Sort) + .Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort) .Select(u => u.Adapt()) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(orgs); @@ -87,9 +89,11 @@ namespace Dilon.Core.Service var sysOrg = _sysOrgRep.DetachedEntities.FirstOrDefault(c => c.Id == u); var parentAndChildIdListWithSelf = sysOrg.Pids.TrimEnd(',').Replace("[", "").Replace("]", "") .Split(",").Select(u => long.Parse(u)).ToList(); + parentAndChildIdListWithSelf.Add(sysOrg.Id); dataScopeList.AddRange(parentAndChildIdListWithSelf); }); } + return dataScopeList; } @@ -107,7 +111,7 @@ namespace Dilon.Core.Service var orgs = await _sysOrgRep.DetachedEntities .Where(pId, u => u.Pid == long.Parse(input.Pid)) .Where(dataScopeList.Count > 0, u => dataScopeList.Contains(u.Id)) - .Where(u => u.Status != (int)CommonStatus.DELETED).OrderBy(u => u.Sort).ToListAsync(); + .Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort).ToListAsync(); return orgs.Adapt>(); } @@ -122,24 +126,36 @@ namespace Dilon.Core.Service var isExist = await _sysOrgRep.DetachedEntities.AnyAsync(u => u.Name == input.Name || u.Code == input.Code); if (isExist) throw Oops.Oh(ErrorCode.D2002); - + var dataScopes = await GetUserDataScopeIdList(); if (!_userManager.SuperAdmin) { // 如果新增的机构父Id不是0,则进行数据权限校验 if (input.Pid != "0" && !string.IsNullOrEmpty(input.Pid)) { // 新增组织机构的父机构不在自己的数据范围内 - var dataScopes = await GetUserDataScopeIdList(); + if (dataScopes.Count < 1 || !dataScopes.Contains(long.Parse(input.Pid))) throw Oops.Oh(ErrorCode.D2003); } else - throw Oops.Oh(ErrorCode.D2003); + throw Oops.Oh(ErrorCode.D2006); } var sysOrg = input.Adapt(); await FillPids(sysOrg); - await sysOrg.InsertNowAsync(); + var newOrg = await _sysOrgRep.InsertNowAsync(sysOrg); + // 当前用户不是超级管理员时,将新增的公司加到用户的数据权限 + if (App.User.FindFirst(ClaimConst.CLAINM_SUPERADMIN)?.Value != ((int)AdminType.SuperAdmin).ToString()) + { + var userId = App.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + new SysUserDataScope + { + SysUserId = long.Parse(userId), + SysOrgId = newOrg.Entity.Id + }.Insert(); + dataScopes.Add(newOrg.Entity.Id); + await _sysCacheService.SetDataScope(long.Parse(userId), dataScopes); // 缓存新结果 + } } /// @@ -166,6 +182,7 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysOrg/delete")] + [UnitOfWork] public async Task DeleteOrg(DeleteOrgInput input) { var sysOrg = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == long.Parse(input.Id)); @@ -180,6 +197,12 @@ namespace Dilon.Core.Service if (hasOrgEmp) throw Oops.Oh(ErrorCode.D2004); + // 该机构下面子机构若有员工,则不能删 + var orgIds = await _sysOrgRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id)).Select(u => u.Id).ToListAsync(); + var emps = await _sysEmpService.HasOrgEmp(orgIds); + if (emps.Count > 0) + throw Oops.Oh(ErrorCode.D2004); + // 该附属机构下若有员工,则不能删 var hasExtOrgEmp = await _sysEmpExtOrgPosService.HasExtOrgEmp(sysOrg.Id); if (hasExtOrgEmp) @@ -190,7 +213,7 @@ namespace Dilon.Core.Service var orgs = await _sysOrgRep.Where(u => childIdList.Contains(u.Id)).ToListAsync(); orgs.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); // 级联删除该机构及子机构对应的角色-数据范围关联信息 @@ -206,6 +229,7 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysOrg/edit")] + [UnitOfWork] public async Task UpdateOrg(UpdateOrgInput input) { if (input.Pid != "0" && !string.IsNullOrEmpty(input.Pid)) @@ -216,6 +240,11 @@ namespace Dilon.Core.Service if (input.Id == input.Pid) throw Oops.Oh(ErrorCode.D2001); + // 如果是编辑,父id不能为自己的子节点 + var childIdListById = await GetChildIdListWithSelfById(long.Parse(input.Id)); + if (childIdListById.Contains(long.Parse(input.Pid))) + throw Oops.Oh(ErrorCode.D2001); + var sysOrg = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == long.Parse(input.Id)); // 检测数据范围能不能操作这个机构 @@ -227,13 +256,20 @@ namespace Dilon.Core.Service if (isExist) throw Oops.Oh(ErrorCode.D2002); - //如果名称有变化,则修改对应员工的机构相关信息 + // 如果名称有变化,则修改对应员工的机构相关信息 if (!sysOrg.Name.Equals(input.Name)) await _sysEmpService.UpdateEmpOrgInfo(sysOrg.Id, sysOrg.Name); sysOrg = input.Adapt(); await FillPids(sysOrg); - await sysOrg.UpdateNowAsync(ignoreNullValues: true); + await sysOrg.UpdateAsync(ignoreNullValues: true); + + //// 将所有子的父id进行更新 + //childIdListById.ForEach(u=> { + // var child = _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == u.Id); + // var newInput = child.Adapt(); + // UpdateOrg(newInput).GetAwaiter(); + //}); } /// @@ -321,6 +357,16 @@ namespace Dilon.Core.Service return orgIdList; } + /// + /// 获取所有的机构组织Id集合 + /// + /// + [NonAction] + public async Task> GetAllDataScopeIdList() + { + return await _sysOrgRep.DetachedEntities.Select(u => u.Id).ToListAsync(); + } + /// /// 获取用户数据范围(机构Id集合) /// diff --git a/backend/Dilon.Core/Service/Pos/SysPosService.cs b/backend/Dilon.Core/Service/Pos/SysPosService.cs index 47ee3ea9d8edab0d8d54fdc5a0b8396e6f6fd9e4..33c8ee398cd9f4d80781990b6107c78cd79b12b8 100644 --- a/backend/Dilon.Core/Service/Pos/SysPosService.cs +++ b/backend/Dilon.Core/Service/Pos/SysPosService.cs @@ -44,7 +44,7 @@ namespace Dilon.Core.Service var pos = await _sysPosRep.DetachedEntities .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")), (code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%"))) - .Where(u => u.Status == (int)CommonStatus.ENABLE).OrderBy(u => u.Sort) + .Where(u => u.Status == CommonStatus.ENABLE).OrderBy(u => u.Sort) .ToPagedListAsync(input.PageNo, input.PageSize); return XnPageResult.PageResult(pos); } @@ -58,7 +58,7 @@ namespace Dilon.Core.Service { var code = !string.IsNullOrEmpty(input.Code?.Trim()); return await _sysPosRep.DetachedEntities.Where(code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")) - .Where(u => u.Status != (int)CommonStatus.DELETED) + .Where(u => u.Status != CommonStatus.DELETED) .OrderBy(u => u.Sort).ToListAsync(); } @@ -75,7 +75,7 @@ namespace Dilon.Core.Service throw Oops.Oh(ErrorCode.D6000); var pos = input.Adapt(); - await pos.InsertNowAsync(); + await pos.InsertAsync(); } /// @@ -97,7 +97,7 @@ namespace Dilon.Core.Service throw Oops.Oh(ErrorCode.D6001); var pos = await _sysPosRep.FirstOrDefaultAsync(u => u.Id == input.Id); - await pos.DeleteNowAsync(); + await pos.DeleteAsync(); } /// @@ -113,7 +113,7 @@ namespace Dilon.Core.Service throw Oops.Oh(ErrorCode.D6000); var pos = input.Adapt(); - await pos.UpdateNowAsync(ignoreNullValues: true); + await pos.UpdateAsync(ignoreNullValues: true); } /// diff --git a/backend/Dilon.Core/Service/Role/Dto/RoleInput.cs b/backend/Dilon.Core/Service/Role/Dto/RoleInput.cs index 72bd7022e6134aa949ccd40bd352f73f9aeb4284..7b998245acdad95fddbc0b14c2881bbc4f4ca7a9 100644 --- a/backend/Dilon.Core/Service/Role/Dto/RoleInput.cs +++ b/backend/Dilon.Core/Service/Role/Dto/RoleInput.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Dilon.Core.Service { @@ -38,13 +38,13 @@ namespace Dilon.Core.Service /// /// 名称 /// - [Required(ErrorMessageResourceName = "角色名称不能为空")] + [Required(ErrorMessage = "角色名称不能为空")] public override string Name { get; set; } /// /// 编码 /// - [Required(ErrorMessageResourceName = "角色编码不能为空")] + [Required(ErrorMessage = "角色编码不能为空")] public override string Code { get; set; } } @@ -53,7 +53,7 @@ namespace Dilon.Core.Service /// /// 角色Id /// - [Required(ErrorMessageResourceName = "角色Id不能为空")] + [Required(ErrorMessage = "角色Id不能为空")] public long Id { get; set; } } @@ -62,7 +62,7 @@ namespace Dilon.Core.Service /// /// 角色Id /// - [Required(ErrorMessageResourceName = "角色Id不能为空")] + [Required(ErrorMessage = "角色Id不能为空")] public long Id { get; set; } } @@ -76,7 +76,7 @@ namespace Dilon.Core.Service /// /// 角色Id /// - [Required(ErrorMessageResourceName = "角色Id不能为空")] + [Required(ErrorMessage = "角色Id不能为空")] public long Id { get; set; } } @@ -84,4 +84,4 @@ namespace Dilon.Core.Service { } -} +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Role/SysRoleDataScopeService.cs b/backend/Dilon.Core/Service/Role/SysRoleDataScopeService.cs index 544c6411c68f12fea9a5e2abeb1c7ae4d31721be..63ecd9fe6f7fddb01822316e979c5f3d15400e50 100644 --- a/backend/Dilon.Core/Service/Role/SysRoleDataScopeService.cs +++ b/backend/Dilon.Core/Service/Role/SysRoleDataScopeService.cs @@ -25,12 +25,13 @@ namespace Dilon.Core.Service /// /// /// + [UnitOfWork] public async Task GrantDataScope(GrantRoleDataInput input) { var dataScopes = await _sysRoleDataScopeRep.DetachedEntities.Where(u => u.SysRoleId == input.Id).ToListAsync(); dataScopes.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); input.GrantOrgIdList.ForEach(u => @@ -39,7 +40,7 @@ namespace Dilon.Core.Service { SysRoleId = input.Id, SysOrgId = u - }.InsertNow(); + }.Insert(); }); } @@ -65,7 +66,7 @@ namespace Dilon.Core.Service var dataScopes = await _sysRoleDataScopeRep.DetachedEntities.Where(u => orgIdList.Contains(u.SysOrgId)).ToListAsync(); dataScopes.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } @@ -79,7 +80,7 @@ namespace Dilon.Core.Service var dataScopes = await _sysRoleDataScopeRep.DetachedEntities.Where(u => u.SysRoleId == roleId).ToListAsync(); dataScopes.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } } diff --git a/backend/Dilon.Core/Service/Role/SysRoleMenuService.cs b/backend/Dilon.Core/Service/Role/SysRoleMenuService.cs index 1b90f5114b658ff1d1ae29ee82b6b034cf9036d8..640a1df196f4f0c618739d05930205d70b38f937 100644 --- a/backend/Dilon.Core/Service/Role/SysRoleMenuService.cs +++ b/backend/Dilon.Core/Service/Role/SysRoleMenuService.cs @@ -14,10 +14,12 @@ namespace Dilon.Core.Service public class SysRoleMenuService : ISysRoleMenuService, ITransient { private readonly IRepository _sysRoleMenuRep; // 角色菜单表仓储 + private readonly ISysCacheService _sysCacheService; - public SysRoleMenuService(IRepository sysRoleMenuRep) + public SysRoleMenuService(IRepository sysRoleMenuRep, ISysCacheService sysCacheService) { _sysRoleMenuRep = sysRoleMenuRep; + _sysCacheService = sysCacheService; } /// @@ -37,12 +39,13 @@ namespace Dilon.Core.Service /// /// /// + [UnitOfWork] public async Task GrantMenu(GrantRoleMenuInput input) { var roleMenus = await _sysRoleMenuRep.DetachedEntities.Where(u => u.SysRoleId == input.Id).ToListAsync(); roleMenus.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); input.GrantMenuIdList.ForEach(u => @@ -51,8 +54,12 @@ namespace Dilon.Core.Service { SysRoleId = input.Id, SysMenuId = u - }.InsertNow(); + }.Insert(); }); + + // 清除缓存 + await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU); + await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_PERMISSION); } /// @@ -65,7 +72,7 @@ namespace Dilon.Core.Service var roleMenus = await _sysRoleMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.SysMenuId)).ToListAsync(); roleMenus.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } @@ -79,7 +86,7 @@ namespace Dilon.Core.Service var roleMenus = await _sysRoleMenuRep.DetachedEntities.Where(u => u.SysRoleId == roleId).ToListAsync(); roleMenus.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } } diff --git a/backend/Dilon.Core/Service/Role/SysRoleService.cs b/backend/Dilon.Core/Service/Role/SysRoleService.cs index fd7edb3449a6c3804aca15d2c88038dea4ee8cb2..889483c0748059bc373e6a8958636ef8eeac94a9 100644 --- a/backend/Dilon.Core/Service/Role/SysRoleService.cs +++ b/backend/Dilon.Core/Service/Role/SysRoleService.cs @@ -49,7 +49,7 @@ namespace Dilon.Core.Service [NonAction] public async Task> GetUserRoleList(long userId) { - return await _sysRoleRep.DetachedEntities.Join(_sysUserRoleRep.AsQueryable(), u => u.Id, e => e.SysRoleId, (u, e) => new { u, e }) + return await _sysRoleRep.DetachedEntities.Join(_sysUserRoleRep.DetachedEntities, u => u.Id, e => e.SysRoleId, (u, e) => new { u, e }) .Where(x => x.e.SysUserId == userId) .Select(x => x.u.Adapt()).ToListAsync(); } @@ -130,7 +130,7 @@ namespace Dilon.Core.Service var role = input.Adapt(); role.DataScopeType = 1; // 新角色默认全部数据范围 - await role.InsertNowAsync(); + await role.InsertAsync(); } /// @@ -139,10 +139,11 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysRole/delete")] + [UnitOfWork] public async Task DeleteRole(DeleteRoleInput input) { var sysRole = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == input.Id); - await sysRole.DeleteNowAsync(); + await sysRole.DeleteAsync(); //级联删除该角色对应的角色-数据范围关联信息 await _sysRoleDataScopeService.DeleteRoleDataScopeListByRoleId(sysRole.Id); @@ -152,7 +153,7 @@ namespace Dilon.Core.Service var userRoles = await _sysUserRoleRep.Where(u => u.SysRoleId == sysRole.Id).ToListAsync(); userRoles.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); //级联删除该角色对应的角色-菜单表关联信息 @@ -172,7 +173,7 @@ namespace Dilon.Core.Service throw Oops.Oh(ErrorCode.D1006); var sysRole = input.Adapt(); - await sysRole.UpdateNowAsync(); + await sysRole.UpdateAsync(); } /// diff --git a/backend/Dilon.Core/Service/Tenant/Dto/TenantInput.cs b/backend/Dilon.Core/Service/Tenant/Dto/TenantInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..449cd9d73a815891465ee07f0842b54911bc7497 --- /dev/null +++ b/backend/Dilon.Core/Service/Tenant/Dto/TenantInput.cs @@ -0,0 +1,109 @@ +using System.ComponentModel.DataAnnotations; + +namespace Dilon.Core.Service +{ + /// + /// 租户参数 + /// + public class TenantInput : PageInputBase + { + /// + /// 公司名称 + /// + public virtual string Name { get; set; } + + /// + /// 管理员名称 + /// + public virtual string AdminName { get; set; } + + /// + /// 主机 + /// + public virtual string Host { get; set; } + + /// + /// 电子邮箱 + /// + public virtual string Email { get; set; } + + /// + /// 电话号码 + /// + public string Phone { get; set; } + + /// + /// 模式 + /// + public string Schema { get; set; } + + /// + /// 数据库连接 + /// + public virtual string Connection { get; set; } + + /// + /// 备注 + /// + public string Remark { get; set; } + + /// + /// 创建时间 + /// + public string CreatedTime { get; set; } + } + + public class AddTenantInput : TenantInput + { + /// + /// 公司名称 + /// + [Required(ErrorMessage = "公司名称")] + public override string Name { get; set; } + + /// + /// 管理员名称 + /// + [Required(ErrorMessage = "管理员名称")] + public override string AdminName { get; set; } + + /// + /// 主机名称 + /// + public override string Host { get; set; } + + /// + /// 数据库连接 + /// + public override string Connection { get; set; } + + /// + /// 电子邮箱 + /// + [Required(ErrorMessage = "电子邮箱")] + public override string Email { get; set; } + } + + public class DeleteTenantInput + { + /// + /// 租户Id + /// + [Required(ErrorMessage = "租户Id不能为空")] + public long Id { get; set; } + } + + public class UpdateTenantInput : TenantInput + { + /// + /// 租户Id + /// + [Required(ErrorMessage = "租户Id不能为空")] + public long Id { get; set; } + } + + public class QueryTenantInput : DeleteTenantInput + { + + } +} diff --git a/backend/Dilon.Core/Service/Tenant/Dto/TenantOutput.cs b/backend/Dilon.Core/Service/Tenant/Dto/TenantOutput.cs new file mode 100644 index 0000000000000000000000000000000000000000..9adfca5d16a3a78988c34c42aa93c47e99aa9d62 --- /dev/null +++ b/backend/Dilon.Core/Service/Tenant/Dto/TenantOutput.cs @@ -0,0 +1,58 @@ +namespace Dilon.Core.Service +{ + /// + /// 租户参数 + /// + public class TenantOutput + { + /// + /// 租户Id + /// + public long Id { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 名称 + /// + public string AdminName { get; set; } + + /// + /// 主机 + /// + public string Host { get; set; } + + /// + /// 电子邮箱 + /// + public string Email { get; set; } + + /// + /// 电话号码 + /// + public string Phone { get; set; } + + /// + /// 模式 + /// + public string Schema { get; set; } + + /// + /// 数据库连接 + /// + public string Connection { get; set; } + + /// + /// 备注 + /// + public string Remark { get; set; } + + /// + /// 创建时间 + /// + public string CreatedTime { get; set; } + } +} diff --git a/backend/Dilon.Core/Service/Tenant/ISysTenantService.cs b/backend/Dilon.Core/Service/Tenant/ISysTenantService.cs new file mode 100644 index 0000000000000000000000000000000000000000..ee61cd826480195b016a089017e09200566dc067 --- /dev/null +++ b/backend/Dilon.Core/Service/Tenant/ISysTenantService.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + public interface ISysTenantService + { + Task AddTenant(AddTenantInput input); + Task DeleteTenant(DeleteTenantInput input); + Task GetTenant([FromQuery] QueryTenantInput input); + Task GrantMenu(GrantRoleMenuInput input); + Task InitNewTenant(SysTenant newTenant); + Task> OwnMenu([FromQuery] QueryTenantInput input); + Task QueryTenantPageList([FromQuery] TenantInput input); + Task ResetUserPwd(QueryTenantInput input); + Task UpdateTenant(UpdateTenantInput input); + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Tenant/SysTenantService.cs b/backend/Dilon.Core/Service/Tenant/SysTenantService.cs new file mode 100644 index 0000000000000000000000000000000000000000..764bc0b00095f0b4e75754fdc433190268489678 --- /dev/null +++ b/backend/Dilon.Core/Service/Tenant/SysTenantService.cs @@ -0,0 +1,230 @@ +using Furion.DatabaseAccessor; +using Furion.DataEncryption; +using Furion.DependencyInjection; +using Furion.DynamicApiController; +using Furion.FriendlyException; +using Mapster; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Dilon.Core.Service +{ + /// + /// 租户服务 + /// + [ApiDescriptionSettings(Name = "Tenant", Order = 100)] + public class SysTenantService : ISysTenantService, IDynamicApiController, ITransient + { + private readonly IRepository _sysTenantRep; // 租户表仓储 + private readonly IRepository _sysUserRep; + private readonly IRepository _sysOrgRep; + private readonly IRepository _sysRoleRep; + private readonly IRepository _sysEmpRep; + + private readonly ISysRoleMenuService _sysRoleMenuService; + private readonly ISysUserRoleService _sysUserRoleService; + + public SysTenantService(IRepository sysTenantRep, + IRepository sysUserService, + IRepository sysOrgService, + IRepository sysRoleService, + IRepository sysEmpService, + ISysRoleMenuService sysRoleMenuService, + ISysUserRoleService sysUserRoleService) + { + _sysTenantRep = sysTenantRep; + _sysUserRep = sysUserService; + _sysOrgRep = sysOrgService; + _sysRoleRep = sysRoleService; + _sysEmpRep = sysEmpService; + _sysRoleMenuService = sysRoleMenuService; + _sysUserRoleService = sysUserRoleService; + } + + /// + /// 分页查询租户 + /// + /// + /// + [HttpGet("/sysTenant/page")] + public async Task QueryTenantPageList([FromQuery] TenantInput input) + { + var name = !string.IsNullOrEmpty(input.Name?.Trim()); + var host = !string.IsNullOrEmpty(input.Host?.Trim()); + var tenants = await _sysTenantRep.DetachedEntities + .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%"))) + .Select(u => u.Adapt()) + .ToPagedListAsync(input.PageNo, input.PageSize); + return XnPageResult.PageResult(tenants); + } + + /// + /// 增加租户 + /// + /// + /// + [HttpPost("/sysTenant/add")] + public async Task AddTenant(AddTenantInput input) + { + var isExist = await _sysTenantRep.DetachedEntities.AnyAsync(u => u.Name == input.Name); + if (isExist) + throw Oops.Oh(ErrorCode.D1300); + + var tenant = input.Adapt(); + var newTenant = _sysTenantRep.InsertNow(tenant); + await InitNewTenant(newTenant.Entity); + } + + /// + /// 新增租户时,初始化数据 + /// + /// + public async Task InitNewTenant(SysTenant newTenant) + { + long tenantId = newTenant.Id; + string email = newTenant.Email; + string companyName = newTenant.Name; + // 初始化公司(组织结构) + SysOrg sysOrg = new() + { + TenantId = tenantId, + Pid = 0, + Pids = "[0],", + Name = companyName, + Code = "1", + Contacts = newTenant.AdminName, + Tel = newTenant.Phone + }; + var newOrg = _sysOrgRep.InsertNow(sysOrg); + + // 初始化角色 + SysRole sysRole = new() + { + TenantId = tenantId, + Code = "1", + Name = "系统管理员", + SysOrgs = new List() { newOrg.Entity } + }; + var newRole = _sysRoleRep.InsertNow(sysRole); + + // 初始化用户 + SysUser sysUser = new() + { + TenantId = tenantId, + Account = email, + Password = "e10adc3949ba59abbe56e057f20f883e", + Name = newTenant.AdminName, + NickName = newTenant.AdminName, + Email = newTenant.Email, + Phone = newTenant.Phone, + AdminType = AdminType.Admin, + SysRoles = new List() { newRole.Entity }, + SysOrgs = new List() { newOrg.Entity } + }; + var newUser = _sysUserRep.InsertNow(sysUser); + + // 初始化职工 + SysEmp sysEmp = new() + { + Id = newUser.Entity.Id, + JobNum = "1", + OrgId = newOrg.Entity.Id, + OrgName = newOrg.Entity.Name + }; + _sysEmpRep.InsertNow(sysEmp); + } + + /// + /// 删除租户 + /// + /// + /// + [HttpPost("/sysTenant/delete")] + public async Task DeleteTenant(DeleteTenantInput input) + { + var tenant = await _sysTenantRep.FirstOrDefaultAsync(u => u.Id == input.Id); + await _sysTenantRep.DeleteAsync(tenant); + } + + /// + /// 更新租户 + /// + /// + /// + [HttpPost("/sysTenant/edit")] + public async Task UpdateTenant(UpdateTenantInput input) + { + var isExist = await _sysTenantRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Host == input.Host) && u.Id != input.Id); + if (isExist) + throw Oops.Oh(ErrorCode.D1300); + + var tenant = input.Adapt(); + await _sysTenantRep.UpdateAsync(tenant, true); + } + + /// + /// 获取租户 + /// + /// + /// + [HttpGet("/sysTenant/detail")] + public async Task GetTenant([FromQuery] QueryTenantInput input) + { + return await _sysTenantRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id); + } + + /// + /// 授权租户管理员角色菜单 + /// + /// + /// + [HttpPost("/sysTenant/grantMenu")] + public async Task GrantMenu(GrantRoleMenuInput input) + { + var tenantAdminUser = await GetTenantAdminUser(input.Id); + var roleIds = await _sysUserRoleService.GetUserRoleIdList(tenantAdminUser.Id); + input.Id = roleIds[0]; // 重置租户管理员角色Id + await _sysRoleMenuService.GrantMenu(input); + } + + /// + /// 获取租户管理员角色拥有菜单Id集合 + /// + /// + /// + [HttpGet("/sysTenant/ownMenu")] + public async Task> OwnMenu([FromQuery] QueryTenantInput input) + { + var tenantAdminUser = await GetTenantAdminUser(input.Id); + var roleIds = await _sysUserRoleService.GetUserRoleIdList(tenantAdminUser.Id); + var tenantAdminRoleId = roleIds[0]; // 租户管理员角色Id + return await _sysRoleMenuService.GetRoleMenuIdList(new List { tenantAdminRoleId }); + } + + /// + /// 重置租户管理员密码 + /// + /// + /// + [HttpPost("/sysTenant/resetPwd")] + public async Task ResetUserPwd(QueryTenantInput input) + { + var tenantAdminUser = await GetTenantAdminUser(input.Id); + tenantAdminUser.Password = MD5Encryption.Encrypt(CommonConst.DEFAULT_PASSWORD); + } + + /// + /// 获取租户管理员用户 + /// + /// + /// + private async Task GetTenantAdminUser(long tenantId) + { + return await _sysUserRep.Where(u => u.TenantId == tenantId, false, true) + .Where(u => u.AdminType == AdminType.Admin).FirstOrDefaultAsync(); + } + } +} diff --git a/backend/Dilon.Core/Service/Timer/Dto/JobInput.cs b/backend/Dilon.Core/Service/Timer/Dto/JobInput.cs index 981ef0b902c82adac51806e58dc69cae68f660d2..14d24e2229f66138d55c519ec8af57dfca05d7c2 100644 --- a/backend/Dilon.Core/Service/Timer/Dto/JobInput.cs +++ b/backend/Dilon.Core/Service/Timer/Dto/JobInput.cs @@ -1,4 +1,5 @@ using Furion.DataValidation; +using Furion.TaskScheduler; using System; using System.ComponentModel.DataAnnotations; @@ -12,48 +13,28 @@ namespace Dilon.Core.Service /// /// 任务名称 /// - /// dilon public string JobName { get; set; } /// - /// 任务分组 + /// 执行间隔时间(单位秒) /// - /// dilon - public string JobGroup { get; set; } - - /// - /// 开始时间 - /// - public DateTimeOffset BeginTime { get; set; } = DateTimeOffset.Now; - - /// - /// 结束时间 - /// - /// null - public DateTimeOffset? EndTime { get; set; } + /// 5 + public int Interval { get; set; } /// /// Cron表达式 /// - /// public string Cron { get; set; } /// - /// 执行次数(默认无限循环) - /// - /// 10 - public int? RunNumber { get; set; } - - /// - /// 执行间隔时间,单位秒(如果有Cron,则IntervalSecond失效) + /// 定时器类型 /// - /// 5 - public int? Interval { get; set; } + public SpareTimeTypes TimerType { get; set; } /// - /// 触发器类型 + /// 执行次数 /// - public TriggerTypeEnum TriggerType { get; set; } = TriggerTypeEnum.Simple; + public int? RunNumber { get; set; } /// /// 请求url @@ -74,18 +55,12 @@ namespace Dilon.Core.Service /// /// 请求类型 /// - /// 2 - public RequestTypeEnum RequestType { get; set; } = RequestTypeEnum.Post; + public RequestTypeEnum RequestType { get; set; } /// - /// 描述 + /// 备注 /// public string Remark { get; set; } - - /// - /// 任务状态 - /// - public string DisplayState { get; set; } } public class DeleteJobInput : JobInput diff --git a/backend/Dilon.Core/Service/Timer/Dto/JobOutput.cs b/backend/Dilon.Core/Service/Timer/Dto/JobOutput.cs index ed65b1e75743f069424b710522cdb9a64e9238b6..bac985ccc9d3e55a4b6b6c86973911d9958b8148 100644 --- a/backend/Dilon.Core/Service/Timer/Dto/JobOutput.cs +++ b/backend/Dilon.Core/Service/Timer/Dto/JobOutput.cs @@ -1,5 +1,4 @@ -using Quartz; -using System; +using Furion.TaskScheduler; namespace Dilon.Core.Service { @@ -9,88 +8,70 @@ namespace Dilon.Core.Service public class JobOutput { /// - /// 任务名称 + /// Id /// - public string JobName { get; set; } + public long Id { get; set; } /// - /// 任务组名 - /// - public string JobGroup { get; set; } - - /// - /// 下次执行时间 + /// 任务名称 /// - public DateTime? NextFireTime { get; set; } + public string JobName { get; set; } /// - /// 上次执行时间 + /// 执行间隔时间(单位秒) /// - public DateTime? PreviousFireTime { get; set; } + public int Interval { get; set; } /// - /// 开始时间 + /// Cron表达式 /// - public DateTime BeginTime { get; set; } + public string Cron { get; set; } /// - /// 结束时间 + /// 定时器类型 /// - public DateTime? EndTime { get; set; } + public SpareTimeTypes TimerType { get; set; } /// - /// 上次执行的异常信息 + /// 执行次数 /// - public string LastErrMsg { get; set; } + public long? RunNumber { get; set; } /// - /// 任务状态 + /// 请求url /// - public TriggerState TriggerState { get; set; } + public string RequestUrl { get; set; } /// - /// 描述 + /// 请求参数(Post,Put请求用) /// - public string Remark { get; set; } + public string RequestParameters { get; set; } /// - /// 显示状态 + /// Headers(可以包含如:Authorization授权认证) + /// 格式:{"Authorization":"userpassword.."} /// - public string DisplayState - { - get - { - return TriggerState switch - { - TriggerState.Normal => "正常", - TriggerState.Paused => "暂停", - TriggerState.Complete => "完成", - TriggerState.Error => "异常", - TriggerState.Blocked => "阻塞", - TriggerState.None => "不存在", - _ => "未知", - }; - } - } + public string Headers { get; set; } /// - /// 时间间隔 + /// 请求类型 /// - public string Interval { get; set; } + /// 2 + public RequestTypeEnum RequestType { get; set; } /// - /// 请求地址 + /// 备注 /// - public string RequestUrl { get; set; } + public string Remark { get; set; } /// - /// 请求类型 + /// 定时器状态 /// - public string RequestType { get; set; } + public SpareTimeStatus TimerStatus { get; set; } = SpareTimeStatus.Stopped; /// - /// 已经执行的次数 + /// 异常信息 /// - public string RunNumber { get; set; } + public string Exception { get; set; } } } diff --git a/backend/Dilon.Core/Service/Timer/HttpJob.cs b/backend/Dilon.Core/Service/Timer/HttpJob.cs deleted file mode 100644 index 8cba5ad36aa98c5ec3b02a769f6ec29084ea36ff..0000000000000000000000000000000000000000 --- a/backend/Dilon.Core/Service/Timer/HttpJob.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Furion.JsonSerialization; -using Furion.RemoteRequest.Extensions; -using Quartz; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Dilon.Core.Service -{ - [DisallowConcurrentExecution] - public class HttpJob : IJob - { - //protected readonly int _maxLogCount = 20; //最多保存日志数量 - //protected Stopwatch _stopwatch = new(); - - public async Task Execute(IJobExecutionContext context) - { - // 获取相关参数 - var requestUrl = context.JobDetail.JobDataMap.GetString(SchedulerDef.REQUESTURL)?.Trim(); - requestUrl = requestUrl?.IndexOf("http") == 0 ? requestUrl : "http://" + requestUrl; - var requestParameters = context.JobDetail.JobDataMap.GetString(SchedulerDef.REQUESTPARAMETERS); - var headersString = context.JobDetail.JobDataMap.GetString(SchedulerDef.HEADERS); - var headers = headersString != null ? JSON.GetJsonSerializer().Deserialize>(headersString?.Trim()) : null; - var requestType = (RequestTypeEnum)int.Parse(context.JobDetail.JobDataMap.GetString(SchedulerDef.REQUESTTYPE)); - - // var response = new HttpResponseMessage(); - switch (requestType) - { - case RequestTypeEnum.Get: - await requestUrl.SetHeaders(headers).GetAsync(); - break; - case RequestTypeEnum.Post: - await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PostAsync(); - break; - case RequestTypeEnum.Put: - await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PutAsync(); - break; - case RequestTypeEnum.Delete: - await requestUrl.SetHeaders(headers).DeleteAsync(); - break; - } - - - //_stopwatch.Restart(); // 开始监视代码运行时间 - //// var beginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); - - //Debug.WriteLine(DateTimeOffset.Now.ToString()); - - //// var endTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); - //_stopwatch.Stop(); // 停止监视 - - ////// 执行次数 - ////var runNumber = context.JobDetail.JobDataMap.GetString(SchedulerDef.RUNNUMBER); - ////context.JobDetail.JobDataMap[SchedulerDef.RUNNUMBER] = runNumber; - - //// 耗时 - //var seconds = _stopwatch.Elapsed.TotalSeconds; // 总秒数 - //var executeTime = seconds >= 1 ? seconds + "秒" : _stopwatch.Elapsed.TotalMilliseconds + "毫秒"; - - ////// 只保留20条记录 - ////var logs = context.JobDetail.JobDataMap[SchedulerDef.LOGLIST] as List ?? new List(); - ////if (logs.Count >= _maxLogCount) - //// logs.RemoveRange(0, logs.Count - _maxLogCount); - - ////logs.Add($"

{beginTime} 至 {endTime} 【耗时】{executeTime}

"); - ////context.JobDetail.JobDataMap[SchedulerDef.LOGLIST] = logs; - } - } -} diff --git a/backend/Dilon.Core/Service/Timer/ISysTimerService.cs b/backend/Dilon.Core/Service/Timer/ISysTimerService.cs index fb71f462a7a76ee11ddff46c014a42f79d20f4b5..ff7c221dd0567aca88e2ebfb59c3422b602f50f2 100644 --- a/backend/Dilon.Core/Service/Timer/ISysTimerService.cs +++ b/backend/Dilon.Core/Service/Timer/ISysTimerService.cs @@ -5,12 +5,13 @@ namespace Dilon.Core.Service { public interface ISysTimerService { - Task AddJob(JobInput input); - Task DeleteJob(DeleteJobInput input); - Task GetJobPageList([FromQuery] JobInput input); + Task AddTimer(JobInput input); + void AddTimerJob(JobInput input); + Task DeleteTimer(DeleteJobInput input); Task GetTimer([FromQuery] QueryJobInput input); - Task StopScheduleJobAsync(JobInput input); - Task TriggerJobAsync(JobInput input); - Task UpdateJob(UpdateJobInput input); + Task GetTimerPageList([FromQuery] JobInput input); + void StartTimerJob(JobInput input); + void StopTimerJob(JobInput input); + Task UpdateTimber(UpdateJobInput input); } } \ No newline at end of file diff --git a/backend/Dilon.Core/Service/Timer/SchedulerCenter.cs b/backend/Dilon.Core/Service/Timer/SchedulerCenter.cs deleted file mode 100644 index 7c4ec5a6580d7470f090214e02ae363ce2071e7a..0000000000000000000000000000000000000000 --- a/backend/Dilon.Core/Service/Timer/SchedulerCenter.cs +++ /dev/null @@ -1,336 +0,0 @@ -using Furion.DatabaseAccessor; -using Furion.DependencyInjection; -using Furion.FriendlyException; -using Mapster; -using Microsoft.AspNetCore.Mvc; -using Quartz; -using Quartz.Impl; -using Quartz.Impl.Matchers; -using Quartz.Impl.Triggers; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Dilon.Core.Service -{ - /// - /// 任务调度中心 - /// - public class SchedulerCenter : ISingleton - { - private IScheduler _scheduler = null; - - public SchedulerCenter() - { - _ = StartScheduleAsync(); - - InitAllJob().GetAwaiter(); - } - - /// - /// 开启调度器 - /// - /// - private async Task StartScheduleAsync() - { - if (_scheduler == null) - { - // 初始化Scheduler - var schedulerFactory = new StdSchedulerFactory(); - _scheduler = await schedulerFactory.GetScheduler(); - - // 开启调度器 - if (_scheduler.InStandbyMode) - await _scheduler.Start(); - } - return _scheduler.InStandbyMode; - } - - /// - /// 停止调度器 - /// - private async Task StopScheduleAsync() - { - //判断调度是否已经关闭 - if (!_scheduler.InStandbyMode) - { - //等待任务运行完成 - await _scheduler.Standby(); // 注意:Shutdown后Start会报错,所以这里使用暂停。 - } - return !_scheduler.InStandbyMode; - } - - /// - /// 添加一个工作任务 - /// - /// - /// - public async Task AddScheduleJobAsync(JobInput input) - { - // 检查任务是否已存在 - var jobKey = new JobKey(input.JobName, input.JobGroup); - if (await _scheduler.CheckExists(jobKey)) - throw Oops.Oh("任务已存在"); - - // http请求配置 - var httpDir = new Dictionary() - { - { SchedulerDef.ENDAT, input.EndTime.ToString()}, - { SchedulerDef.REQUESTURL, input.RequestUrl}, - { SchedulerDef.HEADERS, input.Headers }, - { SchedulerDef.REQUESTPARAMETERS, input.RequestParameters}, - { SchedulerDef.REQUESTTYPE, ((int)input.RequestType).ToString()}, - { SchedulerDef.RUNNUMBER, input.RunNumber.ToString()} - }; - - // 定义这个工作,并将其绑定到我们的IJob实现类 - IJobDetail job = JobBuilder.Create() - .SetJobData(new JobDataMap(httpDir)) - .WithDescription(input.Remark) - .WithIdentity(input.JobName, input.JobGroup) - .Build(); - // 创建触发器 - ITrigger trigger = input.TriggerType == TriggerTypeEnum.Cron // && CronExpression.IsValidExpression(entity.Cron) - ? CreateCronTrigger(input) - : CreateSimpleTrigger(input); - - return await _scheduler.ScheduleJob(job, trigger); - } - - /// - /// 暂停任务 - /// - /// - /// - public async Task StopScheduleJobAsync(JobInput input) - { - var jobKey = new JobKey(input.JobName, input.JobGroup); - await _scheduler.PauseJob(jobKey); - } - - /// - /// 删除任务 - /// - /// - /// - public async Task DeleteScheduleJobAsync(DeleteJobInput input) - { - var jobKey = new JobKey(input.JobName, input.JobGroup); - await _scheduler.PauseJob(jobKey); - await _scheduler.DeleteJob(jobKey); - } - - /// - /// 恢复运行暂停的任务 - /// - /// - /// - [HttpPost("/sysTimer/resumeJob")] - public async Task ResumeJobAsync(JobInput input) - { - //检查任务是否存在 - var jobKey = new JobKey(input.JobName, input.JobGroup); - if (await _scheduler.CheckExists(jobKey)) - { - var jobDetail = await _scheduler.GetJobDetail(jobKey); - var endTime = jobDetail.JobDataMap.GetString(SchedulerDef.ENDAT); - if (!string.IsNullOrWhiteSpace(endTime) && DateTime.Parse(endTime) <= DateTime.Now) - { - throw Oops.Oh("Job的结束时间已过期"); - } - else - { - await _scheduler.ResumeJob(jobKey); // 任务已经存在则暂停任务 - } - } - return Task.CompletedTask; - } - - /// - /// 查询任务 - /// - /// - /// - public async Task QueryJobAsync(JobInput input) - { - var jobKey = new JobKey(input.JobName, input.JobGroup); - var jobDetail = await _scheduler.GetJobDetail(jobKey); - var triggersList = await _scheduler.GetTriggersOfJob(jobKey); - var triggers = triggersList.AsEnumerable().FirstOrDefault(); - var intervalSeconds = (triggers as SimpleTriggerImpl)?.RepeatInterval.TotalSeconds; - var endTime = jobDetail.JobDataMap.GetString(SchedulerDef.ENDAT); - return new JobInput - { - BeginTime = triggers.StartTimeUtc.LocalDateTime, - EndTime = !string.IsNullOrWhiteSpace(endTime) ? DateTime.Parse(endTime) : null, - Interval = intervalSeconds.HasValue ? Convert.ToInt32(intervalSeconds.Value) : null, - JobGroup = input.JobGroup, - JobName = input.JobName, - Cron = (triggers as CronTriggerImpl)?.CronExpressionString, - RunNumber = (triggers as SimpleTriggerImpl)?.RepeatCount, - TriggerType = triggers is SimpleTriggerImpl ? TriggerTypeEnum.Simple : TriggerTypeEnum.Cron, - Remark = jobDetail.Description, - RequestUrl = jobDetail.JobDataMap.GetString(SchedulerDef.REQUESTURL), - RequestType = (RequestTypeEnum)int.Parse(jobDetail.JobDataMap.GetString(SchedulerDef.REQUESTTYPE)), - RequestParameters = jobDetail.JobDataMap.GetString(SchedulerDef.REQUESTPARAMETERS), - Headers = jobDetail.JobDataMap.GetString(SchedulerDef.HEADERS) - }; - } - - /// - /// 立即执行 - /// - /// - /// - public async Task TriggerJobAsync(JobInput input) - { - var jobKey = new JobKey(input.JobName, input.JobGroup); - await _scheduler.ResumeJob(jobKey); - } - - /// - /// 获取任务日志 - /// - /// - /// - public async Task> GetJobLogsAsync(JobInput input) - { - var jobKey = new JobKey(input.JobName, input.JobGroup); - var jobDetail = await _scheduler.GetJobDetail(jobKey); - return jobDetail.JobDataMap[SchedulerDef.LOGLIST] as List; - } - - /// - /// 获取任务运行次数 - /// - /// - /// - public async Task GetRunNumberAsync(JobInput input) - { - var jobKey = new JobKey(input.JobName, input.JobGroup); - var jobDetail = await _scheduler.GetJobDetail(jobKey); - return jobDetail.JobDataMap.GetLong(SchedulerDef.RUNNUMBER); - } - - /// - /// 获取所有任务详情 - /// - /// - public async Task> GetJobList() - { - var jobInfoList = new List(); - var groupNames = await _scheduler.GetJobGroupNames(); - var jboKeyList = new List(); - foreach (var groupName in groupNames.OrderBy(t => t)) - { - jboKeyList.AddRange(await _scheduler.GetJobKeys(GroupMatcher.GroupEquals(groupName))); - //jobInfoList.Add(new JobOutput() { JobGroup = groupName }); - } - foreach (var jobKey in jboKeyList.OrderBy(t => t.Name)) - { - var jobDetail = await _scheduler.GetJobDetail(jobKey); - var triggersList = await _scheduler.GetTriggersOfJob(jobKey); - var triggers = triggersList.AsEnumerable().FirstOrDefault(); - - var interval = triggers is SimpleTriggerImpl - ? ((triggers as SimpleTriggerImpl)?.RepeatInterval.ToString()) - : ((triggers as CronTriggerImpl)?.CronExpressionString); - - jobInfoList.Add(new JobOutput - { - JobName = jobKey.Name, - JobGroup = jobKey.Group, - LastErrMsg = jobDetail.JobDataMap.GetString(SchedulerDef.EXCEPTION), - RequestUrl = jobDetail.JobDataMap.GetString(SchedulerDef.REQUESTURL), - TriggerState = await _scheduler.GetTriggerState(triggers.Key), - PreviousFireTime = triggers.GetPreviousFireTimeUtc()?.LocalDateTime, - NextFireTime = triggers.GetNextFireTimeUtc()?.LocalDateTime, - BeginTime = triggers.StartTimeUtc.LocalDateTime, - Interval = interval, - EndTime = triggers.EndTimeUtc?.LocalDateTime, - Remark = jobDetail.Description, - RequestType = jobDetail.JobDataMap.GetString(SchedulerDef.REQUESTTYPE), - RunNumber = jobDetail.JobDataMap.GetString(SchedulerDef.RUNNUMBER) - }); - } - return jobInfoList; - } - - /// - /// 从数据库里面获取所有任务并初始化 - /// - private async Task InitAllJob() - { - var jobList = Db.GetRepository().AsQueryable().Select(u => u.Adapt()).ToList(); - var jobTasks = new List>(); - jobList.ForEach(u => - { - jobTasks.Add(AddScheduleJobAsync(u)); - }); - await Task.WhenAll(jobTasks); - } - - /// - /// 创建类型Simple的触发器 - /// - /// - /// - private static ITrigger CreateSimpleTrigger(JobInput input) - { - //作业触发器 - if (input.RunNumber.HasValue && input.RunNumber > 0) - { - return TriggerBuilder.Create() - .WithIdentity(input.JobName, input.JobGroup) - .StartAt(input.BeginTime)//开始时间 - //.EndAt(entity.EndTime)//结束数据 - .WithSimpleSchedule(x => - { - x.WithIntervalInSeconds(input.Interval.Value)//执行时间间隔,单位秒 - .WithRepeatCount(input.RunNumber.Value)//执行次数、默认从0开始 - .WithMisfireHandlingInstructionFireNow(); - }) - .ForJob(input.JobName, input.JobGroup)//作业名称 - .Build(); - } - else - { - return TriggerBuilder.Create() - .WithIdentity(input.JobName, input.JobGroup) - .StartAt(input.BeginTime)//开始时间 - //.EndAt(entity.EndTime)//结束数据 - .WithSimpleSchedule(x => - { - x.WithIntervalInSeconds(input.Interval.Value)//执行时间间隔,单位秒 - .RepeatForever()//无限循环 - .WithMisfireHandlingInstructionFireNow(); - }) - .ForJob(input.JobName, input.JobGroup)//作业名称 - .Build(); - } - - } - - /// - /// 创建类型Cron的触发器 - /// - /// - /// - private static ITrigger CreateCronTrigger(JobInput input) - { - if (!CronExpression.IsValidExpression(input.Cron)) - throw Oops.Oh("Cron表达式错误"); - - // 作业触发器 - return TriggerBuilder.Create() - - .WithIdentity(input.JobName, input.JobGroup) - .StartAt(input.BeginTime) //开始时间 - //.EndAt(entity.EndTime) //结束时间 - .WithCronSchedule(input.Cron, cronScheduleBuilder => cronScheduleBuilder.WithMisfireHandlingInstructionFireAndProceed())//指定cron表达式 - .ForJob(input.JobName, input.JobGroup)//作业名称 - .Build(); - } - } -} diff --git a/backend/Dilon.Core/Service/Timer/SchedulerDef.cs b/backend/Dilon.Core/Service/Timer/SchedulerDef.cs deleted file mode 100644 index df0a5c0a7a86faa01a4c0c6f5f707e1a66094bf6..0000000000000000000000000000000000000000 --- a/backend/Dilon.Core/Service/Timer/SchedulerDef.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace Dilon.Core.Service -{ - /// - /// 任务调度相关常量 - /// - public class SchedulerDef - { - /// - /// 请求url RequestUrl - /// - public const string REQUESTURL = "RequestUrl"; - /// - /// 请求参数 RequestParameters - /// - public const string REQUESTPARAMETERS = "RequestParameters"; - /// - /// Headers(可以包含:Authorization授权认证) - /// - public const string HEADERS = "Headers"; - /// - /// 请求类型 RequestType - /// - public const string REQUESTTYPE = "RequestType"; - /// - /// 日志 LogList - /// - public const string LOGLIST = "LogList"; - /// - /// 异常 Exception - /// - public const string EXCEPTION = "Exception"; - /// - /// 执行次数 - /// - public const string RUNNUMBER = "RunNumber"; - /// - /// 任务结束时间 - /// - public const string ENDAT = "EndAt"; - } - - /// - /// http请求类型 - /// - public enum RequestTypeEnum - { - None = 0, - Get = 1, - Post = 2, - Put = 3, - Delete = 4 - } - - /// - /// 触发器类型 - /// - public enum TriggerTypeEnum - { - None = 0, - Simple = 1, - Cron = 2 - } -} diff --git a/backend/Dilon.Core/Service/Timer/SysTimerService.cs b/backend/Dilon.Core/Service/Timer/SysTimerService.cs index fee80c263280646320aa598c3e4c660085f7ee76..0c8ba52bc696c3b3063349a20fc744089a961f5a 100644 --- a/backend/Dilon.Core/Service/Timer/SysTimerService.cs +++ b/backend/Dilon.Core/Service/Timer/SysTimerService.cs @@ -3,9 +3,13 @@ using Furion.DatabaseAccessor.Extensions; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; +using Furion.JsonSerialization; +using Furion.RemoteRequest.Extensions; +using Furion.TaskScheduler; using Mapster; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -14,16 +18,14 @@ namespace Dilon.Core.Service /// /// 任务调度服务 /// - [ApiDescriptionSettings(Name = "sysTimer", Order = 100)] + [ApiDescriptionSettings(Name = "Timer", Order = 100)] public class SysTimerService : ISysTimerService, IDynamicApiController, IScoped { private readonly IRepository _sysTimerRep; // 任务表仓储 - private readonly SchedulerCenter _schedulerCenter; - public SysTimerService(IRepository sysTimerRep, SchedulerCenter schedulerCenter) + public SysTimerService(IRepository sysTimerRep) { _sysTimerRep = sysTimerRep; - _schedulerCenter = schedulerCenter; } /// @@ -32,21 +34,27 @@ namespace Dilon.Core.Service /// /// [HttpGet("/sysTimers/page")] - public async Task GetJobPageList([FromQuery] JobInput input) + public async Task GetTimerPageList([FromQuery] JobInput input) { - var jobList = await _schedulerCenter.GetJobList(); + var workers = SpareTime.GetWorkers().ToList(); var jobName = !string.IsNullOrEmpty(input.JobName?.Trim()); var timers = await _sysTimerRep.DetachedEntities .Where((jobName, u => EF.Functions.Like(u.JobName, $"%{input.JobName.Trim()}%"))) - .Select(u => u.Adapt()) + .Select(u => u.Adapt()) .ToPagedListAsync(input.PageNo, input.PageSize); timers.Items.ToList().ForEach(u => { - u.DisplayState = jobList.Find(m => m.JobName == u.JobName)?.DisplayState; + var timer = workers.FirstOrDefault(m => m.WorkerName == u.JobName); + if (timer != null) + { + u.TimerStatus = timer.Status; + u.RunNumber = timer.Tally; + u.Exception = ""; // JSON.Serialize(timer.Exception); + } }); - return XnPageResult.PageResult(timers); + return XnPageResult.PageResult(timers); } /// @@ -55,7 +63,7 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysTimers/add")] - public async Task AddJob(JobInput input) + public async Task AddTimer(JobInput input) { var isExist = await _sysTimerRep.AnyAsync(u => u.JobName == input.JobName, false); if (isExist) @@ -64,8 +72,8 @@ namespace Dilon.Core.Service var timer = input.Adapt(); await _sysTimerRep.InsertAsync(timer); - // 添加到调度 - await _schedulerCenter.AddScheduleJobAsync(input); + // 添加到任务调度里 + AddTimerJob(input); } /// @@ -74,16 +82,16 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysTimers/delete")] - public async Task DeleteJob(DeleteJobInput input) + public async Task DeleteTimer(DeleteJobInput input) { var timer = await _sysTimerRep.FirstOrDefaultAsync(u => u.Id == input.Id); if (timer == null) throw Oops.Oh(ErrorCode.D1101); - await timer.DeleteNowAsync(); + await timer.DeleteAsync(); - // 从调度器里删除 - await _schedulerCenter.DeleteScheduleJobAsync(input); + // 从调度器里取消 + SpareTime.Cancel(timer.JobName); } /// @@ -92,21 +100,21 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysTimers/edit")] - public async Task UpdateJob(UpdateJobInput input) + public async Task UpdateTimber(UpdateJobInput input) { // 排除自己并且判断与其他是否相同 var isExist = await _sysTimerRep.AnyAsync(u => u.JobName == input.JobName && u.Id != input.Id, false); if (isExist) throw Oops.Oh(ErrorCode.D1100); - var timer = input.Adapt(); - await timer.UpdateNowAsync(ignoreNullValues: true); - - // 先从调度器里删除 + // 先从调度器里取消 var oldTimer = await _sysTimerRep.FirstOrDefaultAsync(u => u.Id == input.Id, false); - await _schedulerCenter.DeleteScheduleJobAsync(oldTimer.Adapt()); + SpareTime.Cancel(oldTimer.JobName); + + var timer = input.Adapt(); + await timer.UpdateAsync(ignoreNullValues: true); - // 再加到调度里 - await _schedulerCenter.AddScheduleJobAsync(timer.Adapt()); + // 再添加到任务调度里 + AddTimerJob(input); } /// @@ -126,9 +134,9 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysTimers/stop")] - public async Task StopScheduleJobAsync(JobInput input) + public void StopTimerJob(JobInput input) { - await _schedulerCenter.StopScheduleJobAsync(input); + SpareTime.Stop(input.JobName); } /// @@ -137,9 +145,66 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysTimers/start")] - public async Task TriggerJobAsync(JobInput input) + public void StartTimerJob(JobInput input) + { + var timer = SpareTime.GetWorkers().ToList().Find(u => u.WorkerName == input.JobName); + if (timer == null) + AddTimerJob(input); + else + SpareTime.Start(input.JobName); + } + + /// + /// 新增定时任务 + /// + /// + [NonAction] + public void AddTimerJob(JobInput input) { - await _schedulerCenter.TriggerJobAsync(input); + if (input.TimerType == SpareTimeTypes.Interval) + { + SpareTime.Do(input.Interval * 1000, async (timer, count) => + { + await InitTimerJob(input); + }, input.JobName, input.Remark, startNow: true); + } + else if (!string.IsNullOrEmpty(input.Cron)) + { + SpareTime.Do(input.Cron, async (timer, count) => + { + await InitTimerJob(input); + }, input.JobName, input.Remark, startNow: true); + } + } + + /// + /// 初始化定时任务 + /// + /// + /// + private async Task InitTimerJob(JobInput input) + { + var requestUrl = input.RequestUrl.Trim(); + requestUrl = requestUrl?.IndexOf("http") == 0 ? requestUrl : "http://" + requestUrl; + var requestParameters = input.RequestParameters; + var headersString = input.Headers; + var headers = string.IsNullOrEmpty(headersString) ? null : JSON.Deserialize>(headersString); + var requestType = input.RequestType; + switch (requestType) + { + case RequestTypeEnum.Get: + await requestUrl.SetHeaders(headers).GetAsync(); + break; + case RequestTypeEnum.Post: + await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PostAsync(); + break; + case RequestTypeEnum.Put: + await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PutAsync(); + break; + case RequestTypeEnum.Delete: + await requestUrl.SetHeaders(headers).DeleteAsync(); + break; + } } } } diff --git a/backend/Dilon.Core/Service/User/Dto/UserInput.cs b/backend/Dilon.Core/Service/User/Dto/UserInput.cs index eb1be62307d9c7022f94d8086f7422333ac5c846..a20afb3099d7152db747bb3bec4dd6d398a8b17f 100644 --- a/backend/Dilon.Core/Service/User/Dto/UserInput.cs +++ b/backend/Dilon.Core/Service/User/Dto/UserInput.cs @@ -61,7 +61,7 @@ namespace Dilon.Core.Service /// /// 状态-正常_0、停用_1、删除_2 /// - public virtual int Status { get; set; } + public virtual CommonStatus Status { get; set; } /// /// 员工信息 @@ -71,7 +71,7 @@ namespace Dilon.Core.Service /// /// 搜索状态(字典 0正常 1停用 2删除) /// - public int SearchStatus { get; set; } = -1; + public CommonStatus SearchStatus { get; set; } = CommonStatus.ENABLE; } public class AddUserInput : UserInput diff --git a/backend/Dilon.Core/Service/User/ISysUserService.cs b/backend/Dilon.Core/Service/User/ISysUserService.cs index 513349fd569876f743fbaf211f44bfde882ee77e..0535552b565cbb981e44f968fcf334b7bcbc2968 100644 --- a/backend/Dilon.Core/Service/User/ISysUserService.cs +++ b/backend/Dilon.Core/Service/User/ISysUserService.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; @@ -9,7 +10,8 @@ namespace Dilon.Core.Service Task AddUser(AddUserInput input); Task ChangeUserStatus(UpdateUserInput input); Task DeleteUser(DeleteUserInput input); - Task ExportUser([FromQuery] UserInput input); + Task ExportUser([FromQuery] UserInput input); + Task ImportUser(IFormFile file); Task GetUser([FromQuery] QueryUserInput input); Task GetUserById(long userId); Task> GetUserDataScopeIdList(); diff --git a/backend/Dilon.Core/Service/User/SysUserDataScopeService.cs b/backend/Dilon.Core/Service/User/SysUserDataScopeService.cs index 999b8f23f6454a0451251ae5f01e8f402a003627..e32961e3218e44d79f6eb538cf190c416c45f94d 100644 --- a/backend/Dilon.Core/Service/User/SysUserDataScopeService.cs +++ b/backend/Dilon.Core/Service/User/SysUserDataScopeService.cs @@ -25,12 +25,13 @@ namespace Dilon.Core.Service /// /// /// + [UnitOfWork] public async Task GrantData(UpdateUserInput input) { var dataScopes = await _sysUserDataScopeRep.Where(u => u.SysUserId == long.Parse(input.Id)).ToListAsync(); dataScopes.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); input.GrantOrgIdList.ForEach(u => @@ -39,7 +40,7 @@ namespace Dilon.Core.Service { SysUserId = long.Parse(input.Id), SysOrgId = u - }.InsertNow(); + }.Insert(); }); } @@ -65,7 +66,7 @@ namespace Dilon.Core.Service var dataScopes = await _sysUserDataScopeRep.Where(u => orgIdList.Contains(u.SysOrgId)).ToListAsync(); dataScopes.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } @@ -79,7 +80,7 @@ namespace Dilon.Core.Service var dataScopes = await _sysUserDataScopeRep.Where(u => u.SysUserId == userId).ToListAsync(); dataScopes.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } } diff --git a/backend/Dilon.Core/Service/User/SysUserRoleService.cs b/backend/Dilon.Core/Service/User/SysUserRoleService.cs index 6d1526e8349a779d690b7a787e7e23cb941ef8e8..11dba24d6f033a8591cab44ae89800d13df454da 100644 --- a/backend/Dilon.Core/Service/User/SysUserRoleService.cs +++ b/backend/Dilon.Core/Service/User/SysUserRoleService.cs @@ -38,12 +38,13 @@ namespace Dilon.Core.Service /// /// /// + [UnitOfWork] public async Task GrantRole(UpdateUserInput input) { var userRoles = await _sysUserRoleRep.Where(u => u.SysUserId == long.Parse(input.Id)).ToListAsync(); userRoles.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); input.GrantRoleIdList.ForEach(u => @@ -52,7 +53,7 @@ namespace Dilon.Core.Service { SysUserId = long.Parse(input.Id), SysRoleId = u - }.InsertNow(); + }.Insert(); }); } @@ -83,7 +84,7 @@ namespace Dilon.Core.Service var userRoles = await _sysUserRoleRep.Where(u => u.SysRoleId == roleId).ToListAsync(); userRoles.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } @@ -97,7 +98,7 @@ namespace Dilon.Core.Service var userRoles = await _sysUserRoleRep.Where(u => u.SysUserId == userId).ToListAsync(); userRoles.ForEach(u => { - u.DeleteNow(); + u.Delete(); }); } } diff --git a/backend/Dilon.Core/Service/User/SysUserService.cs b/backend/Dilon.Core/Service/User/SysUserService.cs index d7ca89c449bfe55a8839ff37b80bde61cc5f6023..22721925211ddb9c44ed8595c3598a053ea57512 100644 --- a/backend/Dilon.Core/Service/User/SysUserService.cs +++ b/backend/Dilon.Core/Service/User/SysUserService.cs @@ -4,11 +4,15 @@ using Furion.DataEncryption; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; +using Furion.Snowflake; using Mapster; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using MiniExcelLibs; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; @@ -27,13 +31,15 @@ namespace Dilon.Core.Service private readonly ISysEmpService _sysEmpService; private readonly ISysUserDataScopeService _sysUserDataScopeService; private readonly ISysUserRoleService _sysUserRoleService; + private readonly ISysOrgService _sysOrgService; public SysUserService(IRepository sysUserRep, IUserManager userManager, ISysCacheService sysCacheService, ISysEmpService sysEmpService, ISysUserDataScopeService sysUserDataScopeService, - ISysUserRoleService sysUserRoleService) + ISysUserRoleService sysUserRoleService, + ISysOrgService sysOrgService) { _sysUserRep = sysUserRep; _userManager = userManager; @@ -41,6 +47,7 @@ namespace Dilon.Core.Service _sysEmpService = sysEmpService; _sysUserDataScopeService = sysUserDataScopeService; _sysUserRoleService = sysUserRoleService; + _sysOrgService = sysOrgService; } /// @@ -59,15 +66,15 @@ namespace Dilon.Core.Service var sysOrgRep = Db.GetRepository(); var dataScopes = await GetUserDataScopeIdList(_userManager.UserId); var users = await _sysUserRep.DetachedEntities - .Join(sysEmpRep.AsQueryable(), u => u.Id, e => e.Id, (u, e) => new { u, e }) - .Join(sysOrgRep.AsQueryable(), n => n.e.OrgId, o => o.Id, (n, o) => new { n, o }) + .Join(sysEmpRep.DetachedEntities, u => u.Id, e => e.Id, (u, e) => new { u, e }) + .Join(sysOrgRep.DetachedEntities, n => n.e.OrgId, o => o.Id, (n, o) => new { n, o }) .Where(!string.IsNullOrEmpty(searchValue), x => (x.n.u.Account.Contains(input.SearchValue) || x.n.u.Name.Contains(input.SearchValue) || x.n.u.Phone.Contains(input.SearchValue))) .Where(!string.IsNullOrEmpty(pid), x => (x.n.e.OrgId == long.Parse(pid) || x.o.Pids.Contains($"[{pid.Trim()}]"))) .Where(input.SearchStatus >= 0, x => x.n.u.Status == input.SearchStatus) - .Where(!superAdmin, x => x.n.u.AdminType != (int)AdminType.SuperAdmin) + .Where(!superAdmin, x => x.n.u.AdminType != AdminType.SuperAdmin) .Where(!superAdmin && dataScopes.Count > 0, x => dataScopes.Contains(x.n.e.OrgId)) .Select(u => u.n.u.Adapt()).ToPagedListAsync(input.PageNo, input.PageSize); @@ -90,6 +97,7 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysUser/add")] + [UnitOfWork] public async Task AddUser(AddUserInput input) { // 数据范围检查 @@ -116,17 +124,18 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysUser/delete")] + [UnitOfWork] public async Task DeleteUser(DeleteUserInput input) { var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == long.Parse(input.Id)); - if (user.AdminType == (int)AdminType.SuperAdmin) + if (user.AdminType == AdminType.SuperAdmin) throw Oops.Oh(ErrorCode.D1014); // 数据范围检查 CheckDataScope(input); // 直接删除用户 - await user.DeleteNowAsync(); + await user.DeleteAsync(); // 删除员工及附属机构职位信息 await _sysEmpService.DeleteEmpInfoByUserId(user.Id); @@ -144,6 +153,7 @@ namespace Dilon.Core.Service /// /// [HttpPost("/sysUser/edit")] + [UnitOfWork] public async Task UpdateUser(UpdateUserInput input) { // 数据范围检查 @@ -154,7 +164,7 @@ namespace Dilon.Core.Service if (isExist) throw Oops.Oh(ErrorCode.D1003); var user = input.Adapt(); - await user.UpdateExcludeNowAsync(new[] { nameof(SysUser.Password), nameof(SysUser.Status), nameof(SysUser.AdminType) }, true); + await user.UpdateExcludeAsync(new[] { nameof(SysUser.Password), nameof(SysUser.Status), nameof(SysUser.AdminType) }, true); input.SysEmpParam.Id = user.Id.ToString(); // 更新员工及附属机构职位信息 await _sysEmpService.AddOrUpdate(input.SysEmpParam); @@ -170,7 +180,10 @@ namespace Dilon.Core.Service { var user = await _sysUserRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == long.Parse(input.Id)); var userDto = user.Adapt(); - userDto.SysEmpInfo = await _sysEmpService.GetEmpInfo(user.Id); + if (userDto != null) + { + userDto.SysEmpInfo = await _sysEmpService.GetEmpInfo(user.Id); + } return userDto; } @@ -183,7 +196,7 @@ namespace Dilon.Core.Service public async Task ChangeUserStatus(UpdateUserInput input) { var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == long.Parse(input.Id)); - if (user.AdminType == (int)AdminType.SuperAdmin) + if (user.AdminType == AdminType.SuperAdmin) throw Oops.Oh(ErrorCode.D1015); if (!Enum.IsDefined(typeof(CommonStatus), input.Status)) @@ -226,7 +239,7 @@ namespace Dilon.Core.Service public async Task UpdateUserInfo(UpdateUserInput input) { var user = input.Adapt(); - await user.UpdateNowAsync(); + await user.UpdateAsync(); } /// @@ -302,8 +315,8 @@ namespace Dilon.Core.Service var name = !string.IsNullOrEmpty(input.Name?.Trim()); return await _sysUserRep.DetachedEntities .Where(name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")) - .Where(u => u.Status != (int)CommonStatus.DELETED) - .Where(u => u.AdminType != (int)AdminType.SuperAdmin) + .Where(u => u.Status != CommonStatus.DELETED) + .Where(u => u.AdminType != AdminType.SuperAdmin) .Select(u => new { u.Id, @@ -312,14 +325,46 @@ namespace Dilon.Core.Service } /// - /// 用户导出(未实现) + /// 用户导出 /// /// /// [HttpGet("/sysUser/export")] - public async Task ExportUser([FromQuery] UserInput input) + public async Task ExportUser([FromQuery] UserInput input) + { + var users = _sysUserRep.DetachedEntities.AsQueryable(); + + var memoryStream = new MemoryStream(); + memoryStream.SaveAs(users); + memoryStream.Seek(0, SeekOrigin.Begin); + return await Task.FromResult(new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + { + FileDownloadName = "user.xlsx" + }); + } + + /// + /// 用户导入 + /// + /// + /// + [HttpPost("/sysUser/import")] + public async Task ImportUser(IFormFile file) { - await Task.CompletedTask; + var path = Path.Combine(Path.GetTempPath(), $"{IDGenerator.NextId()}.xlsx"); + using (var stream = File.Create(path)) + { + await file.CopyToAsync(stream); + } + + var rows = MiniExcel.Query(path); // 解析 + foreach (var row in rows) + { + var a = row.A; + var b = row.B; + // 入库等操作 + + } } /// @@ -343,14 +388,14 @@ namespace Dilon.Core.Service public async Task SaveAuthUserToUser(AuthUserInput authUser, UserInput sysUser) { var user = sysUser.Adapt(); - user.AdminType = (int)AdminType.None; // 非管理员 + user.AdminType = AdminType.None; // 非管理员 // oauth账号与系统账号判断 var isExist = await _sysUserRep.DetachedEntities.AnyAsync(u => u.Account == authUser.Username); user.Account = isExist ? authUser.Username + DateTime.Now.Ticks : authUser.Username; user.Name = user.NickName = authUser.Nickname; user.Email = authUser.Email; - user.Sex = (int)authUser.Gender; + user.Sex = authUser.Gender; await user.InsertAsync(); } @@ -365,16 +410,19 @@ namespace Dilon.Core.Service var dataScopes = await _sysCacheService.GetDataScope(userId); // 先从缓存里面读取 if (dataScopes == null || dataScopes.Count < 1) { - var orgId = await _sysEmpService.GetEmpOrgId(userId); - - // 获取该用户对应的数据范围集合 - var userDataScopeIdListForUser = await _sysUserDataScopeService.GetUserDataScopeIdList(userId); - - // 获取该用户的角色对应的数据范围集合 - var userDataScopeIdListForRole = await _sysUserRoleService.GetUserRoleDataScopeIdList(userId, orgId); - - dataScopes = userDataScopeIdListForUser.Concat(userDataScopeIdListForRole).Distinct().ToList(); // 并集 - + if (!_userManager.SuperAdmin) + { + var orgId = await _sysEmpService.GetEmpOrgId(userId); + // 获取该用户对应的数据范围集合 + var userDataScopeIdListForUser = await _sysUserDataScopeService.GetUserDataScopeIdList(userId); + // 获取该用户的角色对应的数据范围集合 + var userDataScopeIdListForRole = await _sysUserRoleService.GetUserRoleDataScopeIdList(userId, orgId); + dataScopes = userDataScopeIdListForUser.Concat(userDataScopeIdListForRole).Distinct().ToList(); // 并集 + } + else + { + dataScopes = await _sysOrgService.GetAllDataScopeIdList(); + } await _sysCacheService.SetDataScope(userId, dataScopes); // 缓存结果 } return dataScopes; diff --git a/backend/Dilon.Core/Util/ReflectionUtil.cs b/backend/Dilon.Core/Util/ReflectionUtil.cs new file mode 100644 index 0000000000000000000000000000000000000000..071c1b54aea3f4cd077860cbdd9215503a5f345b --- /dev/null +++ b/backend/Dilon.Core/Util/ReflectionUtil.cs @@ -0,0 +1,26 @@ +using System; +using System.Reflection; + +namespace Dilon.Core +{ + /// + /// 反射工具 + /// + public static class ReflectionUtil + { + /// + /// 获取字段特性 + /// + /// + /// + /// + public static T GetDescriptionValue(this FieldInfo field) where T : Attribute + { + // 获取字段的指定特性,不包含继承中的特性 + object[] customAttributes = field.GetCustomAttributes(typeof(T), false); + + // 如果没有数据返回null + return customAttributes.Length > 0 ? (T)customAttributes[0] : null; + } + } +} \ No newline at end of file diff --git a/backend/Dilon.Core/applicationconfig.json b/backend/Dilon.Core/applicationconfig.json index d847bedafee5e12e50ebb2e33f68ade46c057513..e4035019c1af32d90029255bada660f1e325399e 100644 --- a/backend/Dilon.Core/applicationconfig.json +++ b/backend/Dilon.Core/applicationconfig.json @@ -6,7 +6,7 @@ { "Group": "Default", "Title": "Admin.NET通用权限管理平台", - "Description": "前后端分离架构,开箱即用,紧随前沿技术。
后台.NET5平台基于Furion框架,前端基于XiaoNuo生态技术框架的vue版本。
Furion框架,让 .NET 开发更简单,更通用,更流行
XiaoNuo前端框架采用Vue2.x + AntDesign Vue pro1.x + Axios", + "Description": "前后端分离架构,开箱即用,紧随前沿技术。
https://gitee.com/zuohuaijun/Admin.NET", "Version": "1.0.0" } ] @@ -26,6 +26,9 @@ "CacheType": "MemoryCache", // RedisCache "RedisConnectionString": "127.0.0.1:6379,password=,defaultDatabase=2" }, + "SnowId": { + "WorkerId": "1" // 取值范围0~63,默认1 + }, "OAuth": { "Wechat": { "app_id": "wx2959fdd3abc05362", @@ -37,25 +40,25 @@ "UploadFile": { // 头像 "Avatar": { - "path": "/upload/avatar/", + "path": "Upload/Avatar", "maxSize": 1048576, "contentType": [ "image/jpg", "image/png", "image/jpeg", "image/gif" ] }, // 文档 "Document": { - "path": "/upload/document/", + "path": "Upload/Document", "maxSize": 1048576, "contentType": [ "image/jpg", "image/png", "image/jpeg", "image/gif", "image/bmp", "text/plain", "application/pdf", "application/msword", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.presentationml.presentation" ] }, // 商店 "Shop": { - "path": "/upload/shop/", + "path": "Upload/Shop", "maxSize": 1048576, "contentType": [ "image/jpg", "image/png", "image/jpeg", "image/gif" ] }, // 默认 "Default": { - "path": "/upload/default/", + "path": "Upload/Default", "maxSize": 1048576, "contentType": [ "image/jpg", "image/png", "image/jpeg", "image/gif", "image/bmp", "text/plain", "application/pdf", "application/msword", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.presentationml.presentation" ] } diff --git a/backend/Dilon.EntityFramework.Core/DbContexts/DefaultDbContext.cs b/backend/Dilon.EntityFramework.Core/DbContexts/DefaultDbContext.cs index 9917b83965fafafb7a28b470a3e3211b4543d7c6..fd668b84ecde2f3be2499954e8d39d4b3a2c0c9f 100644 --- a/backend/Dilon.EntityFramework.Core/DbContexts/DefaultDbContext.cs +++ b/backend/Dilon.EntityFramework.Core/DbContexts/DefaultDbContext.cs @@ -1,27 +1,43 @@ -using Dilon.Core; +using Dilon.Core; +using Dilon.Core.Entity; using Dilon.Core.Service; using Furion; using Furion.DatabaseAccessor; using Furion.FriendlyException; +using Furion.Snowflake; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Linq; +using System.Linq.Expressions; namespace Dilon.EntityFramework.Core { [AppDbContext("DefaultConnection", DbProvider.Sqlite)] - public class DefaultDbContext : AppDbContext, IModelBuilderFilter + public class DefaultDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter { public DefaultDbContext(DbContextOptions options) : base(options) { // 启用实体数据更改监听 EnabledEntityChangedListener = true; + + // 忽略空值更新 + InsertOrUpdateIgnoreNullValues = true; } /// - /// 配置假删除过滤器 + /// 获取租户Id + /// + /// + public object GetTenantId() + { + if (App.User == null) return null; + return App.User.FindFirst(ClaimConst.TENANT_ID)?.Value; + } + + /// + /// 配置租户Id过滤器 /// /// /// @@ -29,28 +45,20 @@ namespace Dilon.EntityFramework.Core /// public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator) { - var expression = base.FakeDeleteQueryFilterExpression(entityBuilder, dbContext); - if (expression == null) return; - - entityBuilder.HasQueryFilter(expression); + if (entityBuilder.Metadata.ClrType.BaseType.Name == typeof(DBEntityTenant).Name) + entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, dbContext)); } - /// - /// 重写实体保存之前 - /// - /// - /// protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult result) { + // 获取当前事件对应上下文 var dbContext = eventData.Context; - // 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环) var entities = dbContext.ChangeTracker.Entries() .Where(u => u.Entity.GetType() != typeof(SysLogAudit) && u.Entity.GetType() != typeof(SysLogOp) && u.Entity.GetType() != typeof(SysLogVis) && (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)) .ToList(); if (entities == null || entities.Count < 1) return; - // 判断是否是演示环境 var demoEnvFlag = App.GetService().GetDemoEnvFlag().GetAwaiter().GetResult(); if (demoEnvFlag) @@ -60,59 +68,73 @@ namespace Dilon.EntityFramework.Core throw Oops.Oh(ErrorCode.D1200); } - var userManager = App.GetService(); - var userId = userManager?.UserId; + // 当前操作者信息 + var userId = App.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + var userName = App.User.FindFirst(ClaimConst.CLAINM_ACCOUNT)?.Value; - // 获取所有已更改的实体 foreach (var entity in entities) { - if (entity.Entity.GetType().IsSubclassOf(typeof(DEntityBase))) + if (entity.Entity.GetType().IsSubclassOf(typeof(DBEntityTenant))) + { + var obj = entity.Entity as DBEntityTenant; + switch (entity.State) + { + // 自动设置租户Id + case EntityState.Added: + var tenantId = entity.Property(nameof(Entity.TenantId)).CurrentValue; + if (tenantId == null || (long)tenantId == 0) + entity.Property(nameof(Entity.TenantId)).CurrentValue = long.Parse(GetTenantId().ToString()); + + obj.Id = obj.Id == 0 ? IDGenerator.NextId() : obj.Id; + obj.CreatedTime = DateTimeOffset.Now; + if (!string.IsNullOrEmpty(userId)) + { + obj.CreatedUserId = long.Parse(userId); + obj.CreatedUserName = userName; + } + break; + // 排除租户Id + case EntityState.Modified: + entity.Property(nameof(Entity.TenantId)).IsModified = false; + obj.UpdatedTime = DateTimeOffset.Now; + obj.UpdatedUserId = long.Parse(userId); + obj.UpdatedUserName = userName; + break; + } + } + else if (entity.Entity.GetType().IsSubclassOf(typeof(DEntityBase))) { var obj = entity.Entity as DEntityBase; if (entity.State == EntityState.Added) { + obj.Id = IDGenerator.NextId(); obj.CreatedTime = DateTimeOffset.Now; - obj.CreatedUserId = userId; + if (!string.IsNullOrEmpty(userId)) + { + obj.CreatedUserId = long.Parse(userId); + obj.CreatedUserName = userName; + } } else if (entity.State == EntityState.Modified) { obj.UpdatedTime = DateTimeOffset.Now; - obj.UpdatedUserId = userId; + obj.UpdatedUserId = long.Parse(userId); + obj.UpdatedUserName = userName; } } - - //// 获取实体当前(现在)的值 - //var currentValues = entity.CurrentValues; - //// 获取数据库中实体的值 - //var databaseValues = entity.GetDatabaseValues(); - - //// 获取所有实体有效属性,排除 [NotMapper] 属性 - //var props = entity.OriginalValues.Properties; - //foreach (var prop in props) - //{ - // var propName = prop.Name; // 获取属性名 - // var newValue = currentValues[propName]; // 获取现在的实体值 - - // object oldValue = null; - // // 如果是新增数据,则 databaseValues 为空,所以需要判断一下 - // if (databaseValues != null) - // oldValue = databaseValues[propName]; - - // if ((newValue == oldValue) || (newValue != null && newValue.Equals(oldValue))) continue; - // // 插入审计日志表 - // dbContext.AddAsync(new SysLogAudit - // { - // TableName = entity.Entity.GetType().Name, // 获取实体类型(表名) - // ColumnName = propName, - // NewValue = newValue?.ToString(), - // OldValue = oldValue?.ToString(), - // CreatedTime = DateTime.Now, - // UserId = userId, - // UserName = userName, - // Operate = entity.State.ToString() // 操作方式:新增、更新、删除 - // }); - //} } } + + /// + /// 配置假删除过滤器 + /// + /// + /// + /// + /// + protected override LambdaExpression FakeDeleteQueryFilterExpression(EntityTypeBuilder entityBuilder, DbContext dbContext, string isDeletedKey = null) + { + return base.FakeDeleteQueryFilterExpression(entityBuilder, dbContext, isDeletedKey); + } } } \ No newline at end of file diff --git a/backend/Dilon.EntityFramework.Core/DbContexts/MultiTenantDbContext.cs b/backend/Dilon.EntityFramework.Core/DbContexts/MultiTenantDbContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..ad712e00fde209499f48bdf7e1a3215da8ad3dde --- /dev/null +++ b/backend/Dilon.EntityFramework.Core/DbContexts/MultiTenantDbContext.cs @@ -0,0 +1,67 @@ +using Dilon.Core; +using Dilon.Core.Service; +using Furion; +using Furion.DatabaseAccessor; +using Furion.FriendlyException; +using Furion.Snowflake; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using System; +using System.Linq; + +namespace Dilon.EntityFramework.Core +{ + [AppDbContext("MultiTenantConnection", DbProvider.Sqlite)] + public class MultiTenantDbContext : AppDbContext + { + public MultiTenantDbContext(DbContextOptions options) : base(options) + { + + } + + protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult result) + { + // 获取所有已更改的实体 + var entities = eventData.Context.ChangeTracker.Entries() + .Where(u => u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added) + .ToList(); + + // 判断是否是演示环境 + var demoEnvFlag = App.GetService().GetDemoEnvFlag().GetAwaiter().GetResult(); + if (demoEnvFlag) + { + var sysUser = entities.Find(u => u.Entity.GetType() == typeof(SysUser)); + if (sysUser == null || string.IsNullOrEmpty((sysUser.Entity as SysUser).LastLoginTime.ToString())) // 排除登录 + throw Oops.Oh(ErrorCode.D1200); + } + + // 当前操作用户信息 + var userId = App.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + var userName = App.User.FindFirst(ClaimConst.CLAINM_ACCOUNT)?.Value; + + foreach (var entity in entities) + { + if (entity.Entity.GetType().IsSubclassOf(typeof(DEntityBase))) + { + var obj = entity.Entity as DEntityBase; + if (entity.State == EntityState.Added) + { + obj.Id = IDGenerator.NextId(); + obj.CreatedTime = DateTimeOffset.Now; + if (!string.IsNullOrEmpty(userId)) + { + obj.CreatedUserId = long.Parse(userId); + obj.CreatedUserName = userName; + } + } + else if (entity.State == EntityState.Modified) + { + obj.UpdatedTime = DateTimeOffset.Now; + obj.UpdatedUserId = long.Parse(userId); + obj.UpdatedUserName = userName; + } + } + } + } + } +} \ No newline at end of file diff --git a/backend/Dilon.EntityFramework.Core/DbContexts/README.md b/backend/Dilon.EntityFramework.Core/DbContexts/README.md new file mode 100644 index 0000000000000000000000000000000000000000..31aea87359c2a69821a2c7bb66ecb9c6a810b3aa --- /dev/null +++ b/backend/Dilon.EntityFramework.Core/DbContexts/README.md @@ -0,0 +1,9 @@ +1、迁移默认数据库命令 +Add-Migration Init -Context DefaultDbContext +update-database -Context DefaultDbContext + +2、迁移租户数据库命令 +Add-Migration Init -Context MultiTenantDbContext +update-database -Context MultiTenantDbContext + +dotnet run --urls="http://*:5566" diff --git a/backend/Dilon.EntityFramework.Core/Dilon.EntityFramework.Core.csproj b/backend/Dilon.EntityFramework.Core/Dilon.EntityFramework.Core.csproj index 21c035860651b77bd6ebdbf6d3690b1f2c1718d5..c1c63467442729c694a5c6f55b0813b4fee5d663 100644 --- a/backend/Dilon.EntityFramework.Core/Dilon.EntityFramework.Core.csproj +++ b/backend/Dilon.EntityFramework.Core/Dilon.EntityFramework.Core.csproj @@ -9,7 +9,7 @@ - + diff --git a/backend/Dilon.EntityFramework.Core/Startup.cs b/backend/Dilon.EntityFramework.Core/Startup.cs index 54af8a5fff2aeaf1e7ee1085b8dacca25f413d4e..ea8d36ee38903755c21fc0928d7dc073c7b5ea34 100644 --- a/backend/Dilon.EntityFramework.Core/Startup.cs +++ b/backend/Dilon.EntityFramework.Core/Startup.cs @@ -1,4 +1,9 @@ using Furion; +using Furion.DatabaseAccessor; +using Furion.DependencyInjection; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace Dilon.EntityFramework.Core @@ -9,8 +14,21 @@ namespace Dilon.EntityFramework.Core { services.AddDatabaseAccessor(options => { - options.AddDbPool(); + options.CustomizeMultiTenants(); // 自定义租户 + + options.AddDb(); + options.AddDb(); }, "Dilon.Database.Migrations"); } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + //// 自动迁移数据库(update-database命令) + //Scoped.Create((_, scope) => + //{ + // var context = scope.ServiceProvider.GetRequiredService(); + // context.Database.Migrate(); + //}); + } } } \ No newline at end of file diff --git a/backend/Dilon.EntityFramework.Core/dbsettings.json b/backend/Dilon.EntityFramework.Core/dbsettings.json index d651e03611bbc381318f5cdf0cef5d16035d9f12..be4d135c7950b921df862f28fd67d9327182fdeb 100644 --- a/backend/Dilon.EntityFramework.Core/dbsettings.json +++ b/backend/Dilon.EntityFramework.Core/dbsettings.json @@ -1,5 +1,7 @@ { "ConnectionStrings": { - "DefaultConnection": "Data Source=./Dilon.db" + "DefaultConnection": "Data Source=./Dilon.db", + "MultiTenantConnection": "Data Source=./Dilon_SaaS.db", + "PgSqlConnection": "HOST=127.0.0.1;PORT=5432;DATABASE=dilon;PASSWORD=123qwe;USER ID=postgres;", } } \ No newline at end of file diff --git a/backend/Dilon.Web.Core/Handlers/JwtHandler.cs b/backend/Dilon.Web.Core/Handlers/JwtHandler.cs index 8c8c766e847c1c0226d713ebe450ffac0c03a896..e9a20848562990831314f30fd00e2dab4804e634 100644 --- a/backend/Dilon.Web.Core/Handlers/JwtHandler.cs +++ b/backend/Dilon.Web.Core/Handlers/JwtHandler.cs @@ -5,6 +5,7 @@ using Furion.Authorization; using Furion.DataEncryption; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; +using System.Collections.Generic; using System.Threading.Tasks; namespace Dilon.Web.Core @@ -52,6 +53,14 @@ namespace Dilon.Web.Core // 路由名称 var routeName = httpContext.Request.Path.Value.Substring(1).Replace("/", ":"); + // 默认路由(获取登录用户信息) + var defalutRoute = new List() + { + "getLoginUser" + }; + + if (defalutRoute.Contains(routeName)) return true; + // 获取用户权限集合(按钮或API接口) var permissionList = await App.GetService().GetLoginPermissionList(userManager.UserId); diff --git a/backend/Dilon.Web.Core/Startup.cs b/backend/Dilon.Web.Core/Startup.cs index bdb6413949b39b8eee084429e089108a1ff719bd..6eba93c8a825fb8fb2713e1b25efc89f470a03c8 100644 --- a/backend/Dilon.Web.Core/Startup.cs +++ b/backend/Dilon.Web.Core/Startup.cs @@ -1,4 +1,4 @@ -using Dilon.Core; +using Dilon.Core; using Furion; using Furion.Snowflake; using Microsoft.AspNetCore.Builder; @@ -25,12 +25,18 @@ namespace Dilon.Web.Core services.AddControllersWithViews() .AddMvcFilter() .AddInjectWithUnifyResult() - .AddFriendlyException() // 注册友好异常服务 .AddJsonOptions(options => { + //options.JsonSerializerOptions.DefaultBufferSize = 10_0000;//返回较大数据数据序列化时会截断,原因:默认缓冲区大小(以字节为单位)为16384。 options.JsonSerializerOptions.Converters.AddDateFormatString("yyyy-MM-dd HH:mm:ss"); - //options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; // 忽略循环引用 + //options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; // 忽略循环引用 仅.NET 6支持 }); + + services.AddViewEngine(); + + // 设置雪花id的workerId,确保每个实例workerId都应不同 + var workerId = ushort.Parse(App.Configuration["SnowId:WorkerId"] ?? "1"); + IDGenerator.SetIdGenerator(new IDGeneratorOptions { WorkerId = workerId }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) @@ -48,7 +54,7 @@ namespace Dilon.Web.Core // 添加状态码拦截中间件 app.UseUnifyResultStatusCodes(); - app.UseHttpsRedirection(); + app.UseHttpsRedirection(); // 强制https app.UseStaticFiles(); // Serilog请求日志中间件---必须在 UseStaticFiles 和 UseRouting 之间 diff --git a/backend/Dilon.Web.Entry/Dilon.Web.Entry.csproj b/backend/Dilon.Web.Entry/Dilon.Web.Entry.csproj index e42a370af47776eae481ca839be45d30cc5883b8..7e5dfcdfa59db7ac91f508cb923d8a55f0864932 100644 --- a/backend/Dilon.Web.Entry/Dilon.Web.Entry.csproj +++ b/backend/Dilon.Web.Entry/Dilon.Web.Entry.csproj @@ -6,11 +6,19 @@ - + + + + + + + + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -21,9 +29,46 @@ + + Always + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + diff --git a/backend/Dilon.Web.Entry/Dilon.db b/backend/Dilon.Web.Entry/Dilon.db index 0f18c402fb6675a081b2e63319db4728fd1fd23a..17c45ada9f3b5030c219d95f0c90b1e3d5c80b62 100644 Binary files a/backend/Dilon.Web.Entry/Dilon.db and b/backend/Dilon.Web.Entry/Dilon.db differ diff --git a/backend/Dilon.Web.Entry/Dilon_SaaS.db b/backend/Dilon.Web.Entry/Dilon_SaaS.db new file mode 100644 index 0000000000000000000000000000000000000000..02689200ccba2b53592e6cf74be342daf0ebe6d6 Binary files /dev/null and b/backend/Dilon.Web.Entry/Dilon_SaaS.db differ diff --git a/backend/Dilon.Web.Entry/Program.cs b/backend/Dilon.Web.Entry/Program.cs index 3d78e19efda3a40599ee7454667759e0278937dd..0769b5bf82bb01cd8b6b161f7f7b4d336b5118f7 100644 --- a/backend/Dilon.Web.Entry/Program.cs +++ b/backend/Dilon.Web.Entry/Program.cs @@ -15,8 +15,8 @@ namespace Dilon.Web.Entry .ConfigureWebHostDefaults(webBuilder => { webBuilder.Inject() - .UseStartup(); - }) - .UseSerilogDefault(); + .UseStartup() + .UseSerilogDefault(); + }); } } diff --git a/backend/Dilon.Web.Entry/Properties/launchSettings.json b/backend/Dilon.Web.Entry/Properties/launchSettings.json index dfaf76fcabbe75fb51bfa341c01d71ec38754194..ae933dd9529453ab648bb31695e89ea9a36780f8 100644 --- a/backend/Dilon.Web.Entry/Properties/launchSettings.json +++ b/backend/Dilon.Web.Entry/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://127.0.0.1:5566", + "applicationUrl": "http://localhost:5566", "sslPort": 0 } }, diff --git a/backend/Dilon.Web.Entry/appsettings.json b/backend/Dilon.Web.Entry/appsettings.json index 03a0cca982fecbdcd1211677b839cf66f71c3f2e..9491da84144493f4b592f986d7d63a8b8c6b79ef 100644 --- a/backend/Dilon.Web.Entry/appsettings.json +++ b/backend/Dilon.Web.Entry/appsettings.json @@ -19,7 +19,7 @@ { "Name": "File", "Args": { - "path": "Logs/.log", + "path": "logs/.log", "rollingInterval": "Day", "outputTemplate": "【时间】{Timestamp:yyyy-MM-dd HH:mm:ss,fff}{NewLine}【等级】{Level:u3}{NewLine}【消息】{Message:lj}{NewLine}{NewLine}" } diff --git "a/backend/Dilon.Core/Captcha/ClickWord/Data/Font/\347\253\231\351\205\267\351\205\267\351\273\221\344\275\223.ttf" "b/backend/Dilon.Web.Entry/wwwroot/Captcha/Font/\347\253\231\351\205\267\351\205\267\351\273\221\344\275\223.ttf" similarity index 100% rename from "backend/Dilon.Core/Captcha/ClickWord/Data/Font/\347\253\231\351\205\267\351\205\267\351\273\221\344\275\223.ttf" rename to "backend/Dilon.Web.Entry/wwwroot/Captcha/Font/\347\253\231\351\205\267\351\205\267\351\273\221\344\275\223.ttf" diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/1.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/1.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/1.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/1.jpg diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/2.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/2.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/2.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/2.jpg diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/3.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/3.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/3.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/3.jpg diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/4.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/4.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/4.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/4.jpg diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/5.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/5.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/5.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/5.jpg diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/6.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/6.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/6.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/6.jpg diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/7.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/7.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/7.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/7.jpg diff --git a/backend/Dilon.Core/Captcha/ClickWord/Data/Image/8.jpg b/backend/Dilon.Web.Entry/wwwroot/Captcha/Image/8.jpg similarity index 100% rename from backend/Dilon.Core/Captcha/ClickWord/Data/Image/8.jpg rename to backend/Dilon.Web.Entry/wwwroot/Captcha/Image/8.jpg diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/IService.cs.vm b/backend/Dilon.Web.Entry/wwwroot/Template/IService.cs.vm new file mode 100644 index 0000000000000000000000000000000000000000..6dbfd24741bace2a638c1b6bd7851e8b6da8bf80 --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/IService.cs.vm @@ -0,0 +1,16 @@ +using Dilon.Core; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; + +namespace @Model.NameSpace +{ + public interface I@(@Model.ClassName)Service + { + Task Add(Add@(@Model.ClassName)Input input); + Task Delete(Delete@(@Model.ClassName)Input input); + Task<@(@Model.ClassName)> Get([FromQuery] Querye@(@Model.ClassName)Input input); + Task List([FromQuery] @(@Model.ClassName)Input input); + Task Page([FromQuery] @(@Model.ClassName)Input input); + Task Update(Update@(@Model.ClassName)Input input); + } +} \ No newline at end of file diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/Input.cs.vm b/backend/Dilon.Web.Entry/wwwroot/Template/Input.cs.vm new file mode 100644 index 0000000000000000000000000000000000000000..5dd8d25384ad3294e1d0f006142b281418289197 --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/Input.cs.vm @@ -0,0 +1,69 @@ +using Dilon.Core; +using System; +using System.ComponentModel.DataAnnotations; + +namespace @Model.NameSpace +{ + /// + /// @(@Model.BusName)输入参数 + /// + public class @(@Model.ClassName)Input : PageInputBase + { +@foreach (var column in Model.TableField){ +if (@column.ColumnKey != "True"){ + @:/// + @:/// @column.ColumnComment + @:/// + @:public virtual @column.NetType @column.ColumnName { get; set; } + @: +} +} + } + + public class Add@(@Model.ClassName)Input : @(@Model.ClassName)Input + { +@foreach (var column in Model.TableField){ +if (@column.WhetherRequired == "Y"){ + @:/// + @:/// @column.ColumnComment + @:/// + @:[Required(ErrorMessage = "@(@column.ColumnComment)不能为空")] + @:public override @column.NetType @column.ColumnName { get; set; } + @: +} +} + } + + public class Delete@(@Model.ClassName)Input + { +@foreach (var column in Model.TableField){ +if (@column.ColumnKey == "True"){ + @:/// + @:/// @column.ColumnComment + @:/// + @:[Required(ErrorMessage = "@(@column.ColumnComment)不能为空")] + @:public @column.NetType @column.ColumnName { get; set; } + @: +} +} + } + + public class Update@(@Model.ClassName)Input : @(@Model.ClassName)Input + { +@foreach (var column in Model.TableField){ +if (@column.ColumnKey == "True"){ + @:/// + @:/// @column.ColumnComment + @:/// + @:[Required(ErrorMessage = "@(@column.ColumnComment)不能为空")] + @:public @column.NetType @column.ColumnName { get; set; } + @: +} +} + } + + public class Querye@(@Model.ClassName)Input : Delete@(@Model.ClassName)Input + { + + } +} diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/Manage.js.vm b/backend/Dilon.Web.Entry/wwwroot/Template/Manage.js.vm new file mode 100644 index 0000000000000000000000000000000000000000..c9cbceef5798b351f077a2f05776e53d9f1fadcb --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/Manage.js.vm @@ -0,0 +1,66 @@ +import { axios } from '@@/utils/request' + +/** + * 查询@(@Model.BusName) + * + * @@author @Model.AuthorName + */ +export function @(@Model.ClassName)Page (parameter) { + return axios({ + url: '/@Model.ClassName/page', + method: 'get', + params: parameter + }) +} + +/** + * @(@Model.BusName)列表 + * + * @@author @Model.AuthorName + */ +export function @(@Model.ClassName)List (parameter) { + return axios({ + url: '/@Model.ClassName/list', + method: 'get', + params: parameter + }) +} + +/** + * 添加@(@Model.BusName) + * + * @@author @Model.AuthorName + */ +export function @(@Model.ClassName)Add (parameter) { + return axios({ + url: '/@Model.ClassName/add', + method: 'post', + data: parameter + }) +} + +/** + * 编辑@(@Model.BusName) + * + * @@author @Model.AuthorName + */ +export function @(@Model.ClassName)Edit (parameter) { + return axios({ + url: '/@Model.ClassName/edit', + method: 'post', + data: parameter + }) +} + +/** + * 删除@(@Model.BusName) + * + * @@author @Model.AuthorName + */ +export function @(@Model.ClassName)Delete (parameter) { + return axios({ + url: '/@Model.ClassName/delete', + method: 'post', + data: parameter + }) +} diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/Output.cs.vm b/backend/Dilon.Web.Entry/wwwroot/Template/Output.cs.vm new file mode 100644 index 0000000000000000000000000000000000000000..6a1d40b7eafbf8670af1ce591d5d6f494dc693d9 --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/Output.cs.vm @@ -0,0 +1,18 @@ +using System; + +namespace @Model.NameSpace +{ + /// + /// @(@Model.BusName)输出参数 + /// + public class @(@Model.ClassName)Output + { +@foreach (var column in Model.TableField){ + @:/// + @:/// @column.ColumnComment + @:/// + @:public @column.NetType @column.ColumnName { get; set; } + @: +} + } +} diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/Service.cs.vm b/backend/Dilon.Web.Entry/wwwroot/Template/Service.cs.vm new file mode 100644 index 0000000000000000000000000000000000000000..30b1c0e91bcc8ba6c645a49f38fb05bb760cbb63 --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/Service.cs.vm @@ -0,0 +1,117 @@ +using Dilon.Core; +using Furion.DatabaseAccessor; +using Furion.DatabaseAccessor.Extensions; +using Furion.DependencyInjection; +using Furion.DynamicApiController; +using Mapster; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Threading.Tasks; + +namespace @Model.NameSpace +{ + /// + /// @(@Model.BusName)服务 + /// + [ApiDescriptionSettings(Name = "@Model.ClassName", Order = 100)] + public class @(@Model.ClassName)Service : I@(@Model.ClassName)Service, IDynamicApiController, ITransient + { + private readonly IRepository<@(@Model.ClassName)> _rep; + + public @(@Model.ClassName)Service(IRepository<@(@Model.ClassName)> rep) + { + _rep = rep; + } + + /// + /// 分页查询@(@Model.BusName) + /// + /// + /// + [HttpGet("/@Model.ClassName/page")] + public async Task Page([FromQuery] @(@Model.ClassName)Input input) + { + var entities = await _rep.DetachedEntities +@foreach (var column in Model.TableField){ +if (@column.QueryWhether == "Y"){ +if (@column.NetType == "string"){ +if(@column.QueryType == "like"){ + @:.Where(!string.IsNullOrEmpty(input.@column.ColumnName), u => EF.Functions.Like(u.@(@column.ColumnName), $"%{input.@(@column.ColumnName).Trim()}%")) +}else{ + @:.Where(!string.IsNullOrEmpty(input.@column.ColumnName), u => u.@(@column.ColumnName) @column.QueryType input.@(@column.ColumnName)) +} +} +} +} + .ToPagedListAsync(input.PageNo, input.PageSize); + return XnPageResult<@(@Model.ClassName)>.PageResult(entities); + } + + /// + /// 增加@(@Model.BusName) + /// + /// + /// + [HttpPost("/@Model.ClassName/add")] + public async Task Add(Add@(@Model.ClassName)Input input) + { + var entity = input.Adapt<@(@Model.ClassName)>(); + await entity.InsertAsync(); + } + + /// + /// 删除@(@Model.BusName) + /// + /// + /// + [HttpPost("/@Model.ClassName/delete")] + public async Task Delete(Delete@(@Model.ClassName)Input input) + { +@foreach (var column in Model.TableField){ +if (@column.ColumnKey == "True"){ + @:var entity = await _rep.FirstOrDefaultAsync(u => u.@(@column.ColumnName) == input.@(@column.ColumnName)); +} +} + await entity.DeleteAsync(); + } + + /// + /// 更新@(@Model.BusName) + /// + /// + /// + [HttpPost("/@Model.ClassName/edit")] + public async Task Update(Update@(@Model.ClassName)Input input) + { + var entity = input.Adapt<@(@Model.ClassName)>(); + await entity.UpdateAsync(true); + } + + /// + /// 获取@(@Model.BusName) + /// + /// + /// + [HttpGet("/@Model.ClassName/detail")] + public async Task<@(@Model.ClassName)> Get([FromQuery] Querye@(@Model.ClassName)Input input) + { +@foreach (var column in Model.TableField){ +if (@column.ColumnKey == "True"){ + @:return await _rep.DetachedEntities.FirstOrDefaultAsync(u => u.@(@column.ColumnName) == input.@(@column.ColumnName)); +} +} + } + + /// + /// 获取@(@Model.BusName)列表 + /// + /// + /// + [HttpGet("/@Model.ClassName/list")] + public async Task List([FromQuery] @(@Model.ClassName)Input input) + { + return await _rep.DetachedEntities.ToListAsync(); + } + } +} diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/addForm.vue.vm b/backend/Dilon.Web.Entry/wwwroot/Template/addForm.vue.vm new file mode 100644 index 0000000000000000000000000000000000000000..a5b7c6fe355ea20b732293c27bcd7561fae8b9fb --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/addForm.vue.vm @@ -0,0 +1,198 @@ + + + diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/editForm.vue.vm b/backend/Dilon.Web.Entry/wwwroot/Template/editForm.vue.vm new file mode 100644 index 0000000000000000000000000000000000000000..c4860d0a164f2fd3b1abd7ec5bb0f4b3f9afffcf --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/editForm.vue.vm @@ -0,0 +1,261 @@ + + + diff --git a/backend/Dilon.Web.Entry/wwwroot/Template/index.vue.vm b/backend/Dilon.Web.Entry/wwwroot/Template/index.vue.vm new file mode 100644 index 0000000000000000000000000000000000000000..a170185093a827fbdbfbdc563e77c5a4e7d40c81 --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Template/index.vue.vm @@ -0,0 +1,324 @@ + + + diff --git a/backend/Dilon.Web.Entry/wwwroot/Upload/Default/148038614360133.txt b/backend/Dilon.Web.Entry/wwwroot/Upload/Default/148038614360133.txt new file mode 100644 index 0000000000000000000000000000000000000000..d800886d9c86731ae5c4a62b0b77c437015e00d2 --- /dev/null +++ b/backend/Dilon.Web.Entry/wwwroot/Upload/Default/148038614360133.txt @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/doc/img/1.png b/doc/img/1.png index b014f7fced3b4dbb88c3174c9aa571b93f2fc95b..fa41954097fcd4a7c4c3c791506f0fdcd50b4258 100644 Binary files a/doc/img/1.png and b/doc/img/1.png differ diff --git a/doc/img/10.png b/doc/img/10.png new file mode 100644 index 0000000000000000000000000000000000000000..e72f60e874b80e01ca456439740cce0fbe647100 Binary files /dev/null and b/doc/img/10.png differ diff --git a/doc/img/11.png b/doc/img/11.png new file mode 100644 index 0000000000000000000000000000000000000000..0a35d0270de9fff0e0b2b93876de4725fcb45aea Binary files /dev/null and b/doc/img/11.png differ diff --git a/doc/img/12.png b/doc/img/12.png new file mode 100644 index 0000000000000000000000000000000000000000..c97f80e514232ebea4f60cd0efff8db399514124 Binary files /dev/null and b/doc/img/12.png differ diff --git a/doc/img/13.png b/doc/img/13.png new file mode 100644 index 0000000000000000000000000000000000000000..2dde63edbe50536b176826c15af929cbb494bfb4 Binary files /dev/null and b/doc/img/13.png differ diff --git a/doc/img/14.png b/doc/img/14.png new file mode 100644 index 0000000000000000000000000000000000000000..4dd2c1f84848b65850457fdcda2b125d760551e5 Binary files /dev/null and b/doc/img/14.png differ diff --git a/doc/img/15.png b/doc/img/15.png new file mode 100644 index 0000000000000000000000000000000000000000..af80b0c2ef0215fbc3a4669ecb8b9849fb32d0e6 Binary files /dev/null and b/doc/img/15.png differ diff --git a/doc/img/2.png b/doc/img/2.png index a646c88c10fb47c0293d2bacfb3c0daf6271ea18..1a0fd7b75eb754e91d2e970af31ffa87960b0c29 100644 Binary files a/doc/img/2.png and b/doc/img/2.png differ diff --git a/doc/img/3.png b/doc/img/3.png index 47ff8dad7c85b6fca31191f3962970331acb1b0d..9640dce523f3b4672a5a1b15b03645e670dea171 100644 Binary files a/doc/img/3.png and b/doc/img/3.png differ diff --git a/doc/img/4.png b/doc/img/4.png index 0e2ea25a2f632f1798ec967737d9b21a8eb97b54..f2ad23f30511d5a65f7e99e63946a54877f70b96 100644 Binary files a/doc/img/4.png and b/doc/img/4.png differ diff --git a/doc/img/5.png b/doc/img/5.png index 40c972a4bfcc916a0d62d9b502ec0af26a743bb8..e608b679bdc9b04ba03fc3ea0e0ab552c9420c6a 100644 Binary files a/doc/img/5.png and b/doc/img/5.png differ diff --git a/doc/img/6.png b/doc/img/6.png index fb2171ed71bde211cc26792ddc23a582b3e1a345..4697e8138b962e4706ed93ee49df0d9a4e38319a 100644 Binary files a/doc/img/6.png and b/doc/img/6.png differ diff --git a/doc/img/7.png b/doc/img/7.png index 082a5bf97fa6ec7208b5eb39321a5db9f29c98a4..1b15b7901793801592fabf4c17cf28a518c049be 100644 Binary files a/doc/img/7.png and b/doc/img/7.png differ diff --git a/doc/img/8.png b/doc/img/8.png index aa19cc1a0905fa426e3d9299e13b84d49b260b0f..756e6990c6343e190e8105c1fac2997594490900 100644 Binary files a/doc/img/8.png and b/doc/img/8.png differ diff --git a/doc/img/9.png b/doc/img/9.png index c97f80e514232ebea4f60cd0efff8db399514124..a3833750a6830c4f76100d44c001108ac1bd20f7 100644 Binary files a/doc/img/9.png and b/doc/img/9.png differ diff --git a/frontend/docker/docker-compose.yml b/frontend/docker/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..1136a87f12052670020a8000798971c1ff89a9ac --- /dev/null +++ b/frontend/docker/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3.4' + +services: + nginx: + build: + context: ../ + dockerfile: ./docker/nginx/Dockerfile + image: admin_net_web:1.2 + ports: + - 81:80 + restart: "always" + volumes: + - node_modules:/build/node_modules:rw + # network_mode: host #宿主网络,与宿主机共享网络,安全性不佳,本地开发使用,淦,不支持windows,仅支持Linux +volumes: + node_modules: \ No newline at end of file diff --git a/frontend/docker/nginx/Dockerfile b/frontend/docker/nginx/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..2badc04ca08dbd40f6772d0ed22002d9484a52e1 --- /dev/null +++ b/frontend/docker/nginx/Dockerfile @@ -0,0 +1,32 @@ +# build +FROM node:latest AS builder + +# 切换编译目录 +WORKDIR /build +COPY ./ ./ +# 编译项目 测试 +RUN yarn config set registry https://registry.npm.taobao.org/ \ + && yarn install \ + && yarn run build:development + +# 编译项目 正式 +#RUN yarn config set registry https://registry.npm.taobao.org/ \ +# && yarn install \ +# && yarn run build + +# web +FROM nginx:alpine + +# 时区 +ENV TZ=Asia/Shanghai +RUN echo "http://mirrors.aliyun.com/alpine/v3.4/main/" > /etc/apk/repositories \ + && apk --no-cache add tzdata zeromq \ + && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ + && echo '$TZ' > /etc/timezone + +COPY ./docker/nginx/logs /var/log/nginx +COPY ./docker/nginx/vhost /etc/nginx/conf.d/ +COPY ./docker/nginx/nginx.conf /etc/nginx/nginx.conf + +# 拷贝项目 +COPY --from=builder /build/dist/ /var/www/html \ No newline at end of file diff --git a/frontend/docker/nginx/nginx.conf b/frontend/docker/nginx/nginx.conf new file mode 100644 index 0000000000000000000000000000000000000000..5f2842ec107ec5c86a518fd053d1a4b2e9292d5f --- /dev/null +++ b/frontend/docker/nginx/nginx.conf @@ -0,0 +1,21 @@ +user nginx; +worker_processes 1; +pid /var/run/nginx.pid; +error_log /var/log/nginx/nginx.error.log warn; +events { + worker_connections 1024; +} +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /dev/null; + #access_log /var/log/nginx/nginx.access.log main; + sendfile on; + #tcp_nopush on; + keepalive_timeout 65; + #gzip on; + include /etc/nginx/conf.d/*.conf; +} \ No newline at end of file diff --git a/frontend/docker/nginx/vhost/default.conf b/frontend/docker/nginx/vhost/default.conf new file mode 100644 index 0000000000000000000000000000000000000000..5ca558b7c2215bc8926b0cd02663abc963d2a501 --- /dev/null +++ b/frontend/docker/nginx/vhost/default.conf @@ -0,0 +1,30 @@ +server { + listen 80; + server_name localhost; + root /var/www/html; + index index.php index.html index.htm; + access_log /dev/null; + error_log /var/log/nginx/default.error.log warn; + + # redirect server error pages to the static page /50x.html + # + #error_page 500 502 503 504 /50x.html; + + location / { + root /var/www/html; + add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; + try_files $uri $uri/ /index.html; + } + + + location /api { + #如果服务器要获取客户端真实IP,可以用下三句设置主机头和客户端真实地址 + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + rewrite ^/api/(.*)$ /$1 break; #重写 + proxy_pass http://host.docker.internal:5566; # docker内访问宿主机(win或mac)----注意:宿主机需在hosts文件中增加一条 host.docker.internal 127.0.0.1 + # proxy_pass http://host.docker.internal:5566; # 生产环境改成真实后端地址 + } +} \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f2a4c6ba26751414e4ce0d603c042f776b1d04cb..6bfe967ce5a9670221e2e8014e14242a72ebc714 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -365,7 +365,6 @@ "version": "7.12.5", "resolved": "https://registry.npm.taobao.org/@babel/helper-module-imports/download/@babel/helper-module-imports-7.12.5.tgz?cache=0&sync_timestamp=1604441049232&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-module-imports%2Fdownload%2F%40babel%2Fhelper-module-imports-7.12.5.tgz", "integrity": "sha1-G/wCKfeUmI927QpNTpCGCFC1Tfs=", - "dev": true, "requires": { "@babel/types": "^7.12.5" } @@ -455,8 +454,7 @@ "@babel/helper-validator-identifier": { "version": "7.12.11", "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha1-yaHwIZF9y1zPDU5FPjmQIpgfye0=", - "dev": true + "integrity": "sha1-yaHwIZF9y1zPDU5FPjmQIpgfye0=" }, "@babel/helper-validator-option": { "version": "7.12.11", @@ -1220,7 +1218,6 @@ "version": "7.12.5", "resolved": "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.12.5.tgz?cache=0&sync_timestamp=1604441085826&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.12.5.tgz", "integrity": "sha1-QQ5+SHRB4bNgwpvnFdhw2bmFiC4=", - "dev": true, "requires": { "regenerator-runtime": "^0.13.4" }, @@ -1228,8 +1225,7 @@ "regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.7.tgz?cache=0&sync_timestamp=1595456117883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.13.7.tgz", - "integrity": "sha1-ysLazIoepnX+qrrriugziYrkb1U=", - "dev": true + "integrity": "sha1-ysLazIoepnX+qrrriugziYrkb1U=" } } }, @@ -1282,7 +1278,6 @@ "version": "7.12.12", "resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.12.12.tgz?cache=0&sync_timestamp=1608730513422&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.12.12.tgz", "integrity": "sha1-Rgim7DE6u9h6+lUATTc60EqWwpk=", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", "lodash": "^4.17.19", @@ -1698,6 +1693,15 @@ "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=", "dev": true }, + "@simonwep/pickr": { + "version": "1.7.4", + "resolved": "https://registry.npm.taobao.org/@simonwep/pickr/download/@simonwep/pickr-1.7.4.tgz", + "integrity": "sha1-sU/NlFiQOIuHDNbbTWx41THyUUE=", + "requires": { + "core-js": "^3.6.5", + "nanopop": "^2.1.0" + } + }, "@soda/friendly-errors-webpack-plugin": { "version": "1.8.0", "resolved": "https://registry.npm.taobao.org/@soda/friendly-errors-webpack-plugin/download/@soda/friendly-errors-webpack-plugin-1.8.0.tgz?cache=0&sync_timestamp=1607927401282&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40soda%2Ffriendly-errors-webpack-plugin%2Fdownload%2F%40soda%2Ffriendly-errors-webpack-plugin-1.8.0.tgz", @@ -2677,9 +2681,9 @@ } }, "vue-loader-v16": { - "version": "npm:vue-loader@16.1.2", - "resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-16.1.2.tgz", - "integrity": "sha1-XAO2xQ0qX5g8fOuhXFDXjKKymPQ=", + "version": "npm:vue-loader@16.2.0", + "resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-16.2.0.tgz", + "integrity": "sha1-BGpTMI3Ufljv4g3ewe3sAnzjtG4=", "dev": true, "optional": true, "requires": { @@ -3216,12 +3220,13 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "ant-design-vue": { - "version": "1.5.0-rc.6", - "resolved": "https://registry.npm.taobao.org/ant-design-vue/download/ant-design-vue-1.5.0-rc.6.tgz", - "integrity": "sha1-qWFlUOA4a/emsb8AquXK3BMVmWc=", + "version": "1.7.4", + "resolved": "https://registry.npm.taobao.org/ant-design-vue/download/ant-design-vue-1.7.4.tgz?cache=0&sync_timestamp=1616896240769&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fant-design-vue%2Fdownload%2Fant-design-vue-1.7.4.tgz", + "integrity": "sha1-hU6QmF3A+pzMbWgcEEVgwA6q+FU=", "requires": { "@ant-design/icons": "^2.1.1", "@ant-design/icons-vue": "^2.0.0", + "@simonwep/pickr": "~1.7.0", "add-dom-event-listener": "^1.0.2", "array-tree-filter": "^2.1.0", "async-validator": "^3.0.3", @@ -3247,7 +3252,7 @@ "resize-observer-polyfill": "^1.5.1", "shallow-equal": "^1.0.0", "shallowequal": "^1.0.2", - "vue-ref": "^1.0.4", + "vue-ref": "^2.0.0", "warning": "^4.0.0" } }, @@ -3640,7 +3645,6 @@ "version": "1.13.3", "resolved": "https://registry.npm.taobao.org/babel-plugin-import/download/babel-plugin-import-1.13.3.tgz?cache=0&sync_timestamp=1606209920171&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-plugin-import%2Fdownload%2Fbabel-plugin-import-1.13.3.tgz", "integrity": "sha1-nbu6fRrHK9QSkXqDDUReAJQdJtc=", - "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/runtime": "^7.0.0" @@ -11002,6 +11006,73 @@ "verror": "1.10.0" } }, + "k-form-design": { + "version": "3.7.3", + "resolved": "https://registry.npm.taobao.org/k-form-design/download/k-form-design-3.7.3.tgz", + "integrity": "sha1-aIuFh6+AxnlG6nXBS77swft2g5s=", + "requires": { + "ant-design-vue": "^1.7.2", + "babel-plugin-import": "^1.13.0", + "babel-polyfill": "^6.26.0", + "clipboard": "^2.0.6", + "core-js": "^2.6.5", + "moment": "^2.24.0", + "vue": "^2.6.10", + "vue-codemirror-lite": "^1.0.4", + "vue-quill-editor": "^3.0.6", + "vue-router": "^3.0.3", + "vuedraggable": "^2.23.2" + }, + "dependencies": { + "ant-design-vue": { + "version": "1.7.4", + "resolved": "https://registry.npm.taobao.org/ant-design-vue/download/ant-design-vue-1.7.4.tgz?cache=0&sync_timestamp=1616896240769&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fant-design-vue%2Fdownload%2Fant-design-vue-1.7.4.tgz", + "integrity": "sha1-hU6QmF3A+pzMbWgcEEVgwA6q+FU=", + "requires": { + "@ant-design/icons": "^2.1.1", + "@ant-design/icons-vue": "^2.0.0", + "@simonwep/pickr": "~1.7.0", + "add-dom-event-listener": "^1.0.2", + "array-tree-filter": "^2.1.0", + "async-validator": "^3.0.3", + "babel-helper-vue-jsx-merge-props": "^2.0.3", + "babel-runtime": "6.x", + "classnames": "^2.2.5", + "component-classes": "^1.2.6", + "dom-align": "^1.10.4", + "dom-closest": "^0.2.0", + "dom-scroll-into-view": "^2.0.0", + "enquire.js": "^2.1.6", + "intersperse": "^1.0.0", + "is-mobile": "^2.2.1", + "is-negative-zero": "^2.0.0", + "ismobilejs": "^1.0.0", + "json2mq": "^0.2.0", + "lodash": "^4.17.5", + "moment": "^2.21.0", + "mutationobserver-shim": "^0.3.2", + "node-emoji": "^1.10.0", + "omit.js": "^1.0.0", + "raf": "^3.4.0", + "resize-observer-polyfill": "^1.5.1", + "shallow-equal": "^1.0.0", + "shallowequal": "^1.0.2", + "vue-ref": "^2.0.0", + "warning": "^4.0.0" + } + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.12.tgz?cache=0&sync_timestamp=1617822387922&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.12.tgz", + "integrity": "sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw=" + }, + "vue-ref": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/vue-ref/download/vue-ref-2.0.0.tgz", + "integrity": "sha1-SDCE1zKr7RHaeWd4qCZqOvDqGpw=" + } + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npm.taobao.org/killable/download/killable-1.0.1.tgz", @@ -11882,6 +11953,11 @@ } } }, + "nanopop": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/nanopop/download/nanopop-2.1.0.tgz", + "integrity": "sha1-I0dlE87iQFiIr9LopLVAZrcLnmA=" + }, "native-request": { "version": "1.0.8", "resolved": "https://registry.npm.taobao.org/native-request/download/native-request-1.0.8.tgz?cache=0&sync_timestamp=1603410586468&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnative-request%2Fdownload%2Fnative-request-1.0.8.tgz", @@ -15799,8 +15875,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "to-object-path": { "version": "0.3.0", @@ -16551,9 +16626,9 @@ } }, "vue-ref": { - "version": "1.0.6", - "resolved": "https://registry.npm.taobao.org/vue-ref/download/vue-ref-1.0.6.tgz", - "integrity": "sha1-ubPX0OKQ7i/T1Q1de9rFIIBssmU=" + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/vue-ref/download/vue-ref-2.0.0.tgz", + "integrity": "sha1-SDCE1zKr7RHaeWd4qCZqOvDqGpw=" }, "vue-router": { "version": "3.4.9", diff --git a/frontend/package.json b/frontend/package.json index f971af6668af8f8e2d57489a7484b456b39d4757..ece0c8c37a1d91fcef23c988e3f04ed2efa8e39f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@antv/data-set": "^0.10.2", - "ant-design-vue": "1.5.0-rc.6", + "ant-design-vue": "1.7.4", "axios": "^0.19.0", "babel-polyfill": "^6.26.0", "clipboard": "^2.0.6", @@ -22,6 +22,7 @@ "font-awesome": "^4.7.0", "jquery": "^3.5.1", "jsbarcode": "^3.11.3", + "k-form-design": "^3.7.3", "lodash.clonedeep": "^4.5.0", "lodash.get": "^4.4.2", "lodash.pick": "^4.4.0", @@ -70,7 +71,7 @@ "prettier": "^1.18.2", "vue-svg-icon-loader": "^2.1.1", "vue-template-compiler": "^2.6.10", - "webpack-theme-color-replacer": "^1.2.17" + "webpack-theme-color-replacer": "1.3.18" }, "collective": { "type": "opencollective", diff --git a/frontend/src/api/modular/system/enumManage.js b/frontend/src/api/modular/system/enumManage.js new file mode 100644 index 0000000000000000000000000000000000000000..dd48818bb995a6e0f4e2cbde1e0411f53dddabdf --- /dev/null +++ b/frontend/src/api/modular/system/enumManage.js @@ -0,0 +1,29 @@ +import { axios } from '@/utils/request' + +/** + * 根据枚举名称获取枚举数据,返回格式为:[{code:"M",value:"男"},{code:"F",value:"女"}] + * + * @author taoran + * @date 2021-04-16 21:13/sysEnumData/list/{enumName} + */ +export function sysEnumDataList (parameter) { + return axios({ + url: '/sysEnumData/list', + method: 'get', + params: parameter + }) +} + +/** + * 根据实体名和字段名获取枚举数据 + * + * @author taoran + * @date 2021-04-16 21:13 + */ +export function sysEnumDataListByField (parameter) { + return axios({ + url: '/sysEnumData/listByFiled', + method: 'get', + params: parameter + }) +} diff --git a/frontend/src/api/modular/system/logManage.js b/frontend/src/api/modular/system/logManage.js index 3c3a041b760ccb973f147cbd5b88260f8671dadb..b1f2d52efba55eb3750762d62bbb732fc0849896 100644 --- a/frontend/src/api/modular/system/logManage.js +++ b/frontend/src/api/modular/system/logManage.js @@ -1,3 +1,11 @@ +/* + * @Author: your name + * @Date: 2021-04-17 17:45:37 + * @LastEditTime: 2021-04-17 18:03:59 + * @LastEditors: your name + * @Description: In User Settings Edit + * @FilePath: \frontend\src\api\modular\system\logManage.js + */ import { axios } from '@/utils/request' /** @@ -28,6 +36,20 @@ export function sysOpLogPage (parameter) { }) } +/** + * 查询异常日志 + * + * @author yubaoshan + * @date 2020/5/19 11:57 + */ +export function sysExLogPage (parameter) { + return axios({ + url: '/sysExLog/page', + method: 'get', + params: parameter + }) +} + /** * 清空访问日志 * @@ -55,3 +77,17 @@ export function sysOpLogDelete (parameter) { data: parameter }) } + +/** + * 清空异常日志 + * + * @author yubaoshan + * @date 2020/6/23 23:09 + */ + export function sysExLogDelete (parameter) { + return axios({ + url: '/sysExLog/delete', + method: 'post', + data: parameter + }) +} diff --git a/frontend/src/api/modular/system/tenantManage.js b/frontend/src/api/modular/system/tenantManage.js new file mode 100644 index 0000000000000000000000000000000000000000..6168e7ed30de2de07f03d40f3577ac726ef4e3bf --- /dev/null +++ b/frontend/src/api/modular/system/tenantManage.js @@ -0,0 +1,96 @@ +/** + * 租户 + */ +import { + axios +} from '@/utils/request' + +/** + * 租户列表 + * + */ +export function sysTenantPage(parameter) { + return axios({ + url: '/sysTenant/page', + method: 'get', + params: parameter + }) +} + +/** + * 新增租户 + * + */ +export function sysTenantAdd(parameter) { + return axios({ + url: '/sysTenant/add', + method: 'post', + data: parameter + }) +} + +/** + * 删除租户 + * + */ +export function sysTenantDelete(parameter) { + return axios({ + url: '/sysTenant/delete', + method: 'post', + data: parameter + }) +} + +/** + * 编辑租户 + * + */ +export function sysTenantEdit(parameter) { + return axios({ + url: '/sysTenant/edit', + method: 'post', + data: parameter + }) +} + +/** + * 拥有菜单 + * + * @author zuohuaijun + * @date 2021/04/22 10:30 + */ +export function sysTenantOwnMenu (parameter) { + return axios({ + url: '/sysTenant/ownMenu', + method: 'get', + params: parameter + }) +} + +/** + * 授权菜单 + * + * @author zuohuaijun + * @date 2021/04/22 10:30 + */ +export function sysTenantGrantMenu (parameter) { + return axios({ + url: '/sysTenant/grantMenu', + method: 'post', + data: parameter + }) +} + +/** + * 重置密码 + * + * @author zuohuaijun + * @date 2021/04/22 11:00 + */ +export function sysTenantResetPwd (parameter) { + return axios({ + url: '/sysTenant/resetPwd', + method: 'post', + data: parameter + }) +} diff --git a/frontend/src/api/modular/system/userManage.js b/frontend/src/api/modular/system/userManage.js index 3dce14c9e70ef4aa5da5b96a26202974aade95d1..f388b45d82ed325833b94d9e9b73c2d1f7d468ee 100644 --- a/frontend/src/api/modular/system/userManage.js +++ b/frontend/src/api/modular/system/userManage.js @@ -209,3 +209,32 @@ export function sysUserUpdateInfo (parameter) { data: parameter }) } + +/** + * 导出用户信息 + * + * @author zuohuaijun + * @date 2021/4/20 01:00 + */ +export function sysUserExport (parameter) { + return axios({ + url: '/sysUser/export', + method: 'get', + data: parameter, + responseType: 'blob' + }) +} + +/** + * 导入用户信息 + * + * @author zuohuaijun + * @date 2021/4/20 01:00 + */ +export function sysUserImport (parameter) { + return axios({ + url: '/sysUser/import', + method: 'post', + data: parameter + }) +} diff --git a/frontend/src/components/GlobalFooter/GlobalFooter.vue b/frontend/src/components/GlobalFooter/GlobalFooter.vue index 030dda849429065b0b0902625b414dcd68973659..58d4fedc421128bf443c7c6eecac021230ef503a 100644 --- a/frontend/src/components/GlobalFooter/GlobalFooter.vue +++ b/frontend/src/components/GlobalFooter/GlobalFooter.vue @@ -3,7 +3,7 @@ @@ -20,7 +20,7 @@ export default { diff --git a/frontend/src/views/system/log/exlog/details.vue b/frontend/src/views/system/log/exlog/details.vue new file mode 100644 index 0000000000000000000000000000000000000000..b9cb4b0f74dd0d40c0e763cc4627140d5b1c93e0 --- /dev/null +++ b/frontend/src/views/system/log/exlog/details.vue @@ -0,0 +1,77 @@ + + diff --git a/frontend/src/views/system/log/exlog/index.vue b/frontend/src/views/system/log/exlog/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..ca385ff7e0cf006866aa25bb6e23db998178e464 --- /dev/null +++ b/frontend/src/views/system/log/exlog/index.vue @@ -0,0 +1,229 @@ + + + diff --git a/frontend/src/views/system/log/oplog/details.vue b/frontend/src/views/system/log/oplog/details.vue index c7ddd8dfd611598ac5b5c353c643825f193a4039..4c0bedea224b81f5804e630b6dbcb5603dae767c 100644 --- a/frontend/src/views/system/log/oplog/details.vue +++ b/frontend/src/views/system/log/oplog/details.vue @@ -1,90 +1,52 @@ diff --git a/frontend/src/views/system/tenant/editForm.vue b/frontend/src/views/system/tenant/editForm.vue new file mode 100644 index 0000000000000000000000000000000000000000..1c4ee3d14e8e30a89804d9aa56838af3a59a785e --- /dev/null +++ b/frontend/src/views/system/tenant/editForm.vue @@ -0,0 +1,162 @@ + + + diff --git a/frontend/src/views/system/tenant/index.vue b/frontend/src/views/system/tenant/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..1005acb15a33fd0c99c6481261a315a6a575862b --- /dev/null +++ b/frontend/src/views/system/tenant/index.vue @@ -0,0 +1,200 @@ + + + diff --git a/frontend/src/views/system/tenant/tenantMenuForm.vue b/frontend/src/views/system/tenant/tenantMenuForm.vue new file mode 100644 index 0000000000000000000000000000000000000000..8cd498d3d513d2b16f62b346d695375dbf1eefad --- /dev/null +++ b/frontend/src/views/system/tenant/tenantMenuForm.vue @@ -0,0 +1,186 @@ + + + diff --git a/frontend/src/views/system/timers/addForm.vue b/frontend/src/views/system/timers/addForm.vue index 05c3db1ca24f225a0682ee71e1b64d2704a44c9d..123ed9d225a76bb7b8691f545be00177b9ccfa5d 100644 --- a/frontend/src/views/system/timers/addForm.vue +++ b/frontend/src/views/system/timers/addForm.vue @@ -15,8 +15,8 @@ - - + + @@ -40,32 +40,15 @@ - - - - - - - - - - - - - - - - Simple - Cron + + + Interval + Cron - - + - - - - - - - - - @@ -118,7 +92,6 @@ import { sysDictTypeDropDown } from '@/api/modular/system/dictManage' - import moment from 'moment' export default { data() { return { @@ -156,10 +129,7 @@ }, visible: false, confirmLoading: false, - beginTimeString: [], - endTimeString: [], - timeFormat: 'YYYY-MM-DD HH:mm:ss', - VisibleTriggerType: true, + VisibleTimerType: true, requestTypeDictTypeDropDown: [], formLoading: false, form: this.$form.createForm(this) @@ -173,22 +143,11 @@ this.formLoading = false this.sysDictTypeDropDown() - var beginTime = new Date() - if (beginTime != null) { - this.form.getFieldDecorator('beginTime', { - initialValue: moment(beginTime, this.timeFormat) - }) - } - this.beginTimeString = moment(beginTime).format(this.timeFormat) - this.form.getFieldDecorator('requestType', { initialValue: 2 }) - this.form.getFieldDecorator('triggerType', { - initialValue: 1 - }) - this.form.getFieldDecorator('jobGroup', { - initialValue: '默认分组' + this.form.getFieldDecorator('timerType', { + initialValue: 0 }) }, @@ -200,24 +159,10 @@ }) }, - onChangeTriggerType(e) { - this.VisibleTriggerType = e === 1 + onChangeTimerType(e) { + this.VisibleTimerType = e === 0 }, - onChangeBeginTime(date, dateString) { - if (date == null) { - this.beginTimeString = [] - } else { - this.beginTimeString = moment(date).format(this.timeFormat) - } - }, - onChangeEndTime(date, dateString) { - if (date == null) { - this.endTimeString = [] - } else { - this.endTimeString = moment(date).format(this.timeFormat) - } - }, handleSubmit() { const { form: { @@ -227,12 +172,6 @@ this.confirmLoading = true validateFields((errors, values) => { if (!errors) { - if (this.beginTimeString.length > 0) { - values.beginTime = this.beginTimeString - } - if (this.endTimeString.length > 0) { - values.endTime = this.endTimeString - } sysTimersAdd(values).then((res) => { if (res.success) { this.$message.success('新增成功') diff --git a/frontend/src/views/system/timers/editForm.vue b/frontend/src/views/system/timers/editForm.vue index a97d3f2a3ee7a7900dd0f34bac0b748f8fa46507..7e0c9f7f94f5496842b91605c1f846d4b4414df1 100644 --- a/frontend/src/views/system/timers/editForm.vue +++ b/frontend/src/views/system/timers/editForm.vue @@ -22,8 +22,8 @@ - - + + @@ -47,28 +47,15 @@ - - - - - - - - - - - - - - - - Simple - Cron + + + Interval + Cron - + - - - - - - - - - @@ -121,7 +99,6 @@ import { sysDictTypeDropDown } from '@/api/modular/system/dictManage' - import moment from 'moment' export default { data() { @@ -160,10 +137,7 @@ }, visible: false, confirmLoading: false, - beginTimeString: [], - endTimeString: [], - timeFormat: 'YYYY-MM-DD HH:mm:ss', - VisibleTriggerType: true, + VisibleTimerType: true, requestTypeDictTypeDropDown: [], formLoading: false, form: this.$form.createForm(this) @@ -177,18 +151,15 @@ this.sysDictTypeDropDown() // eslint-disable-next-line eqeqeq - this.VisibleTriggerType = record.triggerType == 1 + this.VisibleTimerType = record.timerType == 0 setTimeout(() => { this.form.setFieldsValue({ id: record.id, jobName: record.jobName, - jobGroup: record.jobGroup, requestUrl: record.requestUrl, requestType: record.requestType, - // beginTime: record.beginTime, - // endTime: record.endTime, - triggerType: record.triggerType, + timerType: record.timerType, cron: record.cron, interval: record.interval, headers: record.headers, @@ -196,19 +167,6 @@ remark: record.remark }) }, 100) - // 时间单独处理 - if (record.beginTime != null) { - this.form.getFieldDecorator('beginTime', { - initialValue: moment(record.beginTime, this.timeFormat) - }) - } - this.beginTimeString = moment(record.beginTime).format(this.timeFormat) - if (record.endTime != null) { - this.form.getFieldDecorator('endTime', { - initialValue: moment(record.endTime, this.timeFormat) - }) - } - this.endTimeString = moment(record.endTime).format(this.timeFormat) }, sysDictTypeDropDown() { @@ -220,23 +178,8 @@ this.formLoading = false }, - onChangeTriggerType(e) { - this.VisibleTriggerType = e === 1 - }, - - onChangeBeginTime(date, dateString) { - if (date == null) { - this.beginTimeString = [] - } else { - this.beginTimeString = moment(date).format(this.timeFormat) - } - }, - onChangeEndTime(date, dateString) { - if (date == null) { - this.endTimeString = [] - } else { - this.endTimeString = moment(date).format(this.timeFormat) - } + onChangeTimerType(e) { + this.VisibleTimerType = e === 0 }, handleSubmit() { @@ -248,16 +191,6 @@ this.confirmLoading = true validateFields((errors, values) => { if (!errors) { - // eslint-disable-next-line eqeqeq - if (this.beginTimeString == 'Invalid date') { - this.beginTimeString = null - } - // eslint-disable-next-line eqeqeq - if (this.endTimeString == 'Invalid date') { - this.endTimeString = null - } - values.beginTime = this.beginTimeString - values.endTime = this.endTimeString sysTimersEdit(values).then((res) => { if (res.success) { this.$message.success('编辑成功') diff --git a/frontend/src/views/system/timers/index.vue b/frontend/src/views/system/timers/index.vue index 9af48641577d3a283fd0566a426e02982f40c3eb..d95809973e0523e16bbb9bf8881b757622c6416d 100644 --- a/frontend/src/views/system/timers/index.vue +++ b/frontend/src/views/system/timers/index.vue @@ -9,13 +9,6 @@ - 查询 重置 @@ -33,7 +26,8 @@ :rowKey="(record) => record.id" :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"> {{ text }} @@ -45,19 +39,26 @@ {{ requestTypeFilter(requestType) }} - - + + {{ jobStatusFilter(text) }} - + {{ jobStatusFilter(text) }} 编辑 - + 删除 @@ -113,10 +114,6 @@ customRender: 'requestType' } }, - { - title: '开始时间', - dataIndex: 'beginTime' - }, { title: '执行间隔', dataIndex: 'interval' @@ -127,11 +124,15 @@ }, { title: '状态', - dataIndex: 'displayState', + dataIndex: 'timerStatus', scopedSlots: { customRender: 'jobStatus' } }, + { + title: '执行次数', + dataIndex: 'runNumber' + }, { title: '备注', dataIndex: 'remark' @@ -180,18 +181,25 @@ } }, jobStatusFilter(jobStatus) { - return jobStatus + if (jobStatus === 0) { + return '运行中' + } else if (jobStatus === 1) { + return '已停止' + } else if (jobStatus === 2) { + return '执行失败' + } else if (jobStatus === 3) { + return '已取消' + } }, /** * 启动停止 */ editjobStatusStatus(code, record) { // eslint-disable-next-line eqeqeq - if (code == '正常' || code != '暂停') { + if (code === 0) { sysTimersStop({ id: record.id, - jobName: record.jobName, - jobGroup: record.jobGroup + jobName: record.jobName }).then(res => { if (res.success) { this.$message.success('停止成功') @@ -201,12 +209,8 @@ } }) // eslint-disable-next-line eqeqeq - } else if (code == '暂停') { - sysTimersStart({ - id: record.id, - jobName: record.jobName, - jobGroup: record.jobGroup - }).then(res => { + } else if (code != 0) { + sysTimersStart(record).then(res => { if (res.success) { this.$message.success('启动成功') this.$refs.table.refresh() diff --git a/frontend/src/views/system/user/addForm.vue b/frontend/src/views/system/user/addForm.vue index 632a877e71bedb93bc9d8035ddd5c0d6ced2d9b5..2a53f53b6d09fb0db0cad032ad2f5671d58c2dd9 100644 --- a/frontend/src/views/system/user/addForm.vue +++ b/frontend/src/views/system/user/addForm.vue @@ -47,7 +47,7 @@ diff --git a/frontend/src/views/system/user/index.vue b/frontend/src/views/system/user/index.vue index ffb2ccac8ef928fcbe92ccd2e92e01e3f7fcc821..f46ae16c032ec5c7f4858eb609c56a6e9a38c5ab 100644 --- a/frontend/src/views/system/user/index.vue +++ b/frontend/src/views/system/user/index.vue @@ -29,7 +29,8 @@ - {{ item.value }} + + {{ item.value }} @@ -49,14 +50,28 @@ :alert="true" :rowKey="(record) => record.id" :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"> -