commit 43ef06d4f3ffd2b93b2726026141d61490d0e60b Author: faker <1784913417@qq.com> Date: Mon May 8 16:08:43 2023 +0800 添加项目文件。 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6e62cc8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,316 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +bin/ +obj/ +logs/ +upload/ +*.[pdb] +**/bin/** +**/obj/** +.vs/* +**/wwwroot/Generatecode/** +**/wwwroot/upload/** + + + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]ogs/ +app_data/ +[Aa]pps/ +[Bb]in/ +[Oo]bj/ +app_data/ +[Aa]pps/ +**/[Bb]in/** +**/[Oo]bj/** +**.cache + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json +**.cache + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +# vue +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json +tests/**/coverage/ +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +.idea +.vscode +*.suo +*.ntvs* +*.njsproj + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc +*.dll +/Yuebon.Api/Yuebon.WebApi/wwwroot/upload +/Yuebon.Api/Yuebon.WebApi/upload/opp/20190912 +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816150498189370_300x300.jpeg +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816150498189370.jpeg +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816130781914822_300x300.jpeg +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816130781914822.jpeg +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816104345142749_300x300.jpg +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816104345142749.jpg +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816092171662104_300x300.jpg +/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816092171662104.jpg +/Yuebon.NetCore/Yuebon.Commons/Core/DataManager/DbAppSettings.cs diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3e5d36b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +ENV TZ=Asia/Shanghai +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj", "Znyc.Admin.WebApi/"] +COPY ["Znyc.Admin.MongoDb/Znyc.Admin.MongoDb.Core.csproj", "Znyc.Admin.MongoDb/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Znyc.Admin.AspNetCore.csproj", "Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Znyc.Admin.Security.Core.csproj", "Znyc.Admin.NetCore/Znyc.Admin.Security.Core/"] +COPY ["Znyc.Admin.WeChat.Core/Znyc.Admin.WeChat.Core.csproj", "Znyc.Admin.WeChat.Core/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.Commons/Znyc.Admin.Commons.csproj", "Znyc.Admin.NetCore/Znyc.Admin.Commons/"] +RUN dotnet restore "Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj" +COPY . . +WORKDIR "/src/Znyc.Admin.WebApi" +RUN dotnet build "Znyc.Admin.WebApi.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Znyc.Admin.WebApi.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Znyc.Admin.WebApi.dll"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..db5968b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Znyc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7fa631c --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# znyc_dispatching.admin.api + +派工调度后台Api \ No newline at end of file diff --git a/Znyc.Admin.Hangfire/HangfireDispose.cs b/Znyc.Admin.Hangfire/HangfireDispose.cs new file mode 100644 index 0000000..fc5b880 --- /dev/null +++ b/Znyc.Admin.Hangfire/HangfireDispose.cs @@ -0,0 +1,29 @@ +namespace Znyc.Admin.Hangfire +{ + public class HangfireDispose + { + public static void HangfireService() + { + //Fire - And - forget(发布 / 订阅) + //这是一个主要的后台任务类型,持久化消息队列会去处理这个任务。当你创建了一个发布 / 订阅任务,该任务会被保存到默认队列里面(默认队列是"Default",但是支持使用多队列)。多个专注的工作者(Worker)会监听这个队列,并且从中获取任务并且完成任务。 + //BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget")); + + //延迟 + //如果想要延迟某些任务的执行,可以是用以下任务。在给定延迟时间后,任务会被排入队列,并且和发布 / 订阅任务一样执行。 + //BackgroundJob.Schedule(() => Console.WriteLine("Delayed"), TimeSpan.FromDays(1)); + + //循环 + //按照周期性(小时,天等)来调用方法,请使用RecurringJob类。在复杂的场景,您可以使用CRON表达式指定计划时间来处理任务。 + //RecurringJob.AddOrUpdate(() => Console.WriteLine("Daily Job"), Cron.Daily); + + //连续 + //连续性允许您通过将多个后台任务链接在一起来定义复杂的工作流。 + //var id = BackgroundJob.Enqueue(() => Console.WriteLine("Hello, ")); + //BackgroundJob.ContinueWith(id, () => Console.WriteLine("world!")); + + //这里呢就是需要触发的方法 "0/10 * * * * ? " 可以自行搜索cron表达式 代表循环的规律很简单 + //CancelOrderJob代表你要触发的类 Execute代表你要触发的方法 + + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.Hangfire/Znyc.Admin.Hangfire.csproj b/Znyc.Admin.Hangfire/Znyc.Admin.Hangfire.csproj new file mode 100644 index 0000000..41ffee3 --- /dev/null +++ b/Znyc.Admin.Hangfire/Znyc.Admin.Hangfire.csproj @@ -0,0 +1,19 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + diff --git a/Znyc.Admin.MongoDb/Collection/GpsRealTime.cs b/Znyc.Admin.MongoDb/Collection/GpsRealTime.cs new file mode 100644 index 0000000..311fe58 --- /dev/null +++ b/Znyc.Admin.MongoDb/Collection/GpsRealTime.cs @@ -0,0 +1,149 @@ +using MongoDB.Bson.Serialization.Attributes; +using Pursue.Extension.MongoDB; +using System; + +namespace Znyc.Admin.MongoDb.Core.Collection +{ + public class GpsRealTime : MongoEntityPrimaryKey + { + /// + /// 车辆ID + /// + public long VehicleId { get; set; } + + /// + /// 车辆编号 + /// + public string VehicleCode { get; set; } + + /// + /// 车牌号 + /// + public string VehiclePlate { get; set; } + + /// + /// 司机 + /// + public long VehicleDriver { get; set; } + + /// + /// 司机联系电话 + /// + public string DriverPhone { get; set; } + + /// + /// 状态 + /// + public int Status { get; set; } + + /// + /// Gps状态 + /// + public int GpsState { get; set; } + + /// + /// Gps数据产生时间 + /// + [BsonDateTimeOptions(Kind = DateTimeKind.Unspecified)] + public DateTime GpsTime { get; set; } + + /// + /// Gps服务器接收时间 + /// + [BsonDateTimeOptions(Kind = DateTimeKind.Unspecified)] + public DateTime RecTime { get; set; } + + /// + /// 经度 + /// + public decimal Longitude { get; set; } + + /// + /// 纬度 + /// + public decimal Latitude { get; set; } + + /// + /// 方向 + /// + public int Direct { get; set; } + + /// + /// 速度 + /// + public int Speed { get; set; } + + /// + /// 静止时间 + /// + public string DurationTime { get; set; } + private int _acc; + + /// + /// 打火状态 + /// + public int Acc + { + get => GpsState == 0 ? 0 : _acc; + set => _acc = value; + } + + private string _accDurationTime; + + /// + /// ACC持续时间 + /// + public string AccDurationTime + { + get => GpsState == 0 ? DurationTime : _accDurationTime; + set => _accDurationTime = value; + } + + /// + /// 地址 + /// + public string Address { get; set; } + + /// + /// SIM卡号 + /// + public string SimNo { get; set; } + + /// + /// 公司ID + /// + public long CompanyId { get; set; } + + /// + /// 修改时间 + /// + [BsonDateTimeOptions(Kind = DateTimeKind.Unspecified)] + public DateTime ModifiedTime { get; set; } + + /// + /// 创建时间 + /// + [BsonDateTimeOptions(Kind = DateTimeKind.Unspecified)] + public DateTime CreatedTime { get; set; } + + /// + /// 设备号 + /// + public string TerminalNo { get; set; } + + /// + /// 是否工作 + /// + public int Work { get; set; } + + /// + /// 工作时长 + /// + public string WorkDurationTime { get; set; } + + /// + /// Gps信号模式 1 GPS,2 基站 + /// + //public int GpsMode { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.MongoDb/IRepositorys/IGpsRealTimeRepository.cs b/Znyc.Admin.MongoDb/IRepositorys/IGpsRealTimeRepository.cs new file mode 100644 index 0000000..fc94323 --- /dev/null +++ b/Znyc.Admin.MongoDb/IRepositorys/IGpsRealTimeRepository.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Znyc.Admin.MongoDb.Core.Collection; + +namespace Znyc.Admin.MongoDb.Core.IRepositorys +{ + public interface IGpsRealTimeRepository + + { + Task InsertGpsRealTime(GpsRealTime gpsRealTime); + + Task GetGpsRealTime(long vehicleId); + + Task UpdateGpsRealTime(GpsRealTime gpsRealTime); + } +} \ No newline at end of file diff --git a/Znyc.Admin.MongoDb/MongoContext.cs b/Znyc.Admin.MongoDb/MongoContext.cs new file mode 100644 index 0000000..0052106 --- /dev/null +++ b/Znyc.Admin.MongoDb/MongoContext.cs @@ -0,0 +1,18 @@ +using MongoDB.Driver; +using Pursue.Extension.MongoDB; +using Znyc.Admin.MongoDb.Core.Collection; + +namespace Znyc.Admin.MongoDb +{ + public class MongoContext : MongoDbContext + { + // 使用默认构造(DI配置) + public MongoContext() : base() { } + + // 也可以使用手工配置 + public MongoContext(string Link, string DataBaseName) : base(Link, DataBaseName) { } + + // 上下文模式可以注入需要操作的实体对象和EF一样 + public IMongoCollection GpsRealTime => DbSet(); + } +} \ No newline at end of file diff --git a/Znyc.Admin.MongoDb/Repositorys/GpsRealTimeRepository.cs b/Znyc.Admin.MongoDb/Repositorys/GpsRealTimeRepository.cs new file mode 100644 index 0000000..b5e99c3 --- /dev/null +++ b/Znyc.Admin.MongoDb/Repositorys/GpsRealTimeRepository.cs @@ -0,0 +1,35 @@ +using Pursue.Extension.MongoDB; +using System.Threading.Tasks; +using Znyc.Admin.MongoDb.Core.Collection; +using Znyc.Admin.MongoDb.Core.IRepositorys; + +namespace Znyc.Admin.MongoDb.Core.Repositorys +{ + public class GpsRealTimeRepository : IGpsRealTimeRepository + { + private readonly IMongoDbRepository _gpsRealTimemongoDbRepository; + + public GpsRealTimeRepository(IMongoDbService context) + { + _gpsRealTimemongoDbRepository = context.GetRepository(); ; + } + + public async Task InsertGpsRealTime(GpsRealTime gpsRealTime) + { + await _gpsRealTimemongoDbRepository.AddAsync(gpsRealTime); + return true; + } + + public async Task GetGpsRealTime(long vehicleId) + { + GpsRealTime gpsRealTime = await _gpsRealTimemongoDbRepository.QueryOneAsync(x => x.VehicleId == vehicleId); + return gpsRealTime; + } + + public async Task UpdateGpsRealTime(GpsRealTime gpsRealTime) + { + await _gpsRealTimemongoDbRepository.UpdateAsync(gpsRealTime.Id.ToString(), gpsRealTime); + return true; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.MongoDb/Znyc.Admin.MongoDb.Core.csproj b/Znyc.Admin.MongoDb/Znyc.Admin.MongoDb.Core.csproj new file mode 100644 index 0000000..a5b06e6 --- /dev/null +++ b/Znyc.Admin.MongoDb/Znyc.Admin.MongoDb.Core.csproj @@ -0,0 +1,10 @@ + + + + net6.0 + + + + + + \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/AspNetCore.xml b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/AspNetCore.xml new file mode 100644 index 0000000..d75164d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/AspNetCore.xml @@ -0,0 +1,787 @@ + + + + + Znyc.Admin.AspNetCore + + + + + 错误代码描述 + + + + + 请求成功 + + + + + 请求成功代码0 + + + + + 请求失败 + + + + + 请求失败代码1 + + + + + 获取access_token时AppID或AppSecret错误。请开发者认真比对appid和AppSecret的正确性,或查看是否正在为恰当的应用调用接口 + + + + + 调用接口的服务器URL地址不正确,请联系供应商进行设置 + + + + + 请确保grant_type字段值为client_credential + + + + + 不合法的凭证类型 + + + + + 用户令牌accesstoken超时失效 + + + + + 您未被授权使用该功能,请重新登录试试或联系管理员进行处理 + + + + + 传递参数出现错误 + + + + + 更新数据失败 + + + + + 更新数据失败 + + + + + 物理删除数据失败 + + + + + 该用户不存在 + + + + + 该用户已存在 + + + + + 会员注册失败 + + + + + 查询数据不存在 + + + + + 自定义异常信息 + + + + + 异常消息 + + + + + 成功状态 + + + + + 提示代码 + + + + + 异常 + + + + + + + + + + + + + + + + + + + sso验证 + 其他站点通过后台Post来认证 + 或使用静态类Znyc.Admin.Security.Application.SSO.AuthHelper访问 + + + + + 检验token是否有效 + + The token. + 请求Id备用参数. + + + + 根据token获取用户及用户可访问的所有资源 + + + 备用参数. + + + + 根据token获取用户名称 + + + 备用参数. + + + + 登录接口 + + 登录参数 + + + + + 注销登录 + + + 备用参数. + + + + 获取token + + + + + + 文件上传 + + + + + + + + + + 单文件上传接口 + + + 服务器存储的文件信息 + + + + 批量上传文件接口 + + + 服务器存储的文件信息 + + + + 批量上传文件 + + 文件 + 所属应用,如文章article + 所属应用ID,如文章id + + + + + 单个上传文件 + + + + + + + 实现文件上传到服务器保存,并生成缩略图 + + 文件名称 + 文件字节流 + + + + Identity控制器 + + + + + + + + + + 用户登录接口控制器 + + + + + 构造函数注入服务 + + + + + + 登录验证用户 + + 用户名 + 密码 + 返回Url + 返回用户User对象 + + + + Token令牌接口控制器 + + + + + + + + + + + 根据应用信息获得token令牌 + + 获取access_token填写client_credential + 用户唯一凭证,应用AppId + 应用密钥AppSecret + + + + + 验证token的合法性。 + + + + + + + 刷新token。 + + + + + + + 把object对象转换为ContentResult + + + + + + + WebApi控制器基类 + + + + + 当前登录的用户属性 + + + + + 把object对象转换为ContentResult + + + + + + + 验证token的合法性。如果不合法,返回MyApiException异常 + + + + + + 获取token + + + + + + 基本控制器,增删改查 + + 实体类型 + Service类型 + + + + 服务接口 + + + + + 构造方法 + + + + + + 在插入数据前对数据的修改操作 + + + + + + + 在更新数据前对数据的修改操作 + + + + + + + 在软删除数据前对数据的修改操作 + + + + + + + 异步新增数据 + + + + + + + 异步更新数据 + + + 主键Id + + + + + 物理删除 + + 主键Id + + + + 异步物理删除 + + 主键Id + + + + 软删除信息 + + 主键Id + 删除标识,默认为1:即设为删除,0:未删除 + + + + 异步软删除信息 + + 主键Id + 删除标识,默认为1:即设为删除,0:未删除 + + + + 设为数据有效性 + + 主键Id + 有效标识,默认为1:即设为无效,0:有效 + + + + 异步设为数据有效性 + + 主键Id + 有效标识,默认为1:即设为无效,0:有效 + + + + 根据主键Id获取一个对象信息 + + 主键Id + + + + + 根据条件查询数据库,并返回对象集合(用于分页数据显示) + + info + 指定对象的集合 + + + + 根据Request参数获取分页对象数据 + + + + + + 获取分页操作的查询条件 + + + + + + 表示一个特性,该特性用于全局捕获程序运行异常信息。 + + + + + + + + + + + + + + + + + + + + Swagger 上传文件过滤器 + + + + + 应用过滤器 + + + + + + + 隐藏接口,不生成到swagger文档展示 + + + + + 隐藏接口,不生成到swagger文档展示 + + + + + 实现Apply方法 + + + + + + + 功能权限授权验证 + + + + + + + + + + + + + + 权限 + + + + + 构造函数 + + + + + + Token令牌提供类 + + + + + 构造函数 + + + + + 构造函数,初花jwtmodel + + + + + + 直接通过appid和加密字符串获取访问令牌接口 + + 获取access_token填写client_credential + 用户唯一凭证 + 用户唯一凭证密钥,即appsecret + + + + + 检查用户的Token有效性 + + token令牌 + + + + + 根据用户获取token + + + + + + + 根据URL中的Token参数或Cookie获取token + + + + + + 检查用户登录状态 + + token + 备注信息 + + + + + 检查用户登录状态 + 通过URL中的Token参数或Cookie中的Token + + 备注信息 + + + + 获取当前登录的用户信息 + 通过URL中的Token参数或Cookie中的Token + + The remark. + LoginUserVM. + + + + 获取当前登录的用户名 + 通过URL中的Token参数或Cookie中的Token + + The remark. + System.String. + + + + 登录接口 + + 应用程序key. + 应用程序Secret. + 用户名 + 密码 + System.String. + + + + 注销 + + + + + 登录返回结果 + + + + + 跳转Url + + + + + token + + + + + 系统登录请求实体 + + + + + 账号 + + + + + 密码 + + + + + 系统编码 + + + + + 用户登录验证,主要用管理后台、H5和App应用用户登录 + + + + + + + 获取到的凭证值 + + + + + 获取到的凭证值 + + + + + 用户ID + + + + + 用户账号 + + + + + 用户名 + + + + + 昵称 + + + + + 头像 + + + + + 性别 + + + + + 头像 + + + + + 上级推广员 + + + + + 注册时间 + + + + + 角色编码,多个角色,使用“,”分格 + + + + + 其他对象 + + + + + 查询条件公共实体类 + + + + + 关键词 + + + + + 排序方式 默认asc + + + + + 排序字段 默认Id + + + + + 第几页 + + + + + 每页显示数量 + + + + + SessionObject是登录之后,给客户端传回的对象 + + + + + SessionKey + + + + + 当前登录的用户的信息 + + + + \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/CorsMiddleware.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/CorsMiddleware.cs new file mode 100644 index 0000000..50f70f7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/CorsMiddleware.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using System.Threading.Tasks; + +namespace Znyc.Admin.AspNetCore.Common +{ + /// + /// 跨域中间件 + /// 解决net core 3.1 跨域 Cors 找不到 “Access-Control-Allow-Origin” + /// + public class CorsMiddleware + { + /// + /// + /// + private readonly RequestDelegate _next; + + /// + /// + /// + /// + public CorsMiddleware(RequestDelegate next) + { + _next = next; + } + + /// + /// + /// + /// + /// + public async Task Invoke(HttpContext httpContext) + { + if (!httpContext.Response.Headers.ContainsKey("Access-Control-Allow-Origin")) + { + httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*"); + } + + await _next(httpContext); + } + } + + /// + /// + /// + public static class CorsMiddlewareExtensions + { + public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/ErrCode.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/ErrCode.cs new file mode 100644 index 0000000..7e07755 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/ErrCode.cs @@ -0,0 +1,109 @@ +namespace Znyc.Admin.AspNetCore.Entitys +{ + /// + /// 错误代码描述 + /// + public static class ErrCode + { + /// + /// 请求成功 + /// + public static string err0 = "请求成功"; + + /// + /// 请求成功代码0 + /// + public static string successCode = "0"; + + /// + /// 请求失败 + /// + public static string err1 = "请求失败"; + + /// + /// 请求失败代码1 + /// + public static string failCode = "1"; + + /// + /// 获取access_token时AppID或AppSecret错误。请开发者认真比对appid和AppSecret的正确性,或查看是否正在为恰当的应用调用接口 + /// + public static string err40001 = + "获取access_token时AppID或AppSecret错误。请开发者认真比对appid和AppSecret的正确性,或查看是否正在为恰当的应用调用接口"; + + /// + /// 调用接口的服务器URL地址不正确,请联系供应商进行设置 + /// + public static string err40002 = "调用接口的服务器URL地址不正确,请联系供应商进行授权"; + + /// + /// 请确保grant_type字段值为client_credential + /// + public static string err40003 = "请确保grant_type字段值为client_credential"; + + /// + /// 不合法的凭证类型 + /// + public static string err40004 = "不合法的凭证类型"; + + /// + /// 用户令牌accesstoken超时失效 + /// + public static string err40005 = "用户令牌accesstoken超时失效"; + + /// + /// 您未被授权使用该功能,请重新登录试试或联系管理员进行处理 + /// + public static string err40006 = "您未被授权使用该功能,请重新登录试试或联系系统管理员进行处理"; + + /// + /// 传递参数出现错误 + /// + public static string err40007 = "传递参数出现错误"; + + /// + /// 用户未登录或超时 + /// + public static string err40008 = "用户未登录或超时"; + + /// + /// 程序异常 + /// + public static string err40110 = "程序异常"; + + /// + /// 新增数据失败 + /// + public static string err43001 = "新增数据失败"; + + /// + /// 更新数据失败 + /// + public static string err43002 = "更新数据失败"; + + /// + /// 物理删除数据失败 + /// + public static string err43003 = "删除数据失败"; + + /// + /// 该用户不存在 + /// + public static string err50001 = "该数据不存在"; + + /// + /// 该用户已存在 + /// + public static string err50002 = "用户已存在,请登录或重新注册!"; + + /// + /// 会员注册失败 + /// + public static string err50003 = "会员注册失败"; + + /// + /// 查询数据不存在 + /// + public static string err60001 = "查询数据不存在"; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/Initialization.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/Initialization.cs new file mode 100644 index 0000000..b9b3a11 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/Initialization.cs @@ -0,0 +1,25 @@ +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.AspNetCore.Common +{ + /// + /// 系统初始化内容 + /// + public abstract class Initialization + { + /// + /// 初始化 + /// + public virtual void Initial() + { + CacheHelper cacheHelper = new CacheHelper(); + SysSetting sysSetting = XmlConverter.Deserialize("xmlconfig/sys.config"); + if (sysSetting != null) + { + cacheHelper.Add("SysSetting", sysSetting); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/MyApiException.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/MyApiException.cs new file mode 100644 index 0000000..aa8ba4c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/MyApiException.cs @@ -0,0 +1,115 @@ +using System; +using System.Runtime.Serialization; + +namespace Znyc.Admin.AspNetCore.Common +{ + /// + /// 自定义异常信息 + /// + public class MyApiException : Exception + { + private string _msg; + private bool _success; + private string _errCode; + + /// + /// 异常消息 + /// + public string Msg + { + get => _msg; + set => _msg = value; + } + + /// + /// 成功状态 + /// + public bool Success + { + get => _success; + set => _success = value; + } + + /// + /// 提示代码 + /// + public string ErrCode + { + get => _errCode; + set => _errCode = value; + } + + /// + /// 异常 + /// + /// + public MyApiException(string message) + { + Msg = message; + } + + /// + /// + /// + /// + /// + public MyApiException(string message, string errcode) + { + Msg = message; + ErrCode = errcode; + } + + /// + /// + /// + /// + /// + /// + public MyApiException(string message, bool success, string errcode) + { + Msg = message; + Success = success; + ErrCode = errcode; + } + + /// + /// + /// + public MyApiException() + { + } + + /// + /// + /// + /// + /// + protected MyApiException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + /// + /// + /// + /// + /// + public MyApiException(string message, Exception innerException) : base(message, innerException) + { + Msg = message; + throw innerException; + } + + /// + /// + /// + /// + /// + /// + public MyApiException(string message, string errcode, Exception innerException) : base(message, innerException) + { + Msg = message; + ErrCode = errcode; + throw innerException; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/Permission.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/Permission.cs new file mode 100644 index 0000000..c5c061c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/Permission.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Security.Dtos; + +namespace Znyc.Admin.AspNetCore.Common +{ + /// + /// 权限控制 + /// + public static class Permission + { + /// + /// 判断当前用户是否拥有某功能点的权限 + /// + /// 功能编码code + /// 用户id + /// + public static bool HasFunction(string functionCode, int userId) + { + bool hasFunction = false; + if (!string.IsNullOrEmpty(userId.ToString())) + { + if (string.IsNullOrEmpty(functionCode)) + { + hasFunction = true; + } + else + { + System.Collections.Generic.List listFunction = new CacheHelper().Get("User_Function_" + userId).ToJson() + .ToList(); + if (listFunction != null && listFunction.Count(t => t.EnCode == functionCode) > 0) + { + hasFunction = true; + } + } + } + + return hasFunction; + } + + /// + /// 判断是否为系统管理员或超级管理员 + /// + /// true:系统管理员或超级管理员,false:不是系统管理员或超级管理员 + /// + /// + public static bool IsAdmin(AdminCurrentUser AdminCurrentUser) + { + bool blnIsAdmin = false; + if (AdminCurrentUser != null) + { + if (AdminCurrentUser.Account == "admin" || + AdminCurrentUser.Role.Contains("administrators", StringComparison.Ordinal)) + { + return true; + } + } + + return blnIsAdmin; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/SessionObject.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/SessionObject.cs new file mode 100644 index 0000000..682467b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Common/SessionObject.cs @@ -0,0 +1,20 @@ +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.WebApi.Common +{ + /// + /// SessionObject是登录之后,给客户端传回的对象 + /// + public class SessionObject + { + /// + /// SessionKey + /// + public string SessionKey { get; set; } + + /// + /// 当前登录的用户的信息 + /// + public AdminUser LogonUser { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/ApiController.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/ApiController.cs new file mode 100644 index 0000000..446839e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/ApiController.cs @@ -0,0 +1,249 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Security.Claims; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Unicode; + +using Znyc.Admin.AspNetCore.Common; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.Mvc.Filter; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; + +namespace Znyc.Admin.AspNetCore.Controllers +{ + /// + /// WebApi控制器基类 + /// + [ApiController] + [EnableCors("Cors")] + public class ApiController : Controller + { + /// + /// 当前登录的用户属性 + /// + public AdminCurrentUser CurrentUser; + + #region + + /// + /// 重写基类在Action执行之前的事情 + /// 根据token获得当前用户,允许匿名的不需要获取用户 + /// + /// 重写方法的参数 + public override void OnActionExecuting(ActionExecutingContext context) + { + try + { + ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; + //匿名访问,不需要token认证、签名和登录 + Attribute allowanyone = controllerActionDescriptor.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute), true); + if (allowanyone != null) + { + return; + } + + CommonResult result = new CommonResult(); + //需要token认证 + string authHeader = context.HttpContext.Request.Headers["Authorization"];//Header中的token + if (string.IsNullOrEmpty(authHeader)) + { + result.ErrCode = "40004"; + result.ErrMsg = ErrCode.err40004; + context.Result = ToJsonContent(result); + return; + } + else + { + string token = string.Empty; + if (authHeader != null && authHeader.StartsWith("Bearer ", StringComparison.Ordinal)) + { + token = authHeader.Substring(7); + } + + TokenProvider tokenProvider = new TokenProvider(); + result = tokenProvider.ValidateToken(token); + //token验证失败 + if (!result.Success) + { + context.Result = ToJsonContent(result); + } + else + { + #region 是否需要验证用户登录以及相关的功能权限 + + //是否需要用户登录 + Attribute isDefined = controllerActionDescriptor.MethodInfo.GetCustomAttribute(typeof(NoPermissionRequiredAttribute)); + //不需要登录 + if (isDefined != null) + { + return; + } + //需要登录和验证功能权限 + if (result.ResData != null) + { + List claimlist = result.ResData as List; + string userId = claimlist[3].Value; + + Claim[] claims = new[] { + new Claim(ZnycClaimTypes.UserId,userId), + new Claim(ZnycClaimTypes.UserName,claimlist[2].Value), + new Claim(ZnycClaimTypes.Role,claimlist[4].Value) + }; + ClaimsIdentity identity = new ClaimsIdentity(claims); + ClaimsPrincipal principal = new ClaimsPrincipal(identity); + context.HttpContext.User = principal; + CacheHelper yuebonCacheHelper = new CacheHelper(); + AdminCurrentUser user = yuebonCacheHelper.Get("login_user_" + userId); + if (user != null) + { + CurrentUser = user; + } + bool isAdmin = Permission.IsAdmin(user); + if (!isAdmin) + { + IEnumerable authorizeAttributes = controllerActionDescriptor.MethodInfo.GetCustomAttributes(typeof(FunctionAuthorizeAttribute), true).OfType(); + if (authorizeAttributes.FirstOrDefault() != null) + { + string function = authorizeAttributes.First().Function; + if (!string.IsNullOrEmpty(function)) + { + string functionCode = controllerActionDescriptor.ControllerName + "/" + function; + + bool bl = Permission.HasFunction(functionCode, userId.ToInt()); + if (!bl) + { + result.ErrCode = "40006"; + result.ErrMsg = ErrCode.err40006; + context.Result = ToJsonContent(result); + } + } + } + } + return; + } + else + { + result.ErrCode = "40008"; + result.ErrMsg = ErrCode.err40008; + context.Result = ToJsonContent(result); + } + + #endregion 是否需要验证用户登录以及相关的功能权限 + } + return; + } + } + catch (Exception ex) + { + Log4NetHelper.Error("", ex); + } + } + + #endregion + + /// + /// 把object对象转换为ContentResult + /// + /// + /// + [HttpPost] + [Route("api/ToJsonContent")] + protected IActionResult ToJsonContent(object obj) + { + return Content(obj.ToJson()); + } + + /// + /// 把object对象转换为ContentResult + /// + /// 转换对象 + /// 是否忽略空值 + /// + [HttpPost] + [Route("api/ToJsonContent")] + protected IActionResult ToJsonContent(object obj, bool isNull = false) + { + JsonSerializerOptions options = new JsonSerializerOptions() + { + WriteIndented = true, //格式化json字符串 + AllowTrailingCommas = true, //可以结尾有逗号 + IgnoreNullValues = true, //可以有空值,转换json去除空值属性 + IgnoreReadOnlyProperties = true, //忽略只读属性 + PropertyNameCaseInsensitive = true, //忽略大小写 + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + }; + options.Converters.Add(new DateTimeJsonConverter()); + return Content(JsonSerializer.Serialize(obj, options)); + } + + /// + /// 根据Request参数获取分页对象数据 + /// + /// + protected virtual PagerInfo GetPagerInfo() + { + int pageSize = Request.Query["length"].ToString() == null ? 1 : Request.Query["length"].ToString().ToInt(); + int pageIndex = 1; + string currentPage = Request.Query["CurrentPage"].ToString(); + if (string.IsNullOrWhiteSpace(currentPage)) + { + string start = Request.Query["start"].ToString(); + if (!string.IsNullOrWhiteSpace(start)) + { + pageIndex = (start.ToInt() / pageSize) + 1; + } + } + else + { + pageIndex = currentPage.ToInt(); + } + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = pageIndex, + PageSize = pageSize + }; + return pagerInfo; + } + + /// + /// 获取token + /// + /// + [HttpGet("GetToken")] + [HiddenApi] + public string GetToken() + { + string token = HttpContext.Request.Query["Token"]; + if (!string.IsNullOrEmpty(token)) + { + return token; + } + + string authHeader = HttpContext.Request.Headers["Authorization"];//Header中的token + if (authHeader != null && authHeader.StartsWith("Bearer")) + { + token = authHeader.Substring("Bearer ".Length).Trim(); + return token; + } + string cookie = HttpContext.Request.Cookies["Token"]; + return cookie == null ? string.Empty : cookie; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/AreaApiController.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/AreaApiController.cs new file mode 100644 index 0000000..511854f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/AreaApiController.cs @@ -0,0 +1,394 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.Mvc.Filter; +using Znyc.Admin.AspNetCore.ViewModel; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Mapping; + +namespace Znyc.Admin.AspNetCore.Controllers +{ + /// + /// 基本控制器,增删改查 + /// + /// 实体类型 + /// 数据输出实体类型 + /// 数据输入实体类型 + /// Service类型 + /// 主键数据类型 + [ApiController] + public abstract class AreaApiController : ApiController + where T : Entity + where TService : IService + where TODto : class + where TIDto : class + where TKey : IEquatable + { + #region 属性变量 + + /// + /// 服务接口 + /// + public TService _service; + + #endregion 属性变量 + + #region 构造函数及常用 + + /// + /// 构造方法 + /// + /// + public AreaApiController(TService service) + { + _service = service; + } + + #endregion 构造函数及常用 + + #region 公共添加、修改、删除、软删除接口 + + /// + /// 在插入数据前对数据的修改操作 + /// + /// + /// + protected virtual void OnBeforeInsert(T info) + { + //留给子类对参数对象进行修改 + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected virtual void OnBeforeUpdate(T info) + { + //留给子类对参数对象进行修改 + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected virtual void OnBeforeSoftDelete(T info) + { + //留给子类对参数对象进行修改 + + + + } + + /// + /// 异步新增数据,无效 + /// + /// + /// + [HttpPost("Insert")] + [FunctionAuthorize("Add")] + public virtual async Task InsertAsync(TIDto tinfo) + { + CommonResult result = new CommonResult(); + T info = tinfo.MapTo(); + OnBeforeInsert(info); + long ln = await _service.InsertAsync(info).ConfigureAwait(false); + if (ln > 0) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43001; + result.ErrCode = "43001"; + } + + return ToJsonContent(result); + } + + /// + /// 异步更新数据,需要在业务模块控制器重写该方法,否则更新无效 + /// + /// + /// + [HttpPost("Update")] + [FunctionAuthorize("Edit")] + public virtual async Task UpdateAsync(TIDto inInfo) + { + CommonResult result = new CommonResult(); + return ToJsonContent(result); + } + + ///// + ///// 物理删除 + ///// + ///// 主键Id + //[HttpDelete("Delete")] + //[FunctionAuthorize("Delete")] + //public virtual IActionResult Delete(TKey id) + //{ + // var result = new CommonResult(); + // var bl = _service.Delete(id); + // if (bl) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = ErrCode.err0; + // } + // else + // { + // result.ErrMsg = ErrCode.err43003; + // result.ErrCode = "43003"; + // } + + // return ToJsonContent(result); + //} + + ///// + ///// 异步物理删除 + ///// + ///// 主键Id + //[HttpDelete("DeleteAsync")] + //[FunctionAuthorize("Delete")] + //public virtual async Task DeleteAsync(TKey id) + //{ + // var result = new CommonResult(); + // var bl = await _service.DeleteAsync(id).ConfigureAwait(false); + // if (bl) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = ErrCode.err0; + // } + // else + // { + // result.ErrMsg = ErrCode.err43003; + // result.ErrCode = "43003"; + // } + + // return ToJsonContent(result); + //} + + ///// + ///// 异步批量物理删除 + ///// + ///// + //[HttpDelete("DeleteBatchAsync")] + //[FunctionAuthorize("Delete")] + //public virtual async Task DeleteBatchAsync(DeletesInputDto info) + //{ + // var result = new CommonResult(); + // var where = string.Empty; + // if (typeof(TKey) == typeof(string)) + // @where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + // else if (typeof(TKey) == typeof(int)) @where = "id in (" + info.Ids.Join(",") + ")"; + // if (!string.IsNullOrEmpty(where)) + // { + // var bl = await _service.DeleteBatchWhereAsync(where).ConfigureAwait(false); + // if (bl) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = ErrCode.err0; + // } + // else + // { + // result.ErrMsg = ErrCode.err43003; + // result.ErrCode = "43003"; + // } + // } + + // return ToJsonContent(result); + //} + + ///// + ///// 软删除信息 + ///// + ///// 主键Id + ///// 删除标识,默认为1:即设为删除,0:未删除 + //[HttpPost("DeleteSoft")] + //[FunctionAuthorize("DeleteSoft")] + //public virtual IActionResult DeleteSoft(TKey id, string bltag = "1") + //{ + // var result = new CommonResult(); + // var bl = false; + // if (bltag == "0") bl = true; + // var blResult = _service.DeleteSoft(bl, id, CurrentUser.UserId); + // if (blResult) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = ErrCode.err0; + // } + // else + // { + // result.ErrMsg = ErrCode.err43002; + // result.ErrCode = "43002"; + // } + + // return ToJsonContent(result); + //} + + /// + /// 异步软删除信息 + /// + /// 主键Id + /// 删除标识,默认为1:即设为删除,0:未删除 + [HttpPost("DeleteSoftAsync")] + [FunctionAuthorize("DeleteSoft")] + public virtual async Task DeleteSoftAsync(TKey id, string bltag = "1") + { + CommonResult result = new CommonResult(); + bool bl = false; + if (bltag == "0") + { + bl = true; + } + + bool blResult = await _service.DeleteSoftAsync(bl, id, CurrentUser.UserId); + if (blResult) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 异步批量软删除信息 + /// + /// + /// + [HttpPost("DeleteSoftBatchAsync")] + [FunctionAuthorize("DeleteSoft")] + public virtual async Task DeleteSoftBatchAsync(UpdateEnableViewModel info) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + if (typeof(TKey) == typeof(string)) + { + @where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + } + else if (typeof(TKey) == typeof(int)) + { + @where = "id in (" + info.Ids.Join(",") + ")"; + } + + if (!string.IsNullOrEmpty(where)) + { + bool bl = false; + if (info.Flag == "1") + { + bl = true; + } + + bool blResult = await _service.DeleteSoftBatchAsync(bl, where, CurrentUser.UserId); + if (blResult) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + } + + return ToJsonContent(result); + } + + #endregion 公共添加、修改、删除、软删除接口 + + #region 查询单个实体 + + /// + /// 根据主键Id获取一个对象信息 + /// + /// 主键Id + /// + [HttpGet("GetById")] + [FunctionAuthorize("")] + [NoPermissionRequired] + public virtual async Task> GetById(TKey id) + { + CommonResult result = new CommonResult(); + TODto info = await _service.GetOutDtoAsync(id); + if (info != null) + { + result.ErrCode = ErrCode.successCode; + result.ResData = info; + } + else + { + result.ErrMsg = ErrCode.err50001; + result.ErrCode = "50001"; + } + + return result; + } + + #endregion 查询单个实体 + + //#region 返回集合的接口 + + ///// + ///// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + ///// + ///// 查询条件 + ///// 指定对象的集合 + //[HttpPost("FindWithPager")] + //[FunctionAuthorize("List")] + //public virtual CommonResult> FindWithPager(SearchInputDto search) + //{ + // var result = new CommonResult>(); + // result.ResData = _service.FindWithPager(search); + // result.ErrCode = ErrCode.successCode; + // return result; + //} + + ///// + ///// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + ///// + ///// + ///// + //[HttpPost("FindWithPagerAsync")] + //[FunctionAuthorize("List")] + //public virtual async Task>> FindWithPagerAsync(SearchInputDto search) + //{ + // var result = new CommonResult>(); + // result.ResData = await _service.FindWithPagerAsync(search); + // result.ErrCode = ErrCode.successCode; + // return result; + //} + + /// + /// 获取所有可用的 + /// + /// + [HttpGet("GetAllEnable")] + [FunctionAuthorize("List")] + public virtual async Task>> GetAllEnable() + { + CommonResult> result = new CommonResult>(); + IEnumerable list = await _service.GetAllByIsNotDeleteAndEnabledMarkAsync(); + List resultList = list.MapTo(); + result.ResData = resultList; + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + + return result; + } + + // #endregion + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/ActionFilter.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/ActionFilter.cs new file mode 100644 index 0000000..21d4900 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/ActionFilter.cs @@ -0,0 +1,150 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Newtonsoft.Json; +using StackExchange.Profiling; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.App; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.AspNetCore.Mvc.Filter +{ + /// + /// + /// + public class ActionFilter : IAsyncActionFilter + { + private readonly ILogOpService _operationLogsService = App.GetService(); + + /// + /// + /// + /// + /// + /// + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + MiniProfiler profiler = MiniProfiler.StartNew("StartNew"); + using (profiler.Step("Level1")) + { + // WriteLog(profiler); + + //执行Action + await next(); + } + // await WriteOperationLog(context, next); + + //WriteLog(profiler); + } + + public async Task WriteOperationLog(ActionExecutingContext context, ActionExecutionDelegate next) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + ActionExecutedContext actionExecutedContext = await next(); + sw.Stop(); + + //操作参数 + string args = JsonConvert.SerializeObject(context.ActionArguments); + //操作结果 + // var result = JsonConvert.SerializeObject(actionResult?.Value); + + try + { + LogOp input = new LogOp() + { + //UserName = new AdminCurrentUser().Name ?? "", + //CreatedTime = DateTime.Now, + //OperationTime = DateTime.Now, + //CreatedUserId = new AdminCurrentUser().UserId, + //RequestUrl = args, + //OS = "PC", + //IP = new AdminCurrentUser().CurrentLoginIP ?? "", + //City = new AdminCurrentUser().IPAddressName ?? "", + //CRUD = context.HttpContext.Request.Method.ToLower(), + //Browser = "", + //RequertData = "", + //UserAgent = context.RouteData.Values["controller"].ToString() + // context.HttpContext.Request.Method.ToLower(), + // context.ActionDescriptor.AttributeRouteInfo.Template.ToLower(), + // sw.ElapsedMilliseconds + }; + + if (actionExecutedContext.Result is ObjectResult result && result.Value is CommonResult res) + { + //input.RequertData = res.ErrCode; + //input.Msg = res.Success; + } + await _operationLogsService.InsertAsync(input); + } + catch (Exception) + { + // _logger.LogError("操作日志插入异常:{@ex}", ex); + } + } + + /// + /// sql跟踪 + /// 下载:MiniProfiler.AspNetCore + /// + /// + private void WriteLog(MiniProfiler profiler) + { + if (profiler?.Root != null) + { + Timing root = profiler.Root; + if (root.HasChildren) + { + GetSqlLog(root.Children); + } + } + } + + /// + /// 递归获取MiniProfiler内容 + /// + /// + private void GetSqlLog(List chil) + { + chil.ForEach(chill => + { + if (chill.CustomTimings?.Count > 0) + { + StringBuilder logSql = new StringBuilder(); + foreach (KeyValuePair> customTiming in chill.CustomTimings) + { + int i = 1; + customTiming.Value?.ForEach(value => + { + if (value.ExecuteType != "OpenAsync" && !value.CommandString.Contains("Connection")) + { + logSql.Append( + $"【{customTiming.Key}{i++}】{value.CommandString} 耗时 :{value.DurationMilliseconds} ms,状态 :{(value.Errored ? "失败" : "成功")}"); + } + }); + } + + Console.WriteLine($"sql+{logSql.ToString()}"); + //var logEntity = new Log(); + //logEntity.Date = logEntity.CreatedTime = DateTime.Now; + //logEntity.Type = "SQL"; + //logEntity.Result = true; + //logEntity.Description = logSql.ToString(); + //_logService.Insert(logEntity); + } + else + { + if (chill.Children != null) + { + GetSqlLog(chill.Children); + } + } + }); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/ExceptionHandlingAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/ExceptionHandlingAttribute.cs new file mode 100644 index 0000000..ebd4f58 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/ExceptionHandlingAttribute.cs @@ -0,0 +1,100 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Unicode; +using Znyc.Admin.AspNetCore.Common; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.Repositories; + +namespace Znyc.Admin.AspNetCore.Mvc.Filter +{ + /// + /// 表示一个特性,该特性用于全局捕获程序运行异常信息。 + /// + public class ExceptionHandlingAttribute : ExceptionFilterAttribute + { + private readonly LogExRepository _exceptionsLogs = new LogExRepository(); + + /// + /// + /// + /// + public override void OnException(ExceptionContext context) + { + Exception exception = context.Exception; + AdminCurrentUser CurrentUser = new AdminCurrentUser(); + string requestPath = context.HttpContext.Request.Path.ToString(); + string queryString = context.HttpContext.Request.QueryString.ToString(); + Type type = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType; + string exDesc = requestPath + queryString; + Log4NetHelper.Error(type, "全局捕获程序运行异常信息\n\r" + exDesc, context.Exception); + CommonResult result = new CommonResult(); + if (exception is MyApiException myApiex) + { + context.HttpContext.Response.StatusCode = 200; + context.ExceptionHandled = true; + result.ErrMsg = myApiex.Msg; + result.ErrCode = myApiex.ErrCode; + } + else + { + result.ErrMsg = "程序异常,服务端出现异常![异常消息]" + exception.Message; + result.ErrCode = "500"; + } + + JsonSerializerOptions options = new JsonSerializerOptions() + { + WriteIndented = true, //格式化json字符串 + AllowTrailingCommas = true, //可以结尾有逗号 + //IgnoreNullValues = true, //可以有空值,转换json去除空值属性 + IgnoreReadOnlyProperties = true, //忽略只读属性 + PropertyNameCaseInsensitive = true, //忽略大小写 + //PropertyNamingPolicy = JsonNamingPolicy.CamelCase //命名方式是默认还是CamelCase + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + }; + options.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss")); + context.Result = new JsonResult(result, options); + LogEx exceptionsLogs = new LogEx(); + IEnumerable identities = context.HttpContext.User.Identities; + ClaimsIdentity claimsIdentity = identities.First(); + if (claimsIdentity != null) + { + List claimlist = claimsIdentity.Claims as List; + if (claimlist.Count > 0) + { + string userId = claimlist[0].Value; + CacheHelper cacheHelper = new CacheHelper(); + AdminCurrentUser user = cacheHelper.Get("login_user_" + userId).ToJson().ToObject(); + if (user != null) + { + CurrentUser = user; + } + exceptionsLogs.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + //exceptionsLogs.AppDomainName = requestPath; + //exceptionsLogs.ErrorPage = queryString; + exceptionsLogs.Name = CurrentUser.Name; + //exceptionsLogs.IP = CurrentUser.CurrentLoginIP; + exceptionsLogs.ExceptionName = exception.GetType().Name; + exceptionsLogs.ExceptionMsg = exception.Message; + exceptionsLogs.StackTrace = exception.StackTrace; + exceptionsLogs.ExceptionTime = exceptionsLogs.CreatedTime = DateTime.Now; + exceptionsLogs.CreatedTime = DateTime.Now; + exceptionsLogs.CreatedUserId = CurrentUser.UserId; + exceptionsLogs.IsDeleted = false; + _exceptionsLogs.Insert(exceptionsLogs); + } + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizationFilter.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizationFilter.cs new file mode 100644 index 0000000..750ec10 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizationFilter.cs @@ -0,0 +1,142 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using System.Reflection; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Unicode; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Helpers; + +namespace Znyc.Admin.AspNetCore.Mvc +{ + /// + /// 功能权限授权验证 + /// + public class FunctionAuthorizationFilter : AuthorizeAttribute, IAuthorizationFilter + { + /// + /// 授权验证 + /// + /// + public void OnAuthorization(AuthorizationFilterContext context) + { + ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; + //匿名访问,不需要token认证、签名和登录 + System.Attribute allowanyone = + controllerActionDescriptor.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute), true); + if (allowanyone != null) + { + return; + } + + CommonResult result = new CommonResult(); + JsonSerializerOptions options = new JsonSerializerOptions() + { + WriteIndented = true, //格式化json字符串 + AllowTrailingCommas = true, //可以结尾有逗号 + //IgnoreNullValues = true, //可以有空值,转换json去除空值属性 + IgnoreReadOnlyProperties = true, //忽略只读属性 + PropertyNameCaseInsensitive = true, //忽略大小写 + //PropertyNamingPolicy = JsonNamingPolicy.CamelCase //命名方式是默认还是CamelCase + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + }; + options.Converters.Add(new DateTimeJsonConverter()); + + //需要token认证 + string authHeader = context.HttpContext.Request.Headers["Authorization"]; //Header中的token + if (string.IsNullOrEmpty(authHeader)) + { + result.ErrCode = "40004"; + result.ErrMsg = ErrCode.err40004; + context.Result = new JsonResult(result, options); + return; + } + else + { + string token = string.Empty; + if (authHeader != null) + { + token = authHeader.Substring(7); + } + + TokenProvider tokenProvider = new TokenProvider(); + result = tokenProvider.ValidateToken(token); + //token验证失败 + if (!result.Success) + { + context.Result = new JsonResult(result, options); + } + else + { + //#region 是否需要验证用户登录以及相关的功能权限 + + ////是否需要用户登录 + //var isDefined = + // controllerActionDescriptor.MethodInfo.GetCustomAttribute(typeof(NoPermissionRequiredAttribute)); + ////不需要登录 + //if (isDefined != null) return; + ////需要登录和验证功能权限 + //if (result.ResData != null) + //{ + // var claimlist = result.ResData as List; + // var userId = claimlist[3].Value.ToInt(); + // var user = new AdminCurrentUser + // { + // UserId = userId, + // Account = claimlist[2].Value, + // Role = claimlist[4].Value + // }; + + // var claims = new[] + // { + // new Claim(ZnycClaimTypes.UserId, userId.ToString()), + // new Claim(ZnycClaimTypes.UserName, claimlist[2].Value), + // new Claim(ZnycClaimTypes.Role, claimlist[4].Value) + // }; + // var identity = new ClaimsIdentity(claims); + // var principal = new ClaimsPrincipal(identity); + // context.HttpContext.User = principal; + // var isAdmin = Permission.IsAdmin(user); + // if (!isAdmin) + // { + // var authorizeAttributes = controllerActionDescriptor.MethodInfo + // .GetCustomAttributes(typeof(FunctionAuthorizeAttribute), true) + // .OfType(); + // if (authorizeAttributes.FirstOrDefault() != null) + // { + // var function = authorizeAttributes.First().Function; + // if (!string.IsNullOrEmpty(function)) + // { + // var functionCode = controllerActionDescriptor.ControllerName + "/" + function; + + // var bl = Permission.HasFunction(functionCode, userId); + // if (!bl) + // { + // result.ErrCode = "40006"; + // result.ErrMsg = ErrCode.err40006; + // context.Result = new JsonResult(result, options); + // } + // } + // } + // } + + // return; + //} + //else + //{ + // result.ErrCode = "40008"; + // result.ErrMsg = ErrCode.err40008; + // context.Result = new JsonResult(result, options); + //} + + //#endregion + } + + return; + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizeAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizeAttribute.cs new file mode 100644 index 0000000..53960c6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizeAttribute.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc.Filters; +using System; + +namespace Znyc.Admin.AspNetCore.Mvc +{ + /// + /// 功能权限属性配置 + /// + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] + public class FunctionAuthorizeAttribute : ActionFilterAttribute + { + /// + /// 功能权限 + /// + public string Function { get; set; } + + /// + /// 构造函数 + /// + /// 功能代码 + public FunctionAuthorizeAttribute(string function) + { + Function = function; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/HiddenApiAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/HiddenApiAttribute.cs new file mode 100644 index 0000000..7f480b3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/HiddenApiAttribute.cs @@ -0,0 +1,49 @@ +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System; +using System.Linq; +using System.Reflection; + +namespace Znyc.Admin.AspNetCore.Mvc +{ + /// + /// 隐藏接口,不生成到swagger文档展示 + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] + public partial class HiddenApiAttribute : Attribute + { + } + + /// + /// 隐藏接口,不生成到swagger文档展示 + /// + public class HiddenApiFilter : IDocumentFilter + { + /// + /// 实现Apply方法 + /// + /// + /// + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext documentFilterContext) + { + foreach (Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription apiDescription in documentFilterContext.ApiDescriptions) + { + if (apiDescription.TryGetMethodInfo(out MethodInfo methodInfo)) + { + if (Enumerable.OfType(methodInfo.GetCustomAttributes()) + .Any()) + { + string key = "/" + apiDescription.RelativePath.TrimEnd('/'); + if (key.Contains("?")) + { + int idx = key.IndexOf("?", StringComparison.Ordinal); + key = key.Substring(0, idx); + } + + swaggerDoc.Paths.Remove(key); + } + } + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/NoPermissionRequiredAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/NoPermissionRequiredAttribute.cs new file mode 100644 index 0000000..2243473 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/NoPermissionRequiredAttribute.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Mvc.Filters; + +namespace Znyc.Admin.AspNetCore.Mvc.Filter +{ + /// + /// 不需要权限验证,不需要登录 + /// + public class NoPermissionRequiredAttribute : ActionFilterAttribute + { + /// + /// + /// + /// + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + base.OnActionExecuting(filterContext); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/SwaggerFileUploadFilter.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/SwaggerFileUploadFilter.cs new file mode 100644 index 0000000..da1e07b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/Filter/SwaggerFileUploadFilter.cs @@ -0,0 +1,55 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System; +using System.Linq; + +namespace Znyc.Admin.AspNetCore.Mvc.Filter +{ + /// + /// Swagger 上传文件过滤器 + /// + public class SwaggerFileUploadFilter : IOperationFilter + { + /// + /// 应用过滤器 + /// + /// + /// + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + { + #region 文件上传处理 + + if (!context.ApiDescription.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) && + !context.ApiDescription.HttpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase)) + { + return; + } + + System.Collections.Generic.List fileParameters = context.ApiDescription.ActionDescriptor.Parameters + .Where(n => n.ParameterType == typeof(IFormFile)).ToList(); + if (fileParameters.Count < 0) + { + return; + } + + foreach (Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor fileParameter in fileParameters) + { + OpenApiParameter parameter = operation.Parameters.Single(n => n.Name == fileParameter.Name); + operation.Parameters.Remove(parameter); + operation.Parameters.Add(new OpenApiParameter + { + Name = parameter.Name, + In = ParameterLocation.Header, //"formData", + Description = parameter.Description, + Required = parameter.Required, + Content = parameter.Content + }); + } + + #endregion 文件上传处理 + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/TokenProvider.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/TokenProvider.cs new file mode 100644 index 0000000..64ba3be --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Mvc/TokenProvider.cs @@ -0,0 +1,220 @@ +using IdentityModel; +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Znyc.Admin.AspNetCore.Common; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.Commons.Core.App; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Options; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.AspNetCore.Mvc +{ + /// + /// Token令牌提供类 + /// + public class TokenProvider + { + private readonly JwtOption _jwtModel = App.GetService(); + private readonly IRoleService _roleService = App.GetService(); + + /// + /// 构造函数 + /// + public TokenProvider() + { + } + + /// + /// 构造函数,初花jwtmodel + /// + /// + public TokenProvider(JwtOption jwtModel) + { + _jwtModel = jwtModel; + } + + /// + /// 直接通过appid和加密字符串获取访问令牌接口 + /// + /// 获取access_token填写client_credential + /// 用户唯一凭证AppId + /// 用户唯一凭证密钥,即appsecret + /// + public TokenResult GenerateToken(string granttype, string appid, string secret) + { + byte[] keyByteArray = Encoding.UTF8.GetBytes(secret); + SymmetricSecurityKey signingKey = new SymmetricSecurityKey(keyByteArray); + DateTime expires = DateTime.UtcNow.Add(TimeSpan.FromMinutes(_jwtModel.Expiration)); + SigningCredentials signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); + SecurityTokenDescriptor tokenDescripor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(new Claim[] + { + new Claim(JwtClaimTypes.Audience, appid), + new Claim(JwtClaimTypes.Issuer, _jwtModel.Issuer), + new Claim(JwtClaimTypes.Subject, GrantType.ClientCredentials) + }, granttype), + Expires = expires, + //对称秘钥SymmetricSecurityKey + //签名证书(秘钥,加密算法)SecurityAlgorithms + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyByteArray), + SecurityAlgorithms.HmacSha256Signature) + }; + JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); + SecurityToken token = tokenHandler.CreateToken(tokenDescripor); + string tokenString = tokenHandler.WriteToken(token); + TokenResult result = new TokenResult + { + AccessToken = tokenString, + ExpiresIn = (int)TimeSpan.FromMinutes(_jwtModel.Expiration).TotalMinutes + }; + return result; + } + + /// + /// 检查用户的Token有效性 + /// + /// token令牌 + /// + public CommonResult ValidateToken(string token) + { + //返回的结果对象 + CommonResult result = new CommonResult(); + if (!string.IsNullOrEmpty(token)) + { + try + { + JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token); + if (jwtToken != null) + { + #region 检查令牌对象内容 + + DateTime now = DateTime.UtcNow; + DateTime refreshTime = jwtToken.ValidFrom; + refreshTime = refreshTime.Add(TimeSpan.FromMinutes(_jwtModel.refreshJwtTime)); + if (now > refreshTime && jwtToken.Issuer == _jwtModel.Issuer) + { + result.ErrMsg = ErrCode.err40005; + result.ErrCode = "40005"; + } + else + { + if (jwtToken.Subject == GrantType.Password) + { + List claimlist = jwtToken?.Payload.Claims as List; + result.ResData = claimlist; + } + + result.ErrMsg = ErrCode.err0; + result.ErrCode = ErrCode.successCode; + } + + #endregion 检查令牌对象内容 + } + else + { + result.ErrMsg = ErrCode.err40004; + result.ErrCode = "40004"; + } + } + catch (Exception ex) + { + Log4NetHelper.Error("验证token异常", ex); + throw new MyApiException(ErrCode.err40004, "40004"); + } + } + else + { + result.ErrMsg = ErrCode.err40004; + result.ErrCode = "40004"; + } + + return result; + } + + /// + /// 根据用户获取token + /// + /// 用户信息 + /// 应用Id + /// + public TokenResult LoginToken(AdminUser userInfo, string appid) + { + JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); + byte[] key = Encoding.UTF8.GetBytes(_jwtModel.Secret); + DateTime authTime = DateTime.UtcNow; //授权时间 + DateTime expires = authTime.Add(TimeSpan.FromMinutes(_jwtModel.Expiration)); //过期时间 + SecurityTokenDescriptor tokenDescripor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(new Claim[] + { + new Claim(JwtClaimTypes.Audience, appid), + new Claim(JwtClaimTypes.Issuer, _jwtModel.Issuer), + new Claim(JwtClaimTypes.Name, userInfo.Account), + new Claim(JwtClaimTypes.Id, userInfo.Id.ToString()), + new Claim(JwtClaimTypes.Role, _roleService.GetRoleEnCode(userInfo.RoleId.ToString())), + new Claim(JwtClaimTypes.Subject, GrantType.Password) + }), + Expires = expires, + //对称秘钥SymmetricSecurityKey + //签名证书(秘钥,加密算法)SecurityAlgorithms + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), + SecurityAlgorithms.HmacSha256Signature) + }; + SecurityToken token = tokenHandler.CreateToken(tokenDescripor); + string tokenString = tokenHandler.WriteToken(token); + TokenResult result = new TokenResult + { + AccessToken = tokenString, + ExpiresIn = (int)TimeSpan.FromMinutes(_jwtModel.Expiration).TotalMinutes + }; + return result; + } + + /// + /// 根据登录用户获取token + /// + /// 用户信息 + /// 应用Id + /// + public TokenResult GetUserToken(AdminUser userInfo, string appid) + { + JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); + byte[] key = Encoding.UTF8.GetBytes(_jwtModel.Secret); + DateTime authTime = DateTime.UtcNow; //授权时间 + DateTime expires = authTime.Add(TimeSpan.FromMinutes(_jwtModel.Expiration)); //过期时间 + SecurityTokenDescriptor tokenDescripor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(new Claim[] + { + new Claim(JwtClaimTypes.Audience, appid), + new Claim(JwtClaimTypes.Issuer, _jwtModel.Issuer), + new Claim(JwtClaimTypes.Name, userInfo.Account), + new Claim(JwtClaimTypes.Id, userInfo.Id.ToString()), + new Claim(JwtClaimTypes.Role, userInfo.RoleId.ToString()), + new Claim(JwtClaimTypes.Subject, GrantType.Password) + }), + Expires = expires, + //对称秘钥SymmetricSecurityKey + //签名证书(秘钥,加密算法)SecurityAlgorithms + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), + SecurityAlgorithms.HmacSha256Signature) + }; + SecurityToken token = tokenHandler.CreateToken(tokenDescripor); + string tokenString = tokenHandler.WriteToken(token); + TokenResult result = new TokenResult + { + AccessToken = tokenString, + ExpiresIn = (int)TimeSpan.FromMinutes(_jwtModel.Expiration).TotalMinutes + }; + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Properties/PublishProfiles/FolderProfile.pubxml b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..377dd20 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,16 @@ + + + + + False + False + True + Release + Any CPU + FileSystem + bin\Release\net6.0\publish\ + FileSystem + + \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/DBConnResult.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/DBConnResult.cs new file mode 100644 index 0000000..9c431b7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/DBConnResult.cs @@ -0,0 +1,24 @@ +using System; +using System.Runtime.Serialization; + +namespace Znyc.Admin.AspNetCore.ViewModel +{ + /// + /// 数据库连接返回结果实体 + /// + [Serializable] + public class DBConnResult + { + /// + /// 未加密字符串 + /// + [DataMember] + public string ConnStr { get; set; } + + /// + /// 数据库名称 + /// + [DataMember] + public string EncryptConnStr { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/DbConnInfo.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/DbConnInfo.cs new file mode 100644 index 0000000..5c959de --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/DbConnInfo.cs @@ -0,0 +1,48 @@ +using System; +using System.Runtime.Serialization; + +namespace Znyc.Admin.AspNetCore.ViewModel +{ + /// + /// 数据库连接字符串实体 + /// + [Serializable] + public class DbConnInfo + { + /// + /// 访问地址 + /// + [DataMember] + public string DbAddress { get; set; } + + /// + /// 端口,默认SQLServer为1433;Mysql为3306 + /// + [DataMember] + public int DbPort { get; set; } + + /// + /// 数据库名称 + /// + [DataMember] + public string DbName { get; set; } + + /// + /// 用户名 + /// + [DataMember] + public string DbUserName { get; set; } + + /// + /// 访问密码 + /// + [DataMember] + public string DbPassword { get; set; } + + /// + /// 数据库类型 + /// + [DataMember] + public string DbType { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/SearchModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/SearchModel.cs new file mode 100644 index 0000000..07314d8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/SearchModel.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.Serialization; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.AspNetCore.ViewModel +{ + /// + /// 查询条件公共实体类 + /// + [Serializable] + [DataContract] + public class SearchModel : PagerInfo + { + /// + /// 关键词 + /// + public string Keywords { get; set; } + + /// + /// 编码/代码 + /// + public string EnCode { get; set; } + + /// + /// 排序方式 默认asc + /// + public string Order { get; set; } + + /// + /// 排序字段 默认Id + /// + public string Sort { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/UpdateEnableViewModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/UpdateEnableViewModel.cs new file mode 100644 index 0000000..02e9343 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/UpdateEnableViewModel.cs @@ -0,0 +1,22 @@ +using System; + +namespace Znyc.Admin.AspNetCore.ViewModel +{ + /// + /// 批量更新操作传入参数,如设为禁用、有效、软删除; + /// 物理删除操作是Flag无效不用传参 + /// + [Serializable] + public class UpdateEnableViewModel + { + /// + /// 主键Id集合 + /// + public dynamic[] Ids { get; set; } + + /// + /// 有效标识,默认为1:即设为无效,0:有效 + /// + public string Flag { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/VueCascaderModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/VueCascaderModel.cs new file mode 100644 index 0000000..7f3abc1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/VueCascaderModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace Znyc.Admin.AspNetCore.ViewModel +{ + /// + /// Vue Cascader 级联选择模型 + /// + [Serializable] + public class VueCascaderModel + { + /// + /// 值 + /// + public string value { get; set; } + + /// + /// 显示名称 + /// + public string label { get; set; } + + /// + /// 子集 + /// + public List children { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/VuexMenusTree.cs b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/VuexMenusTree.cs new file mode 100644 index 0000000..a625614 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/ViewModel/VuexMenusTree.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; + +namespace Znyc.Admin.AspNetCore.ViewModel +{ + /// + /// Vuex菜单模型 + /// + [Serializable] + public class VuexMenusTreeModel + { + /// + /// 字符串,对应当前路由的路径,总是解析为绝对路径 + /// + public string path { get; set; } + + /// + /// 命名视图组件 + /// + public string component { get; set; } + + /// + /// 重定向地址,在面包屑中点击会重定向去的地址 + /// + public string redirect { get; set; } + + /// + /// 设定路由的名字,一定要填写不然使用keep-alive时会出现各种问题 + /// + public string name { get; set; } + + /// + /// 在根路由设置权限,这样它下面所以的子路由都继承了这个权限 + /// + public Meta meta { get; set; } + + /// + /// 子菜单 + /// + public List children { get; set; } + } + + /// + /// VuexMenus路由模型 + /// + [Serializable] + public class VuexMenus + { + /// + /// 访问路径 + /// + public string path { get; set; } + + /// + /// 对应模块 + /// + public string component { get; set; } + + /// + /// 重定向地址,在面包屑中点击会重定向去的地址 + /// + public string redirect { get; set; } + + /// + /// 设定路由的名字,一定要填写不然使用keep-alive时会出现各种问题 + /// + public string name { get; set; } + + /// + /// + /// + public Meta meta { get; set; } + } + + /// + /// 路由元信息模型 + /// + [Serializable] + public class Meta + { + /// + /// 设置该路由在侧边栏和面包屑中展示的名字 + /// + public string title { get; set; } + + /// + /// 设置该路由的图标 + /// + public string icon { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Znyc.Admin.AspNetCore.csproj b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Znyc.Admin.AspNetCore.csproj new file mode 100644 index 0000000..b167a4f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Znyc.Admin.AspNetCore.csproj @@ -0,0 +1,75 @@ + + + + net6.0 + + Library + + + + + Znyc.Admin + true + true + + 1.0 + + true + true + + true + Znyc.Admin.AspNetCore + + + 1.3.1.37 + MIT + + + + bin\Release\Znyc.Admin.AspNetCore.xml + bin\Release\ + + + + bin\Debug\ + bin\Debug\Znyc.Admin.AspNetCore.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/AppDbContextFactoryAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/AppDbContextFactoryAttribute.cs new file mode 100644 index 0000000..4ddb822 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/AppDbContextFactoryAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace Znyc.Admin.Commons.Attributes +{ + /// + /// 数据库上下文配置 + /// + public class AppDbContextFactoryAttribute : Attribute + { + /// + /// 数据库配置名称 + /// + public string DbConfigName { get; set; } + + /// + /// + /// + /// 数据库配置名称 + public AppDbContextFactoryAttribute(string dbConfigName) + { + DbConfigName = dbConfigName; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/ShardingTableAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/ShardingTableAttribute.cs new file mode 100644 index 0000000..54c8c9e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/ShardingTableAttribute.cs @@ -0,0 +1,41 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Znyc.Admin.Commons.Attributes +{ + /// + /// 数据库分表特性 + /// + public class ShardingTableAttribute : TableAttribute + { + /// + /// 分隔符 + /// + public string Splitter { get; set; } = "_"; + + /// + /// 分表后缀格式。默认值:_yyyyMMdd + /// + public string Suffix { get; set; } = "yyyyMMdd"; + + /// + /// + /// + /// + public ShardingTableAttribute(string name) : base(name) + { + Suffix = "yyyyMMdd"; + Splitter = "_"; + } + + /// + /// + /// + /// + /// + /// + public ShardingTableAttribute(string name, string splitter = "_", string suffix = "yyyyMMdd") : base(name) + { + Suffix = suffix; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/UnitOfWorkAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/UnitOfWorkAttribute.cs new file mode 100644 index 0000000..471e83b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Attributes/UnitOfWorkAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace Znyc.Admin.Commons.Attributes +{ + /// + /// 工作单元 + /// 仅用来做特性标记 + /// + public class UnitOfWorkAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheHelper.cs new file mode 100644 index 0000000..9ab27c5 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheHelper.cs @@ -0,0 +1,427 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.App; + +namespace Znyc.Admin.Commons.Cache +{ + /// + /// 缓存操作帮助类 + /// + public class CacheHelper + { + /// + /// 缓存提供模式 + /// + private static CacheProvider cacheProvider; + + /// + /// 缓存接口 + /// + private readonly ICacheService cacheservice; + + /// + /// + /// + public CacheHelper() + { + cacheProvider = App.GetService(); + if (cacheProvider == null) + { + throw new ArgumentNullException(nameof(cacheProvider)); + } + else + { + cacheservice = App.GetService(); + } + } + + /// + /// 使用MemoryCache缓存操作 + /// + /// 是否使用MemoryCache + public CacheHelper(bool isMemoryCache = false) + { + cacheProvider = App.GetService(); + if (cacheProvider == null) + { + throw new ArgumentNullException(nameof(cacheProvider)); + } + else + { + if (isMemoryCache) + { + cacheservice = App.GetService(); + } + else + { + cacheservice = App.GetService(); + } + } + } + + #region 验证缓存项是否存在 + + /// + /// 验证缓存项是否存在,TryGetValue 来检测 Key是否存在的 + /// + /// 缓存Key + /// + public bool Exists(string key) + { + return cacheservice.Exists(key); + } + + #endregion 验证缓存项是否存在 + + #region 添加缓存 + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// + public bool Add(string key, object value) + { + return cacheservice.Add(key, value); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + return cacheservice.Add(key, value, expiresSliding, expiressAbsoulte); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + return cacheservice.Add(key, value, expiresIn, isSliding); + } + + #endregion 添加缓存 + + #region 删除缓存 + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public bool Remove(string key) + { + return cacheservice.Remove(key); + } + + /// + /// 批量删除缓存 + /// + /// 缓存Key集合 + /// + public void RemoveAll(IEnumerable keys) + { + cacheservice.RemoveAll(keys); + } + + /// + /// 删除匹配到的缓存 + /// + /// + /// + public void RemoveByPattern(string pattern) + { + cacheservice.RemoveByPattern(pattern); + } + + /// + /// 删除所有缓存 + /// + public void RemoveCacheAll() + { + cacheservice.RemoveCacheAll(); + } + + #endregion 删除缓存 + + #region 获取缓存 + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public T Get(string key) where T : class + { + return cacheservice.Get(key); + } + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public object Get(string key) + { + return cacheservice.Get(key); + } + + /// + /// 获取缓存集合 + /// + /// 缓存Key集合 + /// + public IDictionary GetAll(IEnumerable keys) + { + return cacheservice.GetAll(keys); + } + + #endregion 获取缓存 + + #region 修改缓存 + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// + public bool Replace(string key, object value) + { + return cacheservice.Replace(key, value); + } + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + return cacheservice.Replace(key, value, expiresSliding, expiressAbsoulte); + } + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + return cacheservice.Replace(key, value, expiresIn, isSliding); + } + + #endregion 修改缓存 + + #region Hash + /// + /// + /// + /// + /// + /// + /// + public bool HSet(string key, string filed, object value) + { + return cacheservice.HSet(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + /// + public Task HSetAsync(string key, string filed, object value) + { + return cacheservice.HSetAsync(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + public Task HMSetAsync(string key, object[] value) + { + return cacheservice.HMSetAsync(key, value); + } + + /// + /// + /// + /// + /// + /// + public bool HMSet(string key, object[] value) + { + return cacheservice.HMSet(key, value); + } + + /// + /// + /// + /// + /// + /// + public string[] HMGet(string key, string[] filed) + { + return cacheservice.HMGet(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HMGetAsync(string key, string filed) + { + return cacheservice.HMGetAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public long HDel(string key, string[] filed) + { + return cacheservice.HDel(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HDelAsync(string key, string filed) + { + return cacheservice.HDelAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public bool HExists(string key, string filed) + { + return cacheservice.HExists(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HExistsAsync(string key, string filed) + { + return cacheservice.HExistsAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HIncrAsync(string key, string filed) + { + return cacheservice.HIncrByAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public long HIncr(string key, string filed) + { + return cacheservice.HIncrBy(key, filed); + } + + /// + /// + /// + /// + /// + public Task> HGetAllAsync(string key) + { + return cacheservice.HGetAllAsync(key); + } + + /// + /// + /// + /// + /// + public Dictionary HGetAll(string key) + { + return cacheservice.HGetAll(key); + } + + /// + /// + /// + /// + /// + /// + public Task HGetAsync(string key, string filed) + { + return cacheservice.HGetAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + /// + public Task HSetNxAsync(string key, string filed, object value) + { + return cacheservice.HSetNxAsync(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + /// + public bool HSetNx(string key, string filed, object value) + { + return cacheservice.HSetNx(key, filed, value); + } + + #endregion Hash + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheKey.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheKey.cs new file mode 100644 index 0000000..f5eacc9 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheKey.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Znyc.Admin.Commons.Cache +{ + public class CacheKey + { + /// + /// 默认密码 + /// + public const string DEFAULT_PASSWORD = "a123456"; + + /// + /// 默认超速速度 + /// + public const int DEFAULT_OVERSPEED = 80; + + /// + /// 默认加密盐 + /// + public const string DEFAULT_PASSWORD_SALT = "a4abd4acbdbdcc1c04b92735b6b22740"; + + /// + /// 用户缓存 + /// + public const string CACHE_KEY_USER = "user_"; + + /// + /// 菜单缓存 + /// + public const string CACHE_KEY_MENU = "menu_"; + + /// + /// 权限缓存 + /// + public const string CACHE_KEY_PERMISSION = "permission_"; + + /// + /// 数据范围缓存 + /// + public const string CACHE_KEY_DATASCOPE = "datascope_"; + + /// + /// 验证码缓存 + /// + public const string CACHE_KEY_CODE = "vercode_"; + + /// + ///角色缓存 + /// + public const string CACHE_KEY_ROLE = "rolelist"; + + /// + ///角色菜单缓存 + /// + public const string CACHE_KEY_ROLEMENU = "rolemenulist_"; + + /// + ///车辆类型缓存 + /// + public const string CACHE_KEY_VEHICLETYPE = "vehicletypelist"; + + /// + ///车辆分组缓存 + /// + public const string CACHE_KEY_VEHICLEGROUP = "vehiclegroup_"; + + /// + ///字典缓存 + /// + public const string CACHE_KEY_DICTIONARY = "dictionarylist"; + + /// + ///默认logo地址 + /// + public const string DEFAULT_COMPANYLOG = "https://Znyc-public-1304677865.cos.ap-guangzhou.myqcloud.com/Logo.png"; + + /// + /// 头像地址前缀 + /// + public const string Prefix_AvataUrl = "https://zhongnengyunche.com/dispatching/wx/upload/avatar/"; + + /// + ///默认头像地址 + /// + public const string DEFAULT_AVATARURL = "Default_AvatarUrl.png"; + + /// + /// 公司缓存 + /// + public const string CACHE_KEY_COMPANY = "company_"; + + /// + /// JWT + /// + + public const string CACHE_KEY_JWT = "jwt_"; + + /// + /// token + /// + public const string CACHE_KEY_TOKEN = "token:{0}"; + + /// + ///公司车辆缓存 + /// + public const string CACHE_KEY_VehicleByCompanyId = "vehicles:company_"; + + /// + /// 车辆缓存 + /// + public const string CACHE_KEY_Vehicle = "vehicle:_"; + + /// + /// 车辆GPS信息缓存 + /// + public const string CACHE_KEY_VehicleGps = "vehiclegps_{0}:{1}"; + + /// + /// 超速记录缓存 + /// + public const string CACHE_KEY_VehicleAlert = "vehiclealert_{0}:{1}:{2}"; + + /// + /// 员工缓存 + /// + public const string CACHE_KEY_EMPLOYEE = "employee:{0}"; + + /// + /// 员工列表缓存 + /// + public const string CACHE_KEY_EMPLOYEES = "employees:{0}"; + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheProvider.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheProvider.cs new file mode 100644 index 0000000..14fade8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/CacheProvider.cs @@ -0,0 +1,40 @@ +namespace Znyc.Admin.Commons.Cache +{ + /// + /// 缓存提供模式,使用Redis或MemoryCache + /// + public class CacheProvider + { + private bool _isUseRedis; + + private string _connectionString; + private string _instanceName; + + /// + /// 是否使用Redis + /// + public bool IsUseRedis + { + get => _isUseRedis; + set => _isUseRedis = value; + } + + /// + /// Redis连接 + /// + public string ConnectionString + { + get => _connectionString; + set => _connectionString = value; + } + + /// + /// Redis实例名称 + /// + public string InstanceName + { + get => _instanceName; + set => _instanceName = value; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/ICacheService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/ICacheService.cs new file mode 100644 index 0000000..98fa914 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/ICacheService.cs @@ -0,0 +1,317 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Znyc.Admin.Commons.Cache +{ + /// + /// 缓存服务接口 + /// + public interface ICacheService + { + #region 验证缓存项是否存在 + + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + bool Exists(string key); + + #endregion 验证缓存项是否存在 + + #region 添加缓存 + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// + bool Add(string key, object value); + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte); + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false); + + /// + /// + /// + /// + /// + /// + /// + Task HashSetAsync(string key, string filed, object value); + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// + Task AddAsync(string key, object value); + + /// + /// / + /// + /// + /// + /// + /// + /// + Task AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false); + + #endregion 添加缓存 + + #region 删除缓存 + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + bool Remove(string key); + + /// + /// 批量删除缓存 + /// + /// 缓存Key集合 + /// + void RemoveAll(IEnumerable keys); + + /// + /// 使用通配符找出所有的key然后逐个删除 + /// + /// 通配符 + void RemoveByPattern(string pattern); + + /// + /// 删除所有缓存 + /// + void RemoveCacheAll(); + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + Task RemoveAsync(string key); + + #endregion 删除缓存 + + #region 获取缓存 + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + T Get(string key) where T : class; + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + object Get(string key); + + /// + /// 获取缓存集合 + /// + /// 缓存Key集合 + /// + IDictionary GetAll(IEnumerable keys); + + #endregion 获取缓存 + + #region 修改缓存 + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// + bool Replace(string key, object value); + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte); + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false); + + #endregion 修改缓存 + + #region Hash + + /// + /// + /// + /// + /// + /// + /// + bool HSet(string key, string filed, object value); + + /// + /// + /// + /// + /// + /// + /// + Task HSetAsync(string key, string filed, object value); + + /// + /// + /// + /// + /// + /// + Task HMSetAsync(string key, object[] value); + + /// + /// + /// + /// + /// + /// + bool HMSet(string key, object[] value); + + /// + /// + /// + /// + /// + /// + string[] HMGet(string key, string[] filed); + + /// + /// + /// + /// + /// + /// + Task HMGetAsync(string key, string filed); + + /// + /// + /// + /// + /// + /// + long HDel(string key, string[] filed); + + /// + /// + /// + /// + /// + /// + Task HDelAsync(string key, string filed); + + /// + /// + /// + /// + /// + /// + bool HExists(string key, string filed); + + /// + /// + /// + /// + /// + /// + Task HExistsAsync(string key, string filed); + + /// + /// 自增 + /// + /// + /// + /// + Task HIncrByAsync(string key, string filed); + + /// + /// 自增 + /// + /// + /// + /// + long HIncrBy(string key, string filed); + + /// + /// 获取所有 + /// + /// + /// + Task> HGetAllAsync(string key); + + /// + /// 获取所有 + /// + /// + /// + Dictionary HGetAll(string key); + + /// + /// + /// + /// + /// + /// + Task HGetAsync(string key, string filed); + + /// + /// 设置一个键值对(不存在,则创建;否则,修改) + /// + /// + /// + /// + /// + Task HSetNxAsync(string key, string filed, object value); + + /// + /// 设置一个键值对(不存在,则创建;否则,修改) + /// + /// + /// + /// + /// + bool HSetNx(string key, string filed, object value); + + #endregion + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/MemoryCacheService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/MemoryCacheService.cs new file mode 100644 index 0000000..4d20fcb --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/MemoryCacheService.cs @@ -0,0 +1,613 @@ +using Microsoft.Extensions.Caching.Memory; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Znyc.Admin.Commons.Cache +{ + /// + /// MemoryCache缓存操作 + /// + public class MemoryCacheService : ICacheService + { + /// + /// + /// + protected IMemoryCache _cache; + + /// + /// + /// + /// + public MemoryCacheService(IMemoryCache cache) + { + _cache = cache; + } + + #region 验证缓存项是否存在 + + /// + /// 验证缓存项是否存在,TryGetValue 来检测 Key是否存在的 + /// + /// 缓存Key + /// + public bool Exists(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.TryGetValue(key, out object cached); + } + + #endregion 验证缓存项是否存在 + + #region 添加缓存 + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// + public bool Add(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _cache.Set(key, value); + return Exists(key); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _cache.Set(key, value, + new MemoryCacheEntryOptions() + .SetSlidingExpiration(expiresSliding) + .SetAbsoluteExpiration(expiressAbsoulte) + ); + + return Exists(key); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (isSliding) + { + _cache.Set(key, value, + new MemoryCacheEntryOptions() + .SetSlidingExpiration(expiresIn) + ); + } + else + { + _cache.Set(key, value, + new MemoryCacheEntryOptions() + .SetAbsoluteExpiration(expiresIn) + ); + } + + return Exists(key); + } + + public Task HashSetAsync(string key, string filed, object value) + { + throw new NotImplementedException(); + } + + #endregion 添加缓存 + + #region 删除缓存 + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public bool Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + _cache.Remove(key); + + return !Exists(key); + } + + /// + /// 批量删除缓存 + /// + /// 缓存Key集合 + /// + public void RemoveAll(IEnumerable keys) + { + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + keys.ToList().ForEach(item => _cache.Remove(item)); + } + + /// + /// 删除所有缓存 + /// + public void RemoveCacheAll() + { + List l = GetCacheKeys(); + foreach (string s in l) + { + Remove(s); + } + } + + /// + /// 删除匹配到的缓存 + /// + /// + /// + public void RemoveByPattern(string pattern) + { + IList l = SearchCacheRegex(pattern); + foreach (string s in l) + { + Remove(s); + } + } + + /// + /// 搜索 匹配到的缓存 + /// + /// + /// + public IList SearchCacheRegex(string pattern) + { + List cacheKeys = GetCacheKeys(); + List l = cacheKeys.Where(k => Regex.IsMatch(k, pattern)).ToList(); + return l.AsReadOnly(); + } + + #endregion 删除缓存 + + #region 获取缓存 + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public T Get(string key) where T : class + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.Get(key) as T; + } + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public object Get(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.Get(key); + } + + /// + /// 获取缓存集合 + /// + /// 缓存Key集合 + /// + public IDictionary GetAll(IEnumerable keys) + { + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + Dictionary dict = new Dictionary(); + + keys.ToList().ForEach(item => dict.Add(item, _cache.Get(item))); + + return dict; + } + + /// + /// 获取所有缓存键 + /// + /// + public List GetCacheKeys() + { + const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; + object entries = _cache.GetType().GetField("_entries", flags).GetValue(_cache); + IDictionary cacheItems = entries as IDictionary; + List keys = new List(); + if (cacheItems == null) + { + return keys; + } + + foreach (DictionaryEntry cacheItem in cacheItems) + { + keys.Add(cacheItem.Key.ToString()); + } + + return keys; + } + + #endregion 获取缓存 + + #region 修改缓存 + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// + public bool Replace(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (Exists(key)) + { + if (!Remove(key)) + { + return false; + } + } + + return Add(key, value); + } + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (Exists(key)) + { + if (!Remove(key)) + { + return false; + } + } + + return Add(key, value, expiresSliding, expiressAbsoulte); + } + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (Exists(key)) + { + if (!Remove(key)) + { + return false; + } + } + + return Add(key, value, expiresIn, isSliding); + } + + #endregion 修改缓存 + + /// + /// + /// + public void Dispose() + { + if (_cache != null) + { + _cache.Dispose(); + } + + GC.SuppressFinalize(this); + } + + public Task AddAsync(string key, object value) + { + throw new NotImplementedException(); + } + + public Task AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + throw new NotImplementedException(); + } + + public Task RemoveAsync(string key) + { + throw new NotImplementedException(); + } + + #region Hash + /// + /// + /// + /// + /// + /// + /// + public bool HSet(string key, string filed, object value) + { + return RedisHelper.HSet(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + /// + public Task HSetAsync(string key, string filed, object value) + { + return RedisHelper.HSetAsync(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + public Task HMSetAsync(string key, object[] value) + { + return RedisHelper.HMSetAsync(key, value); + } + + /// + /// + /// + /// + /// + /// + public bool HMSet(string key, object[] value) + { + return RedisHelper.HMSet(key, value); + } + + /// + /// + /// + /// + /// + /// + public string[] HMGet(string key, string[] filed) + { + return RedisHelper.HMGet(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HMGetAsync(string key, string filed) + { + return RedisHelper.HMGetAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public long HDel(string key, string[] filed) + { + return RedisHelper.HDel(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HDelAsync(string key, string filed) + { + return RedisHelper.HDelAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public bool HExists(string key, string filed) + { + return RedisHelper.HExists(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HExistsAsync(string key, string filed) + { + return RedisHelper.HExistsAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HIncrByAsync(string key, string filed) + { + return RedisHelper.HIncrByAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public long HIncrBy(string key, string filed) + { + return RedisHelper.HIncrBy(key, filed); + } + + /// + /// + /// + /// + /// + public Task> HGetAllAsync(string key) + { + return RedisHelper.HGetAllAsync(key); + } + + /// + /// + /// + /// + /// + public Dictionary HGetAll(string key) + { + return RedisHelper.HGetAll(key); + } + + /// + /// + /// + /// + /// + /// + public async Task HGetAsync(string key, string filed) + { + return await RedisHelper.HGetAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + /// + public Task HSetNxAsync(string key, string filed, object value) + { + return RedisHelper.HSetNxAsync(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + /// + public bool HSetNx(string key, string filed, object value) + { + return RedisHelper.HSetNx(key, filed, value); + } + + #endregion Hash + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/RedisCacheService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/RedisCacheService.cs new file mode 100644 index 0000000..d9cccf8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Cache/RedisCacheService.cs @@ -0,0 +1,656 @@ +using Microsoft.Extensions.Caching.StackExchangeRedis; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; + +namespace Znyc.Admin.Commons.Cache +{ + /// + /// Redis缓存操作 + /// + public class RedisCacheService : ICacheService + { + /// + /// + /// + protected IDatabase _cache; + + /// + /// + /// + private readonly ConnectionMultiplexer _connection; + + /// + /// + /// + private readonly string _instance; + + private readonly JsonSerializerOptions _jsonOptions; + + /// + /// + /// + /// + /// + /// + public RedisCacheService(RedisCacheOptions options, JsonSerializerOptions jsonOptions, int database = 6) + { + _connection = ConnectionMultiplexer.Connect(options.Configuration); + _cache = _connection.GetDatabase(database); + _instance = options.InstanceName; + _jsonOptions = jsonOptions; + } + + /// + /// + /// + /// + /// + public string GetKeyForRedis(string key) + { + return _instance + key; + } + + #region 验证缓存项是否存在 + + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + public bool Exists(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.KeyExists(GetKeyForRedis(key)); + } + + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + public Task ExistsAsync(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.KeyExistsAsync(GetKeyForRedis(key)); + } + + #endregion 验证缓存项是否存在 + + #region 添加缓存 + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// + public bool Add(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.StringSet(GetKeyForRedis(key), + Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions))); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效) + /// 绝对过期时长 + /// + public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.StringSet(GetKeyForRedis(key), + Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiressAbsoulte); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效) + /// + public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.StringSet(GetKeyForRedis(key), + Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiresIn); + } + + public Task AddAsync(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.StringSetAsync(GetKeyForRedis(key), + Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions))); + } + + public Task AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.StringSetAsync(GetKeyForRedis(key), + Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiressAbsoulte); + } + + public Task AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.StringSetAsync(GetKeyForRedis(key), + Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiresIn); + } + + public Task HashSetAsync(string key, string filed, object value) + { + return _cache.HashSetAsync(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(filed, _jsonOptions)), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions))); + } + + #endregion 添加缓存 + + #region 删除缓存 + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public bool Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.KeyDelete(GetKeyForRedis(key)); + } + + /// + /// 批量删除缓存 + /// + /// 缓存Key集合 + /// + public void RemoveAll(IEnumerable keys) + { + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + keys.ToList().ForEach(item => Remove(item)); + } + + /// + /// + /// + /// + /// + public Task RemoveAsync(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _cache.KeyDeleteAsync(GetKeyForRedis(key)); + } + + public Task RemoveAllAsync(IEnumerable keys) + { + //if (keys == null) + //{ + throw new ArgumentNullException(nameof(keys)); + //} + + //keys.ToList().ForEach(item => RemoveAsync(item)); + } + + /// + /// 使用通配符找出所有的key然后逐个删除 + /// + /// 通配符 + public virtual void RemoveByPattern(string pattern) + { + foreach (System.Net.EndPoint ep in _connection.GetEndPoints()) + { + IServer server = _connection.GetServer(ep); + IEnumerable keys = server.Keys(pattern: "*" + pattern + "*", database: _cache.Database); + foreach (RedisKey key in keys) + { + _cache.KeyDelete(key); + } + } + } + + /// + /// 删除所有缓存 + /// + public void RemoveCacheAll() + { + RemoveByPattern(""); + } + + #endregion 删除缓存 + + #region 获取缓存 + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public T Get(string key) where T : class + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + RedisValue value = _cache.StringGet(GetKeyForRedis(key)); + + if (!value.HasValue) + { + return default(T); + } + + return JsonSerializer.Deserialize(value, _jsonOptions); + } + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public object Get(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + RedisValue value = _cache.StringGet(GetKeyForRedis(key)); + + if (!value.HasValue) + { + return null; + } + + return JsonSerializer.Deserialize(value, _jsonOptions); + //string json = value.ToString(); + //return Newtonsoft.Json.JsonConvert.DeserializeObject(json); + } + + /// + /// 获取缓存集合 + /// + /// 缓存Key集合 + /// + public IDictionary GetAll(IEnumerable keys) + { + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + Dictionary dict = new Dictionary(); + + keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item)))); + + return dict; + } + + public Task GetAsync(string key) where T : class + { + throw new NotImplementedException(); + } + + public Task GetAsync(string key) + { + throw new NotImplementedException(); + } + + public Task> GetAllAsync(IEnumerable keys) + { + throw new ArgumentNullException(nameof(keys)); + } + + #endregion 获取缓存 + + #region 修改缓存 + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// + public bool Replace(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (Exists(key)) + { + if (!Remove(key)) + { + return false; + } + } + + return Add(key, value); + } + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (Exists(key)) + { + if (!Remove(key)) + { + return false; + } + } + + return Add(key, value, expiresSliding, expiressAbsoulte); + } + + /// + /// 修改缓存 + /// + /// 缓存Key + /// 新的缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (Exists(key)) + { + if (!Remove(key)) + { + return false; + } + } + + return Add(key, value, expiresIn, isSliding); + } + + public Task ReplaceAsync(string key, object value) + { + throw new NotImplementedException(); + } + + public Task ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + throw new NotImplementedException(); + } + + public Task ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + throw new NotImplementedException(); + } + + #endregion 修改缓存 + + public void Dispose() + { + if (_connection != null) + { + _connection.Dispose(); + } + + GC.SuppressFinalize(this); + } + + #region Hash + /// + /// + /// + /// + /// + /// + /// + public bool HSet(string key, string filed, object value) + { + return RedisHelper.HSet(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + /// + public Task HSetAsync(string key, string filed, object value) + { + return RedisHelper.HSetAsync(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + public Task HMSetAsync(string key, object[] value) + { + return RedisHelper.HMSetAsync(key, value); + } + + /// + /// + /// + /// + /// + /// + public bool HMSet(string key, object[] value) + { + return RedisHelper.HMSet(key, value); + } + + /// + /// + /// + /// + /// + /// + public string[] HMGet(string key, string[] filed) + { + return RedisHelper.HMGet(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HMGetAsync(string key, string filed) + { + return RedisHelper.HMGetAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public long HDel(string key, string[] filed) + { + return RedisHelper.HDel(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HDelAsync(string key, string filed) + { + return RedisHelper.HDelAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public bool HExists(string key, string filed) + { + return RedisHelper.HExists(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HExistsAsync(string key, string filed) + { + return RedisHelper.HExistsAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public Task HIncrByAsync(string key, string filed) + { + return RedisHelper.HIncrByAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + public long HIncrBy(string key, string filed) + { + return RedisHelper.HIncrBy(key, filed); + } + + /// + /// + /// + /// + /// + public Task> HGetAllAsync(string key) + { + return RedisHelper.HGetAllAsync(key); + } + + /// + /// + /// + /// + /// + public Dictionary HGetAll(string key) + { + return RedisHelper.HGetAll(key); + } + + /// + /// + /// + /// + /// + /// + public async Task HGetAsync(string key, string filed) + { + return await RedisHelper.HGetAsync(key, filed); + } + + /// + /// + /// + /// + /// + /// + /// + public Task HSetNxAsync(string key, string filed, object value) + { + return RedisHelper.HSetNxAsync(key, filed, value); + } + + /// + /// + /// + /// + /// + /// + /// + public bool HSetNx(string key, string filed, object value) + { + return RedisHelper.HSetNx(key, filed, value); + } + + #endregion Hash + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Commons.csproj b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Commons.csproj new file mode 100644 index 0000000..873c458 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Commons.csproj @@ -0,0 +1,235 @@ + + + + net5.0 + Yuebon + 上海越邦网络科技有限公司 + YuebonNetCore开发框架基础库 + YuebonNetCore开发框架基础库 + 上海越邦网络科技有限公司 版权所有 + true + https://gitee.com/yuebon/YuebonNetCore + 1.3.1.32 + true + + + https://gitee.com/yuebon/YuebonNetCore + LICENSE + logo.png + 1.3.1.32 + + + + bin\Debug\ZNYC.Admin.Commons.xml + bin\Debug\ + + + + bin\Release\ + bin\Release\ZNYC.Admin.Commons.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + + + + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + Always + + + + + + + + diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Config/Configs.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Config/Configs.cs new file mode 100644 index 0000000..6e5b79c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Config/Configs.cs @@ -0,0 +1,49 @@ +using Microsoft.Extensions.Configuration; +using Znyc.Admin.Commons.Core.App; + +namespace Znyc.Admin.Commons +{ + /// + /// 配置文件读取操作 + /// + public class Configs + { + public static IConfiguration configuration; + + static Configs() + { + configuration = App.GetService(); + } + + /// + /// 根据Key获取数配置内容 + /// + /// + /// + public static IConfigurationSection GetSection(string key) + { + return configuration.GetSection(key); + } + + /// + /// 根据section和key获取配置内容 + /// + /// + /// + /// + public static string GetConfigurationValue(string section, string key) + { + return GetSection(section)?[key]; + } + + /// + /// 根据Key获取数据库连接字符串 + /// + /// + /// + public static string GetConnectionString(string key) + { + return configuration.GetConnectionString(key); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/CommonConst.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/CommonConst.cs new file mode 100644 index 0000000..43457a3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/CommonConst.cs @@ -0,0 +1,40 @@ + +namespace Znyc.Admin.Commons.Const +{ + /// + /// + /// + public class CommonConst + { + /// + /// 默认超速速度 + /// + public const int DEFAULT_OVERSPEED = 80; + + /// + /// 默认停留标示Id + /// + public const long DEFAULT_STAPTAG = 1003; + + /// + /// 默认图片地址 + /// + public const string Default_Image_Prefix = + "https://zhongnengyunche.com/dispatching/wx/upload/avatar/"; + + /// + /// 默认公司Logo名称 + /// + public const string Default_CompanyLogo = "Default_AvatarUrl.png"; + + /// + /// 未知设备型号 + /// + public const string Unknown_TerminalType = "未知设备型号"; + + /// + /// 未知物联卡类型 + /// + public const string Unknown_CardType = "未知物联卡类型"; + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/ReturnConst.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/ReturnConst.cs new file mode 100644 index 0000000..b87a95f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/ReturnConst.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Znyc.Admin.Commons.Const +{ + /// + /// 返回 + /// + public static class ReturnConst + { + /// + /// + /// + public const string Password_Error = "密码错误,请重新输入。"; + + /// + /// + /// + public const string User_Not_Exist = "系统不存在该用户,请重新确认。"; + + /// + /// + /// + public const string User_Disable = "该用户已被禁用,请联系管理员。"; + + /// + /// 公司审核报错 + /// + public const string Audit_Error = "该信息未在审核中!"; + + + /// + /// 公司审核报错 + /// + public const string Audit_Repeat = "一个用户只能注册一个账套,抱歉!"; + + + /// + /// 公司审核结果-通过 + /// + public const string Audit_Success = "审核成功"; + + /// + /// 公司审核结果-失败 + /// + public const string Audit_Failed = "审核失败"; + + /// + /// 公司审核成功备注 + /// + public const string Audit_Success_Note = "您的初始密码为:a123456,前往登陆"; + + /// + /// 公司审核失败备注 + /// + public const string Audit_Failed_Note = " "; + + /// + /// 编号或车牌号重复 + /// + public const string Vehicle_Repeat = "编号或车牌号重复"; + + /// + /// Sim卡号或IMEI号重复 + /// + public const string Vehicle_Equipment_Repeat = "Sim卡号或IMEI号与车牌号为{0}的车辆重复"; + + /// + /// 车辆信息不存在 + /// + public const string Vehicle_Not_Exist = "车辆信息不存在"; + + + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/SysConst.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/SysConst.cs new file mode 100644 index 0000000..3732819 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Const/SysConst.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Znyc.Admin.Commons.Const +{ + /// + /// 系统常量 + /// + public class SysConst + { + /// + /// 环境 + /// + public const string ASPNETCORE_ENVIRONMENT = "ASPNETCORE_ENVIRONMENT"; + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/App.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/App.cs new file mode 100644 index 0000000..a151a9a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/App.cs @@ -0,0 +1,289 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace Znyc.Admin.Commons.Core.App +{ + /// + /// 全局应用类 + /// + public static class App + { + /// + /// 全局配置选项 + /// + public static IConfiguration Configuration; + + /// + /// 应用服务 + /// + public static IServiceCollection Services; + + /// + /// 全局配置构建器 + /// + private static IConfigurationBuilder ConfigurationBuilder; + + /// + /// 私有环境变量,避免重复解析 + /// + private static IWebHostEnvironment _webHostEnvironment; + + /// + /// 应用环境,如,是否是开发环境,生产环境等 + /// + public static IWebHostEnvironment WebHostEnvironment => + _webHostEnvironment ??= GetService(); + + /// + /// 应用有效程序集 + /// + public static readonly IEnumerable Assemblies; + + /// + /// 有效程序集类型 + /// + public static readonly IEnumerable EffectiveTypes; + + /// + /// 服务提供器 + /// + public static IServiceProvider ServiceProvider => + HttpContext?.RequestServices ?? Services.BuildServiceProvider(); + + /// + /// 获取请求上下文 + /// + public static HttpContext HttpContext => HttpContextLocal.Current(); + + /// + /// 获取请求生命周期的服务 + /// + /// + /// + public static TService GetService() + where TService : class + { + return GetService(typeof(TService)) as TService; + } + + /// + /// 获取请求生命周期的服务 + /// + /// + /// + public static object GetService(Type type) + { + return ServiceProvider.GetService(type); + } + + /// + /// 获取请求生命周期的服务 + /// + /// + /// + public static TService GetRequiredService() + where TService : class + { + return GetRequiredService(typeof(TService)) as TService; + } + + /// + /// 获取请求生命周期的服务 + /// + /// + /// + public static object GetRequiredService(Type type) + { + return ServiceProvider.GetRequiredService(type); + } + + /// + /// 获取选项 + /// + /// 强类型选项类 + /// TOptions + public static TOptions GetOptions() + where TOptions : class, new() + { + return GetService>()?.Value; + } + + /// + /// 获取选项 + /// + /// 强类型选项类 + /// TOptions + public static TOptions GetOptionsMonitor() + where TOptions : class, new() + { + return GetService>()?.CurrentValue; + } + + /// + /// 获取选项 + /// + /// 强类型选项类 + /// TOptions + public static TOptions GetOptionsSnapshot() + where TOptions : class, new() + { + return GetService>()?.Value; + } + + /// + /// 构造函数 + /// + static App() + { + // 编译配置 + // Configuration =ConfigurationBuilder.Build(); + } + + #region + + /// + /// 添加配置文件 + /// + /// + /// + internal static void AddConfigureFiles(IConfigurationBuilder config, IHostEnvironment env) + { + // 读取忽略的配置文件 + string[] ignoreConfigurationFiles = config.Build() + .GetSection("IgnoreConfigurationFiles").Get() + ?? Array.Empty(); + + // 加载配置 + AutoAddJsonFiles(config, env, ignoreConfigurationFiles); + AutoAddXmlFiles(config, env, ignoreConfigurationFiles); + + // 存储配置 + ConfigurationBuilder = config; + } + + /// + /// 自动加载自定义 .json 配置文件 + /// + /// + /// + /// + public static void AutoAddJsonFiles(IConfigurationBuilder config, IHostEnvironment env, + string[] ignoreConfigurationFiles) + { + // 获取程序目录下的所有配置文件 + IEnumerable jsonFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.json", SearchOption.TopDirectoryOnly) + .Union( + Directory.GetFiles(Directory.GetCurrentDirectory(), "*.json", SearchOption.TopDirectoryOnly) + ) + .Where(u => !excludeJsons.Contains(Path.GetFileName(u)) && + !ignoreConfigurationFiles.Contains(Path.GetFileName(u)) && + !runtimeJsonSuffixs.Any(j => u.EndsWith(j))); + + if (!jsonFiles.Any()) + { + return; + } + + // 获取环境变量名 + string envName = env.EnvironmentName; + List envFiles = new List(); + + // 自动加载配置文件 + foreach (string jsonFile in jsonFiles) + { + // 处理带环境的配置文件 + if (Path.GetFileNameWithoutExtension(jsonFile).EndsWith($".{envName}")) + { + envFiles.Add(jsonFile); + continue; + } + + config.AddJsonFile(jsonFile, true, true); + } + + // 配置带环境的配置文件 + envFiles.ForEach(u => config.AddJsonFile(u, true, true)); + } + + /// + /// 自动加载自定义 .xml 配置文件 + /// + /// + /// + /// + public static void AutoAddXmlFiles(IConfigurationBuilder config, IHostEnvironment env, + string[] ignoreConfigurationFiles) + { + // 获取程序目录下的所有配置文件,必须以 .config.xml 结尾 + IEnumerable xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml", SearchOption.TopDirectoryOnly) + .Union( + Directory.GetFiles(Directory.GetCurrentDirectory(), "*.xml", SearchOption.TopDirectoryOnly) + ) + .Where(u => !ignoreConfigurationFiles.Contains(Path.GetFileName(u)) && + u.EndsWith(".config.xml", StringComparison.OrdinalIgnoreCase)); + + if (!xmlFiles.Any()) + { + return; + } + + // 获取环境变量名 + string envName = env.EnvironmentName; + List envFiles = new List(); + + // 自动加载配置文件 + foreach (string xmlFile in xmlFiles) + { + // 处理带环境的配置文件 + if (Path.GetFileNameWithoutExtension(xmlFile).EndsWith($".{envName}.config")) + { + envFiles.Add(xmlFile); + continue; + } + + config.AddXmlFile(xmlFile, true, true); + } + + // 配置带环境的配置文件 + envFiles.ForEach(u => config.AddXmlFile(u, true, true)); + } + + /// + /// 默认排除配置项 + /// + private static readonly string[] excludeJsons = new[] + { + "appsettings.json", + "appsettings.Development.json", + "appsettings.Production.json", + "bundleconfig.json", + "bundleconfig.Development.json", + "bundleconfig.Production.json", + "compilerconfig.json", + "compilerconfig.Development.json", + "compilerconfig.Production.json" + }; + + /// + /// 排除运行时 Json 后缀 + /// + private static readonly string[] runtimeJsonSuffixs = new[] + { + "deps.json", + "runtimeconfig.dev.json", + "runtimeconfig.prod.json", + "runtimeconfig.json" + }; + + #endregion + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/HostingStartup.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/HostingStartup.cs new file mode 100644 index 0000000..79f0d09 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/HostingStartup.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Hosting; + +//通过HostingStartup指定要启动的类型 +[assembly: HostingStartup(typeof(Znyc.Admin.Commons.Core.App.HostingStartup))] + +namespace Znyc.Admin.Commons.Core.App +{ + /// + /// 配置程序启动时自动注入 + /// + public sealed class HostingStartup : IHostingStartup + { + /// + /// 配置应用启动 + /// + /// + public void Configure(IWebHostBuilder builder) + { + //可以添加配置 + builder.ConfigureAppConfiguration((hostingContext, config) => + { + // 自动装载配置 + App.AddConfigureFiles(config, hostingContext.HostingEnvironment); + }); + + //可以添加ConfigureServices + // 自动注入 AddApp() 服务 + builder.ConfigureServices(services => { }); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/HttpContextLocal.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/HttpContextLocal.cs new file mode 100644 index 0000000..b723858 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/App/HttpContextLocal.cs @@ -0,0 +1,69 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Linq.Expressions; +using System.Reflection; +using System.Threading; + +namespace Znyc.Admin.Commons.Core.App +{ + /// + /// 获取 HttpContext 上下文 + /// + public static class HttpContextLocal + { + private static Func _asyncLocalAccessor; + private static Func _holderAccessor; + private static Func _httpContextAccessor; + + /// + /// 获取当前 HttpContext 对象 + /// + /// + public static HttpContext Current() + { + object asyncLocal = (_asyncLocalAccessor ??= CreateAsyncLocalAccessor())(); + if (asyncLocal == null) + { + return null; + } + + object holder = (_holderAccessor ??= CreateHolderAccessor(asyncLocal))(asyncLocal); + if (holder == null) + { + return null; + } + + return (_httpContextAccessor ??= CreateHttpContextAccessor(holder))(holder); + + // 创建异步本地访问器 + static Func CreateAsyncLocalAccessor() + { + FieldInfo fieldInfo = typeof(HttpContextAccessor).GetField("_httpContextCurrent", + BindingFlags.Static | BindingFlags.NonPublic); + MemberExpression field = Expression.Field(null, fieldInfo); + return Expression.Lambda>(field).Compile(); + } + + // 创建常驻 HttpContext 访问器 + static Func CreateHolderAccessor(object asyncLocal) + { + Type holderType = asyncLocal.GetType().GetGenericArguments()[0]; + MethodInfo method = typeof(AsyncLocal<>).MakeGenericType(holderType).GetProperty("Value").GetGetMethod(); + ParameterExpression target = Expression.Parameter(typeof(object)); + UnaryExpression convert = Expression.Convert(target, asyncLocal.GetType()); + MethodCallExpression getValue = Expression.Call(convert, method); + return Expression.Lambda>(getValue, target).Compile(); + } + + // 获取 HttpContext 访问器 + static Func CreateHttpContextAccessor(object holder) + { + ParameterExpression target = Expression.Parameter(typeof(object)); + UnaryExpression convert = Expression.Convert(target, holder.GetType()); + MemberExpression field = Expression.Field(convert, "Context"); + UnaryExpression convertAsResult = Expression.Convert(field, typeof(HttpContext)); + return Expression.Lambda>(convertAsResult, target).Compile(); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Application/BaseApp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Application/BaseApp.cs new file mode 100644 index 0000000..eaca6cd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Application/BaseApp.cs @@ -0,0 +1,463 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.Application +{ + /// + /// 业务层基类,Service用于普通的数据库操作 + /// + /// 实体类型 + /// 实体类型 + /// Service类型 + /// 主键类型 + public class BaseApp + where T : Entity + where TDto : class + where TService : IService + { + /// + /// 用于普通的数据库操作 + /// + /// The service. + protected IService service; + + /// + /// + /// + /// + public BaseApp(IService _service) + { + service = _service; + } + + /// + /// 同步物理删除实体。 + /// + /// 实体 + /// + public virtual bool Delete(T entity) + { + return service.Delete(entity, null); + } + + /// + /// 同步物理删除实体。 + /// + /// 主键 + /// + public virtual bool Delete(Tkey id) + { + return service.Delete(id, null); + } + + /// + /// 异步物理删除实体。 + /// + /// 主键 + /// + public virtual Task DeleteAsync(Tkey id) + { + return service.DeleteAsync(id, null); + } + + /// + /// 异步物理删除实体。 + /// + /// 实体 + /// + public virtual Task DeleteAsync(T entity) + { + return service.DeleteAsync(entity, null); + } + + /// + /// 按主键批量删除 + /// + /// + /// + public virtual bool DeleteBatch(IList ids) + { + return service.DeleteBatch(ids, null); + } + + /// + /// 按条件批量删除 + /// + /// 条件 + /// + public virtual bool DeleteBatchWhere(string where) + { + return service.DeleteBatchWhere(where, null); + } + + /// + /// 软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// + public virtual bool DeleteSoft(bool bl, Tkey id, int userId) + { + return service.DeleteSoft(bl, id, userId, null); + } + + /// + /// 异步软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// + public virtual Task DeleteSoftAsync(bool bl, Tkey id, int userId) + { + return service.DeleteSoftAsync(bl, id, userId, null); + } + + /// + /// 同步查询单个实体。 + /// + /// 主键 + /// + public virtual T Get(Tkey id) + { + return service.Get(id); + } + + /// + /// 同步查询单个实体。 + /// + /// 查询条件 + /// + public virtual T GetWhere(string where) + { + return service.GetWhere(where, null); + } + + /// + /// 异步查询单个实体。 + /// + /// 查询条件 + /// + public virtual async Task GetWhereAsync(string where) + { + return await service.GetWhereAsync(where, null); + } + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// + public virtual IEnumerable GetListTopWhere(int top, string where = null) + { + return service.GetListTopWhere(top, where); + } + + /// + /// 同步查询所有实体。 + /// + /// + public virtual IEnumerable GetAll() + { + return service.GetAll(null); + } + + /// + /// 异步步查询所有实体。 + /// + /// + public virtual Task> GetAllAsync() + { + return service.GetAllAsync(null); + } + + /// + /// + /// + /// + /// + public virtual Task GetAsync(Tkey id) + { + return service.GetAsync(id); + } + + /// + /// 根据查询条件查询数据 + /// + /// 查询条件 + /// + public virtual IEnumerable GetListWhere(string where = null) + { + return service.GetListWhere(where, null); + } + + /// + /// 异步根据查询条件查询数据 + /// + /// 查询条件 + /// + public virtual async Task> GetListWhereAsync(string where = null) + { + return await service.GetListWhereAsync(where, null); + } + + /// + /// 同步新增实体。 + /// + /// 实体 + /// + public virtual long Insert(T entity) + { + return service.Insert(entity, null); + } + + /// + /// 异步步新增实体。 + /// + /// 实体 + /// + public virtual Task InsertAsync(T entity) + { + return service.InsertAsync(entity, null); + } + + /// + /// 同步更新实体。 + /// + /// 实体 + /// 主键ID + /// + public virtual bool Update(T entity, Tkey id) + { + return service.Update(entity, id, null); + } + + /// + /// 异步更新实体。 + /// + /// 实体 + /// 主键ID + /// + public virtual Task UpdateAsync(T entity, Tkey id) + { + return service.UpdateAsync(entity, id, null); + } + + /// + /// 更新某一字段值 + /// + /// 字段 + /// 字段值 + /// 条件,为空更新所有内容 + /// + public virtual bool UpdateTableField(string strField, string fieldValue, string where) + { + return service.UpdateTableField(strField, fieldValue, where, null); + } + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// + public virtual IEnumerable GetAllByIsIsDeleted(string where = null) + { + return service.GetAllByIsIsDeleted(where, null); + } + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// + public virtual IEnumerable GetAllByIsNotIsDeleted(string where = null) + { + return service.GetAllByIsNotIsDeleted(where, null); + } + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// + public virtual IEnumerable GetAllByIsEnabledMark(string where = null) + { + return service.GetAllByIsEnabledMark(where, null); + } + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// + public virtual IEnumerable GetAllByIsNotEnabledMark(string where = null) + { + return service.GetAllByIsNotEnabledMark(where, null); + } + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// + public virtual IEnumerable GetAllByIsNotDeleteAndEnabledMark(string where = null) + { + return service.GetAllByIsNotDeleteAndEnabledMark(where, null); + } + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// + public virtual async Task> GetAllByIsIsDeletedAsync(string where = null) + { + return await service.GetAllByIsIsDeletedAsync(where, null); + } + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// + public virtual async Task> GetAllByIsNotIsDeletedAsync(string where = null) + { + return await service.GetAllByIsNotIsDeletedAsync(where, null); + } + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// + public virtual async Task> GetAllByIsEnabledMarkAsync(string where = null) + { + return await service.GetAllByIsEnabledMarkAsync(where, null); + } + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// + public virtual async Task> GetAllByIsNotEnabledMarkAsync(string where = null) + { + return await service.GetAllByIsNotEnabledMarkAsync(where, null); + } + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// + public virtual async Task> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null) + { + return await service.GetAllByIsNotDeleteAndEnabledMarkAsync(where, null); + } + + /// + /// 设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// + public virtual bool SetEnabledMark(bool bl, Tkey id, int userId = 0) + { + return service.SetEnabledMark(bl, id, userId, null); + } + + /// + /// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// + public virtual async Task SetEnabledMarkAsync(bool bl, Tkey id, int userId = 0) + { + return await service.SetEnabledMarkAsync(bl, id, userId, null); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info) + { + return service.FindWithPager(condition, info, null); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, string fieldToSort) + { + return service.FindWithPager(condition, info, fieldToSort, null); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 是否降序 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc) + { + return service.FindWithPager(condition, info, fieldToSort, desc, null); + } + + /// + /// 分页查询,自行封装sql语句 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + public virtual List FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc) + { + return service.FindWithPagerSql(condition, info, fieldToSort, desc, null); + } + + /// + /// 分页查询包含用户信息 + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// + public virtual List FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort, + bool desc) + { + return service.FindWithPagerRelationUser(condition, info, fieldToSort, desc, null); + } + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// + public virtual int GetCountByWhere(string condition) + { + return service.GetCountByWhere(condition); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dapper/DapperDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dapper/DapperDbContext.cs new file mode 100644 index 0000000..2c81bb3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dapper/DapperDbContext.cs @@ -0,0 +1,128 @@ +using System.Data; +using Znyc.Admin.Commons.Core.DataManager; + +namespace Znyc.Admin.Commons.Core.Dapper +{ + /// + /// 注册的时候 InstancePerLifetimeScope + /// 线程内唯一(也就是单个请求内唯一) + /// + public class DapperDbContext + { + private IDbConnection dbConnection { get; set; } + + /// + /// 获取的数据库连接 + /// + /// + /// + /// + public IDbConnection GetConnection(bool masterDb = true) where T : class + { + if (dbConnection == null || dbConnection.State == ConnectionState.Closed) + { + dbConnection = DBServerProvider.GetDBConnection(masterDb); + } + + //if (MiniProfiler.Current != null) + //{ + // dbConnection = new StackExchange.Profiling.Data.ProfiledDbConnection((DbConnection)dbConnection, MiniProfiler.Current); + //} + return dbConnection; + } + + /// + /// 事务 + /// + public IDbTransaction DbTransaction { get; set; } + + /// + /// 是否已被提交 + /// + public bool Committed { get; private set; } = true; + + /// + /// 开启事务 + /// + public void BeginTransaction() + { + Committed = false; + bool isClosed = dbConnection.State == ConnectionState.Closed; + if (isClosed) + { + dbConnection.Open(); + } + + DbTransaction = dbConnection?.BeginTransaction(); + } + + /// + /// 事务提交 + /// + public void CommitTransaction() + { + DbTransaction?.Commit(); + Committed = true; + Dispose(); + } + + /// + /// 事务回滚 + /// + public void RollBackTransaction() + { + DbTransaction?.Rollback(); + Committed = true; + Dispose(); + } + + #region Dispose实现 + + private bool disposedValue = false; // 要检测冗余调用 + + /// + /// 释放 + /// + /// + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + // TODO: 释放托管状态(托管对象)。 + } + + // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。 + // TODO: 将大型字段设置为 null。 + + disposedValue = true; + } + + if (dbConnection != null) + { + DbTransaction.Dispose(); + dbConnection.Dispose(); + } + } + + /// + /// 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。 + /// + public void Dispose() + { + // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 + Dispose(true); + + DbTransaction?.Dispose(); + if (dbConnection.State == ConnectionState.Open) + { + dbConnection?.Close(); + } + // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。 + // GC.SuppressFinalize(this); + } + + #endregion Dispose实现 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/AppDBContextAttribute.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/AppDBContextAttribute.cs new file mode 100644 index 0000000..5f92e72 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/AppDBContextAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace Znyc.Admin.Commons.Core.DataManager +{ + /// + /// 数据库连接配置特性 + /// + public class AppDBContextAttribute : Attribute + { + /// + /// 数据库配置名称 + /// + public string DbConfigName { get; set; } + + /// + /// 构造函数 + /// + /// + public AppDBContextAttribute(string dbConfigName) + { + DbConfigName = dbConfigName; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/DBServerProvider.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/DBServerProvider.cs new file mode 100644 index 0000000..606135f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/DBServerProvider.cs @@ -0,0 +1,234 @@ +using Microsoft.Data.Sqlite; +using Microsoft.Extensions.Configuration; +using MySql.Data.MySqlClient; +using Npgsql; +using Oracle.ManagedDataAccess.Client; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Reflection; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Extensions; + +namespace Znyc.Admin.Commons.Core.DataManager +{ + /// + /// 数据库服务提供者 + /// + public class DBServerProvider + { + /// + /// 数据库配置名称 + /// + private static string dbConfigName = ""; + + /// + /// 数据库连接 + /// + private static IDbConnection dbConnection; + + #region Dapper Context + + /// + /// 获取默认数据库连接 + /// + /// + public static string GetConnectionString() + { + return GetConnectionString(dbConfigName); + } + + /// + /// + /// + /// + /// + public static string GetConnectionString(string key) + { + return dbConfigName = key ?? dbConfigName; + } + + /// + /// 获取数据库连接 + /// + /// 是否访问主库,默认为是,否则访问从库即只读数据库 + /// + public static IDbConnection GetDBConnection(bool masterDb = true) + { + DbConnectionOptions connectionOptions = GeDbConnectionOptions(masterDb); + string defaultSqlConnectionString = connectionOptions.ConnectionString; + DatabaseType dbType = connectionOptions.DatabaseType; + if (dbType == DatabaseType.SqlServer) + { + dbConnection = new SqlConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.MySql) + { + dbConnection = new MySqlConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.Oracle) + { + dbConnection = new OracleConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.SQLite) + { + dbConnection = new SqliteConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.Npgsql) + { + dbConnection = new NpgsqlConnection(defaultSqlConnectionString); + } + else + { + throw new NotSupportedException("The database is not supported"); + } + + return dbConnection; + } + + /// + /// 获取数据库连接 + /// + /// 是否访问主库,默认为是,否则访问从库即只读数据库 + /// + public static IDbConnection GetDBConnection(bool masterDb = true) + { + DbConnectionOptions connectionOptions = GeDbConnectionOptions(masterDb); + string defaultSqlConnectionString = connectionOptions.ConnectionString; + DatabaseType dbType = connectionOptions.DatabaseType; + if (dbType == DatabaseType.SqlServer) + { + dbConnection = new SqlConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.MySql) + { + dbConnection = new MySqlConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.Oracle) + { + dbConnection = new OracleConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.SQLite) + { + dbConnection = new SqliteConnection(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.Npgsql) + { + dbConnection = new NpgsqlConnection(defaultSqlConnectionString); + } + else + { + throw new NotSupportedException("The database is not supported"); + } + + return dbConnection; + } + + /// + /// 获取数据库连接连接配置 + /// + /// 数据实体 + /// 是否访问主库,默认为是,否则访问从库即只读数据库 + /// + public static DbConnectionOptions GeDbConnectionOptions(bool masterDb = true) + { + dbConfigName = typeof(TEntity).GetCustomAttribute(false)?.DbConfigName ?? + dbConfigName; + bool conStringEncrypt = Configs.GetConfigurationValue("AppSetting", "ConStringEncrypt").ToBool(); + if (string.IsNullOrEmpty(dbConfigName)) + { + dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase"); + } + + Dictionary dictRead = Configs.GetSection("DbConnections:" + dbConfigName + ":ReadDb") + .Get>(); + + DbConnectionOptions dbConnectionOptions = new DbConnectionOptions(); + bool isDBReadWriteSeparate = Configs.GetConfigurationValue("AppSetting", "IsDBReadWriteSeparate").ToBool(); + if (masterDb || !isDBReadWriteSeparate) + { + dbConnectionOptions.ConnectionString = + Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "ConnectionString"); + dbConnectionOptions.DatabaseType = (DatabaseType)Enum.Parse(typeof(DatabaseType), + Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "DatabaseType")); + } + else + { + dbConnectionOptions = GetReadConn(dictRead); + } + + if (conStringEncrypt) + { + dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString); + } + + return dbConnectionOptions; + } + + /// + /// 获取数据库连接连接配置 + /// + /// 是否访问主库,默认为是,否则访问从库即只读数据库 + /// + public static DbConnectionOptions GeDbConnectionOptions(bool masterDb = true) + { + bool conStringEncrypt = Configs.GetConfigurationValue("AppSetting", "ConStringEncrypt").ToBool(); + if (string.IsNullOrEmpty(dbConfigName)) + { + dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase"); + } + + Dictionary dictRead = Configs.GetSection("DbConnections:" + dbConfigName + ":ReadDb") + .Get>(); + + DbConnectionOptions dbConnectionOptions = new DbConnectionOptions(); + bool isDBReadWriteSeparate = Configs.GetConfigurationValue("AppSetting", "IsDBReadWriteSeparate").ToBool(); + if (masterDb || !isDBReadWriteSeparate) + { + dbConnectionOptions.ConnectionString = + Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "ConnectionString"); + dbConnectionOptions.DatabaseType = (DatabaseType)Enum.Parse(typeof(DatabaseType), + Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "DatabaseType")); + } + else + { + dbConnectionOptions = GetReadConn(dictRead); + } + + if (conStringEncrypt) + { + dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString); + } + + return dbConnectionOptions; + } + + /// + /// 按从库数据库连接的策略进行返回连接对象,实现从库的负载均衡 + /// + /// + /// + private static DbConnectionOptions GetReadConn(Dictionary slaveData) + { + DbConnectionOptions connectionOptions = new DbConnectionOptions(); + string queryDBStrategy = Configs.GetConfigurationValue("AppSetting", "QueryDBStrategy"); + if (queryDBStrategy == "Random") //随机策略 + { + int index = new Random().Next(0, slaveData.Count - 1); + connectionOptions = slaveData[index.ToString()]; + } + else if (queryDBStrategy == "Polling") //轮询策略 + { + } + else //权重策略 + { + } + + return connectionOptions; + } + + #endregion Dapper Context + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/DbConnectionOptions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/DbConnectionOptions.cs new file mode 100644 index 0000000..6f53b9d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/DbConnectionOptions.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.Enums; + +namespace Znyc.Admin.Commons.Core.DataManager +{ + /// + /// 定义主数据和从数据库配置选项 + /// + public class DbConnections + { + /// + /// 主数据库 + /// + public DbConnectionOptions MassterDB { get; set; } + + /// + /// 从数据库 + /// + public List ReadDB { get; set; } + } + + /// + /// 数据库配置选项,定义数据库连接字符串、数据库类型和访问权重 + /// + public class DbConnectionOptions + { + /// + /// 数据库连接字符 + /// + public string ConnectionString { get; set; } + + /// + /// 数据库类型 + /// + public DatabaseType DatabaseType { get; set; } + + /// + /// 访问权重,值越大权重越低 + /// + public int DbLevel { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/WriteAndReadEnum.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/WriteAndReadEnum.cs new file mode 100644 index 0000000..e493ea7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/WriteAndReadEnum.cs @@ -0,0 +1,23 @@ +namespace Znyc.Admin.Commons.DataManager +{ + /// + /// 数据库读、写操作枚举 + /// + public enum WriteAndReadEnum + { + /// + /// 写操作 + /// + Write, + + /// + /// 读操作 + /// + Read, + + /// + /// 默认,不区分读写 + /// + Default + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/YuebonDbOptions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/YuebonDbOptions.cs new file mode 100644 index 0000000..c669d42 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/YuebonDbOptions.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.Enums; + +namespace Znyc.Admin.Commons.Core.DataManager +{ + public class ZnycDbOptions + { + public ZnycDbOptions() + { + } + + /// + /// 默认数据库类型 + /// + public DatabaseType DefaultDatabaseType { get; set; } = DatabaseType.SqlServer; + + /// + /// 数据库连接配置 + /// + public IDictionary DbConnections { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/YuebonDbOptionsSetup.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/YuebonDbOptionsSetup.cs new file mode 100644 index 0000000..ec528d4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DataManager/YuebonDbOptionsSetup.cs @@ -0,0 +1,64 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Znyc.Admin.Commons.Core.DataManager +{ + public class ZnycDbOptionsSetup : IConfigureOptions + { + private readonly IConfiguration _configuration; + + public ZnycDbOptionsSetup(IConfiguration configuration) + { + _configuration = configuration; + } + + /// + /// 配置options各属性信息 + /// + /// + public void Configure(ZnycDbOptions options) + { + SetDbConnectionsOptions(options); + } + + private void SetDbConnectionsOptions(ZnycDbOptions options) + { + Dictionary dbConnectionMap = new Dictionary(); + options.DbConnections = dbConnectionMap; + + string dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase"); + IConfiguration section = _configuration.GetSection("DbConnections:" + dbConfigName); + Dictionary dict = section.Get>(); + if (dict == null || dict.Count == 0) + { + string connectionString = _configuration["ConnectionStrings:DefaultDbContext"]; + if (connectionString == null) + { + return; + } + + dbConnectionMap.Add("DefaultDb", new DbConnectionOptions + { + ConnectionString = connectionString, + DatabaseType = options.DefaultDatabaseType + }); + + return; + } + + IGrouping ambiguous = dict.Keys.GroupBy(d => d).FirstOrDefault(d => d.Count() > 1); + if (ambiguous != null) + { + throw new Exception($"数据上下文配置中存在多个配置节点拥有同一个数据库连接名称,存在二义性:{ambiguous.First()}"); + } + + foreach (KeyValuePair db in dict) + { + dbConnectionMap.Add(db.Key, db.Value); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/BaseDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/BaseDbContext.cs new file mode 100644 index 0000000..801cf9f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/BaseDbContext.cs @@ -0,0 +1,791 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Pomelo.EntityFrameworkCore.MySql.Infrastructure; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Attributes; +using Znyc.Admin.Commons.Core.DataManager; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.DbContextCore +{ + /// + /// DbContext上下文的实现 + /// + public class BaseDbContext : DbContext, IDbContextCore + { + #region 基础参数 + + /// + /// 数据库配置名称,可在子类指定不同的配置名称,用于访问不同的数据库 + /// + protected string dbConfigName = ""; + + /// + /// 是否开启多租户 + /// + protected bool isMultiTenant = false; + + /// + /// + /// + protected DbConnectionOptions dbConnectionOptions; + + /// + /// 数据库访问对象的外键约束 + /// + public bool IsMultiTenant => isMultiTenant; + + /// + /// + /// + /// + public DatabaseFacade GetDatabase() + { + return Database; + } + + #endregion 基础参数 + + /// + /// + /// + protected BaseDbContext() + { + } + + /// + /// + /// + /// + public BaseDbContext(DbConnectionOptions dbConnectionOptions) + { + this.dbConnectionOptions = dbConnectionOptions; + } + + /// + /// 配置,初始化数据库引擎 + /// + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (dbConnectionOptions == null) + { + dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(); + } + + string defaultSqlConnectionString = dbConnectionOptions.ConnectionString; + + DatabaseType dbType = dbConnectionOptions.DatabaseType; + if (dbType == DatabaseType.SqlServer) + { + optionsBuilder.UseSqlServer(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.MySql) + { + optionsBuilder.UseMySql(defaultSqlConnectionString, new MySqlServerVersion(new Version(5, 7, 1)), + mySqlOptions => mySqlOptions + .CharSetBehavior(CharSetBehavior.NeverAppend)); + } + else if (dbType == DatabaseType.Oracle) + { + optionsBuilder.UseOracle(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.SQLite) + { + optionsBuilder.UseSqlite(defaultSqlConnectionString); + } + else if (dbType == DatabaseType.Npgsql) + { + optionsBuilder.UseNpgsql(defaultSqlConnectionString); + } + else + { + throw new NotSupportedException("The database is not supported"); + } + //使用查询跟踪行为 + optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); + base.OnConfiguring(optionsBuilder); + } + + /// + /// 模型创建 + /// + /// + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + MappingEntityTypes(modelBuilder); + base.OnModelCreating(modelBuilder); + } + + /// + /// + /// + /// + private void MappingEntityTypes(ModelBuilder modelBuilder) + { + IList assemblies = RuntimeHelper.GetAllZnycAssemblies(); + foreach (Assembly assembly in assemblies) + { + IEnumerable entityTypes = assembly.GetTypes() + .Where(type => !string.IsNullOrWhiteSpace(type.Namespace)) + .Where(type => type.IsClass) + .Where(type => type.BaseType != null) + .Where(type => typeof(Entity).IsAssignableFrom(type) || type.IsSubclassOf(typeof(BaseViewModel))); + + foreach (Type entityType in entityTypes) + { + if (modelBuilder.Model.FindEntityType(entityType) != null || entityType.Name == "Entity" || + entityType.Name == "BaseEntity`1") + { + continue; + } + + TableAttribute table = entityType.GetCustomAttributes().FirstOrDefault(); + modelBuilder.Model.AddEntityType(entityType).SetTableName(table.Name); + + IMutableEntityType ientityTypes = modelBuilder.Model.FindEntityType(entityType); + ShardingTableAttribute attr = entityType.GetCustomAttributes().FirstOrDefault(); + if (attr != null && entityType != null) + { + modelBuilder.Model.FindEntityType(entityType) + .SetTableName($"{entityType.Name}{attr.Splitter}{DateTime.Now.ToString(attr.Suffix)}"); + } + + if (typeof(IDeleteAudited).IsAssignableFrom(typeof(Entity))) + { + modelBuilder.Entity().HasQueryFilter(m => ((IDeleteAudited)m).IsDeleted == false); + } + + if (IsMultiTenant) + { + if (typeof(IMustHaveTenant).IsAssignableFrom(typeof(Entity))) + { + modelBuilder.Entity().HasQueryFilter(m => ((IMustHaveTenant)m).TenantId == ""); + } + } + } + } + } + + #region 接口实现 + + /// + /// 新增实体 + /// + /// + /// + /// + public new virtual int Add(T entity) where T : class + { + base.Add(entity); + return SaveChanges(); + } + + /// + /// 新增实体 + /// + /// + /// + /// + public virtual async Task AddAsync(T entity) where T : class + { + await base.AddAsync(entity); + return await SaveChangesAsync(); + } + + /// + /// 批量新增 + /// + /// + /// + /// + public virtual int AddRange(ICollection entities) where T : class + { + base.AddRange(entities); + return SaveChanges(); + } + + /// + /// 批量新增 + /// + /// + /// + /// + public virtual async Task AddRangeAsync(ICollection entities) where T : class + { + await base.AddRangeAsync(entities); + return await SaveChangesAsync(); + } + + /// + /// 统计数量Count() + /// + /// + /// 查询条件 + /// + public virtual int Count(Expression> @where = null) where T : class + { + return where == null ? GetDbSet().Count() : GetDbSet().Count(@where); + } + + /// + /// 统计数量Count() + /// + /// + /// 查询条件 + /// + public virtual async Task CountAsync(Expression> @where = null) where T : class + { + return await (where == null ? GetDbSet().CountAsync() : GetDbSet().CountAsync(@where)); + } + + /// + /// 物理删除数据 + /// + /// + /// 主键类型 + /// 主键 + /// + public virtual int Delete(TKey key) where T : Entity + { + T entity = Find(key); + Remove(entity); + return SaveChanges(); + } + + /// + ///执行Sql,返回影响记录行数 + /// + /// + /// + /// + public virtual int ExecuteSqlWithNonQuery(string sql, params object[] parameters) + { + return Database.ExecuteSqlRaw(sql, parameters); + } + + /// + /// 执行Sql,返回影响记录行数 + /// + /// + /// + /// + public virtual async Task ExecuteSqlWithNonQueryAsync(string sql, params object[] parameters) + { + return await Database.ExecuteSqlRawAsync(sql, parameters); + } + + /// + /// 编辑更新保存实体 + /// + /// + /// + /// + public virtual int Edit(T entity) where T : class + { + base.Update(entity); + base.Entry(entity).State = EntityState.Modified; + return SaveChanges(); + } + + /// + /// 批量更新保存实体 + /// 以添加状态开始跟踪给定的实体和任何其他尚未被跟踪的可访问实体 + /// + /// + /// + /// + public virtual int EditRange(ICollection entities) where T : class + { + GetDbSet().AttachRange(entities.ToArray()); + return SaveChanges(); + } + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// 查询条件 + /// + public virtual bool Exist(Expression> @where = null) where T : class + { + return @where == null ? GetDbSet().Any() : GetDbSet().Any(@where); + } + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// + /// + public virtual async Task ExistAsync(Expression> @where = null) where T : class + { + return await Task.FromResult(Exist(where)); + } + + /// + /// 根据条件进行查询数据 + /// + /// + /// + /// 查询条件 + /// + public virtual IQueryable FilterWithInclude(Func, IQueryable> include, + Expression> @where) where T : class + { + IQueryable result = GetDbSet().AsQueryable(); + if (where != null) + { + result = GetDbSet().Where(where); + } + + if (include != null) + { + result = include(result); + } + + return result; + } + + /// + /// 根据主键查询实体 + /// + /// + /// + /// + public virtual T Find(object key) where T : class + { + return base.Find(key); + } + + /// + /// 根据主键查询实体 + /// + /// + /// + /// + public virtual T Find(string key) where T : class + { + return base.Find(key); + } + + /// + /// 根据主键查询实体 + /// + /// + /// + /// + /// + public virtual T Find(TKey key) where T : Entity + { + return base.Find(key); + } + + /// + /// 根据主键查询实体 + /// + /// + /// + /// + public virtual async Task FindAsync(object key) where T : class + { + return await base.FindAsync(key); + } + + /// + /// 根据主键查询实体 + /// + /// + /// + /// + /// + public virtual async Task FindAsync(TKey key) where T : Entity + { + return await base.FindAsync(key); + } + + /// + /// 根据条件查询实体,返回实体集合 + /// + /// + /// 查询条件 + /// 是否启用模型跟踪,默认为false不跟踪 + /// + public virtual IQueryable Get(Expression> @where = null, bool asNoTracking = false) + where T : class + { + IQueryable query = GetDbSet().AsQueryable(); + if (where != null) + { + query = query.Where(where); + } + + if (asNoTracking) + { + query = query.AsNoTracking(); + } + + return query; + } + + /// + /// 获取所有实体类型 + /// + /// + public virtual List GetAllEntityTypes() + { + return Model.GetEntityTypes().ToList(); + } + + /// + /// + /// + /// + /// + public virtual DbSet GetDbSet() where T : class + { + if (Model.FindEntityType(typeof(T)) != null) + { + return Set(); + } + + throw new Exception( + $"类型{typeof(T).Name}未在数据库上下文中注册,请先在DbContextOption设置ModelAssemblyName以将所有实体类型注册到数据库上下文中。"); + } + + /// + /// 根据条件查询一个实体, + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + public virtual T GetSingleOrDefault(Expression> @where = null) where T : class + { + return where == null ? GetDbSet().SingleOrDefault() : GetDbSet().SingleOrDefault(where); + } + + /// + /// 根据条件查询一个实体, + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + public virtual async Task GetSingleOrDefaultAsync(Expression> @where = null) where T : class + { + return await (where == null + ? GetDbSet().SingleOrDefaultAsync() + : GetDbSet().SingleOrDefaultAsync(where)); + } + + /// + /// 更新指定字段的值 + /// + /// + /// 数据实体 + /// 指定字段 + /// + public virtual int Update(T model, params string[] updateColumns) where T : class + { + if (updateColumns != null && updateColumns.Length > 0) + { + if (Entry(model).State == EntityState.Added || + Entry(model).State == EntityState.Detached) + { + GetDbSet().Attach(model); + } + + foreach (string propertyName in updateColumns) + { + Entry(model).Property(propertyName).IsModified = true; + } + } + else + { + Entry(model).State = EntityState.Modified; + } + + return SaveChanges(); + } + + /// + /// 批量插入 + /// + /// + /// 数据实体集合 + /// 数据库表名称 + public virtual void BulkInsert(IList entities, string destinationTableName = null) where T : class + { + if (!Database.IsSqlServer() && !Database.IsMySql()) + { + throw new NotSupportedException("This method only supports for SQL Server or MySql."); + } + } + + /// + /// Sql查询,并返回实体 + /// + /// 查询对象实体 + /// 返回/输出实体 + /// sql语句 + /// SQL参数 + /// + public virtual List SqlQuery(string sql, params object[] parameters) + where T : class + { + return GetDbSet().FromSqlRaw(sql, parameters).Cast().ToList(); + } + + /// + /// Sql查询,并返回实体 + /// + /// 查询对象实体 + /// 返回/输出实体 + /// sql语句 + /// SQL参数 + /// + public virtual async Task> SqlQueryAsync(string sql, params object[] parameters) + where T : class + where TView : class + { + return await GetDbSet().FromSqlRaw(sql, parameters).Cast().ToListAsync(); + } + + /// + /// 分页查询,SQL语句查询,返回指定输出对象集合 + /// + /// 查询对象实体 + /// 返回/输出实体 + /// sql语句 + /// 排序条件 + /// 当前页 + /// 每页显示数量 + /// + /// + public virtual PageResult SqlQueryByPagination(string sql, string[] orderBys, int pageIndex, + int pageSize, + Action eachAction = null) where T : class where TView : class + { + throw new NotImplementedException(); + } + + /// + /// 分页查询,SQL语句查询,返回数据实体集合 + /// + /// 查询对象实体 + /// sql语句 + /// 排序条件 + /// 当前页 + /// 每页显示数量 + /// 查询SQL参数 + /// + public virtual PageResult SqlQueryByPagination(string sql, string[] orderBys, int pageIndex, int pageSize, + params DbParameter[] parameters) where T : class, new() + { + throw new NotImplementedException(); + } + + #region 显式编译的查询,提高查询性能 + + /// + /// 根据主键查询返回一个实体,该方法是显式编译的查询 + /// + /// + /// 主键类型 + /// 主键值 + /// + public T GetByCompileQuery(TKey id) where T : Entity + { + return EF.CompileQuery((DbContext context, TKey id) => context.Set().Find(id))(this, id); + } + + /// + /// 根据主键查询返回一个实体,该方法是显式编译的查询 + /// + /// + /// 主键类型 + /// 主键值 + /// + public Task GetByCompileQueryAsync(TKey id) where T : Entity + { + return EF.CompileAsyncQuery((DbContext context, TKey id) => context.Set().Find(id))(this, id); + } + + /// + /// 根据条件查询返回实体集合,该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + public IList GetByCompileQuery(Expression> filter) where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileQuery((DbContext context) => context.Set().AsNoTracking().Where(filter).ToList())(this); + } + + /// + /// 根据条件查询返回实体集合,该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + public Task> GetByCompileQueryAsync(Expression> filter) where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileAsyncQuery((DbContext context) => + context.Set().AsNoTracking().Where(filter).ToList())(this); + } + + /// + /// 根据条件查询一个实体,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + public T FirstOrDefaultByCompileQuery(Expression> filter) where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileQuery((DbContext context) => context.Set().AsNoTracking().FirstOrDefault(filter))(this); + } + + /// + /// 根据条件查询一个实体,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + public Task FirstOrDefaultByCompileQueryAsync(Expression> filter) where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileAsyncQuery((DbContext context) => + context.Set().AsNoTracking().FirstOrDefault(filter))(this); + } + + /// + /// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + public T FirstOrDefaultWithTrackingByCompileQuery(Expression> filter) where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileQuery((DbContext context) => context.Set().FirstOrDefault(filter))(this); + } + + /// + /// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + public Task FirstOrDefaultWithTrackingByCompileQueryAsync(Expression> filter) + where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileAsyncQuery((DbContext context) => context.Set().FirstOrDefault(filter))(this); + } + + /// + /// 统计数量Count(),该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + public int CountByCompileQuery(Expression> filter) where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileQuery((DbContext context) => context.Set().Count(filter))(this); + } + + /// + /// 统计数量Count(),该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + public Task CountByCompileQueryAsync(Expression> filter) where T : class + { + if (filter == null) + { + filter = m => true; + } + + return EF.CompileAsyncQuery((DbContext context) => context.Set().Count(filter))(this); + } + + /// + /// 根据sql语句返回DataTable数据 + /// + /// Sql语句 + /// 执行超时时间,默认30毫秒 + /// DbParameter[]参数 + /// + public virtual DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + throw new NotImplementedException(); + } + + /// + /// 根据sql语句返回List数据 + /// + /// Sql语句 + /// 执行超时时间,默认30毫秒 + /// DbParameter[] 参数 + /// + public virtual List GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + throw new NotImplementedException(); + } + + #endregion 显式编译的查询,提高查询性能 + + #endregion 接口实现 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/DbContextFactory.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/DbContextFactory.cs new file mode 100644 index 0000000..16b6e32 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/DbContextFactory.cs @@ -0,0 +1,109 @@ +using Microsoft.Extensions.DependencyInjection; +using Znyc.Admin.Commons.Core.DataManager; +using Znyc.Admin.Commons.DataManager; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Options; + +namespace Znyc.Admin.Commons.DbContextCore +{ + /// + /// 上下文工厂类 + /// + public class DbContextFactory : IDbContextFactory + { + /// + /// + /// + public static DbContextFactory Instance => new DbContextFactory(); + + /// + /// 服务 + /// + public IServiceCollection ServiceCollection { get; set; } + + /// + /// 构造函数 + /// + public DbContextFactory() + { + } + + /// + /// 向服务注入上下文 + /// + /// + /// + public void AddDbContext(DbContextOption option) + where TContext : BaseDbContext, IDbContextCore + { + ServiceCollection.AddDbContext(option); + } + + /// + /// 向服务注入上下文 + /// + /// 上下文接口 + /// 上下文实现类 + /// + public void AddDbContext(DbContextOption option) + where ITContext : IDbContextCore + where TContext : BaseDbContext, ITContext + { + ServiceCollection.AddDbContext(option); + } + + /// + /// 创建数据库读写上下文 + /// + /// 指定读、写操作 + /// + public BaseDbContext CreateContext(WriteAndReadEnum writeAndRead) + { + DbConnectionOptions dbConnectionOptions = new DbConnectionOptions(); + switch (writeAndRead) + { + case WriteAndReadEnum.Write: + dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(true); + break; + + case WriteAndReadEnum.Read: + dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(false); + break; + + default: + dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(true); + break; + } + + return new BaseDbContext(dbConnectionOptions); + } + + /// + /// 创建数据库读写上下文 + /// + /// + /// 指定读、写操作 + /// + public BaseDbContext CreateContext(WriteAndReadEnum writeAndRead) + { + DbConnectionOptions dbConnectionOptions = new DbConnectionOptions(); + switch (writeAndRead) + { + case WriteAndReadEnum.Write: + dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(true); + break; + + case WriteAndReadEnum.Read: + dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(false); + break; + + default: + dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(true); + break; + } + + return new BaseDbContext(dbConnectionOptions); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/DefaultModelBuilder.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/DefaultModelBuilder.cs new file mode 100644 index 0000000..b6200cb --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/DefaultModelBuilder.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Conventions; + +namespace Znyc.Admin.Commons.EfDbContext +{ + public class DefaultModelBuilder : ModelBuilder + { + public DefaultModelBuilder(ConventionSet conventions) : base(conventions) + { + } + + public override ModelBuilder ApplyConfiguration(IEntityTypeConfiguration configuration) + { + return base.ApplyConfiguration(configuration); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/MySqlDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/MySqlDbContext.cs new file mode 100644 index 0000000..1386402 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/MySqlDbContext.cs @@ -0,0 +1,126 @@ +using Microsoft.EntityFrameworkCore; +using MySql.Data.MySqlClient; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data; +using System.Data.Common; +using System.IO; +using System.Linq; +using System.Reflection; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.IDbContext; + +namespace Znyc.Admin.Commons.DbContextCore +{ + /// + /// + /// + public class MySqlDbContext : BaseDbContext, IMySqlDbContext + { + /// + /// 批量插入 + /// + /// + /// 数据实体集合 + /// 数据库表名称 + public override void BulkInsert(IList entities, string destinationTableName = null) + { + if (entities == null || !entities.Any()) + { + return; + } + + if (string.IsNullOrEmpty(destinationTableName)) + { + string mappingTableName = typeof(T).GetCustomAttribute()?.Name; + destinationTableName = string.IsNullOrEmpty(mappingTableName) ? typeof(T).Name : mappingTableName; + } + + MySqlBulkInsert(entities, destinationTableName); + } + + /// + /// + /// + /// + /// + /// + private void MySqlBulkInsert(IList entities, string destinationTableName) where T : class + { + string tmpDir = Path.Combine(AppContext.BaseDirectory, "Temp"); + if (!Directory.Exists(tmpDir)) + { + Directory.CreateDirectory(tmpDir); + } + + string csvFileName = Path.Combine(tmpDir, $"{DateTime.Now:yyyyMMddHHmmssfff}.csv"); + if (!File.Exists(csvFileName)) + { + File.Create(csvFileName); + } + + string separator = ","; + entities.SaveToCsv(csvFileName, separator); + MySqlConnection conn = (MySqlConnection)Database.GetDbConnection(); + if (conn.State != ConnectionState.Open) + { + conn.Open(); + } + + MySqlBulkLoader bulk = new MySqlBulkLoader(conn) + { + NumberOfLinesToSkip = 0, + TableName = destinationTableName, + FieldTerminator = separator, + FieldQuotationCharacter = '"', + EscapeCharacter = '"', + LineTerminator = "\r\n" + }; + bulk.LoadAsync(); + conn.Close(); + File.Delete(csvFileName); + } + + public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault(); + } + + public override List GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + List dts = new List(); + //TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。” + DbConnection connection = Database.GetDbConnection(); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + + using (MySqlCommand cmd = new MySqlCommand(sql, (MySqlConnection)connection)) + { + cmd.CommandTimeout = cmdTimeout; + if (parameters != null && parameters.Length > 0) + { + cmd.Parameters.AddRange(parameters); + } + + using (MySqlDataAdapter da = new MySqlDataAdapter(cmd)) + { + using (DataSet ds = new DataSet()) + { + da.Fill(ds); + foreach (DataTable table in ds.Tables) + { + dts.Add(table); + } + } + } + } + + connection.Close(); + + return dts; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/OracleDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/OracleDbContext.cs new file mode 100644 index 0000000..cb2789c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/OracleDbContext.cs @@ -0,0 +1,71 @@ +using Microsoft.EntityFrameworkCore; +using Oracle.ManagedDataAccess.Client; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using Znyc.Admin.Commons.IDbContext; + +namespace Znyc.Admin.Commons.DbContextCore +{ + /// + /// Oracle上下文 + /// + public class OracleDbContext : BaseDbContext, IOracleDbContext + { + /// + /// + /// + /// + /// + /// + /// + public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault(); + } + + /// + /// + /// + /// + /// + /// + /// + public override List GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + List dts = new List(); + //TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。” + DbConnection connection = Database.GetDbConnection(); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + + using (OracleCommand cmd = new OracleCommand(sql, (OracleConnection)connection)) + { + cmd.CommandTimeout = cmdTimeout; + if (parameters != null && parameters.Length > 0) + { + cmd.Parameters.AddRange(parameters); + } + + using (OracleDataAdapter da = new OracleDataAdapter(cmd)) + { + using (DataSet ds = new DataSet()) + { + da.Fill(ds); + foreach (DataTable table in ds.Tables) + { + dts.Add(table); + } + } + } + } + + connection.Close(); + + return dts; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/PostgreSQLDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/PostgreSQLDbContext.cs new file mode 100644 index 0000000..e62e935 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/PostgreSQLDbContext.cs @@ -0,0 +1,80 @@ +using Microsoft.EntityFrameworkCore; +using Npgsql; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.IDbContext; + +namespace Znyc.Admin.Commons.DbContextCore +{ + public class PostgreSQLDbContext : BaseDbContext, IPostgreSQLDbContext + { + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + string conStringEncrypt = Configs.GetConfigurationValue("AppSetting", "ConStringEncrypt"); + isMultiTenant = Configs.GetConfigurationValue("AppSetting", "IsMultiTenant").ToBool(); + if (string.IsNullOrEmpty(dbConfigName)) + { + dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase"); + } + + string defaultSqlConnectionString = Configs.GetConnectionString(dbConfigName); + if (conStringEncrypt == "true") + { + defaultSqlConnectionString = DEncrypt.Decrypt(defaultSqlConnectionString); + } + + string dbType = dbConfigName.ToUpper(); + if (dbType.Contains("NPGSQL")) + { + optionsBuilder.UseNpgsql(defaultSqlConnectionString); + } + + base.OnConfiguring(optionsBuilder); + } + + public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault(); + } + + public override List GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + List dts = new List(); + //TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。” + DbConnection connection = Database.GetDbConnection(); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + + using (NpgsqlCommand cmd = new NpgsqlCommand(sql, (NpgsqlConnection)connection)) + { + cmd.CommandTimeout = cmdTimeout; + if (parameters != null && parameters.Length > 0) + { + cmd.Parameters.AddRange(parameters); + } + + using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd)) + { + using (DataSet ds = new DataSet()) + { + da.Fill(ds); + foreach (DataTable table in ds.Tables) + { + dts.Add(table); + } + } + } + } + + connection.Close(); + + return dts; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/SQLiteDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/SQLiteDbContext.cs new file mode 100644 index 0000000..bee0e2f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/SQLiteDbContext.cs @@ -0,0 +1,64 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using Znyc.Admin.Commons.IDbContext; + +namespace Znyc.Admin.Commons.DbContextCore +{ + /// + /// SQLite数据库操作 + /// + public class SQLiteDbContext : BaseDbContext, ISQLiteDbContext + { + /// + /// + /// + /// + /// + /// + /// + public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault(); + } + + /// + /// + /// + /// + /// + /// + /// + public override List GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + List dts = new List(); + //TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。” + DbConnection connection = Database.GetDbConnection(); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + + using (SqliteCommand cmd = new SqliteCommand(sql, (SqliteConnection)connection)) + { + cmd.CommandTimeout = cmdTimeout; + if (parameters != null && parameters.Length > 0) + { + cmd.Parameters.AddRange(parameters); + } + + using (SqliteDataReader reader = cmd.ExecuteReader()) + { + dts.Add(reader.GetSchemaTable()); + } + } + + connection.Close(); + + return dts; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/SqlServerDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/SqlServerDbContext.cs new file mode 100644 index 0000000..a202182 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/DbContextCore/SqlServerDbContext.cs @@ -0,0 +1,225 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Reflection; +using Znyc.Admin.Commons.Extend; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.DbContextCore +{ + /// + /// Sql Server数据库上下文 + /// + public class SqlServerDbContext : BaseDbContext, ISqlServerDbContext + { + /// + /// 批量插入 + /// + /// + /// 数据实体集合 + /// 如果为 null,则使用 TModel 名称作为 destinationTableName + /// + public override void BulkInsert(IList entities, string destinationTableName = null) + { + if (entities == null || !entities.Any()) + { + return; + } + + if (string.IsNullOrEmpty(destinationTableName)) + { + string mappingTableName = typeof(T).GetCustomAttribute()?.Name; + destinationTableName = string.IsNullOrEmpty(mappingTableName) ? typeof(T).Name : mappingTableName; + } + + SqlBulkInsert(entities, destinationTableName); + } + + /// + /// 批量插入 + /// + /// + /// 数据实体集合 + /// 如果为 null,则使用 TModel 名称作为 destinationTableName + /// + private void SqlBulkInsert(IList entities, string destinationTableName = null) where T : class + { + using (DataTable dt = entities.ToDataTable()) + { + dt.TableName = destinationTableName; + SqlConnection conn = (SqlConnection)Database.GetDbConnection(); + if (conn.State != ConnectionState.Open) + { + conn.Open(); + } + + using (SqlTransaction tran = conn.BeginTransaction()) + { + try + { + SqlBulkCopy bulk = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, tran) + { + BatchSize = entities.Count, + DestinationTableName = dt.TableName + }; + GenerateColumnMappings(bulk.ColumnMappings); + bulk.WriteToServerAsync(dt); + tran.Commit(); + } + catch (Exception) + { + tran.Rollback(); + throw; + } + } + + conn.Close(); + } + } + + /// + /// 字段与实体关系映射 + /// + /// + /// + private void GenerateColumnMappings(SqlBulkCopyColumnMappingCollection mappings) + where T : class + { + PropertyInfo[] properties = typeof(T).GetProperties(); + foreach (PropertyInfo property in properties) + { + if (property.GetCustomAttributes().Any()) + { + mappings.Add(new SqlBulkCopyColumnMapping(property.Name, typeof(T).Name + property.Name)); + } + else + { + mappings.Add(new SqlBulkCopyColumnMapping(property.Name, property.Name)); + } + } + } + + /// + /// 分页查询,SQL语句查询,返回指定输出对象集合 + /// + /// 查询对象实体 + /// 返回/输出实体 + /// sql语句 + /// 排序条件 + /// 当前页 + /// 每页显示数量 + /// + /// + public override PageResult SqlQueryByPagination(string sql, string[] orderBys, int pageIndex, + int pageSize, + Action eachAction = null) + { + int total = SqlQuery($"select count(1) from ({sql}) as s").FirstOrDefault(); + List jsonResults = SqlQuery( + $"select * from (select *,row_number() over (order by {string.Join(",", orderBys)}) as RowId from ({sql}) as s) as t where RowId between {pageSize * (pageIndex - 1) + 1} and {pageSize * pageIndex} order by {string.Join(",", orderBys)}") + .ToList(); + if (eachAction != null) + { + jsonResults = jsonResults.Each(eachAction).ToList(); + } + + return new PageResult() + { + CurrentPage = pageIndex, + ItemsPerPage = pageSize, + TotalItems = total + }; + } + + /// + /// 分页查询,SQL语句查询,返回数据实体集合 + /// + /// 查询对象实体 + /// sql语句 + /// 排序条件 + /// 当前页 + /// 每页显示数量 + /// 查询SQL参数 + /// + public override PageResult SqlQueryByPagination(string sql, string[] orderBys, int pageIndex, + int pageSize, + params DbParameter[] parameters) + { + int total = (int)this.ExecuteScalar($"select count(1) from ({sql}) as s"); + List jsonResults = GetDataTable( + $"select * from (select *,row_number() over (order by {string.Join(",", orderBys)}) as RowId from ({sql}) as s) as t where RowId between {pageSize * (pageIndex - 1) + 1} and {pageSize * pageIndex} order by {string.Join(",", orderBys)}") + .ToList(); + return new PageResult() + { + CurrentPage = pageIndex, + ItemsPerPage = pageSize, + TotalItems = total, + Items = jsonResults + }; + } + + /// + /// 根据sql语句返回DataTable数据 + /// + /// Sql语句 + /// 执行超时时间,默认30毫秒 + /// DbParameter[]参数 + /// + public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault(); + } + + /// + /// 根据sql语句返回List数据 + /// + /// Sql语句 + /// 执行超时时间,默认30毫秒 + /// DbParameter[] 参数 + /// + public override List GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters) + { + List dts = new List(); + //TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。” + DbConnection connection = Database.GetDbConnection(); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + + using (SqlCommand cmd = new SqlCommand(sql, (SqlConnection)connection)) + { + cmd.CommandTimeout = cmdTimeout; + if (parameters != null && parameters.Length > 0) + { + cmd.Parameters.AddRange(parameters); + } + + using (SqlDataAdapter da = new SqlDataAdapter(cmd)) + { + using (DataSet ds = new DataSet()) + { + da.Fill(ds); + foreach (DataTable table in ds.Tables) + { + dts.Add(table); + } + } + } + } + + connection.Close(); + + return dts; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/DeletesInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/DeletesInputDto.cs new file mode 100644 index 0000000..9dc249c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/DeletesInputDto.cs @@ -0,0 +1,16 @@ +using System; + +namespace Znyc.Admin.Commons.Core.Dtos +{ + /// + /// 批量物理删除操作传参 + /// + [Serializable] + public class DeletesInputDto + { + /// + /// 主键Id集合 + /// + public dynamic[] Ids { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/IInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/IInputDto.cs new file mode 100644 index 0000000..14da056 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/IInputDto.cs @@ -0,0 +1,14 @@ +namespace Znyc.Admin.Commons.Dtos +{ + /// + /// 定义输入DTO + /// + /// + public interface IInputDto + { + /// + /// 获取或设置 主键,唯一标识 + /// + TKey Id { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/IOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/IOutputDto.cs new file mode 100644 index 0000000..d5ea9cb --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/IOutputDto.cs @@ -0,0 +1,9 @@ +namespace Znyc.Admin.Commons.Dtos +{ + /// + /// 定义输出DTO + /// + public interface IOutputDto + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/InputDtoValidateExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/InputDtoValidateExtensions.cs new file mode 100644 index 0000000..928e388 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/InputDtoValidateExtensions.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Reflection; +using Znyc.Admin.Commons.Data; +using Znyc.Admin.Commons.Extensions; + +namespace Znyc.Admin.Commons.Dtos +{ + /// + /// 验证扩展 + /// + public static class InputDtoValidateExtensions + { + private static readonly ConcurrentDictionary> + _dict + = new ConcurrentDictionary>(); + + /// + /// InputDto属性验证 + /// + public static void Validate(this IEnumerable> dtos) + { + IInputDto[] inputDtos = dtos as IInputDto[] ?? dtos.ToArray(); + Check.NotNull(inputDtos, nameof(dtos)); + foreach (IInputDto dto in inputDtos) + { + Validate(dto); + } + } + + /// + /// InputDto属性验证 + /// + public static void Validate(this IInputDto dto) + { + Check.NotNull(dto, nameof(dto)); + Type type = dto.GetType(); + if (!_dict.TryGetValue(type, out ConcurrentDictionary dict)) + { + PropertyInfo[] properties = type.GetProperties(); + dict = new ConcurrentDictionary(); + if (properties.Length == 0) + { + _dict[type] = dict; + return; + } + + foreach (PropertyInfo property in properties) + { + dict[property] = null; + } + + _dict[type] = dict; + } + + foreach (PropertyInfo property in dict.Keys) + { + if (!dict.TryGetValue(property, out ValidationAttribute[] attributes) || attributes == null) + { + attributes = property.GetAttributes(); + dict[property] = attributes; + } + + if (attributes.Length == 0) + { + continue; + } + + object value = property.GetValue(dto); + foreach (ValidationAttribute attribute in attributes) + { + attribute.Validate(value, property.Name); + } + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/SearchInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/SearchInputDto.cs new file mode 100644 index 0000000..a3d8278 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Dtos/SearchInputDto.cs @@ -0,0 +1,39 @@ +using System; +using System.Runtime.Serialization; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.Dtos +{ + /// + /// 查询条件公共实体类 + /// + [Serializable] + [DataContract] + public class SearchInputDto : PagerInfo + { + /// + /// 关键词 + /// + public string Keywords { get; set; } + + /// + /// 编码/代码 + /// + public string EnCode { get; set; } + + /// + /// 排序方式 默认asc + /// + public string Order { get; set; } + + /// + /// 排序字段 默认Id + /// + public string Sort { get; set; } = "ModifiedTime"; + + /// + /// 查询条件 + /// + public T Filter { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IDbContextCore.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IDbContextCore.cs new file mode 100644 index 0000000..06544e4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IDbContextCore.cs @@ -0,0 +1,483 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.IDbContext +{ + /// + /// 上下文基础接口 + /// + public interface IDbContextCore : IDisposable + { + /// + /// + /// + /// + DatabaseFacade GetDatabase(); + + #region 新增 + + /// + /// 新增实体 + /// + /// + /// + /// + int Add(T entity) where T : class; + + /// + /// 异步新增 + /// + /// + /// + /// + Task AddAsync(T entity) where T : class; + + /// + /// 批量新增 + /// + /// + /// + /// + int AddRange(ICollection entities) where T : class; + + /// + /// 异步批量新增 + /// + /// + /// + /// + Task AddRangeAsync(ICollection entities) where T : class; + + #endregion 新增 + + #region 删除 + + /// + /// 物理删除数据 + /// + /// + /// 主键类型 + /// 主键 + /// + int Delete(TKey key) where T : Entity; + + /// + /// 根据条件删除一个实体,返回影响记录行数 + /// + /// + /// 条件 + /// + ////int Delete(Expression> @where) where T : class; + /// + /// 根据条件删除一个实体,返回影响记录行数 + /// + /// + /// 条件 + /// + //Task DeleteAsync(Expression> @where) where T : class; + + #endregion 删除 + + /// + /// 执行Sql语句,返回影响记录行数 + /// + /// + /// + /// + int ExecuteSqlWithNonQuery(string sql, params object[] parameters); + + /// + /// 执行Sql,返回影响记录行数 + /// + /// + /// + /// + Task ExecuteSqlWithNonQueryAsync(string sql, params object[] parameters); + + #region 更新 + + /// + /// 更新保存实体 + /// + /// + /// + /// + int Edit(T entity) where T : class; + + /// + /// 批量更新保存实体 + /// + /// + /// + /// + int EditRange(ICollection entities) where T : class; + + /// + /// 更新指定字段的值 + /// + /// + /// 数据实体 + /// 指定字段 + /// + int Update(T model, params string[] updateColumns) where T : class; + + /// + /// 按条件更新, + /// + /// + /// 条件 + /// + /// + //int Update(Expression> @where, Expression> updateFactory) where T : class; + + /// + /// 按条件更新, + /// + /// + /// 条件 + /// + /// + // Task UpdateAsync(Expression> @where, Expression> updateFactory) + // where T : class; + + #endregion 更新 + + #region 查询 + + /// + /// 根据条件统计数量Count() + /// + /// + /// 查询条件 + /// + int Count(Expression> @where = null) where T : class; + + /// + /// 根据条件异步统计数量Count() + /// + /// + /// 查询条件 + /// + Task CountAsync(Expression> @where = null) where T : class; + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// 查询条件 + /// + bool Exist(Expression> @where = null) where T : class; + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// 查询条件 + /// + Task ExistAsync(Expression> @where = null) where T : class; + + /// + /// 根据条件进行查询数据 + /// + /// + /// + /// 查询数据 + /// + IQueryable FilterWithInclude(Func, IQueryable> include, Expression> where) + where T : class; + + /// + /// 根据主键查询实体 + /// + /// + /// 主键值 + /// + T Find(object key) where T : class; + + /// + /// 根据主键查询实体 + /// + /// + /// 主键值 + /// + T Find(string key) where T : class; + + /// + /// 根据主键查询实体 + /// + /// + /// 主键类型 + /// 主键值 + /// + T Find(TKey key) where T : Entity; + + /// + /// 根据主键查询实体 + /// + /// + /// 主键值 + /// + Task FindAsync(object key) where T : class; + + /// + /// 根据主键查询实体 + /// + /// + /// 主键类型 + /// 主键值 + /// + Task FindAsync(TKey key) where T : Entity; + + /// + /// 根据条件查询实体,返回实体集合 + /// + /// + /// 查询条件 + /// 是否启用模型跟踪,默认为false不跟踪 + /// + IQueryable Get(Expression> @where = null, bool asNoTracking = false) where T : class; + + /// + /// 获取所有实体类型 + /// + /// + List GetAllEntityTypes(); + + /// + /// + /// + /// + /// + DbSet GetDbSet() where T : class; + + /// + /// 根据条件查询一个实体, + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + T GetSingleOrDefault(Expression> @where = null) where T : class; + + /// + /// 根据条件查询一个实体, + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + Task GetSingleOrDefaultAsync(Expression> @where = null) where T : class; + + #endregion 查询 + + /// + /// 批量插入 + /// + /// + /// 数据实体集合 + /// 数据库表名称,默认为实体名称 + /// + void BulkInsert(IList entities, string destinationTableName = null) + where T : class; + + /// + /// Sql查询,并返回实体集合 + /// + /// 查询对象实体 + /// 返回/输出实体 + /// sql语句 + /// SQL参数 + /// + List SqlQuery(string sql, params object[] parameters) + where T : class; + + /// + /// Sql查询,并返回实体集合 + /// + /// 查询对象实体 + /// 返回/输出实体 + /// sql语句 + /// SQL参数 + /// + Task> SqlQueryAsync(string sql, params object[] parameters) + where T : class + where TView : class; + + /// + /// 分页查询,SQL语句查询,返回指定输出对象集合 + /// + /// 查询对象实体 + /// 返回/输出实体 + /// sql语句 + /// 排序条件 + /// 当前页 + /// 每页显示数量 + /// + /// + PageResult SqlQueryByPagination(string sql, string[] orderBys, int pageIndex, int pageSize, + Action eachAction = null) + where T : class + where TView : class; + + /// + /// 分页查询,SQL语句查询,返回数据实体集合 + /// + /// 查询对象实体 + /// sql语句 + /// 排序条件 + /// 当前页 + /// 每页显示数量 + /// 查询SQL参数 + /// + PageResult SqlQueryByPagination(string sql, string[] orderBys, int pageIndex, int pageSize, + params DbParameter[] parameters) where T : class, new(); + + /// + /// 保存到数据库 + /// + /// + int SaveChanges(); + + /// + /// 保存到数据库 + /// + /// 更改成功发送到数据库后是否调用AcceptAllChanges() + /// + int SaveChanges(bool acceptAllChangesOnSuccess); + + /// + /// 保存到数据库 + /// + /// 是否等待任务完成时要观察 + /// + Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// 保存到数据库 + /// + /// 是否更改成功发送到数据库后是否调用AcceptAllChanges() + /// 是否等待任务完成时要观察 + /// + Task SaveChangesAsync(bool acceptAllChangesOnSuccess, + CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// 根据sql语句返回DataTable数据 + /// + /// Sql语句 + /// 执行超时时间,默认30毫秒 + /// DbParameter[]参数 + /// + DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters); + + /// + /// 根据sql语句返回List集合数据 + /// + /// Sql语句 + /// 执行超时时间,默认30毫秒 + /// DbParameter[]参数 + /// + List GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters); + + #region 显式编译的查询,提高查询性能 + + /// + /// 根据主键查询返回一个实体,该方法是显式编译的查询 + /// + /// + /// 主键类型 + /// 主键值 + /// + T GetByCompileQuery(TKey id) where T : Entity; + + /// + /// 根据主键查询返回一个实体,该方法是显式编译的查询 + /// + /// + /// 主键类型 + /// 主键值 + /// + Task GetByCompileQueryAsync(TKey id) where T : Entity; + + /// + /// 根据条件查询返回实体集合,该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + IList GetByCompileQuery(Expression> filter) where T : class; + + /// + /// 根据条件查询返回实体集合,该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + Task> GetByCompileQueryAsync(Expression> filter) where T : class; + + /// + /// 根据条件查询一个实体,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + T FirstOrDefaultByCompileQuery(Expression> filter) where T : class; + + /// + /// 根据条件查询一个实体,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + Task FirstOrDefaultByCompileQueryAsync(Expression> filter) where T : class; + + /// + /// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + T FirstOrDefaultWithTrackingByCompileQuery(Expression> filter) where T : class; + + /// + /// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询 + /// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。 + /// + /// + /// 查询条件 + /// + Task FirstOrDefaultWithTrackingByCompileQueryAsync(Expression> filter) where T : class; + + /// + /// 统计数量Count(),该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + int CountByCompileQuery(Expression> filter) where T : class; + + /// + /// 统计数量Count(),该方法是显式编译的查询 + /// + /// + /// 查询条件 + /// + Task CountByCompileQueryAsync(Expression> filter) where T : class; + + #endregion 显式编译的查询,提高查询性能 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IDbContextFactory.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IDbContextFactory.cs new file mode 100644 index 0000000..db3b434 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IDbContextFactory.cs @@ -0,0 +1,26 @@ +using Znyc.Admin.Commons.DataManager; +using Znyc.Admin.Commons.DbContextCore; + +namespace Znyc.Admin.Commons.IDbContext +{ + /// + /// + /// + public interface IDbContextFactory + { + /// + /// + /// + /// 指定读、写操作 + /// + BaseDbContext CreateContext(WriteAndReadEnum writeAndRead); + + /// + /// 创建数据库读写上下文 + /// + /// + /// 指定读、写操作 + /// + BaseDbContext CreateContext(WriteAndReadEnum writeAndRead); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IMySqlDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IMySqlDbContext.cs new file mode 100644 index 0000000..957f7c7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IMySqlDbContext.cs @@ -0,0 +1,6 @@ +namespace Znyc.Admin.Commons.IDbContext +{ + public interface IMySqlDbContext : IDbContextCore + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IOracleDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IOracleDbContext.cs new file mode 100644 index 0000000..6cf7a87 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IOracleDbContext.cs @@ -0,0 +1,6 @@ +namespace Znyc.Admin.Commons.IDbContext +{ + public interface IOracleDbContext : IDbContextCore + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IPostgreSQLDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IPostgreSQLDbContext.cs new file mode 100644 index 0000000..2cbfe6d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/IPostgreSQLDbContext.cs @@ -0,0 +1,6 @@ +namespace Znyc.Admin.Commons.IDbContext +{ + public interface IPostgreSQLDbContext : IDbContextCore + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/ISQLiteDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/ISQLiteDbContext.cs new file mode 100644 index 0000000..b3ef156 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/ISQLiteDbContext.cs @@ -0,0 +1,6 @@ +namespace Znyc.Admin.Commons.IDbContext +{ + public interface ISQLiteDbContext : IDbContextCore + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/ISqlServerDbContext.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/ISqlServerDbContext.cs new file mode 100644 index 0000000..2c19a77 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IDbContext/ISqlServerDbContext.cs @@ -0,0 +1,6 @@ +namespace Znyc.Admin.Commons.IDbContext +{ + public interface ISqlServerDbContext : IDbContextCore + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IRepositories/IReadOnlyRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IRepositories/IReadOnlyRepository.cs new file mode 100644 index 0000000..e991adf --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IRepositories/IReadOnlyRepository.cs @@ -0,0 +1,14 @@ +using System; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Commons.Core.IRepositories +{ + /// + /// 只读仓储接口,提供查询相关方法 + /// + /// + /// + public interface IReadOnlyRepository : IDisposable where T : Entity + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IRepositories/IRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IRepositories/IRepository.cs new file mode 100644 index 0000000..6790ea5 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IRepositories/IRepository.cs @@ -0,0 +1,821 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq.Expressions; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.IRepositories +{ + /// + /// 定义泛型接口,实体仓储模型的数据标准操作 + /// + /// 实体类型 + /// 主键类型 + public interface IRepository : IDisposable where T : Entity + { + #region dapper 操作 + + #region 新增 + + /// + /// 同步新增实体。 + /// + /// 实体 + /// 事务对象 + /// + long Insert(T entity, IDbTransaction trans = null); + + /// + /// 异步新增实体。 + /// + /// 实体 + /// 事务对象 + /// + Task InsertAsync(T entity, IDbTransaction trans = null); + + /// + /// 异步新增实体返回主键 + /// + /// + /// + /// + Task InsertReturnPrimaryKeyAsync(T entity, IDbTransaction trans = null); + + /// + /// 同步批量新增实体。 + /// + /// 实体集合 + /// + void Insert(List entities); + + #endregion 新增 + + #region 删除 + + /// + /// 同步物理删除实体。 + /// + /// 实体 + /// + bool Delete(T entity); + + /// + /// 异步物理删除实体。 + /// + /// 实体 + /// 事务对象 + /// + Task DeleteAsync(T entity, IDbTransaction trans = null); + + /// + /// 同步物理删除实体。 + /// + /// 主键 + /// 事务对象 + /// + bool Delete(TKey primaryKey, IDbTransaction trans = null); + + /// + /// 异步物理删除实体。 + /// + /// 主键 + /// 事务对象 + /// + Task DeleteAsync(TKey primaryKey, IDbTransaction trans = null); + + /// + /// 按主键批量删除 + /// + /// + /// 事务对象 + /// + bool DeleteBatch(IList ids, IDbTransaction trans = null); + + /// + /// 按条件批量删除 + /// + /// 条件 + /// 事务对象 + /// + bool DeleteBatchWhere(string where, IDbTransaction trans = null); + + /// + /// 异步按条件批量删除 + /// + /// 条件 + /// 事务对象 + /// + Task DeleteBatchWhereAsync(string where, IDbTransaction trans = null); + + #endregion 删除 + + #region 更新操作 + + #region 更新实体或批量更新 + + /// + /// 同步更新实体。 + /// + /// 实体 + /// 主键ID + /// 事务对象 + /// + bool Update(T entity, TKey primaryKey, IDbTransaction trans = null); + + /// + /// 异步更新实体。 + /// + /// 实体 + /// 主键ID + /// 事务对象 + /// + Task UpdateAsync(T entity, TKey primaryKey, IDbTransaction trans = null); + + #endregion 更新实体或批量更新 + + #region 更新某一字段值 + + /// + /// 更新某一字段值 + /// + /// 字段 + /// 字段值 + /// 条件,为空更新所有内容 + /// + /// + bool UpdateTableField(string strField, string fieldValue, string where, IDbTransaction trans = null); + + /// + /// 异步更新某一字段值 + /// + /// 字段 + /// 字段值 + /// 条件,为空更新所有内容 + /// + /// + Task UpdateTableFieldAsync(string strField, string fieldValue, string where, IDbTransaction trans = null); + + /// + /// 更新某一字段值,字段值为数字 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + bool UpdateTableField(string strField, int fieldValue, string where, IDbTransaction trans = null); + + /// + /// 更新某一字段值,字段值为数字 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + Task UpdateTableFieldAsync(string strField, int fieldValue, string where, IDbTransaction trans = null); + + #endregion 更新某一字段值 + + #region 逻辑删除 + + /// + /// 同步软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + bool DeleteSoft(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 c + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + Task DeleteSoftAsync(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步批量软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 c + /// 条件 + /// 操作用户 + /// 事务对象 + /// + Task DeleteSoftBatchAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null); + + #endregion 逻辑删除 + + #region 数据有效性 + + /// + /// 设置数据有效性,将IsEnabled设置为1-有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + bool SetEnabledMark(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + Task SetEnabledMarkAsync(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 条件 + /// 操作用户 + /// 事务对象 + /// + Task SetEnabledMarkByWhereAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 条件 + /// 参数 + /// 操作用户 + /// 事务对象 + /// + Task SetEnabledMarkByWhereAsync(bool bl, string where, object paramparameters = null, long userId = 0, + IDbTransaction trans = null); + + #endregion 数据有效性 + + #endregion 更新操作 + + #region 查询 + + #region 单个实体 + + /// + /// 同步查询单个实体。 + /// + /// 主键 + /// + T Get(TKey primaryKey); + + /// + /// 异步查询单个实体。 + /// + /// 主键 + /// + Task GetAsync(TKey primaryKey); + + /// + /// 同步查询单个实体。 + /// + /// 查询条件 + /// + T GetWhere(string where); + + /// + /// 异步查询单个实体。 + /// + /// 查询条件 + /// + Task GetWhereAsync(string where); + + #endregion 单个实体 + + /// + /// 获取所有数据,谨慎使用 + /// + /// 事务对象 + /// + IEnumerable GetAll(IDbTransaction trans = null); + + /// + /// 获取所有数据,谨慎使用 + /// + /// 事务对象 + /// + Task> GetAllAsync(IDbTransaction trans = null); + + /// + /// 根据查询条件查询数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetListWhere(string where = null, IDbTransaction trans = null); + + /// + /// 异步根据查询条件查询数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetListWhereAsync(string where = null, IDbTransaction trans = null); + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetListTopWhere(int top, string where = null, IDbTransaction trans = null); + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + Task> GetListTopWhereAsync(int top, string where = null, IDbTransaction trans = null); + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsIsDeleted(string where = null, IDbTransaction trans = null); + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsNotIsDeleted(string where = null, IDbTransaction tran = null); + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsEnabledMark(string where = null, IDbTransaction tran = null); + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsNotEnabledMark(string where = null, IDbTransaction tran = null); + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsNotDeleteAndEnabledMark(string where = null, IDbTransaction tran = null); + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsIsDeletedAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsNotIsDeletedAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsEnabledMarkAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsNotEnabledMarkAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null, IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 是否降序 + /// 事务对象 + /// 指定对象的集合 + Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 是否降序 + /// 事务对象 + /// 指定对象的集合 + List FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, + IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + List FindWithPager(string condition, PagerInfo info, string fieldToSort, IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + Task> FindWithPagerAsync(string condition, PagerInfo info, IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + List FindWithPager(string condition, PagerInfo info, IDbTransaction trans = null); + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + Task> FindWithPagerSqlAsync(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + List FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + Task> FindWithPagerRelationUserAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null); + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + List FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + int GetCountByWhere(string condition, string fieldName = "*"); + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + Task GetCountByWhereAsync(string condition, string fieldName = "*"); + + /// + /// / + /// + /// + Task GetCount(); + + /// + /// 根据条件查询获取某个字段的最大值 + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段的最大值 + Task GetMaxValueByFieldAsync(string strField, string where, IDbTransaction trans = null); + + /// + /// 根据条件统计某个字段之和,sum(字段) + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段求和后的值 + Task GetSumValueByFieldAsync(string strField, string where, IDbTransaction trans = null); + + #endregion 查询 + + #region 多表批量操作,支持事务 + + /// + /// 多表操作--事务 + /// + /// 事务 + /// 超时 + /// + Task> + ExecuteTransactionAsync(List> trans, int? commandTimeout = null); + + /// + /// 多表操作--事务 + /// + /// 事务 + /// 超时 + /// + Tuple ExecuteTransaction(List> trans, int? commandTimeout = null); + + #endregion 多表批量操作,支持事务 + + #endregion dapper 操作 + + #region EF 操作 + + #region Insert 新增 + + /// + /// 新增实体 + /// + /// + /// + int Add(T entity); + + /// + /// 新增实体 + /// + /// + /// + Task AddAsync(T entity); + + /// + /// 批量新增,数量量较多是推荐使用BulkInsert() + /// + /// + /// + int AddRange(ICollection entities); + + /// + /// 批量新增,数量量较多是推荐使用BulkInsert() + /// + /// + /// + Task AddRangeAsync(ICollection entities); + + /// + /// 批量新增SqlBulk方式,效率最高 + /// + /// + /// + void BulkInsert(IList entities, string destinationTableName = null); + + /// + /// 执行新增的sql语句 + /// + /// 新增Sql语句 + /// + int AddBySql(string sql); + + #endregion Insert 新增 + + #region Delete 删除 + + /// + /// 根据主键删除数据 + /// + /// + /// + int Delete(TKey key); + + /// + /// 执行删除数据Sql语句 + /// + /// 删除的Sql语句 + /// + int DeleteBySql(string sql); + + #endregion Delete 删除 + + #region Update 更新 + + /// + /// 更新一个实体数据 + /// + /// + /// + int Edit(T entity); + + /// + /// 批量更新数据实体 + /// + /// + /// + int EditRange(ICollection entities); + + /// + /// 更新指定字段的值 + /// + /// + /// 数据实体 + /// 指定字段 + /// + int Update(T model, params string[] updateColumns); + + /// + /// 执行更新数据的Sql语句 + /// + /// 更新数据的Sql语句 + /// + int UpdateBySql(string sql); + + #endregion Update 更新 + + #region Query 查询 + + /// + /// 根据条件统计数量Count() + /// + /// + /// + int Count(Expression> @where = null); + + /// + /// 根据条件统计数量Count() + /// + /// + /// + Task CountAsync(Expression> @where = null); + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// + bool Exist(Expression> @where = null); + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// + Task ExistAsync(Expression> @where = null); + + /// + /// 根据主键获取实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + T GetSingle(TKey key); + + /// + /// 根据主键获取实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + Task GetSingleAsync(TKey key); + + /// + /// 获取单个实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + T GetSingleOrDefault(Expression> @where = null); + + /// + /// 获取单个实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + Task GetSingleOrDefaultAsync(Expression> @where = null); + + /// + /// 获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + IList Get(Expression> @where = null); + + /// + /// 获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + Task> GetAsync(Expression> @where = null); + + /// + /// 分页获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// 查询条件 + /// 分页信息 + /// 排序方式 + /// 排序字段 + /// + IEnumerable GetByPagination(Expression> @where, PagerInfo pagerInfo, bool asc = true, + params Expression>[] @orderby); + + /// + /// sql语句查询数据集 + /// + /// + /// + List GetBySql(string sql); + + /// + /// sql语句查询数据集,返回输出Dto实体 + /// + /// 返回结果对象 + /// + /// + List GetViews(string sql); + + /// + /// 查询视图 + /// + /// 返回结果对象 + /// 视图名称 + /// 查询条件 + /// + List GetViews(string viewName, Func where); + + #endregion Query 查询 + + #endregion EF 操作 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IServices/IService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IServices/IService.cs new file mode 100644 index 0000000..c2a7d89 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/IServices/IService.cs @@ -0,0 +1,615 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.IServices +{ + /// + /// 泛型应用服务接口 + /// + /// + /// + /// + public interface IService : IDisposable where T : Entity + where TODto : class + { + /// + /// 同步查询单个实体。 + /// + /// 主键 + /// + T Get(TKey id); + + /// + /// 同步查询单个实体。 + /// + /// 主键 + /// + TODto GetOutDto(TKey id); + + /// + /// 异步查询单个实体。 + /// + /// 主键 + /// + Task GetOutDtoAsync(TKey id); + + /// + /// 异步查询单个实体。 + /// + /// 主键 + /// + Task GetAsync(TKey id); + + /// + /// 同步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + T GetWhere(string where, IDbTransaction trans = null); + + /// + /// 同步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + TODto GetOutDtoWhere(string where, IDbTransaction trans = null); + + /// + /// 异步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + Task GetWhereAsync(string where, IDbTransaction trans = null); + + /// + /// 异步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + Task GetOutDtoWhereAsync(string where, IDbTransaction trans = null); + + /// + /// 同步查询所有实体。 + /// + /// 事务对象 + /// + IEnumerable GetAll(IDbTransaction trans = null); + + /// + /// 异步查询所有实体。 + /// + /// 事务对象 + /// + Task> GetAllAsync(IDbTransaction trans = null); + + /// + /// 根据查询条件查询数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetListWhere(string where = null, IDbTransaction trans = null); + + /// + /// 异步根据查询条件查询数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetListWhereAsync(string where = null, IDbTransaction trans = null); + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetListTopWhere(int top, string where = null, IDbTransaction trans = null); + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + Task> GetListTopWhereAsync(int top, string where = null, IDbTransaction trans = null); + + /// + /// 同步新增实体。 + /// + /// 实体 + /// 事务对象 + /// + long Insert(T entity, IDbTransaction trans = null); + + /// + /// 异步新增实体。 + /// + /// 实体 + /// 事务对象 + /// + Task InsertAsync(T entity, IDbTransaction trans = null); + + /// + /// 异步新增实体返回主键 + /// + /// + /// + /// + Task InsertReturnPrimaryKeyAsync(T entity, IDbTransaction trans = null); + + /// + /// 同步批量新增实体。 + /// + /// 实体集合 + /// + void Insert(List entities); + + /// + /// 同步更新实体。 + /// + /// 实体 + /// 主键ID + /// 事务对象 + /// + bool Update(T entity, TKey id, IDbTransaction trans = null); + + /// + /// 异步更新实体。 + /// + /// 实体 + /// 主键ID + /// 事务对象 + /// + Task UpdateAsync(T entity, TKey id, IDbTransaction trans = null); + + /// + /// 更新某一字段值 + /// + /// 字段 + /// 字段值 + /// 条件,为空更新所有内容 + /// + /// + bool UpdateTableField(string strField, string fieldValue, string where, IDbTransaction trans = null); + + /// + /// 异步更新某一字段值 + /// + /// 字段 + /// 字段值 + /// 条件,为空更新所有内容 + /// + /// + Task UpdateTableFieldAsync(string strField, string fieldValue, string where, IDbTransaction trans = null); + + /// + /// 更新某一字段值,字段值为数字 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + bool UpdateTableField(string strField, int fieldValue, string where, IDbTransaction trans = null); + + /// + /// 更新某一字段值,字段值为数字 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + Task UpdateTableFieldAsync(string strField, int fieldValue, string where, IDbTransaction trans = null); + + /// + /// 同步物理删除实体。 + /// + /// 实体 + /// 事务对象 + /// + bool Delete(T entity, IDbTransaction trans = null); + + /// + /// 异步物理删除实体。 + /// + /// 实体 + /// 事务对象 + /// + Task DeleteAsync(T entity, IDbTransaction trans = null); + + /// + /// 同步物理删除实体。 + /// + /// 主键 + /// 事务对象 + /// + bool Delete(TKey id, IDbTransaction trans = null); + + /// + /// 异步物理删除实体。 + /// + /// 主键 + /// 事务对象 + /// + Task DeleteAsync(TKey id, IDbTransaction trans = null); + + /// + /// 按主键批量删除 + /// + /// + /// 事务对象 + /// + bool DeleteBatch(IList ids, IDbTransaction trans = null); + + /// + /// 按条件批量删除 + /// + /// 条件 + /// 事务对象 + /// + bool DeleteBatchWhere(string where, IDbTransaction trans = null); + + /// + /// 异步按条件批量删除 + /// + /// 条件 + /// 事务对象 + /// + Task DeleteBatchWhereAsync(string where, IDbTransaction trans = null); + + /// + /// 同步软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + bool DeleteSoft(bool bl, TKey id, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 c + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + Task DeleteSoftAsync(bool bl, TKey id, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步批量软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 c + /// 条件 + /// 操作用户 + /// 事务对象 + /// + Task DeleteSoftBatchAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null); + + /// + /// 设置数据有效性,将IsEnabled设置为1-有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + bool SetEnabledMark(bool bl, TKey id, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// + Task SetEnabledMarkAsync(bool bl, TKey id, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 条件 + /// 操作用户 + /// 事务对象 + /// + Task SetEnabledMarkByWhereAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null); + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 条件 + /// + /// 操作用户 + /// 事务对象 + /// + Task SetEnabledMarkByWhereAsync(bool bl, string where, object paramparameters = null, long userId = 0, + IDbTransaction trans = null); + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsIsDeleted(string where = null, IDbTransaction trans = null); + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsNotIsDeleted(string where = null, IDbTransaction tran = null); + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsEnabledMark(string where = null, IDbTransaction tran = null); + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsNotEnabledMark(string where = null, IDbTransaction tran = null); + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// 事务对象 + /// + IEnumerable GetAllByIsNotDeleteAndEnabledMark(string where = null, IDbTransaction tran = null); + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsIsDeletedAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsNotIsDeletedAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsEnabledMarkAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsNotEnabledMarkAsync(string where = null, IDbTransaction tran = null); + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// 事务对象 + /// + Task> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null, IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 是否降序 + /// 事务对象 + /// 指定对象的集合 + Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 是否降序 + /// 事务对象 + /// 指定对象的集合 + List FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, + IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + List FindWithPager(string condition, PagerInfo info, string fieldToSort, IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + Task> FindWithPagerAsync(string condition, PagerInfo info, IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + List FindWithPager(string condition, PagerInfo info, IDbTransaction trans = null); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 指定对象的集合 + PageResult FindWithPager(SearchInputDto search); + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 指定对象的集合 + Task> FindWithPagerAsync(SearchInputDto search); + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + Task> FindWithPagerSqlAsync(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + List FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + Task> FindWithPagerRelationUserAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null); + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + List FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null); + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + int GetCountByWhere(string condition, string fieldName = "*"); + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + Task GetCountByWhereAsync(string condition, string fieldName = "*"); + + /// + /// 获取总条数 + /// + /// + Task GetCount(); + + /// + /// 根据条件查询获取某个字段的最大值 + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段的最大值 + Task GetMaxValueByFieldAsync(string strField, string where, IDbTransaction trans = null); + + /// + /// 根据条件统计某个字段之和,sum(字段) + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段求和后的值 + Task GetSumValueByFieldAsync(string strField, string where, IDbTransaction trans = null); + + /// + /// 多表操作--事务 + /// + /// 事务 + /// 超时 + /// + Task> + ExecuteTransactionAsync(List> trans, int? commandTimeout = null); + + /// + /// 多表操作--事务 + /// + /// 事务 + /// 超时 + /// + Tuple ExecuteTransaction(List> trans, int? commandTimeout = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/BaseEntity.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/BaseEntity.cs new file mode 100644 index 0000000..bc8a9ec --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/BaseEntity.cs @@ -0,0 +1,63 @@ +using System; +using System.ComponentModel; + +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义领域对象框架实体类的基类,系统默认主键为Id + /// + /// 实体主键类型 + [Serializable] + public abstract class BaseEntity : Entity, IBaseEntity + { + /// + /// + /// + protected BaseEntity() + { + } + + /// + /// Id + /// + [Description("Id")] + public TKey Id { get; set; } + + /// + /// 创建者Id + /// + [Description("创建者Id")] + public TKey CreatedUserId { get; set; } + + /// + /// 创建时间 + /// + [Description("创建时间")] + public DateTime CreatedTime { get; set; } + + /// + /// 是否删除 + /// + [Description("是否删除")] + public bool IsDeleted { get; set; } = false; + + /// + /// 修改者Id + /// + [Description("修改者Id")] + public TKey ModifiedUserId { get; set; } + + /// + /// 修改时间 + /// + [Description("修改时间")] + public DateTime ModifiedTime { get; set; } + } + + /// + /// + /// + public class BaseEntity : BaseEntity + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/BaseViewModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/BaseViewModel.cs new file mode 100644 index 0000000..bbf98f1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/BaseViewModel.cs @@ -0,0 +1,12 @@ +using System; + +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 所有数据库视图对应实体类必须继承此类 + /// + [Serializable] + public abstract class BaseViewModel : IEntity + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/Entity.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/Entity.cs new file mode 100644 index 0000000..a9081f2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/Entity.cs @@ -0,0 +1,9 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 实体基类 + /// + public abstract class Entity : IEntity + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IBaseEntity.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IBaseEntity.cs new file mode 100644 index 0000000..99522f5 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IBaseEntity.cs @@ -0,0 +1,14 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 数据模型接口 + /// + /// 实体主键类型 + public interface IBaseEntity : IEntity + { + /// + /// 获取 实体唯一标识,主键 + /// + TKey Id { get; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/ICreationAudited.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/ICreationAudited.cs new file mode 100644 index 0000000..2682569 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/ICreationAudited.cs @@ -0,0 +1,20 @@ +using System; + +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义创建审计信息:给实体添加创建时的 创建人CreatedUserId,创建时间CreatedTime 的审计信息,这些值将在数据层执行 创建Insert 时自动赋值。 + /// + public interface ICreationAudited + { + /// + /// 获取或设置 创建日期 + /// + DateTime CreatedTime { get; set; } + + /// + /// 获取或设置 创建用户主键 + /// + long CreatedUserId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IDataAuthEnabled.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IDataAuthEnabled.cs new file mode 100644 index 0000000..0d74bdf --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IDataAuthEnabled.cs @@ -0,0 +1,18 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义数据权限的更新,删除状态 + /// + public interface IDataAuthEnabled + { + /// + /// 获取或设置 是否可更新的数据权限状态 + /// + bool Updatable { get; set; } + + /// + /// 获取或设置 是否可删除的数据权限状态 + /// + bool Deletable { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IDeleteAudited.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IDeleteAudited.cs new file mode 100644 index 0000000..67caff2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IDeleteAudited.cs @@ -0,0 +1,13 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义逻辑删除功能审计信息 + /// + public interface IDeleteAudited + { + /// + /// 获取或设置 逻辑删除标记 + /// + bool IsDeleted { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IEntity.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IEntity.cs new file mode 100644 index 0000000..cc99176 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IEntity.cs @@ -0,0 +1,9 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 实体基接口,是所有实体的基接口 + /// + public interface IEntity + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IEntityHash.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IEntityHash.cs new file mode 100644 index 0000000..af89821 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IEntityHash.cs @@ -0,0 +1,10 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义实体Hash功能,对实体的属性值进行Hash,确定实体是否存在变化, + /// 这些变化可用于系统初始化时确定是否需要进行数据同步 + /// + public interface IEntityHash + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IExpirable.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IExpirable.cs new file mode 100644 index 0000000..6b71c38 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IExpirable.cs @@ -0,0 +1,20 @@ +using System; + +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义可过期性,包含生效时间和过期时间:给实体添加 生效时间BeginTime,过期时间EndTime 的属性 + /// + public interface IExpirable + { + /// + /// 获取或设置 生效时间 + /// + DateTime? BeginTime { get; set; } + + /// + /// 获取或设置 过期时间 + /// + DateTime? EndTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IModificationAudited.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IModificationAudited.cs new file mode 100644 index 0000000..e336965 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IModificationAudited.cs @@ -0,0 +1,20 @@ +using System; + +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义更新审计的信息 + /// + public interface IModificationAudited + { + /// + /// 获取或设置 最后修改用户 + /// + string ModifiedUserId { get; set; } + + /// + /// 获取或设置 最后修改时间 + /// + DateTime? ModifiedTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IMustHaveTenant.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IMustHaveTenant.cs new file mode 100644 index 0000000..243f06b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Models/IMustHaveTenant.cs @@ -0,0 +1,13 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 定义多租户实体信息 + /// + public interface IMustHaveTenant + { + /// + /// 租户Id + /// + string TenantId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Module/AutoMapperService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Module/AutoMapperService.cs new file mode 100644 index 0000000..e7cd248 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Module/AutoMapperService.cs @@ -0,0 +1,23 @@ +using AutoMapper; +using Microsoft.Extensions.DependencyInjection; +using System; +using Znyc.Admin.Commons.Mapping; + +namespace Znyc.Admin.Commons.Module +{ + /// + /// AutoMapperService + /// + public class AutoMapperService + { + /// + /// + /// + /// + public static void UsePack(IServiceProvider provider) + { + IMapper mapper = provider.GetService(); + MapperExtensions.SetMapper(mapper); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Module/MoudleService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Module/MoudleService.cs new file mode 100644 index 0000000..ca4ddf2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Module/MoudleService.cs @@ -0,0 +1,88 @@ +using AutoMapper; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Yuebon.Commons.Repositories; +using Yuebon.Commons.IoC; +using Yuebon.Commons.Linq; +using Yuebon.Commons.Log; + +namespace Yuebon.Commons.Module +{ + /// + /// 模块服务 + /// + public class MoudleService + { + /// + /// 实现应用模块程序集的注册服务 + /// + /// + /// + public static IServiceProvider LoaderMoudleService(IServiceCollection services) + { + // services.AddScoped(typeof(IUnitOfWork), typeof(UnitOfWork)); + var apps = AppContext.BaseDirectory + "Apps"; + if (!Directory.Exists(apps)) + { + Directory.CreateDirectory(apps); + } + // 把 Apps 下的动态库拷贝一份来运行, + // 使 Apps 中的动态库不会在运行时被占用(以便重新编译) + var targetPath = PrepareShadowCopies(); + // 从 Shadow Copy 目录加载 Assembly 并注册到 Mvc 中 + //LoadFromShadowCopies(targetPath); + + string PrepareShadowCopies() + { + // 准备 Shadow Copy 的目标目录 + var target = Path.Combine(AppContext.BaseDirectory, "app_data", "apps-cache"); + + if (!Directory.Exists(target)) + { + Directory.CreateDirectory(target); + } + // 找到插件目录下 bin 目录中的 .dll,拷贝 + Directory.EnumerateDirectories(apps) + .Select(path => Path.Combine(path, "bin")) + .Where(Directory.Exists) + .SelectMany(bin => Directory.EnumerateFiles(bin, "*.dll")) + .ForEach(dll => File.Copy(dll, Path.Combine(target, Path.GetFileName(dll)), true)); + + return target; + } + + DirectoryInfo folder = new DirectoryInfo(targetPath); + List myAssembly = new List(); + myAssembly.Add(Assembly.Load("Yuebon.Security.Core")); + if (File.Exists(AppContext.BaseDirectory+ "Yuebon.Messages.Core.dll")) + { + myAssembly.Add(Assembly.Load("Yuebon.Messages.Core")); + } + foreach (FileInfo finfo in folder.GetFiles("*.Core.dll")) + { + try + { + myAssembly.Add(Assembly.LoadFrom(finfo.FullName)); + string dllNamespaceStr = finfo.Name.Substring(0, finfo.Name.IndexOf(".Core")); + IoCContainer.RegisterFrom(finfo.FullName); + IoCContainer.RegisterLoadFrom(finfo.FullName, dllNamespaceStr); + Log4NetHelper.Info("注入应用模块" + finfo.Name + "成功"); + } + catch (Exception ex) + { + Log4NetHelper.Error("注入应用模块" + finfo.Name + "失败\r\n" , ex); + } + } + + services.AddAutoMapper(myAssembly); + services.AddScoped(); + + return IoCContainer.Build(services); + } + + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Repositories/BaseRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Repositories/BaseRepository.cs new file mode 100644 index 0000000..26b8fa6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Repositories/BaseRepository.cs @@ -0,0 +1,2206 @@ +using Dapper; +using Dapper.Contrib.Extensions; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.Dapper; +using Znyc.Admin.Commons.Core.DataManager; +using Znyc.Admin.Commons.DataManager; +using Znyc.Admin.Commons.DependencyInjection; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Pages; +using static Dapper.SqlMapper; + +namespace Znyc.Admin.Commons.Repositories +{ + /// + /// 泛型仓储,实现泛型仓储接口 + /// + /// 实体类型 + /// 实体主键类型 + public abstract class BaseRepository : IRepository, ITransientDependency + where T : Entity + { + #region 构造函数及基本配置 + + /// + /// EF DBContext + /// + private readonly IDbContextCore _dbContext; + + private readonly IDbContextFactory _dbContextFactory; + + /// + /// + /// + protected DbSet DbSet => DbContext.GetDbSet(); + + /// + /// 获取访问数据库配置 + /// + protected DbConnectionOptions dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(); + + /// + /// 需要初始化的对象表名 + /// + protected string tableName = typeof(T).GetCustomAttribute(false)?.Name; + + /// + /// 数据库参数化访问的占位符 + /// + protected string parameterPrefix = "@"; + + /// + /// 防止和保留字、关键字同名的字段格式,如[value] + /// + protected string safeFieldFormat = "[{0}]"; + + /// + /// 数据库的主键字段名,若主键不是Id请重载BaseRepository设置 + /// + protected string primaryKey = "Id"; + + /// + /// 排序字段 + /// + protected string sortField; + + /// + /// 是否为降序 + /// + protected bool isDescending = true; + + /// + /// 选择的字段,默认为所有(*) + /// + protected string selectedFields = " * "; + + /// + /// 是否开启多租户 + /// + protected bool isMultiTenant = false; + + /// + /// 排序字段 + /// + public string SortField + { + get => sortField; + set => sortField = value; + } + /// + /// + /// + public string PrimaryKey => primaryKey; + + /// + /// 构造方法 + /// + public BaseRepository() + { + } + + /// + /// 构造方法,注入上下文 + /// + /// 上下文 + public BaseRepository(IDbContextCore dbContext) + { + if (dbContext == null) + { + throw new ArgumentNullException(nameof(dbContext)); + } + + _dbContext = dbContext; + } + + /// + /// 构造方法,注入上下文 + /// + /// 上下文 + public BaseRepository(IDbContextFactory dbContextFactory) + { + _dbContextFactory = dbContextFactory; + } + + #endregion 构造函数及基本配置 + + #region Dapper 操作 + + /// + /// 用Dapper原生方法操作数据,支持读写操作 + /// + public IDbConnection DapperConn => new DapperDbContext().GetConnection(); + + /// + /// 用Dapper原生方法,仅用于只读数据库 + /// + public IDbConnection DapperConnRead => new DapperDbContext().GetConnection(false); + + #region 查询获得对象和列表 + + /// + /// 根据id获取一个对象 + /// + /// 主键 + /// + public virtual T Get(TKey primaryKey) + { + return DapperConnRead.Get(primaryKey); + } + + /// + /// 异步根据id获取一个对象 + /// + /// 主键 + /// + public virtual async Task GetAsync(TKey primaryKey) + { + return await DapperConnRead.GetAsync(primaryKey); + } + + /// + /// 根据条件获取一个对象 + /// + /// 查询条件 + /// + public virtual T GetWhere(string where) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"select * from {tableName} "; + sql += " where " + where; + return DapperConnRead.QueryFirstOrDefault(sql); + } + + /// + /// 根据条件异步获取一个对象 + /// + /// 查询条件 + /// + public virtual async Task GetWhereAsync(string where) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"select * from {tableName} "; + sql += " where " + where; + + return await DapperConnRead.QueryFirstOrDefaultAsync(sql); + } + + /// + /// 获取所有数据,谨慎使用 + /// + /// 事务 + /// + public virtual IEnumerable GetAll(IDbTransaction trans = null) + { + return GetListWhere(); + } + + /// + /// 获取所有数据,谨慎使用 + /// + /// + /// + public virtual async Task> GetAllAsync(IDbTransaction trans = null) + { + return await GetListWhereAsync(); + } + + /// + /// 根据查询条件获取数据集合 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetListWhere(string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sql = $"select {selectedFields} from {tableName} "; + if (!string.IsNullOrWhiteSpace(where)) + { + sql += " where " + @where; + } + + return DapperConnRead.Query(sql, trans); + } + + /// + /// 根据查询条件获取数据集合 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetListWhereAsync(string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sql = $"select {selectedFields} from {tableName} where IsDeleted=0"; + if (!string.IsNullOrWhiteSpace(where)) + { + sql += " and" + @where; + } + + return await DapperConnRead.QueryAsync(sql, trans); + } + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetListTopWhere(int top, string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sql = $"select top {top} {selectedFields} from " + tableName; + ; + if (dbConnectionOptions.DatabaseType == DatabaseType.SqlServer) + { + if (!string.IsNullOrWhiteSpace(where)) + { + sql += " where " + @where; + } + } + else if (dbConnectionOptions.DatabaseType == DatabaseType.MySql) + { + sql = $"select {selectedFields} from " + tableName; + + if (!string.IsNullOrWhiteSpace(where)) + { + sql += " where " + @where; + } + + sql += $" LIMIT 0,{top}; "; + } + + return DapperConnRead.Query(sql, trans); + } + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetListTopWhereAsync(int top, string where = null, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sql = $"select top {top} {selectedFields} from " + tableName; + if (dbConnectionOptions.DatabaseType == DatabaseType.SqlServer) + { + if (!string.IsNullOrWhiteSpace(where)) + { + sql += " where " + @where; + } + } + else if (dbConnectionOptions.DatabaseType == DatabaseType.MySql) + { + sql = $"select {selectedFields} from " + tableName; + + if (!string.IsNullOrWhiteSpace(where)) + { + sql += " where " + @where; + } + + sql += $" LIMIT 0,{top}; "; + } + + return await DapperConnRead.QueryAsync(sql, trans); + } + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetAllByIsIsDeleted(string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsDeleted=1 "; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return GetListWhere(sqlWhere, trans); + } + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetAllByIsNotIsDeleted(string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsDeleted=0 "; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return GetListWhere(sqlWhere, trans); + } + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetAllByIsEnabledMark(string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsEnabled=1 "; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return GetListWhere(sqlWhere, trans); + } + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetAllByIsNotEnabledMark(string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsEnabled=0 "; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return GetListWhere(sqlWhere, trans); + } + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetAllByIsNotDeleteAndEnabledMark(string where = null, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsDeleted=0"; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return GetListWhere(sqlWhere, trans); + } + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetAllByIsIsDeletedAsync(string where = null, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsDeleted=1"; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return await GetListWhereAsync(sqlWhere, trans); + } + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetAllByIsNotIsDeletedAsync(string where = null, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsDeleted=0 "; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return await GetListWhereAsync(sqlWhere, trans); + } + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetAllByIsEnabledMarkAsync(string where = null, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsEnabled=1 "; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return await GetListWhereAsync(sqlWhere, trans); + } + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + string sqlWhere = " IsDeleted=0"; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + @where; + } + + return await GetListWhereAsync(sqlWhere, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, IDbTransaction trans = null) + { + return FindWithPager(condition, info, SortField, isDescending, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, string fieldToSort, + IDbTransaction trans = null) + { + return FindWithPager(condition, info, fieldToSort, isDescending, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + public virtual async Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, + IDbTransaction trans = null) + { + return await FindWithPagerAsync(condition, info, fieldToSort, isDescending, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + public virtual async Task> FindWithPagerAsync(string condition, PagerInfo info, + IDbTransaction trans = null) + { + return await FindWithPagerAsync(condition, info, SortField, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// 事务对象 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null) + { + List list = new List(); + + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + PagerHelper pagerHelper = new PagerHelper(tableName, selectedFields, fieldToSort, info.PageSize, + info.CurrenetPageIndex, desc, condition); + + string pageSql = pagerHelper.GetPagingSql(true, dbConnectionOptions.DatabaseType); + pageSql += ";" + pagerHelper.GetPagingSql(false, dbConnectionOptions.DatabaseType); + + GridReader reader = DapperConnRead.QueryMultiple(pageSql); + info.RecordCount = reader.ReadFirst(); + list = reader.Read().AsList(); + return list; + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// 事务对象 + /// 指定对象的集合 + public virtual async Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null) + { + List list = new List(); + + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + PagerHelper pagerHelper = new PagerHelper(tableName, selectedFields, fieldToSort, info.PageSize, + info.CurrenetPageIndex, desc, condition); + + string pageSql = pagerHelper.GetPagingSql(true, dbConnectionOptions.DatabaseType); + pageSql += ";" + pagerHelper.GetPagingSql(false, dbConnectionOptions.DatabaseType); + + GridReader reader = await DapperConnRead.QueryMultipleAsync(pageSql); + info.RecordCount = reader.ReadFirst(); + list = reader.Read().AsList(); + return list; + } + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + public virtual List FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null) + { + List list = new List(); + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + StringBuilder sb = new StringBuilder(); + int startRows = (info.CurrenetPageIndex - 1) * info.PageSize + 1; //起始记录 + int endNum = info.CurrenetPageIndex * info.PageSize; //结束记录 + string strOrder = string.Format(" {0} {1}", fieldToSort, desc ? "DESC" : "ASC"); + sb.AppendFormat("SELECT count(*) as RecordCount FROM (select {0} FROM {1} where {2}) AS main_temp;", + primaryKey, tableName, condition); + sb.AppendFormat( + "SELECT * FROM ( SELECT ROW_NUMBER() OVER (order by {0}) AS rows ,{1} FROM {2} where {3}) AS main_temp where rows BETWEEN {4} and {5}", + strOrder, selectedFields, tableName, condition, startRows, endNum); + GridReader reader = DapperConnRead.QueryMultiple(sb.ToString()); + info.RecordCount = reader.ReadFirst(); + list = reader.Read().AsList(); + return list; + } + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + public virtual async Task> FindWithPagerSqlAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null) + { + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + StringBuilder sb = new StringBuilder(); + int startRows = (info.CurrenetPageIndex - 1) * info.PageSize + 1; //起始记录 + int endNum = info.CurrenetPageIndex * info.PageSize; //结束记录 + string strOrder = string.Format(" {0} {1}", fieldToSort, desc ? "DESC" : "ASC"); + sb.AppendFormat("SELECT count(*) as RecordCount FROM (select {0} FROM {1} where {2}) AS main_temp;", + primaryKey, tableName, condition); + sb.AppendFormat( + "SELECT * FROM ( SELECT ROW_NUMBER() OVER (order by {0}) AS rows ,{1} FROM {2} where {3}) AS main_temp where rows BETWEEN {4} and {5}", + strOrder, selectedFields, tableName, condition, startRows, endNum); + GridReader reader = await DapperConnRead.QueryMultipleAsync(sb.ToString()); + info.RecordCount = reader.ReadFirst(); + List list = reader.Read().AsList(); + return list; + } + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + public virtual List FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null) + { + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + StringBuilder sb = new StringBuilder(); + int startRows = (info.CurrenetPageIndex - 1) * info.PageSize + 1; //起始记录 + int endNum = info.CurrenetPageIndex * info.PageSize; //结束记录 + string strOrder = string.Format(" {0} {1}", fieldToSort, desc ? "DESC" : "ASC"); + sb.AppendFormat( + "SELECT count(*) as RecordCount FROM (select t1.{0} FROM {1} t1 inner join sys_adminuser t2 on t1.CreatedUserId = t2.Id where {2}) AS main_temp;", + primaryKey, tableName, condition); + sb.AppendFormat( + "SELECT * FROM (SELECT ROW_NUMBER() OVER (order by {0}) AS rows ,t1.{1},t2.Account as Account,t2.UserName as UserName,t2.RealName as RealName,t2.HeadIcon as HeadIcon ,t2.MobilePhone as MobilePhone FROM {2} t1 inner join sys_adminuser t2 on t1.CreatedUserId = t2.Id " + + "where {3}) AS main_temp where rows BETWEEN {4} and {5}", strOrder, selectedFields, tableName, + condition, startRows, endNum); + + GridReader reader = DapperConnRead.QueryMultiple(sb.ToString()); + info.RecordCount = reader.ReadFirst(); + List list = reader.Read().AsList(); + return list; + } + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + public virtual async Task> FindWithPagerRelationUserAsync(string condition, PagerInfo info, + string fieldToSort, bool desc, IDbTransaction trans = null) + { + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + StringBuilder sb = new StringBuilder(); + int startRows = (info.CurrenetPageIndex - 1) * info.PageSize + 1; //起始记录 + int endNum = info.CurrenetPageIndex * info.PageSize; //结束记录 + string strOrder = string.Format(" {0} {1}", fieldToSort, desc ? "DESC" : "ASC"); + sb.AppendFormat( + "SELECT count(*) as RecordCount FROM (select t1.{0} FROM {1} t1 inner join sys_adminuser t2 on t1.CreatedUserId = t2.Id where {2}) AS main_temp;", + primaryKey, tableName, condition); + sb.AppendFormat( + "SELECT * FROM (SELECT ROW_NUMBER() OVER (order by {0}) AS rows ,t1.{1},t2.Account as Account,t2.UserName as UserName,t2.RealName as RealName,t2.HeadIcon as HeadIcon ,t2.MobilePhone as MobilePhone FROM {2} t1 inner join sys_adminuser t2 on t1.CreatedUserId = t2.Id " + + "where {3}) AS main_temp where rows BETWEEN {4} and {5}", strOrder, selectedFields, tableName, + condition, startRows, endNum); + + GridReader reader = await DapperConnRead.QueryMultipleAsync(sb.ToString()); + info.RecordCount = reader.ReadFirst(); + List list = reader.Read().AsList(); + return list; + } + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + public virtual int GetCountByWhere(string condition, string fieldName = "*") + { + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + string sql = $"select count({fieldName}) from {tableName} where "; + if (!string.IsNullOrWhiteSpace(condition)) + { + sql = sql + condition; + } + + return DapperConnRead.Query(sql).FirstOrDefault(); + } + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + public virtual async Task GetCountByWhereAsync(string condition, string fieldName = "*") + { + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", condition)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + string sql = $"select count({fieldName}) from {tableName} where IsDeleted=0 and "; + if (!string.IsNullOrWhiteSpace(condition)) + { + sql = sql + condition; + } + + return await DapperConnRead.QueryFirstAsync(sql); + } + + /// + /// 根据条件统计数据 + /// + /// + public virtual async Task GetCount() + { + string sql = $"select count(*) from {tableName} where IsDeleted=0 "; + return await DapperConnRead.QueryFirstAsync(sql); + } + + /// + /// 根据条件查询获取某个字段的最大值 + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段的最大值 + public virtual async Task GetMaxValueByFieldAsync(string strField, string where, + IDbTransaction trans = null) + { + string sql = $"select isnull(MAX({strField}),0) as maxVaule from {tableName} "; + if (dbConnectionOptions.DatabaseType == DatabaseType.MySql) + { + sql = $"select if(isnull(MAX({strField})),0,MAX({strField})) as maxVaule from {tableName} "; + } + + if (!string.IsNullOrEmpty(where)) + { + sql += " where " + @where; + } + + return await DapperConnRead.QueryFirstAsync(sql); + } + + /// + /// 根据条件统计某个字段之和,sum(字段) + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段求和后的值 + public virtual async Task GetSumValueByFieldAsync(string strField, string where, + IDbTransaction trans = null) + { + string sql = $"select isnull(sum({strField}),0) as sumVaule from {tableName} "; + if (dbConnectionOptions.DatabaseType == DatabaseType.MySql) + { + sql = $"select if(isnull(sum({strField})),0,sum({strField})) as sumVaule from {tableName} "; + } + + if (!string.IsNullOrEmpty(where)) + { + sql += " where " + @where; + } + + return await DapperConnRead.QueryFirstAsync(sql); + } + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetAllByIsNotEnabledMarkAsync(string where = null, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + string sqlWhere = " EnabledMark=0"; + if (!string.IsNullOrWhiteSpace(where)) + { + sqlWhere += " and " + where; + } + return await GetListWhereAsync(sqlWhere, trans); + } + + #endregion 查询获得对象和列表 + + #region 新增、修改和删除 + + /// + /// 新增 + /// + /// + /// 事务对象 + /// + public virtual long Insert(T entity, IDbTransaction trans = null) + { + return DapperConn.Insert(entity); + } + + /// + /// 异步新增 + /// + /// + /// 事务对象 + /// 1新增成功,0新增失败 + public virtual async Task InsertAsync(T entity, IDbTransaction trans = null) + { + return await DapperConn.InsertAsync(entity); + } + + /// + /// 异步新增实体返回主键 + /// + /// + /// + /// + public virtual async Task InsertReturnPrimaryKeyAsync(T entity, IDbTransaction trans = null) + { + return await DapperConn.InsertReturnPrimaryKeyAsync(entity); + } + + /// + /// 批量插入数据 + /// + /// + /// 执行成功返回true,否则为false + public virtual void Insert(List entities) + { + DbContext.BulkInsert(entities); + } + + /// + /// 更新 + /// + /// + /// 主键 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool Update(T entity, TKey primaryKey, IDbTransaction trans = null) + { + return DbContext.Edit(entity) > 0; + } + + /// + /// 更新 + /// + /// + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool Update(T entity, IDbTransaction trans = null) + { + return DbContext.Edit(entity) > 0; + } + + /// + /// + /// + /// + /// + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task UpdateAsync(T entity, TKey primaryKey, IDbTransaction trans = null) + { + return await DapperConn.UpdateAsync(entity); + } + + /// + /// 同步物理删除实体。 + /// + /// 实体 + /// + public virtual bool Delete(T entity) + { + DbContext.GetDbSet().Remove(entity); + return DbContext.SaveChanges() > 0; + } + + /// + /// 异步物理删除实体。 + /// + /// 实体 + /// 事务对象 + /// + public virtual async Task DeleteAsync(T entity, IDbTransaction trans = null) + { + DbContext.GetDbSet().Remove(entity); + return await DbContext.SaveChangesAsync() > 0; + } + + /// + /// 物理删除信息 + /// + /// + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool Delete(TKey primaryKey, IDbTransaction trans = null) + { + List> param = new List>(); + string sql = $"delete from {tableName} where " + PrimaryKey + "=@PrimaryKey"; + Tuple tupel = new Tuple(sql, new { @PrimaryKey = primaryKey }); + + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 异步物理删除信息 + /// + /// + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task DeleteAsync(TKey primaryKey, IDbTransaction trans = null) + { + List> param = new List>(); + string sql = $"delete from {tableName} where " + PrimaryKey + "=@PrimaryKey"; + Tuple tupel = new Tuple(sql, new { @PrimaryKey = primaryKey }); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 按主键批量删除 + /// + /// 主键Id List集合 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool DeleteBatch(IList ids, IDbTransaction trans = null) + { + List> param = new List>(); + string sql = $"delete from {tableName} where PrimaryKey in (@PrimaryKey)"; + Tuple tupel = new Tuple(sql, new { @PrimaryKey = ids }); + + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 按条件批量删除 + /// + /// 条件 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool DeleteBatchWhere(string where, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + List> param = new List>(); + string sql = $"delete from {tableName} where " + where; + Tuple tupel = new Tuple(sql, null); + + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 按条件批量删除 + /// + /// 条件 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task DeleteBatchWhereAsync(string where, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + List> param = new List>(); + string sql = $"delete from {tableName} where " + where; + Tuple tupel = new Tuple(sql, null); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 根据指定对象的ID和用户ID,从数据库中删除指定对象(用于记录人员的操作日志) + /// + /// 指定对象的ID + /// 用户ID + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool DeleteByUser(TKey primaryKey, int userId, IDbTransaction trans = null) + { + List> param = new List>(); + string sql = $"delete from {tableName} where " + PrimaryKey + " = @PrimaryKey"; + Tuple tupel = new Tuple(sql, new { @PrimaryKey = primaryKey }); + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 异步根据指定对象的ID和用户ID,从数据库中删除指定对象(用于记录人员的操作日志) + /// + /// 指定对象的ID + /// 用户ID + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task DeleteByUserAsync(TKey primaryKey, int userId, IDbTransaction trans = null) + { + List> param = new List>(); + string sql = $"delete from {tableName} where " + PrimaryKey + " = @PrimaryKey"; + Tuple tupel = new Tuple(sql, new { @PrimaryKey = primaryKey }); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 逻辑删除信息,bl为true时将IsDeleted设置为1删除,bl为flase时将IsDeleted设置为10-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool DeleteSoft(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null) + { + string sql = $"update {tableName} set "; + if (bl) + { + sql += "IsDeleted=0 "; + } + else + { + sql += "IsDeleted=1 "; + } + + DateTime deleteTime = DateTime.Now; + sql += ",ModifiedTime=@ModifiedTime where " + PrimaryKey + "=@PrimaryKey"; + List> param = new List>(); + Tuple tupel = new Tuple(sql, new { @PrimaryKey = primaryKey, @DeleteTime = deleteTime }); + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 异步逻辑删除信息,bl为true时将IsDeleted设置为1删除,bl为flase时将IsDeleted设置为0-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task DeleteSoftAsync(bool bl, TKey primaryKey, long userId = 0, + IDbTransaction trans = null) + { + string sql = $"update {tableName} set "; + if (bl) + { + sql += "IsDeleted=0 "; + } + else + { + sql += "IsDeleted=1 "; + } + + DateTime deleteTime = DateTime.Now; + sql += ",ModifiedTime=@ModifiedTime where " + PrimaryKey + "=@PrimaryKey"; + List> param = new List>(); + Tuple tupel = new Tuple(sql, new { @PrimaryKey = primaryKey, @ModifiedTime = deleteTime }); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 异步批量软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 c + /// 条件 + /// 操作用户 + /// 事务对象 + /// + public virtual async Task DeleteSoftBatchAsync(bool bl, string where, long userId = 0, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"update {tableName} set "; + if (bl) + { + sql += "IsDeleted=0 "; + } + else + { + sql += "IsDeleted=1 "; + } + + DateTime deleteTime = DateTime.Now; + sql += ",ModifiedTime=@ModifiedTime where " + where; + + List> param = new List>(); + Tuple tupel = new Tuple(sql, new { @ModifiedTime = deleteTime }); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 设置数据有效性,将IsEnabled设置为1-有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool SetEnabledMark(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null) + { + string sql = $"update {tableName} set "; + if (bl) + { + sql += "IsEnabled=1 "; + } + else + { + sql += "IsEnabled=0 "; + } + + DateTime ModifiedTime = DateTime.Now; + sql += ",ModifiedTime=@ModifiedTime where " + PrimaryKey + "=@PrimaryKey"; + + List> param = new List>(); + Tuple tupel = new Tuple(sql, new { @PrimaryKey = primaryKey, @ModifiedTime = ModifiedTime }); + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task SetEnabledMarkAsync(bool bl, TKey primaryKey, long userId = 0, + IDbTransaction trans = null) + { + string sql = $"update {tableName} set "; + if (bl) + { + sql += "IsEnabled=1 "; + } + else + { + sql += "IsEnabled=0 "; + } + + if (!string.IsNullOrEmpty(userId.ToString())) + { + sql += ",ModifiedUserId='" + userId + "'"; + } + + DateTime ModifiedTime = DateTime.Now; + sql += ",ModifiedTime=@ModifiedTime where " + PrimaryKey + "=@PrimaryKey"; + + List> param = new List>(); + Tuple tupel = new Tuple(sql, new { @PrimaryKey = PrimaryKey, @ModifiedTime = ModifiedTime }); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 条件 + /// 操作用户 + /// 事务对象 + /// + public virtual async Task SetEnabledMarkByWhereAsync(bool bl, string where, long userId = 0, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"update {tableName} set "; + if (bl) + { + sql += "IsEnabled=1 "; + } + else + { + sql += "IsEnabled=0 "; + } + + if (!string.IsNullOrEmpty(userId.ToString())) + { + sql += ",ModifiedUserId='" + userId + "'"; + } + + DateTime ModifiedTime = DateTime.Now; + sql += ",ModifiedTime=@ModifiedTime where " + where; + + List> param = new List>(); + Tuple tupel = new Tuple(sql, new { ModifiedTime = ModifiedTime }); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 条件 + /// + /// + /// + /// + public virtual async Task SetEnabledMarkByWhereAsync(bool bl, string where, object paramparameters = null, + long userId = 0, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"update {tableName} set "; + if (bl) + { + sql += "IsEnabled=1 "; + } + else + { + sql += "IsEnabled=0 "; + } + + if (!string.IsNullOrEmpty(userId.ToString())) + { + sql += ",ModifiedUserId='" + userId + "'"; + } + + DateTime ModifiedTime = DateTime.Now; + sql += ",ModifiedTime=@ModifiedTime " + where; + + List> param = new List>(); + Tuple tupel = new Tuple(sql, new { ModifiedTime = ModifiedTime, paramparameters }); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 更新某一字段值,字段值字符类型 + /// + /// 字段 + /// 字段值字符类型 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool UpdateTableField(string strField, string fieldValue, string where, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"update {tableName} set " + strField + "='" + fieldValue + "'"; + if (!string.IsNullOrEmpty(where)) + { + sql += " where " + @where; + } + + List> param = new List>(); + Tuple tupel = new Tuple(sql, null); + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 更新某一字段值,字段值字符类型 + /// + /// 字段 + /// 字段值字符类型 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task UpdateTableFieldAsync(string strField, string fieldValue, string where, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"update {tableName} set " + strField + "='" + fieldValue + "'"; + if (!string.IsNullOrEmpty(where)) + { + sql += " where " + @where; + } + + List> param = new List>(); + Tuple tupel = new Tuple(sql, null); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 更新某一字段值,字段值为数字 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool UpdateTableField(string strField, int fieldValue, string where, IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"update {tableName} set " + strField + "=" + fieldValue + ""; + if (!string.IsNullOrEmpty(where)) + { + sql += " where " + @where; + } + + List> param = new List>(); + Tuple tupel = new Tuple(sql, null); + param.Add(tupel); + Tuple result = ExecuteTransaction(param); + return result.Item1; + } + + /// + /// 更新某一字段值,字段值为数字 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task UpdateTableFieldAsync(string strField, int fieldValue, string where, + IDbTransaction trans = null) + { + if (HasInjectionData(where)) + { + Log4NetHelper.Info(string.Format("检测出SQL注入的恶意数据, {0}", where)); + throw new Exception("检测出SQL注入的恶意数据"); + } + + if (string.IsNullOrEmpty(where)) + { + @where = "1=1"; + } + + string sql = $"update {tableName} set " + strField + "=" + fieldValue + ""; + if (!string.IsNullOrEmpty(where)) + { + sql += " where " + @where; + } + + List> param = new List>(); + Tuple tupel = new Tuple(sql, null); + param.Add(tupel); + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + + /// + /// 多表多数据操作批量插入、更新、删除--事务 + /// + /// 事务 + /// 超时 + /// + public async Task> ExecuteTransactionAsync(List> trans, + int? commandTimeout = null) + { + if (!trans.Any()) + { + return new Tuple(false, "执行事务SQL语句不能为空!"); + } + + using (IDbConnection connection = DapperConn) + { + bool isClosed = connection.State == ConnectionState.Closed; + if (isClosed) + { + connection.Open(); + } + + using (IDbTransaction transaction = connection.BeginTransaction()) + { + try + { + foreach (Tuple tran in trans) + { + await connection.ExecuteAsync(tran.Item1, tran.Item2, transaction, commandTimeout); + } + //提交事务 + transaction.Commit(); + return new Tuple(true, string.Empty); + } + catch (Exception ex) + { + //回滚事务 + Log4NetHelper.Error("", ex); + transaction.Rollback(); + connection.Close(); + connection.Dispose(); + DapperConn.Close(); + DapperConn.Dispose(); + throw ex; + } + finally + { + connection.Close(); + connection.Dispose(); + DapperConn.Close(); + DapperConn.Dispose(); + } + } + } + } + + /// + /// 多表多数据操作批量插入、更新、删除--事务 + /// + /// 事务 + /// 超时 + /// + public Tuple ExecuteTransaction(List> trans, int? commandTimeout = null) + { + if (!trans.Any()) + { + return new Tuple(false, "执行事务SQL语句不能为空!"); + } + + using (IDbConnection connection = DapperConn) + { + bool isClosed = connection.State == ConnectionState.Closed; + if (isClosed) + { + connection.Open(); + } + //开启事务 + using (IDbTransaction transaction = connection.BeginTransaction()) + { + try + { + foreach (Tuple tran in trans) + { + connection.Execute(tran.Item1, tran.Item2, transaction, commandTimeout); + } + //提交事务 + transaction.Commit(); + return new Tuple(true, string.Empty); + } + catch (Exception ex) + { + //回滚事务 + Log4NetHelper.Error("", ex); + transaction.Rollback(); + connection.Close(); + connection.Dispose(); + DapperConn.Close(); + DapperConn.Dispose(); + return new Tuple(false, ex.ToString()); + } + finally + { + connection.Close(); + connection.Dispose(); + DapperConn.Close(); + DapperConn.Dispose(); + } + } + } + } + + #endregion 新增、修改和删除 + + #endregion Dapper 操作 + + #region EF操作 + + /// + /// EF 上下文接口,可读可写 + /// + public virtual IDbContextCore DbContext => _dbContext; + + /// + /// EF 上下文接口,仅可读 + /// + public virtual IDbContextCore DbContextRead => _dbContextFactory.CreateContext(WriteAndReadEnum.Read); + + #region 新增 + + /// + /// 新增实体 + /// + /// + /// + public virtual int Add(T entity) + { + return DbContext.Add(entity); + } + + /// + /// 新增实体 + /// + /// + /// + public virtual async Task AddAsync(T entity) + { + return await DbContext.AddAsync(entity); + } + + /// + /// 批量新增实体,数量量较多是推荐使用BulkInsert() + /// + /// + /// + public virtual int AddRange(ICollection entities) + { + return DbContext.AddRange(entities); + } + + /// + /// 批量新增实体,数量量较多是推荐使用BulkInsert() + /// + /// + /// + public virtual async Task AddRangeAsync(ICollection entities) + { + return await DbContext.AddRangeAsync(entities); + } + + /// + /// 批量新增SqlBulk方式,效率最高 + /// + /// 数据实体集合 + /// 数据库表名称,默认为实体名称 + public virtual void BulkInsert(IList entities, string destinationTableName = null) + { + DbContext.BulkInsert(entities, destinationTableName); + } + + /// + /// 执行新增的sql语句 + /// + /// 新增Sql语句 + /// + public int AddBySql(string sql) + { + return DbContext.ExecuteSqlWithNonQuery(sql); + } + + #endregion 新增 + + #region Update + + /// + /// 更新数据实体 + /// + /// + /// + public virtual int Edit(T entity) + { + return DbContext.Edit(entity); + } + + /// + /// 批量更新数据实体 + /// + /// + /// + public virtual int EditRange(ICollection entities) + { + return DbContext.EditRange(entities); + } + + /// + /// 更新指定字段的值 + /// + /// 数据实体 + /// 指定字段 + /// + public virtual int Update(T model, params string[] updateColumns) + { + DbContext.Update(model, updateColumns); + return DbContext.SaveChanges(); + } + + /// + /// 执行更新数据的Sql语句 + /// + /// 更新数据的Sql语句 + /// + public int UpdateBySql(string sql) + { + return DbContext.ExecuteSqlWithNonQuery(sql); + } + + #endregion Update + + #region Delete + + /// + /// 根据主键删除数据 + /// + /// + /// + public virtual int Delete(TKey key) + { + return DbContext.Delete(key); + } + + /// + /// 执行删除数据Sql语句 + /// + /// 删除的Sql语句 + /// + public int DeleteBySql(string sql) + { + return DbContext.ExecuteSqlWithNonQuery(sql); + } + + #endregion Delete + + #region Query + + /// + /// 根据条件统计数量Count() + /// + /// + /// + public virtual int Count(Expression> @where = null) + { + return DbContext.Count(where); + } + + /// + /// 根据条件统计数量Count() + /// + /// + /// + public virtual async Task CountAsync(Expression> @where = null) + { + return await DbContext.CountAsync(where); + } + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// + public virtual bool Exist(Expression> @where = null) + { + return DbContext.Exist(where); + } + + /// + /// 是否存在,存在返回true,不存在返回false + /// + /// + /// + public virtual async Task ExistAsync(Expression> @where = null) + { + return await DbContext.ExistAsync(where); + } + + /// + /// 根据主键获取实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + public virtual T GetSingle(TKey key) + { + return DbContext.Find(key); + } + + /// + /// 根据主键获取实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + public virtual async Task GetSingleAsync(TKey key) + { + return await DbContext.FindAsync(key); + } + + /// + /// 获取单个实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + public virtual T GetSingleOrDefault(Expression> @where = null) + { + return DbContext.GetSingleOrDefault(@where); + } + + /// + /// 获取单个实体。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + public virtual async Task GetSingleOrDefaultAsync(Expression> @where = null) + { + return await DbContext.GetSingleOrDefaultAsync(where); + } + + /// + /// 获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + public virtual IList Get(Expression> @where = null) + { + return DbContext.GetByCompileQuery(where); + } + + /// + /// 获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// + /// + public virtual async Task> GetAsync(Expression> @where = null) + { + return await DbContext.GetByCompileQueryAsync(where); + } + + /// + /// 分页获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。 + /// + /// 查询条件 + /// 分页信息 + /// 排序方式 + /// 排序字段 + /// + public virtual IEnumerable GetByPagination(Expression> @where, PagerInfo pagerInfo, + bool asc = false, params Expression>[] @orderby) + { + IQueryable filter = DbContext.Get(where); + if (orderby != null) + { + foreach (Expression> func in @orderby) + { + filter = asc ? filter.OrderBy(func).AsQueryable() : filter.OrderByDescending(func).AsQueryable(); + } + } + + pagerInfo.RecordCount = filter.Count(); + return filter.Skip(pagerInfo.PageSize * (pagerInfo.CurrenetPageIndex - 1)).Take(pagerInfo.PageSize); + } + + /// + /// sql语句查询数据集 + /// + /// + /// + public List GetBySql(string sql) + { + return DbContext.SqlQuery(sql); + } + + /// + /// sql语句查询数据集,返回输出Dto实体 + /// + /// + /// + /// + public List GetViews(string sql) + { + List list = DbContext.SqlQuery(sql); + return list; + } + + /// + /// 查询视图 + /// + /// 返回结果对象 + /// 视图名称 + /// 查询条件 + /// + public List GetViews(string viewName, Func @where) + { + List list = DbContext.SqlQuery($"select * from {viewName}"); + if (where != null) + { + return list.Where(@where).ToList(); + } + + return list; + } + + #endregion Query + + #endregion EF操作 + + #region 辅助类方法 + + /// + /// 验证是否存在注入代码(条件语句) + /// + /// + public virtual bool HasInjectionData(string inputData) + { + if (string.IsNullOrEmpty(inputData)) + { + return false; + } + + //里面定义恶意字符集合 + //验证inputData是否包含恶意集合 + if (Regex.IsMatch(inputData.ToLower(), GetRegexString())) + { + return true; + } + else + { + return false; + } + } + + /// + /// 获取正则表达式 + /// + /// + private static string GetRegexString() + { + //构造SQL的注入关键字符 + string[] strBadChar = + { + "select\\s", + "from\\s", + "insert\\s", + "delete\\s", + "update\\s", + "drop\\s", + "truncate\\s", + "exec\\s", + "count\\(", + "declare\\s", + "asc\\(", + "mid\\(", + //"char\\(", + "net user", + "xp_cmdshell", + "/add\\s", + "exec master.dbo.xp_cmdshell", + "net localgroup administrators" + }; + + //构造正则表达式 + string str_Regex = ".*("; + for (int i = 0; i < strBadChar.Length - 1; i++) + { + str_Regex += strBadChar[i] + "|"; + } + + str_Regex += strBadChar[^1] + ").*"; + + return str_Regex; + } + + #endregion 辅助类方法 + + #region IDisposable Support + + private bool disposedValue = false; // 要检测冗余调用 + + /// + /// + /// + /// + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + // TODO: 释放托管状态(托管对象)。 + } + + // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。 + // TODO: 将大型字段设置为 null。 + + disposedValue = true; + } + if (DbContext != null) + { + DbContext.Dispose(); + } + if (DapperConn != null) + { + DapperConn?.Dispose(); + } + } + + // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。 + // ~BaseRepository() { + // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 + // Dispose(false); + // } + + /// + /// + /// + public void Dispose() + { + // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 + Dispose(true); + + DbContext?.Dispose(); + DapperConn?.Dispose(); + // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。 + // GC.SuppressFinalize(this); + } + + #endregion IDisposable Support + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Services/BaseService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Services/BaseService.cs new file mode 100644 index 0000000..e22c79d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Core/Services/BaseService.cs @@ -0,0 +1,997 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Security.Claims; +using System.Text.Json; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.DependencyInjection; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; + +namespace Znyc.Admin.Commons.Services +{ + /// + /// + /// + /// + /// + /// + public abstract class BaseService : IService, ITransientDependency + where T : Entity + where TODto : class + where TKey : IEquatable + { + private readonly IHttpContextAccessor _accessor; + + /// + /// + /// + protected IRepository repository; + + /// + /// + /// + /// + protected BaseService(IRepository iRepository) + { + repository = iRepository; + } + + /// + /// + /// + /// + /// + protected BaseService(IRepository iRepository, IHttpContextAccessor accessor) + { + _accessor = accessor; + repository = iRepository; + } + + /// + /// 同步物理删除实体。 + /// + /// 实体 + /// 事务对象 + /// + public virtual bool Delete(T entity, IDbTransaction trans = null) + { + return repository.Delete(entity); + } + + /// + /// 同步物理删除实体。 + /// + /// 主键 + /// 事务对象 + /// + public virtual bool Delete(TKey id, IDbTransaction trans = null) + { + return repository.Delete(id, trans); + } + + /// + /// 异步物理删除实体。 + /// + /// 主键 + /// 事务对象 + /// + public virtual Task DeleteAsync(TKey id, IDbTransaction trans = null) + { + return repository.DeleteAsync(id, trans); + } + + /// + /// 异步物理删除实体。 + /// + /// 实体 + /// 事务对象 + /// + public virtual Task DeleteAsync(T entity, IDbTransaction trans = null) + { + return repository.DeleteAsync(entity, trans); + } + + /// + /// 按主键批量删除 + /// + /// + /// + /// + public virtual bool DeleteBatch(IList ids, IDbTransaction trans = null) + { + return repository.DeleteBatch(ids, trans); + } + + /// + /// 按条件批量删除 + /// + /// 条件 + /// + /// + public virtual bool DeleteBatchWhere(string where, IDbTransaction trans = null) + { + return repository.DeleteBatchWhere(where, trans); + } + + /// + /// 按条件批量删除 + /// + /// 条件 + /// + /// + public virtual async Task DeleteBatchWhereAsync(string where, IDbTransaction trans = null) + { + return await repository.DeleteBatchWhereAsync(where, trans); + } + + /// + /// 软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// + /// + public virtual bool DeleteSoft(bool bl, TKey id, long userId, IDbTransaction trans = null) + { + return repository.DeleteSoft(bl, id, userId, trans); + } + + /// + /// 异步软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 + /// 主键ID + /// 操作用户 + /// + /// + public virtual async Task DeleteSoftAsync(bool bl, TKey id, long userId, IDbTransaction trans = null) + { + return await repository.DeleteSoftAsync(bl, id, userId, trans); + } + + /// + /// 异步批量软删除信息,将IsDeleted设置为1-删除,0-恢复删除 + /// + /// true为不删除,false删除 c + /// 条件 + /// 操作用户 + /// 事务对象 + /// + public virtual async Task DeleteSoftBatchAsync(bool bl, string where, long userId = 0, + IDbTransaction trans = null) + { + return await repository.DeleteSoftBatchAsync(bl, where, userId, trans); + } + + /// + /// 同步查询单个实体。 + /// + /// 主键 + /// + public virtual T Get(TKey id) + { + return repository.Get(id); + } + + /// + /// 同步查询单个实体。 + /// + /// 主键 + /// + public virtual TODto GetOutDto(TKey id) + { + return repository.Get(id).MapTo(); + } + + /// + /// 同步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual T GetWhere(string where, IDbTransaction trans = null) + { + return repository.GetWhere(where); + } + + /// + /// 同步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual TODto GetOutDtoWhere(string where, IDbTransaction trans = null) + { + return repository.GetWhere(where).MapTo(); + } + + /// + /// 异步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task GetWhereAsync(string where, IDbTransaction trans = null) + { + return await repository.GetWhereAsync(where); + } + + /// + /// 异步查询单个实体。 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task GetOutDtoWhereAsync(string where, IDbTransaction trans = null) + { + T info = await repository.GetWhereAsync(where); + return info.MapTo(); + } + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetListTopWhere(int top, string where = null, IDbTransaction trans = null) + { + return repository.GetListTopWhere(top, where); + } + + /// + /// 根据查询条件查询前多少条数据 + /// + /// 多少条数据 + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetListTopWhereAsync(int top, string where = null, + IDbTransaction trans = null) + { + return await repository.GetListTopWhereAsync(top, where); + } + + /// + /// 同步查询所有实体。 + /// + /// 事务对象 + /// + public virtual IEnumerable GetAll(IDbTransaction trans = null) + { + return repository.GetAll(trans); + } + + /// + /// 异步步查询所有实体。 + /// + /// 事务对象 + /// + public virtual Task> GetAllAsync(IDbTransaction trans = null) + { + return repository.GetAllAsync(trans); + } + + /// + /// 异步查询单个实体。 + /// + /// 主键 + /// + public virtual async Task GetAsync(TKey id) + { + return await repository.GetAsync(id); + } + + /// + /// 异步查询单个实体。 + /// + /// 主键 + /// + public virtual async Task GetOutDtoAsync(TKey id) + { + T info = await repository.GetAsync(id); + return info.MapTo(); + } + + /// + /// 根据查询条件查询数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual IEnumerable GetListWhere(string where = null, IDbTransaction trans = null) + { + return repository.GetListWhere(where, trans); + } + + /// + /// 异步根据查询条件查询数据 + /// + /// 查询条件 + /// 事务对象 + /// + public virtual async Task> GetListWhereAsync(string where = null, IDbTransaction trans = null) + { + return await repository.GetListWhereAsync(where, trans); + } + + /// + /// 同步新增实体。 + /// + /// 实体 + /// 事务对象 + /// + public virtual long Insert(T entity, IDbTransaction trans = null) + { + return repository.Insert(entity, trans); + } + + /// + /// 异步步新增实体。 + /// + /// 实体 + /// 事务对象 + /// + public virtual Task InsertAsync(T entity, IDbTransaction trans = null) + { + return repository.InsertAsync(entity, trans); + } + + /// + /// 异步新增实体返回主键 + /// + /// + /// + /// + public virtual Task InsertReturnPrimaryKeyAsync(T entity, IDbTransaction trans = null) + { + return repository.InsertReturnPrimaryKeyAsync(entity, trans); + } + + /// + /// 同步批量新增实体。 + /// + /// 实体集合 + /// + public virtual void Insert(List entities) + { + repository.Insert(entities); + } + + /// + /// 同步更新实体。 + /// + /// 实体 + /// 主键ID + /// 事务对象 + /// + public virtual bool Update(T entity, TKey id, IDbTransaction trans = null) + { + return repository.Update(entity, id, trans); + } + + /// + /// 异步更新实体。 + /// + /// 实体 + /// 主键ID + /// 事务对象 + /// + public virtual Task UpdateAsync(T entity, TKey id, IDbTransaction trans = null) + { + return repository.UpdateAsync(entity, id, trans); + } + + /// + /// 更新某一字段值,字段值字符类型 + /// + /// 字段 + /// 字段值字符类型 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool UpdateTableField(string strField, string fieldValue, string where, + IDbTransaction trans = null) + { + return repository.UpdateTableField(strField, fieldValue, where, trans); + } + + /// + /// 更新某一字段值,字段值字符类型 + /// + /// 字段 + /// 字段值字符类型 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task UpdateTableFieldAsync(string strField, string fieldValue, string where, + IDbTransaction trans = null) + { + return await repository.UpdateTableFieldAsync(strField, fieldValue, where, trans); + } + + /// + /// 更新某一字段值,字段值数字类型 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual bool UpdateTableField(string strField, int fieldValue, string where, IDbTransaction trans = null) + { + return repository.UpdateTableField(strField, fieldValue, where, trans); + } + + /// + /// 更新某一字段值,字段值数字类型 + /// + /// 字段 + /// 字段值数字 + /// 条件,为空更新所有内容 + /// 事务对象 + /// 执行成功返回true,否则为false + public virtual async Task UpdateTableFieldAsync(string strField, int fieldValue, string where, + IDbTransaction trans = null) + { + return await repository.UpdateTableFieldAsync(strField, fieldValue, where, trans); + } + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// + /// + public virtual IEnumerable GetAllByIsIsDeleted(string where = null, IDbTransaction trans = null) + { + return repository.GetAllByIsIsDeleted(where, trans); + } + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// + /// + public virtual IEnumerable GetAllByIsNotIsDeleted(string where = null, IDbTransaction trans = null) + { + return repository.GetAllByIsNotIsDeleted(where, trans); + } + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// + /// + public virtual IEnumerable GetAllByIsEnabledMark(string where = null, IDbTransaction trans = null) + { + return repository.GetAllByIsEnabledMark(where, trans); + } + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// + /// + public virtual IEnumerable GetAllByIsNotEnabledMark(string where = null, IDbTransaction trans = null) + { + return repository.GetAllByIsNotEnabledMark(where, trans); + } + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// + /// + public virtual IEnumerable GetAllByIsNotDeleteAndEnabledMark(string where = null, + IDbTransaction trans = null) + { + return repository.GetAllByIsNotDeleteAndEnabledMark(where, trans); + } + + /// + /// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据 + /// + /// 查询条件 + /// + /// + public virtual async Task> GetAllByIsIsDeletedAsync(string where = null, + IDbTransaction trans = null) + { + return await repository.GetAllByIsIsDeletedAsync(where, trans); + } + + /// + /// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据 + /// + /// 查询条件 + /// + /// + public virtual async Task> GetAllByIsNotIsDeletedAsync(string where = null, + IDbTransaction trans = null) + { + return await repository.GetAllByIsNotIsDeletedAsync(where, trans); + } + + /// + /// 查询有效的数据,如果查询条件为空,即查询所有有效的数据 + /// + /// 查询条件 + /// + /// + public virtual async Task> GetAllByIsEnabledMarkAsync(string where = null, + IDbTransaction trans = null) + { + return await repository.GetAllByIsEnabledMarkAsync(where, trans); + } + + /// + /// 查询无效的数据,如果查询条件为空,即查询所有无效的数据 + /// + /// 查询条件 + /// + /// + public virtual async Task> GetAllByIsNotEnabledMarkAsync(string where = null, + IDbTransaction trans = null) + { + return await repository.GetAllByIsNotEnabledMarkAsync(where, trans); + } + + /// + /// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据 + /// + /// 查询条件 + /// + /// + public virtual async Task> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null, + IDbTransaction trans = null) + { + return await repository.GetAllByIsNotDeleteAndEnabledMarkAsync(where, trans); + } + + /// + /// 设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// + /// + public virtual bool SetEnabledMark(bool bl, TKey id, long userId = 0, IDbTransaction trans = null) + { + return repository.SetEnabledMark(bl, id, userId, trans); + } + + /// + /// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 主键ID + /// 操作用户 + /// + /// + public virtual async Task SetEnabledMarkAsync(bool bl, TKey id, long userId = 0, + IDbTransaction trans = null) + { + return await repository.SetEnabledMarkAsync(bl, id, userId, trans); + } + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// true为有效,false无效 + /// 条件 + /// 操作用户 + /// 事务对象 + /// + public virtual async Task SetEnabledMarkByWhereAsync(bool bl, string where, long userId = 0, + IDbTransaction trans = null) + { + return await repository.SetEnabledMarkByWhereAsync(bl, where, userId, trans); + } + + /// + /// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效 + /// + /// + /// + /// + /// + /// + /// + public virtual async Task SetEnabledMarkByWhereAsync(bool bl, string where, object paramparameters = null, + long userId = 0, IDbTransaction trans = null) + { + return await repository.SetEnabledMarkByWhereAsync(bl, where, paramparameters, userId, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, IDbTransaction trans = null) + { + return repository.FindWithPager(condition, info, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, string fieldToSort, + IDbTransaction trans = null) + { + return repository.FindWithPager(condition, info, fieldToSort, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 是否降序 + /// 事务对象 + /// 指定对象的集合 + public virtual List FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null) + { + return repository.FindWithPager(condition, info, fieldToSort, desc, trans); + } + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + public virtual List FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc, + IDbTransaction trans = null) + { + return repository.FindWithPagerSql(condition, info, fieldToSort, desc, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 排序方式 + /// 事务对象 + /// 指定对象的集合 + public virtual async Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null) + { + return await repository.FindWithPagerAsync(condition, info, fieldToSort, desc, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// 查询条件变换时请重写该方法。 + /// + /// 查询的条件 + /// 指定对象的集合 + public virtual PageResult FindWithPager(SearchInputDto search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(); + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = repository.FindWithPager(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// 查询条件变换时请重写该方法。 + /// + /// 查询的条件 + /// 指定对象的集合 + public virtual async Task> FindWithPagerAsync(SearchInputDto search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(); + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 事务对象 + /// 指定对象的集合 + public virtual async Task> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, + IDbTransaction trans = null) + { + return await repository.FindWithPagerAsync(condition, info, fieldToSort, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 事务对象 + /// 指定对象的集合 + public virtual async Task> FindWithPagerAsync(string condition, PagerInfo info, + IDbTransaction trans = null) + { + return await repository.FindWithPagerAsync(condition, info, trans); + } + + /// + /// 分页查询,自行封装sql语句(仅支持sql server) + /// 非常复杂的查询,可在具体业务模块重写该方法 + /// + /// 查询条件 + /// 分页信息 + /// 排序字段 + /// 排序方式 true为desc,false为asc + /// + /// + public virtual async Task> FindWithPagerSqlAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null) + { + return await repository.FindWithPagerAsync(condition, info, fieldToSort, desc, trans); + } + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + public virtual async Task> FindWithPagerRelationUserAsync(string condition, PagerInfo info, + string fieldToSort, bool desc, IDbTransaction trans = null) + { + return await repository.FindWithPagerRelationUserAsync(condition, info, fieldToSort, desc, trans); + } + + /// + /// 分页查询包含用户信息(仅支持sql server) + /// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段 + /// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone + /// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类 + /// + /// 查询条件字段需要加表别名 + /// 分页信息 + /// 排序字段,也需要加表别名 + /// 排序方式 + /// 事务 + /// + public virtual List FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null) + { + return repository.FindWithPagerRelationUser(condition, info, fieldToSort, desc, trans); + } + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + public virtual int GetCountByWhere(string condition, string fieldName = "*") + { + return repository.GetCountByWhere(condition, fieldName); + } + + /// + /// 根据条件统计数据 + /// + /// 查询条件 + /// 统计字段名称 + /// + public virtual async Task GetCountByWhereAsync(string condition, string fieldName = "*") + { + return await repository.GetCountByWhereAsync(condition, fieldName); + } + + /// + /// + /// + /// + public virtual async Task GetCount() + { + return await repository.GetCount(); + } + + /// + /// 根据条件查询获取某个字段的最大值 + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段的最大值 + public virtual async Task GetMaxValueByFieldAsync(string strField, string where, + IDbTransaction trans = null) + { + return await repository.GetMaxValueByFieldAsync(strField, where); + } + + /// + /// 根据条件统计某个字段之和,sum(字段) + /// + /// 字段 + /// 条件 + /// 事务 + /// 返回字段求和后的值 + public virtual async Task GetSumValueByFieldAsync(string strField, string where, + IDbTransaction trans = null) + { + return await repository.GetSumValueByFieldAsync(strField, where); + } + + /// + /// 多表操作--事务 + /// + /// 事务 + /// 超时 + /// + public virtual async Task> ExecuteTransactionAsync(List> trans, + int? commandTimeout = null) + { + return await repository.ExecuteTransactionAsync(trans, commandTimeout); + } + + /// + /// 多表操作--事务 + /// + /// 事务 + /// 超时 + /// + public virtual Tuple ExecuteTransaction(List> trans, + int? commandTimeout = null) + { + return repository.ExecuteTransaction(trans, commandTimeout); + } + + /// + /// 获取当前登录用户的数据访问权限 + /// + /// 是否开启,默认开启 + /// + protected virtual string GetDataPrivilege(bool blDeptCondition = true) + { + string where = "1=1"; + //开权限数据过滤 + if (blDeptCondition) + { + IEnumerable identities = HttpContextHelper.HttpContext.User.Identities; + ClaimsIdentity claimsIdentity = identities.First(); + List claimlist = claimsIdentity.Claims as List; + CacheHelper cacheHelper = new CacheHelper(); + if (claimlist[1].Value != "admin") + { + //如果公司过滤条件不为空,那么需要进行过滤 + List list = JsonSerializer.Deserialize>(cacheHelper + .Get("User_RoleData_" + claimlist[0].Value).ToJson()); + if (list.Count() > 0) + { + string DataFilterCondition = string.Join(",", list.ToArray()); + if (!string.IsNullOrEmpty(DataFilterCondition)) + { + @where += string.Format(" and (DeptId in ('{0}') or CreatedUserId='{1}')", + DataFilterCondition.Replace(",", "','"), claimlist[0].Value); + } + } + else + { + where += string.Format(" and CreatedUserId='{0}'", claimlist[0].Value); + } + + bool isMultiTenant = Configs.GetConfigurationValue("AppSetting", "IsMultiTenant").ToBool(); + if (isMultiTenant) + { + @where += string.Format(" and TenantId='{0}'", claimlist[3].Value); + } + } + } + + return where; + } + + #region IDisposable Support + + private bool disposedValue = false; // 要检测冗余调用 + + /// + /// + /// + /// + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + // TODO: 释放托管状态(托管对象)。 + } + + // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。 + // TODO: 将大型字段设置为 null。 + + disposedValue = true; + } + } + + // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。 + // ~BaseService() { + // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 + // Dispose(false); + // } + + /// + /// 添加此代码以正确实现可处置模式 + /// + void IDisposable.Dispose() + { + // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 + Dispose(true); + // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。 + // GC.SuppressFinalize(this); + } + + #endregion IDisposable Support + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/Check.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/Check.cs new file mode 100644 index 0000000..f57441d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/Check.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Properties; + +namespace Znyc.Admin.Commons.Data +{ + /// + /// 参数合法性检查类 + /// + [DebuggerStepThrough] + public static class Check + { + /// + /// 验证指定值的断言是否为真,如果不为真,抛出指定消息的指定类型异常 + /// + /// 异常类型 + /// 要验证的断言。 + /// 异常消息。 + private static void Require(bool assertion, string message) + where TException : Exception + { + if (assertion) + { + return; + } + + if (string.IsNullOrEmpty(message)) + { + throw new ArgumentNullException(nameof(message)); + } + + TException exception = (TException)Activator.CreateInstance(typeof(TException), message); + throw exception; + } + + /// + /// 验证指定值的断言表达式是否为真,不为值抛出异常 + /// + /// + /// 要验证的断言表达式 + /// 异常消息 + public static void Required(T value, Func assertionFunc, string message) + { + if (assertionFunc == null) + { + throw new ArgumentNullException(nameof(assertionFunc)); + } + + Require(assertionFunc(value), message); + } + + /// + /// 验证指定值的断言表达式是否为真,不为真抛出异常 + /// + /// 要判断的值的类型 + /// 抛出的异常类型 + /// 要判断的值 + /// 要验证的断言表达式 + /// 异常消息 + public static void Required(T value, Func assertionFunc, string message) + where TException : Exception + { + if (assertionFunc == null) + { + throw new ArgumentNullException("assertionFunc"); + } + + Require(assertionFunc(value), message); + } + + /// + /// 检查参数不能为空引用,否则抛出异常。 + /// + /// + /// 参数名称 + /// + public static void NotNull(T value, string paramName) + { + Require(value != null, string.Format(Resources.ParameterCheck_NotNull, paramName)); + } + + /// + /// 检查字符串不能为空引用或空字符串,否则抛出异常或异常。 + /// + /// + /// 参数名称。 + /// + /// + public static void NotNullOrEmpty(string value, string paramName) + { + Require(!string.IsNullOrEmpty(value), + string.Format(Resources.ParameterCheck_NotNullOrEmpty_String, paramName)); + } + + /// + /// 检查Guid值不能为Guid.Empty,否则抛出异常。 + /// + /// + /// 参数名称。 + /// + public static void NotEmpty(Guid value, string paramName) + { + Require(value != Guid.Empty, + string.Format(Resources.ParameterCheck_NotEmpty_Guid, paramName)); + } + + /// + /// 检查集合不能为空引用或空集合,否则抛出异常或异常。 + /// + /// 集合项的类型。 + /// + /// 参数名称。 + /// + /// + public static void NotNullOrEmpty(IReadOnlyList list, string paramName) + { + NotNull(list, paramName); + Require(list.Any(), + string.Format(Resources.ParameterCheck_NotNullOrEmpty_Collection, paramName)); + } + + /// + /// 检查集合中没有包含值为null的项 + /// + public static void HasNoNulls(IReadOnlyList list, string paramName) + { + NotNull(list, paramName); + Require(list.All(m => m != null), + string.Format(Resources.ParameterCheck_NotContainsNull_Collection, paramName)); + } + + /// + /// 检查参数必须小于[或可等于,参数]指定值,否则抛出异常。 + /// + /// 参数类型。 + /// + /// 参数名称。 + /// 要比较的值。 + /// 是否可等于。 + /// + public static void LessThan(T value, string paramName, T target, bool canEqual = false) + where T : IComparable + { + bool flag = canEqual ? value.CompareTo(target) <= 0 : value.CompareTo(target) < 0; + string format = canEqual ? Resources.ParameterCheck_NotLessThanOrEqual : Resources.ParameterCheck_NotLessThan; + Require(flag, string.Format(format, paramName, target)); + } + + /// + /// 检查参数必须大于[或可等于,参数]指定值,否则抛出异常。 + /// + /// 参数类型。 + /// + /// 参数名称。 + /// 要比较的值。 + /// 是否可等于。 + /// + public static void GreaterThan(T value, string paramName, T target, bool canEqual = false) + where T : IComparable + { + bool flag = canEqual ? value.CompareTo(target) >= 0 : value.CompareTo(target) > 0; + string format = canEqual + ? Resources.ParameterCheck_NotGreaterThanOrEqual + : Resources.ParameterCheck_NotGreaterThan; + Require(flag, string.Format(format, paramName, target)); + } + + /// + /// 检查参数必须在指定范围之间,否则抛出异常。 + /// + /// 参数类型。 + /// + /// 参数名称。 + /// 比较范围的起始值。 + /// 比较范围的结束值。 + /// 是否可等于起始值 + /// 是否可等于结束值 + /// + public static void Between(T value, string paramName, T start, T end, bool startEqual = false, + bool endEqual = false) + where T : IComparable + { + bool flag = startEqual ? value.CompareTo(start) >= 0 : value.CompareTo(start) > 0; + string message = startEqual + ? string.Format(Resources.ParameterCheck_Between, paramName, start, end) + : string.Format(Resources.ParameterCheck_BetweenNotEqual, paramName, start, end, start); + Require(flag, message); + + flag = endEqual ? value.CompareTo(end) <= 0 : value.CompareTo(end) < 0; + message = endEqual + ? string.Format(Resources.ParameterCheck_Between, paramName, start, end) + : string.Format(Resources.ParameterCheck_BetweenNotEqual, paramName, start, end, end); + Require(flag, message); + } + + /// + /// 检查指定路径的文件夹必须存在,否则抛出异常。 + /// + /// + /// 参数名称。 + /// + /// + public static void DirectoryExists(string directory, string paramName = null) + { + NotNull(directory, paramName); + Require(Directory.Exists(directory), + string.Format(Resources.ParameterCheck_DirectoryNotExists, directory)); + } + + /// + /// 检查指定路径的文件必须存在,否则抛出异常。 + /// + /// + /// 参数名称。 + /// 当文件路径为null时 + /// 当文件路径不存在时 + public static void FileExists(string filename, string paramName = null) + { + NotNull(filename, paramName); + Require(File.Exists(filename), + string.Format(Resources.ParameterCheck_FileNotExists, filename)); + } + + /// + /// 检查各属性的合法性,否则抛出异常 + /// + public static void Validate(IInputDto dto, string paramName) + { + NotNull(dto, paramName); + dto.Validate(); + } + + /// + /// 检查各属性的合法性,否则抛出异常 + /// + public static void Validate(TInputDto[] dtos, string paramName) + where TInputDto : IInputDto + { + NotNull(dtos, paramName); + foreach (TInputDto dto in dtos) + { + dto.Validate(); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/MicroDataTable.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/MicroDataTable.cs new file mode 100644 index 0000000..ba6953c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/MicroDataTable.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; + +namespace Znyc.Admin.Commons.Data +{ + /// + /// 查询结果数据表样式 + /// + public class MicroDataTable + { + /// + /// 整个查询语句结果的总条数,而非本DataTable的条数 + /// + public int TotalCount { get; set; } + + /// + /// 数据列名称 + /// + public List Columns { get; set; } = new List(); + + /// + /// 数据记录 + /// + public List Rows { get; set; } = new List(); + + /// + /// 主键 + /// + public MicroDataColumn[] PrimaryKey { get; set; } + + public MicroDataRow NewRow() + { + return new MicroDataRow(Columns, new object[Columns.Count]); + } + } + + public class MicroDataColumn + { + public string ColumnName { get; set; } + public Type ColumnType { get; set; } + } + + public class MicroDataRow + { + private readonly object[] _ItemArray; + public List Columns { get; private set; } + + public MicroDataRow(List columns, object[] itemArray) + { + Columns = columns; + _ItemArray = itemArray; + } + + public object this[int index] + { + get => _ItemArray[index]; + set => _ItemArray[index] = value; + } + + public object this[string columnName] + { + get + { + int i = 0; + foreach (MicroDataColumn column in Columns) + { + if (column.ColumnName == columnName) + { + break; + } + + i++; + } + + return _ItemArray[i]; + } + set + { + int i = 0; + foreach (MicroDataColumn column in Columns) + { + if (column.ColumnName == columnName) + { + break; + } + + i++; + } + + _ItemArray[i] = value; + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/MicroDataTableHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/MicroDataTableHelper.cs new file mode 100644 index 0000000..6314519 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Data/MicroDataTableHelper.cs @@ -0,0 +1,52 @@ +using System.Data.Common; + +namespace Znyc.Admin.Commons.Data +{ + public class MicroDataTableHelper + { + /// + /// DbDataReaders 数据转化Datatable + /// + /// + /// + /// + /// + public static MicroDataTable FillDataTable(DbDataReader reader, int pageIndex, int pageSize) + { + bool defined = false; + MicroDataTable table = new MicroDataTable(); + int index = 0; + int beginIndex = pageSize * pageIndex; + int endIndex = pageSize * (pageIndex + 1) - 1; + while (reader.Read()) + { + object[] values = new object[reader.FieldCount]; + if (!defined) + { + for (int i = 0; i < reader.FieldCount; i++) + { + MicroDataColumn column = new MicroDataColumn() + { + ColumnName = reader.GetName(i), + ColumnType = reader.GetFieldType(i) + }; + table.Columns.Add(column); + } + + defined = true; + } + + if (index >= beginIndex && index <= endIndex) + { + reader.GetValues(values); + table.Rows.Add(new MicroDataRow(table.Columns, values)); + } + + index++; + } + + table.TotalCount = index; + return table; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/IPrivateDependency.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/IPrivateDependency.cs new file mode 100644 index 0000000..8680182 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/IPrivateDependency.cs @@ -0,0 +1,9 @@ +namespace Znyc.Admin.Commons.DependencyInjection +{ + /// + /// 依赖空接口(禁止外部继承) + /// + public interface IPrivateDependency + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/IScopedDependency.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/IScopedDependency.cs new file mode 100644 index 0000000..0bca6f8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/IScopedDependency.cs @@ -0,0 +1,9 @@ +namespace Znyc.Admin.Commons.DependencyInjection +{ + /// + /// 作用域服务注册依赖 + /// + public interface IScopedDependency : IPrivateDependency + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/ISingletonDependency.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/ISingletonDependency.cs new file mode 100644 index 0000000..af6c5ed --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/ISingletonDependency.cs @@ -0,0 +1,9 @@ +namespace Znyc.Admin.Commons.DependencyInjection +{ + /// + /// 单例服务注册依赖 + /// + public interface ISingletonDependency : IPrivateDependency + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/ITransientDependency.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/ITransientDependency.cs new file mode 100644 index 0000000..651abce --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/DependencyInjection/ITransientDependency.cs @@ -0,0 +1,9 @@ +namespace Znyc.Admin.Commons.DependencyInjection +{ + /// + /// 暂时服务注册依赖 + /// + public interface ITransientDependency : IPrivateDependency + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/AudioHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/AudioHelper.cs new file mode 100644 index 0000000..037e34c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/AudioHelper.cs @@ -0,0 +1,183 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Media; +using System.Security; +using System.Security.Permissions; + +namespace Znyc.Admin.Commons.Device +{ + /// + /// WAV声音格式文件播放辅助类 + /// + [HostProtection(SecurityAction.LinkDemand, Resources = HostProtectionResource.ExternalProcessMgmt)] + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Advanced)] + public class AudioHelper + { + /// + /// 播放 .wav 格式的声音文件 + /// + /// 声音文件路径 + public static void Play(string location) + { + Play(location, AudioPlayMode.Background); + } + + /// + /// 播放 .wav 格式的声音文件 + /// + /// 播放声音的枚举模式。默认为AudioPlayMode.Background。 + /// 声音文件路径 + public static void Play(string location, AudioPlayMode playMode) + { + ValidateAudioPlayModeEnum(playMode, "playMode"); + string fileName = ValidateFilename(location); + SoundPlayer player1 = new SoundPlayer(fileName); + Play(player1, playMode); + } + + /// + /// 播放 .wav 格式的声音文件 + /// + /// 声音文件的流对象 + /// 播放声音的枚举模式。默认为AudioPlayMode.Background。 + public static void Play(Stream stream, AudioPlayMode playMode) + { + ValidateAudioPlayModeEnum(playMode, "playMode"); + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + Play(new SoundPlayer(stream), playMode); + } + + /// + /// 播放 .wav 格式的声音文件 + /// + /// 声音文件的字节数组 + /// 播放声音的枚举模式。默认为AudioPlayMode.Background。 + public static void Play(byte[] data, AudioPlayMode playMode) + { + if (data == null) + { + throw new ArgumentNullException("data"); + } + + ValidateAudioPlayModeEnum(playMode, "playMode"); + MemoryStream stream1 = new MemoryStream(data); + Play(stream1, playMode); + stream1.Close(); + } + + /// + /// 播放系统声音 + /// + public static void PlaySystemSound(SystemSound systemSound) + { + if (systemSound == null) + { + throw new ArgumentNullException("systemSound"); + } + + systemSound.Play(); + } + + /// + /// 停止正在后台播放的声音 + /// + public static void Stop() + { + SoundPlayer player1 = new SoundPlayer(); + InternalStop(player1); + } + + #region 辅助方法 + + private static SoundPlayer _SoundPlayer; + + private static void InternalStop(SoundPlayer sound) + { + new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); + try + { + sound.Stop(); + } + finally + { + CodeAccessPermission.RevertAssert(); + } + } + + /// + /// 播放声音函数 + /// + /// 声音文件 + /// 播放模式 + private static void Play(SoundPlayer sound, AudioPlayMode mode) + { + if (_SoundPlayer != null) + { + InternalStop(_SoundPlayer); + } + + _SoundPlayer = sound; + switch (mode) + { + case AudioPlayMode.WaitToComplete: + _SoundPlayer.PlaySync(); + return; + + case AudioPlayMode.Background: + _SoundPlayer.Play(); + return; + + case AudioPlayMode.BackgroundLoop: + _SoundPlayer.PlayLooping(); + return; + } + } + + private static void ValidateAudioPlayModeEnum(AudioPlayMode value, string paramName) + { + if (value < AudioPlayMode.WaitToComplete || value > AudioPlayMode.BackgroundLoop) + { + throw new InvalidEnumArgumentException(paramName, (int)value, typeof(AudioPlayMode)); + } + } + + private static string ValidateFilename(string location) + { + if (string.IsNullOrEmpty(location)) + { + throw new ArgumentNullException("location"); + } + + return location; + } + + #endregion 辅助方法 + } + + /// + /// 声音播放的方式 + /// + public enum AudioPlayMode + { + /// + /// 播放声音,并等待,直到它完成 + /// + WaitToComplete, + + /// + /// 在后台播放声音。调用代码继续执行。 + /// + Background, + + /// + /// 在后台播放声音,直到调用stop方法。调用代码继续执行。 + /// + BackgroundLoop + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/Camera.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/Camera.cs new file mode 100644 index 0000000..676b490 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/Camera.cs @@ -0,0 +1,327 @@ +using System; +using System.Runtime.InteropServices; + +namespace Znyc.Admin.Commons.Device +{ + /// + /// 摄像头操作辅助类,包括开启、关闭、抓图、设置等功能 + /// + public class Camera + { + private IntPtr lwndC; + private readonly IntPtr mControlPtr; + private readonly int mWidth; + private readonly int mHeight; + + /// + /// 构造函数 + /// + /// + /// + /// + public Camera(IntPtr handle, int width, int height) + { + mControlPtr = handle; + mWidth = width; + mHeight = height; + } + + /// + /// 帧回调的委托 + /// + /// 数据 + public delegate void RecievedFrameEventHandler(byte[] data); + + /// + /// 帧回调事件处理 + /// + public event RecievedFrameEventHandler RecievedFrame; + + private AviCapture.FrameEventHandler mFrameEventHandler; + + /// + /// 关闭摄像头 + /// + public void CloseWebcam() + { + capDriverDisconnect(lwndC); + } + + /// + /// 开启摄像头 + /// + public void StartWebCam() + { + byte[] lpszName = new byte[100]; + byte[] lpszVer = new byte[100]; + + AviCapture.capGetDriverDescriptionA(1, lpszName, 100, lpszVer, 100); + lwndC = AviCapture.capCreateCaptureWindowA(lpszName, AviCapture.WS_VISIBLE + AviCapture.WS_CHILD, 0, 0, + mWidth, mHeight, mControlPtr, 0); + + if (capDriverConnect(lwndC, 0)) + { + capPreviewRate(lwndC, 66); + + capPreview(lwndC, true); + capOverlay(lwndC, true); + AviCapture.BITMAPINFO bitmapinfo = new AviCapture.BITMAPINFO(); + bitmapinfo.bmiHeader.biSize = AviCapture.SizeOf(bitmapinfo.bmiHeader); + bitmapinfo.bmiHeader.biWidth = mWidth; + bitmapinfo.bmiHeader.biHeight = mHeight; + bitmapinfo.bmiHeader.biPlanes = 1; + bitmapinfo.bmiHeader.biBitCount = 24; + capSetVideoFormat(lwndC, ref bitmapinfo, AviCapture.SizeOf(bitmapinfo)); + + mFrameEventHandler = new AviCapture.FrameEventHandler(FrameCallBack); + capSetCallbackOnFrame(lwndC, mFrameEventHandler); + AviCapture.SetWindowPos(lwndC, 0, 0, 0, mWidth, mHeight, 6); + } + } + + /// + /// 抓图到文件 + /// + /// + public void GrabImage(string path) + { + IntPtr hBmp = Marshal.StringToHGlobalAnsi(path); + AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_SAVEDIB, 0, hBmp.ToInt32()); + } + + /// + /// 抓图到剪切板 + /// + /// + public bool GrabImageToClipBoard() + { + return AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_EDIT_COPY, 0, 0); + } + + /// + /// 弹出色彩设置对话框 + /// + public void SetCaptureSource() + { + AviCapture.CAPDRIVERCAPS caps = new AviCapture.CAPDRIVERCAPS(); + AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_GET_CAPS, AviCapture.SizeOf(caps), ref caps); + if (caps.fHasDlgVideoSource) + { + AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_DLG_VIDEOSOURCE, 0, 0); + } + } + + /// + /// 弹出视频格式设置对话框 + /// + public void SetCaptureFormat() + { + AviCapture.CAPDRIVERCAPS caps = new AviCapture.CAPDRIVERCAPS(); + AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_GET_CAPS, AviCapture.SizeOf(caps), ref caps); + if (caps.fHasDlgVideoSource) + { + AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_DLG_VIDEOFORMAT, 0, 0); + } + } + + #region 以下为私有函数 + + private bool capDriverConnect(IntPtr lwnd, short i) + { + return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_DRIVER_CONNECT, i, 0); + } + + private bool capDriverDisconnect(IntPtr lwnd) + { + return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_DRIVER_DISCONNECT, 0, 0); + } + + private bool capPreview(IntPtr lwnd, bool f) + { + return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_PREVIEW, f, 0); + } + + private bool capPreviewRate(IntPtr lwnd, short wMS) + { + return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_PREVIEWRATE, wMS, 0); + } + + private bool capSetCallbackOnFrame(IntPtr lwnd, AviCapture.FrameEventHandler lpProc) + { + return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc); + } + + private bool capSetVideoFormat(IntPtr hCapWnd, ref AviCapture.BITMAPINFO BmpFormat, int CapFormatSize) + { + return AviCapture.SendMessage(hCapWnd, AviCapture.WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat); + } + + private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr) + { + AviCapture.VIDEOHDR videoHeader = new AviCapture.VIDEOHDR(); + byte[] VideoData; + videoHeader = (AviCapture.VIDEOHDR)AviCapture.GetStructure(lpVHdr, videoHeader); + VideoData = new byte[videoHeader.dwBytesUsed]; + AviCapture.Copy(videoHeader.lpData, VideoData); + if (RecievedFrame != null) + { + RecievedFrame(VideoData); + } + } + + private bool capOverlay(IntPtr lwnd, bool f) + { + return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_OVERLAY, f, 0); + } + + #endregion 以下为私有函数 + } + + /// + /// 视频辅助类 + /// + internal class AviCapture + { + //通过调用acicap32.dll进行读取摄像头数据 + [DllImport("avicap32.dll")] + public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, + int nWidth, int nHeight, IntPtr hWndParent, int nID); + + [DllImport("avicap32.dll")] + public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, + int cbVer); + + [DllImport("User32.dll")] + public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam); + + [DllImport("User32.dll")] + public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam); + + [DllImport("User32.dll")] + public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam); + + [DllImport("User32.dll")] + public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam); + + [DllImport("User32.dll")] + public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPDRIVERCAPS lParam); + + [DllImport("User32.dll")] + public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, + int wFlags); + + [DllImport("avicap32.dll")] + public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize); + + //部分常量 + public const int WM_USER = 0x400; + + public const int WS_CHILD = 0x40000000; + public const int WS_VISIBLE = 0x10000000; + public const int SWP_NOMOVE = 0x2; + public const int SWP_NOZORDER = 0x4; + public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10; + public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11; + public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5; + public const int WM_CAP_SET_PREVIEW = WM_USER + 50; + public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52; + public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45; + public const int WM_CAP_SAVEDIB = WM_USER + 25; + public const int WM_CAP_SET_OVERLAY = WM_USER + 51; + public const int WM_CAP_GET_CAPS = WM_USER + 14; + public const int WM_CAP_DLG_VIDEOFORMAT = WM_USER + 41; + public const int WM_CAP_DLG_VIDEOSOURCE = WM_USER + 42; + public const int WM_CAP_DLG_VIDEODISPLAY = WM_USER + 43; + public const int WM_CAP_EDIT_COPY = WM_USER + 30; + public const int WM_CAP_SET_SEQUENCE_SETUP = WM_USER + 64; + public const int WM_CAP_GET_SEQUENCE_SETUP = WM_USER + 65; + + // 结构 + [StructLayout(LayoutKind.Sequential)] + //VideoHdr + public struct VIDEOHDR + { + [MarshalAs(UnmanagedType.I4)] public int lpData; + [MarshalAs(UnmanagedType.I4)] public int dwBufferLength; + [MarshalAs(UnmanagedType.I4)] public int dwBytesUsed; + [MarshalAs(UnmanagedType.I4)] public int dwTimeCaptured; + [MarshalAs(UnmanagedType.I4)] public int dwUser; + [MarshalAs(UnmanagedType.I4)] public int dwFlags; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public int[] dwReserved; + } + + [StructLayout(LayoutKind.Sequential)] + //BitmapInfoHeader + public struct BITMAPINFOHEADER + { + [MarshalAs(UnmanagedType.I4)] public int biSize; + [MarshalAs(UnmanagedType.I4)] public int biWidth; + [MarshalAs(UnmanagedType.I4)] public int biHeight; + [MarshalAs(UnmanagedType.I2)] public short biPlanes; + [MarshalAs(UnmanagedType.I2)] public short biBitCount; + [MarshalAs(UnmanagedType.I4)] public int biCompression; + [MarshalAs(UnmanagedType.I4)] public int biSizeImage; + [MarshalAs(UnmanagedType.I4)] public int biXPelsPerMeter; + [MarshalAs(UnmanagedType.I4)] public int biYPelsPerMeter; + [MarshalAs(UnmanagedType.I4)] public int biClrUsed; + [MarshalAs(UnmanagedType.I4)] public int biClrImportant; + } + + [StructLayout(LayoutKind.Sequential)] + //BitmapInfo + public struct BITMAPINFO + { + [MarshalAs(UnmanagedType.Struct, SizeConst = 40)] + public BITMAPINFOHEADER bmiHeader; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] + public int[] bmiColors; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CAPDRIVERCAPS + { + [MarshalAs(UnmanagedType.U2)] public ushort wDeviceIndex; + [MarshalAs(UnmanagedType.Bool)] public bool fHasOverlay; + [MarshalAs(UnmanagedType.Bool)] public bool fHasDlgVideoSource; + [MarshalAs(UnmanagedType.Bool)] public bool fHasDlgVideoFormat; + [MarshalAs(UnmanagedType.Bool)] public bool fHasDlgVideoDisplay; + [MarshalAs(UnmanagedType.Bool)] public bool fCaptureInitialized; + [MarshalAs(UnmanagedType.Bool)] public bool fDriverSuppliesPalettes; + [MarshalAs(UnmanagedType.I4)] public int hVideoIn; + [MarshalAs(UnmanagedType.I4)] public int hVideoOut; + [MarshalAs(UnmanagedType.I4)] public int hVideoExtIn; + [MarshalAs(UnmanagedType.I4)] public int hVideoExtOut; + } + + public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr); + + // 公共函数 + public static object GetStructure(IntPtr ptr, ValueType structure) + { + return Marshal.PtrToStructure(ptr, structure.GetType()); + } + + public static object GetStructure(int ptr, ValueType structure) + { + return GetStructure(new IntPtr(ptr), structure); + } + + public static void Copy(IntPtr ptr, byte[] data) + { + Marshal.Copy(ptr, data, 0, data.Length); + } + + public static void Copy(int ptr, byte[] data) + { + Copy(new IntPtr(ptr), data); + } + + public static int SizeOf(object structure) + { + return Marshal.SizeOf(structure); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/HardwareInfoHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/HardwareInfoHelper.cs new file mode 100644 index 0000000..0f14646 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/HardwareInfoHelper.cs @@ -0,0 +1,964 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Management; +using System.Runtime.InteropServices; +using System.Text; + +namespace Znyc.Admin.Commons.Device +{ + /// + /// ȡϵͳϢCPU̡ڴϢ + /// + public sealed class HardwareInfoHelper + { + #region ӲϢȡ + + [DllImport("kernel32.dll")] + private static extern int GetVolumeInformation( + string lpRootPathName, + string lpVolumeNameBuffer, + int nVolumeNameSize, + ref int lpVolumeSerialNumber, + int lpMaximumComponentLength, + int lpFileSystemFlags, + string lpFileSystemNameBuffer, + int nFileSystemNameSize + ); + + /// + /// ̷ΪdrvIDӲкţȱʡΪC + /// + /// ̷"C" + /// + public static string HDVal(string drvID) + { + const int MAX_FILENAME_LEN = 256; + int retVal = 0; + int a = 0; + int b = 0; + string str1 = null; + string str2 = null; + + int i = GetVolumeInformation( + drvID + @":\", + str1, + MAX_FILENAME_LEN, + ref retVal, + a, + b, + str2, + MAX_FILENAME_LEN + ); + + return retVal.ToString(); + } + + /// + /// ȡĬC̵Ĵк + /// + /// + public static string HDVal() + { + return HDVal("C"); + } + + /// + /// ȡӲID + /// + /// + public static string GetDiskID() + { + string HDid = ""; + ManagementClass mc = new ManagementClass("Win32_DiskDrive"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + HDid = mo.Properties["signature"].Value.ToString(); + } + + return HDid; + } + + /// + /// ȡӲModelϢ + /// + public static string GetDiskModel() + { + string HDid = string.Empty; + using (ManagementClass mc = new ManagementClass("Win32_DiskDrive")) + { + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + HDid = (string)mo.Properties["Model"].Value; + } + } + + return HDid; + } + + #endregion ӲϢȡ + + #region CPUϢȡ + + #region CpuUsage + + /// + /// һʵCPUʹʼ + /// + public abstract class CpuUsage + { + /// + /// Creates and returns a CpuUsage instance that can be used to query the CPU time on this operating system. + /// + /// An instance of the CpuUsage class. + /// This platform is not supported -or- initialization of the CPUUsage object failed. + public static CpuUsage Create() + { + if (m_CpuUsage == null) + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + m_CpuUsage = new CpuUsageNt(); + } + else if (Environment.OSVersion.Platform == PlatformID.Win32Windows) + { + m_CpuUsage = new CpuUsage9x(); + } + else + { + throw new NotSupportedException(); + } + } + + return m_CpuUsage; + } + + /// + /// Determines the current average CPU load. + /// + /// An integer that holds the CPU load percentage. + /// One of the system calls fails. The CPU time can not be obtained. + public abstract int Query(); + + /// + /// Holds an instance of the CPUUsage class. + /// + private static CpuUsage m_CpuUsage = null; + } + + //------------------------------------------- win 9x --------------------------------------- + /// + /// Inherits the CPUUsage class and implements the Query method for Windows 9x systems. + /// + /// + ///

This class works on Windows 98 and Windows Millenium Edition.

+ ///

You should not use this class directly in your code. Use the CPUUsage.Create() method to instantiate a CPUUsage object.

+ ///
+ internal sealed class CpuUsage9x : CpuUsage + { + /// + /// Initializes a new CPUUsage9x instance. + /// + /// One of the system calls fails. + public CpuUsage9x() + { + try + { + // start the counter by reading the value of the 'StartStat' key + RegistryKey startKey = Registry.PerformanceData.OpenSubKey(@"PerfStats\StartStat", false); + if (startKey == null) + { + throw new NotSupportedException(); + } + + startKey.GetValue(@"KERNEL\CPUUsage"); + startKey.Close(); + // open the counter's value key + m_StatData = Registry.PerformanceData.OpenSubKey(@"PerfStats\StatData", false); + if (m_StatData == null) + { + throw new NotSupportedException(); + } + } + catch (NotSupportedException e) + { + throw e; + } + catch (Exception e) + { + throw new NotSupportedException("Error while querying the system information.", e); + } + } + + /// + /// Determines the current average CPU load. + /// + /// An integer that holds the CPU load percentage. + /// One of the system calls fails. The CPU time can not be obtained. + public override int Query() + { + try + { + return (int)m_StatData.GetValue(@"KERNEL\CPUUsage"); + } + catch (Exception e) + { + throw new NotSupportedException("Error while querying the system information.", e); + } + } + + /// + /// Closes the allocated resources. + /// + ~CpuUsage9x() + { + try + { + m_StatData.Close(); + } + catch + { + } + + // stopping the counter + try + { + RegistryKey stopKey = Registry.PerformanceData.OpenSubKey(@"PerfStats\StopStat", false); + stopKey.GetValue(@"KERNEL\CPUUsage", false); + stopKey.Close(); + } + catch + { + } + } + + /// Holds the registry key that's used to read the CPU load. + private readonly RegistryKey m_StatData; + } + + //------------------------------------------- win nt --------------------------------------- + /// + /// Inherits the CPUUsage class and implements the Query method for Windows NT systems. + /// + /// + ///

This class works on Windows NT4, Windows 2000, Windows XP, Windows .NET Server and higher.

+ ///

You should not use this class directly in your code. Use the CPUUsage.Create() method to instantiate a CPUUsage object.

+ ///
+ internal sealed class CpuUsageNt : CpuUsage + { + /// + /// Initializes a new CpuUsageNt instance. + /// + /// One of the system calls fails. + public CpuUsageNt() + { + byte[] timeInfo = new byte[32]; // SYSTEM_TIME_INFORMATION structure + byte[] perfInfo = new byte[312]; // SYSTEM_PERFORMANCE_INFORMATION structure + byte[] baseInfo = new byte[44]; // SYSTEM_BASIC_INFORMATION structure + int ret; + // get new system time + ret = NtQuerySystemInformation(SYSTEM_TIMEINFORMATION, timeInfo, timeInfo.Length, IntPtr.Zero); + if (ret != NO_ERROR) + { + throw new NotSupportedException(); + } + // get new CPU's idle time + ret = NtQuerySystemInformation(SYSTEM_PERFORMANCEINFORMATION, perfInfo, perfInfo.Length, IntPtr.Zero); + if (ret != NO_ERROR) + { + throw new NotSupportedException(); + } + // get number of processors in the system + ret = NtQuerySystemInformation(SYSTEM_BASICINFORMATION, baseInfo, baseInfo.Length, IntPtr.Zero); + if (ret != NO_ERROR) + { + throw new NotSupportedException(); + } + // store new CPU's idle and system time and number of processors + oldIdleTime = BitConverter.ToInt64(perfInfo, 0); // SYSTEM_PERFORMANCE_INFORMATION.liIdleTime + oldSystemTime = BitConverter.ToInt64(timeInfo, 8); // SYSTEM_TIME_INFORMATION.liKeSystemTime + processorCount = baseInfo[40]; + } + + /// + /// Determines the current average CPU load. + /// + /// An integer that holds the CPU load percentage. + /// One of the system calls fails. The CPU time can not be obtained. + public override int Query() + { + byte[] timeInfo = new byte[32]; // SYSTEM_TIME_INFORMATION structure + byte[] perfInfo = new byte[312]; // SYSTEM_PERFORMANCE_INFORMATION structure + double dbIdleTime, dbSystemTime; + int ret; + // get new system time + ret = NtQuerySystemInformation(SYSTEM_TIMEINFORMATION, timeInfo, timeInfo.Length, IntPtr.Zero); + if (ret != NO_ERROR) + { + throw new NotSupportedException(); + } + // get new CPU's idle time + ret = NtQuerySystemInformation(SYSTEM_PERFORMANCEINFORMATION, perfInfo, perfInfo.Length, IntPtr.Zero); + if (ret != NO_ERROR) + { + throw new NotSupportedException(); + } + // CurrentValue = NewValue - OldValue + dbIdleTime = BitConverter.ToInt64(perfInfo, 0) - oldIdleTime; + dbSystemTime = BitConverter.ToInt64(timeInfo, 8) - oldSystemTime; + // CurrentCpuIdle = IdleTime / SystemTime + if (dbSystemTime != 0) + { + dbIdleTime = dbIdleTime / dbSystemTime; + } + // CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors + dbIdleTime = 100.0 - dbIdleTime * 100.0 / processorCount + 0.5; + // store new CPU's idle and system time + oldIdleTime = BitConverter.ToInt64(perfInfo, 0); // SYSTEM_PERFORMANCE_INFORMATION.liIdleTime + oldSystemTime = BitConverter.ToInt64(timeInfo, 8); // SYSTEM_TIME_INFORMATION.liKeSystemTime + return (int)dbIdleTime; + } + + /// + /// NtQuerySystemInformation is an internal Windows function that retrieves various kinds of system information. + /// + /// One of the values enumerated in SYSTEM_INFORMATION_CLASS, indicating the kind of system information to be retrieved. + /// Points to a buffer where the requested information is to be returned. The size and structure of this information varies depending on the value of the SystemInformationClass parameter. + /// Length of the buffer pointed to by the SystemInformation parameter. + /// Optional pointer to a location where the function writes the actual size of the information requested. + /// Returns a success NTSTATUS if successful, and an NTSTATUS error code otherwise. + [DllImport("ntdll", EntryPoint = "NtQuerySystemInformation")] + private static extern int NtQuerySystemInformation(int dwInfoType, byte[] lpStructure, int dwSize, + IntPtr returnLength); + + /// Returns the number of processors in the system in a SYSTEM_BASIC_INFORMATION structure. + private const int SYSTEM_BASICINFORMATION = 0; + + /// Returns an opaque SYSTEM_PERFORMANCE_INFORMATION structure. + private const int SYSTEM_PERFORMANCEINFORMATION = 2; + + /// Returns an opaque SYSTEM_TIMEOFDAY_INFORMATION structure. + private const int SYSTEM_TIMEINFORMATION = 3; + + /// The value returned by NtQuerySystemInformation is no error occurred. + private const int NO_ERROR = 0; + + /// Holds the old idle time. + private long oldIdleTime; + + /// Holds the old system time. + private long oldSystemTime; + + /// Holds the number of processors in the system. + private readonly double processorCount; + } + + #endregion CpuUsage + + /// + /// Cpuʹ + /// + public static int GetCpuUsage() + { + return CpuUsage.Create().Query(); + } + + /// + /// ȡCPUID + /// + /// + public static string GetCPUId() + { + string strCpuID = ""; + try + { + ManagementClass mc = new ManagementClass("Win32_Processor"); + ManagementObjectCollection moc = mc.GetInstances(); + + foreach (ManagementObject mo in moc) + { + strCpuID = mo.Properties["ProcessorId"].Value.ToString(); + break; + } + } + catch + { + strCpuID = "078BFBFF00020FC1"; //Ĭϸһ + } + + return strCpuID; + } + + /// + /// ȡCPU + /// + /// + public static string GetCPUName() + { + RegistryKey rk = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0"); + + object obj = rk.GetValue("ProcessorNameString"); + string CPUName = (string)obj; + return CPUName.TrimStart(); + } + + #endregion CPUϢȡ + + #region USB̷б + + /// + /// USB̷б + /// + public static List GetUSBDriveLetters() + { + List list = new List(); + ManagementObjectSearcher ddMgmtObjSearcher = + new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'"); + + foreach (ManagementObject ddObj in ddMgmtObjSearcher.Get()) + { + foreach (ManagementObject dpObj in ddObj.GetRelated("Win32_DiskPartition")) + { + foreach (ManagementObject ldObj in dpObj.GetRelated("Win32_LogicalDisk")) + { + list.Add(ldObj["DeviceID"].ToString()); + } + } + } + + return list; + } + + #endregion USB̷б + + #region ȡӲϢʵ + + #region ṹ + + /// + /// ӲϢ + /// + [Serializable] + public struct HardDiskInfo + { + /// + /// ͺ + /// + public string ModuleNumber; + + /// + /// ̼汾 + /// + public string Firmware; + + /// + /// к + /// + public string SerialNumber; + + /// + /// MΪλ + /// + public uint Capacity; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct GetVersionOutParams + { + public byte bVersion; + public byte bRevision; + public byte bReserved; + public byte bIDEDeviceMap; + public uint fCapabilities; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public uint[] dwReserved; // For future use. + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct IdeRegs + { + public byte bFeaturesReg; + public byte bSectorCountReg; + public byte bSectorNumberReg; + public byte bCylLowReg; + public byte bCylHighReg; + public byte bDriveHeadReg; + public byte bCommandReg; + public byte bReserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct SendCmdInParams + { + public uint cBufferSize; + public IdeRegs irDriveRegs; + public byte bDriveNumber; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] bReserved; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public uint[] dwReserved; + + public byte bBuffer; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct DriverStatus + { + public byte bDriverError; + public byte bIDEStatus; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] bReserved; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public uint[] dwReserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct SendCmdOutParams + { + public uint cBufferSize; + public DriverStatus DriverStatus; + public IdSector bBuffer; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 512)] + internal struct IdSector + { + public ushort wGenConfig; + public ushort wNumCyls; + public ushort wReserved; + public ushort wNumHeads; + public ushort wBytesPerTrack; + public ushort wBytesPerSector; + public ushort wSectorsPerTrack; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public ushort[] wVendorUnique; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + public byte[] sSerialNumber; + + public ushort wBufferType; + public ushort wBufferSize; + public ushort wECCSize; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] sFirmwareRev; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] + public byte[] sModelNumber; + + public ushort wMoreVendorUnique; + public ushort wDoubleWordIO; + public ushort wCapabilities; + public ushort wReserved1; + public ushort wPIOTiming; + public ushort wDMATiming; + public ushort wBS; + public ushort wNumCurrentCyls; + public ushort wNumCurrentHeads; + public ushort wNumCurrentSectorsPerTrack; + public uint ulCurrentSectorCapacity; + public ushort wMultSectorStuff; + public uint ulTotalAddressableSectors; + public ushort wSingleWordDMA; + public ushort wMultiWordDMA; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + public byte[] bReserved; + } + + #endregion ṹ + + #region API + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern int CloseHandle(IntPtr hObject); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr CreateFile( + string lpFileName, + uint dwDesiredAccess, + uint dwShareMode, + IntPtr lpSecurityAttributes, + uint dwCreationDisposition, + uint dwFlagsAndAttributes, + IntPtr hTemplateFile); + + [DllImport("kernel32.dll")] + private static extern int DeviceIoControl( + IntPtr hDevice, + uint dwIoControlCode, + IntPtr lpInBuffer, + uint nInBufferSize, + ref GetVersionOutParams lpOutBuffer, + uint nOutBufferSize, + ref uint lpBytesReturned, + [Out] IntPtr lpOverlapped); + + [DllImport("kernel32.dll")] + private static extern int DeviceIoControl( + IntPtr hDevice, + uint dwIoControlCode, + ref SendCmdInParams lpInBuffer, + uint nInBufferSize, + ref SendCmdOutParams lpOutBuffer, + uint nOutBufferSize, + ref uint lpBytesReturned, + [Out] IntPtr lpOverlapped); + + private const uint DFP_GET_VERSION = 0x00074080; + private const uint DFP_SEND_DRIVE_COMMAND = 0x0007c084; + private const uint DFP_RECEIVE_DRIVE_DATA = 0x0007c088; + + private const uint GENERIC_READ = 0x80000000; + private const uint GENERIC_WRITE = 0x40000000; + private const uint FILE_SHARE_READ = 0x00000001; + private const uint FILE_SHARE_WRITE = 0x00000002; + private const uint CREATE_NEW = 1; + private const uint OPEN_EXISTING = 3; + + #endregion API + + /// + /// ȡ9XܹӲϢ + /// + private static HardDiskInfo GetHddInfo9x(byte driveIndex) + { + GetVersionOutParams vers = new GetVersionOutParams(); + SendCmdInParams inParam = new SendCmdInParams(); + SendCmdOutParams outParam = new SendCmdOutParams(); + uint bytesReturned = 0; + + IntPtr hDevice = CreateFile( + @"\\.\Smartvsd", + 0, + 0, + IntPtr.Zero, + CREATE_NEW, + 0, + IntPtr.Zero); + if (hDevice == IntPtr.Zero) + { + throw new Exception("Open smartvsd.vxd failed."); + } + + if (0 == DeviceIoControl( + hDevice, + DFP_GET_VERSION, + IntPtr.Zero, + 0, + ref vers, + (uint)Marshal.SizeOf(vers), + ref bytesReturned, + IntPtr.Zero)) + { + CloseHandle(hDevice); + throw new Exception("DeviceIoControl failed:DFP_GET_VERSION"); + } + + // If IDE identify command not supported, fails + if (0 == (vers.fCapabilities & 1)) + { + CloseHandle(hDevice); + throw new Exception("Error: IDE identify command not supported."); + } + + if (0 != (driveIndex & 1)) + { + inParam.irDriveRegs.bDriveHeadReg = 0xb0; + } + else + { + inParam.irDriveRegs.bDriveHeadReg = 0xa0; + } + + if (0 != (vers.fCapabilities & (16 >> driveIndex))) + { + // We don''t detect a ATAPI device. + CloseHandle(hDevice); + throw new Exception(string.Format("Drive {0} is a ATAPI device, we don''t detect it", driveIndex + 1)); + } + else + { + inParam.irDriveRegs.bCommandReg = 0xec; + } + + inParam.bDriveNumber = driveIndex; + inParam.irDriveRegs.bSectorCountReg = 1; + inParam.irDriveRegs.bSectorNumberReg = 1; + inParam.cBufferSize = 512; + if (0 == DeviceIoControl( + hDevice, + DFP_RECEIVE_DRIVE_DATA, + ref inParam, + (uint)Marshal.SizeOf(inParam), + ref outParam, + (uint)Marshal.SizeOf(outParam), + ref bytesReturned, + IntPtr.Zero)) + { + CloseHandle(hDevice); + throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA"); + } + + CloseHandle(hDevice); + + return GetHardDiskInfo(outParam.bBuffer); + } + + /// + /// ȡNTܹӲϢ + /// + private static HardDiskInfo GetHddInfoNT(byte driveIndex) + { + GetVersionOutParams vers = new GetVersionOutParams(); + SendCmdInParams inParam = new SendCmdInParams(); + SendCmdOutParams outParam = new SendCmdOutParams(); + uint bytesReturned = 0; + + // We start in NT/Win2000 + IntPtr hDevice = CreateFile( + string.Format(@"\\.\PhysicalDrive{0}", driveIndex), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + IntPtr.Zero, + OPEN_EXISTING, + 0, + IntPtr.Zero); + if (hDevice == IntPtr.Zero) + { + throw new Exception("CreateFile faild."); + } + + if (0 == DeviceIoControl( + hDevice, + DFP_GET_VERSION, + IntPtr.Zero, + 0, + ref vers, + (uint)Marshal.SizeOf(vers), + ref bytesReturned, + IntPtr.Zero)) + { + CloseHandle(hDevice); + throw new Exception(string.Format("Drive {0} may not exists.", driveIndex + 1)); + } + + // If IDE identify command not supported, fails + if (0 == (vers.fCapabilities & 1)) + { + CloseHandle(hDevice); + throw new Exception("Error: IDE identify command not supported."); + } + + // Identify the IDE drives + if (0 != (driveIndex & 1)) + { + inParam.irDriveRegs.bDriveHeadReg = 0xb0; + } + else + { + inParam.irDriveRegs.bDriveHeadReg = 0xa0; + } + + if (0 != (vers.fCapabilities & (16 >> driveIndex))) + { + CloseHandle(hDevice); + throw new Exception(string.Format("Drive {0} is a ATAPI device, we don''t detect it.", driveIndex + 1)); + } + else + { + inParam.irDriveRegs.bCommandReg = 0xec; + } + + inParam.bDriveNumber = driveIndex; + inParam.irDriveRegs.bSectorCountReg = 1; + inParam.irDriveRegs.bSectorNumberReg = 1; + inParam.cBufferSize = 512; + + if (0 == DeviceIoControl( + hDevice, + DFP_RECEIVE_DRIVE_DATA, + ref inParam, + (uint)Marshal.SizeOf(inParam), + ref outParam, + (uint)Marshal.SizeOf(outParam), + ref bytesReturned, + IntPtr.Zero)) + { + CloseHandle(hDevice); + throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA"); + } + + CloseHandle(hDevice); + + return GetHardDiskInfo(outParam.bBuffer); + } + + /// + /// ȡӲϢϸ + /// + /// + /// + private static HardDiskInfo GetHardDiskInfo(IdSector phdinfo) + { + HardDiskInfo hddInfo = new HardDiskInfo(); + ChangeByteOrder(phdinfo.sModelNumber); + hddInfo.ModuleNumber = Encoding.ASCII.GetString(phdinfo.sModelNumber).Trim(); + + ChangeByteOrder(phdinfo.sFirmwareRev); + hddInfo.Firmware = Encoding.ASCII.GetString(phdinfo.sFirmwareRev).Trim(); + + ChangeByteOrder(phdinfo.sSerialNumber); + hddInfo.SerialNumber = Encoding.ASCII.GetString(phdinfo.sSerialNumber).Trim(); + + hddInfo.Capacity = phdinfo.ulTotalAddressableSectors / 2 / 1024; + + return hddInfo; + } + + /// + /// byteбϢתַ + /// + /// + private static void ChangeByteOrder(byte[] charArray) + { + byte temp; + for (int i = 0; i < charArray.Length; i += 2) + { + temp = charArray[i]; + charArray[i] = charArray[i + 1]; + charArray[i + 1] = temp; + } + } + + /// + /// ӲϢ + /// + public static HardDiskInfo GetHDInfo(byte driveIndex) + { + switch (Environment.OSVersion.Platform) + { + case PlatformID.Win32Windows: + return GetHddInfo9x(driveIndex); + + case PlatformID.Win32NT: + return GetHddInfoNT(driveIndex); + + case PlatformID.Win32S: + throw new NotSupportedException("Win32s is not supported."); + case PlatformID.WinCE: + throw new NotSupportedException("WinCE is not supported."); + default: + throw new NotSupportedException("Unknown Platform."); + } + } + + #endregion ȡӲϢʵ + + #region + + /// + /// ȡMACַ + /// + /// + public static string GetMacAddress() + { + string mac = ""; + ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + if ((bool)mo["IPEnabled"] == true) + { + mac = mo["MacAddress"].ToString(); + break; + } + } + + return mac; + } + + /// + /// ȡIPַ + /// + public static string GetIPAddress() + { + string st = ""; + ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + if ((bool)mo["IPEnabled"] == true) + { + //st=mo["IpAddress"].ToString(); + Array ar; + ar = (Array)mo.Properties["IpAddress"].Value; + st = ar.GetValue(0).ToString(); + break; + } + } + + moc = null; + mc = null; + return st; + } + + /// + /// ȡϵͳĵ¼û + /// + public static string GetUserName() + { + return Environment.UserName; + } + + /// + /// ȡ + /// + public static string GetComputerName() + { + return Environment.MachineName; + } + + /// + /// ȡPC + /// + public static string GetSystemType() + { + string st = ""; + ManagementClass mc = new ManagementClass("Win32_ComputerSystem"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + st = mo["SystemType"].ToString(); + } + + return st; + } + + /// + /// ȡڴ + /// + public static string GetTotalPhysicalMemory() + { + string st = ""; + ManagementClass mc = new ManagementClass("Win32_ComputerSystem"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + st = mo["TotalPhysicalMemory"].ToString(); + } + + return st; + } + + #endregion + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/SoundPlayerHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/SoundPlayerHelper.cs new file mode 100644 index 0000000..dd20526 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Device/SoundPlayerHelper.cs @@ -0,0 +1,143 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace Znyc.Admin.Commons.Device +{ + /// + ///声音文件播放操作辅助类。除了MP3声音文件外,还可以播放WAV格式、midi格式声音文件。 + /// + public class SoundPlayerHelper + { + [DllImport("winmm.dll")] + private static extern long mciSendString(string strCommand, StringBuilder strReturn, int iReturnLength, + IntPtr hwndCallback); + + [DllImport("winmm.dll")] + private static extern int waveOutGetVolume(IntPtr hwo, out uint dwVolume); + + [DllImport("winmm.dll")] + private static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume); + + /// + /// 播放声音文件 + /// + /// 声音文件路径(可以是MP3、WAV、Midi等声音文件) + /// 是否重复播放 + public static void Play(string soundFileName, bool Repeat) + { + mciSendString("open \"" + soundFileName + "\" type mpegvideo alias MediaFile", null, 0, IntPtr.Zero); + mciSendString("play MediaFile" + (Repeat ? " repeat" : string.Empty), null, 0, IntPtr.Zero); + } + + /// + /// 播放声音嵌入资源字节数组 + /// + /// 声音文件嵌入资源字节数组(可以是MP3、WAV、Midi等声音格式) + /// 是否重复播放 + public static void Play(byte[] soundEmbeddedResource, bool Repeat) + { + extractResource(soundEmbeddedResource, Path.GetTempPath() + "resource.tmp"); + mciSendString("open \"" + Path.GetTempPath() + "resource.tmp" + "\" type mpegvideo alias MediaFile", null, + 0, IntPtr.Zero); + mciSendString("play MediaFile" + (Repeat ? " repeat" : string.Empty), null, 0, IntPtr.Zero); + } + + /// + /// 暂停播放 + /// + public static void Pause() + { + mciSendString("stop MediaFile", null, 0, IntPtr.Zero); + } + + /// + /// 停止播放 + /// + public static void Stop() + { + mciSendString("close MediaFile", null, 0, IntPtr.Zero); + } + + /// + /// 释放资源 + /// + public static void Dispose() + { + mciSendString("close all", null, 0, IntPtr.Zero); + mciSendString("clear all", null, 0, IntPtr.Zero); + } + + /// + /// 获取或设置音量的百分比 + /// + /// + public static float VolumePercent + { + get + { + float currentVolume = (float)Math.Round(GetVolume() * 100, 0); + return currentVolume; + } + set => SetVolume((float)Math.Round(value, 0) / 100); + } + + /// + /// 获取音量 + /// + /// + public static float GetVolume() + { + waveOutGetVolume(IntPtr.Zero, out uint curVol); + ushort calcVol = (ushort)(curVol & 0xffff); + float currentVolume = (float)calcVol / ushort.MaxValue; + return currentVolume; + } + + /// + /// 设置音量 + /// + /// + public static void SetVolume(float volume) + { + volume = ushort.MaxValue * volume; + uint volumeBothChannels = ((uint)volume & 0xffff) | ((uint)volume << 16); + waveOutSetVolume(IntPtr.Zero, volumeBothChannels); + } + + /// + /// 返回当前状态播放:播放,暂停,停止等 + /// + public static string Status + { + get + { + int i = 128; + StringBuilder stringBuilder = new StringBuilder(i); + mciSendString("status MediaFile mode", stringBuilder, i, IntPtr.Zero); + return stringBuilder.ToString(); + } + } + + private static void extractResource(byte[] res, string filePath) + { + FileStream fs; + BinaryWriter bw; + + if (!File.Exists(filePath)) + { + fs = new FileStream(filePath, FileMode.OpenOrCreate); + bw = new BinaryWriter(fs); + + foreach (byte b in res) + { + bw.Write(b); + } + + bw.Close(); + fs.Close(); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/Base64Util.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/Base64Util.cs new file mode 100644 index 0000000..9ed5641 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/Base64Util.cs @@ -0,0 +1,330 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Znyc.Admin.Commons +{ + /// + /// 基于Base64的加密编码辅助类, + /// 可以设置不同的密码表来获取不同的编码与解码 + /// + public class Base64Util + { + /// + /// 构造函数,初始化编码表 + /// + public Base64Util() + { + InitDict(); + } + + /// + /// + /// + protected static Base64Util s_b64 = new Base64Util(); + + /// + /// 使用默认的密码表加密字符串 + /// + /// 待加密字符串 + /// + public static string Encrypt(string input) + { + return s_b64.Encode(input); + } + + /// + /// 使用默认的密码表解密字符串 + /// + /// 待解密字符串 + /// + public static string Decrypt(string input) + { + return s_b64.Decode(input); + } + + /// + /// 获取具有标准的Base64密码表的加密类 + /// + /// + public static Base64Util GetStandardBase64() + { + Base64Util b64 = new Base64Util + { + Pad = "=", + CodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + }; + return b64; + } + + /// + /// 密码表 + /// + protected string m_codeTable = @"ABCDEFGHIJKLMNOPQRSTUVWXYZbacdefghijklmnopqrstu_wxyz0123456789*-"; + + /// + /// 补码 + /// + protected string m_pad = "v"; + + /// + /// + /// + protected Dictionary m_t1 = new Dictionary(); + + /// + /// + /// + protected Dictionary m_t2 = new Dictionary(); + + /// + /// 密码表 + /// + public string CodeTable + { + get => m_codeTable; + set + { + if (value == null) + { + throw new Exception("密码表不能为null"); + } + else if (value.Length < 64) + { + throw new Exception("密码表长度必须至少为64"); + } + else + { + ValidateRepeat(value); + ValidateEqualPad(value, m_pad); + m_codeTable = value; + InitDict(); + } + } + } + + /// + /// 补码 + /// + public string Pad + { + get => m_pad; + set + { + if (value == null) + { + throw new Exception("密码表的补码不能为null"); + } + else if (value.Length != 1) + { + throw new Exception("密码表的补码长度必须为1"); + } + else + { + ValidateEqualPad(m_codeTable, value); + m_pad = value; + InitDict(); + } + } + } + + /// + /// 返回编码后的字符串 + /// + /// 原字符串 + /// + public string Encode(string source) + { + if (source == null || source == "") + { + return ""; + } + else + { + StringBuilder sb = new StringBuilder(); + byte[] tmp = Encoding.UTF8.GetBytes(source); + int remain = tmp.Length % 3; + int patch = 3 - remain; + if (remain != 0) + { + Array.Resize(ref tmp, tmp.Length + patch); + } + + int cnt = (int)Math.Ceiling(tmp.Length * 1.0 / 3); + for (int i = 0; i < cnt; i++) + { + sb.Append(EncodeUnit(tmp[i * 3], tmp[i * 3 + 1], tmp[i * 3 + 2])); + } + + if (remain != 0) + { + sb.Remove(sb.Length - patch, patch); + for (int i = 0; i < patch; i++) + { + sb.Append(m_pad); + } + } + + return sb.ToString(); + } + } + + /// + /// + /// + /// + /// + protected string EncodeUnit(params byte[] unit) + { + int[] obj = new int[4]; + obj[0] = (unit[0] & 0xfc) >> 2; + obj[1] = ((unit[0] & 0x03) << 4) + ((unit[1] & 0xf0) >> 4); + obj[2] = ((unit[1] & 0x0f) << 2) + ((unit[2] & 0xc0) >> 6); + obj[3] = unit[2] & 0x3f; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < obj.Length; i++) + { + sb.Append(GetEC(obj[i])); + } + + return sb.ToString(); + } + + /// + /// + /// + /// + /// + protected char GetEC(int code) + { + return m_t1[code]; //m_codeTable[code]; + } + + /// + /// 获得解码字符串 + /// + /// 原字符串 + /// + public string Decode(string source) + { + if (source == null || source == "") + { + return ""; + } + else + { + List list = new List(); + char[] tmp = source.ToCharArray(); + int remain = tmp.Length % 4; + if (remain != 0) + { + Array.Resize(ref tmp, tmp.Length - remain); + } + + int patch = source.IndexOf(m_pad); + if (patch != -1) + { + patch = source.Length - patch; + } + + int cnt = tmp.Length / 4; + for (int i = 0; i < cnt; i++) + { + DecodeUnit(list, tmp[i * 4], tmp[i * 4 + 1], tmp[i * 4 + 2], tmp[i * 4 + 3]); + } + + for (int i = 0; i < patch; i++) + { + list.RemoveAt(list.Count - 1); + } + + return Encoding.UTF8.GetString(list.ToArray()); + } + } + + /// + /// 获得解码字符串 + /// + /// + /// + protected void DecodeUnit(List byteArr, params char[] chArray) + { + int[] res = new int[3]; + byte[] unit = new byte[chArray.Length]; + for (int i = 0; i < chArray.Length; i++) + { + unit[i] = FindChar(chArray[i]); + } + + res[0] = (unit[0] << 2) + ((unit[1] & 0x30) >> 4); + res[1] = ((unit[1] & 0xf) << 4) + ((unit[2] & 0x3c) >> 2); + res[2] = ((unit[2] & 0x3) << 6) + unit[3]; + for (int i = 0; i < res.Length; i++) + { + byteArr.Add((byte)res[i]); + } + } + + /// + /// + /// + /// + /// + protected byte FindChar(char ch) + { + int pos = m_t2[ch]; //m_codeTable.IndexOf(ch); + return (byte)pos; + } + + /// + /// 初始化双向哈希字典 + /// + protected void InitDict() + { + m_t1.Clear(); + m_t2.Clear(); + m_t2.Add(m_pad[0], -1); + for (int i = 0; i < m_codeTable.Length; i++) + { + m_t1.Add(i, m_codeTable[i]); + m_t2.Add(m_codeTable[i], i); + } + } + + /// + /// 检查字符串中的字符是否有重复 + /// + /// 待检查字符串 + /// + protected void ValidateRepeat(string input) + { + for (int i = 0; i < input.Length; i++) + { + if (input.LastIndexOf(input[i]) > i) + { + throw new Exception("密码表中含有重复字符:" + input[i]); + } + } + } + + /// + /// 检查字符串是否包含补码字符 + /// + /// 待检查字符串 + /// + protected void ValidateEqualPad(string input, string pad) + { + if (input.IndexOf(pad) > -1) + { + throw new Exception("密码表中包含了补码字符:" + pad); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/Cryptography.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/Cryptography.cs new file mode 100644 index 0000000..96748b6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/Cryptography.cs @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; +using System.Security.Cryptography; +using System.Text; + +namespace Znyc.Admin.Commons +{ + /// + /// 用于webapi 生成票据使用,公开 + /// + public sealed class Cryptography + { + /// + /// + /// + /// + /// + /// + public static string AES_encrypt(string tmpStr, string encodingAESKey) + { + string str = tmpStr + GetMD5_32(encodingAESKey); + return GetMD5_32(SHA256(str)) + GetMD5_32(tmpStr); + } + + /// + /// SHA256函数 + /// + /// 原始字符串 + /// SHA256结果(返回长度为44字节的字符串) + public static string SHA256(string str) + { + byte[] SHA256Data = Encoding.UTF8.GetBytes(str); + SHA256Managed Sha256 = new SHA256Managed(); + byte[] Result = Sha256.ComputeHash(SHA256Data); + return Convert.ToBase64String(Result); //返回长度为44字节的字符串 + } + + /// + /// 获得32位的MD5加密 + /// + public static string GetMD5_32(string input) + { + MD5 md5 = MD5.Create(); + byte[] data = md5.ComputeHash(Encoding.Default.GetBytes(input)); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < data.Length; i++) + { + sb.Append(data[i].ToString("x2")); + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/DEncrypt.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/DEncrypt.cs new file mode 100644 index 0000000..d43cdc7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/DEncrypt.cs @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; +using System.Security.Cryptography; +using System.Text; + +namespace Znyc.Admin.Commons.Encrypt +{ + /// + /// Encrypt 的加密/解密。 + /// + public class DEncrypt + { + /// + /// 构造方法 + /// + public DEncrypt() + { + } + + #region 使用 缺省密钥字符串 加密/解密string + + /// + /// 使用缺省密钥字符串加密string + /// + /// 明文 + /// 密文 + public static string Encrypt(string original) + { + return Encrypt(original, "ZnycSOFT"); + } + + /// + /// 使用缺省密钥字符串解密string + /// + /// 密文 + /// 明文 + public static string Decrypt(string original) + { + return Decrypt(original, "ZnycSOFT", Encoding.Default); + } + + #endregion 使用 缺省密钥字符串 加密/解密string + + #region 使用 给定密钥字符串 加密/解密string + + /// + /// 使用给定密钥字符串加密string + /// + /// 原始文字 + /// 密钥 + /// 密文 + public static string Encrypt(string original, string key) + { + byte[] buff = Encoding.Default.GetBytes(original); + byte[] kb = Encoding.Default.GetBytes(key); + return Convert.ToBase64String(Encrypt(buff, kb)); + } + + /// + /// 使用给定密钥字符串解密string + /// + /// 密文 + /// 密钥 + /// 明文 + public static string Decrypt(string original, string key) + { + return Decrypt(original, key, Encoding.Default); + } + + /// + /// 使用给定密钥字符串解密string,返回指定编码方式明文 + /// + /// 密文 + /// 密钥 + /// 字符编码方案 + /// 明文 + public static string Decrypt(string encrypted, string key, Encoding encoding) + { + byte[] buff = Convert.FromBase64String(encrypted); + byte[] kb = Encoding.Default.GetBytes(key); + return encoding.GetString(Decrypt(buff, kb)); + } + + #endregion 使用 给定密钥字符串 加密/解密string + + #region 使用 缺省密钥字符串 加密/解密/byte[] + + /// + /// 使用缺省密钥字符串解密byte[] + /// + /// 密文 + /// 密钥 + /// 明文 + public static byte[] Decrypt(byte[] encrypted) + { + byte[] key = Encoding.Default.GetBytes("ZnycSOFT"); + return Decrypt(encrypted, key); + } + + /// + /// 使用缺省密钥字符串加密 + /// + /// 原始数据 + /// 密钥 + /// 密文 + public static byte[] Encrypt(byte[] original) + { + byte[] key = Encoding.Default.GetBytes("ZnycSOFT"); + return Encrypt(original, key); + } + + #endregion 使用 缺省密钥字符串 加密/解密/byte[] + + #region 使用 给定密钥 加密/解密/byte[] + + /// + /// 生成MD5摘要 + /// + /// 数据源 + /// 摘要 + public static byte[] MakeMD5(byte[] original) + { + MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); + byte[] keyhash = hashmd5.ComputeHash(original); + hashmd5 = null; + return keyhash; + } + + /// + /// 使用给定密钥加密 + /// + /// 明文 + /// 密钥 + /// 密文 + public static byte[] Encrypt(byte[] original, byte[] key) + { + TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider + { + Key = MakeMD5(key), + Mode = CipherMode.ECB + }; + + return des.CreateEncryptor().TransformFinalBlock(original, 0, original.Length); + } + + /// + /// 使用给定密钥解密数据 + /// + /// 密文 + /// 密钥 + /// 明文 + public static byte[] Decrypt(byte[] encrypted, byte[] key) + { + TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider + { + Key = MakeMD5(key), + Mode = CipherMode.ECB + }; + + return des.CreateDecryptor().TransformFinalBlock(encrypted, 0, encrypted.Length); + } + + #endregion 使用 给定密钥 加密/解密/byte[] + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/EncodeHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/EncodeHelper.cs new file mode 100644 index 0000000..2a3524d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/EncodeHelper.cs @@ -0,0 +1,655 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Znyc.Admin.Commons.Encrypt +{ + /// + /// DES对称加解密、AES RijndaelManaged加解密、Base64加密解密、MD5加密等操作辅助类 + /// + public sealed class EncodeHelper + { + #region DES对称加密解密 + + /// + /// 注意DEFAULT_ENCRYPT_KEY的长度为8位(如果要增加或者减少key长度,调整IV的长度就是了) + /// + public const string DEFAULT_ENCRYPT_KEY = "12345678"; + + /// + /// 使用默认加密 + /// + /// + /// + public static string DesEncrypt(string strText) + { + try + { + return DesEncrypt(strText, DEFAULT_ENCRYPT_KEY); + } + catch + { + return ""; + } + } + + /// + /// 使用默认解密 + /// + /// 解密字符串 + /// + public static string DesDecrypt(string strText) + { + try + { + return DesDecrypt(strText, DEFAULT_ENCRYPT_KEY); + } + catch + { + return ""; + } + } + + /// + /// 加密字符串,注意strEncrKey的长度为8位 + /// + /// 待加密字符串 + /// 加密键 + /// + public static string DesEncrypt(string strText, string strEncrKey) + { + byte[] byKey = null; + byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; + + byKey = Encoding.UTF8.GetBytes(strEncrKey.Substring(0, 8)); + DESCryptoServiceProvider des = new DESCryptoServiceProvider(); + byte[] inputByteArray = Encoding.UTF8.GetBytes(strText); + MemoryStream ms = new MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + return Convert.ToBase64String(ms.ToArray()); + } + + /// + /// 解密字符串,注意strEncrKey的长度为8位 + /// + /// 待解密的字符串 + /// 解密键 + /// 解密后的字符串 + public static string DesDecrypt(string strText, string sDecrKey) + { + byte[] byKey = null; + byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; + byte[] inputByteArray = new byte[strText.Length]; + + byKey = Encoding.UTF8.GetBytes(sDecrKey.Substring(0, 8)); + DESCryptoServiceProvider des = new DESCryptoServiceProvider(); + inputByteArray = Convert.FromBase64String(strText); + MemoryStream ms = new MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(byKey, IV), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + Encoding encoding = new UTF8Encoding(); + return encoding.GetString(ms.ToArray()); + } + + /// + /// 加密数据文件,注意strEncrKey的长度为8位 + /// + /// 待加密的文件路径 + /// 输出文件路径 + /// 加密键 + public static void DesEncrypt(string m_InFilePath, string m_OutFilePath, string strEncrKey) + { + byte[] byKey = null; + byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; + + byKey = Encoding.UTF8.GetBytes(strEncrKey.Substring(0, 8)); + FileStream fin = new FileStream(m_InFilePath, FileMode.Open, FileAccess.Read); + FileStream fout = new FileStream(m_OutFilePath, FileMode.OpenOrCreate, FileAccess.Write); + fout.SetLength(0); + //Create variables to help with read and write. + byte[] bin = new byte[100]; //This is intermediate storage for the encryption. + long rdlen = 0; //This is the total number of bytes written. + long totlen = fin.Length; //This is the total length of the input file. + int len; //This is the number of bytes to be written at a time. + + DES des = new DESCryptoServiceProvider(); + CryptoStream encStream = new CryptoStream(fout, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write); + + //Read from the input file, then encrypt and write to the output file. + while (rdlen < totlen) + { + len = fin.Read(bin, 0, 100); + encStream.Write(bin, 0, len); + rdlen = rdlen + len; + } + + encStream.Close(); + fout.Close(); + fin.Close(); + } + + /// + /// 解密数据文件,注意strEncrKey的长度为8位 + /// + /// 待解密的文件路径 + /// 输出路径 + /// 解密键 + public static void DesDecrypt(string m_InFilePath, string m_OutFilePath, string sDecrKey) + { + byte[] byKey = null; + byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; + + byKey = Encoding.UTF8.GetBytes(sDecrKey.Substring(0, 8)); + FileStream fin = new FileStream(m_InFilePath, FileMode.Open, FileAccess.Read); + FileStream fout = new FileStream(m_OutFilePath, FileMode.OpenOrCreate, FileAccess.Write); + fout.SetLength(0); + //Create variables to help with read and write. + byte[] bin = new byte[100]; //This is intermediate storage for the encryption. + long rdlen = 0; //This is the total number of bytes written. + long totlen = fin.Length; //This is the total length of the input file. + int len; //This is the number of bytes to be written at a time. + + DES des = new DESCryptoServiceProvider(); + CryptoStream encStream = new CryptoStream(fout, des.CreateDecryptor(byKey, IV), CryptoStreamMode.Write); + + //Read from the input file, then encrypt and write to the output file. + while (rdlen < totlen) + { + len = fin.Read(bin, 0, 100); + encStream.Write(bin, 0, len); + rdlen = rdlen + len; + } + + encStream.Close(); + fout.Close(); + fin.Close(); + } + + #endregion DES对称加密解密 + + #region 对称加密算法AES RijndaelManaged加密解密 + + private static readonly string Default_AES_Key = "@#Znycqinwn123"; + + private static readonly byte[] Keys = + { + 0x41, 0x72, 0x65, 0x79, 0x6F, 0x75, 0x6D, 0x79, + 0x53, 0x6E, 0x6F, 0x77, 0x6D, 0x61, 0x6E, 0x3F + }; + + /// + /// 对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法) + /// + /// 待加密字符串 + /// 加密结果字符串 + public static string AES_Encrypt(string encryptString) + { + return AES_Encrypt(encryptString, Default_AES_Key); + } + + /// + /// 对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法) + /// + /// 待加密字符串 + /// 加密密钥,须半角字符 + /// 加密结果字符串 + public static string AES_Encrypt(string encryptString, string encryptKey) + { + encryptKey = GetSubString(encryptKey, 32, ""); + encryptKey = encryptKey.PadRight(32, ' '); + + RijndaelManaged rijndaelProvider = new RijndaelManaged + { + Key = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32)), + IV = Keys + }; + ICryptoTransform rijndaelEncrypt = rijndaelProvider.CreateEncryptor(); + + byte[] inputData = Encoding.UTF8.GetBytes(encryptString); + byte[] encryptedData = rijndaelEncrypt.TransformFinalBlock(inputData, 0, inputData.Length); + + return Convert.ToBase64String(encryptedData); + } + + /// + /// 对称加密算法AES RijndaelManaged解密字符串 + /// + /// 待解密的字符串 + /// 解密成功返回解密后的字符串,失败返源串 + public static string AES_Decrypt(string decryptString) + { + return AES_Decrypt(decryptString, Default_AES_Key); + } + + /// + /// 对称加密算法AES RijndaelManaged解密字符串 + /// + /// 待解密的字符串 + /// 解密密钥,和加密密钥相同 + /// 解密成功返回解密后的字符串,失败返回空 + public static string AES_Decrypt(string decryptString, string decryptKey) + { + try + { + decryptKey = GetSubString(decryptKey, 32, ""); + decryptKey = decryptKey.PadRight(32, ' '); + + RijndaelManaged rijndaelProvider = new RijndaelManaged + { + Key = Encoding.UTF8.GetBytes(decryptKey), + IV = Keys + }; + ICryptoTransform rijndaelDecrypt = rijndaelProvider.CreateDecryptor(); + + byte[] inputData = Convert.FromBase64String(decryptString); + byte[] decryptedData = rijndaelDecrypt.TransformFinalBlock(inputData, 0, inputData.Length); + + return Encoding.UTF8.GetString(decryptedData); + } + catch + { + return string.Empty; + } + } + + /// + /// 按字节长度(按字节,一个汉字为2个字节)取得某字符串的一部分 + /// + /// 源字符串 + /// 所取字符串字节长度 + /// 附加字符串(当字符串不够长时,尾部所添加的字符串,一般为"...") + /// 某字符串的一部分 + private static string GetSubString(string sourceString, int length, string tailString) + { + return GetSubString(sourceString, 0, length, tailString); + } + + /// + /// 按字节长度(按字节,一个汉字为2个字节)取得某字符串的一部分 + /// + /// 源字符串 + /// 索引位置,以0开始 + /// 所取字符串字节长度 + /// 附加字符串(当字符串不够长时,尾部所添加的字符串,一般为"...") + /// 某字符串的一部分 + private static string GetSubString(string sourceString, int startIndex, int length, string tailString) + { + string myResult = sourceString; + + //当是日文或韩文时(注:中文的范围:\u4e00 - \u9fa5, 日文在\u0800 - \u4e00, 韩文为\xAC00-\xD7A3) + if (System.Text.RegularExpressions.Regex.IsMatch(sourceString, "[\u0800-\u4e00]+") || + System.Text.RegularExpressions.Regex.IsMatch(sourceString, "[\xAC00-\xD7A3]+")) + { + //当截取的起始位置超出字段串长度时 + if (startIndex >= sourceString.Length) + { + return string.Empty; + } + else + { + return sourceString.Substring(startIndex, + length + startIndex > sourceString.Length ? sourceString.Length - startIndex : length); + } + } + + //中文字符,如"中国人民abcd123" + if (length <= 0) + { + return string.Empty; + } + + byte[] bytesSource = Encoding.Default.GetBytes(sourceString); + + //当字符串长度大于起始位置 + if (bytesSource.Length > startIndex) + { + int endIndex = bytesSource.Length; + + //当要截取的长度在字符串的有效长度范围内 + if (bytesSource.Length > startIndex + length) + { + endIndex = length + startIndex; + } + else + { + //当不在有效范围内时,只取到字符串的结尾 + length = bytesSource.Length - startIndex; + tailString = ""; + } + + int[] anResultFlag = new int[length]; + int nFlag = 0; + //字节大于127为双字节字符 + for (int i = startIndex; i < endIndex; i++) + { + if (bytesSource[i] > 127) + { + nFlag++; + if (nFlag == 3) + { + nFlag = 1; + } + } + else + { + nFlag = 0; + } + + anResultFlag[i] = nFlag; + } + + //最后一个字节为双字节字符的一半 + if (bytesSource[endIndex - 1] > 127 && anResultFlag[length - 1] == 1) + { + length = length + 1; + } + + byte[] bsResult = new byte[length]; + Array.Copy(bytesSource, startIndex, bsResult, 0, length); + myResult = Encoding.Default.GetString(bsResult); + myResult = myResult + tailString; + + return myResult; + } + + return string.Empty; + } + + /// + /// 加密文件流 + /// + /// 文件流对象 + /// 加密键 + /// + public static CryptoStream AES_EncryptStrream(FileStream fs, string encryptKey) + { + encryptKey = GetSubString(encryptKey, 32, ""); + encryptKey = encryptKey.PadRight(32, ' '); + + RijndaelManaged rijndaelProvider = new RijndaelManaged + { + Key = Encoding.UTF8.GetBytes(encryptKey), + IV = Keys + }; + + ICryptoTransform encrypto = rijndaelProvider.CreateEncryptor(); + CryptoStream cytptostreamEncr = new CryptoStream(fs, encrypto, CryptoStreamMode.Write); + return cytptostreamEncr; + } + + /// + /// 解密文件流 + /// + /// 文件流对象 + /// 解密键 + /// + public static CryptoStream AES_DecryptStream(FileStream fs, string decryptKey) + { + decryptKey = GetSubString(decryptKey, 32, ""); + decryptKey = decryptKey.PadRight(32, ' '); + + RijndaelManaged rijndaelProvider = new RijndaelManaged + { + Key = Encoding.UTF8.GetBytes(decryptKey), + IV = Keys + }; + ICryptoTransform Decrypto = rijndaelProvider.CreateDecryptor(); + CryptoStream cytptostreamDecr = new CryptoStream(fs, Decrypto, CryptoStreamMode.Read); + return cytptostreamDecr; + } + + /// + /// 对指定文件加密 + /// + /// 输入文件 + /// 输出文件 + /// + public static bool AES_EncryptFile(string InputFile, string OutputFile) + { + try + { + string decryptKey = "www.iqidi.com"; + + FileStream fr = new FileStream(InputFile, FileMode.Open); + FileStream fren = new FileStream(OutputFile, FileMode.Create); + CryptoStream Enfr = AES_EncryptStrream(fren, decryptKey); + byte[] bytearrayinput = new byte[fr.Length]; + fr.Read(bytearrayinput, 0, bytearrayinput.Length); + Enfr.Write(bytearrayinput, 0, bytearrayinput.Length); + Enfr.Close(); + fr.Close(); + fren.Close(); + } + catch + { + //文件异常 + return false; + } + + return true; + } + + /// + /// 对指定的文件解压缩 + /// + /// 输入文件 + /// 输出文件 + /// + public static bool AES_DecryptFile(string InputFile, string OutputFile) + { + try + { + string decryptKey = "www.iqidi.com"; + FileStream fr = new FileStream(InputFile, FileMode.Open); + FileStream frde = new FileStream(OutputFile, FileMode.Create); + CryptoStream Defr = AES_DecryptStream(fr, decryptKey); + byte[] bytearrayoutput = new byte[1024]; + int m_count = 0; + + do + { + m_count = Defr.Read(bytearrayoutput, 0, bytearrayoutput.Length); + frde.Write(bytearrayoutput, 0, m_count); + if (m_count < bytearrayoutput.Length) + { + break; + } + } while (true); + + Defr.Close(); + fr.Close(); + frde.Close(); + } + catch + { + //文件异常 + return false; + } + + return true; + } + + #endregion 对称加密算法AES RijndaelManaged加密解密 + + #region Base64加密解密 + + /// + /// Base64是一種使用64基的位置計數法。它使用2的最大次方來代表僅可列印的ASCII 字元。 + /// 這使它可用來作為電子郵件的傳輸編碼。在Base64中的變數使用字元A-Z、a-z和0-9 , + /// 這樣共有62個字元,用來作為開始的64個數字,最後兩個用來作為數字的符號在不同的 + /// 系統中而不同。 + /// Base64加密 + /// + /// Base64方式加密字符串 + /// + public static string Base64Encrypt(string str) + { + byte[] encbuff = Encoding.UTF8.GetBytes(str); + return Convert.ToBase64String(encbuff); + } + + /// + /// Base64解密字符串 + /// + /// 待解密的字符串 + /// + public static string Base64Decrypt(string str) + { + byte[] decbuff = Convert.FromBase64String(str); + return Encoding.UTF8.GetString(decbuff); + } + + #endregion Base64加密解密 + + #region MD5加密 + + /// + /// 使用MD5加密字符串 + /// + /// 待加密的字符串 + /// MD5加密后的字符串 + public static string MD5Encrypt(string strText) + { + MD5 md5 = new MD5CryptoServiceProvider(); + byte[] result = md5.ComputeHash(Encoding.Default.GetBytes(strText)); + return Encoding.Default.GetString(result); + } + + /// + /// 使用MD5加密的Hash表 + /// + /// 待加密字符串 + /// + public static string MD5EncryptHash(string input) + { + MD5 md5 = new MD5CryptoServiceProvider(); + //the GetBytes method returns byte array equavalent of a string + byte[] res = md5.ComputeHash(Encoding.Default.GetBytes(input), 0, input.Length); + char[] temp = new char[res.Length]; + //copy to a char array which can be passed to a String constructor + Array.Copy(res, temp, res.Length); + //return the result as a string + return new string(temp); + } + + /// + /// 使用Md5加密为16进制字符串 + /// + /// 待加密字符串 + /// + public static string MD5EncryptHashHex(string input) + { + MD5 md5 = new MD5CryptoServiceProvider(); + //the GetBytes method returns byte array equavalent of a string + byte[] res = md5.ComputeHash(Encoding.Default.GetBytes(input), 0, input.Length); + + string returnThis = string.Empty; + + for (int i = 0; i < res.Length; i++) + { + returnThis += Uri.HexEscape((char)res[i]); + } + + returnThis = returnThis.Replace("%", ""); + returnThis = returnThis.ToLower(); + + return returnThis; + } + + /// + /// MD5 三次加密算法.计算过程: (QQ使用) + /// 1. 验证码转为大写 + /// 2. 将密码使用这个方法进行三次加密后,与验证码进行叠加 + /// 3. 然后将叠加后的内容再次MD5一下,得到最终验证码的值 + /// + /// 待加密字符串 + /// + public static string EncyptMD5_3_16(string s) + { + MD5 md5 = MD5.Create(); + byte[] bytes = Encoding.ASCII.GetBytes(s); + byte[] bytes1 = md5.ComputeHash(bytes); + byte[] bytes2 = md5.ComputeHash(bytes1); + byte[] bytes3 = md5.ComputeHash(bytes2); + + StringBuilder sb = new StringBuilder(); + foreach (byte item in bytes3) + { + sb.Append(item.ToString("x").PadLeft(2, '0')); + } + + return sb.ToString().ToUpper(); + } + + #endregion MD5加密 + + /// + /// SHA256函数 + /// + /// 原始字符串 + /// SHA256结果(返回长度为44字节的字符串) + public static string SHA256(string str) + { + byte[] SHA256Data = Encoding.UTF8.GetBytes(str); + SHA256Managed Sha256 = new SHA256Managed(); + byte[] Result = Sha256.ComputeHash(SHA256Data); + return Convert.ToBase64String(Result); //返回长度为44字节的字符串 + } + + /// + /// 加密字符串 + /// + /// 待加密的字符串 + /// + public static string EncryptString(string input) + { + return MD5Util.AddMD5Profix(Base64Util.Encrypt(MD5Util.AddMD5Profix(input))); + //return Base64.Encrypt(MD5.AddMD5Profix(Base64.Encrypt(input))); + } + + /// + /// 解密加过密的字符串 + /// + /// 待解密的字符串 + /// 解密失败是否抛异常 + /// + public static string DecryptString(string input, bool throwException) + { + string res = ""; + try + { + res = input; // Base64.Decrypt(input); + if (MD5Util.ValidateValue(res)) + { + return MD5Util.RemoveMD5Profix(Base64Util.Decrypt(MD5Util.RemoveMD5Profix(res))); + } + else + { + throw new Exception("字符串无法转换成功!"); + } + } + catch + { + if (throwException) + { + throw; + } + else + { + return ""; + } + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/EncryptHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/EncryptHelper.cs new file mode 100644 index 0000000..a841aca --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/EncryptHelper.cs @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; +using System.Text; + +namespace Znyc.Admin.Commons.Encrypt +{ + /// + /// + /// + public class EncryptHelper + { + /// + /// + /// + /// + /// + /// + public static string ComputeHash(string source, string key) + { + if (source == null) + { + return ""; + } + + string text = "abcdefghjklmnopqrstuvwxyz"; + if (source.Length < 0x1a) + { + source = source + text.Substring(source.Length); + } + + byte[] inArray = Encoding.Unicode.GetBytes(source); + int length = inArray.Length; + if (key == null || key.Length == 0) + { + key = "Encryptheqinwn"; + } + + byte[] bytes = Encoding.Unicode.GetBytes(key); + byte num2 = Convert.ToByte(bytes.Length); + byte num3 = 2; + byte index = 0; + for (int i = 0; i < length; i++) + { + byte[] buffer3; + IntPtr ptr; + byte num5 = (byte)(bytes[index] | num2); + num5 = (byte)(num5 & num3); + (buffer3 = inArray)[(int)(ptr = (IntPtr)i)] = (byte)(buffer3[(int)ptr] ^ num5); + num3 = (byte)(num3 + 1); + if (num3 > 0xfd) + { + num3 = 2; + } + + index = (byte)(index + 1); + if (index >= num2) + { + index = 0; + } + } + + return Convert.ToBase64String(inArray, 0, inArray.Length); + } + + /// + /// + /// + /// + /// + /// + public static string EncryptStr(string source, string key) + { + key = key.PadLeft(8, 'x'); + return EncodeHelper.DesEncrypt(source, key); + } + + /// + /// + /// + /// + /// + /// + public static string UnEncryptStr(string source, string key) + { + key = key.PadLeft(8, 'x'); + return EncodeHelper.DesDecrypt(source, key); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/MD5Util.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/MD5Util.cs new file mode 100644 index 0000000..29af2de --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/MD5Util.cs @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System.IO; +using System.Text; + +namespace Znyc.Admin.Commons.Encrypt +{ + /// + /// MD5各种长度加密字符、验证MD5等操作辅助类 + /// + public class MD5Util + { + /// + /// 构造函数 + /// + public MD5Util() + { + } + + /// + /// 获得32位的MD5加密 + /// + public static string GetMD5_32(string input) + { + System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); + byte[] data = md5.ComputeHash(Encoding.Default.GetBytes(input)); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < data.Length; i++) + { + sb.Append(data[i].ToString("x2")); + } + + return sb.ToString(); + } + + /// + /// 获得16位的MD5加密 + /// + public static string GetMD5_16(string input) + { + return GetMD5_32(input).Substring(8, 16); + } + + /// + /// 获得8位的MD5加密 + /// + public static string GetMD5_8(string input) + { + return GetMD5_32(input).Substring(8, 8); + } + + /// + /// 获得4位的MD5加密 + /// + public static string GetMD5_4(string input) + { + return GetMD5_32(input).Substring(8, 4); + } + + /// + /// 添加MD5的前缀,便于检查有无篡改 + /// + public static string AddMD5Profix(string input) + { + return GetMD5_4(input) + input; + } + + /// + /// 移除MD5的前缀 + /// + public static string RemoveMD5Profix(string input) + { + return input.Substring(4); + } + + /// + /// 验证MD5前缀处理的字符串有无被篡改 + /// + public static bool ValidateValue(string input) + { + bool res = false; + if (input.Length >= 4) + { + string tmp = input.Substring(4); + if (input.Substring(0, 4) == GetMD5_4(tmp)) + { + res = true; + } + } + + return res; + } + + #region MD5签名验证 + + /// + /// 对给定文件路径的文件加上标签 + /// + /// 要加密的文件的路径 + /// 标签的值 + public static bool AddMD5(string path) + { + bool IsNeed = true; + + if (CheckMD5(path)) //已进行MD5处理 + { + IsNeed = false; + } + + try + { + FileStream fsread = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + byte[] md5File = new byte[fsread.Length]; + fsread.Read(md5File, 0, (int)fsread.Length); // 将文件流读取到Buffer中 + fsread.Close(); + + if (IsNeed) + { + string result = MD5Buffer(md5File, 0, md5File.Length); // 对Buffer中的字节内容算MD5 + byte[] md5 = Encoding.ASCII.GetBytes(result); // 将字符串转换成字节数组以便写人到文件中 + FileStream fsWrite = new FileStream(path, FileMode.Open, FileAccess.ReadWrite); + fsWrite.Write(md5File, 0, md5File.Length); // 将文件,MD5值 重新写入到文件中。 + fsWrite.Write(md5, 0, md5.Length); + fsWrite.Close(); + } + else + { + FileStream fsWrite = new FileStream(path, FileMode.Open, FileAccess.ReadWrite); + fsWrite.Write(md5File, 0, md5File.Length); + fsWrite.Close(); + } + } + catch + { + return false; + } + + return true; + } + + /// + /// 对给定路径的文件进行验证,如果一致返回True,否则返回False + /// + /// + /// 是否加了标签或是否标签值与内容值一致 + public static bool CheckMD5(string path) + { + try + { + FileStream get_file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + byte[] md5File = new byte[get_file.Length]; // 读入文件 + get_file.Read(md5File, 0, (int)get_file.Length); + get_file.Close(); + + string result = MD5Buffer(md5File, 0, md5File.Length - 32); // 对文件除最后32位以外的字节计算MD5,这个32是因为标签位为32位。 + string md5 = Encoding.ASCII.GetString(md5File, md5File.Length - 32, 32); //读取文件最后32位,其中保存的就是MD5值 + return result == md5; + } + catch + { + return false; + } + } + + /// + /// 计算文件的MD5值 + /// + /// MD5签名文件字符数组 + /// 计算起始位置 + /// 计算终止位置 + /// 计算结果 + private static string MD5Buffer(byte[] MD5File, int index, int count) + { + System.Security.Cryptography.MD5CryptoServiceProvider get_md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); + byte[] hash_byte = get_md5.ComputeHash(MD5File, index, count); + string result = System.BitConverter.ToString(hash_byte); + + result = result.Replace("-", ""); + return result; + } + + #endregion MD5签名验证 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/QQEncryptUtil.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/QQEncryptUtil.cs new file mode 100644 index 0000000..5c576df --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/QQEncryptUtil.cs @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; + +namespace Znyc.Admin.Commons.Encrypt +{ + /// + /// QQ密码加密操作辅助类 + /// + public class QQEncryptUtil + { + /// + /// QQ根据密码及验证码对数据进行加密 + /// + /// 原始密码 + /// 验证码 + /// + public static string EncodePasswordWithVerifyCode(string password, string verifyCode) + { + return MD5(MD5_3(password) + verifyCode.ToUpper()); + } + + private static string MD5_3(string arg) + { + System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); + + byte[] buffer = System.Text.Encoding.ASCII.GetBytes(arg); + buffer = md5.ComputeHash(buffer); + buffer = md5.ComputeHash(buffer); + buffer = md5.ComputeHash(buffer); + + return BitConverter.ToString(buffer).Replace("-", "").ToUpper(); + } + + private static string MD5(string arg) + { + System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); + + byte[] buffer = System.Text.Encoding.ASCII.GetBytes(arg); + buffer = md5.ComputeHash(buffer); + + return BitConverter.ToString(buffer).Replace("-", "").ToUpper(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/RSASecurityHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/RSASecurityHelper.cs new file mode 100644 index 0000000..75faebb --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/RSASecurityHelper.cs @@ -0,0 +1,273 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Znyc.Admin.Commons.Encrypt +{ + /// + /// 非对称加密、解密、验证辅助类 + /// + public class RSASecurityHelper + { + /// + /// 默认公钥。必须是8位字符的密钥字符串(不能有特殊字符) + /// + private const string DESENCRYPT_KEY = "Znyc.Admin.com"; + + /// + /// 非对称加密生成的私钥和公钥 + /// + /// 公钥,必须是8位字符的密钥字符串(不能有特殊字符) + /// 私钥 + public static void GenerateRSAKey(out string privateKey, out string publicKey) + { + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); + privateKey = rsa.ToXmlString(true); + publicKey = rsa.ToXmlString(false); + } + + #region 非对称数据加密(公钥加密) + + /// + /// 非对称加密字符串数据,返回加密后的数据 + /// + /// 待加密的字符串 + /// + public static string RSAEncrypt(string originalString) + { + return RSAEncrypt(originalString, DESENCRYPT_KEY); + } + + /// + /// 非对称加密字节数组,返回加密后的数据 + /// + /// 待加密的字节数组 + public static string RSAEncrypt(byte[] originalBytes) + { + return RSAEncrypt(originalBytes, DESENCRYPT_KEY); + } + + /// + /// 非对称加密字符串数据,返回加密后的数据 + /// + /// 待加密的字符串 + /// 公钥,必须是8位字符的密钥字符串(不能有特殊字符) + /// 加密后的数据 + public static string RSAEncrypt(string originalString, string publicKey) + { + if (string.IsNullOrEmpty(publicKey) && publicKey.Length != 8) + { + publicKey = DESENCRYPT_KEY; + } + + byte[] PlainTextBArray; + byte[] CypherTextBArray; + string Result; + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); + rsa.FromXmlString(publicKey); + PlainTextBArray = new UnicodeEncoding().GetBytes(originalString); + CypherTextBArray = rsa.Encrypt(PlainTextBArray, false); + Result = Convert.ToBase64String(CypherTextBArray); + return Result; + } + + /// + /// 非对称加密字节数组,返回加密后的数据 + /// + /// 待加密的字节数组 + /// 公钥,必须是8位字符的密钥字符串(不能有特殊字符) + /// 返回加密后的数据 + public static string RSAEncrypt(byte[] originalBytes, string publicKey) + { + if (string.IsNullOrEmpty(publicKey) && publicKey.Length != 8) + { + publicKey = DESENCRYPT_KEY; + } + + byte[] CypherTextBArray; + string Result; + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); + rsa.FromXmlString(publicKey); + CypherTextBArray = rsa.Encrypt(originalBytes, false); + Result = Convert.ToBase64String(CypherTextBArray); + return Result; + } + + #endregion 非对称数据加密(公钥加密) + + #region 非对称解密(私钥解密) + + /// + /// 非对称解密字符串,返回解密后的数据 + /// + /// 私钥 + /// 待解密数据 + /// 返回解密后的数据 + public static string RSADecrypt(string privateKey, string encryptedString) + { + byte[] PlainTextBArray; + byte[] DypherTextBArray; + string Result; + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); + rsa.FromXmlString(privateKey); + PlainTextBArray = Convert.FromBase64String(encryptedString); + DypherTextBArray = rsa.Decrypt(PlainTextBArray, false); + Result = new UnicodeEncoding().GetString(DypherTextBArray); + return Result; + } + + /// + /// 非对称解密字节数组,返回解密后的数据 + /// + /// 私钥 + /// 待解密数据 + /// + public static string RSADecrypt(string privateKey, byte[] encryptedBytes) + { + byte[] DypherTextBArray; + string Result; + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); + rsa.FromXmlString(privateKey); + DypherTextBArray = rsa.Decrypt(encryptedBytes, false); + Result = new UnicodeEncoding().GetString(DypherTextBArray); + return Result; + } + + #endregion 非对称解密(私钥解密) + + #region 非对称加密签名、验证 + + /// + /// 使用非对称加密签名数据 + /// + /// 私钥 + /// 待加密的字符串 + /// 加密后的数据 + public static string RSAEncrypSignature(string originalString, string privateKey) + { + string signature; + using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) + { + rsa.FromXmlString(privateKey); //私钥 + // 加密对象 + RSAPKCS1SignatureFormatter f = new RSAPKCS1SignatureFormatter(rsa); + f.SetHashAlgorithm("SHA1"); + byte[] source = Encoding.ASCII.GetBytes(originalString); + SHA1Managed sha = new SHA1Managed(); + byte[] result = sha.ComputeHash(source); + byte[] b = f.CreateSignature(result); + signature = Convert.ToBase64String(b); + } + + return signature; + } + + /// + /// 对私钥加密的字符串,使用公钥对其进行验证 + /// + /// 未加密的文本,如机器码 + /// 加密后的文本,如注册序列号 + /// 非对称加密的公钥 + /// 如果验证成功返回True,否则为False + public static bool Validate(string originalString, string encrytedString, string publicKey) + { + bool bPassed = false; + using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) + { + try + { + rsa.FromXmlString(publicKey); //公钥 + RSAPKCS1SignatureDeformatter formatter = new RSAPKCS1SignatureDeformatter(rsa); + formatter.SetHashAlgorithm("SHA1"); + + byte[] key = Convert.FromBase64String(encrytedString); //验证 + SHA1Managed sha = new SHA1Managed(); + byte[] name = sha.ComputeHash(Encoding.ASCII.GetBytes(originalString)); + if (formatter.VerifySignature(name, key)) + { + bPassed = true; + } + } + catch + { + } + } + + return bPassed; + } + + #endregion 非对称加密签名、验证 + + #region Hash 加密 + + /// Hash 加密 + /// + /// + public static int HashEncrypt(string str2Hash) + { + const int salt = 100716; // 盐值 + str2Hash += "Commons"; // 增加一个常量字符串 + + int len = str2Hash.Length; + int result = (str2Hash[len - 1] - 31) * 95 + salt; + for (int i = 0; i < len - 1; i++) + { + result = result * 95 + (str2Hash[i] - 32); + } + + return result; + } + + /// + /// MD5加密 + /// + /// 待加密字串 + /// 加密后的字串 + public static string ComputeMD5(string str) + { + byte[] hashValue = ComputeMD5Data(str); + return BitConverter.ToString(hashValue).Replace("-", ""); + } + + /// + /// MD5加密 + /// + /// 待加密字串 + /// 加密后的字串 + public static byte[] ComputeMD5Data(string input) + { + byte[] buffer = Encoding.UTF8.GetBytes(input); + return MD5.Create().ComputeHash(buffer); + } + + /// + /// MD5加密 + /// + /// 待加密数据 + /// 加密后的字串 + public static byte[] ComputeMD5Data(byte[] data) + { + return MD5.Create().ComputeHash(data); + } + + /// + /// MD5加密 + /// + /// 待加密流 + /// 加密后的字串 + public static byte[] ComputeMD5Data(Stream stream) + { + return MD5.Create().ComputeHash(stream); + } + + #endregion Hash 加密 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/RSAUtils.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/RSAUtils.cs new file mode 100644 index 0000000..8b45505 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Encrypt/RSAUtils.cs @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using Newtonsoft.Json; +using System.IO; +using System.Security.Cryptography; + +namespace Znyc.Admin.Commons.Encrypt +{ + /// + /// RSA加解密工具 + /// + public static class RSAUtils + { + /// + /// 从本地文件中读取用来签发Token的 RSA Key。 + /// + /// 存放密钥的文件夹路径 + /// + /// + /// + public static bool TryGetKeyParameters(string filePath, bool withPrivate, out RSAParameters keyParameters) + { + string filename = withPrivate ? "key.json" : "key.public.json"; + keyParameters = default(RSAParameters); + if (Directory.Exists(filePath) == false) + { + return false; + } + + keyParameters = + JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(filePath, filename))); + return true; + } + + /// + /// 生成并保存 RSA 公钥与私钥。 + /// + /// 存放密钥的文件夹路径 + /// + public static RSAParameters GenerateAndSaveKey(string filePath) + { + RSAParameters publicKeys, privateKeys; + using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048)) + { + try + { + privateKeys = rsa.ExportParameters(true); + publicKeys = rsa.ExportParameters(false); + } + finally + { + rsa.PersistKeyInCsp = false; + } + } + + File.WriteAllText(Path.Combine(filePath, "key.json"), JsonConvert.SerializeObject(privateKeys)); + File.WriteAllText(Path.Combine(filePath, "key.public.json"), JsonConvert.SerializeObject(publicKeys)); + return privateKeys; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/CommonStatus.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/CommonStatus.cs new file mode 100644 index 0000000..7632122 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/CommonStatus.cs @@ -0,0 +1,34 @@ +using System.ComponentModel; + +namespace Znyc.Admin.Commons.Enums +{ + /// + /// 派工调度公共状态 + /// + public enum CommonStatus + { + /// + /// 正常 + /// + [Description("正常")] + ENABLE = 1, + + /// + /// 停用 + /// + [Description("停用")] + DISABLE = -1, + + /// + /// 删除 + /// + [Description("删除")] + DELETED = -2, + + /// + /// 审核中 + /// + [Description("审核中")] + REVIEW = 0, + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/DatabaseType.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/DatabaseType.cs new file mode 100644 index 0000000..c539935 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/DatabaseType.cs @@ -0,0 +1,43 @@ +namespace Znyc.Admin.Commons.Enums +{ + /// + /// 数据库类型枚举 + /// + public enum DatabaseType + { + /// + /// SqlServer数据库 + /// + SqlServer = 0, + + /// + /// Oracle数据库 + /// + Oracle, + + /// + /// Access数据库 + /// + Access, + + /// + /// MySql数据库 + /// + MySql, + + /// + /// SQLite数据库 + /// + SQLite, + + /// + /// PostgreSQL数据库 + /// + PostgreSQL, + + /// + /// Npgsql数据库 + /// + Npgsql + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/HandleStatusEnum.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/HandleStatusEnum.cs new file mode 100644 index 0000000..67b9d01 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/HandleStatusEnum.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace Znyc.Admin.Commons.Enums +{ + /// + /// + /// + public enum HandleStatusEnum + { + /// + /// 审核中 + /// + [Description("未审核")] InReview = 0, + + /// + /// 审核通过 + /// + [Description("审核通过")] Finding = 1, + + /// + /// 未通过 + /// + [Description("未通过")] Fail = 4 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/JobAction.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/JobAction.cs new file mode 100644 index 0000000..9dd933a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/JobAction.cs @@ -0,0 +1,19 @@ +namespace Znyc.Admin.Commons.Enums +{ + /// + /// 任务操作 + /// + public enum JobAction + { + 新增 = 1, + 删除 = 2, + 修改 = 3, + 暂停 = 4, + 停止 = 5, + 开启 = 6, + 立即执行 = 7, + 执行中 = 8, + 开始, + 结束 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/JobRunResult.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/JobRunResult.cs new file mode 100644 index 0000000..a3f51d4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/JobRunResult.cs @@ -0,0 +1,18 @@ +namespace Znyc.Admin.Commons.Enums +{ + /// + /// + /// + public enum JobRunResult + { + 新增 = 1, + 删除 = 2, + 修改 = 3, + 暂停 = 4, + 停止 = 5, + 开启 = 6, + 立即执行 = 7, + 开始 = 8, + 结束 = 9 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/LinqExpressionType.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/LinqExpressionType.cs new file mode 100644 index 0000000..a7183e3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/LinqExpressionType.cs @@ -0,0 +1,15 @@ +namespace Znyc.Admin.Commons.Enums +{ + public enum LinqExpressionType + { + Equal = 0, //= + NotEqual = 1, //!= + GreaterThan, //> + LessThan, //< + ThanOrEqual, //>= + LessThanOrEqual, //<= + In, + Contains, //Contains + NotContains //NotContains + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/MsgType.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/MsgType.cs new file mode 100644 index 0000000..6d8543d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/MsgType.cs @@ -0,0 +1,23 @@ +namespace Znyc.Admin.Commons.Enums +{ + /// + /// 通知操作类型 + /// + public enum MsgType + { + /// + /// 不通知 + /// + No = 0, + + /// + /// 异常通知 + /// + Error = 1, + + /// + /// 通知所有 + /// + All = 2 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/PlatformTypeEnum.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/PlatformTypeEnum.cs new file mode 100644 index 0000000..6e6d90c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/PlatformTypeEnum.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace Znyc.Admin.Commons.Enums +{ + /// + /// 来源平台 + /// + public enum PlatformTypeEnum + { + /// + /// 人才招聘 + /// + [Description("人才招聘")] Recruitment = 1, + + /// + /// 派工调度 + /// + [Description("派工调度")] Dispatching = 2, + + /// + /// 后台管理系统 + /// + [Description("后台管理系统")] Management = 3 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/QueryOrderBy.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/QueryOrderBy.cs new file mode 100644 index 0000000..4e06727 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/QueryOrderBy.cs @@ -0,0 +1,18 @@ +namespace Znyc.Admin.Commons.Enums +{ + /// + /// 排序枚举 + /// + public enum QueryOrderBy + { + /// + /// 倒序排序 + /// + Desc = 1, + + /// + /// 正序排序 + /// + Asc = 2 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/TerminalTypeEnum.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/TerminalTypeEnum.cs new file mode 100644 index 0000000..2ec35c7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/TerminalTypeEnum.cs @@ -0,0 +1,28 @@ +using System.ComponentModel; + +namespace Znyc.Admin.Commons.Enums +{ + /// + /// GPS设备类型 + /// + public enum TerminalTypeEnum + { + /// + /// 博实结KG_M08四线 + /// + [Description("博实结KG_M08四线")] + BSJKGM_08 = 1, + } + + /// + /// 物联卡类型 + /// + public enum CardTypeEnum + { + /// + /// 北京移动 + /// + [Description("北京移动")] + Beijing_Mobile = 1, + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/UserType.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/UserType.cs new file mode 100644 index 0000000..99a5eb8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Enums/UserType.cs @@ -0,0 +1,23 @@ +namespace Znyc.Admin.Commons.Enums +{ + /// + /// 用户类型 + /// + public enum UserType + { + /// + /// 会员 + /// + Member = 0, + + /// + /// 租户 + /// + Tenant, + + /// + /// 管理员 + /// + Manager + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtDate.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtDate.cs new file mode 100644 index 0000000..94da07d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtDate.cs @@ -0,0 +1,291 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; + +namespace Znyc.Admin.Commons.Extend +{ + /// + /// 日期扩展方法 + /// + public static class ExtDate + { + /// + /// 格式:刚刚、几分钟前、几小时前、几天前、yyyy/MM/dd + /// + /// + /// + public static string ToEasyString(this DateTime value) + { + DateTime now = DateTime.Now; + if (now < value) + { + return value.ToString("yyyy/MM/dd"); + } + + TimeSpan dep = now - value; + if (dep.TotalMinutes < 30) + { + return "刚刚"; + } + else if (dep.TotalMinutes >= 30 && dep.TotalMinutes < 60) + { + return (int)dep.TotalMinutes + " 分钟前"; + } + else if (dep.TotalHours < 24) + { + return (int)dep.TotalHours + " 小时前"; + } + else if (dep.TotalDays <= 7) + { + return (int)dep.TotalDays + " 天前"; + } + else if (dep.TotalDays > 7 && dep.TotalDays <= 14) + { + int defautlWeek = 0; + defautlWeek = (int)dep.TotalDays / 7; + if ((int)dep.TotalDays % 7 > 0) + { + defautlWeek++; + } + + return defautlWeek + " 周前"; + } + else if (dep.TotalDays > 14 && dep.TotalDays < 365) + { + return value.Month.ToString().PadLeft(2, '0') + "-" + + value.Day.ToString().PadLeft(2, '0') + " " + value.Hour + ":" + value.Minute; + } + else + { + return now.Year - value.Year + " 年前"; + } + } + + /// + /// 格式:即将、几分钟后、几小时后、几天后、yyyy/MM/dd + /// + /// + /// + public static string ToEasyStringDQ(this DateTime value) + { + DateTime now = DateTime.Now; + if (value < now) + { + return "已过期"; + } + + TimeSpan dep = value - now; + + if (dep.TotalMinutes < 60) + { + return (int)dep.TotalMinutes + " 分钟后"; + } + else if (dep.TotalHours < 24) + { + return (int)dep.TotalHours + " 小时后"; + } + else if (dep.TotalDays <= 30) + { + return (int)dep.TotalDays + " 天后"; + } + else if (dep.TotalDays > 30 && dep.TotalDays <= 90) + { + int defautlWeek = 0; + defautlWeek = (int)dep.TotalDays / 30; + if ((int)dep.TotalDays % 30 > 0) + { + defautlWeek++; + } + + return defautlWeek + " 个月后"; + } + else if (dep.TotalDays > 90 && dep.TotalDays < 365) + { + return value.Month.ToString().PadLeft(2, '0') + "-" + + value.Day.ToString().PadLeft(2, '0') + " " + value.Hour + ":" + value.Minute; + } + else + { + return " 长期"; + } + } + + /// + /// 格式:几秒、几分钟几秒、几小时几分钟几秒 + /// + /// + /// + public static string ToBrowseTime(this int value) + { + if (value > 0) + { + TimeSpan ts = new TimeSpan(0, 0, value); + if (ts.Days > 0) + { + if (ts.Hours > 0) + { + return ts.Days + "天" + ts.Hours + "小时" + ts.Minutes + "分钟" + ts.Seconds + "秒"; + } + else + { + return ts.Hours + "小时" + ts.Minutes + "分钟"; + } + } + else if (ts.Hours > 0) + { + if (ts.Seconds > 0) + { + return ts.Hours + "小时" + ts.Minutes + "分钟" + ts.Seconds + "秒"; + } + else + { + return ts.Hours + "小时" + ts.Minutes + "分钟"; + } + } + else + { + if (ts.Minutes > 0) + { + return ts.Minutes + "分钟" + ts.Seconds + "秒"; + } + else + { + return ts.Seconds + "秒"; + } + } + } + else + { + return "1秒"; + } + } + + /// + /// + /// + /// + /// + public static string ToEasyString(this DateTime? value) + { + if (value.HasValue) + { + return value.Value.ToEasyString(); + } + else + { + return string.Empty; + } + } + + /// + /// + /// + /// + /// + public static string ToEasyStringDQ(this DateTime? value) + { + if (value.HasValue) + { + return value.Value.ToEasyStringDQ(); + } + else + { + return string.Empty; + } + } + + /// + /// 计算日期间隔 + /// + /// 要参与计算的其中一个日期 + /// 要参与计算的另一个日期 + /// 决定返回值形式的枚举 + /// 一个代表年月日的int数组,具体数组长度与枚举参数drf有关 + public static int[] ToDiffResult(DateTime d1, DateTime d2, DiffResultFormat drf) + { + #region 数据初始化 + + DateTime max; + DateTime min; + int year; + int month; + int tempYear, tempMonth; + if (d1 > d2) + { + max = d1; + min = d2; + } + else + { + max = d2; + min = d1; + } + + tempYear = max.Year; + tempMonth = max.Month; + if (max.Month < min.Month) + { + tempYear--; + tempMonth = tempMonth + 12; + } + + year = tempYear - min.Year; + month = tempMonth - min.Month; + + #endregion 数据初始化 + + #region 按条件计算 + + if (drf == DiffResultFormat.dd) + { + TimeSpan ts = max - min; + return new int[] { ts.Days }; + } + + if (drf == DiffResultFormat.mm) + { + return new int[] { month + year * 12 }; + } + + if (drf == DiffResultFormat.yy) + { + return new int[] { year }; + } + + return new int[] { year, month }; + + #endregion 按条件计算 + } + } + + /// + /// 关于返回值形式的枚举 + /// + public enum DiffResultFormat + { + /// + /// 年数和月数 + /// + yymm, + + /// + /// 年数 + /// + yy, + + /// + /// 月数 + /// + mm, + + /// + /// 天数 + /// + dd + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtIEnumerable.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtIEnumerable.cs new file mode 100644 index 0000000..70e64ad --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtIEnumerable.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Znyc.Admin.Commons.Extend +{ + /// + /// IEnumerable��չ�� + /// + [DebuggerStepThrough] + public static class ExtIEnumerable + { + /// + /// ѭ��IEnumerable + /// + /// + /// + /// + /// + public static IEnumerable Each(this IEnumerable source, Action fun) + { + foreach (T item in source) + { + fun(item); + } + + return source; + } + + /// + /// IEnumerableתList + /// + /// + /// + /// + /// + /// + public static List ToList(this IEnumerable source, Func fun) + { + List result = new List(); + source.Each(m => result.Add(fun(m))); + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtInt.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtInt.cs new file mode 100644 index 0000000..0fbc476 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtInt.cs @@ -0,0 +1,33 @@ +namespace Znyc.Admin.Commons.Extend +{ + /// + /// ļССļ + /// + public static class ExtInt + { + /// + /// ʾļСX Bytex KbxMxG + /// + /// + /// + public static string ToDisplayFileSize(this int value) + { + if (value < 1000) + { + return string.Format("{0} Byte", value); + } + else if (value >= 1000 && value < 1000000) + { + return string.Format("{0:F2} Kb", (double)value / 1024); + } + else if (value >= 1000 && value < 1000000000) + { + return string.Format("{0:F2} M", (double)value / 1048576); + } + else + { + return string.Format("{0:F2} G", (double)value / 1073741824); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtQueryable.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtQueryable.cs new file mode 100644 index 0000000..23fe411 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtQueryable.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; +using System.Linq.Expressions; + +namespace Znyc.Admin.Commons.Extend +{ + /// + /// + /// + public static class ExtQueryable + { + /// + /// + /// + /// + /// + /// + /// + public static IQueryable OrderBy(this IQueryable source, string ordering) + { + Type type = typeof(T); + System.Reflection.PropertyInfo property = type.GetProperty(ordering); + ParameterExpression parameter = Expression.Parameter(type, "p"); + MemberExpression propertyAccess = Expression.MakeMemberAccess(parameter, property); + LambdaExpression orderByExp = Expression.Lambda(propertyAccess, parameter); + MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { type, property.PropertyType }, + source.Expression, Expression.Quote(orderByExp)); + return source.Provider.CreateQuery(resultExp); + } + + /// + /// + /// + /// + /// + /// + /// + public static IQueryable OrderByDescending(this IQueryable source, string ordering) + { + Type type = typeof(T); + System.Reflection.PropertyInfo property = type.GetProperty(ordering); + ParameterExpression parameter = Expression.Parameter(type, "p"); + MemberExpression propertyAccess = Expression.MakeMemberAccess(parameter, property); + LambdaExpression orderByExp = Expression.Lambda(propertyAccess, parameter); + MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderByDescending", + new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp)); + return source.Provider.CreateQuery(resultExp); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtString.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtString.cs new file mode 100644 index 0000000..ba90955 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extend/ExtString.cs @@ -0,0 +1,568 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; + +namespace Znyc.Admin.Commons.Extend +{ + /// + /// ַ + /// + public static class ExtString + { + /// + /// htmlʽ + /// + /// + /// + public static string NoHTML(this string Htmlstring) + { + Htmlstring = Regex.Replace(Htmlstring, @"", "", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"", "", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"", "", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"<.*?>", "", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", " ", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", " ", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"-->", " ", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @" UserService, IUserRepository --> UserRepository. + /// + /// + /// + /// 接口程序集的名称(不包含文件扩展名) + /// + public static IServiceCollection AddTransientAssembly(this IServiceCollection service, + string interfaceAssemblyName) + { + if (service == null) + { + throw new ArgumentNullException(nameof(service)); + } + + if (string.IsNullOrEmpty(interfaceAssemblyName)) + { + throw new ArgumentNullException(nameof(interfaceAssemblyName)); + } + + Assembly assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); + if (assembly == null) + { + throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); + } + + //过滤掉非接口及泛型接口 + System.Collections.Generic.IEnumerable types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); + + foreach (Type type in types) + { + string implementTypeName = type.Name.Substring(1); + Type implementType = RuntimeHelper.GetImplementType(implementTypeName, type); + if (implementType != null) + { + service.AddTransient(type, implementType); + } + } + + return service; + } + + /// + /// 用DI批量注入接口程序集中对应的实现类。 + /// 在同一个作用域内只初始化一个实例 ,可以理解为每一个请求只创建一个实例,同一个请求会在一个作用域内。在Scooped的生存周期内,如果容器释放 它也就被释放了 + /// + /// 需要注意的是,这里有如下约定: + /// IUserService --> UserService, IUserRepository --> UserRepository. + /// + /// + /// + /// 接口程序集的名称(不包含文件扩展名) + /// + public static IServiceCollection AddScopedAssembly(this IServiceCollection service, + string interfaceAssemblyName) + { + if (service == null) + { + throw new ArgumentNullException(nameof(service)); + } + + if (string.IsNullOrEmpty(interfaceAssemblyName)) + { + throw new ArgumentNullException(nameof(interfaceAssemblyName)); + } + + Assembly assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); + if (assembly == null) + { + throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); + } + + //过滤掉非接口及泛型接口 + System.Collections.Generic.IEnumerable types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); + + foreach (Type type in types) + { + string implementTypeName = type.Name.Substring(1); + Type implementType = RuntimeHelper.GetImplementType(implementTypeName, type); + if (implementType != null) + { + service.AddScoped(type, implementType); + } + } + + return service; + } + + /// + /// 用DI批量注入接口程序集中对应的实现类。 + /// 整个应用程序生命周期以内只创建一个实例,后续每个请求都使用相同的实例。如果应用程序需要单例行为,建议让服务容器管理服务的生命周期,而不是在自己的类中实现单例模式。 + /// + /// 需要注意的是,这里有如下约定: + /// IUserService --> UserService, IUserRepository --> UserRepository. + /// + /// + /// + /// 接口程序集的名称(不包含文件扩展名) + /// + public static IServiceCollection AddSingletonAssembly(this IServiceCollection service, + string interfaceAssemblyName) + { + if (service == null) + { + throw new ArgumentNullException(nameof(service)); + } + + if (string.IsNullOrEmpty(interfaceAssemblyName)) + { + throw new ArgumentNullException(nameof(interfaceAssemblyName)); + } + + Assembly assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); + if (assembly == null) + { + throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); + } + + //过滤掉非接口及泛型接口 + System.Collections.Generic.IEnumerable types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); + + foreach (Type type in types) + { + string implementTypeName = type.Name.Substring(1); + Type implementType = RuntimeHelper.GetImplementType(implementTypeName, type); + if (implementType != null) + { + service.AddSingleton(type, implementType); + } + } + + return service; + } + + #endregion 用DI批量注入接口程序集中对应的实现类,接口和实现类在一个程序集中。 + + #region 用DI批量注入接口程序集中对应的实现类,接口和实现类在独立的程序集中。 + + /// + /// 用DI批量注入接口程序集中对应的实现类。 + /// + /// + /// 接口程序集的名称(不包含文件扩展名) + /// 实现程序集的名称(不包含文件扩展名) + /// + public static IServiceCollection AddScopedAssembly(this IServiceCollection service, + string interfaceAssemblyName, string implementAssemblyName) + { + if (service == null) + { + throw new ArgumentNullException(nameof(service)); + } + + if (string.IsNullOrEmpty(interfaceAssemblyName)) + { + throw new ArgumentNullException(nameof(interfaceAssemblyName)); + } + + if (string.IsNullOrEmpty(implementAssemblyName)) + { + throw new ArgumentNullException(nameof(implementAssemblyName)); + } + + Assembly interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); + if (interfaceAssembly == null) + { + throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); + } + + Assembly implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName); + if (implementAssembly == null) + { + throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found"); + } + + //过滤掉非接口及泛型接口 + System.Collections.Generic.IEnumerable types = interfaceAssembly.GetTypes() + .Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); + + foreach (Type type in types) + { + //过滤掉抽象类、泛型类以及非class + TypeInfo implementType = implementAssembly.DefinedTypes + .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && + t.GetInterfaces().Any(b => b.Name == type.Name)); + if (implementType != null) + { + service.AddScoped(type, implementType.AsType()); + } + } + + return service; + } + + /// + /// 用DI批量注入接口程序集中对应的实现类。 + /// + /// + /// 接口程序集的名称(不包含文件扩展名) + /// 实现程序集的名称(不包含文件扩展名) + /// + public static IServiceCollection AddTransientAssembly(this IServiceCollection service, + string interfaceAssemblyName, string implementAssemblyName) + { + if (service == null) + { + throw new ArgumentNullException(nameof(service)); + } + + if (string.IsNullOrEmpty(interfaceAssemblyName)) + { + throw new ArgumentNullException(nameof(interfaceAssemblyName)); + } + + if (string.IsNullOrEmpty(implementAssemblyName)) + { + throw new ArgumentNullException(nameof(implementAssemblyName)); + } + + Assembly interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); + if (interfaceAssembly == null) + { + throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); + } + + Assembly implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName); + if (implementAssembly == null) + { + throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found"); + } + + //过滤掉非接口及泛型接口 + System.Collections.Generic.IEnumerable types = interfaceAssembly.GetTypes() + .Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); + + foreach (Type type in types) + { + //过滤掉抽象类、泛型类以及非class + TypeInfo implementType = implementAssembly.DefinedTypes + .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && + t.GetInterfaces().Any(b => b.Name == type.Name)); + if (implementType != null) + { + service.AddTransient(type, implementType.AsType()); + } + } + + return service; + } + + /// + /// 用DI批量注入接口程序集中对应的实现类。 + /// + /// + /// 接口程序集的名称(不包含文件扩展名) + /// 实现程序集的名称(不包含文件扩展名) + /// + public static IServiceCollection AddSingletonAssembly(this IServiceCollection service, + string interfaceAssemblyName, string implementAssemblyName) + { + if (service == null) + { + throw new ArgumentNullException(nameof(service)); + } + + if (string.IsNullOrEmpty(interfaceAssemblyName)) + { + throw new ArgumentNullException(nameof(interfaceAssemblyName)); + } + + if (string.IsNullOrEmpty(implementAssemblyName)) + { + throw new ArgumentNullException(nameof(implementAssemblyName)); + } + + Assembly interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); + if (interfaceAssembly == null) + { + throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); + } + + Assembly implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName); + if (implementAssembly == null) + { + throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found"); + } + + //过滤掉非接口及泛型接口 + System.Collections.Generic.IEnumerable types = interfaceAssembly.GetTypes() + .Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); + + foreach (Type type in types) + { + //过滤掉抽象类、泛型类以及非class + TypeInfo implementType = implementAssembly.DefinedTypes + .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && + t.GetInterfaces().Any(b => b.Name == type.Name)); + if (implementType != null) + { + service.AddSingleton(type, implementType.AsType()); + } + } + + return service; + } + + #endregion 用DI批量注入接口程序集中对应的实现类,接口和实现类在独立的程序集中。 + + #region 注入控制器Controler + + /// + /// 注入Controler + /// + /// + /// + /// + public static IServiceCollection RegisterControllers(this IServiceCollection service, + string controllerAssemblyName) + { + if (service == null) + { + throw new ArgumentNullException(nameof(service)); + } + + if (string.IsNullOrEmpty(controllerAssemblyName)) + { + throw new ArgumentNullException(nameof(controllerAssemblyName)); + } + + Assembly controllerAssembly = RuntimeHelper.GetAssembly(controllerAssemblyName); + if (controllerAssembly == null) + { + throw new DllNotFoundException($"the dll \"{controllerAssemblyName}\" not be found"); + } + + //过滤掉非接口及泛型接口 + System.Collections.Generic.IEnumerable types = controllerAssembly.GetTypes().Where(t => + { + TypeInfo typeInfo = t.GetTypeInfo(); + return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType && + t.IsAssignableFrom(typeof(Controller)); + }); + + foreach (Type type in types) + { + service.AddScoped(type); + } + + return service; + } + + #endregion 注入控制器Controler + + #region 数据库上下文相关服务注入 + + /// + /// 注册数据库上下文工厂 + /// + /// + /// + /// + public static IServiceCollection AddDbContextFactory(this IServiceCollection services, + Action action) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + DbContextFactory factory = DbContextFactory.Instance; + factory.ServiceCollection = services; + action?.Invoke(factory); + return factory.ServiceCollection; + } + + /// + /// 注入数据库上下文 + /// + /// + /// + /// + /// 数据库上下文配置参数 + /// + public static IServiceCollection AddDbContext(this IServiceCollection services, DbContextOption option) + where IT : IDbContextCore where T : BaseDbContext, IT + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + if (option == null) + { + throw new ArgumentNullException(nameof(option)); + } + + services.AddSingleton(option); + return services.AddDbContext(option); + } + + /// + /// 注入数据库上下文 + /// + /// + /// + /// + /// + public static IServiceCollection AddDbContext(this IServiceCollection services) + where IT : IDbContextCore where T : BaseDbContext, IT + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + return services.AddDbContext(); + } + + /// + /// 获取数据库上下文 + /// + /// + /// 上下文标签名称 + /// + /// + public static object GetDbContext(this IServiceProvider provider, string dbContextTagName, Type serviceType) + { + if (provider == null) + { + throw new ArgumentNullException(nameof(provider)); + } + + object implService = provider.GetRequiredService(serviceType); + DbContextOption option = provider.GetServices() + .FirstOrDefault(m => m.dbConfigName == dbContextTagName); + + object context = Activator.CreateInstance(implService.GetType(), option); + + return context; + } + + #endregion 数据库上下文相关服务注入 + + #region 注册仓储Repositories + + /// + /// 注册仓储Repositories + /// + /// + /// + /// + public static IServiceCollection RegisterDefaultRepositories(this IServiceCollection services) + where T : DbContext, new() + { + Assembly assembly = Assembly.GetExecutingAssembly(); + System.Collections.Generic.List list = assembly.GetTypes().Where(t => t.GetCustomAttributes() + .Any(a => a.ContextType == typeof(T)) + && !t.GetCustomAttributes().Any() && + !t.FullName.Contains("Migrations")).ToList(); + if (list.Any()) + { + foreach (Type type in list) + { + Type pkType = GetPrimaryKeyType(type); + Type implType = GetRepositoryType(type, pkType); + if (pkType != null) + { + services.TryAddScoped(typeof(IRepository<,>).MakeGenericType(type, pkType), implType); + } + } + } + + return services; + } + + /// + /// 获取继承仓储BaseRepository的所有仓储类型 + /// + /// + /// + /// + private static Type GetRepositoryType(Type entityType, Type primaryKeyType) + { + return typeof(BaseRepository<,>).MakeGenericType(entityType, primaryKeyType); + } + + /// + /// 获取继承Entity的所有实体类型主键类型 + /// + /// + /// + private static Type GetPrimaryKeyType(Type entityType) + { + foreach (Type interfaceType in entityType.GetTypeInfo().GetInterfaces()) + { + if (interfaceType.GetTypeInfo().IsGenericType && + interfaceType.GetGenericTypeDefinition() == typeof(Entity)) + { + return interfaceType.GenericTypeArguments[0]; + } + } + + return null; + } + + #endregion 注册仓储Repositories + + /// + /// 添加自动扫描注入Service服务和Respository仓储 + /// + /// + /// 需要注意的是,遵循如下约定: + /// IUserService --> UserService, IUserRepository --> UserRepository. + /// + /// + /// 服务集合 + /// 服务集合 + public static IServiceCollection AddAutoScanInjection(this IServiceCollection services) + { + RuntimeHelper.GetAllZnycAssemblies().ToList().ForEach(a => + { + a.GetTypes().Where(t => typeof(IPrivateDependency).IsAssignableFrom(t) && t.IsClass).ToList().ForEach( + t => + { + Type serviceType = t.GetInterface($"I{t.Name}"); + if ((serviceType ?? t).GetInterface(typeof(ISingletonDependency).Name) != null) + { + if (serviceType != null) + { + services.AddSingleton(serviceType, t); + } + else + { + services.AddSingleton(t); + } + } + else if ((serviceType ?? t).GetInterface(typeof(IScopedDependency).Name) != null) + { + if (serviceType != null) + { + services.AddScoped(serviceType, t); + } + else + { + services.AddScoped(t); + } + } + else if ((serviceType ?? t).GetInterface(typeof(ITransientDependency).Name) != null) + { + if (serviceType != null) + { + services.AddTransient(serviceType, t); + } + else + { + services.AddTransient(t); + } + } + else + { + if (serviceType != null) + { + services.AddTransient(serviceType, t); + } + else + { + services.AddTransient(t); + } + } + }); + }); + return services; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/CollectionExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/CollectionExtensions.cs new file mode 100644 index 0000000..9f1bc93 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/CollectionExtensions.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Znyc.Admin.Commons.Data; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// 集合扩展方法 + /// + public static class CollectionExtensions + { + /// + /// 如果条件成立,添加项 + /// + public static void AddIf(this ICollection collection, T value, bool flag) + { + Check.NotNull(collection, nameof(collection)); + if (flag) + { + collection.Add(value); + } + } + + /// + /// 如果条件成立,添加项 + /// + public static void AddIf(this ICollection collection, T value, Func func) + { + Check.NotNull(collection, nameof(collection)); + if (func()) + { + collection.Add(value); + } + } + + /// + /// 如果不存在,添加项 + /// + public static void AddIfNotExist(this ICollection collection, T value, Func existFunc = null) + { + Check.NotNull(collection, nameof(collection)); + bool exists = existFunc == null ? collection.Contains(value) : existFunc(value); + if (!exists) + { + collection.Add(value); + } + } + + /// + /// 如果不为空,添加项 + /// + public static void AddIfNotNull(this ICollection collection, T value) where T : class + { + Check.NotNull(collection, nameof(collection)); + if (value != null) + { + collection.Add(value); + } + } + + /// + /// 获取对象,不存在对使用委托添加对象 + /// + public static T GetOrAdd(this ICollection collection, Func selector, Func factory) + { + Check.NotNull(collection, nameof(collection)); + T item = collection.FirstOrDefault(selector); + if (item == null) + { + item = factory(); + collection.Add(item); + } + + return item; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/DateTimeExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/DateTimeExtensions.cs new file mode 100644 index 0000000..5690b01 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/DateTimeExtensions.cs @@ -0,0 +1,312 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// 日期时间扩展 + /// + public static class DateTimeExtensions + { + /// + /// + /// + public static readonly DateTime BeginOfEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + /// + /// Converts a nullable date/time value to UTC. + /// + /// The nullable date/time + /// The nullable date/time in UTC + public static DateTime? ToUniversalTime(this DateTime? dateTime) + { + return dateTime.HasValue ? dateTime.Value.ToUniversalTime() : null; + } + + /// + /// Converts a nullable UTC date/time value to local time. + /// + /// The nullable UTC date/time + /// The nullable UTC date/time as local time + public static DateTime? ToLocalTime(this DateTime? dateTime) + { + return dateTime.HasValue ? dateTime.Value.ToLocalTime() : null; + } + + /// + /// Returns a date that is rounded to the next even hour above the given + /// date. + ///

+ /// For example an input date with a time of 08:13:54 would result in a date + /// with the time of 09:00:00. If the date's time is in the 23rd hour, the + /// date's 'day' will be promoted, and the time will be set to 00:00:00. + ///

+ ///
+ /// the Date to round, if the current time will + /// be used + /// the new rounded date + public static DateTime GetEvenHourDate(this DateTime? dateTime) + { + if (!dateTime.HasValue) + { + dateTime = DateTime.UtcNow; + } + + DateTime d = dateTime.Value.AddHours(1); + return new DateTime(d.Year, d.Month, d.Day, d.Hour, 0, 0); + } + + /// + /// Returns a date that is rounded to the next even minute above the given + /// date. + ///

+ /// For example an input date with a time of 08:13:54 would result in a date + /// with the time of 08:14:00. If the date's time is in the 59th minute, + /// then the hour (and possibly the day) will be promoted. + ///

+ ///
+ /// The Date to round, if the current time will be used + /// The new rounded date + public static DateTime GetEvenMinuteDate(this DateTime? dateTime) + { + if (!dateTime.HasValue) + { + dateTime = DateTime.UtcNow; + } + + DateTime d = dateTime.Value; + d = d.AddMinutes(1); + return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, 0); + } + + /// + /// Returns a date that is rounded to the previous even minute below the + /// given date. + ///

+ /// For example an input date with a time of 08:13:54 would result in a date + /// with the time of 08:13:00. + ///

+ ///
+ /// the Date to round, if the current time will + /// be used + /// the new rounded date + public static DateTime GetEvenMinuteDateBefore(this DateTime? dateTime) + { + if (!dateTime.HasValue) + { + dateTime = DateTime.UtcNow; + } + + DateTime d = dateTime.Value; + return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, 0); + } + + /// + /// + /// + /// + /// + public static long ToJavaScriptTicks(this DateTime dateTime) + { + DateTimeOffset utcDateTime = dateTime.ToUniversalTime(); + long javaScriptTicks = (utcDateTime.Ticks - BeginOfEpoch.Ticks) / 10000; + return javaScriptTicks; + } + + /// + /// Get the first day of the month for + /// any full date submitted + /// + /// + /// + public static DateTime GetFirstDayOfMonth(this DateTime date) + { + DateTime dtFrom = date; + dtFrom = dtFrom.AddDays(-(dtFrom.Day - 1)); + return dtFrom; + } + + /// + /// Get the last day of the month for any + /// full date + /// + /// + /// + public static DateTime GetLastDayOfMonth(this DateTime date) + { + DateTime dtTo = date; + dtTo = dtTo.AddMonths(1); + dtTo = dtTo.AddDays(-dtTo.Day); + return dtTo; + } + + /// + /// + /// + /// + /// + public static DateTime ToEndOfTheDay(this DateTime dt) + { + if (dt != null) + { + return new DateTime(dt.Year, dt.Month, dt.Day, 23, 59, 59); + } + + return dt; + } + + /// + /// + /// + /// + /// + public static DateTime? ToEndOfTheDay(this DateTime? dt) + { + return dt.HasValue ? dt.Value.ToEndOfTheDay() : dt; + } + + /// Epoch time. Number of seconds since midnight (UTC) on 1st January 1970. + public static long ToUnixTime(this DateTime date) + { + return Convert.ToInt64((date.ToUniversalTime() - BeginOfEpoch).TotalSeconds); + } + + /// UTC date based on number of seconds since midnight (UTC) on 1st January 1970. + public static DateTime FromUnixTime(this long unixTime) + { + return BeginOfEpoch.AddSeconds(unixTime); + } + + + /// + /// Creates a DateTime from an OLE Automation Date. + /// + /// + /// + public static DateTime FromOADate(this double d) + { + return new DateTime(DoubleDateToTicks(d), DateTimeKind.Unspecified); + } + + // Number of 100ns ticks per time unit + private const long TicksPerMillisecond = 10000; + + private const long TicksPerSecond = TicksPerMillisecond * 1000; + private const long TicksPerMinute = TicksPerSecond * 60; + private const long TicksPerHour = TicksPerMinute * 60; + + private const long TicksPerDay = TicksPerHour * 24; + + // Number of milliseconds per time unit + private const int MillisPerSecond = 1000; + + private const int MillisPerMinute = MillisPerSecond * 60; + private const int MillisPerHour = MillisPerMinute * 60; + + private const int MillisPerDay = MillisPerHour * 24; + + // Number of days in a non-leap year + private const int DaysPerYear = 365; + + // Number of days in 4 years + private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461 + + // Number of days in 100 years + private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524 + + // Number of days in 400 years + private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097 + + // Number of days from 1/1/0001 to 12/31/1600 + private const int DaysTo1601 = DaysPer400Years * 4; // 584388 + + // Number of days from 1/1/0001 to 12/30/1899 + private const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367; + + // Number of days from 1/1/0001 to 12/31/1969 + internal const int + DaysTo1970 = DaysPer400Years * 4 + DaysPer100Years * 3 + DaysPer4Years * 17 + DaysPerYear; // 719,162 + + // Number of days from 1/1/0001 to 12/31/9999 + private const int DaysTo10000 = DaysPer400Years * 25 - 366; // 3652059 + + internal const long MinTicks = 0; + internal const long MaxTicks = DaysTo10000 * TicksPerDay - 1; + private const long MaxMillis = (long)DaysTo10000 * MillisPerDay; + + private const long DoubleDateOffset = DaysTo1899 * TicksPerDay; + + // All OA dates must be greater than (not >=) OADateMinAsDouble + private const double OADateMinAsDouble = -657435.0; + + // All OA dates must be less than (not <=) OADateMaxAsDouble + private const double OADateMaxAsDouble = 2958466.0; + + // Converts an OLE Date to a tick count. + // This function is duplicated in COMDateTime.cpp + internal static long DoubleDateToTicks(double value) + { + // The check done this way will take care of NaN + if (!(value < OADateMaxAsDouble) || !(value > OADateMinAsDouble)) + { + throw new ArgumentException("Arg_OleAutDateInvalid"); + } + + // Conversion to long will not cause an overflow here, as at this point the "value" is in between OADateMinAsDouble and OADateMaxAsDouble + long millis = (long)(value * MillisPerDay + (value >= 0 ? 0.5 : -0.5)); + // The interesting thing here is when you have a value like 12.5 it all positive 12 days and 12 hours from 01/01/1899 + // However if you a value of -12.25 it is minus 12 days but still positive 6 hours, almost as though you meant -11.75 all negative + // This line below fixes up the millis in the negative case + if (millis < 0) + { + millis -= millis % MillisPerDay * 2; + } + + millis += DoubleDateOffset / TicksPerMillisecond; + + if (millis < 0 || millis >= MaxMillis) + { + throw new ArgumentException("Arg_OleAutDateScale"); + } + + return millis * TicksPerMillisecond; + } + + #region 时间对象与时间戳相互转换 + + /// + /// 将 DateTime 转换为 Unix 时间戳 + /// + /// 需要转换的时间 + /// Unix 时间戳 + public static long DateTimeToUnixTime(this DateTime dateTime) + { + return (long)(dateTime - TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1, 0, 0, 0), TimeZoneInfo.Local)) + .TotalSeconds; + } + + /// + /// 将 Unix 时间戳转换为 DateTime + /// + /// Unix 时间戳 + /// 需要转换的时间 + public static DateTime UnixTimeToDateTime(this long timestamp) + { + if (timestamp < 0) + { + throw new ArgumentOutOfRangeException("timestamp is out of range"); + } + + return TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1, 0, 0, 0), TimeZoneInfo.Local) + .AddSeconds(timestamp); + } + + #endregion 时间对象与时间戳相互转换 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/EntityFrameworkCoreExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/EntityFrameworkCoreExtensions.cs new file mode 100644 index 0000000..61f91e1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/EntityFrameworkCoreExtensions.cs @@ -0,0 +1,246 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.IDbContext; + +namespace Znyc.Admin.Commons.Extensions +{ + public static class EntityFrameworkCoreExtensions + { + public static DataTable GetCurrentDatabaseAllTables(this IDbContextCore context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade db = context.GetDatabase(); + string sql = string.Empty; + if (db.IsSqlServer()) + { + sql = "select * from (SELECT (case when a.colorder=1 then d.name else '' end) as TableName," + + "(case when a.colorder=1 then isnull(f.value,'') else '' end) as TableComment" + + " FROM syscolumns a" + + " inner join sysobjects d on a.id=d.id and d.xtype='U' and d.name<>'dtproperties'" + + " left join sys.extended_properties f on d.id=f.major_id and f.minor_id=0) t" + + " where t.TableName!=''"; + } + else if (db.IsMySql()) + { + sql = + "SELECT TABLE_NAME as TableName," + + " Table_Comment as TableComment" + + " FROM INFORMATION_SCHEMA.TABLES" + + $" where TABLE_SCHEMA = '{db.GetDbConnection().Database}'"; + } + else if (db.IsNpgsql()) + { + sql = + "select relname as TableName," + + " cast(obj_description(relfilenode,'pg_class') as varchar) as TableComment" + + " from pg_class c" + + " where relkind = 'r' and relname not like 'pg_%' and relname not like 'sql_%'" + + " order by relname"; + } + else if (db.IsOracle()) + { + sql = + "select \"a\".TABLE_NAME as \"TableName\",\"b\".COMMENTS as \"TableComment\" from USER_TABLES \"a\" JOIN user_tab_comments \"b\" on \"b\".TABLE_NAME=\"a\".TABLE_NAME"; + } + else + { + throw new NotImplementedException("This method does not support current database yet."); + } + + return context.GetDataTable(sql); + } + + public static DataTable GetTableColumns(this IDbContextCore context, params string[] tableNames) + { + if (tableNames == null || tableNames.Length == 0) + { + return null; + } + + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade db = context.GetDatabase(); + string sql = string.Empty; + if (db.IsSqlServer()) + { + sql = "SELECT d.name as TableName,a.name as ColName," + + "CONVERT(bit,(case when COLUMNPROPERTY(a.id,a.name,'IsIdentity')=1 then 1 else 0 end)) as IsIdentity, " + + "CONVERT(bit,(case when (SELECT count(*) FROM sysobjects WHERE (name in (SELECT name FROM sysindexes WHERE (id = a.id) AND (indid in (SELECT indid FROM sysindexkeys WHERE (id = a.id) AND (colid in (SELECT colid FROM syscolumns WHERE (id = a.id) AND (name = a.name))))))) AND (xtype = 'PK'))>0 then 1 else 0 end)) as IsPrimaryKey," + + "b.name as ColumnType," + + "COLUMNPROPERTY(a.id,a.name,'PRECISION') as ColumnLength," + + "CONVERT(bit,(case when a.isnullable=1 then 1 else 0 end)) as IsNullable, " + + "isnull(e.text,'') as DefaultValue," + + "isnull(g.[value], ' ') AS Comments " + + "FROM syscolumns a left join systypes b on a.xtype=b.xusertype inner join sysobjects d on a.id=d.id and d.xtype='U' and d.name<>'dtproperties' left join syscomments e on a.cdefault=e.id left join sys.extended_properties g on a.id=g.major_id AND a.colid=g.minor_id left join sys.extended_properties f on d.id=f.class and f.minor_id=0 " + + $"where b.name is not null and d.name in ({tableNames.Select(m => $"'{m}'").Join(",")}) order by a.id,a.colorder"; + } + else if (db.IsMySql()) + { + sql = + "select table_name as TableName,column_name as ColName, " + + " column_default as DefaultValue," + + " IF(extra = 'auto_increment','TRUE','FALSE') as IsIdentity," + + " IF(is_nullable = 'YES','TRUE','FALSE') as IsNullable," + + " DATA_TYPE as ColumnType," + + " CHARACTER_MAXIMUM_LENGTH as ColumnLength," + + " IF(COLUMN_KEY = 'PRI','TRUE','FALSE') as IsPrimaryKey," + + " COLUMN_COMMENT as Comments " + + $" from information_schema.columns where table_schema = '{db.GetDbConnection().Database}' and table_name in ({tableNames.Select(m => $"'{m}'").Join(",")})"; + } + else if (db.IsNpgsql()) + { + sql = + "select table_name as TableName,column_name as ColName," + + "data_type as ColumnType," + + "coalesce(character_maximum_length, numeric_precision, -1) as ColumnLength," + + "CAST((case is_nullable when 'NO' then 0 else 1 end) as bool) as IsNullable," + + "column_default as DefaultValue," + + "CAST((case when position('nextval' in column_default)> 0 then 1 else 0 end) as bool) as IsIdentity, " + + "CAST((case when b.pk_name is null then 0 else 1 end) as bool) as IsPrimaryKey," + + "c.DeText as Comments" + + " from information_schema.columns" + + " left join " + + " (select pg_attr.attname as colname,pg_constraint.conname as pk_name from pg_constraint " + + " inner join pg_class on pg_constraint.conrelid = pg_class.oid" + + " inner join pg_attribute pg_attr on pg_attr.attrelid = pg_class.oid and pg_attr.attnum = pg_constraint.conkey[1]" + + $" inner join pg_type on pg_type.oid = pg_attr.atttypid where pg_class.relname in ({tableNames.Select(m => $"'{m}'").Join(",")}) and pg_constraint.contype = 'p') b on b.colname = information_schema.columns.column_name " + + " left join " + + " (select attname, description as DeText from pg_class " + + " left join pg_attribute pg_attr on pg_attr.attrelid = pg_class.oid" + + " left join pg_description pg_desc on pg_desc.objoid = pg_attr.attrelid and pg_desc.objsubid = pg_attr.attnum " + + $" where pg_attr.attnum > 0 and pg_attr.attrelid = pg_class.oid and pg_class.relname in ({tableNames.Select(m => $"'{m}'").Join(",")})) c on c.attname = information_schema.columns.column_name" + + $" where table_schema = 'public' and table_name in ({tableNames.Select(m => $"'{m}'").Join(",")}) order by ordinal_position asc"; + } + else if (db.IsOracle()) + { + sql = "select a.Table_Name as TableName," + + "a.DATA_LENGTH as ColumnLength," + + "a.COLUMN_NAME as ColName," + + "a.DATA_PRECISION as DataPrecision," + + "a.DATA_SCALE as DataScale," + + "a.DATA_TYPE as ColumnType," + + "decode(a.NULLABLE, 'Y', 'TRUE', 'N', 'FALSE') as IsNullable," + + "case when d.COLUMN_NAME is null then 'FALSE' else 'TRUE' end as IsPrimaryKey," + + "decode(a.IDENTITY_COLUMN, 'YES', 'TRUE', 'NO', 'FALSE') as IsIdentity," + + "b.COMMENTS as Comments " + + "from user_tab_columns a " + + "left join user_tab_comments b on b.TABLE_NAME = a.COLUMN_NAME " + + "left join user_constraints c on c.TABLE_NAME = a.TABLE_NAME and c.CONSTRAINT_TYPE = 'P' " + + "left join user_cons_columns d on d.CONSTRAINT_NAME = c.CONSTRAINT_NAME and d.COLUMN_NAME = a.COLUMN_NAME " + + $"where a.Table_Name in ({tableNames.Select(m => $"'{m.ToUpper()}'").Join(",")})"; + } + else + { + throw new NotImplementedException("This method does not support current database yet."); + } + + return context.GetDataTable(sql); + } + + /// + /// 执行SQL返回受影响的行数 + /// + public static int ExecuteSqlNoQuery(this IDbContextCore context, string sql, DbParameter[] sqlParams = null) + { + return ExecuteNoQuery(context, sql, sqlParams); + } + + /// + /// 执行存储过程返回IEnumerable数据集 + /// + public static IEnumerable ExecuteStoredProcedure(this IDbContextCore context, string sql, + DbParameter[] sqlParams = null) where T : new() + { + return Execute(context, sql, CommandType.StoredProcedure, sqlParams); + } + + /// + /// 执行sql返回IEnumerable数据集 + /// + public static IEnumerable ExecuteSqlReader(this IDbContextCore context, string sql, + DbParameter[] sqlParams = null) where T : new() + { + return Execute(context, sql, CommandType.Text, sqlParams); + } + + private static int ExecuteNoQuery(this IDbContextCore context, string sql, DbParameter[] sqlParams) + { + Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade db = context.GetDatabase(); + DbConnection connection = db.GetDbConnection(); + DbCommand cmd = connection.CreateCommand(); + if (connection.State == ConnectionState.Closed) + { + connection.Open(); + } + + cmd.CommandText = sql; + cmd.CommandType = CommandType.Text; + if (sqlParams != null) + { + cmd.Parameters.AddRange(sqlParams); + } + + int result = cmd.ExecuteNonQuery(); + connection.Close(); + return result; + } + + private static IEnumerable Execute(this IDbContextCore context, string sql, CommandType type, + params DbParameter[] sqlParams) where T : new() + { + Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade db = context.GetDatabase(); + DbConnection connection = db.GetDbConnection(); + DbCommand cmd = connection.CreateCommand(); + if (connection.State == ConnectionState.Closed) + { + connection.Open(); + } + + cmd.CommandText = sql; + cmd.CommandType = type; + if (sqlParams != null) + { + cmd.Parameters.AddRange(sqlParams); + } + + DbDataReader reader = cmd.ExecuteReader(); + IEnumerable result = reader.ToList(); + connection.Close(); + return result; + } + + public static object ExecuteScalar(this IDbContextCore context, string sql, params DbParameter[] sqlParams) + { + Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade db = context.GetDatabase(); + DbConnection connection = db.GetDbConnection(); + DbCommand cmd = connection.CreateCommand(); + if (connection.State == ConnectionState.Closed) + { + connection.Open(); + } + + cmd.CommandText = sql; + cmd.CommandType = CommandType.Text; + if (sqlParams != null) + { + cmd.Parameters.AddRange(sqlParams); + } + + object result = cmd.ExecuteScalar(); + connection.Close(); + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/EnumExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/EnumExtensions.cs new file mode 100644 index 0000000..0f1fd2f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/EnumExtensions.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// 枚举类型的扩展 + /// + public static class EnumExtensions + { + /// + /// + /// + /// + /// + public static string ToDescription(this Enum item) + { + string name = item.ToString(); + DescriptionAttribute desc = item.GetType().GetField(name)?.GetCustomAttribute(); + return desc?.Description ?? name; + } + + /// + /// + /// + /// + /// + public static long ToInt64(this Enum item) + { + return Convert.ToInt64(item); + } + + /// + /// 根据枚举的value获取枚举 + /// + /// 枚举的类型,示例:typeof(enum1) + /// 可能的枚举值 + /// 枚举,示例:enum1.en1 + public static Enum ParseEnum(Type enumType, string value) + { + return Enum.Parse(enumType, value) as Enum; + } + + /// + /// 根据 value 值获取Description + /// + /// + /// + /// + public static string GetDescription(this Type enumType, int value) + { + var Key = GetNameAndValue(enumType).FirstOrDefault(p => p.Value.Equals(value)).Key; + if (Key == null) + { + return null; + } + + return Key.ToString(); + } + + /// + /// 获取枚举名以及对应的Value + /// + /// 枚举类型typeof(T) + /// 返回Dictionary ,Key为描述名, Value为枚举对应的值 + public static Dictionary GetNameAndValue(this Type type) + { + if (type.IsEnum) + { + var dic = new Dictionary(); + var enumValues = Enum.GetValues(type); + foreach (Enum value in enumValues) + { + dic.Add(GetDescription(value), value.GetHashCode()); + } + return dic; + } + return null; + } + + /// + /// 从枚举中获取Description + /// + /// 需要获取枚举描述的枚举 + /// 描述内容 + public static string GetDescription(this Enum enumName) + { + var description = string.Empty; + var fieldInfo = enumName.GetType().GetField(enumName.ToString()); + var attributes = GetDescriptAttr(fieldInfo); + if (attributes != null && attributes.Length > 0) + { + description = attributes[0].Description; + } + else + { + description = enumName.ToString(); + } + return description; + } + + /// + /// 获取字段Description + /// + /// FieldInfo + /// DescriptionAttribute[] + private static DescriptionAttribute[] GetDescriptAttr(FieldInfo fieldInfo) + { + if (fieldInfo != null) + { + return (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); + } + return null; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ExpressionExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ExpressionExtensions.cs new file mode 100644 index 0000000..667d807 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ExpressionExtensions.cs @@ -0,0 +1,350 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +namespace Zxw.Framework.NetCore.Extensions +{ + /// + /// 表达式树常用扩展方法 + /// + public static class ExpressionExtensions + { + /// + /// 取的 Expression> predicate 表达式对应的属性名称 + /// 例如:c=>c.Value.Year 侧返回:Value.Year + /// + /// + /// + /// + /// + public static string GetPropertyName(this Expression> predicate) + { + MemberExpression expression = predicate.Body as MemberExpression; + //return expression.Member.Name; //该属性只返回最后一个属性,因此采用下面方法返回。 + return expression.ToString().Substring(2); + } + + /// + /// + /// + /// + /// + /// + public static ParameterExpression CreateLambdaParam(string name) + { + return Expression.Parameter(typeof(T), name); + } + + /// + /// 创建linq表达示的body部分 + /// + public static Expression GenerateBody(this ParameterExpression param, Filter filterObj) + { + System.Reflection.PropertyInfo property = typeof(T).GetProperty(filterObj.Key); + + //组装左边 + Expression left = Expression.Property(param, property); + //组装右边 + Expression right = null; + + if (property.PropertyType == typeof(int)) + { + right = Expression.Constant(int.Parse(filterObj.Value)); + } + else if (property.PropertyType == typeof(DateTime)) + { + right = Expression.Constant(DateTime.Parse(filterObj.Value)); + } + else if (property.PropertyType == typeof(string)) + { + right = Expression.Constant(filterObj.Value); + } + else if (property.PropertyType == typeof(decimal)) + { + right = Expression.Constant(decimal.Parse(filterObj.Value)); + } + else if (property.PropertyType == typeof(Guid)) + { + right = Expression.Constant(Guid.Parse(filterObj.Value)); + } + else if (property.PropertyType == typeof(bool)) + { + right = Expression.Constant(filterObj.Value.Equals("1")); + } + else if (property.PropertyType == typeof(Guid?)) + { + left = Expression.Property(left, "Value"); + right = Expression.Constant(Guid.Parse(filterObj.Value)); + } + else + { + throw new Exception("暂不能解析该Key的类型"); + } + + //c.XXX=="XXX" + Expression filter = Expression.Equal(left, right); + switch (filterObj.Contrast) + { + case "<=": + filter = Expression.LessThanOrEqual(left, right); + break; + + case "<": + filter = Expression.LessThan(left, right); + break; + + case ">": + filter = Expression.GreaterThan(left, right); + break; + + case ">=": + filter = Expression.GreaterThanOrEqual(left, right); + break; + + case "!=": + filter = Expression.NotEqual(left, right); + break; + + case "like": + filter = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), + Expression.Constant(filterObj.Value)); + break; + + case "not in": + ConstantExpression listExpression = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组 + System.Reflection.MethodInfo method = typeof(List).GetMethod("Contains", new Type[] { typeof(string) }); //Contains语句 + filter = Expression.Not(Expression.Call(listExpression, method, left)); + break; + + case "in": + ConstantExpression lExp = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组 + System.Reflection.MethodInfo methodInfo = + typeof(List).GetMethod("Contains", new Type[] { typeof(string) }); //Contains语句 + filter = Expression.Call(lExp, methodInfo, left); + break; + } + + return filter; + } + + /// + /// + /// + /// + /// + /// + /// + public static Expression> GenerateTypeBody(this ParameterExpression param, Filter filterObj) + { + return (Expression>)param.GenerateBody(filterObj); + } + + /// + /// 创建完整的lambda + /// + public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body) + { + //c=>c.XXX=="XXX" + return Expression.Lambda(body, param); + } + + /// + /// + /// + /// + /// + /// + /// + public static Expression> GenerateTypeLambda(this ParameterExpression param, Expression body) + { + return (Expression>)param.GenerateLambda(body); + } + + /// + /// + /// + /// + /// + /// + public static Expression AndAlso(this Expression expression, Expression expressionRight) + { + return Expression.AndAlso(expression, expressionRight); + } + + /// + /// + /// + /// + /// + /// + public static Expression Or(this Expression expression, Expression expressionRight) + { + return Expression.Or(expression, expressionRight); + } + + /// + /// + /// + /// + /// + /// + public static Expression And(this Expression expression, Expression expressionRight) + { + return Expression.And(expression, expressionRight); + } + + //系统已经有该函数的实现 + //public static IQueryable Where(this IQueryable query, Expression expression) + //{ + // Expression expr = Expression.Call(typeof(Queryable), "Where", new[] { typeof(T) }, + // Expression.Constant(query), expression); + // //生成动态查询 + // IQueryable result = query.Provider.CreateQuery(expr); + // return result; + //} + + /// + /// + /// + /// + /// + /// + /// + public static IQueryable GenerateFilter(this IQueryable query, string filterjson) + { + if (!string.IsNullOrEmpty(filterjson)) + { + IEnumerable filters = JsonConvert.DeserializeObject>(filterjson); + ParameterExpression param = CreateLambdaParam("c"); + + Expression result = Expression.Constant(true); + foreach (Filter filter in filters) + { + result = result.AndAlso(param.GenerateBody(filter)); + } + + query = query.Where(param.GenerateTypeLambda(result)); + } + + return query; + } + + /// + /// 以特定的条件运行组合两个Expression表达式 + /// + /// 表达式的主实体类型 + /// 第一个Expression表达式 + /// 要组合的Expression表达式 + /// 组合条件运算方式 + /// 组合后的表达式 + public static Expression Compose(this Expression first, Expression second, + Func merge) + { + // build parameter map (from parameters of second to parameters of first) + Dictionary map = + first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); + + // replace parameters in the second lambda expression with parameters from the first + Expression secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); + + // apply composition of lambda expression bodies to parameters from the first expression + return Expression.Lambda(merge(first.Body, secondBody), first.Parameters); + } + + /// + /// 以 Expression.AndAlso 组合两个Expression表达式 + /// + /// 表达式的主实体类型 + /// 第一个Expression表达式 + /// 要组合的Expression表达式 + /// 组合后的表达式 + public static Expression> And(this Expression> first, + Expression> second) + { + return first.Compose(second, Expression.AndAlso); + } + + /// + /// 以 Expression.OrElse 组合两个Expression表达式 + /// + /// 表达式的主实体类型 + /// 第一个Expression表达式 + /// 要组合的Expression表达式 + /// 组合后的表达式 + public static Expression> Or(this Expression> first, + Expression> second) + { + return first.Compose(second, Expression.OrElse); + } + + /// + /// 参数重新绑定 + /// + /// + private class ParameterRebinder : ExpressionVisitor + { + private readonly Dictionary _map; + + /// + /// Initializes a new instance of the class. + /// + /// The map. + private ParameterRebinder(Dictionary map) + { + _map = map ?? new Dictionary(); + } + + /// + /// Replaces the parameters. + /// + /// The map. + /// The exp. + /// + public static Expression ReplaceParameters(Dictionary map, + Expression exp) + { + return new ParameterRebinder(map).Visit(exp); + } + + /// + /// 访问 。 + /// + /// 要访问的表达式。 + /// + /// 如果修改了该表达式或任何子表达式,则为修改后的表达式;否则返回原始表达式。 + /// + protected override Expression VisitParameter(ParameterExpression node) + { + if (_map.TryGetValue(node, out ParameterExpression replacement)) + { + node = replacement; + } + + return base.VisitParameter(node); + } + } + } + + /// + /// + /// + public class Filter + { + /// + /// + /// + public string Key { get; set; } + + /// + /// + /// + public string Value { get; set; } + + /// + /// + /// + public string Contrast { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/HttpContextExtentions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/HttpContextExtentions.cs new file mode 100644 index 0000000..14e70a2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/HttpContextExtentions.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Znyc.Admin.Commons.Helpers; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// HttpContext 扩展 + /// + public static class HttpContextExtentions + { + public static IApplicationBuilder UseStaticHttpContextAccessor(this IApplicationBuilder app) + { + IHttpContextAccessor httpContextAccessor = app.ApplicationServices.GetRequiredService(); + HttpContextHelper.Configure(httpContextAccessor); + return app; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ObjectExtension.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ObjectExtension.cs new file mode 100644 index 0000000..5a15116 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ObjectExtension.cs @@ -0,0 +1,1534 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; +using System.Xml; +using System.Xml.Linq; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// 对象自定义扩展类 + /// + public static class ObjectExtension + { + /// + /// 将集合转换为数据集。 + /// + /// 转换的元素类型。 + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToDataSet(this IEnumerable list, bool generic = true) + { + return ListToDataSet(list, generic); + } + + /// + /// 将集合转换为数据集。 + /// + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToDataSet(this IEnumerable list, bool generic = true) + { + return ListToDataSet(list, generic); + } + + /// + /// 将集合转换为数据集。 + /// + /// 转换的元素类型。 + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToDataSet(this IEnumerable list, bool generic = true) + { + return ListToDataSet(list, typeof(T), generic); + } + + /// + /// 将实例转换为集合数据集。 + /// + /// 实例类型。 + /// 实例。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToListSet(this T o, bool generic = true) + { + if (o is IEnumerable) + { + return ListToDataSet(o as IEnumerable, generic); + } + else + { + return ListToDataSet(new T[] { o }, generic); + } + } + + /// + /// 将可序列化实例转换为XmlDocument。 + /// + /// 实例类型。 + /// 实例。 + /// XmlDocument。 + public static XmlDocument ToXmlDocument(this T o) + { + XmlDocument xmlDocument = new XmlDocument + { + InnerXml = o.ToListSet().GetXml() + }; + return xmlDocument; + } + + /// + /// + /// + /// + /// + /// + public static object ChangeType(this object convertibleValue, Type type) + { + if (null == convertibleValue) + { + return null; + } + + try + { + if (type == typeof(Guid) || type == typeof(Guid?)) + { + string value = convertibleValue.ToString(); + if (value == "") + { + return null; + } + + return Guid.Parse(value); + } + + if (!type.IsGenericType) + { + return Convert.ChangeType(convertibleValue, type); + } + + if (type.ToString() == "System.Nullable`1[System.Boolean]" || type.ToString() == "System.Boolean") + { + if (convertibleValue.ToString() == "0") + { + return false; + } + + return true; + } + + Type genericTypeDefinition = type.GetGenericTypeDefinition(); + if (genericTypeDefinition == typeof(Nullable<>)) + { + return Convert.ChangeType(convertibleValue, Nullable.GetUnderlyingType(type)); + } + } + catch + { + return null; + } + + return null; + } + + /// + /// 获取对象里指定成员名称 + /// + /// + /// properties = x => new { x.字段1, x.字段2 };或x=>x.Name + /// + public static string[] GetExpressionProperty(this Expression> properties) + { + if (properties == null) + { + return new string[] { }; + } + + if (properties.Body is NewExpression) + { + return ((NewExpression)properties.Body).Members.Select(x => x.Name).ToArray(); + } + + if (properties.Body is MemberExpression) + { + return new string[] { ((MemberExpression)properties.Body).Member.Name }; + } + + if (properties.Body is UnaryExpression) + { + return new string[] { ((properties.Body as UnaryExpression).Operand as MemberExpression).Member.Name }; + } + + throw new Exception("未实现的表达式"); + } + + /// + /// 将集合转换为数据集。 + /// + /// 集合。 + /// 转换的元素类型。 + /// 是否生成泛型数据集。 + /// 转换后的数据集。 + private static DataSet ListToDataSet(IEnumerable list, Type t, bool generic) + { + DataSet ds = new DataSet("Data"); + if (t == null) + { + if (list != null) + { + foreach (object i in list) + { + if (i == null) + { + continue; + } + + t = i.GetType(); + break; + } + } + + if (t == null) + { + return ds; + } + } + + ds.Tables.Add(t.Name); + //如果集合中元素为DataSet扩展涉及到的基本类型时,进行特殊转换。 + if (t.IsValueType || t == typeof(string)) + { + ds.Tables[0].TableName = "Info"; + ds.Tables[0].Columns.Add(t.Name); + if (list != null) + { + foreach (object i in list) + { + DataRow addRow = ds.Tables[0].NewRow(); + addRow[t.Name] = i; + ds.Tables[0].Rows.Add(addRow); + } + } + + return ds; + } + + //处理模型的字段和属性。 + FieldInfo[] fields = t.GetFields(); + PropertyInfo[] properties = t.GetProperties(); + foreach (FieldInfo j in fields) + { + if (!ds.Tables[0].Columns.Contains(j.Name)) + { + if (generic) + { + ds.Tables[0].Columns.Add(j.Name, j.FieldType); + } + else + { + ds.Tables[0].Columns.Add(j.Name); + } + } + } + + foreach (PropertyInfo j in properties) + { + if (!ds.Tables[0].Columns.Contains(j.Name)) + { + if (generic) + { + ds.Tables[0].Columns.Add(j.Name, j.PropertyType); + } + else + { + ds.Tables[0].Columns.Add(j.Name); + } + } + } + + if (list == null) + { + return ds; + } + //读取list中元素的值。 + foreach (object i in list) + { + if (i == null) + { + continue; + } + + DataRow addRow = ds.Tables[0].NewRow(); + foreach (FieldInfo j in fields) + { + MemberExpression field = Expression.Field(Expression.Constant(i), j.Name); + LambdaExpression lambda = Expression.Lambda(field, new ParameterExpression[] { }); + Delegate func = lambda.Compile(); + object value = func.DynamicInvoke(); + addRow[j.Name] = value; + } + + foreach (PropertyInfo j in properties) + { + MemberExpression property = Expression.Property(Expression.Constant(i), j); + LambdaExpression lambda = Expression.Lambda(property, new ParameterExpression[] { }); + Delegate func = lambda.Compile(); + object value = func.DynamicInvoke(); + addRow[j.Name] = value; + } + + ds.Tables[0].Rows.Add(addRow); + } + + return ds; + } + + /// + /// 将集合转换为数据集。 + /// + /// 转换的元素类型。 + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + private static DataSet ListToDataSet(IEnumerable list, bool generic) + { + return ListToDataSet(list, typeof(T), generic); + } + + /// + /// 将集合转换为数据集。 + /// + /// 集合。 + /// 是否转换为字符串形式。 + /// 转换后的数据集。 + private static DataSet ListToDataSet(IEnumerable list, bool generic) + { + return ListToDataSet(list, null, generic); + } + + /// + /// 获取DataSet第一表,第一行,第一列的值。 + /// + /// DataSet数据集。 + /// 值。 + public static object GetData(this DataSet ds) + { + if ( + ds == null + || ds.Tables.Count == 0 + ) + { + return string.Empty; + } + else + { + return ds.Tables[0].GetData(); + } + } + + /// + /// 获取DataTable第一行,第一列的值。 + /// + /// DataTable数据集表。 + /// 值。 + public static object GetData(this DataTable dt) + { + if ( + dt.Columns.Count == 0 + || dt.Rows.Count == 0 + ) + { + return string.Empty; + } + else + { + return dt.Rows[0][0]; + } + } + + /// + /// 获取DataSet第一个匹配columnName的值。 + /// + /// 数据集。 + /// 列名。 + /// 值。 + public static object GetData(this DataSet ds, string columnName) + { + if ( + ds == null + || ds.Tables.Count == 0 + ) + { + return string.Empty; + } + + foreach (DataTable dt in ds.Tables) + { + object o = dt.GetData(columnName); + if (!string.IsNullOrEmpty(o.ToString())) + { + return o; + } + } + + return string.Empty; + } + + /// + /// 获取DataTable第一个匹配columnName的值。 + /// + /// 数据表。 + /// 列名。 + /// 值。 + public static object GetData(this DataTable dt, string columnName) + { + if (string.IsNullOrEmpty(columnName)) + { + return GetData(dt); + } + + if ( + dt.Columns.Count == 0 + || dt.Columns.IndexOf(columnName) == -1 + || dt.Rows.Count == 0 + ) + { + return string.Empty; + } + + return dt.Rows[0][columnName]; + } + + /// + /// 将object转换为string类型信息。 + /// + /// object。 + /// 默认值。 + /// string。 + public static string ToString(this object o, string t) + { + string info = string.Empty; + if (o == null) + { + info = t; + } + else + { + info = o.ToString(); + } + + return info; + } + + /// + /// 将DateTime?转换为string类型信息。 + /// + /// DateTime?。 + /// 标准或自定义日期和时间格式的字符串。 + /// 默认值。 + /// string。 + public static string ToString(this DateTime? o, string format, string t) + { + string info = string.Empty; + if (o == null) + { + info = t; + } + else + { + info = o.Value.ToString(format); + } + + return info; + } + + /// + /// 将TimeSpan?转换为string类型信息。 + /// + /// TimeSpan?。 + /// 标准或自定义时间格式的字符串。 + /// 默认值。 + /// string。 + public static string ToString(this TimeSpan? o, string format, string t) + { + string info = string.Empty; + if (o == null) + { + info = t; + } + else + { + info = o.Value.ToString(format); + } + + return info; + } + + /// + /// 将object转换为截取后的string类型信息。 + /// + /// object。 + /// 此实例中子字符串的起始字符位置(从零开始)。 + /// 子字符串中的字符数。 + /// 后缀。如果没有截取则不添加。 + /// 截取后的string类型信息。 + public static string ToSubString(this object o, int startIndex, int length, string suffix = null) + { + string inputString = o.ToString(string.Empty); + startIndex = Math.Max(startIndex, 0); + startIndex = Math.Min(startIndex, inputString.Length - 1); + length = Math.Max(length, 1); + if (startIndex + length > inputString.Length) + { + length = inputString.Length - startIndex; + } + + if (inputString.Length == startIndex + length) + { + return inputString; + } + else + { + return inputString.Substring(startIndex, length) + suffix; + } + } + + /// + /// 将object转换为byte类型信息。 + /// + /// object。 + /// 默认值。 + /// byte。 + public static byte ToByte(this object o, byte t = default(byte)) + { + if (!byte.TryParse(o.ToString(string.Empty), out byte info)) + { + info = t; + } + + return info; + } + + /// + /// + /// + /// + /// + public static byte[] ToBytes(this object obj) + { + if (obj == null) + { + return null; + } + + BinaryFormatter bf = new BinaryFormatter(); + using (MemoryStream ms = new MemoryStream()) + { + bf.Serialize(ms, obj); + return ms.ToArray(); + } + } + + /// + /// + /// + /// + /// + public static object ToObject(this byte[] source) + { + using (MemoryStream memStream = new MemoryStream()) + { + BinaryFormatter bf = new BinaryFormatter(); + memStream.Write(source, 0, source.Length); + memStream.Seek(0, SeekOrigin.Begin); + object obj = bf.Deserialize(memStream); + return obj; + } + } + + /// + /// 将object转换为char类型信息。 + /// + /// object。 + /// 默认值。 + /// char。 + public static char ToChar(this object o, char t = default(char)) + { + if (!char.TryParse(o.ToString(string.Empty), out char info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为int类型信息。 + /// + /// object。 + /// 默认值。 + /// int。 + public static int ToInt(this object o, int t = default(int)) + { + if (!int.TryParse(o.ToString(string.Empty), out int info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为double类型信息。 + /// + /// object。 + /// 默认值。 + /// double。 + public static double ToDouble(this object o, double t = default(double)) + { + if (!double.TryParse(o.ToString(string.Empty), out double info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为decimal类型信息。 + /// + /// object。 + /// 默认值。 + /// decimal。 + public static decimal ToDecimal(this object o, decimal t = default(decimal)) + { + if (!decimal.TryParse(o.ToString(string.Empty), out decimal info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为float类型信息。 + /// + /// object。 + /// 默认值。 + /// float。 + public static float ToFloat(this object o, float t = default(float)) + { + if (!float.TryParse(o.ToString(string.Empty), out float info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为long类型信息。 + /// + /// object。 + /// 默认值。 + /// long。 + public static long ToLong(this object o, long t = default(long)) + { + if (!long.TryParse(o.ToString(string.Empty), out long info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为bool类型信息。 + /// + /// object。 + /// 默认值。 + /// bool。 + public static bool ToBool(this object o, bool t = default(bool)) + { + if (!bool.TryParse(o.ToString(string.Empty), out bool info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为sbyte类型信息。 + /// + /// object。 + /// 默认值。 + /// sbyte。 + public static sbyte ToSbyte(this object o, sbyte t = default(sbyte)) + { + if (!sbyte.TryParse(o.ToString(string.Empty), out sbyte info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为short类型信息。 + /// + /// object。 + /// 默认值。 + /// short。 + public static short ToShort(this object o, short t = default(short)) + { + if (!short.TryParse(o.ToString(string.Empty), out short info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为ushort类型信息。 + /// + /// object。 + /// 默认值。 + /// ushort。 + public static ushort ToUShort(this object o, ushort t = default(ushort)) + { + if (!ushort.TryParse(o.ToString(string.Empty), out ushort info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为ulong类型信息。 + /// + /// object。 + /// 默认值。 + /// ulong。 + public static ulong ToULong(this object o, ulong t = default(ulong)) + { + if (!ulong.TryParse(o.ToString(string.Empty), out ulong info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为Enum[T]类型信息。 + /// + /// object。 + /// 默认值。 + /// Enum[T]。 + public static T ToEnum(this object o, T t = default(T)) + where T : struct + { + if (!Enum.TryParse(o.ToString(string.Empty), out T info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为DateTime类型信息。 + /// + /// object。 + /// 默认值。 + /// DateTime。 + public static DateTime ToDateTime(this object o, DateTime t = default(DateTime)) + { + if (t == default(DateTime)) + { + t = new DateTime(1753, 1, 1); + } + + if (!DateTime.TryParse(o.ToString(string.Empty), out DateTime info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为TimeSpan类型信息。 + /// + /// object。 + /// 默认值。 + /// TimeSpan。 + public static TimeSpan ToTimeSpan(this object o, TimeSpan t = default(TimeSpan)) + { + if (t == default(TimeSpan)) + { + t = new TimeSpan(0, 0, 0); + } + + if (!TimeSpan.TryParse(o.ToString(string.Empty), out TimeSpan info)) + { + info = t; + } + + return info; + } + + /// + /// 将object转换为Guid类型信息。 + /// + /// object。 + /// 默认值。 + /// Guid。 + public static Guid ToGuid(this object o, Guid t = default(Guid)) + { + if (!Guid.TryParse(o.ToString(string.Empty), out Guid info)) + { + info = t; + } + + return info; + } + + private static readonly Regex BoolRegex = + new Regex("(?(true|false))", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取bool类型信息。 + /// + /// object。 + /// bool。 + public static bool? GetBool(this object o) + { + if (!bool.TryParse(BoolRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out bool info)) + { + return null; + } + + return info; + } + + private static readonly Regex IntRegex = new Regex("(?-?\\d+)", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取int类型信息。 + /// + /// object。 + /// int。 + public static int? GetInt(this object o) + { + if (!int.TryParse(IntRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out int info)) + { + return null; + } + + return info; + } + + private static readonly Regex DecimalRegex = + new Regex("(?-?\\d+(\\.\\d+)?)", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取decimal类型信息。 + /// + /// object。 + /// decimal。 + public static decimal? GetDecimal(this object o) + { + if (!decimal.TryParse(DecimalRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out decimal info)) + { + return null; + } + + return info; + } + + /// + /// 从object中获取double类型信息。 + /// + /// object。 + /// double。 + public static double? GetDouble(this object o) + { + if (!double.TryParse(DecimalRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out double info)) + { + return null; + } + + return info; + } + + /// + /// 从object中获取正数信息。 + /// + /// object。 + /// decimal。 + public static decimal? GetPositiveNumber(this object o) + { + if (!decimal.TryParse(DecimalRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out decimal info)) + { + return null; + } + + return Math.Abs(info); + } + + private static readonly Regex DateTimeRegex = new Regex( + "(?(((\\d+)[/年-](0?[13578]|1[02])[/月-](3[01]|[12]\\d|0?\\d)[日]?)|((\\d+)[/年-](0?[469]|11)[/月-](30|[12]\\d|0?\\d)[日]?)|((\\d+)[/年-]0?2[/月-](2[0-8]|1\\d|0?\\d)[日]?))(\\s((2[0-3]|[0-1]\\d)):[0-5]\\d:[0-5]\\d)?)", + RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取DateTime?类型信息。 + /// + /// object。 + /// DateTime?。 + public static DateTime? GetDateTime(this object o) + { + if (!DateTime.TryParse( + DateTimeRegex.Match(o.ToString(string.Empty)).Groups["info"].Value.Replace("年", "-").Replace("月", "-") + .Replace("/", "-").Replace("日", ""), out DateTime info)) + { + return null; + } + + return info; + } + + private static readonly Regex TimeSpanRegex = + new Regex( + "(?-?(\\d+\\.(([0-1]\\d)|(2[0-3])):[0-5]\\d:[0-5]\\d)|((([0-1]\\d)|(2[0-3])):[0-5]\\d:[0-5]\\d)|(\\d+))", + RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取TimeSpan?类型信息。 + /// + /// object。 + /// TimeSpan?。 + public static TimeSpan? GetTimeSpan(this object o) + { + if (!TimeSpan.TryParse(TimeSpanRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out TimeSpan info)) + { + return null; + } + + return info; + } + + private static readonly Regex GuidRegex = + new Regex( + "(?\\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\\}{0,1})", + RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取Guid?类型信息。 + /// + /// object。 + /// Guid?。 + public static Guid? GetGuid(this object o) + { + if (!Guid.TryParse(GuidRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out Guid info)) + { + return null; + } + + return info; + } + + /// + /// 将object转换为SqlServer中的DateTime?类型信息。 + /// + /// object。 + /// 默认值。 + /// DateTime?。 + public static DateTime? GetSqlDateTime(this object o, DateTime t = default(DateTime)) + { + if (!DateTime.TryParse(o.ToString(string.Empty), out DateTime info)) + { + info = t; + } + + if (info < new DateTime(1753, 1, 1) || info > new DateTime(9999, 12, 31)) + { + return null; + } + + return info; + } + + /// + /// 读取XElement节点的文本内容。 + /// + /// XElement节点。 + /// 默认值。 + /// 文本内容。 + public static string Value(this XElement xElement, string t = default(string)) + { + if (xElement == null) + { + return t; + } + else + { + return xElement.Value; + } + } + + /// + /// 获取与指定键相关的值。 + /// + /// 键类型。 + /// 值类型。 + /// 表示键/值对象的泛型集合。 + /// 键。 + /// 默认值。 + /// 值。 + public static TValue GetValue(this IDictionary dictionary, TKey key, + TValue t = default(TValue)) + { + if (dictionary == null || key == null) + { + return t; + } + + if (!dictionary.TryGetValue(key, out TValue value)) + { + value = t; + } + + return value; + } + + /// + /// 获取与指定键相关或者第一个的值。 + /// + /// 键类型。 + /// 值类型。 + /// 表示键/值对象的泛型集合。 + /// 键。 + /// 默认值。 + /// 值。 + public static TValue GetFirstOrDefaultValue(this IDictionary dictionary, TKey key, + TValue t = default(TValue)) + { + if (dictionary == null || key == null) + { + return t; + } + + if (!dictionary.TryGetValue(key, out TValue value)) + { + if (dictionary.Count() == 0) + { + value = t; + } + else + { + value = dictionary.FirstOrDefault().Value; + } + } + + return value; + } + + /// + /// 获取具有指定 System.Xml.Linq.XName 的第一个(按文档顺序)子元素。 + /// + /// XContainer。 + /// 要匹配的 System.Xml.Linq.XName。 + /// 是否返回同名默认值。 + /// 与指定 System.Xml.Linq.XName 匹配的 System.Xml.Linq.XElement,或者为 null。 + public static XElement Element(this XContainer xContainer, XName xName, bool t) + { + XElement info; + if (xContainer == null) + { + info = null; + } + else + { + info = xContainer.Element(xName); + } + + if (t && info == null) + { + info = new XElement(xName); + } + + return info; + } + + /// + /// 按文档顺序返回此元素或文档的子元素集合。 + /// + /// XContainer。 + /// 是否返回非空默认值。 + /// System.Xml.Linq.XElement 的按文档顺序包含此System.Xml.Linq.XContainer 的子元素,或者非空默认值。 + public static IEnumerable Elements(this XContainer xContainer, bool t) + { + IEnumerable info; + if (xContainer == null) + { + info = null; + } + else + { + info = xContainer.Elements(); + } + + if (t && info == null) + { + info = new List(); + } + + return info; + } + + /// + /// 按文档顺序返回此元素或文档的经过筛选的子元素集合。集合中只包括具有匹配 System.Xml.Linq.XName 的元素。 + /// + /// XContainer。 + /// 要匹配的 System.Xml.Linq.XName。 + /// 是否返回非空默认值。 + /// System.Xml.Linq.XElement 的按文档顺序包含具有匹配System.Xml.Linq.XName 的 System.Xml.Linq.XContainer 的子级,或者非空默认值。 + public static IEnumerable Elements(this XContainer xContainer, XName xName, bool t) + { + IEnumerable info; + if (xContainer == null) + { + info = null; + } + else + { + info = xContainer.Elements(xName); + } + + if (t && info == null) + { + info = new List(); + } + + return info; + } + + /// + /// 删除html标签。 + /// + /// 输入的字符串。 + /// 没有html标签的字符串。 + public static string RemoveHTMLTags(this string html) + { + return Regex + .Replace( + Regex.Replace( + Regex.Replace( + (html ?? string.Empty).Replace(" ", " ").Replace("\r\n", " ").Replace("\n", " ") + .Replace("\r", " ").Replace("\t", " "), "<\\/?[^>]+>", "\r\n"), "(\r\n)+", "\r\n"), + "(\\s)+", " ").Trim(); + } + + /// + /// 字符串转换为文件名。 + /// + /// 字符串。 + /// 文件名。 + public static string ToFileName(this string s) + { + return Regex.Replace(s.ToString(string.Empty), @"[\\/:*?<>|]", "_").Replace("\t", " ").Replace("\r\n", " ") + .Replace("\"", " "); + } + + /// + /// 获取星期一的日期。 + /// + /// 日期。 + /// 星期一的日期。 + public static DateTime? GetMonday(this DateTime dateTime) + { + return dateTime.AddDays(-1 * (int)dateTime.AddDays(-1).DayOfWeek).ToString("yyyy-MM-dd").GetDateTime(); + } + + /// + /// 获取默认非空字符串。 + /// + /// 首选默认非空字符串。 + /// 依次非空字符串可选项。 + /// 默认非空字符串。若无可选项则返回string.Empty。 + public static string DefaultStringIfEmpty(this string s, params string[] args) + { + if (string.IsNullOrEmpty(s)) + { + foreach (string i in args) + { + if (!string.IsNullOrEmpty(i) && !string.IsNullOrEmpty(i.Trim())) + { + return i; + } + } + } + + return s ?? string.Empty; + } + + /// + /// 对 URL 字符串进行编码。 + /// + /// 要编码的文本。 + /// 匹配要编码的文本。 + /// 指定编码方案的 System.Text.Encoding 对象。 + /// 一个已编码的字符串。 + public static string ToUrlEncodeString(this string s, Regex regex = default(Regex), Encoding encoding = null) + { + if (encoding == null) + { + encoding = Encoding.UTF8; + } + + if (regex == null) + { + return HttpUtility.UrlEncode(s, encoding); + } + + List l = new List(); + foreach (char i in s) + { + string t = i.ToString(); + l.Add(regex.IsMatch(t) ? HttpUtility.UrlEncode(t, encoding) : t); + } + + return string.Join(string.Empty, l); + } + + /// + /// 对 URL 字符串进行编码。 + /// + /// 要编码的文本。 + /// 匹配要编码的文本。 + /// 指定编码方案的 System.Text.Encoding 对象。 + /// 一个已编码的字符串。 + public static string ToUrlEncodeString(this string s, string regex, Encoding encoding = null) + { + return ToUrlEncodeString(s, new Regex(regex), encoding); + } + + /// + /// 将日期转换为UNIX时间戳字符串 + /// + /// + /// + public static string ToUnixTimeStamp(this DateTime date) + { + DateTime startTime = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1)); + string timeStamp = date.Subtract(startTime).Ticks.ToString(); + return timeStamp.Substring(0, timeStamp.Length - 7); + } + + /// + /// + /// + /// + /// + /// + public static string Join(this IEnumerable source, string separator) + { + return string.Join(separator, source); + } + + private static readonly Regex MobileRegex = new Regex("^1[3|4|5|7|8][0-9]\\d{4,8}$"); + + private static readonly Regex EmailRegex = + new Regex("^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$"); + + /// + /// 判断当前字符串是否是移动电话号码 + /// + /// + /// + public static bool IsMobile(this string mobile) + { + return MobileRegex.IsMatch(mobile); + } + + /// + /// 判断当前字符串是否为邮箱 + /// + /// + /// + public static bool IsEmail(this string email) + { + return EmailRegex.IsMatch(email); + } + + /// + /// 把对象类型转换为指定类型 + /// + /// + /// + /// + public static object CastTo(this object value, Type conversionType) + { + if (value == null) + { + return null; + } + + if (conversionType.IsNullableType()) + { + conversionType = conversionType.GetUnNullableType(); + } + + if (conversionType.IsEnum) + { + return Enum.Parse(conversionType, value.ToString()); + } + + if (conversionType == typeof(Guid)) + { + return Guid.Parse(value.ToString()); + } + + return Convert.ChangeType(value, conversionType); + } + + /// + /// 把对象类型转化为指定类型 + /// + /// 动态类型 + /// 要转化的源对象 + /// 转化后的指定类型的对象,转化失败引发异常。 + public static T CastTo(this object value) + { + if (value == null && default(T) == null) + { + return default(T); + } + + if (value.GetType() == typeof(T)) + { + return (T)value; + } + + object result = CastTo(value, typeof(T)); + return (T)result; + } + + /// + /// 把对象类型转化为指定类型,转化失败时返回指定的默认值 + /// + /// 动态类型 + /// 要转化的源对象 + /// 转化失败返回的指定默认值 + /// 转化后的指定类型对象,转化失败时返回指定的默认值 + public static T CastTo(this object value, T defaultValue) + { + try + { + return CastTo(value); + } + catch (Exception) + { + return defaultValue; + } + } + + /// + /// 将对象保存为csv + /// + /// + /// + /// 文件名称 + /// 分隔符,默认逗号 + public static void SaveToCsv(this IEnumerable source, string csvFullName, string separator = ",") + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (string.IsNullOrEmpty(separator)) + { + separator = ","; + } + + string csv = string.Join(separator, source); + using (StreamWriter sw = new StreamWriter(csvFullName, false)) + { + sw.Write(csv); + sw.Close(); + } + } + + /// + /// + /// + /// + /// + /// + public static bool IsImplement(this Type entityType, Type interfaceType) + { + return /*entityType.IsClass && !entityType.IsAbstract &&*/ entityType.GetTypeInfo().GetInterfaces().Any(t => + t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == interfaceType); + } + + /// + /// 将对象转为DataTable + /// + /// + /// + /// + public static DataTable ToDataTable(this IEnumerable source) + { + DataTable dtReturn = new DataTable(); + + if (source == null) + { + return dtReturn; + } + // column names + PropertyInfo[] oProps = null; + + foreach (T rec in source) + { + // Use reflection to get property names, to create table, Only first time, others will follow + if (oProps == null) + { + oProps = rec.GetType().GetProperties(); + foreach (PropertyInfo pi in oProps) + { + Type colType = pi.PropertyType; + + if (colType.IsNullableType()) + { + colType = colType.GetGenericArguments()[0]; + } + + if (colType == typeof(bool)) + { + colType = typeof(int); + } + + dtReturn.Columns.Add(new DataColumn(pi.Name, colType)); + } + } + + DataRow dr = dtReturn.NewRow(); + + foreach (PropertyInfo pi in oProps) + { + object value = pi.GetValue(rec, null) ?? DBNull.Value; + if (value is bool) + { + dr[pi.Name] = (bool)value ? 1 : 0; + } + else + { + dr[pi.Name] = value; + } + } + + dtReturn.Rows.Add(dr); + } + + return dtReturn; + } + } + + /// + /// 结果。 + /// + /// 结果返回值类型。 + public class Result + { + /// + /// 标记。 + /// + public Flag Flag { get; set; } + + /// + /// 返回值。 + /// + public T Return { get; set; } + + /// + /// 消息。 + /// + public string Message { get; set; } + + /// + /// 异常。 + /// + public Exception Exception { get; set; } + + /// + /// 时间。 + /// + public DateTime DateTime { get; set; } + + /// + /// 整型数据。 + /// + public int Int { get; set; } + + /// + /// 浮点数据。 + /// + public decimal Decimal { get; set; } + + /// + /// 布尔数据。 + /// + public bool Bool { get; set; } + + /// + /// 对象。 + /// + public object Object { get; set; } + } + + /// + /// 标记。 + /// + public enum Flag + { + /// + /// 默认。 + /// + Default, + + /// + /// 真。 + /// + True, + + /// + /// 假。 + /// + False + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ParameterCheckExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ParameterCheckExtensions.cs new file mode 100644 index 0000000..3db7132 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/ParameterCheckExtensions.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Znyc.Admin.Commons.Properties; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// 用于参数检查的扩展方法 + /// + public static class ParameterCheckExtensions + { + /// + /// 验证指定值的断言是否为真,如果不为真,抛出指定消息的指定类型异常 + /// + /// 异常类型 + /// 要验证的断言。 + /// 异常消息。 + private static void Require(bool assertion, string message) where TException : Exception + { + if (assertion) + { + return; + } + + if (string.IsNullOrEmpty(message)) + { + throw new ArgumentNullException("message"); + } + + TException exception = (TException)Activator.CreateInstance(typeof(TException), message); + throw exception; + } + + /// + /// 验证指定值的断言表达式是否为真,不为值抛出异常 + /// + /// + /// 要验证的断言表达式 + /// 异常消息 + public static void Required(this T value, Func assertionFunc, string message) + { + if (assertionFunc == null) + { + throw new ArgumentNullException("assertionFunc"); + } + + Require(assertionFunc(value), message); + } + + /// + /// 验证指定值的断言表达式是否为真,不为真抛出异常 + /// + /// 要判断的值的类型 + /// 抛出的异常类型 + /// 要判断的值 + /// 要验证的断言表达式 + /// 异常消息 + public static void Required(this T value, Func assertionFunc, string message) + where TException : Exception + { + if (assertionFunc == null) + { + throw new ArgumentNullException("assertionFunc"); + } + + Require(assertionFunc(value), message); + } + + /// + /// 检查参数不能为空引用,否则抛出异常。 + /// + /// + /// 参数名称 + /// + public static void CheckNotNull(this T value, string paramName) where T : class + { + Require(value != null, string.Format(Resources.ParameterCheck_NotNull, paramName)); + } + + /// + /// 检查字符串不能为空引用或空字符串,否则抛出异常或异常。 + /// + /// + /// 参数名称。 + /// + /// + public static void CheckNotNullOrEmpty(this string value, string paramName) + { + value.CheckNotNull(paramName); + Require(value.Length > 0, + string.Format(Resources.ParameterCheck_NotNullOrEmpty_String, paramName)); + } + + /// + /// 检查Guid值不能为Guid.Empty,否则抛出异常。 + /// + /// + /// 参数名称。 + /// + public static void CheckNotEmpty(this Guid value, string paramName) + { + Require(value != Guid.Empty, + string.Format(Resources.ParameterCheck_NotEmpty_Guid, paramName)); + } + + /// + /// 检查集合不能为空引用或空集合,否则抛出异常或异常。 + /// + /// 集合项的类型。 + /// + /// 参数名称。 + /// + /// + public static void CheckNotNullOrEmpty(this IEnumerable collection, string paramName) + { + collection.CheckNotNull(paramName); + Require(collection.Any(), + string.Format(Resources.ParameterCheck_NotNullOrEmpty_Collection, paramName)); + } + + /// + /// 检查参数必须小于[或可等于,参数canEqual]指定值,否则抛出异常。 + /// + /// 参数类型。 + /// + /// 参数名称。 + /// 要比较的值。 + /// 是否可等于。 + /// + public static void CheckLessThan(this T value, string paramName, T target, bool canEqual = false) + where T : IComparable + { + bool flag = canEqual ? value.CompareTo(target) <= 0 : value.CompareTo(target) < 0; + string format = canEqual ? Resources.ParameterCheck_NotLessThanOrEqual : Resources.ParameterCheck_NotLessThan; + Require(flag, string.Format(format, paramName, target)); + } + + /// + /// 检查参数必须大于[或可等于,参数canEqual]指定值,否则抛出异常。 + /// + /// 参数类型。 + /// + /// 参数名称。 + /// 要比较的值。 + /// 是否可等于。 + /// + public static void CheckGreaterThan(this T value, string paramName, T target, bool canEqual = false) + where T : IComparable + { + bool flag = canEqual ? value.CompareTo(target) >= 0 : value.CompareTo(target) > 0; + string format = canEqual + ? Resources.ParameterCheck_NotGreaterThanOrEqual + : Resources.ParameterCheck_NotGreaterThan; + Require(flag, string.Format(format, paramName, target)); + } + + /// + /// 检查参数必须在指定范围之间,否则抛出异常。 + /// + /// 参数类型。 + /// + /// 参数名称。 + /// 比较范围的起始值。 + /// 比较范围的结束值。 + /// 是否可等于起始值 + /// 是否可等于结束值 + /// + public static void CheckBetween(this T value, string paramName, T start, T end, bool startEqual = false, + bool endEqual = false) + where T : IComparable + { + bool flag = startEqual ? value.CompareTo(start) >= 0 : value.CompareTo(start) > 0; + string message = startEqual + ? string.Format(Resources.ParameterCheck_Between, paramName, start, end) + : string.Format(Resources.ParameterCheck_BetweenNotEqual, paramName, start, end, start); + Require(flag, message); + + flag = endEqual ? value.CompareTo(end) <= 0 : value.CompareTo(end) < 0; + message = endEqual + ? string.Format(Resources.ParameterCheck_Between, paramName, start, end) + : string.Format(Resources.ParameterCheck_BetweenNotEqual, paramName, start, end, end); + Require(flag, message); + } + + /// + /// 检查指定路径的文件夹必须存在,否则抛出异常。 + /// + /// + /// 参数名称。 + /// + /// + public static void CheckDirectoryExists(this string directory, string paramName = null) + { + CheckNotNull(directory, paramName); + Require(Directory.Exists(directory), + string.Format(Resources.ParameterCheck_DirectoryNotExists, directory)); + } + + /// + /// 检查指定路径的文件必须存在,否则抛出异常。 + /// + /// + /// 参数名称。 + /// 当文件路径为null时 + /// 当文件路径不存在时 + public static void CheckFileExists(this string filename, string paramName = null) + { + CheckNotNull(filename, paramName); + Require(File.Exists(filename), + string.Format(Resources.ParameterCheck_FileNotExists, filename)); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SessionExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SessionExtensions.cs new file mode 100644 index 0000000..e1500f7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SessionExtensions.cs @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using Microsoft.AspNetCore.Http; +using Newtonsoft.Json; +using System.Text; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// Session 扩展函数,直接将实体类序列化成json存储和读取 + /// + public static class SessionExtensions + { + /// + /// 设置session值 + /// + /// + /// + /// + public static void Set(this ISession session, string key, object value) + { + session.SetString(key, JsonConvert.SerializeObject(value)); + } + + /// + /// 获取session + /// + /// + /// + /// + /// + public static T Get(this ISession session, string key) + { + string value = session.GetString(key); + + return value == null ? default(T) : JsonConvert.DeserializeObject(value); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SqlMapperExtensions.Async.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SqlMapperExtensions.Async.cs new file mode 100644 index 0000000..a1e497f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SqlMapperExtensions.Async.cs @@ -0,0 +1,788 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Dapper.Contrib.Extensions +{ + /// + /// 修改mysql新增数据时返回影响记录数 + /// + public static partial class SqlMapperExtensions + { + /// + /// Returns a single entity by a single id from table "Ts" asynchronously using Task. T must be of interface type. + /// Id must be marked with [Key] attribute. + /// Created entity is tracked/intercepted for changes and used by the Update() extension. + /// + /// Interface type to create and populate + /// Open SqlConnection + /// Id of the entity to get, must be marked with [Key] attribute + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// Entity of T + public static async Task GetAsync(this IDbConnection connection, dynamic id, + IDbTransaction transaction = null, int? commandTimeout = null) where T : class + { + Type type = typeof(T); + if (!GetQueries.TryGetValue(type.TypeHandle, out string sql)) + { + PropertyInfo key = GetSingleKey(nameof(GetAsync)); + string name = GetTableName(type); + sql = $"SELECT * FROM {name} WHERE {key.Name} = @keyName"; + GetQueries[type.TypeHandle] = sql; + } + + DynamicParameters dynParms = new DynamicParameters(); + dynParms.Add("@keyName", id); + + if (!type.IsInterface) + { + return (await connection.QueryAsync(sql, dynParms, transaction, commandTimeout) + .ConfigureAwait(false)).FirstOrDefault(); + } + + IDictionary res = + (await connection.QueryAsync(sql, dynParms).ConfigureAwait(false)).FirstOrDefault() as + IDictionary; + + if (res == null) + { + return null; + } + + T obj = ProxyGenerator.GetInterfaceProxy(); + + foreach (PropertyInfo property in TypePropertiesCache(type)) + { + object val = res[property.Name]; + if (val == null) + { + continue; + } + + if (property.PropertyType.IsGenericType && + property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + Type genericType = Nullable.GetUnderlyingType(property.PropertyType); + if (genericType != null) + { + property.SetValue(obj, Convert.ChangeType(val, genericType), null); + } + } + else + { + property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null); + } + } + + ((IProxy)obj).IsDirty = false; //reset change tracking and return + + return obj; + } + + /// + /// Returns a list of entites from table "Ts". + /// Id of T must be marked with [Key] attribute. + /// Entities created from interfaces are tracked/intercepted for changes and used by the Update() extension + /// for optimal performance. + /// + /// Interface or type to create and populate + /// Open SqlConnection + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// Entity of T + public static Task> GetAllAsync(this IDbConnection connection, + IDbTransaction transaction = null, int? commandTimeout = null) where T : class + { + Type type = typeof(T); + Type cacheType = typeof(List); + + if (!GetQueries.TryGetValue(cacheType.TypeHandle, out string sql)) + { + GetSingleKey(nameof(GetAll)); + string name = GetTableName(type); + + sql = "SELECT * FROM " + name; + GetQueries[cacheType.TypeHandle] = sql; + } + + if (!type.IsInterface) + { + return connection.QueryAsync(sql, null, transaction, commandTimeout); + } + + return GetAllAsyncImpl(connection, transaction, commandTimeout, sql, type); + } + + private static async Task> GetAllAsyncImpl(IDbConnection connection, + IDbTransaction transaction, int? commandTimeout, string sql, Type type) where T : class + { + IEnumerable result = await connection.QueryAsync(sql).ConfigureAwait(false); + List list = new List(); + foreach (IDictionary res in result) + { + T obj = ProxyGenerator.GetInterfaceProxy(); + foreach (PropertyInfo property in TypePropertiesCache(type)) + { + object val = res[property.Name]; + if (val == null) + { + continue; + } + + if (property.PropertyType.IsGenericType && + property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + Type genericType = Nullable.GetUnderlyingType(property.PropertyType); + if (genericType != null) + { + property.SetValue(obj, Convert.ChangeType(val, genericType), null); + } + } + else + { + property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null); + } + } + + ((IProxy)obj).IsDirty = false; //reset change tracking and return + list.Add(obj); + } + + return list; + } + + /// + /// Inserts an entity into table "Ts" asynchronously using Task and returns identity id. + /// + /// The type being inserted. + /// Open SqlConnection + /// Entity to insert + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// The specific ISqlAdapter to use, auto-detected based on connection if null + /// Identity of inserted entity + public static async Task InsertAsync(this IDbConnection connection, T entityToInsert, + IDbTransaction transaction = null, + int? commandTimeout = null, ISqlAdapter sqlAdapter = null) where T : class + { + Type type = typeof(T); + sqlAdapter = sqlAdapter ?? GetFormatter(connection); + + bool isList = false; + if (type.IsArray) + { + isList = true; + type = type.GetElementType(); + } + else if (type.IsGenericType) + { + TypeInfo typeInfo = type.GetTypeInfo(); + bool implementsGenericIEnumerableOrIsGenericIEnumerable = + typeInfo.ImplementedInterfaces.Any(ti => + ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + if (implementsGenericIEnumerableOrIsGenericIEnumerable) + { + isList = true; + type = type.GetGenericArguments()[0]; + } + } + + string name = GetTableName(type); + StringBuilder sbColumnList = new StringBuilder(null); + List allProperties = TypePropertiesCache(type); + List keyProperties = KeyPropertiesCache(type).ToList(); + List computedProperties = ComputedPropertiesCache(type); + List allPropertiesExceptKeyAndComputed = + allProperties.ToList(); //.Except(keyProperties.Union(computedProperties)).ToList(); + + for (int i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++) + { + PropertyInfo property = allPropertiesExceptKeyAndComputed[i]; + sqlAdapter.AppendColumnName(sbColumnList, property.Name); + if (i < allPropertiesExceptKeyAndComputed.Count - 1) + { + sbColumnList.Append(", "); + } + } + + StringBuilder sbParameterList = new StringBuilder(null); + for (int i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++) + { + PropertyInfo property = allPropertiesExceptKeyAndComputed[i]; + sbParameterList.AppendFormat("@{0}", property.Name); + if (i < allPropertiesExceptKeyAndComputed.Count - 1) + { + sbParameterList.Append(", "); + } + } + + int returnVal = 0; + bool wasClosed = connection.State == ConnectionState.Closed; + if (wasClosed) + { + connection.Open(); + } + + if (!isList) //single entity + { + returnVal = await sqlAdapter.InsertAsync(connection, transaction, commandTimeout, name, + sbColumnList.ToString(), + sbParameterList.ToString(), keyProperties, entityToInsert); + } + else + { + //insert list of entities + string cmd = $"insert into {name} ({sbColumnList}) values ({sbParameterList})"; + returnVal = await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout); + } + + if (wasClosed) + { + connection.Close(); + } + + return returnVal; + } + + /// + /// Inserts an entity into table "Ts" asynchronously using Task and returns identity id. + /// + /// The type being inserted. + /// Open SqlConnection + /// Entity to insert + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// The specific ISqlAdapter to use, auto-detected based on connection if null + /// Identity of inserted entity + public static async Task InsertReturnPrimaryKeyAsync(this IDbConnection connection, T entityToInsert, + IDbTransaction transaction = null, + int? commandTimeout = null, ISqlAdapter sqlAdapter = null) where T : class + { + Type type = typeof(T); + sqlAdapter = sqlAdapter ?? GetFormatter(connection); + if (type.IsArray) + { + type = type.GetElementType(); + } + else if (type.IsGenericType) + { + TypeInfo typeInfo = type.GetTypeInfo(); + bool implementsGenericIEnumerableOrIsGenericIEnumerable = + typeInfo.ImplementedInterfaces.Any(ti => + ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + if (implementsGenericIEnumerableOrIsGenericIEnumerable) + { + type = type.GetGenericArguments()[0]; + } + } + + string name = GetTableName(type); + StringBuilder sbColumnList = new StringBuilder(null); + List allProperties = TypePropertiesCache(type); + List keyProperties = KeyPropertiesCache(type).ToList(); + List computedProperties = ComputedPropertiesCache(type); + List allPropertiesExceptKeyAndComputed = + allProperties.ToList(); //.Except(keyProperties.Union(computedProperties)).ToList(); + + for (int i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++) + { + PropertyInfo property = allPropertiesExceptKeyAndComputed[i]; + sqlAdapter.AppendColumnName(sbColumnList, property.Name); + if (i < allPropertiesExceptKeyAndComputed.Count - 1) + { + sbColumnList.Append(", "); + } + } + + StringBuilder sbParameterList = new StringBuilder(null); + for (int i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++) + { + PropertyInfo property = allPropertiesExceptKeyAndComputed[i]; + sbParameterList.AppendFormat("@{0}", property.Name); + if (i < allPropertiesExceptKeyAndComputed.Count - 1) + { + sbParameterList.Append(", "); + } + } + + long returnVal = 0; + bool wasClosed = connection.State == ConnectionState.Closed; + if (wasClosed) + { + connection.Open(); + } + + //if (!isList) //single entity + //{ + // returnVal = await sqlAdapter.(connection, transaction, commandTimeout, name, + // sbColumnList.ToString(), + // sbParameterList.ToString(), keyProperties, entityToInsert); + //} + //else + //{ + //insert list of entities + string cmd = $"insert into {name} ({sbColumnList}) values ({sbParameterList});SELECT LAST_INSERT_ID();"; + returnVal = await connection.ExecuteScalarAsync(cmd, entityToInsert, transaction, commandTimeout); + // } + + if (wasClosed) + { + connection.Close(); + } + + return returnVal; + } + + /// + /// Updates entity in table "Ts" asynchronously using Task, checks if the entity is modified if the entity is tracked by the Get() extension. + /// + /// Type to be updated + /// Open SqlConnection + /// Entity to be updated + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// true if updated, false if not found or not modified (tracked entities) + public static async Task UpdateAsync(this IDbConnection connection, T entityToUpdate, + IDbTransaction transaction = null, int? commandTimeout = null) where T : class + { + if (entityToUpdate is IProxy proxy && !proxy.IsDirty) + { + return false; + } + + Type type = typeof(T); + + if (type.IsArray) + { + type = type.GetElementType(); + } + else if (type.IsGenericType) + { + TypeInfo typeInfo = type.GetTypeInfo(); + bool implementsGenericIEnumerableOrIsGenericIEnumerable = + typeInfo.ImplementedInterfaces.Any(ti => + ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + if (implementsGenericIEnumerableOrIsGenericIEnumerable) + { + type = type.GetGenericArguments()[0]; + } + } + + List keyProperties = KeyPropertiesCache(type).ToList(); + List explicitKeyProperties = ExplicitKeyPropertiesCache(type); + if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0) + { + throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property"); + } + + string name = GetTableName(type); + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("update {0} set ", name); + + List allProperties = TypePropertiesCache(type); + keyProperties.AddRange(explicitKeyProperties); + List computedProperties = ComputedPropertiesCache(type); + List nonIdProps = allProperties.Except(keyProperties.Union(computedProperties)).ToList(); + + ISqlAdapter adapter = GetFormatter(connection); + + for (int i = 0; i < nonIdProps.Count; i++) + { + PropertyInfo property = nonIdProps[i]; + adapter.AppendColumnNameEqualsValue(sb, property.Name); + if (i < nonIdProps.Count - 1) + { + sb.Append(", "); + } + } + + sb.Append(" where "); + for (int i = 0; i < keyProperties.Count; i++) + { + PropertyInfo property = keyProperties[i]; + adapter.AppendColumnNameEqualsValue(sb, property.Name); + if (i < keyProperties.Count - 1) + { + sb.Append(" and "); + } + } + + int updated = await connection + .ExecuteAsync(sb.ToString(), entityToUpdate, commandTimeout: commandTimeout, transaction: transaction) + .ConfigureAwait(false); + return updated > 0; + } + + /// + /// Delete entity in table "Ts" asynchronously using Task. + /// + /// Type of entity + /// Open SqlConnection + /// Entity to delete + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// true if deleted, false if not found + public static async Task DeleteAsync(this IDbConnection connection, T entityToDelete, + IDbTransaction transaction = null, int? commandTimeout = null) where T : class + { + if (entityToDelete == null) + { + throw new ArgumentException("Cannot Delete null Object", nameof(entityToDelete)); + } + + Type type = typeof(T); + + if (type.IsArray) + { + type = type.GetElementType(); + } + else if (type.IsGenericType) + { + TypeInfo typeInfo = type.GetTypeInfo(); + bool implementsGenericIEnumerableOrIsGenericIEnumerable = + typeInfo.ImplementedInterfaces.Any(ti => + ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + if (implementsGenericIEnumerableOrIsGenericIEnumerable) + { + type = type.GetGenericArguments()[0]; + } + } + + List keyProperties = KeyPropertiesCache(type); + List explicitKeyProperties = ExplicitKeyPropertiesCache(type); + if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0) + { + throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property"); + } + + string name = GetTableName(type); + keyProperties.AddRange(explicitKeyProperties); + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("DELETE FROM {0} WHERE ", name); + + ISqlAdapter adapter = GetFormatter(connection); + + for (int i = 0; i < keyProperties.Count; i++) + { + PropertyInfo property = keyProperties[i]; + adapter.AppendColumnNameEqualsValue(sb, property.Name); + if (i < keyProperties.Count - 1) + { + sb.Append(" AND "); + } + } + + int deleted = await connection.ExecuteAsync(sb.ToString(), entityToDelete, transaction, commandTimeout) + .ConfigureAwait(false); + return deleted > 0; + } + + /// + /// Delete all entities in the table related to the type T asynchronously using Task. + /// + /// Type of entity + /// Open SqlConnection + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// true if deleted, false if none found + public static async Task DeleteAllAsync(this IDbConnection connection, + IDbTransaction transaction = null, int? commandTimeout = null) where T : class + { + Type type = typeof(T); + string statement = "DELETE FROM " + GetTableName(type); + int deleted = await connection.ExecuteAsync(statement, null, transaction, commandTimeout) + .ConfigureAwait(false); + return deleted > 0; + } + } +} + +public partial interface ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert); +} + +public partial class SqlServerAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, + string tableName, string columnList, string parameterList, IEnumerable keyProperties, + object entityToInsert) + { + string cmd = $"INSERT INTO {tableName} ({columnList}) values ({parameterList}); select @@ROWCOUNT num"; + SqlMapper.GridReader multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout) + .ConfigureAwait(false); + + dynamic first = multi.Read().FirstOrDefault(); + if (first == null || first.num == null) + { + return 0; + } + + int num = (int)first.num; + + return num; + } +} + +public partial class SqlCeServerAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, + string tableName, string columnList, string parameterList, IEnumerable keyProperties, + object entityToInsert) + { + string cmd = $"INSERT INTO {tableName} ({columnList}) values ({parameterList}); select @@ROWCOUNT num"; + SqlMapper.GridReader multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout) + .ConfigureAwait(false); + + dynamic first = multi.Read().FirstOrDefault(); + if (first == null || first.num == null) + { + return 0; + } + + int num = (int)first.num; + + return num; + } +} + +public partial class MySqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, + string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert) + { + string cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList});select ROW_COUNT() num"; + SqlMapper.GridReader multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout) + .ConfigureAwait(false); + + dynamic first = multi.Read().FirstOrDefault(); + if (first == null || first.num == null) + { + return 0; + } + + int num = (int)first.num; + + return num; + //await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false); + //var r = await connection.QueryAsync("SELECT LAST_INSERT_ID() id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false); + + //var id = r.First().id; + //if (id == null) return 0; + //var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); + //if (pi.Length == 0) return Convert.ToInt32(id); + + //var idp = pi[0]; + //idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null); + + //return Convert.ToInt32(id); + } +} + +public partial class PostgresAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, + string tableName, string columnList, string parameterList, IEnumerable keyProperties, + object entityToInsert) + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("INSERT INTO {0} ({1}) VALUES ({2})", tableName, columnList, parameterList); + + // If no primary key then safe to assume a join table with not too much data to return + PropertyInfo[] propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); + if (propertyInfos.Length == 0) + { + sb.Append(" RETURNING *"); + } + else + { + sb.Append(" RETURNING "); + bool first = true; + foreach (PropertyInfo property in propertyInfos) + { + if (!first) + { + sb.Append(", "); + } + + first = false; + sb.Append(property.Name); + } + } + + IEnumerable results = await connection.QueryAsync(sb.ToString(), entityToInsert, transaction, commandTimeout) + .ConfigureAwait(false); + + // Return the key by assinging the corresponding property in the object - by product is that it supports compound primary keys + int id = 0; + foreach (PropertyInfo p in propertyInfos) + { + object value = ((IDictionary)results.First())[p.Name.ToLower()]; + p.SetValue(entityToInsert, value, null); + if (id == 0) + { + id = Convert.ToInt32(value); + } + } + + return id; + } +} + +public partial class SQLiteAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, + string tableName, string columnList, string parameterList, IEnumerable keyProperties, + object entityToInsert) + { + string cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id"; + SqlMapper.GridReader multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout) + .ConfigureAwait(false); + + int id = (int)multi.Read().First().id; + PropertyInfo[] pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); + if (pi.Length == 0) + { + return id; + } + + PropertyInfo idp = pi[0]; + idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null); + + return id; + } +} + +public partial class FbAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, + string tableName, string columnList, string parameterList, IEnumerable keyProperties, + object entityToInsert) + { + string cmd = $"insert into {tableName} ({columnList}) values ({parameterList})"; + await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false); + + PropertyInfo[] propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); + string keyName = propertyInfos[0].Name; + IEnumerable r = await connection.QueryAsync($"SELECT FIRST 1 {keyName} ID FROM {tableName} ORDER BY {keyName} DESC", + transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false); + + dynamic id = r.First().ID; + if (id == null) + { + return 0; + } + + if (propertyInfos.Length == 0) + { + return Convert.ToInt32(id); + } + + PropertyInfo idp = propertyInfos[0]; + idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null); + + return Convert.ToInt32(id); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SqlMapperExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SqlMapperExtensions.cs new file mode 100644 index 0000000..acfa4d3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/SqlMapperExtensions.cs @@ -0,0 +1,1265 @@ +using Dapper; +using StackExchange.Profiling.Data; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; + +#if NETSTANDARD1_3 +using DataException = System.InvalidOperationException; +#endif + +namespace Dapper.Contrib.Extensions +{ + /// + /// The Dapper.Contrib extensions for Dapper + /// + public static partial class SqlMapperExtensions + { + /// + /// Defined a proxy object with a possibly dirty state. + /// + public interface IProxy //must be kept public + { + /// + /// Whether the object has been changed. + /// + bool IsDirty { get; set; } + } + + /// + /// Defines a table name mapper for getting table names from types. + /// + public interface ITableNameMapper + { + /// + /// Gets a table name from a given . + /// + /// The to get a name from. + /// The table name for the given . + string GetTableName(Type type); + } + + /// + /// The function to get a database type from the given . + /// + /// The connection to get a database type name from. + public delegate string GetDatabaseTypeDelegate(IDbConnection connection); + + /// + /// The function to get a a table name from a given + /// + /// The to get a table name for. + public delegate string TableNameMapperDelegate(Type type); + + private static readonly ConcurrentDictionary> KeyProperties = + new ConcurrentDictionary>(); + + private static readonly ConcurrentDictionary> ExplicitKeyProperties + = new ConcurrentDictionary>(); + + private static readonly ConcurrentDictionary> TypeProperties = + new ConcurrentDictionary>(); + + private static readonly ConcurrentDictionary> ComputedProperties = + new ConcurrentDictionary>(); + + private static readonly ConcurrentDictionary GetQueries = + new ConcurrentDictionary(); + + private static readonly ConcurrentDictionary TypeTableName = + new ConcurrentDictionary(); + + private static readonly ISqlAdapter DefaultAdapter = new SqlServerAdapter(); + + private static readonly Dictionary AdapterDictionary + = new Dictionary + { + ["sqlconnection"] = new SqlServerAdapter(), + ["sqlceconnection"] = new SqlCeServerAdapter(), + ["npgsqlconnection"] = new PostgresAdapter(), + ["sqliteconnection"] = new SQLiteAdapter(), + ["mysqlconnection"] = new MySqlAdapter(), + ["fbconnection"] = new FbAdapter() + }; + + private static List ComputedPropertiesCache(Type type) + { + if (ComputedProperties.TryGetValue(type.TypeHandle, out IEnumerable pi)) + { + return pi.ToList(); + } + + List computedProperties = TypePropertiesCache(type) + .Where(p => p.GetCustomAttributes(true).Any(a => a is ComputedAttribute)).ToList(); + + ComputedProperties[type.TypeHandle] = computedProperties; + return computedProperties; + } + + private static List ExplicitKeyPropertiesCache(Type type) + { + if (ExplicitKeyProperties.TryGetValue(type.TypeHandle, out IEnumerable pi)) + { + return pi.ToList(); + } + + List explicitKeyProperties = TypePropertiesCache(type) + .Where(p => p.GetCustomAttributes(true).Any(a => a is ExplicitKeyAttribute)).ToList(); + + ExplicitKeyProperties[type.TypeHandle] = explicitKeyProperties; + return explicitKeyProperties; + } + + /// + /// 查询主键,属性加了Key标签 + /// + /// + /// + private static List KeyPropertiesCache(Type type) + { + if (KeyProperties.TryGetValue(type.TypeHandle, out IEnumerable pi)) + { + return pi.ToList(); + } + + List allProperties = TypePropertiesCache(type); + List keyProperties = allProperties.Where(p => p.GetCustomAttributes(true).Any(a => a is KeyAttribute)) + .ToList(); + + if (keyProperties.Count == 0) + { + PropertyInfo idProp = allProperties.Find(p => + string.Equals(p.Name, "Id", StringComparison.CurrentCultureIgnoreCase)); + if (idProp != null && !idProp.GetCustomAttributes(true).Any(a => a is ExplicitKeyAttribute)) + { + keyProperties.Add(idProp); + } + } + + KeyProperties[type.TypeHandle] = keyProperties; + return keyProperties; + } + + private static List TypePropertiesCache(Type type) + { + if (TypeProperties.TryGetValue(type.TypeHandle, out IEnumerable pis)) + { + return pis.ToList(); + } + + PropertyInfo[] properties = type.GetProperties().Where(IsWriteable).ToArray(); + TypeProperties[type.TypeHandle] = properties; + return properties.ToList(); + } + + private static bool IsWriteable(PropertyInfo pi) + { + List attributes = pi.GetCustomAttributes(typeof(WriteAttribute), false).AsList(); + if (attributes.Count != 1) + { + return true; + } + + WriteAttribute writeAttribute = (WriteAttribute)attributes[0]; + return writeAttribute.Write; + } + + private static PropertyInfo GetSingleKey(string method) + { + Type type = typeof(T); + List keys = KeyPropertiesCache(type); + //var explicitKeys = ExplicitKeyPropertiesCache(type); + int keyCount = keys.Count; // + explicitKeys.Count; + if (keyCount > 1) + { + throw new DataException( + $"{method} only supports an entity with a single [Key] property. [Key] Count: {keys.Count}"); + } + + if (keyCount == 0) + { + throw new DataException($"{method} only supports an entity with a [Key] property"); + } + + return keys[0]; + } + + /// + /// Returns a single entity by a single id from table "Ts". + /// Id must be marked with [Key] attribute. + /// Entities created from interfaces are tracked/intercepted for changes and used by the Update() extension + /// for optimal performance. + /// + /// Interface or type to create and populate + /// Open SqlConnection + /// Id of the entity to get, must be marked with [Key] attribute + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// Entity of T + public static T Get(this IDbConnection connection, dynamic id, IDbTransaction transaction = null, + int? commandTimeout = null) where T : class + { + Type type = typeof(T); + + if (!GetQueries.TryGetValue(type.TypeHandle, out string sql)) + { + PropertyInfo key = GetSingleKey(nameof(Get)); + string name = GetTableName(type); + + sql = $"select * from {name} where {key.Name} = @KeyName"; + GetQueries[type.TypeHandle] = sql; + } + + DynamicParameters dynParms = new DynamicParameters(); + dynParms.Add("@KeyName", id); + + T obj; + + if (type.IsInterface) + { + IDictionary res = connection.Query(sql, dynParms).FirstOrDefault() as IDictionary; + + if (res == null) + { + return null; + } + + obj = ProxyGenerator.GetInterfaceProxy(); + + foreach (PropertyInfo property in TypePropertiesCache(type)) + { + object val = res[property.Name]; + if (val == null) + { + continue; + } + + if (property.PropertyType.IsGenericType && + property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + Type genericType = Nullable.GetUnderlyingType(property.PropertyType); + if (genericType != null) + { + property.SetValue(obj, Convert.ChangeType(val, genericType), null); + } + } + else + { + property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null); + } + } + + ((IProxy)obj).IsDirty = false; //reset change tracking and return + } + else + { + obj = connection.Query(sql, dynParms, transaction, commandTimeout: commandTimeout).FirstOrDefault(); + } + + return obj; + } + + /// + /// Returns a list of entites from table "Ts". + /// Id of T must be marked with [Key] attribute. + /// Entities created from interfaces are tracked/intercepted for changes and used by the Update() extension + /// for optimal performance. + /// + /// Interface or type to create and populate + /// Open SqlConnection + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// Entity of T + public static IEnumerable GetAll(this IDbConnection connection, IDbTransaction transaction = null, + int? commandTimeout = null) where T : class + { + Type type = typeof(T); + Type cacheType = typeof(List); + + if (!GetQueries.TryGetValue(cacheType.TypeHandle, out string sql)) + { + GetSingleKey(nameof(GetAll)); + string name = GetTableName(type); + + sql = "select * from " + name; + GetQueries[cacheType.TypeHandle] = sql; + } + + if (!type.IsInterface) + { + return connection.Query(sql, null, transaction, commandTimeout: commandTimeout); + } + + IEnumerable result = connection.Query(sql); + List list = new List(); + foreach (IDictionary res in result) + { + T obj = ProxyGenerator.GetInterfaceProxy(); + foreach (PropertyInfo property in TypePropertiesCache(type)) + { + object val = res[property.Name]; + if (val == null) + { + continue; + } + + if (property.PropertyType.IsGenericType && + property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + Type genericType = Nullable.GetUnderlyingType(property.PropertyType); + if (genericType != null) + { + property.SetValue(obj, Convert.ChangeType(val, genericType), null); + } + } + else + { + property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null); + } + } + + ((IProxy)obj).IsDirty = false; //reset change tracking and return + list.Add(obj); + } + + return list; + } + + /// + /// Specify a custom table name mapper based on the POCO type name + /// + public static TableNameMapperDelegate TableNameMapper; + + private static string GetTableName(Type type) + { + if (TypeTableName.TryGetValue(type.TypeHandle, out string name)) + { + return name; + } + + if (TableNameMapper != null) + { + name = TableNameMapper(type); + } + else + { +#if NETSTANDARD1_3 + var info = type.GetTypeInfo(); +#else + Type info = type; +#endif + //NOTE: This as dynamic trick falls back to handle both our own Table-attribute as well as the one in EntityFramework + dynamic tableAttrName = + info.GetCustomAttribute(false)?.Name + ?? (info.GetCustomAttributes(false) + .FirstOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic)?.Name; + + if (tableAttrName != null) + { + name = tableAttrName; + } + else + { + name = type.Name + "s"; + if (type.IsInterface && name.StartsWith("I")) + { + name = name.Substring(1); + } + } + } + + TypeTableName[type.TypeHandle] = name; + return name; + } + + /// + /// Inserts an entity into table "Ts" and returns identity id or number of inserted rows if inserting a list. + /// + /// The type to insert. + /// Open SqlConnection + /// Entity to insert, can be list of entities + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// Identity of inserted entity, or number of inserted rows if inserting a list + public static long Insert(this IDbConnection connection, T entityToInsert, IDbTransaction transaction = null, + int? commandTimeout = null) where T : class + { + bool isList = false; + Type type = typeof(T); + + if (type.IsArray) + { + isList = true; + type = type.GetElementType(); + } + else if (type.IsGenericType) + { + TypeInfo typeInfo = type.GetTypeInfo(); + bool implementsGenericIEnumerableOrIsGenericIEnumerable = + typeInfo.ImplementedInterfaces.Any(ti => + ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + if (implementsGenericIEnumerableOrIsGenericIEnumerable) + { + isList = true; + type = type.GetGenericArguments()[0]; + } + } + + string name = GetTableName(type); + StringBuilder sbColumnList = new StringBuilder(null); + List allProperties = TypePropertiesCache(type); + List keyProperties = KeyPropertiesCache(type); + List computedProperties = ComputedPropertiesCache(type); + List allPropertiesExceptKeyAndComputed = + allProperties.ToList(); //.Except(keyProperties.Union(computedProperties)).ToList(); + + ISqlAdapter adapter = GetFormatter(connection); + + for (int i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++) + { + PropertyInfo property = allPropertiesExceptKeyAndComputed[i]; + adapter.AppendColumnName(sbColumnList, property.Name); //fix for issue #336 + if (i < allPropertiesExceptKeyAndComputed.Count - 1) + { + sbColumnList.Append(", "); + } + } + + StringBuilder sbParameterList = new StringBuilder(null); + for (int i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++) + { + PropertyInfo property = allPropertiesExceptKeyAndComputed[i]; + sbParameterList.AppendFormat("@{0}", property.Name); + if (i < allPropertiesExceptKeyAndComputed.Count - 1) + { + sbParameterList.Append(", "); + } + } + + int returnVal; + bool wasClosed = connection.State == ConnectionState.Closed; + if (wasClosed) + { + connection.Open(); + } + + if (!isList) //single entity + { + returnVal = adapter.Insert(connection, transaction, commandTimeout, name, sbColumnList.ToString(), + sbParameterList.ToString(), keyProperties, entityToInsert); + } + else + { + //insert list of entities + string cmd = $"insert into {name} ({sbColumnList}) values ({sbParameterList})"; + returnVal = connection.Execute(cmd, entityToInsert, transaction, commandTimeout); + } + + if (wasClosed) + { + connection.Close(); + } + + return returnVal; + } + + /// + /// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension. + /// + /// Type to be updated + /// Open SqlConnection + /// Entity to be updated + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// true if updated, false if not found or not modified (tracked entities) + public static bool Update(this IDbConnection connection, T entityToUpdate, IDbTransaction transaction = null, + int? commandTimeout = null) where T : class + { + if (entityToUpdate is IProxy proxy && !proxy.IsDirty) + { + return false; + } + + Type type = typeof(T); + + if (type.IsArray) + { + type = type.GetElementType(); + } + else if (type.IsGenericType) + { + TypeInfo typeInfo = type.GetTypeInfo(); + bool implementsGenericIEnumerableOrIsGenericIEnumerable = + typeInfo.ImplementedInterfaces.Any(ti => + ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + if (implementsGenericIEnumerableOrIsGenericIEnumerable) + { + type = type.GetGenericArguments()[0]; + } + } + + List keyProperties = + KeyPropertiesCache(type).ToList(); //added ToList() due to issue #418, must work on a list copy + List explicitKeyProperties = ExplicitKeyPropertiesCache(type); + if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0) + { + throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property"); + } + + string name = GetTableName(type); + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("update {0} set ", name); + + List allProperties = TypePropertiesCache(type); + keyProperties.AddRange(explicitKeyProperties); + List computedProperties = ComputedPropertiesCache(type); + List nonIdProps = allProperties.Except(keyProperties.Union(computedProperties)).ToList(); + + ISqlAdapter adapter = GetFormatter(connection); + + for (int i = 0; i < nonIdProps.Count; i++) + { + PropertyInfo property = nonIdProps[i]; + adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336 + if (i < nonIdProps.Count - 1) + { + sb.Append(", "); + } + } + + sb.Append(" where "); + for (int i = 0; i < keyProperties.Count; i++) + { + PropertyInfo property = keyProperties[i]; + adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336 + if (i < keyProperties.Count - 1) + { + sb.Append(" and "); + } + } + + int updated = connection.Execute(sb.ToString(), entityToUpdate, commandTimeout: commandTimeout, + transaction: transaction); + return updated > 0; + } + + /// + /// Delete entity in table "Ts". + /// + /// Type of entity + /// Open SqlConnection + /// Entity to delete + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// true if deleted, false if not found + public static bool Delete(this IDbConnection connection, T entityToDelete, IDbTransaction transaction = null, + int? commandTimeout = null) where T : class + { + if (entityToDelete == null) + { + throw new ArgumentException("Cannot Delete null Object", nameof(entityToDelete)); + } + + Type type = typeof(T); + + if (type.IsArray) + { + type = type.GetElementType(); + } + else if (type.IsGenericType) + { + TypeInfo typeInfo = type.GetTypeInfo(); + bool implementsGenericIEnumerableOrIsGenericIEnumerable = + typeInfo.ImplementedInterfaces.Any(ti => + ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + if (implementsGenericIEnumerableOrIsGenericIEnumerable) + { + type = type.GetGenericArguments()[0]; + } + } + + List keyProperties = + KeyPropertiesCache(type).ToList(); //added ToList() due to issue #418, must work on a list copy + List explicitKeyProperties = ExplicitKeyPropertiesCache(type); + if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0) + { + throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property"); + } + + string name = GetTableName(type); + keyProperties.AddRange(explicitKeyProperties); + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("delete from {0} where ", name); + + ISqlAdapter adapter = GetFormatter(connection); + + for (int i = 0; i < keyProperties.Count; i++) + { + PropertyInfo property = keyProperties[i]; + adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336 + if (i < keyProperties.Count - 1) + { + sb.Append(" and "); + } + } + + int deleted = connection.Execute(sb.ToString(), entityToDelete, transaction, commandTimeout); + return deleted > 0; + } + + /// + /// Delete all entities in the table related to the type T. + /// + /// Type of entity + /// Open SqlConnection + /// The transaction to run under, null (the default) if none + /// Number of seconds before command execution timeout + /// true if deleted, false if none found + public static bool DeleteAll(this IDbConnection connection, IDbTransaction transaction = null, + int? commandTimeout = null) where T : class + { + Type type = typeof(T); + string name = GetTableName(type); + string statement = $"delete from {name}"; + int deleted = connection.Execute(statement, null, transaction, commandTimeout); + return deleted > 0; + } + + /// + /// Specifies a custom callback that detects the database type instead of relying on the default strategy (the name of the connection type object). + /// Please note that this callback is global and will be used by all the calls that require a database specific adapter. + /// + public static GetDatabaseTypeDelegate GetDatabaseType; + + /// + /// 适配数据类型 + /// 2020-11-09 集成MiniProfiler + /// + /// + /// + private static ISqlAdapter GetFormatter(IDbConnection connection) + { + string name = GetDatabaseType?.Invoke(connection).ToLower() + ?? connection.GetType().Name.ToLower(); + if (name == "profileddbconnection") + { + ProfiledDbConnection pconn = (ProfiledDbConnection)connection; + name = pconn.WrappedConnection.GetType().Name.ToLower(); + } + + return !AdapterDictionary.ContainsKey(name) + ? DefaultAdapter + : AdapterDictionary[name]; + } + + private static class ProxyGenerator + { + private static readonly Dictionary TypeCache = new Dictionary(); + + private static AssemblyBuilder GetAsmBuilder(string name) + { + return AssemblyBuilder.DefineDynamicAssembly(new AssemblyName { Name = name }, AssemblyBuilderAccess.Run); + } + + public static T GetInterfaceProxy() + { + Type typeOfT = typeof(T); + + if (TypeCache.TryGetValue(typeOfT, out Type k)) + { + return (T)Activator.CreateInstance(k); + } + + AssemblyBuilder assemblyBuilder = GetAsmBuilder(typeOfT.Name); + + ModuleBuilder moduleBuilder = + assemblyBuilder.DefineDynamicModule("SqlMapperExtensions." + + typeOfT.Name); //NOTE: to save, add "asdasd.dll" parameter + + Type interfaceType = typeof(IProxy); + TypeBuilder typeBuilder = moduleBuilder.DefineType(typeOfT.Name + "_" + Guid.NewGuid(), + TypeAttributes.Public | TypeAttributes.Class); + typeBuilder.AddInterfaceImplementation(typeOfT); + typeBuilder.AddInterfaceImplementation(interfaceType); + + //create our _isDirty field, which implements IProxy + MethodInfo setIsDirtyMethod = CreateIsDirtyProperty(typeBuilder); + + // Generate a field for each property, which implements the T + foreach (PropertyInfo property in typeof(T).GetProperties()) + { + bool isId = property.GetCustomAttributes(true).Any(a => a is KeyAttribute); + CreateProperty(typeBuilder, property.Name, property.PropertyType, setIsDirtyMethod, isId); + } + +#if NETSTANDARD1_3 || NETSTANDARD2_0 + var generatedType = typeBuilder.CreateTypeInfo().AsType(); +#else + Type generatedType = typeBuilder.CreateType(); +#endif + + TypeCache.Add(typeOfT, generatedType); + return (T)Activator.CreateInstance(generatedType); + } + + private static MethodInfo CreateIsDirtyProperty(TypeBuilder typeBuilder) + { + Type propType = typeof(bool); + FieldBuilder field = typeBuilder.DefineField("_" + nameof(IProxy.IsDirty), propType, FieldAttributes.Private); + PropertyBuilder property = typeBuilder.DefineProperty(nameof(IProxy.IsDirty), + PropertyAttributes.None, + propType, + new[] { propType }); + + const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.NewSlot | + MethodAttributes.SpecialName + | MethodAttributes.Final | MethodAttributes.Virtual | + MethodAttributes.HideBySig; + + // Define the "get" and "set" accessor methods + MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_" + nameof(IProxy.IsDirty), + getSetAttr, + propType, + Type.EmptyTypes); + ILGenerator currGetIl = currGetPropMthdBldr.GetILGenerator(); + currGetIl.Emit(OpCodes.Ldarg_0); + currGetIl.Emit(OpCodes.Ldfld, field); + currGetIl.Emit(OpCodes.Ret); + MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_" + nameof(IProxy.IsDirty), + getSetAttr, + null, + new[] { propType }); + ILGenerator currSetIl = currSetPropMthdBldr.GetILGenerator(); + currSetIl.Emit(OpCodes.Ldarg_0); + currSetIl.Emit(OpCodes.Ldarg_1); + currSetIl.Emit(OpCodes.Stfld, field); + currSetIl.Emit(OpCodes.Ret); + + property.SetGetMethod(currGetPropMthdBldr); + property.SetSetMethod(currSetPropMthdBldr); + MethodInfo getMethod = typeof(IProxy).GetMethod("get_" + nameof(IProxy.IsDirty)); + MethodInfo setMethod = typeof(IProxy).GetMethod("set_" + nameof(IProxy.IsDirty)); + typeBuilder.DefineMethodOverride(currGetPropMthdBldr, getMethod); + typeBuilder.DefineMethodOverride(currSetPropMthdBldr, setMethod); + + return currSetPropMthdBldr; + } + + private static void CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propType, + MethodInfo setIsDirtyMethod, bool isIdentity) + { + //Define the field and the property + FieldBuilder field = typeBuilder.DefineField("_" + propertyName, propType, FieldAttributes.Private); + PropertyBuilder property = typeBuilder.DefineProperty(propertyName, + PropertyAttributes.None, + propType, + new[] { propType }); + + const MethodAttributes getSetAttr = MethodAttributes.Public + | MethodAttributes.Virtual + | MethodAttributes.HideBySig; + + // Define the "get" and "set" accessor methods + MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_" + propertyName, + getSetAttr, + propType, + Type.EmptyTypes); + + ILGenerator currGetIl = currGetPropMthdBldr.GetILGenerator(); + currGetIl.Emit(OpCodes.Ldarg_0); + currGetIl.Emit(OpCodes.Ldfld, field); + currGetIl.Emit(OpCodes.Ret); + + MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_" + propertyName, + getSetAttr, + null, + new[] { propType }); + + //store value in private field and set the isdirty flag + ILGenerator currSetIl = currSetPropMthdBldr.GetILGenerator(); + currSetIl.Emit(OpCodes.Ldarg_0); + currSetIl.Emit(OpCodes.Ldarg_1); + currSetIl.Emit(OpCodes.Stfld, field); + currSetIl.Emit(OpCodes.Ldarg_0); + currSetIl.Emit(OpCodes.Ldc_I4_1); + currSetIl.Emit(OpCodes.Call, setIsDirtyMethod); + currSetIl.Emit(OpCodes.Ret); + + //TODO: Should copy all attributes defined by the interface? + if (isIdentity) + { + Type keyAttribute = typeof(KeyAttribute); + ConstructorInfo myConstructorInfo = keyAttribute.GetConstructor(new Type[] { }); + CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(myConstructorInfo, new object[] { }); + property.SetCustomAttribute(attributeBuilder); + } + + property.SetGetMethod(currGetPropMthdBldr); + property.SetSetMethod(currSetPropMthdBldr); + MethodInfo getMethod = typeof(T).GetMethod("get_" + propertyName); + MethodInfo setMethod = typeof(T).GetMethod("set_" + propertyName); + typeBuilder.DefineMethodOverride(currGetPropMthdBldr, getMethod); + typeBuilder.DefineMethodOverride(currSetPropMthdBldr, setMethod); + } + } + } + + /// + /// Specifies that this field is a explicitly set primary key in the database + /// + [AttributeUsage(AttributeTargets.Property)] + public class ExplicitKeyAttribute : Attribute + { + } + + /// + /// Specifies whether a field is writable in the database. + /// + [AttributeUsage(AttributeTargets.Property)] + public class WriteAttribute : Attribute + { + /// + /// Specifies whether a field is writable in the database. + /// + /// Whether a field is writable in the database. + public WriteAttribute(bool write) + { + Write = write; + } + + /// + /// Whether a field is writable in the database. + /// + public bool Write { get; } + } + + /// + /// Specifies that this is a computed column. + /// + [AttributeUsage(AttributeTargets.Property)] + public class ComputedAttribute : Attribute + { + } +} + +/// +/// The interface for all Dapper.Contrib database operations +/// Implementing this is each provider's model. +/// +public partial interface ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert); + + /// + /// Adds the name of a column. + /// + /// The string builder to append to. + /// The column name. + void AppendColumnName(StringBuilder sb, string columnName); + + /// + /// Adds a column equality to a parameter. + /// + /// The string builder to append to. + /// The column name. + void AppendColumnNameEqualsValue(StringBuilder sb, string columnName); +} + +/// +/// The SQL Server database adapter. +/// +public partial class SqlServerAdapter : ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert) + { + string cmd = $"insert into {tableName} ({columnList}) values ({parameterList}); select @@ROWCOUNT num"; + SqlMapper.GridReader multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout); + + dynamic first = multi.Read().FirstOrDefault(); + if (first == null || first.num == null) + { + return 0; + } + + int num = (int)first.num; + return num; + } + + /// + /// Adds the name of a column. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnName(StringBuilder sb, string columnName) + { + sb.AppendFormat("[{0}]", columnName); + } + + /// + /// Adds a column equality to a parameter. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + { + sb.AppendFormat("[{0}] = @{1}", columnName, columnName); + } +} + +/// +/// The SQL Server Compact Edition database adapter. +/// +public partial class SqlCeServerAdapter : ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert) + { + string cmd = $"insert into {tableName} ({columnList}) values ({parameterList}); select @@ROWCOUNT num"; + SqlMapper.GridReader multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout); + + dynamic first = multi.Read().FirstOrDefault(); + if (first == null || first.num == null) + { + return 0; + } + + int num = (int)first.num; + return num; + } + + /// + /// Adds the name of a column. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnName(StringBuilder sb, string columnName) + { + sb.AppendFormat("[{0}]", columnName); + } + + /// + /// Adds a column equality to a parameter. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + { + sb.AppendFormat("[{0}] = @{1}", columnName, columnName); + } +} + +/// +/// The MySQL database adapter. +/// +public partial class MySqlAdapter : ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// 2020-11-09 影响行数改为Select ROW_COUNT() + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert) + { + string cmd = $"insert into {tableName} ({columnList}) values ({parameterList}); select ROW_COUNT() num"; + SqlMapper.GridReader multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout); + + dynamic first = multi.Read().FirstOrDefault(); + if (first == null || first.num == null) + { + return 0; + } + + int num = (int)first.num; + return num; + } + + /// + /// Adds the name of a column. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnName(StringBuilder sb, string columnName) + { + sb.AppendFormat("`{0}`", columnName); + } + + /// + /// Adds a column equality to a parameter. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + { + sb.AppendFormat("`{0}` = @{1}", columnName, columnName); + } +} + +/// +/// The Postgres database adapter. +/// +public partial class PostgresAdapter : ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert) + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList); + + // If no primary key then safe to assume a join table with not too much data to return + PropertyInfo[] propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); + if (propertyInfos.Length == 0) + { + sb.Append(" RETURNING *"); + } + else + { + sb.Append(" RETURNING "); + bool first = true; + foreach (PropertyInfo property in propertyInfos) + { + if (!first) + { + sb.Append(", "); + } + + first = false; + sb.Append(property.Name); + } + } + + List results = connection.Query(sb.ToString(), entityToInsert, transaction, commandTimeout: commandTimeout) + .ToList(); + + // Return the key by assinging the corresponding property in the object - by product is that it supports compound primary keys + int id = 0; + foreach (PropertyInfo p in propertyInfos) + { + object value = ((IDictionary)results[0])[p.Name.ToLower()]; + p.SetValue(entityToInsert, value, null); + if (id == 0) + { + id = Convert.ToInt32(value); + } + } + + return id; + } + + /// + /// Adds the name of a column. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnName(StringBuilder sb, string columnName) + { + sb.AppendFormat("\"{0}\"", columnName); + } + + /// + /// Adds a column equality to a parameter. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + { + sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName); + } +} + +/// +/// The SQLite database adapter. +/// +public partial class SQLiteAdapter : ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert) + { + string cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id"; + SqlMapper.GridReader multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout); + + int id = (int)multi.Read().First().id; + PropertyInfo[] propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); + if (propertyInfos.Length == 0) + { + return id; + } + + PropertyInfo idProperty = propertyInfos[0]; + idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null); + + return id; + } + + /// + /// Adds the name of a column. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnName(StringBuilder sb, string columnName) + { + sb.AppendFormat("\"{0}\"", columnName); + } + + /// + /// Adds a column equality to a parameter. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + { + sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName); + } +} + +/// +/// The Firebase SQL adapeter. +/// +public partial class FbAdapter : ISqlAdapter +{ + /// + /// Inserts into the database, returning the Id of the row created. + /// + /// The connection to use. + /// The transaction to use. + /// The command timeout to use. + /// The table to insert into. + /// The columns to set with this insert. + /// The parameters to set for this insert. + /// The key columns in this table. + /// The entity to insert. + /// The Id of the row created. + public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, + string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert) + { + string cmd = $"insert into {tableName} ({columnList}) values ({parameterList})"; + connection.Execute(cmd, entityToInsert, transaction, commandTimeout); + + PropertyInfo[] propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); + string keyName = propertyInfos[0].Name; + IEnumerable r = connection.Query($"SELECT FIRST 1 {keyName} ID FROM {tableName} ORDER BY {keyName} DESC", + transaction: transaction, commandTimeout: commandTimeout); + + dynamic id = r.First().ID; + if (id == null) + { + return 0; + } + + if (propertyInfos.Length == 0) + { + return Convert.ToInt32(id); + } + + PropertyInfo idp = propertyInfos[0]; + idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null); + + return Convert.ToInt32(id); + } + + /// + /// Adds the name of a column. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnName(StringBuilder sb, string columnName) + { + sb.AppendFormat("{0}", columnName); + } + + /// + /// Adds a column equality to a parameter. + /// + /// The string builder to append to. + /// The column name. + public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) + { + sb.AppendFormat("{0} = @{1}", columnName, columnName); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/TypeExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/TypeExtensions.cs new file mode 100644 index 0000000..274b6f7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/TypeExtensions.cs @@ -0,0 +1,426 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Data; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// 类型辅助扩展方法类 + /// + public static class TypeExtensions + { + /// + /// 判断当前类型是否可由指定类型派生 + /// + public static bool IsDeriveClassFrom(this Type type, bool canAbstract = false) + { + return IsDeriveClassFrom(type, typeof(TBaseType), canAbstract); + } + + /// + /// 判断当前类型是否可由指定类型派生 + /// + public static bool IsDeriveClassFrom(this Type type, Type baseType, bool canAbstract = false) + { + Check.NotNull(type, nameof(type)); + Check.NotNull(baseType, nameof(baseType)); + + return type.IsClass && !canAbstract && !type.IsAbstract && type.IsBaseOn(baseType); + } + + /// + /// 判断类型是否为Nullable类型 + /// + /// 要处理的类型 + /// 是返回True,不是返回False + public static bool IsNullableType(this Type type) + { + return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + } + + /// + /// 由类型的Nullable类型返回实际类型 + /// + /// 要处理的类型对象 + /// + public static Type GetNonNullableType(this Type type) + { + if (IsNullableType(type)) + { + return type.GetGenericArguments()[0]; + } + + return type; + } + + /// + /// 通过类型转换器获取Nullable类型的基础类型 + /// + /// 要处理的类型对象 + /// + public static Type GetUnNullableType(this Type type) + { + if (IsNullableType(type)) + { + NullableConverter nullableConverter = new NullableConverter(type); + return nullableConverter.UnderlyingType; + } + + return type; + } + + /// + /// 获取类型的Description特性描述信息 + /// + /// 类型对象 + /// 是否搜索类型的继承链以查找描述特性 + /// 返回Description特性描述信息,如不存在则返回类型的全名 + public static string GetDescription(this Type type, bool inherit = true) + { + DescriptionAttribute desc = type.GetAttribute(inherit); + return desc == null ? type.FullName : desc.Description; + } + + /// + /// 获取成员元数据的Description特性描述信息 + /// + /// 成员元数据对象 + /// 是否搜索成员的继承链以查找描述特性 + /// 返回Description特性描述信息,如不存在则返回成员的名称 + public static string GetDescription(this MemberInfo member, bool inherit = true) + { + DescriptionAttribute desc = member.GetAttribute(inherit); + if (desc != null) + { + return desc.Description; + } + + DisplayNameAttribute displayName = member.GetAttribute(inherit); + if (displayName != null) + { + return displayName.DisplayName; + } + + DisplayAttribute display = member.GetAttribute(inherit); + if (display != null) + { + return display.Name; + } + + return member.Name; + } + + /// + /// 检查指定指定类型成员中是否存在指定的Attribute特性 + /// + /// 要检查的Attribute特性类型 + /// 要检查的类型成员 + /// 是否从继承中查找 + /// 是否存在 + public static bool HasAttribute(this MemberInfo memberInfo, bool inherit = true) where T : Attribute + { + return memberInfo.IsDefined(typeof(T), inherit); + } + + /// + /// 从类型成员获取指定Attribute特性 + /// + /// Attribute特性类型 + /// 类型类型成员 + /// 是否从继承中查找 + /// 存在返回第一个,不存在返回null + public static T GetAttribute(this MemberInfo memberInfo, bool inherit = true) where T : Attribute + { + object[] attributes = memberInfo.GetCustomAttributes(typeof(T), inherit); + return attributes.FirstOrDefault() as T; + } + + /// + /// 从类型成员获取指定Attribute特性 + /// + /// Attribute特性类型 + /// 类型类型成员 + /// 是否从继承中查找 + /// 返回所有指定Attribute特性的数组 + public static T[] GetAttributes(this MemberInfo memberInfo, bool inherit = true) where T : Attribute + { + return memberInfo.GetCustomAttributes(typeof(T), inherit).Cast().ToArray(); + } + + /// + /// 判断类型是否为集合类型 + /// + /// 要处理的类型 + /// 是返回True,不是返回False + public static bool IsEnumerable(this Type type) + { + if (type == typeof(string)) + { + return false; + } + + return typeof(IEnumerable).IsAssignableFrom(type); + } + + /// + /// 判断当前泛型类型是否可由指定类型的实例填充 + /// + /// 泛型类型 + /// 指定类型 + /// + public static bool IsGenericAssignableFrom(this Type genericType, Type type) + { + genericType.CheckNotNull("genericType"); + type.CheckNotNull("type"); + if (!genericType.IsGenericType) + { + throw new ArgumentException("该功能只支持泛型类型的调用,非泛型类型可使用 IsAssignableFrom 方法。"); + } + + List allOthers = new List { type }; + if (genericType.IsInterface) + { + allOthers.AddRange(type.GetInterfaces()); + } + + foreach (Type other in allOthers) + { + Type cur = other; + while (cur != null) + { + if (cur.IsGenericType) + { + cur = cur.GetGenericTypeDefinition(); + } + + if (cur.IsSubclassOf(genericType) || cur == genericType) + { + return true; + } + + cur = cur.BaseType; + } + } + + return false; + } + + /// + /// 方法是否是异步 + /// + public static bool IsAsync(this MethodInfo method) + { + return method.ReturnType == typeof(Task) + || method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>); + } + + /// + /// 返回当前类型是否是指定基类的派生类 + /// + /// 当前类型 + /// 要判断的基类型 + /// + public static bool IsBaseOn(this Type type, Type baseType) + { + if (baseType.IsGenericTypeDefinition) + { + return baseType.IsGenericAssignableFrom(type); + } + + return baseType.IsAssignableFrom(type); + } + + /// + /// 返回当前类型是否是指定基类的派生类 + /// + /// 要判断的基类型 + /// 当前类型 + /// + public static bool IsBaseOn(this Type type) + { + Type baseType = typeof(TBaseType); + return type.IsBaseOn(baseType); + } + + /// + /// 获取类型的全名,附带所在类库 + /// + public static string GetFullNameWithModule(this Type type) + { + return $"{type.FullName},{type.Module.Name.Replace(".dll", "").Replace(".exe", "")}"; + } + + /// + /// 获取类型的显示短名称 + /// + public static string ShortDisplayName(this Type type) + { + return type.DisplayName(false); + } + + /// + /// 获取类型的显示名称 + /// + public static string DisplayName([NotNull] this Type type, bool fullName = true) + { + StringBuilder sb = new StringBuilder(); + ProcessType(sb, type, fullName); + return sb.ToString(); + } + + /// + /// 获取主键字段 + /// + /// + /// + public static PropertyInfo GetKeyProperty(this Type entity) + { + return entity.GetProperties().GetKeyProperty(); + } + + /// + /// + /// + /// + /// + public static PropertyInfo GetKeyProperty(this PropertyInfo[] properties) + { + return properties.Where(c => c.IsKey()).FirstOrDefault(); + } + + /// + /// + /// + /// + /// + public static bool IsKey(this PropertyInfo propertyInfo) + { + object[] keyAttributes = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), false); + if (keyAttributes.Length > 0) + { + return true; + } + + return false; + } + + #region 私有方法 + + private static readonly Dictionary _builtInTypeNames = new Dictionary + { + {typeof(bool), "bool"}, + {typeof(byte), "byte"}, + {typeof(char), "char"}, + {typeof(decimal), "decimal"}, + {typeof(double), "double"}, + {typeof(float), "float"}, + {typeof(int), "int"}, + {typeof(long), "long"}, + {typeof(object), "object"}, + {typeof(sbyte), "sbyte"}, + {typeof(short), "short"}, + {typeof(string), "string"}, + {typeof(uint), "uint"}, + {typeof(ulong), "ulong"}, + {typeof(ushort), "ushort"}, + {typeof(void), "void"} + }; + + private static void ProcessType(StringBuilder builder, Type type, bool fullName) + { + if (type.IsGenericType) + { + Type[] genericArguments = type.GetGenericArguments(); + ProcessGenericType(builder, type, genericArguments, genericArguments.Length, fullName); + } + else if (type.IsArray) + { + ProcessArrayType(builder, type, fullName); + } + else if (_builtInTypeNames.TryGetValue(type, out string builtInName)) + { + builder.Append(builtInName); + } + else if (!type.IsGenericParameter) + { + builder.Append(fullName ? type.FullName : type.Name); + } + } + + private static void ProcessArrayType(StringBuilder builder, Type type, bool fullName) + { + Type innerType = type; + while (innerType.IsArray) + { + innerType = innerType.GetElementType(); + } + + ProcessType(builder, innerType, fullName); + + while (type.IsArray) + { + builder.Append('['); + builder.Append(',', type.GetArrayRank() - 1); + builder.Append(']'); + type = type.GetElementType(); + } + } + + private static void ProcessGenericType(StringBuilder builder, Type type, Type[] genericArguments, int length, + bool fullName) + { + int offset = type.IsNested ? type.DeclaringType.GetGenericArguments().Length : 0; + + if (fullName) + { + if (type.IsNested) + { + ProcessGenericType(builder, type.DeclaringType, genericArguments, offset, fullName); + builder.Append('+'); + } + else + { + builder.Append(type.Namespace); + builder.Append('.'); + } + } + + int genericPartIndex = type.Name.IndexOf('`'); + if (genericPartIndex <= 0) + { + builder.Append(type.Name); + return; + } + + builder.Append(type.Name, 0, genericPartIndex); + builder.Append('<'); + + for (int i = offset; i < length; i++) + { + ProcessType(builder, genericArguments[i], fullName); + if (i + 1 == length) + { + continue; + } + + builder.Append(','); + if (!genericArguments[i + 1].IsGenericParameter) + { + builder.Append(' '); + } + } + + builder.Append('>'); + } + + #endregion 私有方法 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/YuebonClaimTypes.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/YuebonClaimTypes.cs new file mode 100644 index 0000000..ca54dbc --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Extensions/YuebonClaimTypes.cs @@ -0,0 +1,60 @@ +using System.Security.Claims; + +namespace Znyc.Admin.Commons.Extensions +{ + /// + /// + /// + public static class ZnycClaimTypes + { + /// + /// Default: + /// + public static string UserName { get; set; } = ClaimTypes.Name; + + /// + /// Default: + /// + public static string UserId { get; set; } = ClaimTypes.NameIdentifier; + + /// + /// Default: + /// + public static string Role { get; set; } = ClaimTypes.Role; + + /// + /// Default: + /// + public static string Email { get; set; } = ClaimTypes.Email; + + /// + /// Default: "email_verified". + /// + public static string EmailVerified { get; set; } = "email_verified"; + + /// + /// Default: "phone_number". + /// + public static string PhoneNumber { get; set; } = "phone_number"; + + /// + /// Default: "phone_number_verified". + /// + public static string PhoneNumberVerified { get; set; } = "phone_number_verified"; + + /// + /// Default: "tenantid". + /// + public static string TenantId { get; set; } = "tenantid"; + + /// + /// Default: "editionid". + /// + public static string EditionId { get; set; } = "editionid"; + + /// + /// Default: "client_id". + /// + public static string ClientId { get; set; } = "client_id"; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/AppVersionHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/AppVersionHelper.cs new file mode 100644 index 0000000..79fbfa7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/AppVersionHelper.cs @@ -0,0 +1,28 @@ +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 应用版本号、软件厂商等信息 + /// + public class AppVersionHelper + { + /// + /// 版本号 + /// + public const string Version = "3.0"; + + /// + /// 软件厂商 + /// + public const string Manufacturer = "上海越邦网络科技有限公司"; + + /// + /// 网站地址 + /// + public const string WebSite = "http://www.Znyc.Admin.com"; + + /// + /// 更新地址 + /// + public const string UpdateUrl = "http://netcore.Znyc.Admin.com/update"; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/BooleanJsonConverter.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/BooleanJsonConverter.cs new file mode 100644 index 0000000..78463c2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/BooleanJsonConverter.cs @@ -0,0 +1,40 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// + /// + public class BooleanJsonConverter : JsonConverter + { + /// + /// + /// + /// + /// + /// + /// + public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.True || reader.TokenType == JsonTokenType.False) + { + return reader.GetBoolean(); + } + + return bool.Parse(reader.GetString()); + } + + /// + /// + /// + /// + /// + /// + public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) + { + writer.WriteBooleanValue(value); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ByteConvertHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ByteConvertHelper.cs new file mode 100644 index 0000000..f3599fd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ByteConvertHelper.cs @@ -0,0 +1,44 @@ +using Newtonsoft.Json; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// byte转换类 + /// + public class ByteConvertHelper + { + /// + /// 将对象转换为byte数组 + /// + /// 被转换对象 + /// 转换后byte数组 + public static byte[] Object2Bytes(object obj) + { + string json = JsonConvert.SerializeObject(obj); + byte[] serializedResult = System.Text.Encoding.UTF8.GetBytes(json); + return serializedResult; + } + + /// + /// 将byte数组转换成对象 + /// + /// 被转换byte数组 + /// 转换完成后的对象 + public static object Bytes2Object(byte[] buff) + { + string json = System.Text.Encoding.UTF8.GetString(buff); + return JsonConvert.DeserializeObject(json); + } + + /// + /// 将byte数组转换成对象 + /// + /// 被转换byte数组 + /// 转换完成后的对象 + public static T Bytes2Object(byte[] buff) + { + string json = System.Text.Encoding.UTF8.GetString(buff); + return JsonConvert.DeserializeObject(json); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ConvertHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ConvertHelper.cs new file mode 100644 index 0000000..1f39095 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ConvertHelper.cs @@ -0,0 +1,884 @@ +using System; +using System.Text; +using System.Threading; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 处理数据类型转换,数制转换、编码转换相关的类 + /// + public sealed class ConvertHelper + { + #region 各进制数间转换 + + /// + /// 实现各进制数间的转换。ConvertBase("15",10,16)表示将十进制数15转换为16进制的数。 + /// + /// 要转换的值,即原值 + /// 原值的进制,只能是2,8,10,16四个值。 + /// 要转换到的目标进制,只能是2,8,10,16四个值。 + public static string ConvertBase(string value, int from, int to) + { + if (!isBaseNumber(from)) + { + throw new ArgumentException("参数from只能是2,8,10,16四个值。"); + } + + if (!isBaseNumber(to)) + { + throw new ArgumentException("参数to只能是2,8,10,16四个值。"); + } + + int intValue = Convert.ToInt32(value, from); //先转成10进制 + string result = Convert.ToString(intValue, to); //再转成目标进制 + if (to == 2) + { + int resultLength = result.Length; //获取二进制的长度 + switch (resultLength) + { + case 7: + result = "0" + result; + break; + + case 6: + result = "00" + result; + break; + + case 5: + result = "000" + result; + break; + + case 4: + result = "0000" + result; + break; + + case 3: + result = "00000" + result; + break; + } + } + + return result; + } + + /// + /// 判断是否是 2 8 10 16 + /// + /// + /// + private static bool isBaseNumber(int baseNumber) + { + if (baseNumber == 2 || baseNumber == 8 || baseNumber == 10 || baseNumber == 16) + { + return true; + } + + return false; + } + + #endregion 各进制数间转换 + + #region 使用指定字符集将string转换成byte[] + + /// + /// 将string转换成byte[] + /// + /// 要转换的字符串 + public static byte[] StringToBytes(string text) + { + return Encoding.Default.GetBytes(text); + } + + /// + /// 使用指定字符集将string转换成byte[] + /// + /// 要转换的字符串 + /// 字符编码 + public static byte[] StringToBytes(string text, Encoding encoding) + { + return encoding.GetBytes(text); + } + + #endregion 使用指定字符集将string转换成byte[] + + #region 使用指定字符集将byte[]转换成string + + /// + /// 将byte[]转换成string + /// + /// 要转换的字节数组 + public static string BytesToString(byte[] bytes) + { + return Encoding.Default.GetString(bytes); + } + + /// + /// 使用指定字符集将byte[]转换成string + /// + /// 要转换的字节数组 + /// 字符编码 + public static string BytesToString(byte[] bytes, Encoding encoding) + { + return encoding.GetString(bytes); + } + + #endregion 使用指定字符集将byte[]转换成string + + #region 将byte[]转换成int + + /// + /// 将byte[]转换成int + /// + /// 需要转换成整数的byte数组 + public static int BytesToInt32(byte[] data) + { + //如果传入的字节数组长度小于4,则返回0 + if (data.Length < 4) + { + return 0; + } + + //定义要返回的整数 + int num = 0; + + //如果传入的字节数组长度大于4,需要进行处理 + if (data.Length >= 4) + { + //创建一个临时缓冲区 + byte[] tempBuffer = new byte[4]; + + //将传入的字节数组的前4个字节复制到临时缓冲区 + Buffer.BlockCopy(data, 0, tempBuffer, 0, 4); + + //将临时缓冲区的值转换成整数,并赋给num + num = BitConverter.ToInt32(tempBuffer, 0); + } + + //返回整数 + return num; + } + + #endregion 将byte[]转换成int + + #region 将数据转换为整型 + + /// + /// 将数据转换为整型 转换失败返回默认值 + /// + /// 数据类型 + /// 数据 + /// 默认值 + /// + public static int ToInt32(T data, int defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToInt32(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为整型 转换失败返回默认值 + /// + /// 数据 + /// 默认值 + /// + public static int ToInt32(string data, int defValue) + { + //如果为空则返回默认值 + if (string.IsNullOrEmpty(data)) + { + return defValue; + } + + if (int.TryParse(data, out int temp)) + { + return temp; + } + else + { + return defValue; + } + } + + /// + /// 将数据转换为整型 转换失败返回默认值 + /// + /// 数据 + /// 默认值 + /// + public static int ToInt32(object data, int defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToInt32(data); + } + catch + { + return defValue; + } + } + + #endregion 将数据转换为整型 + + #region 将数据转换为布尔型 + + /// + /// 将数据转换为布尔类型 转换失败返回默认值 + /// + /// 数据类型 + /// 数据 + /// 默认值 + /// + public static bool ToBoolean(T data, bool defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToBoolean(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为布尔类型 转换失败返回 默认值 + /// + /// 数据 + /// 默认值 + /// + public static bool ToBoolean(string data, bool defValue) + { + //如果为空则返回默认值 + if (string.IsNullOrEmpty(data)) + { + return defValue; + } + + if (bool.TryParse(data, out bool temp)) + { + return temp; + } + else + { + return defValue; + } + } + + /// + /// 将数据转换为布尔类型 转换失败返回 默认值 + /// + /// 数据 + /// 默认值 + /// + public static bool ToBoolean(object data, bool defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToBoolean(data); + } + catch + { + return defValue; + } + } + + #endregion 将数据转换为布尔型 + + #region 将数据转换为单精度浮点型 + + /// + /// 将数据转换为单精度浮点型 转换失败 返回默认值 + /// + /// 数据类型 + /// 数据 + /// 默认值 + /// + public static float ToFloat(T data, float defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToSingle(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为单精度浮点型 转换失败返回默认值 + /// + /// 数据 + /// 默认值 + /// + public static float ToFloat(object data, float defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToSingle(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为单精度浮点型 转换失败返回默认值 + /// + /// 数据 + /// 默认值 + /// + public static float ToFloat(string data, float defValue) + { + //如果为空则返回默认值 + if (string.IsNullOrEmpty(data)) + { + return defValue; + } + + if (float.TryParse(data, out float temp)) + { + return temp; + } + else + { + return defValue; + } + } + + #endregion 将数据转换为单精度浮点型 + + #region 将数据转换为双精度浮点型 + + /// + /// 将数据转换为双精度浮点型 转换失败返回默认值 + /// + /// 数据的类型 + /// 要转换的数据 + /// 默认值 + /// + public static double ToDouble(T data, double defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToDouble(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为双精度浮点型,并设置小数位 转换失败返回默认值 + /// + /// 数据的类型 + /// 要转换的数据 + /// 小数的位数 + /// 默认值 + /// + public static double ToDouble(T data, int decimals, double defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Math.Round(Convert.ToDouble(data), decimals); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为双精度浮点型 转换失败返回默认值 + /// + /// 要转换的数据 + /// 默认值 + /// + public static double ToDouble(object data, double defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToDouble(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为双精度浮点型 转换失败返回默认值 + /// + /// 要转换的数据 + /// 默认值 + /// + public static double ToDouble(string data, double defValue) + { + //如果为空则返回默认值 + if (string.IsNullOrEmpty(data)) + { + return defValue; + } + + if (double.TryParse(data, out double temp)) + { + return temp; + } + else + { + return defValue; + } + } + + /// + /// 将数据转换为双精度浮点型,并设置小数位 转换失败返回默认值 + /// + /// 要转换的数据 + /// 小数的位数 + /// 默认值 + /// + public static double ToDouble(object data, int decimals, double defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Math.Round(Convert.ToDouble(data), decimals); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为双精度浮点型,并设置小数位 转换失败返回默认值 + /// + /// 要转换的数据 + /// 小数的位数 + /// 默认值 + /// + public static double ToDouble(string data, int decimals, double defValue) + { + //如果为空则返回默认值 + if (string.IsNullOrEmpty(data)) + { + return defValue; + } + + if (double.TryParse(data, out double temp)) + { + return Math.Round(temp, decimals); + } + else + { + return defValue; + } + } + + #endregion 将数据转换为双精度浮点型 + + #region 将数据转换为指定类型 + + /// + /// 将数据转换为指定类型 + /// + /// 转换的数据 + /// 转换的目标类型 + public static object ConvertTo(object data, Type targetType) + { + if (data == null || Convert.IsDBNull(data)) + { + return null; + } + + Type type2 = data.GetType(); + if (targetType == type2) + { + return data; + } + + if ((targetType == typeof(Guid) || targetType == typeof(Guid?)) && type2 == typeof(string)) + { + if (string.IsNullOrEmpty(data.ToString())) + { + return null; + } + + return new Guid(data.ToString()); + } + + if (targetType.IsEnum) + { + try + { + return Enum.Parse(targetType, data.ToString(), true); + } + catch + { + return Enum.ToObject(targetType, data); + } + } + + if (targetType.IsGenericType) + { + targetType = targetType.GetGenericArguments()[0]; + } + + return Convert.ChangeType(data, targetType); + } + + /// + /// 将数据转换为指定类型 + /// + /// 转换的目标类型 + /// 转换的数据 + public static T ConvertTo(object data) + { + if (data == null || Convert.IsDBNull(data)) + { + return default(T); + } + + object obj = ConvertTo(data, typeof(T)); + if (obj == null) + { + return default(T); + } + + return (T)obj; + } + + #endregion 将数据转换为指定类型 + + #region = ChangeType = + + /// + /// + /// + /// + /// + /// + public static object ChangeType(object obj, Type conversionType) + { + return ChangeType(obj, conversionType, Thread.CurrentThread.CurrentCulture); + } + + /// + /// + /// + /// + /// + /// + /// + public static object ChangeType(object obj, Type conversionType, IFormatProvider provider) + { + #region Nullable + + Type nullableType = Nullable.GetUnderlyingType(conversionType); + if (nullableType != null) + { + if (obj == null) + { + return null; + } + + return Convert.ChangeType(obj, nullableType, provider); + } + + #endregion Nullable + + if (typeof(Enum).IsAssignableFrom(conversionType)) + { + return Enum.Parse(conversionType, obj.ToString()); + } + + return Convert.ChangeType(obj, conversionType, provider); + } + + #endregion = ChangeType = + + #region 将数据转换Decimal + + /// + /// 将数据转换为Decimal 转换失败返回默认值 + /// + /// 数据类型 + /// 数据 + /// 默认值 + /// + public static decimal ToDecimal(T data, decimal defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToDecimal(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为Decimal 转换失败返回 默认值 + /// + /// 数据 + /// 默认值 + /// + public static decimal ToDecimal(object data, decimal defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToDecimal(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为Decimal 转换失败返回 默认值 + /// + /// 数据 + /// 默认值 + /// + public static decimal ToDecimal(string data, decimal defValue) + { + //如果为空则返回默认值 + if (string.IsNullOrEmpty(data)) + { + return defValue; + } + + if (decimal.TryParse(data, out decimal temp)) + { + return temp; + } + else + { + return defValue; + } + } + + #endregion 将数据转换Decimal + + #region 将数据转换为DateTime + + /// + /// 将数据转换为DateTime 转换失败返回默认值 + /// + /// 数据类型 + /// 数据 + /// 默认值 + /// + public static DateTime ToDateTime(T data, DateTime defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToDateTime(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为DateTime 转换失败返回 默认值 + /// + /// 数据 + /// 默认值 + /// + public static DateTime ToDateTime(object data, DateTime defValue) + { + //如果为空则返回默认值 + if (data == null || Convert.IsDBNull(data)) + { + return defValue; + } + + try + { + return Convert.ToDateTime(data); + } + catch + { + return defValue; + } + } + + /// + /// 将数据转换为DateTime 转换失败返回 默认值 + /// + /// 数据 + /// 默认值 + /// + public static DateTime ToDateTime(string data, DateTime defValue) + { + //如果为空则返回默认值 + if (string.IsNullOrEmpty(data)) + { + return defValue; + } + + DateTime temp = DateTime.Now; + + if (DateTime.TryParse(data, out temp)) + { + return temp; + } + else + { + return defValue; + } + } + + #endregion 将数据转换为DateTime + + #region 半角全角转换 + + /// + /// 转全角的函数(SBC case) + /// + /// 任意字符串 + /// 全角字符串 + /// + ///全角空格为12288,半角空格为32 + ///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248 + /// + public static string ConvertToSBC(string input) + { + //半角转全角: + char[] c = input.ToCharArray(); + for (int i = 0; i < c.Length; i++) + { + if (c[i] == 32) + { + c[i] = (char)12288; + continue; + } + + if (c[i] < 127) + { + c[i] = (char)(c[i] + 65248); + } + } + + return new string(c); + } + + /// 转半角的函数(DBC case) + /// 任意字符串 + /// 半角字符串 + /// + ///全角空格为12288,半角空格为32 + ///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248 + /// + public static string ConvertToDBC(string input) + { + char[] c = input.ToCharArray(); + for (int i = 0; i < c.Length; i++) + { + if (c[i] == 12288) + { + c[i] = (char)32; + continue; + } + + if (c[i] > 65280 && c[i] < 65375) + { + c[i] = (char)(c[i] - 65248); + } + } + + return new string(c); + } + + #endregion 半角全角转换 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/CookiesHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/CookiesHelper.cs new file mode 100644 index 0000000..664e61e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/CookiesHelper.cs @@ -0,0 +1,129 @@ +using Microsoft.AspNetCore.Http; +using System; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// Cookie操作类 + /// + public static class CookiesHelper + { + /// + /// + /// + public static HttpContext HttpHelper => HttpContextHelper.HttpContext; + + /// + /// Cookie名称 + /// + public static string CookieName { get; set; } = "Znyc_"; + + /// + /// 设置Cookie键 + /// + /// 键 + /// + private static string CookieKey(string cookieName) + { + return CookieName + cookieName; + } + + /// + /// 删除Cookie + /// + /// + /// Coookie名称 + public static void DeleteCookie(HttpContext context, string cookieName) + { + string key = CookieKey(cookieName); + context.Response.Cookies.Delete(key); + } + + /// + /// 写/保存Cookie + /// + /// + /// Coookie名称 + /// Coookie值 + /// 有效月数 + public static void WriteCookie(HttpContext context, string cookieName, string value, int months) + { + WriteCookie(context, cookieName, value, months, 0); + } + + /// + /// 写/保存Cookie + /// + /// Coookie名称 + /// Coookie值 + /// 有效月数 + public static void WriteCookie(string cookieName, string value, int months) + { + WriteCookie(HttpHelper, cookieName, value, months, 0); + } + + /// + /// 写/保存Cookie + /// + /// + /// Coookie名称 + /// Coookie值 + /// 有效月数 + /// 有效天数 + public static void WriteCookie(HttpContext context, string cookieName, string value, int months, int days) + { + string key = CookieKey(cookieName); + if (!context.Request.Cookies.ContainsKey(key)) + { + DateTime expires = DateTime.Today.AddDays(30 * months + days); + DateTimeOffset dateAndOffset = new DateTimeOffset(expires, + TimeZoneInfo.Local.GetUtcOffset(expires)); + + context.Response.Cookies.Append(key, value, + new CookieOptions + { + Expires = expires + }); + } + } + + /// + /// 获取Cookie值 + /// + /// + /// Coookie名称 + /// + public static string ReadCookie(HttpContext context, string cookieName) + { + string key = CookieKey(cookieName); + + try + { + return System.Net.WebUtility.UrlDecode(context.Request.Cookies[key]); + } + catch + { + return ""; + } + } + + /// + /// 获取Cookie值 + /// + /// Coookie名称 + /// + public static string ReadCookie(string cookieName) + { + string key = CookieKey(cookieName); + + try + { + return System.Net.WebUtility.UrlDecode(HttpHelper.Request.Cookies[key]); + } + catch + { + return ""; + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/DatetimeJsonConverter.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/DatetimeJsonConverter.cs new file mode 100644 index 0000000..1b701c6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/DatetimeJsonConverter.cs @@ -0,0 +1,78 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 时间类型格式数据处理 + /// + public class DateTimeJsonConverter : JsonConverter + { + /// + /// 时间格式 + /// + private readonly string _dateFormatString; + + /// + /// + /// + public DateTimeJsonConverter() + { + _dateFormatString = "yyyy-MM-dd HH:mm:ss"; + } + + /// + /// + /// + /// 时间格式 + public DateTimeJsonConverter(string dateFormatString) + { + _dateFormatString = dateFormatString; + } + + /// + /// + /// + /// + /// + /// + /// + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + if (DateTime.TryParse(reader.GetString(), out DateTime date)) + { + return date; + } + } + + return reader.GetDateTime(); + } + + /// + /// + /// + /// + /// + /// + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss")); + } + } + + public class DateTimeNullableConverter : JsonConverter + { + public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return string.IsNullOrEmpty(reader.GetString()) ? default(DateTime?) : DateTime.Parse(reader.GetString()); + } + + public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) + { + writer.WriteStringValue(value?.ToString("yyyy-MM-dd HH:mm:ss")); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/DecimalJsonConverter.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/DecimalJsonConverter.cs new file mode 100644 index 0000000..171674e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/DecimalJsonConverter.cs @@ -0,0 +1,40 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Znyc.Admin.Commons.Extensions; + +namespace Znyc.Admin.Commons.Helpers +{ + public class DecimalJsonConverter : JsonConverter + { + /// + /// + /// + /// + /// + /// + /// + public override decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Number) + { + return reader.GetDecimal(); + } + + return reader.GetString().Equals("") + ? "0.00".ToDecimal() + : reader.GetString().ToDecimal(); + } + + /// + /// + /// + /// + /// + /// + public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options) + { + writer.WriteNumberValue(value); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/EntityMapper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/EntityMapper.cs new file mode 100644 index 0000000..283b3c4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/EntityMapper.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Reflection; +using System.Reflection.Emit; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 实体类映射,源自SqlSugar(http://www.codeisbug.com/Doc/3/1113) + /// + public static class EntityMapper + { + private delegate T MapEntity(DbDataReader dr); + + //把DataRow转换为对象的委托声明 + private delegate T Load(DataRow dataRecord); + + //用于构造Emit的DataRow中获取字段的方法信息 + private static readonly MethodInfo getValueMethod = + typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(int) }); + + //用于构造Emit的DataRow中判断是否为空行的方法信息 + private static readonly MethodInfo isDBNullMethod = + typeof(DataRow).GetMethod("IsNull", new Type[] { typeof(int) }); + + private static readonly ConcurrentDictionary CachedMappers = + new ConcurrentDictionary(); + + public static IEnumerable ToList(this DbDataReader dr) + { + // If a mapping function from dr -> T does not exist, create and cache one + if (!CachedMappers.ContainsKey(typeof(T))) + { + // Our method will take in a single parameter, a DbDataReader + Type[] methodArgs = { typeof(DbDataReader) }; + + // The MapDR method will map a DbDataReader row to an instance of type T + DynamicMethod dm = new DynamicMethod("MapDR", typeof(T), methodArgs, + Assembly.GetExecutingAssembly().GetType().Module); + ILGenerator il = dm.GetILGenerator(); + + // We'll have a single local variable, the instance of T we're mapping + il.DeclareLocal(typeof(T)); + + // Create a new instance of T and save it as variable 0 + il.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); + il.Emit(OpCodes.Stloc_0); + + foreach (PropertyInfo pi in typeof(T).GetProperties()) + { + // Load the T instance, SqlDataReader parameter and the field name onto the stack + il.Emit(OpCodes.Ldloc_0); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldstr, pi.Name); + + // Push the column value onto the stack + il.Emit(OpCodes.Callvirt, typeof(DbDataReader).GetMethod("get_Item", new Type[] { typeof(string) })); + + // Depending on the type of the property, convert the datareader column value to the type + switch (pi.PropertyType.Name) + { + case "Int16": + il.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt16", new Type[] { typeof(object) })); + break; + + case "Int32": + il.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(object) })); + break; + + case "Int64": + il.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt64", new Type[] { typeof(object) })); + break; + + case "Boolean": + il.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToBoolean", new Type[] { typeof(object) })); + break; + + case "String": + il.Emit(OpCodes.Callvirt, typeof(string).GetMethod("ToString", new Type[] { })); + break; + + case "DateTime": + il.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToDateTime", new Type[] { typeof(object) })); + break; + + case "Decimal": + il.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToDecimal", new Type[] { typeof(object) })); + break; + + default: + // Don't set the field value as it's an unsupported type + continue; + } + + // Set the T instances property value + il.Emit(OpCodes.Callvirt, typeof(T).GetMethod("set_" + pi.Name, new Type[] { pi.PropertyType })); + } + + // Load the T instance onto the stack + il.Emit(OpCodes.Ldloc_0); + + // Return + il.Emit(OpCodes.Ret); + + // Cache the method so we won't have to create it again for the type T + CachedMappers.TryAdd(typeof(T), dm.CreateDelegate(typeof(MapEntity))); + } + + // Get a delegate reference to the dynamic method + MapEntity invokeMapEntity = (MapEntity)CachedMappers[typeof(T)]; + + // For each row, map the row to an instance of T and yield return it + while (dr.Read()) + { + yield return invokeMapEntity(dr); + } + } + + /// + /// 将DataTable转换成泛型对象列表 + /// + /// + /// + /// + public static List ToList(this DataTable dt) + { + List list = new List(); + if (dt == null) + { + return list; + } + + //声明 委托Load的一个实例rowMap + Load rowMap = null; + + //从rowMapMethods查找当前T类对应的转换方法,没有则使用Emit构造一个。 + if (!CachedMappers.ContainsKey(typeof(T))) + { + DynamicMethod method = new DynamicMethod("DynamicCreateEntity_" + typeof(T).Name, typeof(T), + new Type[] { typeof(DataRow) }, typeof(T), true); + ILGenerator generator = method.GetILGenerator(); + LocalBuilder result = generator.DeclareLocal(typeof(T)); + generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); + generator.Emit(OpCodes.Stloc, result); + + for (int index = 0; index < dt.Columns.Count; index++) + { + PropertyInfo propertyInfo = typeof(T).GetProperty(dt.Columns[index].ColumnName); + Label endIfLabel = generator.DefineLabel(); + if (propertyInfo != null && propertyInfo.GetSetMethod() != null) + { + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, index); + generator.Emit(OpCodes.Callvirt, isDBNullMethod); + generator.Emit(OpCodes.Brtrue, endIfLabel); + generator.Emit(OpCodes.Ldloc, result); + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, index); + generator.Emit(OpCodes.Callvirt, getValueMethod); + generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); + generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); + generator.MarkLabel(endIfLabel); + } + } + + generator.Emit(OpCodes.Ldloc, result); + generator.Emit(OpCodes.Ret); + + //构造完成以后传给rowMap + rowMap = (Load)method.CreateDelegate(typeof(Load)); + } + else + { + rowMap = (Load)CachedMappers[typeof(T)]; + } + + //遍历Datatable的rows集合,调用rowMap把DataRow转换为对象(T) + foreach (DataRow info in dt.Rows) + { + list.Add(rowMap(info)); + } + + return list; + } + + public static void ClearCachedMapperMethods() + { + CachedMappers.Clear(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/FileHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/FileHelper.cs new file mode 100644 index 0000000..e294329 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/FileHelper.cs @@ -0,0 +1,250 @@ +using ICSharpCode.SharpZipLib.Checksum; +using ICSharpCode.SharpZipLib.Zip; +using System; +using System.IO; +using System.Text; +using Znyc.Admin.Commons.Extend; +using Znyc.Admin.Commons.Log; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 文件处理帮助类 + /// + public class FileHelper + { + /// + /// 制作压缩包(多个文件压缩到一个压缩包,支持加密、注释) + /// + /// 压缩文件目录 + /// 压缩包文件名 + /// 压缩级别 1-9 + /// 密码 + /// 注释 + /// 文件类型 + public static void ZipFiles(string topDirectoryName, string zipedFileName, int compresssionLevel, + string password, string comment, string filetype) + { + using (ZipOutputStream zos = new ZipOutputStream(File.Open(zipedFileName, FileMode.OpenOrCreate))) + { + if (compresssionLevel != 0) + { + zos.SetLevel(compresssionLevel); //设置压缩级别 + } + + if (!string.IsNullOrEmpty(password)) + { + zos.Password = password; //设置zip包加密密码 + } + + if (!string.IsNullOrEmpty(comment)) + { + zos.SetComment(comment); //设置zip包的注释 + } + //循环设置目录下所有的*.jpg文件(支持子目录搜索) + foreach (string file in Directory.GetFiles(topDirectoryName, filetype, SearchOption.AllDirectories)) + { + if (File.Exists(file)) + { + FileInfo item = new FileInfo(file); + FileStream fs = File.OpenRead(item.FullName); + byte[] buffer = new byte[fs.Length]; + fs.Read(buffer, 0, buffer.Length); + ZipEntry entry = new ZipEntry(item.Name); + zos.PutNextEntry(entry); + zos.Write(buffer, 0, buffer.Length); + fs.Close(); + } + } + + zos.Close(); + } + } + + /// + /// 压缩多层目录 + /// + /// 压缩文件目录 + /// 压缩包文件名 + /// 压缩级别 1-9 + /// 密码 + /// 注释 + /// 文件类型 + public static void ZipFileDirectory(string topDirectoryName, string zipedFileName, int compresssionLevel, + string password, string comment, string filetype) + { + using (FileStream ZipFile = File.Open(zipedFileName, FileMode.OpenOrCreate)) + { + using (ZipOutputStream zos = new ZipOutputStream(ZipFile)) + { + if (compresssionLevel != 0) + { + zos.SetLevel(compresssionLevel); //设置压缩级别 + } + + if (!string.IsNullOrEmpty(password)) + { + zos.Password = password; //设置zip包加密密码 + } + + if (!string.IsNullOrEmpty(comment)) + { + zos.SetComment(comment); //设置zip包的注释 + } + + ZipSetp(topDirectoryName, zos, "", filetype); + } + } + } + + /// + /// 递归遍历目录 + /// + /// The directory. + /// The ZipOutputStream Object. + /// The parent path. + private static void ZipSetp(string strDirectory, ZipOutputStream s, string parentPath, string filetype) + { + if (strDirectory[strDirectory.Length - 1] != Path.DirectorySeparatorChar) + { + strDirectory += Path.DirectorySeparatorChar; + } + + Crc32 crc = new Crc32(); + + string[] filenames = Directory.GetFileSystemEntries(strDirectory, filetype); + foreach (string file in filenames) // 遍历所有的文件和目录 + { + if (Directory.Exists(file)) // 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件 + { + string pPath = parentPath; + pPath += file.Substring(file.LastIndexOf("\\") + 1); + pPath += "\\"; + ZipSetp(file, s, pPath, filetype); + } + else // 否则直接压缩文件 + { + //打开压缩文件 + using (FileStream fs = File.OpenRead(file)) + { + byte[] buffer = new byte[fs.Length]; + fs.Read(buffer, 0, buffer.Length); + string fileName = parentPath + file.Substring(file.LastIndexOf("\\") + 1); + ZipEntry entry = new ZipEntry(fileName) + { + DateTime = DateTime.Now, + Size = fs.Length + }; + fs.Close(); + crc.Reset(); + crc.Update(buffer); + entry.Crc = crc.Value; + s.PutNextEntry(entry); + s.Write(buffer, 0, buffer.Length); + } + } + } + } + + /// + /// 读文件 + /// + /// + /// + public static string ReadFile(string path) + { + path = path.ToFilePath(); + if (!File.Exists(path)) + { + return ""; + } + + using (StreamReader stream = new StreamReader(path)) + { + return stream.ReadToEnd(); // 读取文件 + } + } + + /// + /// 写文件 + /// + /// 文件路径 + /// 文件名称 + /// 文件内容 + /// 是否追加到最后 + public static void WriteFile(string path, string fileName, string content, bool appendToLast = false) + { + if (!path.EndsWith("\\")) + { + path = path + "\\"; + } + + path = path.ToFilePath(); + if (!Directory.Exists(path)) //如果不存在就创建file文件夹 + { + Directory.CreateDirectory(path); + } + + using (FileStream stream = File.Open(path + fileName, FileMode.OpenOrCreate, FileAccess.Write)) + { + byte[] by = Encoding.Default.GetBytes(content); + if (appendToLast) + { + stream.Position = stream.Length; + } + else + { + stream.SetLength(0); + } + + stream.Write(by, 0, by.Length); + } + } + + #region 直接删除指定目录下的所有文件及文件夹(保留目录) + + /// + /// 删除指定目录下的所有文件及文件夹(保留目录) + /// + /// 文件目录 + public static void DeleteDirectory(string file) + { + try + { + //判断文件夹是否还存在 + if (Directory.Exists(file)) + { + DirectoryInfo fileInfo = new DirectoryInfo(file) + { + //去除文件夹的只读属性 + Attributes = FileAttributes.Normal & FileAttributes.Directory + }; + foreach (string f in Directory.GetFileSystemEntries(file)) + { + if (File.Exists(f)) + { + //去除文件的只读属性 + File.SetAttributes(file, FileAttributes.Normal); + //如果有子文件删除文件 + File.Delete(f); + } + else + { + //循环递归删除子文件夹 + DeleteDirectory(f); + } + } + + //删除空文件夹 + Directory.Delete(file); + } + } + catch (Exception ex) // 异常处理 + { + Log4NetHelper.Error("代码生成异常", ex); + } + } + + #endregion 直接删除指定目录下的所有文件及文件夹(保留目录) + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/FileQuartz.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/FileQuartz.cs new file mode 100644 index 0000000..da29ebd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/FileQuartz.cs @@ -0,0 +1,133 @@ +using Quartz; +using System; +using System.IO; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Extend; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 定时任务日志文件 + /// + public class FileQuartz + { + private static string _rootPath { get; set; } + + private static string _logPath { get; set; } + + /// + /// 创建作业所在根目录及日志文件夹 + /// + /// + public static string CreateQuartzRootPath() + { + if (!string.IsNullOrEmpty(_rootPath)) + { + return _rootPath; + } + + _rootPath = AppDomain.CurrentDomain.BaseDirectory; + _rootPath = _rootPath.ReplacePath(); + if (!Directory.Exists(_rootPath)) + { + Directory.CreateDirectory(_rootPath); + } + + _rootPath = _rootPath + "Logs\\Quartz\\"; + _rootPath = _rootPath.ReplacePath(); + //生成日志文件夹 + if (!Directory.Exists(_rootPath)) + { + Directory.CreateDirectory(_rootPath); + } + + return _rootPath; + } + + /// + /// 初始化任务日志文件路径 + /// + /// 任务名称 + public static void InitTaskJobLogPath(string jobName) + { + if (string.IsNullOrEmpty(_logPath)) + { + CreateQuartzRootPath(); + } + + _logPath = _rootPath + jobName; + _logPath = _logPath.ReplacePath(); + //生成日志文件夹 + if (!Directory.Exists(_logPath)) + { + Directory.CreateDirectory(_logPath); + } + } + + /// + /// 任务启动日志 + /// + /// + public static void WriteStartLog(string content) + { + content = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "," + content; + if (!content.EndsWith("\r\n")) + { + content += "\r\n"; + } + + FileHelper.WriteFile(LogPath, "start.txt", content, true); + } + + /// + /// 任务操作日志 + /// + /// + /// + /// + /// + public static void WriteJobAction(JobAction jobAction, ITrigger trigger, string taskName, string groupName) + { + WriteJobAction(jobAction, taskName, groupName, trigger == null ? "未找到作业" : "OK"); + } + + /// + /// 任务操作日志 + /// + /// + /// + /// + /// + public static void WriteJobAction(JobAction jobAction, string taskName, string groupName, string content = null) + { + content = + $"{jobAction.ToString()} -- {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} --分组:{groupName},作业:{taskName},消息:{content ?? "OK"}\r\n"; + FileHelper.WriteFile(LogPath, "action.txt", content, true); + } + + /// + /// 任务错误日志 + /// + /// + public static void WriteErrorLog(string content) + { + content = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "," + content; + if (!content.EndsWith("\r\n")) + { + content += "\r\n"; + } + + FileHelper.WriteFile(LogPath, "Error.txt", content, true); + } + + /// + /// 根目录 + /// + public static string RootPath => _rootPath; + + /// + /// 日志目录 + /// + public static string LogPath => _logPath; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/GuidUtils.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/GuidUtils.cs new file mode 100644 index 0000000..796287a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/GuidUtils.cs @@ -0,0 +1,99 @@ +using System; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// Guid工具类 + /// + public class GuidUtils + { + #region 自动生成编号 + + /// + /// 表示全局唯一标识符 (GUID)。 + /// + /// + public static string GuId() + { + return Guid.NewGuid().ToString(); + } + + /// + /// 自动生成编号/唯一订单号生成,时间戳+随机数,时间戳精确到毫秒,形如2020052113254137177350 + /// + /// + public static string CreateNo() + { + Random random = new Random(); + string strRandom = random.Next(1000, 10000).ToString(); //生成随机编号 + string code = DateTime.Now.ToString("yyyyMMddHHmmssffff") + strRandom; //形如2020052113254137177350 + return code; + } + + #endregion 自动生成编号 + + /// + /// 获取一个大写的字符串 + /// + /// + /// + private static string upper(string str) + { + return str.ToUpper(); + } + + /// + /// 获取32位不包含“-”号的GUID字符串 + /// + /// + public static string NewGuidFormatN(bool isUpper = false) + { + string guid = Guid.NewGuid().ToString("N"); + return isUpper == true ? upper(guid) : guid; + } + + /// + /// 获取32位包含“-”号的GUID字符串 + /// + /// + /// + public static string NewGuidFormatD(bool isUpper = false) + { + string guid = Guid.NewGuid().ToString("D"); + return isUpper == true ? upper(guid) : guid; + } + + /// + /// 获取32位包含“-”号的GUID被“(”、“)”包括的字符串 + /// + /// + /// + public static string NewGuidFormatP(bool isUpper = false) + { + string guid = Guid.NewGuid().ToString("P"); + return isUpper == true ? upper(guid) : guid; + } + + /// + /// 获取32位包含“-”号的GUID被“{”、“}”包括的字符串 + /// + /// + /// + public static string NewGuidFormatB(bool isUpper = false) + { + string guid = Guid.NewGuid().ToString("B"); + return isUpper == true ? upper(guid) : guid; + } + + /// + /// 获取4个被“{”、“}”包括的十六进制数,其中第四个值位8个被“{”、“}”包括的十六进制数字符串 + /// + /// + /// + public static string NewGuidFormatX(bool isUpper = false) + { + string guid = Guid.NewGuid().ToString("X"); + return isUpper == true ? upper(guid) : guid; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/HttpContextHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/HttpContextHelper.cs new file mode 100644 index 0000000..1b4b3bd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/HttpContextHelper.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Http; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// HttpContext帮助类 + /// + public static class HttpContextHelper + { + /// + /// + /// + private static IHttpContextAccessor httpContextAccessor; + + /// + /// 注入 + /// + /// + public static void Configure(IHttpContextAccessor _httpContextAccessor) + { + httpContextAccessor = _httpContextAccessor; + } + + /// + /// + /// + public static HttpContext HttpContext => httpContextAccessor.HttpContext; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/HttpRequestHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/HttpRequestHelper.cs new file mode 100644 index 0000000..1c08d5c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/HttpRequestHelper.cs @@ -0,0 +1,221 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// http请求类 + /// + public static class HttpRequestHelper + { + #region 同步方法 + + /// + /// 使用Get方法获取字符串结果 + /// + /// + /// + /// + /// + public static string HttpGet(string url, Encoding encoding = null, int timeOut = 60000) + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "GET"; + request.Timeout = timeOut; + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + using (Stream responseStream = response.GetResponseStream()) + { + using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.GetEncoding("utf-8"))) + { + string retString = myStreamReader.ReadToEnd(); + return retString; + } + } + } + + /// + /// 使用Post方法获取字符串结果,常规提交 + /// + /// + public static string HttpPost(string url, Dictionary formData = null, Encoding encoding = null, + int timeOut = 60000, Dictionary headers = null) + { + MemoryStream ms = new MemoryStream(); + formData.FillFormDataStream(ms); //填充formData + return HttpPost(url, ms, "application/x-www-form-urlencoded", encoding, headers, timeOut); + } + + /// + /// 发送HttpPost请求,使用JSON格式传输数据 + /// + /// + /// + /// + /// + /// + public static string HttpPost(string url, string postData, Encoding encoding = null, + Dictionary headers = null) + { + if (encoding == null) + { + encoding = Encoding.UTF8; + } + + if (string.IsNullOrWhiteSpace(postData)) + { + throw new ArgumentNullException("postData"); + } + + byte[] data = encoding.GetBytes(postData); + MemoryStream stream = new MemoryStream(); + byte[] formDataBytes = postData == null ? new byte[0] : Encoding.UTF8.GetBytes(postData); + stream.Write(formDataBytes, 0, formDataBytes.Length); + stream.Seek(0, SeekOrigin.Begin); //设置指针读取位置 + return HttpPost(url, stream, "application/json", encoding, headers); + } + + /// + /// 使用POST请求数据,使用JSON传输数据 + /// + /// + /// 传输对象,转换为JSON传输 + /// + /// + public static string HttpPost(string url, object dataObj, Encoding encoding = null, + Dictionary headers = null) + { + if (encoding == null) + { + encoding = Encoding.UTF8; + } + + if (dataObj == null) + { + throw new ArgumentNullException("dataObj"); + } + + string postData = JsonConvert.SerializeObject(dataObj, + new JsonSerializerSettings() { DateFormatString = "yyyy-MM-dd HH:mm:ss" }); + byte[] data = encoding.GetBytes(postData); + MemoryStream stream = new MemoryStream(); + byte[] formDataBytes = postData == null ? new byte[0] : Encoding.UTF8.GetBytes(postData); + stream.Write(formDataBytes, 0, formDataBytes.Length); + stream.Seek(0, SeekOrigin.Begin); //设置指针读取位置 + return HttpPost(url, stream, "application/json", encoding, headers); + } + + /// + /// 使用Post方法获取字符串结果 + /// + /// + /// + /// + /// + /// + /// + /// + public static string HttpPost(string url, Stream postStream = null, + string contentType = "application/x-www-form-urlencoded", Encoding encoding = null, + Dictionary headers = null, int timeOut = 60000) + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "POST"; + request.Timeout = timeOut; + + request.ContentLength = postStream != null ? postStream.Length : 0; + request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + request.KeepAlive = false; + + request.UserAgent = + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.87 Safari/537.36 QQBrowser/9.2.5748.400"; + request.ContentType = contentType; + + if (headers != null) + { + foreach (KeyValuePair header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + #region 输入二进制流 + + if (postStream != null) + { + postStream.Position = 0; + + //直接写入流 + Stream requestStream = request.GetRequestStream(); + + byte[] buffer = new byte[1024]; + int bytesRead = 0; + while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0) + { + requestStream.Write(buffer, 0, bytesRead); + } + + postStream.Close(); //关闭文件访问 + } + + #endregion 输入二进制流 + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + using (Stream responseStream = response.GetResponseStream()) + { + using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.GetEncoding("utf-8"))) + { + string retString = myStreamReader.ReadToEnd(); + return retString; + } + } + } + + #endregion 同步方法 + + /// + /// + /// + /// + /// + public static void FillFormDataStream(this Dictionary formData, Stream stream) + { + string dataString = GetQueryString(formData); + byte[] formDataBytes = formData == null ? new byte[0] : Encoding.UTF8.GetBytes(dataString); + stream.Write(formDataBytes, 0, formDataBytes.Length); + stream.Seek(0, SeekOrigin.Begin); //设置指针读取位置 + } + + /// + /// 组装QueryString的方法 + /// 参数之间用&连接,首位没有符号,如:a=1&b=2&c=3 + /// + /// + /// + public static string GetQueryString(this Dictionary formData) + { + if (formData == null || formData.Count == 0) + { + return ""; + } + + StringBuilder sb = new StringBuilder(); + int i = 0; + foreach (KeyValuePair kv in formData) + { + i++; + sb.AppendFormat("{0}={1}", kv.Key, kv.Value); + if (i < formData.Count) + { + sb.Append("&"); + } + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ImgHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ImgHelper.cs new file mode 100644 index 0000000..9f9fdc3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ImgHelper.cs @@ -0,0 +1,158 @@ +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; +using System.Net; +using Znyc.Admin.Commons.Log; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 图片处理 + /// + public class ImgHelper + { + /// + /// 生成缩略图 + /// + /// 源文件 + /// 缩略图 + /// 宽 + /// 高 + /// + public static void MakeThumbnail(string originalImagePath, + string thumbnailPath, + int width = 120, int height = 90, string mode = "H") + { + Image image = Image.FromFile(originalImagePath); + if (image.Width <= width && image.Height <= height) + { + File.Copy(originalImagePath, thumbnailPath, true); + image.Dispose(); + } + else + { + int width2 = image.Width; + int height2 = image.Height; + float num = height / (float)height2; + if (width / (float)width2 < num) + { + num = width / (float)width2; + } + + width = (int)(width2 * num); + height = (int)(height2 * num); + Image image2 = new Bitmap(width, height); + Graphics graphics = Graphics.FromImage(image2); + graphics.Clear(Color.White); + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.DrawImage(image, new Rectangle(0, 0, width, height), new Rectangle(0, 0, width2, height2), + GraphicsUnit.Pixel); + EncoderParameters encoderParameters = new EncoderParameters(); + EncoderParameter encoderParameter = new EncoderParameter(Encoder.Quality, 100L); + encoderParameters.Param[0] = encoderParameter; + ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); + ImageCodecInfo encoder = null; + int num2 = 0; + while (num2 < imageEncoders.Length) + { + if (!imageEncoders[num2].FormatDescription.Equals("JPEG")) + { + num2++; + continue; + } + + encoder = imageEncoders[num2]; + break; + } + + image2.Save(thumbnailPath, encoder, encoderParameters); + encoderParameters.Dispose(); + encoderParameter.Dispose(); + image.Dispose(); + image2.Dispose(); + graphics.Dispose(); + } + } + + /// + /// 获取网络图片 + /// + /// + /// + public static Bitmap GetNetImg(string imgUrl) + { + try + { + Random random = new Random(); + imgUrl = !imgUrl.Contains("?") + ? imgUrl + "?aid=" + random.NextDouble() + : imgUrl + "&aid=" + random.NextDouble(); + WebRequest webRequest = WebRequest.Create(imgUrl); + WebResponse response = webRequest.GetResponse(); + Stream responseStream = response.GetResponseStream(); + Image image = Image.FromStream(responseStream); + responseStream.Close(); + responseStream.Dispose(); + webRequest = null; + response = null; + return (Bitmap)image; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取网络图片错误", ex); + return new Bitmap(100, 100); + } + } + + /// + /// 将图片裁剪成圆形 + /// + /// + /// + /// + /// + /// + public static Image CutEllipse(Image img, Rectangle rec, Size size, string imgSavePath) + { + Bitmap bitmap = new Bitmap(size.Width, size.Height); + using (Graphics g = Graphics.FromImage(bitmap)) + { + using (TextureBrush br = new TextureBrush(img, WrapMode.Clamp, rec)) + { + br.ScaleTransform(bitmap.Width / (float)rec.Width, bitmap.Height / (float)rec.Height); + g.SmoothingMode = SmoothingMode.AntiAlias; + g.FillEllipse(br, new Rectangle(Point.Empty, size)); + } + } + + bitmap.Save(imgSavePath, ImageFormat.Png); + return bitmap; + } + + /// + /// 将图片裁剪成圆形 + /// + /// + /// + /// + /// + public static Bitmap CutEllipse(Image img, Rectangle rec, Size size) + { + Bitmap bitmap = new Bitmap(size.Width, size.Height); + using (Graphics g = Graphics.FromImage(bitmap)) + { + using (TextureBrush br = new TextureBrush(img, WrapMode.Clamp, rec)) + { + br.ScaleTransform(bitmap.Width / (float)rec.Width, bitmap.Height / (float)rec.Height); + g.SmoothingMode = SmoothingMode.AntiAlias; + g.FillEllipse(br, new Rectangle(Point.Empty, size)); + } + } + + return bitmap; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/IntJsonConverter.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/IntJsonConverter.cs new file mode 100644 index 0000000..d0a883c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/IntJsonConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Znyc.Admin.Commons.Extensions; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// + /// + public class IntJsonConverter : JsonConverter + { + /// + /// + /// + /// + /// + /// + /// + public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Number) + { + return reader.GetInt32(); + } + + return reader.GetString().ToInt(); + } + + /// + /// + /// + /// + /// + /// + public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) + { + writer.WriteNumberValue(value); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/NPOIHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/NPOIHelper.cs new file mode 100644 index 0000000..de6d557 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/NPOIHelper.cs @@ -0,0 +1,627 @@ +using NPOI.HPSF; +using NPOI.HSSF.UserModel; +using NPOI.SS.UserModel; +using NPOI.XSSF.UserModel; +using System; +using System.Data; +using System.IO; +using System.Text; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// office 导入导出 + /// + public class NPOIHelper + { + /// + /// DataTable 导出到 Excel 的 MemoryStream + /// + /// 源 DataTable + /// 表头文本 空值未不要表头标题 + /// + public static MemoryStream ExportExcel(DataTable dtSource, string strHeaderText) + { + HSSFWorkbook workbook = new HSSFWorkbook(); + ISheet sheet = workbook.CreateSheet(); + + #region 文件属性 + + DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); + dsi.Company = "Znyc.Admin.com"; + workbook.DocumentSummaryInformation = dsi; + SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); + si.Author = "Znyc.Admin.com"; + si.ApplicationName = "Znyc.Admin.com"; + si.LastAuthor = "Znyc.Admin.com"; + si.Comments = ""; + si.Title = ""; + si.Subject = ""; + si.CreateDateTime = DateTime.Now; + workbook.SummaryInformation = si; + + #endregion 文件属性 + + ICellStyle dateStyle = workbook.CreateCellStyle(); + IDataFormat format = workbook.CreateDataFormat(); + dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); + int[] arrColWidth = new int[dtSource.Columns.Count]; + foreach (DataColumn item in dtSource.Columns) + { + arrColWidth[item.Ordinal] = Encoding.GetEncoding("gb2312").GetBytes(item.ColumnName.ToString()).Length; + } + + for (int i = 0; i < dtSource.Rows.Count; i++) + { + for (int j = 0; j < dtSource.Columns.Count; j++) + { + int intTemp = Encoding.GetEncoding("gb2312").GetBytes(dtSource.Rows[i][j].ToString()).Length; + if (intTemp > arrColWidth[j]) + { + arrColWidth[j] = intTemp; + } + } + } + + int rowIndex = 0; + int intTop = 0; + foreach (DataRow row in dtSource.Rows) + { + #region 新建表、填充表头、填充列头,样式 + + if (rowIndex == 65535 || rowIndex == 0) + { + if (rowIndex != 0) + { + sheet = workbook.CreateSheet(); + } + + intTop = 0; + + #region 表头及样式 + + { + if (strHeaderText.Length > 0) + { + IRow headerRow = sheet.CreateRow(intTop); + intTop += 1; + headerRow.HeightInPoints = 25; + headerRow.CreateCell(0).SetCellValue(strHeaderText); + ICellStyle headStyle = workbook.CreateCellStyle(); + headStyle.Alignment = HorizontalAlignment.Center; + IFont font = workbook.CreateFont(); + font.FontHeightInPoints = 20; + font.Boldweight = 700; + headStyle.SetFont(font); + headerRow.GetCell(0).CellStyle = headStyle; + sheet.AddMergedRegion( + new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); + } + } + + #endregion 表头及样式 + + #region 列头及样式 + + { + IRow headerRow = sheet.CreateRow(intTop); + intTop += 1; + ICellStyle headStyle = workbook.CreateCellStyle(); + headStyle.Alignment = HorizontalAlignment.Center; + IFont font = workbook.CreateFont(); + font.Boldweight = 700; + headStyle.SetFont(font); + foreach (DataColumn column in dtSource.Columns) + { + headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); + headerRow.GetCell(column.Ordinal).CellStyle = headStyle; + //设置列宽 + sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); + } + } + + #endregion 列头及样式 + + rowIndex = intTop; + } + + #endregion 新建表、填充表头、填充列头,样式 + + #region 填充内容 + + IRow dataRow = sheet.CreateRow(rowIndex); + foreach (DataColumn column in dtSource.Columns) + { + ICell newCell = dataRow.CreateCell(column.Ordinal); + string drValue = row[column].ToString(); + switch (column.DataType.ToString()) + { + case "System.String": //字符串类型 + newCell.SetCellValue(drValue); + break; + + case "System.DateTime": //日期类型 + DateTime dateV; + DateTime.TryParse(drValue, out dateV); + newCell.SetCellValue(dateV); + newCell.CellStyle = dateStyle; //格式化显示 + break; + + case "System.Boolean": //布尔型 + bool boolV = false; + bool.TryParse(drValue, out boolV); + newCell.SetCellValue(boolV); + break; + + case "System.Int16": + case "System.Int32": + case "System.Int64": + case "System.Byte": + int intV = 0; + int.TryParse(drValue, out intV); + newCell.SetCellValue(intV); + break; + + case "System.Decimal": + case "System.Double": + double doubV = 0; + double.TryParse(drValue, out doubV); + newCell.SetCellValue(doubV); + break; + + case "System.DBNull": //空值处理 + newCell.SetCellValue(""); + break; + + default: + newCell.SetCellValue(""); + break; + } + } + + #endregion 填充内容 + + rowIndex++; + } + + using (MemoryStream ms = new MemoryStream()) + { + workbook.Write(ms); + ms.Flush(); + ms.Position = 0; + return ms; + } + } + + /// + /// DaataTable 导出到 Excel 文件 + /// + /// 源 DataaTable + /// 表头文本 + /// 保存位置(文件名及路径) + public static void ExportExcel(DataTable dtSource, string strHeaderText, string strFileName) + { + using (MemoryStream ms = ExportExcel(dtSource, strHeaderText)) + { + using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) + { + byte[] data = ms.ToArray(); + fs.Write(data, 0, data.Length); + fs.Flush(); + } + } + } + + /// + /// 读取 excel + /// 默认第一行为标头 + /// + /// excel 文档路径 + /// + public static DataTable ImportExcel(string strFileName) + { + DataTable dt = new DataTable(); + HSSFWorkbook hssfworkbook; + using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) + { + hssfworkbook = new HSSFWorkbook(file); + } + + ISheet sheet = hssfworkbook.GetSheetAt(0); + System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); + IRow headerRow = sheet.GetRow(0); + int cellCount = headerRow.LastCellNum; + for (int j = 0; j < cellCount; j++) + { + ICell cell = headerRow.GetCell(j); + dt.Columns.Add(cell.ToString()); + } + + for (int i = sheet.FirstRowNum + 1; i <= sheet.LastRowNum; i++) + { + IRow row = sheet.GetRow(i); + if (row.GetCell(row.FirstCellNum) != null && row.GetCell(row.FirstCellNum).ToString().Length > 0) + { + DataRow dataRow = dt.NewRow(); + for (int j = row.FirstCellNum; j < cellCount; j++) + { + if (row.GetCell(j) != null) + { + dataRow[j] = row.GetCell(j).ToString(); + } + } + + dt.Rows.Add(dataRow); + } + } + + return dt; + } + + /// + /// DataSet 导出到 Excel 的 MemoryStream + /// + /// 源 DataSet + /// 表头文本 空值未不要表头标题(多个表对应多个表头以英文逗号(,)分开,个数应与表相同) + /// + public static MemoryStream ExportExcel(DataSet dsSource, string strHeaderText) + { + HSSFWorkbook workbook = new HSSFWorkbook(); + + #region 文件属性 + + DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); + dsi.Company = "Znyc.Admin.com"; + workbook.DocumentSummaryInformation = dsi; + SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); + si.Author = "Znyc.Admin.com"; + si.ApplicationName = "Znyc.Admin.com"; + si.LastAuthor = "Znyc.Admin.com"; + si.Comments = ""; + si.Title = ""; + si.Subject = ""; + si.CreateDateTime = DateTime.Now; + workbook.SummaryInformation = si; + + #endregion 文件属性 + + #region 注释 + + //ICellStyle dateStyle = workbook.CreateCellStyle(); + //IDataFormat format = workbook.CreateDataFormat(); + //dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); + + //ISheet sheet = workbook.CreateSheet(); + //int[] arrColWidth = new int[dtSource.Columns.Count]; + //foreach (DataColumn item in dtSource.Columns) + //{ + // arrColWidth[item.Ordinal] = Encoding.GetEncoding("gb2312").GetBytes(item.ColumnName.ToString()).Length; + //} + //for (int i = 0; i < dtSource.Rows.Count; i++) + //{ + // for (int j = 0; j < dtSource.Columns.Count; j++) + // { + // int intTemp = Encoding.GetEncoding("gb2312").GetBytes(dtSource.Rows[i][j].ToString()).Length; + // if (intTemp > arrColWidth[j]) + // { + // arrColWidth[j] = intTemp; + // } + // } + //} + //int rowIndex = 0; + //int intTop = 0; + //foreach (DataRow row in dtSource.Rows) + //{ + // #region 新建表、填充表头、填充列头,样式 + // if (rowIndex == 65535 || rowIndex == 0) + // { + // if (rowIndex != 0) + // { + // sheet = workbook.CreateSheet(); + // } + // intTop = 0; + // #region 表头及样式 + // { + // if (strHeaderText.Length > 0) + // { + // IRow headerRow = sheet.CreateRow(intTop); + // intTop += 1; + // headerRow.HeightInPoints = 25; + // headerRow.CreateCell(0).SetCellValue(strHeaderText); + // ICellStyle headStyle = workbook.CreateCellStyle(); + // headStyle.Alignment = HorizontalAlignment.CENTER; + // IFont font = workbook.CreateFont(); + // font.FontHeightInPoints = 20; + // font.Boldweight = 700; + // headStyle.SetFont(font); + // headerRow.GetCell(0).CellStyle = headStyle; + // sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); + + // } + // } + // #endregion + // #region 列头及样式 + // { + // IRow headerRow = sheet.CreateRow(intTop); + // intTop += 1; + // ICellStyle headStyle = workbook.CreateCellStyle(); + // headStyle.Alignment = HorizontalAlignment.CENTER; + // IFont font = workbook.CreateFont(); + // font.Boldweight = 700; + // headStyle.SetFont(font); + // foreach (DataColumn column in dtSource.Columns) + // { + // headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); + // headerRow.GetCell(column.Ordinal).CellStyle = headStyle; + // //设置列宽 + // sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); + // } + + // } + // #endregion + // rowIndex = intTop; + // } + // #endregion + // #region 填充内容 + // IRow dataRow = sheet.CreateRow(rowIndex); + // foreach (DataColumn column in dtSource.Columns) + // { + // ICell newCell = dataRow.CreateCell(column.Ordinal); + // string drValue = row[column].ToString(); + // switch (column.DataType.ToString()) + // { + // case "System.String"://字符串类型 + // newCell.SetCellValue(drValue); + // break; + // case "System.DateTime"://日期类型 + // DateTime dateV; + // DateTime.TryParse(drValue, out dateV); + // newCell.SetCellValue(dateV); + // newCell.CellStyle = dateStyle;//格式化显示 + // break; + // case "System.Boolean"://布尔型 + // bool boolV = false; + // bool.TryParse(drValue, out boolV); + // newCell.SetCellValue(boolV); + // break; + // case "System.Int16": + // case "System.Int32": + // case "System.Int64": + // case "System.Byte": + // int intV = 0; + // int.TryParse(drValue, out intV); + // newCell.SetCellValue(intV); + // break; + // case "System.Decimal": + // case "System.Double": + // double doubV = 0; + // double.TryParse(drValue, out doubV); + // newCell.SetCellValue(doubV); + // break; + // case "System.DBNull"://空值处理 + // newCell.SetCellValue(""); + // break; + // default: + // newCell.SetCellValue(""); + // break; + // } + // } + // #endregion + // rowIndex++; + //} + + #endregion 注释 + + string[] strNewText = strHeaderText.Split(Convert.ToChar(",")); + if (dsSource.Tables.Count == strNewText.Length) + { + for (int i = 0; i < dsSource.Tables.Count; i++) + { + ExportFromDSExcel(workbook, dsSource.Tables[i], strNewText[i]); + } + } + + using (MemoryStream ms = new MemoryStream()) + { + workbook.Write(ms); + ms.Flush(); + ms.Position = 0; + return ms; + } + } + + /// + /// DataTable 导出到 Excel 的 MemoryStream + /// + /// 源 workbook + /// 源 DataTable + /// 表头文本 空值未不要表头标题(多个表对应多个表头以英文逗号(,)分开,个数应与表相同) + /// + public static void ExportFromDSExcel(HSSFWorkbook workbook, DataTable dtSource, string strHeaderText) + { + ICellStyle dateStyle = workbook.CreateCellStyle(); + IDataFormat format = workbook.CreateDataFormat(); + dateStyle.DataFormat = format.GetFormat("yyyy-MM-dd HH:mm:ss"); + ISheet sheet = workbook.CreateSheet(strHeaderText); + + int[] arrColWidth = new int[dtSource.Columns.Count]; + foreach (DataColumn item in dtSource.Columns) + { + arrColWidth[item.Ordinal] = Encoding.GetEncoding("gb2312").GetBytes(item.ColumnName.ToString()).Length; + } + + for (int i = 0; i < dtSource.Rows.Count; i++) + { + for (int j = 0; j < dtSource.Columns.Count; j++) + { + int intTemp = Encoding.GetEncoding("gb2312").GetBytes(dtSource.Rows[i][j].ToString()).Length; + if (intTemp > arrColWidth[j]) + { + arrColWidth[j] = intTemp; + } + } + } + + int rowIndex = 0; + int intTop = 0; + foreach (DataRow row in dtSource.Rows) + { + #region 新建表、填充表头、填充列头,样式 + + if (rowIndex == 65535 || rowIndex == 0) + { + if (rowIndex != 0) + { + sheet = workbook.CreateSheet(); + } + + intTop = 0; + + #region 表头及样式 + + { + if (strHeaderText.Length > 0) + { + IRow headerRow = sheet.CreateRow(intTop); + intTop += 1; + headerRow.HeightInPoints = 25; + headerRow.CreateCell(0).SetCellValue(strHeaderText); + ICellStyle headStyle = workbook.CreateCellStyle(); + headStyle.Alignment = HorizontalAlignment.Center; + IFont font = workbook.CreateFont(); + font.FontHeightInPoints = 20; + font.Boldweight = 700; + headStyle.SetFont(font); + headerRow.GetCell(0).CellStyle = headStyle; + sheet.AddMergedRegion( + new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); + } + } + + #endregion 表头及样式 + + #region 列头及样式 + + { + IRow headerRow = sheet.CreateRow(intTop); + intTop += 1; + ICellStyle headStyle = workbook.CreateCellStyle(); + headStyle.Alignment = HorizontalAlignment.Center; + IFont font = workbook.CreateFont(); + font.Boldweight = 700; + headStyle.SetFont(font); + foreach (DataColumn column in dtSource.Columns) + { + headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); + headerRow.GetCell(column.Ordinal).CellStyle = headStyle; + //设置列宽 + // sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); // 设置设置列宽 太长会报错 修改2014 年9月22日 + int dd = (arrColWidth[column.Ordinal] + 1) * 256; + + if (dd > 200 * 256) + { + dd = 100 * 256; + } + + sheet.SetColumnWidth(column.Ordinal, dd); + } + } + + #endregion 列头及样式 + + rowIndex = intTop; + } + + #endregion 新建表、填充表头、填充列头,样式 + + #region 填充内容 + + IRow dataRow = sheet.CreateRow(rowIndex); + foreach (DataColumn column in dtSource.Columns) + { + ICell newCell = dataRow.CreateCell(column.Ordinal); + string drValue = row[column].ToString(); + switch (column.DataType.ToString()) + { + case "System.String": //字符串类型 + newCell.SetCellValue(drValue); + break; + + case "System.DateTime": //日期类型 + if (drValue.Length > 0) + { + DateTime.TryParse(drValue, out DateTime dateV); + newCell.SetCellValue(dateV); + newCell.CellStyle = dateStyle; //格式化显示 + } + else + { + newCell.SetCellValue(drValue); + } + + break; + + case "System.Boolean": //布尔型 + bool boolV = false; + bool.TryParse(drValue, out boolV); + newCell.SetCellValue(boolV); + break; + + case "System.Int16": + case "System.Int32": + case "System.Int64": + case "System.Byte": + int intV = 0; + int.TryParse(drValue, out intV); + newCell.SetCellValue(intV); + break; + + case "System.Decimal": + case "System.Double": + double doubV = 0; + double.TryParse(drValue, out doubV); + newCell.SetCellValue(doubV); + break; + + case "System.DBNull": //空值处理 + newCell.SetCellValue(""); + break; + + default: + newCell.SetCellValue(""); + break; + } + } + + #endregion 填充内容 + + rowIndex++; + } + } + + /// + /// 按指定长度创建列并带入样式 + /// + /// + /// + /// + /// + public static bool CreateCellsWithLength(XSSFRow hssfrow, int len, XSSFCellStyle cellstyle) + { + try + { + for (int i = 0; i < len; i++) + { + hssfrow.CreateCell(i); + hssfrow.Cells[i].CellStyle = cellstyle; + } + + return true; + } + catch (Exception ce) + { + throw new Exception("CreateCellsWithLength:" + ce.Message); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ObjectReplaceHtmlHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ObjectReplaceHtmlHelper.cs new file mode 100644 index 0000000..7edfc09 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/ObjectReplaceHtmlHelper.cs @@ -0,0 +1,61 @@ +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 用对象属性及属性值替换预设字符串 + /// 主要应用于模板打印,导出 + /// + public class ObjectReplaceHtmlHelper + { + /// + /// 用实体属性替换相关的字符串,主要应用于打印和导出 + /// 方法将日期时间型属性值截取为日期型,格式“YYYY-MM-DD”, + /// 将布尔型属性值调整为是或否 + /// + /// 实体对象 + /// 要替换的原字符串 + /// 变量前缀 + /// + public static string ObjectReplaceString(object objInfo, string strReplace, string prefix = "") + { + string result = string.Empty; + string nowReplace = strReplace; + System.Type type = objInfo.GetType(); //获得该类的Type + foreach (System.Reflection.PropertyInfo pi in type.GetProperties()) + { + string name = pi.Name; //获得属性的名字,后面就可以根据名字判断来进行些自己想要的操作 + object value = pi.GetValue(objInfo, null); //用pi.GetValue获得值 + System.Type propertyType = value?.GetType() ?? typeof(object); //获得属性的类型 + string replaceOld = "$" + prefix + name; + string newStrValue = ""; + if (value != null) + { + //将日期时间型和布尔型数据进行处理,其他枚举数据提前处理 + if (propertyType.Name == "DateTime") //如果是时间型取日期 + { + newStrValue = value.ToString().Substring(0, 10); + } + else if (propertyType.Name == "Boolean") //布尔型转为是或否 + { + if (bool.TryParse(value.ToString(), out bool blvalue)) + { + newStrValue = "是"; + } + else + { + newStrValue = "否"; + } + } + else + { + newStrValue = value.ToString(); + } + } + + nowReplace = nowReplace.Replace(replaceOld, newStrValue); + } + + result += nowReplace; + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/RuntimeHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/RuntimeHelper.cs new file mode 100644 index 0000000..a2de195 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/RuntimeHelper.cs @@ -0,0 +1,141 @@ +using Microsoft.Extensions.DependencyModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using Znyc.Admin.Commons.Options; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// + /// + public class RuntimeHelper + { + /// + /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包 + /// + /// + public static IList GetAllAssemblies() + { + List list = new List(); + DependencyContext deps = DependencyContext.Default; + //排除所有的系统程序集、Nuget下载包 + IEnumerable libs = deps.CompileLibraries.Where(lib => lib.Type == AssembleTypeConsts.Project); //只获取本项目用到的包 + foreach (CompilationLibrary lib in libs) + { + try + { + Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name)); + list.Add(assembly); + } + catch (Exception) + { + // ignored + } + } + + return list; + } + + /// + /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包和Znyc.Admin.Commons.dll + /// 获取所有关于Znyc的程序集 + /// + /// + public static IList GetAllZnycAssemblies() + { + List list = new List(); + DependencyContext deps = DependencyContext.Default; + //排除所有的系统程序集、Nuget下载包 + IEnumerable libs = deps.CompileLibraries.Where(lib => + lib.Type == AssembleTypeConsts.Project || lib.Name.StartsWith("Znyc")); //只获取本项目用到的包 + foreach (CompilationLibrary lib in libs) + { + try + { + if (lib.Name != "Znyc.Admin.Commons") + { + Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name)); + list.Add(assembly); + } + } + catch (Exception) + { + // ignored + } + } + + return list; + } + + /// + /// + /// + /// + /// + public static Assembly GetAssembly(string assemblyName) + { + return GetAllZnycAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName)); + } + + /// + /// + /// + /// + public static IList GetAllTypes() + { + List list = new List(); + foreach (Assembly assembly in GetAllAssemblies()) + { + IEnumerable typeInfos = assembly.DefinedTypes; + foreach (TypeInfo typeInfo in typeInfos) + { + list.Add(typeInfo.AsType()); + } + } + + return list; + } + + /// + /// + /// + /// + /// + public static IList GetTypesByAssembly(string assemblyName) + { + List list = new List(); + Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName)); + IEnumerable typeInfos = assembly.DefinedTypes; + foreach (TypeInfo typeInfo in typeInfos) + { + list.Add(typeInfo.AsType()); + } + + return list; + } + + /// + /// 获取实现类 + /// + /// + /// + /// + public static Type GetImplementType(string typeName, Type baseInterfaceType) + { + return GetAllTypes().FirstOrDefault(t => + { + if (t.Name == typeName && + t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name)) + { + TypeInfo typeInfo = t.GetTypeInfo(); + return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType; + } + + return false; + }); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/SessionHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/SessionHelper.cs new file mode 100644 index 0000000..957de5e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/SessionHelper.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Http; +using System.Text; +using Znyc.Admin.Commons.Extensions; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// Session帮助类,可在非controler中读取或保存session + /// + public static class SessionHelper + { + /// + /// + /// + public static HttpContext HttpHelper => HttpContextHelper.HttpContext; + + /// + /// 设置 Session + /// + /// + /// + public static void SetSession(string key, object value) + { + HttpHelper.Session.Set(key, value); + } + + /// + /// 获取 Session + /// + /// + /// + /// + public static T GetSession(string key) + { + return HttpHelper.Session.Get(key); + } + + /// + /// 获取 Session + /// + /// + /// + public static string GetString(string key) + { + return HttpHelper.Session.GetString(key); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/SignHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/SignHelper.cs new file mode 100644 index 0000000..3fa10b6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/SignHelper.cs @@ -0,0 +1,193 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Text; +using System.Web; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Options; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 签名验证自定义类 + /// + public class SignHelper + { + /// + /// 全局过滤器验证签名 + /// + /// + /// + public static CommonResult CheckSign(HttpContext httpContext) + { + CommonResult result = new CommonResult(); + //从http请求的头里面获取参数 + HttpRequest request = httpContext.Request; + string appId = ""; //客户端应用唯一标识 + string nonce = ""; //随机字符串 + string signature = ""; //参数签名,去除空参数,按字母倒序排序进行Md5签名 为了提高传参过程中,防止参数被恶意修改,在请求接口的时候加上sign可以有效防止参数被篡改 + long timeStamp; //时间戳, 校验5分钟内有效 + try + { + appId = request.Headers["appId"].SingleOrDefault(); + nonce = request.Headers["nonce"].SingleOrDefault(); + timeStamp = Convert.ToInt64(request.Headers["timeStamp"].SingleOrDefault()); + signature = request.Headers["signature"].SingleOrDefault(); + } + catch (Exception ex) + { + result.ErrCode = "40004"; + result.ErrMsg = "签名参数异常:" + ex.Message; + return result; + } + + //appId是否为可用的AllowCacheApp allowCacheApp = VerifyAppId(appId); + //if (allowCacheApp == null) + //{ + // result.ErrCode = "40004"; + // result.ErrMsg = "AppId不被允许访问:" + appId; + // return result; + //} + + //判断timespan是否有效,请求是否超时 + DateTime tonow = timeStamp.UnixTimeToDateTime(); + int expires_minute = tonow.Minute - DateTime.Now.Minute; + if (expires_minute > 5 || expires_minute < -5) + { + result.ErrCode = "40004"; + result.ErrMsg = "接口请求超时"; + return result; + } + + //根据请求类型拼接参数 + NameValueCollection form = HttpUtility.ParseQueryString(request.QueryString.ToString()); + string data = string.Empty; + if (form.Count > 0) + { + data = GetQueryString(form); + } + else + { + //request.EnableBuffering(); + request.Body.Seek(0, SeekOrigin.Begin); + Stream stream = request.Body; + StreamReader streamReader = new StreamReader(stream); + data = streamReader.ReadToEndAsync().Result; + request.Body.Seek(0, SeekOrigin.Begin); + } + + CacheHelper cacheHelper = new CacheHelper(); + object reqtimeStampCache = cacheHelper.Get("request_" + timeStamp + nonce); + if (reqtimeStampCache != null) + { + result.ErrCode = "40004"; + result.ErrMsg = "无效签名"; + return result; + } + + TimeSpan expiresSliding = DateTime.Now.AddMinutes(120) - DateTime.Now; + cacheHelper.Add("request_" + timeStamp + nonce, timeStamp + nonce, expiresSliding); + //bool blValidate = Validate(timeStamp.ToString(), nonce, allowCacheApp.AppSecret, data, signature); + //if (!blValidate) + //{ + // result.ErrCode = "40004"; + // result.ErrMsg = "无效签名"; + // return result; + //} + //else + //{ + result.ErrCode = "0"; + result.Success = true; + return result; + //} + } + + /// + /// get请求查询参数, url上直接接参数时,通过此方法获取 + /// + /// 请求参数 + /// + public static string GetQueryString(NameValueCollection form) + { + //第一步:取出所有get参数 + Dictionary parames = new Dictionary(); + for (int f = 0; f < form.Count; f++) + { + string key = form.Keys[f]; + if (key != null) + { + parames.Add(key, form[key]); + } + } + + // 第二步:把字典按Key的字母顺序排序 + IDictionary sortedParams = new SortedDictionary(parames); + IEnumerator> dem = sortedParams.GetEnumerator(); + + // 第三步:把所有参数名和参数值串在一起 + StringBuilder query = new StringBuilder(""); //签名字符串 + if (parames == null || parames.Count == 0) + { + return query.ToString(); + } + + while (dem.MoveNext()) + { + string key = dem.Current.Key; + string value = dem.Current.Value; + if (!string.IsNullOrEmpty(key)) + { + query.Append(key).Append(value); + } + } + + return query.ToString(); + } + + /// + /// 签名验证 + /// + /// 时间戳 + /// 随机字符串 + /// 客户端应用密钥 + /// 接口参数内容 + /// 当前请求内容的数字签名 + /// + public static bool Validate(string timeStamp, string nonce, string appSecret, string data, string signature) + { + string signStr = timeStamp + nonce + data + appSecret; + string signMd5 = MD5Util.GetMD5_32(signStr); + return signMd5 == signature; + } + + /// + /// 验证appId是否被允许 + /// + /// + /// + private static AllowCacheApp VerifyAppId(string appId) + { + AllowCacheApp allowCacheApp = new AllowCacheApp(); + if (string.IsNullOrEmpty(appId)) + { + return allowCacheApp; + } + + CacheHelper cacheHelper = new CacheHelper(); + List list = cacheHelper.Get("AllowAppId").ToJson().ToList(); + if (list.Count > 0) + { + allowCacheApp = list.Where(s => s.AppId == appId).FirstOrDefault(); + } + + return allowCacheApp; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/StringHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/StringHelper.cs new file mode 100644 index 0000000..ac2bcfd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/StringHelper.cs @@ -0,0 +1,152 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Text; +using System.Text.RegularExpressions; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 字符串帮助类 + /// + public class StringHelper + { + private static readonly char[] _constant = + { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' + }; + + /// + /// 生成随机字符串,默认32位 + /// + /// 随机数长度 + /// + public static string GenerateRandom(int length = 32) + { + StringBuilder newRandom = new StringBuilder(); + Random rd = new Random(); + for (int i = 0; i < length; i++) + { + newRandom.Append(_constant[rd.Next(_constant.Length)]); + } + + return newRandom.ToString(); + } + + /// + /// 生成随机字符串,只包含数字 + /// + /// + /// + public static string GenerateRandomNumber(int length = 6) + { + StringBuilder newRandom = new StringBuilder(); + Random rd = new Random(); + for (int i = 0; i < length; i++) + { + newRandom.Append(_constant[rd.Next(10)]); + } + + return newRandom.ToString(); + } + + /// + /// + /// + /// + /// + /// + public static string Format(string str, object obj) + { + if (string.IsNullOrEmpty(str)) + { + return str; + } + + string s = str; + if (obj.GetType().Name == "JObject") + { + foreach (System.Collections.Generic.KeyValuePair item in (JObject)obj) + { + string k = item.Key; + string v = item.Value.ToString(); + s = Regex.Replace(s, "\\{" + k + "\\}", v, RegexOptions.IgnoreCase); + } + } + else + { + foreach (System.Reflection.PropertyInfo p in obj.GetType().GetProperties()) + { + string xx = p.Name; + string yy = p.GetValue(obj).ToString(); + s = Regex.Replace(s, "\\{" + xx + "\\}", yy, RegexOptions.IgnoreCase); + } + } + + return s; + } + + /// + /// 隐藏手机号 + /// + /// + /// + public static string ConvertPhoneNo(string Phone) + { + return Regex.Replace(Phone, "(\\d{3})\\d{4}(\\d{4})", "$1****$2"); + } + + /// + /// 隐藏身份证号 + /// + /// + /// + public static string ConvertIdCard(string idCard) + { + return Regex.Replace(idCard, "(\\d{6})\\d{8}(\\w{4})", "$1********$2"); + } + + /// + /// + /// + /// + /// + public static string ChineseMainlandForPhone(string phone) + { + return string.Format("+86{0}", phone); + } + /// + /// 计算年龄 + /// + /// + /// + public static int GetAgeByBirthDate(DateTime birthDate) + { + int age = 0; + if (!birthDate.ToString().Equals("0001/1/1 0:00:00")) + { + DateTime now = DateTime.Now; + age = now.Year - birthDate.Year; + if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) + { + age--; + } + } + return age < 0 ? 0 : age; + } + + /// + /// 计算百分比 + /// + /// 除数 + /// 被除数 + /// + public static decimal GetPercent(decimal divisor, decimal dividend) + { + if (divisor == 0 || dividend == 0) + { + return Convert.ToDecimal(0); + } + return Math.Floor(Math.Round(decimal.Parse((divisor / dividend).ToString("0.000")), 2) * 100); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/UpperFirstCaseNamingPolicy.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/UpperFirstCaseNamingPolicy.cs new file mode 100644 index 0000000..8111013 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/UpperFirstCaseNamingPolicy.cs @@ -0,0 +1,21 @@ +using System.Text.Json; +using Znyc.Admin.Commons.Extend; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// 首字母大写 + /// + public class UpperFirstCaseNamingPolicy : JsonNamingPolicy + { + /// + /// + /// + /// + /// + public override string ConvertName(string name) + { + return name.UpperFirst(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/XmlConverter.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/XmlConverter.cs new file mode 100644 index 0000000..d7b66c9 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Helpers/XmlConverter.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using System.Xml.Linq; +using System.Xml.Serialization; + +namespace Znyc.Admin.Commons.Helpers +{ + /// + /// XML文件与对象相互转化操作 + /// + public class XmlConverter + { + /// + /// 将对象转换为xml格式 + /// + /// + /// + /// xml文件路径 + /// + public static void Serialize(T obj, string xmlFilePath) + { + FileStream xmlfs = null; + try + { + XmlSerializer serializer = new XmlSerializer(typeof(T)); + xmlfs = new FileStream(xmlFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); + serializer.Serialize(xmlfs, obj); + } + catch (Exception ex) + { + //throw ex; + } + finally + { + if (xmlfs != null) + { + xmlfs.Close(); + } + } + } + + /// + /// 将xml格式转为对象 + /// + /// + /// xml文件路径 + /// + public static T Deserialize(string xmlFilePath) + { + XDocument doc = XDocument.Load(xmlFilePath); + XmlSerializer serializer = new XmlSerializer(typeof(T)); + StringReader reader = new StringReader(doc.ToString()); + T result = (T)serializer.Deserialize(reader); + reader.Close(); + reader.Dispose(); + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/IoC/IoCContainer.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/IoC/IoCContainer.cs new file mode 100644 index 0000000..cdf52a1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/IoC/IoCContainer.cs @@ -0,0 +1,21 @@ +using Znyc.Admin.Commons.Core.App; + +namespace Znyc.Admin.Commons.IoC +{ + /// + ///IOC 容器 + /// + public class IoCContainer + { + /// + /// 从容器中获取对象 Resolve an instance of the default requested type from the container + /// + /// 类型 + /// + /// 该方法即将废弃,请使用App.GetService(); + public static T Resolve() where T : class + { + return App.GetService(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Json/JsonHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Json/JsonHelper.cs new file mode 100644 index 0000000..78099d3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Json/JsonHelper.cs @@ -0,0 +1,136 @@ +using System.Collections.Generic; +using System.Data; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Unicode; +using Znyc.Admin.Commons.Helpers; + +namespace Znyc.Admin.Commons.Json +{ + /// + /// JSON序列化、反序列化扩展类。 + /// + public static class JsonHelper + { + /// + /// 对象序列化成JSON字符串。 + /// + /// 序列化对象 + /// + public static string ToJson(this object obj) + { + JsonSerializerOptions options = new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + AllowTrailingCommas = true + }; + //设置时间格式 + options.Converters.Add(new DateTimeJsonConverter()); + options.Converters.Add(new DateTimeNullableConverter()); + //设置bool获取格式 + options.Converters.Add(new BooleanJsonConverter()); + //设置数字 + options.Converters.Add(new IntJsonConverter()); + options.PropertyNamingPolicy = new UpperFirstCaseNamingPolicy(); + options.PropertyNameCaseInsensitive = true; //忽略大小写 + //JsonSerializerOptions options = new JsonSerializerOptions() + //{ + // WriteIndented = true, //格式化json字符串 + // AllowTrailingCommas = true, //可以结尾有逗号 + // //IgnoreNullValues = true, //可以有空值,转换json去除空值属性 + // IgnoreReadOnlyProperties = true, //忽略只读属性 + // PropertyNameCaseInsensitive = true, //忽略大小写 + // Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + //}; + return JsonSerializer.Serialize(obj, options); + } + + /// + /// JSON字符串序列化成对象。 + /// + /// 对象类型 + /// JSON字符串 + /// + public static T ToObject(this string json) + { + //JsonSerializerOptions options = new JsonSerializerOptions() + //{ + // WriteIndented = true, //格式化json字符串 + // AllowTrailingCommas = true, //可以结尾有逗号 + // //IgnoreNullValues = true, //可以有空值,转换json去除空值属性 + // IgnoreReadOnlyProperties = true, //忽略只读属性 + // PropertyNameCaseInsensitive = true, //忽略大小写 + // //PropertyNamingPolicy = JsonNamingPolicy.CamelCase //命名方式是默认还是CamelCase + // Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + //}; + + JsonSerializerOptions options = new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + AllowTrailingCommas = true + }; + //设置时间格式 + options.Converters.Add(new DateTimeJsonConverter()); + options.Converters.Add(new DateTimeNullableConverter()); + //设置bool获取格式 + options.Converters.Add(new BooleanJsonConverter()); + //设置数字 + options.Converters.Add(new IntJsonConverter()); + //options.PropertyNamingPolicy = new UpperFirstCaseNamingPolicy(); + options.PropertyNameCaseInsensitive = true; //忽略大小写 + return json == null ? default(T) : JsonSerializer.Deserialize(json, options); + } + + /// + /// JSON字符串序列化成集合。 + /// + /// 集合类型 + /// JSON字符串 + /// + public static List ToList(this string json) + { + //JsonSerializerOptions options = new JsonSerializerOptions() + //{ + // WriteIndented = true, //格式化json字符串 + // AllowTrailingCommas = true, //可以结尾有逗号 + // //IgnoreNullValues = true, //可以有空值,转换json去除空值属性 + // IgnoreReadOnlyProperties = true, //忽略只读属性 + // PropertyNameCaseInsensitive = true, //忽略大小写 + // //PropertyNamingPolicy = JsonNamingPolicy.CamelCase //命名方式是默认还是CamelCase + // Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + //}; + + JsonSerializerOptions options = new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + AllowTrailingCommas = true + }; + //设置时间格式 + options.Converters.Add(new DateTimeJsonConverter()); + options.Converters.Add(new DateTimeNullableConverter()); + //设置bool获取格式 + options.Converters.Add(new BooleanJsonConverter()); + //设置数字 + options.Converters.Add(new IntJsonConverter()); + //options.PropertyNamingPolicy = new UpperFirstCaseNamingPolicy(); + options.PropertyNameCaseInsensitive = true; //忽略大小写 + return json == null ? null : JsonSerializer.Deserialize>(json, options); + } + + /// + /// JSON字符串序列化成DataTable。 + /// + /// JSON字符串 + /// + public static DataTable ToTable(this string json) + { + return json == null ? null : JsonSerializer.Deserialize(json); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Linq/EnumerableExtentions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Linq/EnumerableExtentions.cs new file mode 100644 index 0000000..05831f6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Linq/EnumerableExtentions.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Znyc.Admin.Commons.Linq +{ + public static partial class EnumerableExtentions + { + public static T[] AsToArray(this IEnumerable source, bool isNullAsEmpty = false) + { + if (source == null) + { + return isNullAsEmpty ? new T[0] : null; + } + + return source as T[] ?? source.ToArray(); + } + + public static List AsToList(this IEnumerable source, bool isNullAsEmpty = false) + { + if (source == null) + { + return isNullAsEmpty ? new List() : null; + } + + return source as List ?? source.ToList(); + } + + public static void ForEach(this IEnumerable source, Action process) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (process == null) + { + throw new ArgumentNullException(nameof(process)); + } + + foreach (T item in source) + { + process(item); + } + } + + public static void ForEach(this IEnumerable source, Func process) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (process == null) + { + throw new ArgumentNullException(nameof(process)); + } + + foreach (T item in source) + { + process(item); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Log/DbLogType.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Log/DbLogType.cs new file mode 100644 index 0000000..8b373a0 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Log/DbLogType.cs @@ -0,0 +1,65 @@ +using System.ComponentModel; + +namespace Znyc.Admin.Commons.Log +{ + /// + /// 日志类型 + /// + public enum DbLogType + { + /// + /// 其他 + /// + [Description("其他")] Other = 0, + + /// + /// 登录 + /// + [Description("登录")] Login = 1, + + /// + /// 退出 + /// + [Description("退出")] Exit = 2, + + /// + /// 访问 + /// + [Description("访问")] Visit = 3, + + /// + /// 新增 + /// + [Description("新增")] Create = 4, + + /// + /// 删除 + /// + [Description("删除")] Delete = 5, + + /// + /// 修改 + /// + [Description("修改")] Update = 6, + + /// + /// 提交 + /// + [Description("提交")] Submit = 7, + + /// + /// 异常 + /// + [Description("异常")] Exception = 8, + + /// + /// 软删除 + /// + [Description("软删除")] DeleteSoft = 9, + + /// + /// 软删除 + /// + [Description("SQL语句")] SQL = 10 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Log/Log4netHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Log/Log4netHelper.cs new file mode 100644 index 0000000..47a8ab0 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Log/Log4netHelper.cs @@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 + * Author: Znyc + * Description: Znyc快速开发平台 + * Website:http://www.Znyc.Admin.com +*********************************************************************************/ + +using log4net; +using log4net.Config; +using log4net.Repository; +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; + +namespace Znyc.Admin.Commons.Log +{ + /// + /// log4net封装类 + /// *********************************使用说明********************************** + /// 1.首先将配置文件(log4net.config或App.config)放置在程序运行目录 + /// 2.调用SetConfig方法,并传入配置文件的全路径 + /// + public class Log4NetHelper + { + /// + /// log4net 仓储库 + /// + private static ILoggerRepository _repository; + + private static readonly ConcurrentDictionary Loggers = new ConcurrentDictionary(); + + /// + /// 读取配置文件,并使其生效。如果未找到配置文件,则抛出异常 + /// + /// + /// 配置文件全路径 + public static void SetConfig(ILoggerRepository repository, string configFilePath) + { + _repository = repository; + FileInfo fileInfo = new FileInfo(configFilePath); + if (!fileInfo.Exists) + { + throw new Exception("未找到配置文件" + configFilePath); + } + + XmlConfigurator.ConfigureAndWatch(_repository, fileInfo); + } + + /// + /// 获取记录器 + /// + /// soruce + /// + private static ILog GetLogger(string source) + { + if (Loggers.ContainsKey(source)) + { + return Loggers[source]; + } + else + { + ILog logger = LogManager.GetLogger(_repository.Name, source); + Loggers.TryAdd(source, logger); + return logger; + } + } + + #region Log a message object + + /// + /// 调试信息日志 + /// + /// 日志信息 + public static void Debug(string msg) + { + ILog logger = GetLogger("Debug"); + if (logger.IsDebugEnabled) + { + StackTrace stackTrace = new StackTrace(); + StackFrame stackFrame = stackTrace.GetFrame(1); + System.Reflection.MethodBase methodBase = stackFrame.GetMethod(); + string message = "方法名称:" + methodBase.Name + "\r\n日志内容:" + msg; + logger.Info(message); + } + } + + /// + /// 错误信息日志 + /// + /// 日志信息 + public static void Error(string msg) + { + ILog logger = GetLogger("Debug"); + if (logger.IsErrorEnabled) + { + StackTrace stackTrace = new StackTrace(); + StackFrame stackFrame = stackTrace.GetFrame(1); + System.Reflection.MethodBase methodBase = stackFrame.GetMethod(); + string message = "方法名称:" + methodBase.Name + "\r\n日志内容:" + msg; + logger.Info(message); + } + } + + /// + /// 异常错误信息日志 + /// + /// 异常抛出信息 + /// 异常信息 + public static void Error(string throwMsg, Exception ex) + { + ILog logger = GetLogger("Error"); + if (logger.IsErrorEnabled) + { + string message = + $"抛出信息:{throwMsg} \r\n异常类型:{ex.GetType().Name} \r\n异常信息:{ex.Message} \r\n堆栈调用:\r\n{ex.StackTrace}"; + logger.Error(message); + } + } + + /// + /// 异常错误信息 + /// + /// source + /// 异常抛出信息 + /// 异常信息 + public static void Error(Type source, object throwMsg, Exception ex) + { + ILog logger = GetLogger("Error"); + if (logger.IsErrorEnabled) + { + string message = + $"抛出信息:{throwMsg} \r\n异常类型:{ex.GetType().Name} \r\n异常信息:{ex.Message} \r\n【堆栈调用】:\r\n{ex.StackTrace}"; + logger.Error(message); + } + } + + /// + /// 关键信息日志 + /// + /// 日志信息 + public static void Info(string msg) + { + ILog logger = GetLogger("Info"); + if (logger.IsInfoEnabled) + { + StackTrace stackTrace = new StackTrace(); + StackFrame stackFrame = stackTrace.GetFrame(1); + System.Reflection.MethodBase methodBase = stackFrame.GetMethod(); + string message = "方法名称:" + methodBase.Name + "\r\n日志内容:" + msg; + logger.Info(message); + } + } + + /// + /// 警告信息日志 + /// + /// 日志信息 + public static void Warn(string msg) + { + ILog logger = GetLogger("Warn"); + if (logger.IsWarnEnabled) + { + StackTrace stackTrace = new StackTrace(); + StackFrame stackFrame = stackTrace.GetFrame(1); + System.Reflection.MethodBase methodBase = stackFrame.GetMethod(); + string message = "方法名称:" + methodBase.Name + "\r\n日志内容:" + msg; + logger.Info(message); + } + } + + /// + /// 失败信息日志 + /// + /// 日志信息 + public static void Fatal(string msg) + { + ILog logger = GetLogger("Fatal"); + if (logger.IsFatalEnabled) + { + StackTrace stackTrace = new StackTrace(); + StackFrame stackFrame = stackTrace.GetFrame(1); + System.Reflection.MethodBase methodBase = stackFrame.GetMethod(); + string message = "方法名称:" + methodBase.Name + "\r\n日志内容:" + msg; + logger.Info(message); + } + } + + #endregion Log a message object + + /// + /// 关键信息日志 + /// + /// 文件路径 + /// 日志信息 + public static void Info(string path, string msg) + { + ILog logger = GetLogger("Info"); + if (logger.IsInfoEnabled) + { + StackTrace stackTrace = new StackTrace(); + StackFrame stackFrame = stackTrace.GetFrame(1); + System.Reflection.MethodBase methodBase = stackFrame.GetMethod(); + string message = "方法名称:" + methodBase.Name + "\r\n日志内容:" + msg; + logger.Info(message); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Mapping/MapperExtensions.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Mapping/MapperExtensions.cs new file mode 100644 index 0000000..8ade2aa --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Mapping/MapperExtensions.cs @@ -0,0 +1,93 @@ +using AutoMapper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Properties; + +namespace Znyc.Admin.Commons.Mapping +{ + /// + /// 对象映射扩展操作 + /// + public static class MapperExtensions + { + private static IMapper _mapper; + + /// + /// 设置对象映射执行者 + /// + /// 映射执行者 + public static void SetMapper(IMapper mapper) + { + mapper.CheckNotNull("mapper"); + _mapper = mapper; + } + + /// + /// 将对象映射为指定类型 + /// + /// 要映射的目标类型 + /// 源对象 + /// 目标类型的对象 + public static TTarget MapTo(this object source) + { + CheckMapper(); + return _mapper.Map(source); + } + + /// + /// 使用源类型的对象更新目标类型的对象 + /// + /// 源类型 + /// 目标类型 + /// 源对象 + /// 待更新的目标对象 + /// 更新后的目标类型对象 + public static TTarget MapTo(this TSource source, TTarget target) + { + CheckMapper(); + return _mapper.Map(source, target); + } + + /// + /// 将数据源映射为指定的集合 + /// + /// + /// + /// + /// + /// + public static IQueryable ToOutput(this IQueryable source, + params Expression>[] membersToExpand) + { + CheckMapper(); + return _mapper.ProjectTo(source, membersToExpand); + } + + /// + /// 集合到集合 + /// + /// + /// + /// + public static List MapTo(this IEnumerable obj) + { + CheckMapper(); + return _mapper.Map>(obj); + } + + /// + /// 验证映射执行者是否为空 + /// + private static void CheckMapper() + { + if (_mapper == null) + { + throw new NullReferenceException(Resources.Map_MapperIsNull); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IIPAddressParser.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IIPAddressParser.cs new file mode 100644 index 0000000..20836a8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IIPAddressParser.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Http; +using System.Collections.Generic; +using System.Net; + +namespace Znyc.Admin.Commons.Net +{ + public interface IIpAddressParser + { + bool ContainsIp(string ipRule, string clientIp); + + bool ContainsIp(List ipRules, string clientIp); + + bool ContainsIp(List ipRules, string clientIp, out string rule); + + IPAddress GetClientIp(HttpContext context); + + IPAddress ParseIp(string ipAddress); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IPAddressRange.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IPAddressRange.cs new file mode 100644 index 0000000..2a54f61 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IPAddressRange.cs @@ -0,0 +1,143 @@ +using System; +using System.Linq; +using System.Net; +using System.Text.RegularExpressions; + +namespace Znyc.Admin.Commons.Net +{ + /// + /// IP v4 and v6 range helper by jsakamoto + /// Fork from https://github.com/jsakamoto/ipaddressrange + /// + /// + /// "192.168.0.0/24" + /// "fe80::/10" + /// "192.168.0.0/255.255.255.0" + /// "192.168.0.0-192.168.0.255" + /// + public class IpAddressRange + { + public IPAddress Begin { get; set; } + + public IPAddress End { get; set; } + + public IpAddressRange() + { + Begin = new IPAddress(0L); + End = new IPAddress(0L); + } + + public IpAddressRange(string ipRangeString) + { + // remove all spaces. + ipRangeString = ipRangeString.Replace(" ", ""); + + // Pattern 1. CIDR range: "192.168.0.0/24", "fe80::/10" + Match m1 = Regex.Match(ipRangeString, @"^(?[\da-f\.:]+)/(?\d+)$", RegexOptions.IgnoreCase); + if (m1.Success) + { + byte[] baseAdrBytes = IPAddress.Parse(m1.Groups["adr"].Value).GetAddressBytes(); + byte[] maskBytes = Bits.GetBitMask(baseAdrBytes.Length, int.Parse(m1.Groups["maskLen"].Value)); + baseAdrBytes = Bits.And(baseAdrBytes, maskBytes); + Begin = new IPAddress(baseAdrBytes); + End = new IPAddress(Bits.Or(baseAdrBytes, Bits.Not(maskBytes))); + return; + } + + // Pattern 2. Uni address: "127.0.0.1", ":;1" + Match m2 = Regex.Match(ipRangeString, @"^(?[\da-f\.:]+)$", RegexOptions.IgnoreCase); + if (m2.Success) + { + Begin = End = IPAddress.Parse(ipRangeString); + return; + } + + // Pattern 3. Begin end range: "169.258.0.0-169.258.0.255" + Match m3 = Regex.Match(ipRangeString, @"^(?[\da-f\.:]+)-(?[\da-f\.:]+)$", + RegexOptions.IgnoreCase); + if (m3.Success) + { + Begin = IPAddress.Parse(m3.Groups["begin"].Value); + End = IPAddress.Parse(m3.Groups["end"].Value); + return; + } + + // Pattern 4. Bit mask range: "192.168.0.0/255.255.255.0" + Match m4 = Regex.Match(ipRangeString, @"^(?[\da-f\.:]+)/(?[\da-f\.:]+)$", + RegexOptions.IgnoreCase); + if (m4.Success) + { + byte[] baseAdrBytes = IPAddress.Parse(m4.Groups["adr"].Value).GetAddressBytes(); + byte[] maskBytes = IPAddress.Parse(m4.Groups["bitmask"].Value).GetAddressBytes(); + baseAdrBytes = Bits.And(baseAdrBytes, maskBytes); + Begin = new IPAddress(baseAdrBytes); + End = new IPAddress(Bits.Or(baseAdrBytes, Bits.Not(maskBytes))); + return; + } + + throw new FormatException("Unknown IP range string."); + } + + public bool Contains(IPAddress ipaddress) + { + if (ipaddress.AddressFamily != Begin.AddressFamily) + { + return false; + } + + byte[] adrBytes = ipaddress.GetAddressBytes(); + return Bits.GE(Begin.GetAddressBytes(), adrBytes) && Bits.LE(End.GetAddressBytes(), adrBytes); + } + } + + internal static class Bits + { + internal static byte[] Not(byte[] bytes) + { + return bytes.Select(b => (byte)~b).ToArray(); + } + + internal static byte[] And(byte[] A, byte[] B) + { + return A.Zip(B, (a, b) => (byte)(a & b)).ToArray(); + } + + internal static byte[] Or(byte[] A, byte[] B) + { + return A.Zip(B, (a, b) => (byte)(a | b)).ToArray(); + } + + internal static bool GE(byte[] A, byte[] B) + { + return A.Zip(B, (a, b) => a == b ? 0 : a < b ? 1 : -1) + .SkipWhile(c => c == 0) + .FirstOrDefault() >= 0; + } + + internal static bool LE(byte[] A, byte[] B) + { + return A.Zip(B, (a, b) => a == b ? 0 : a < b ? 1 : -1) + .SkipWhile(c => c == 0) + .FirstOrDefault() <= 0; + } + + internal static byte[] GetBitMask(int sizeOfBuff, int bitLen) + { + byte[] maskBytes = new byte[sizeOfBuff]; + int bytesLen = bitLen / 8; + int bitsLen = bitLen % 8; + for (int i = 0; i < bytesLen; i++) + { + maskBytes[i] = 0xff; + } + + if (bitsLen > 0) + { + maskBytes[bytesLen] = (byte)~Enumerable.Range(1, 8 - bitsLen).Select(n => 1 << (n - 1)) + .Aggregate((a, b) => a | b); + } + + return maskBytes; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IpAddressUtil.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IpAddressUtil.cs new file mode 100644 index 0000000..1c83e2d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/IpAddressUtil.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text.RegularExpressions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Net.TencentIp; + +namespace Znyc.Admin.Commons.Net +{ + /// + /// IP地址 + /// + public class IpAddressUtil + { + /// + /// Ip地址段是否包含另外一个IP地址 + /// + /// + /// + /// + public static bool ContainsIp(string rule, string clientIp) + { + IPAddress ip = ParseIp(clientIp); + + IpAddressRange range = new IpAddressRange(rule); + if (range.Contains(ip)) + { + return true; + } + + return false; + } + + /// + /// Ip地址集合是否包含另外一个IP地址 + /// + /// Ip地址集合List + /// + /// + public static bool ContainsIp(List ipRules, string clientIp) + { + IPAddress ip = ParseIp(clientIp); + if (ipRules != null && ipRules.Any()) + { + foreach (string rule in ipRules) + { + IpAddressRange range = new IpAddressRange(rule); + if (range.Contains(ip)) + { + return true; + } + } + } + + return false; + } + + /// + /// Ip地址集合是否包含另外一个IP地址 + /// + /// + /// + /// + /// + public static bool ContainsIp(List ipRules, string clientIp, out string rule) + { + rule = null; + IPAddress ip = ParseIp(clientIp); + if (ipRules != null && ipRules.Any()) + { + foreach (string r in ipRules) + { + IpAddressRange range = new IpAddressRange(r); + if (range.Contains(ip)) + { + rule = r; + return true; + } + } + } + + return false; + } + + /// + /// + /// + /// + /// + public static IPAddress ParseIp(string ipAddress) + { + return IPAddress.Parse(ipAddress); + } + + /// + /// 是否为ip + /// + /// + /// + public static bool IsIP(string ip) + { + return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"); + } + + /// + /// 根据腾讯地图接口查询IP所属地区 + /// + /// + /// + public static string GetCityByIp(string strIP) + { + try + { + string url = "https://apis.map.qq.com/ws/location/v1/ip?ip=" + strIP + + "&key=WANBZ-6C56D-6P34Y-HWNMG-YHAH7-BJFP5"; + string jsonText = HttpRequestHelper.HttpGet(url); + TencentIpResult ipResult = jsonText.ToObject(); + if (ipResult.status == 0) + { + string nation = ipResult.result.ad_info.nation.ToString(); //国家 + string province = ipResult.result.ad_info.province.ToString(); //省份 + string city = ipResult.result.ad_info.city.ToString(); //城市 + string district = ipResult.result.ad_info.district.ToString(); //区/县 + string adcode = ipResult.result.ad_info.adcode.ToString(); //行政区划代码 + string resultStr = ""; + if (nation is { Length: > 0 }) + { + resultStr += nation; + } + + if (province is { Length: > 0 }) + { + resultStr += province; + } + + if (city is { Length: > 0 }) + { + resultStr += city; + } + + if (district is { Length: > 0 }) + { + resultStr += district; + } + + return resultStr; + } + else + { + Log4NetHelper.Error(strIP + "获取地区接口调用异常。" + ipResult.message); + return "未知"; + } + } + catch (Exception ex) + { + Log4NetHelper.Error(strIP + "获取地区异常。" + ex.Message); + return "未知"; + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/RemoteIpParser.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/RemoteIpParser.cs new file mode 100644 index 0000000..d24f200 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/RemoteIpParser.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Http; +using System.Collections.Generic; +using System.Net; + +namespace Znyc.Admin.Commons.Net +{ + public class RemoteIpParser : IIpAddressParser + { + public bool ContainsIp(string ipRule, string clientIp) + { + return IpAddressUtil.ContainsIp(ipRule, clientIp); + } + + public bool ContainsIp(List ipRules, string clientIp) + { + return IpAddressUtil.ContainsIp(ipRules, clientIp); + } + + public bool ContainsIp(List ipRules, string clientIp, out string rule) + { + return IpAddressUtil.ContainsIp(ipRules, clientIp, out rule); + } + + public virtual IPAddress GetClientIp(HttpContext context) + { + return context.Connection.RemoteIpAddress; + } + + public IPAddress ParseIp(string ipAddress) + { + return IpAddressUtil.ParseIp(ipAddress); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/ReversProxyIpParser.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/ReversProxyIpParser.cs new file mode 100644 index 0000000..502b0cd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/ReversProxyIpParser.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Linq; +using System.Net; + +namespace Znyc.Admin.Commons.Net +{ + public class ReversProxyIpParser : RemoteIpParser + { + private readonly string _realIpHeader; + + public ReversProxyIpParser(string realIpHeader) + { + _realIpHeader = realIpHeader; + } + + public override IPAddress GetClientIp(HttpContext context) + { + if (context.Request.Headers.Keys.Contains(_realIpHeader, StringComparer.CurrentCultureIgnoreCase)) + { + return ParseIp(context.Request.Headers[_realIpHeader].First()); + } + + return base.GetClientIp(context); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/TencentIp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/TencentIp.cs new file mode 100644 index 0000000..d470c82 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Net/TencentIp.cs @@ -0,0 +1,97 @@ +namespace Znyc.Admin.Commons.Net.TencentIp +{ + /// + /// 通过终端设备IP地址获取其当前所在地理位置,精确到市级,常用于显示当地城市天气预报、初始化用户城市等非精确定位场景。 + /// 响应结果 + /// + public class TencentIpResult + { + /// + /// 状态状态码, + /// 0为正常, + /// 310请求参数信息有误, + /// 311Key格式错误, + /// 306请求有护持信息请检查字符串, + /// 110请求来源未被授权 + /// + public int status { get; set; } + + /// + /// 对status的描述 + /// + public string message { get; set; } + + /// + /// IP定位结果 + /// + public IpResult result { get; set; } + } + + /// + /// IP定位结果 + /// + public class IpResult + { + /// + /// 用于定位的IP地址 + /// + public string ip { get; set; } + + /// + /// 定位坐标 + /// + public Location location { get; set; } + + /// + /// 定位行政区划信息 + /// + public Adinfo ad_info { get; set; } + } + + /// + /// 定位坐标 + /// + public class Location + { + /// + /// 纬度 + /// + public decimal lat { get; set; } + + /// + /// 经度 + /// + public decimal lng { get; set; } + } + + /// + /// 定位行政区划信息 + /// + public class Adinfo + { + /// + /// 国家 + /// + public string nation { get; set; } + + /// + /// 省 + /// + public string province { get; set; } + + /// + /// 市 + /// + public string city { get; set; } + + /// + /// 区 + /// + public string district { get; set; } + + /// + /// 行政区划代码 + /// + public int adcode { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AllowCacheApp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AllowCacheApp.cs new file mode 100644 index 0000000..87dfe35 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AllowCacheApp.cs @@ -0,0 +1,53 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Commons.Options +{ + /// + /// 缓存中可用的应用 + /// + [Serializable] + public class AllowCacheApp + { + /// + /// 设置或获取 ID + /// + [MaxLength(50)] + public int Id { get; set; } + + /// + /// 设置或获取 应用Id + /// + [MaxLength(50)] + public string AppId { get; set; } + + /// + /// 设置或获取 应用密钥 + /// + [MaxLength(50)] + public string AppSecret { get; set; } + + /// + /// 设置或获取 消息加密密钥 + /// + [MaxLength(256)] + public string EncodingAESKey { get; set; } + + /// + /// 设置或获取 请求url + /// + [MaxLength(256)] + public string RequestUrl { get; set; } + + /// + /// 设置或获取 token + /// + [MaxLength(256)] + public string Token { get; set; } + + /// + /// 设置或获取 是否开启消息加解密 + /// + public bool? IsOpenAEKey { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AppSetting.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AppSetting.cs new file mode 100644 index 0000000..e899ed4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AppSetting.cs @@ -0,0 +1,316 @@ +using System; +using System.Xml.Serialization; + +namespace Znyc.Admin.Commons.Options +{ + /// + /// 应用设置实体类 + /// + [Serializable] + public class AppSetting + { + #region 系统基本信息 + + /// + /// 系统名称 + /// + [XmlElement("SoftName")] + public string SoftName { get; set; } + + /// + /// 系统简介 + /// + [XmlElement("SoftSummary")] + public string SoftSummary { get; set; } + + /// + /// 访问域名 + /// + [XmlElement("WebUrl")] + public string WebUrl { get; set; } + + /// + /// Logo + /// + [XmlElement("SysLogo")] + public string SysLogo { get; set; } + + /// + /// 公司名称 + /// + [XmlElement("CompanyName")] + public string CompanyName { get; set; } + + /// + /// 地址 + /// + [XmlElement("Address")] + public string Address { get; set; } + + /// + /// 电话 + /// + [XmlElement("Telphone")] + public string Telphone { get; set; } + + /// + /// Email + /// + [XmlElement("Email")] + public string Email { get; set; } + + /// + /// ICP备案号 + /// + [XmlElement("ICPCode")] + public string ICPCode { get; set; } + + /// + /// 公安备案号 + /// + [XmlElement("PublicSecurityCode")] + public string PublicSecurityCode { get; set; } + + /// + /// 分享标题 + /// + [XmlElement("ShareTitle")] + public string ShareTitle { get; set; } + + /// + /// 微信公众号分享图片 + /// + [XmlElement("ShareWeChatImage")] + public string ShareWeChatImage { get; set; } + + /// + /// 微信小程序分享图片 + /// + [XmlElement("ShareWxAppletImage")] + public string ShareWxAppletImage { get; set; } + + /// + /// 微信推广二维码背景图片 + /// + [XmlElement("ShareBackgroundImage")] + public string ShareBackgroundImage { get; set; } + + #endregion 系统基本信息 + + #region 功能权限设置 + + /// + /// URL重写开关 + /// + [XmlElement("Staticstatus")] + public string Staticstatus { get; set; } + + /// + /// 静态URL后缀 + /// + [XmlElement("Staticextension")] + public string Staticextension { get; set; } + + /// + /// 开启会员功能 + /// + [XmlElement("Memberstatus")] + public string Memberstatus { get; set; } + + /// + /// 是否开启网站 + /// + [XmlElement("Webstatus")] + public string Webstatus { get; set; } + + /// + /// 网站关闭原因 + /// + [XmlElement("Webclosereason")] + public string Webclosereason { get; set; } + + /// + /// 网站统计代码 + /// + [XmlElement("Webcountcode")] + public string Webcountcode { get; set; } + + #endregion 功能权限设置 + + #region 文件服务器 + + /// + /// 文件服务器 + /// + [XmlElement("Fileserver")] + public string Fileserver { get; set; } + + /// + /// 本地文件存储物理物理路径 + /// + [XmlElement("LocalPath")] + public string LocalPath { get; set; } + + /// + /// 阿里云KeyId + /// + [XmlElement("Osssecretid")] + public string Osssecretid { get; set; } + + /// + /// 阿里云SecretKey + /// + [XmlElement("Osssecretkey")] + public string Osssecretkey { get; set; } + + /// + /// 阿里云Bucket + /// + [XmlElement("Ossbucket")] + public string Ossbucket { get; set; } + + /// + /// 阿里云EndPoint + /// + [XmlElement("Ossendpoint")] + public string Ossendpoint { get; set; } + + /// + /// 阿里云绑定域名 + /// + [XmlElement("Ossdomain")] + public string Ossdomain { get; set; } + + #endregion 文件服务器 + + #region 文件上传设置 + + /// + /// 文件上传目录 + /// + [XmlElement("Filepath")] + public string Filepath { get; set; } + + /// + /// 文件保存方式 + /// + [XmlElement("Filesave")] + public string Filesave { get; set; } + + /// + /// 编辑器图片 + /// + [XmlElement("Fileremote")] + public string Fileremote { get; set; } + + /// + /// 文件上传类型 + /// + [XmlElement("Fileextension")] + public string Fileextension { get; set; } + + /// + /// 视频上传类型 + /// + [XmlElement("Videoextension")] + public string Videoextension { get; set; } + + /// + /// 附件上传大小 + /// + [XmlElement("Attachsize")] + public string Attachsize { get; set; } + + /// + /// 视频上传大小 + /// + [XmlElement("Videosize")] + public string Videosize { get; set; } + + /// + /// 图片上传大小 + /// + [XmlElement("Imgsize")] + public string Imgsize { get; set; } + + /// + /// 图片最大尺寸 高度 + /// + [XmlElement("Imgmaxheight")] + public string Imgmaxheight { get; set; } + + /// + /// 图片最大尺寸 宽度 + /// + [XmlElement("Imgmaxwidth")] + public string Imgmaxwidth { get; set; } + + /// + /// 缩略图生成尺寸 高度 + /// + [XmlElement("Thumbnailheight")] + public string Thumbnailheight { get; set; } + + /// + /// 缩略图生成尺寸 宽度 + /// + [XmlElement("Thumbnailwidth")] + public string Thumbnailwidth { get; set; } + + /// + /// 缩略图生成方式 + /// + [XmlElement("Thumbnailmode")] + public string Thumbnailmode { get; set; } + + /// + /// 图片水印类型 + /// + [XmlElement("Watermarktype")] + public string Watermarktype { get; set; } + + /// + /// 图片水印位置 + /// + [XmlElement("Watermarkposition")] + public string Watermarkposition { get; set; } + + /// + /// 图片生成质量 + /// + [XmlElement("Watermarkimgquality")] + public string Watermarkimgquality { get; set; } + + /// + /// 图片水印文件 + /// + [XmlElement("Watermarkpic")] + public string Watermarkpic { get; set; } + + /// + /// 水印透明度 + /// + [XmlElement("Watermarktransparency")] + public string Watermarktransparency { get; set; } + + /// + /// 水印文字 + /// + [XmlElement("Watermarktext")] + public string Watermarktext { get; set; } + + /// + /// 文字字体格式 + /// + [XmlElement("Watermarkfont")] + public string Watermarkfont { get; set; } + + /// + /// 文字字体大小 + /// + [XmlElement("Watermarkfontsize")] + public string Watermarkfontsize { get; set; } + + #endregion 文件上传设置 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AssembleTypeConsts.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AssembleTypeConsts.cs new file mode 100644 index 0000000..ad97d93 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/AssembleTypeConsts.cs @@ -0,0 +1,23 @@ +namespace Znyc.Admin.Commons.Options +{ + /// + /// + /// + public class AssembleTypeConsts + { + /// + /// + /// + public const string Package = "package"; + + /// + /// + /// + public const string ReferenceAssembly = "referenceassembly"; + + /// + /// + /// + public const string Project = "project"; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/CodeGenerateOption.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/CodeGenerateOption.cs new file mode 100644 index 0000000..27c78f5 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/CodeGenerateOption.cs @@ -0,0 +1,58 @@ +namespace Znyc.Admin.Commons.Options +{ + /// + /// 代码生成器配置 + /// + public class CodeGenerateOption + { + /// + /// 项目命名空间 + /// + public string BaseNamespace { get; set; } + + /// + /// 数据实体命名空间 + /// + public string EntitysNamespace { get; set; } + + /// + /// 输入输出数据实体名称空间 + /// + public string DtosNamespace { get; set; } + + /// + /// 仓储接口命名空间 + /// + public string IRepositoriesNamespace { get; set; } + + /// + /// 仓储实现名称空间 + /// + public string RepositoriesNamespace { get; set; } + + /// + /// 服务接口命名空间 + /// + public string IServicsNamespace { get; set; } + + /// + /// 服务接口实现命名空间 + /// + public string ServicesNamespace { get; set; } + + /// + /// Api控制器命名空间 + /// + public string ApiControllerNamespace { get; set; } + + /// + /// 去掉的表头字符 + /// + public string ReplaceTableNameStr { get; set; } + + /// + /// 要生数据的表,用“,”分割 + /// + public string TableList { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/DbContextOption.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/DbContextOption.cs new file mode 100644 index 0000000..f32f6cf --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/DbContextOption.cs @@ -0,0 +1,30 @@ +using Znyc.Admin.Commons.Enums; + +namespace Znyc.Admin.Commons.Options +{ + /// + /// 数据库上下文配置 + /// + public class DbContextOption + { + /// + /// 数据库连接字符串 + /// + public string dbConfigName { get; set; } + + /// + /// 实体程序集名称 + /// + public string ModelAssemblyName { get; set; } + + /// + /// 数据库类型 + /// + public DatabaseType DbType { get; set; } = DatabaseType.SqlServer; + + /// + /// 是否输出Sql日志 + /// + public bool IsOutputSql; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/JwtOption.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/JwtOption.cs new file mode 100644 index 0000000..98268a8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/JwtOption.cs @@ -0,0 +1,33 @@ +namespace Znyc.Admin.Commons.Options +{ + /// + /// JsonWebToken配置模型。 + /// + public class JwtOption + { + /// + /// 签发者。 + /// + public string Issuer { get; set; } + + /// + /// 收发者。 + /// + public string Audience { get; set; } + + /// + /// 密钥。 + /// + public string Secret { get; set; } + + /// + /// Token有效期(单位:分钟)。 + /// + public int Expiration { get; set; } + + /// + /// Token有效刷新时间(单位:分钟)。 + /// + public int refreshJwtTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/UIConstants.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/UIConstants.cs new file mode 100644 index 0000000..9c462ba --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Options/UIConstants.cs @@ -0,0 +1,74 @@ +using System; + +namespace Znyc.Admin.Commons +{ + /// + /// ַ + /// + public static class UIConstants + { + /// + /// ʱ + /// + public static string ApplicationExpiredDate = "12/29/2012"; + + /// + /// 汾 + /// + public static string SoftwareVersion = "3.0"; + + /// + /// Ʒ + /// + public static string SoftwareProductName = "ZnycSoftSystem"; + + /// + /// + /// + public static int SoftwareProbationDay = 20; + + /// + /// 洢Ŀ¼ + /// + public static string IsolatedStorageDirectoryName = "UserNameDir"; + + /// + /// 洢Կ + /// + public static string IsolatedStorageEncryptKey = "12345678"; + + /// + /// עܹԿ + /// + public static string PublicKey = + @"mtDtu679/0quhftVyOc6/cBov/i534Dkh3AB8RwrpC9Vq2RIFB3uvjRUuaAEPR8vMcijQjVzqLZgMM7jFKclzbh21rWTM+YlOeraKz5FPCC7rSLnv6Tfbzia9VI/r5cfM8ogVMuUKCZeU+PTEmVviasCl8nPYyqOQchlf/MftMM=AQAB"; + + /// + /// ȨϢ + /// + public static string CopyRight = + string.Format( + "Copyright © 2017-{0} Znyc Tech.", + DateTime.Now.Year); + + /// + /// Webַ֤ + /// + public static string WebRegisterURL = "http://www.Znyc.Admin.com/WebRegister.aspx"; + + /// + /// òֵ + /// + /// ʱ + /// 汾 + /// + /// Կַ + public static void SetValue(string expiredDate, string version, string name, string publicKey) + { + ApplicationExpiredDate = expiredDate; + SoftwareVersion = version; + SoftwareProductName = name; + PublicKey = publicKey; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PageIfno.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PageIfno.cs new file mode 100644 index 0000000..faa1411 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PageIfno.cs @@ -0,0 +1,99 @@ +using System; +using System.Runtime.Serialization; +using System.Xml.Serialization; + +namespace Znyc.Admin.Commons.Pages +{ + /// + /// + /// + /// + public delegate void PageInfoChanged(PagerInfo info); + + /// + /// 分页实体 + /// + [Serializable] + [DataContract] + public class PagerInfo + { + /// + /// 页面选择事件 + /// + public event PageInfoChanged OnPageInfoChanged; + + /// + /// 当前页码 + /// + private int currenetPageIndex; + + /// + /// 每页显示的记录 + /// + private int pageSize; + + /// + /// 记录总数 + /// + private int recordCount; + + #region 属性变量 + + /// + /// 获取或设置当前页码 + /// + [XmlElement(ElementName = "CurrenetPageIndex")] + [DataMember] + public int CurrenetPageIndex + { + get => currenetPageIndex; + set + { + currenetPageIndex = value; + + if (OnPageInfoChanged != null) + { + OnPageInfoChanged(this); + } + } + } + + /// + /// 获取或设置每页显示的记录 + /// + [XmlElement(ElementName = "PageSize")] + [DataMember] + public int PageSize + { + get => pageSize; + set + { + pageSize = value; + if (OnPageInfoChanged != null) + { + OnPageInfoChanged(this); + } + } + } + + /// + /// 获取或设置记录总数 + /// + [XmlElement(ElementName = "RecordCount")] + [DataMember] + public int RecordCount + { + get => recordCount; + set + { + recordCount = value; + if (OnPageInfoChanged != null) + { + OnPageInfoChanged(this); + } + } + } + + #endregion 属性变量 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PageResult.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PageResult.cs new file mode 100644 index 0000000..0dd284f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PageResult.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Commons.Pages +{ + /// + /// 保存分页请求的结果。 + /// + /// 返回结果集中的POCO类型 + public class PageResult : CommonResult + { + public PageResult() + { + } + + public PageResult(bool success, string msg, object rows) + { + Success = success; + ErrMsg = msg; + ResData = rows; + } + + public PageResult(long currentPage, long totalItems, long itemsPerPage) + { + CurrentPage = currentPage; + TotalItems = totalItems; + ItemsPerPage = itemsPerPage; + } + + public PageResult(long currentPage, long totalPages, long totalItems, long itemsPerPage, List items, + object context) : this(currentPage, totalPages, totalItems) + { + ItemsPerPage = itemsPerPage; + Items = items; + Context = context; + } + + /// + /// 当前页码。 + /// + public long CurrentPage { get; set; } + + /// + /// 总页码数。 + /// + public long TotalPages { get; set; } + + /// + /// 记录总数。 + /// + public long TotalItems { get; set; } + + /// + /// 每页数量。 + /// + public long ItemsPerPage { get; set; } + + /// + /// 当前结果集。 + /// + public List Items { get; set; } + + /// + /// 自定义用户属性。 + /// + public object Context { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PagerHelper.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PagerHelper.cs new file mode 100644 index 0000000..3085c87 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Page/PagerHelper.cs @@ -0,0 +1,390 @@ +using System; +using Znyc.Admin.Commons.Enums; + +namespace Znyc.Admin.Commons.Pages +{ + /// + /// 根据各种不同数据库生成不同分页语句的辅助类 PagerHelper + /// + public class PagerHelper + { + #region 成员变量 + + private string tableName; //待查询表或自定义查询语句 + private string fieldsToReturn = "*"; //需要返回的列 + private string fieldNameToSort = string.Empty; //排序字段名称 + private int pageSize = 10; //页尺寸,就是一页显示多少条记录 + private int pageIndex = 1; //当前的页码 + private bool isDescending = false; //是否以降序排列 + private string strwhere = string.Empty; //检索条件(注意: 不要加 where) + + #endregion 成员变量 + + #region 属性对象 + + /// + /// 待查询表或自定义查询语句 + /// + public string TableName + { + get => tableName; + set => tableName = value; + } + + /// + /// 需要返回的列 + /// + public string FieldsToReturn + { + get => fieldsToReturn; + set => fieldsToReturn = value; + } + + /// + /// 排序字段名称 + /// + public string FieldNameToSort + { + get => fieldNameToSort; + set => fieldNameToSort = value; + } + + /// + /// 页尺寸,就是一页显示多少条记录 + /// + public int PageSize + { + get => pageSize; + set => pageSize = value; + } + + /// + /// 当前的页码 + /// + public int PageIndex + { + get => pageIndex; + set => pageIndex = value; + } + + /// + /// 是否以降序排列结果 + /// + public bool IsDescending + { + get => isDescending; + set => isDescending = value; + } + + /// + /// 检索条件(注意: 不要加 where) + /// + public string StrWhere + { + get => strwhere; + set => strwhere = value; + } + + /// + /// 表或Sql语句包装属性 + /// + internal string TableOrSqlWrapper + { + get + { + bool isSql = tableName.ToLower().Contains("from"); + if (isSql) + { + return string.Format("({0}) AA ", tableName); //如果是Sql语句,则加括号后再使用 + } + else + { + return tableName; //如果是表名,则直接使用 + } + } + } + + #endregion 属性对象 + + #region 构造函数 + + /// + /// 默认构造函数,其他通过属性设置 + /// + public PagerHelper() + { + } + + /// + /// 完整的构造函数,可以包含条件,返回记录字段等条件 + /// + /// 表名称,可以自定义查询语句 + /// 需要返回的列 + /// 排序字段名称 + /// 每页显示数量 + /// 当前的页码 + /// 是否以降序排列 + /// 检索条件 + public PagerHelper(string tableName, string fieldsToReturn, string fieldNameToSort, + int pageSize, int pageIndex, bool isDescending, string strwhere) + { + this.tableName = tableName; + this.fieldsToReturn = fieldsToReturn; + this.fieldNameToSort = fieldNameToSort; + this.pageSize = pageSize; + this.pageIndex = pageIndex; + this.isDescending = isDescending; + this.strwhere = strwhere; + } + + #endregion 构造函数 + + #region 各种数据库Sql分页查询,不依赖于存储过程 + + /// + /// 不依赖于存储过程的分页(Oracle) + /// + /// 如果isDoCount为True,返回总数统计Sql;否则返回分页语句Sql + /// + private string GetOracleSql(bool isDoCount) + { + string sql = ""; + if (string.IsNullOrEmpty(strwhere)) + { + strwhere = " (1=1) "; + } + + if (isDoCount) //执行总数统计 + { + sql = string.Format("select count(*) as Total from {0} Where {1} ", TableOrSqlWrapper, strwhere); + } + else + { + string strOrder = string.Format(" order by {0} {1}", fieldNameToSort, isDescending ? "DESC" : "ASC"); + + int minRow = pageSize * (pageIndex - 1); + int maxRow = pageSize * pageIndex; + string selectSql = string.Format("select {0} from {1} Where {2} {3}", fieldsToReturn, TableOrSqlWrapper, + strwhere, strOrder); + sql = string.Format(@"select b.* from + (select a.*, rownum as rowIndex from({2}) a) b + where b.rowIndex > {0} and b.rowIndex <= {1}", minRow, maxRow, selectSql); + } + + return sql; + } + + /// + /// 不依赖于存储过程的分页(SqlServer) + /// + /// 如果isDoCount为True,返回总数统计Sql;否则返回分页语句Sql + /// 是否是Sql server2008及低版本,默认为false + /// + private string GetSqlServerSql(bool isDoCount, bool isSql2008 = false) + { + string sql = ""; + if (string.IsNullOrEmpty(strwhere)) + { + strwhere = " (1=1)"; + } + + if (isDoCount) //执行总数统计 + { + sql = string.Format("select count(*) as Total from {0} Where {1} ", TableOrSqlWrapper, strwhere); + } + else + { + string strOrder = string.Format(" order by {0} {1}", fieldNameToSort, isDescending ? "DESC" : "ASC"); + int minRow = pageSize * (pageIndex - 1) + 1; + int maxRow = pageSize * pageIndex; + if (isSql2008) + { + sql = string.Format( + "SELECT * FROM ( SELECT ROW_NUMBER() OVER (order by {0}) AS rows ,{1} FROM {2} where {3}) AS main_temp where rows BETWEEN {4} and {5}", + strOrder, fieldsToReturn, TableOrSqlWrapper, strwhere, minRow, maxRow); + } + else + { + sql = string.Format(@"With Paging AS + ( SELECT ROW_NUMBER() OVER ({0}) as RowNumber, {1} FROM {2} Where {3}) + SELECT * FROM Paging WHERE RowNumber Between {4} and {5}", strOrder, fieldsToReturn, TableOrSqlWrapper, + strwhere, + minRow, maxRow); + } + } + + return sql; + } + + /// + /// 不依赖于存储过程的分页(Access) + /// + /// 如果isDoCount为True,返回总数统计Sql;否则返回分页语句Sql + /// + private string GetAccessSql(bool isDoCount) + { + string sql = ""; + if (string.IsNullOrEmpty(strwhere)) + { + strwhere = " (1=1) "; + } + + if (isDoCount) //执行总数统计 + { + sql = string.Format("select count(*) as Total from {0} Where {1} ", TableOrSqlWrapper, strwhere); + } + else + { + string strTemp = string.Empty; + string strOrder = string.Empty; + if (isDescending) + { + strTemp = "<(select min"; + strOrder = string.Format(" order by [{0}] desc", fieldNameToSort); + } + else + { + strTemp = ">(select max"; + strOrder = string.Format(" order by [{0}] asc", fieldNameToSort); + } + + sql = string.Format("select top {0} {1} from {2} ", pageSize, fieldsToReturn, TableOrSqlWrapper); + + //如果是第一页就执行以上代码,这样会加快执行速度 + if (pageIndex == 1) + { + sql += string.Format(" Where {0} ", strwhere); + sql += strOrder; + } + else + { + sql += string.Format( + " Where [{0}] {1} ([{0}]) from (select top {2} [{0}] from {3} where {5} {4} ) as tblTmp) and {5} {4}", + fieldNameToSort, strTemp, (pageIndex - 1) * pageSize, TableOrSqlWrapper, strOrder, strwhere); + } + } + + return sql; + } + + /// + /// 不依赖于存储过程的分页(MySql) + /// + /// 如果isDoCount为True,返回总数统计Sql;否则返回分页语句Sql + /// + private string GetMySqlSql(bool isDoCount) + { + string sql = ""; + if (string.IsNullOrEmpty(strwhere)) + { + strwhere = " (1=1) "; + } + + if (isDoCount) //执行总数统计 + { + sql = string.Format("select count(Id) as Total from {0} Where IsDeleted=0 and {1}", TableOrSqlWrapper, strwhere); + } + else + { + //SELECT * FROM 表名称 LIMIT M,N + string strOrder = string.Format(" order by {0} {1}", fieldNameToSort, isDescending ? "DESC" : "ASC"); + + int minRow = pageSize * (pageIndex - 1); + int maxRow = pageSize * pageIndex; + sql = string.Format( + "select {0} from {1} where Id IN(select t.Id from (select Id from {1} Where IsDeleted=0 and {2} )as t) {3} limit {4},{5};", + //"select {0} from {1} where Id IN(select t.Id from (select Id from {1} Where IsDeleted=0 and {2} {3} limit {4},{5})as t);", + fieldsToReturn, TableOrSqlWrapper, strwhere, strOrder, minRow, pageSize); + } + + return sql; + } + + /// + /// 不依赖于存储过程的分页(SQLite) + /// + /// 如果isDoCount为True,返回总数统计Sql;否则返回分页语句Sql + /// + private string GetSQLiteSql(bool isDoCount) + { + string sql = ""; + if (string.IsNullOrEmpty(strwhere)) + { + strwhere = " (1=1) "; + } + + if (isDoCount) //执行总数统计 + { + sql = string.Format("select count(*) as Total from {0} Where {1} ", TableOrSqlWrapper, strwhere); + } + else + { + //SELECT * FROM 表名称 LIMIT M,N + string strOrder = string.Format(" order by {0} {1}", fieldNameToSort, isDescending ? "DESC" : "ASC"); + + int minRow = pageSize * (pageIndex - 1); + int maxRow = pageSize * pageIndex; + sql = string.Format("select {0} from {1} Where {2} {3} LIMIT {4},{5}", + fieldsToReturn, TableOrSqlWrapper, strwhere, strOrder, minRow, pageSize); + } + + return sql; + } + + /// + /// 获取对应数据库的分页语句(指定数据库类型) + /// + /// 如果isDoCount为True,返回总数统计Sql;否则返回分页语句Sql + /// 数据库类型枚举 + public string GetPagingSql(bool isDoCount, DatabaseType dbType) + { + string sql = ""; + switch (dbType) + { + case DatabaseType.Access: + sql = GetAccessSql(isDoCount); + break; + + case DatabaseType.SqlServer: + sql = GetSqlServerSql(isDoCount); + break; + + case DatabaseType.Oracle: + sql = GetOracleSql(isDoCount); + break; + + case DatabaseType.MySql: + sql = GetMySqlSql(isDoCount); + break; + + case DatabaseType.SQLite: + sql = GetSQLiteSql(isDoCount); + break; + } + + return sql; + } + + /// + /// 数据库类型 + /// + /// + /// + private DatabaseType GetDataBaseType(string databaseType) + { + DatabaseType returnValue = DatabaseType.SqlServer; + foreach (DatabaseType dbType in Enum.GetValues(typeof(DatabaseType))) + { + if (dbType.ToString().Equals(databaseType, StringComparison.OrdinalIgnoreCase)) + { + returnValue = dbType; + break; + } + } + + return returnValue; + } + + #endregion 各种数据库Sql分页查询,不依赖于存储过程 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/PublishProfiles/FolderProfile.pubxml b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..7c95673 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,14 @@ + + + + + FileSystem + Release + Any CPU + netcoreapp3.1 + D:\netcorespace\YueGroup\publish\ + false + + \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/Resources.Designer.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/Resources.Designer.cs new file mode 100644 index 0000000..742199c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/Resources.Designer.cs @@ -0,0 +1,378 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Znyc.Admin.Commons.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Znyc.Admin.Commons.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 参数中的字符\"{0}\"不是 {1} 进制数的有效字符。 的本地化字符串。 + /// + internal static string AnyRadixConvert_CharacterIsNotValid { + get { + return ResourceManager.GetString("AnyRadixConvert_CharacterIsNotValid", resourceCulture); + } + } + + /// + /// 查找类似 0 的本地化字符串。 + /// + internal static string AnyRadixConvert_Overflow { + get { + return ResourceManager.GetString("AnyRadixConvert_Overflow", resourceCulture); + } + } + + /// + /// 查找类似 缓存功能尚未初始化,未找到可用的 ICacheProvider 实现。 的本地化字符串。 + /// + internal static string Caching_CacheNotInitialized { + get { + return ResourceManager.GetString("Caching_CacheNotInitialized", resourceCulture); + } + } + + /// + /// 查找类似 标识为“{0}”的项重复定义 的本地化字符串。 + /// + internal static string ConfigFile_ItemKeyDefineRepeated { + get { + return ResourceManager.GetString("ConfigFile_ItemKeyDefineRepeated", resourceCulture); + } + } + + /// + /// 查找类似 名称为“{0}”的类型不存在 的本地化字符串。 + /// + internal static string ConfigFile_NameToTypeIsNull { + get { + return ResourceManager.GetString("ConfigFile_NameToTypeIsNull", resourceCulture); + } + } + + /// + /// 查找类似 请先初始化依赖注入服务,再使用OSharpContext.IocRegisterservices属性 的本地化字符串。 + /// + internal static string Context_BuildservicesFirst { + get { + return ResourceManager.GetString("Context_BuildservicesFirst", resourceCulture); + } + } + + /// + /// 查找类似 上下文初始化类型“{0}”不存在 的本地化字符串。 + /// + internal static string DbContextInitializerConfig_InitializerNotExists { + get { + return ResourceManager.GetString("DbContextInitializerConfig_InitializerNotExists", resourceCulture); + } + } + + /// + /// 查找类似 查询条件组中的操作类型错误,只能为And或者Or。 的本地化字符串。 + /// + internal static string Filter_GroupOperateError { + get { + return ResourceManager.GetString("Filter_GroupOperateError", resourceCulture); + } + } + + /// + /// 查找类似 指定的属性“{0}”在类型“{1}”中不存在。 的本地化字符串。 + /// + internal static string Filter_RuleFieldInTypeNotFound { + get { + return ResourceManager.GetString("Filter_RuleFieldInTypeNotFound", resourceCulture); + } + } + + /// + /// 查找类似 无法解析类型“{0}”的构造函数中类型为“{1}”的参数 的本地化字符串。 + /// + internal static string Ioc_CannotResolveservice { + get { + return ResourceManager.GetString("Ioc_CannotResolveservice", resourceCulture); + } + } + + /// + /// 查找类似 OSharp框架尚未初始化,请先初始化 的本地化字符串。 + /// + internal static string Ioc_FrameworkNotInitialized { + get { + return ResourceManager.GetString("Ioc_FrameworkNotInitialized", resourceCulture); + } + } + + /// + /// 查找类似 类型“{0}”的实现类型无法找到 的本地化字符串。 + /// + internal static string Ioc_ImplementationTypeNotFound { + get { + return ResourceManager.GetString("Ioc_ImplementationTypeNotFound", resourceCulture); + } + } + + /// + /// 查找类似 类型“{0}”中找不到合适参数的构造函数 的本地化字符串。 + /// + internal static string Ioc_NoConstructorMatch { + get { + return ResourceManager.GetString("Ioc_NoConstructorMatch", resourceCulture); + } + } + + /// + /// 查找类似 实现类型不能为“{0}”,因为该类型与注册为“{1}”的其他类型无法区分 的本地化字符串。 + /// + internal static string Ioc_TryAddIndistinguishableTypeToEnumerable { + get { + return ResourceManager.GetString("Ioc_TryAddIndistinguishableTypeToEnumerable", resourceCulture); + } + } + + /// + /// 查找类似 类型“{0}”不是仓储接口“IRepository<,>”的派生类。 的本地化字符串。 + /// + internal static string IocInitializerBase_TypeNotIRepositoryType { + get { + return ResourceManager.GetString("IocInitializerBase_TypeNotIRepositoryType", resourceCulture); + } + } + + /// + /// 查找类似 类型“{0}”不是操作单元“IUnitOfWork”的派生类。 的本地化字符串。 + /// + internal static string IocInitializerBase_TypeNotIUnitOfWorkType { + get { + return ResourceManager.GetString("IocInitializerBase_TypeNotIUnitOfWorkType", resourceCulture); + } + } + + /// + /// 查找类似 创建名称为“{0}”的日志实例时“{1}”返回空实例。 的本地化字符串。 + /// + internal static string Logging_CreateLogInstanceReturnNull { + get { + return ResourceManager.GetString("Logging_CreateLogInstanceReturnNull", resourceCulture); + } + } + + /// + /// 查找类似 MapperExtensions.Mapper不能为空,请先设置值 的本地化字符串。 + /// + internal static string Map_MapperIsNull { + get { + return ResourceManager.GetString("Map_MapperIsNull", resourceCulture); + } + } + + /// + /// 查找类似 当前Http上下文中不存在Request有效范围的Mef部件容器。 的本地化字符串。 + /// + internal static string Mef_HttpContextItems_NotFoundRequestContainer { + get { + return ResourceManager.GetString("Mef_HttpContextItems_NotFoundRequestContainer", resourceCulture); + } + } + + /// + /// 查找类似 指定对象中不存在名称为“{0}”的属性。 的本地化字符串。 + /// + internal static string ObjectExtensions_PropertyNameNotExistsInType { + get { + return ResourceManager.GetString("ObjectExtensions_PropertyNameNotExistsInType", resourceCulture); + } + } + + /// + /// 查找类似 指定名称“{0}”的属性类型不是“{1}”。 的本地化字符串。 + /// + internal static string ObjectExtensions_PropertyNameNotFixedType { + get { + return ResourceManager.GetString("ObjectExtensions_PropertyNameNotFixedType", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”的值必须在“{1}”与“{2}”之间。 的本地化字符串。 + /// + internal static string ParameterCheck_Between { + get { + return ResourceManager.GetString("ParameterCheck_Between", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”的值必须在“{1}”与“{2}”之间,且不能等于“{3}”。 的本地化字符串。 + /// + internal static string ParameterCheck_BetweenNotEqual { + get { + return ResourceManager.GetString("ParameterCheck_BetweenNotEqual", resourceCulture); + } + } + + /// + /// 查找类似 指定的目录路径“{0}”不存在。 的本地化字符串。 + /// + internal static string ParameterCheck_DirectoryNotExists { + get { + return ResourceManager.GetString("ParameterCheck_DirectoryNotExists", resourceCulture); + } + } + + /// + /// 查找类似 指定的文件路径“{0}”不存在。 的本地化字符串。 + /// + internal static string ParameterCheck_FileNotExists { + get { + return ResourceManager.GetString("ParameterCheck_FileNotExists", resourceCulture); + } + } + + /// + /// 查找类似 集合“{0}”中不能包含null的项 的本地化字符串。 + /// + internal static string ParameterCheck_NotContainsNull_Collection { + get { + return ResourceManager.GetString("ParameterCheck_NotContainsNull_Collection", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”的值不能为Guid.Empty 的本地化字符串。 + /// + internal static string ParameterCheck_NotEmpty_Guid { + get { + return ResourceManager.GetString("ParameterCheck_NotEmpty_Guid", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”的值必须大于“{1}”。 的本地化字符串。 + /// + internal static string ParameterCheck_NotGreaterThan { + get { + return ResourceManager.GetString("ParameterCheck_NotGreaterThan", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”的值必须大于或等于“{1}”。 的本地化字符串。 + /// + internal static string ParameterCheck_NotGreaterThanOrEqual { + get { + return ResourceManager.GetString("ParameterCheck_NotGreaterThanOrEqual", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”的值必须小于“{1}”。 的本地化字符串。 + /// + internal static string ParameterCheck_NotLessThan { + get { + return ResourceManager.GetString("ParameterCheck_NotLessThan", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”的值必须小于或等于“{1}”。 的本地化字符串。 + /// + internal static string ParameterCheck_NotLessThanOrEqual { + get { + return ResourceManager.GetString("ParameterCheck_NotLessThanOrEqual", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”不能为空引用。 的本地化字符串。 + /// + internal static string ParameterCheck_NotNull { + get { + return ResourceManager.GetString("ParameterCheck_NotNull", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”不能为空引用或空集合。 的本地化字符串。 + /// + internal static string ParameterCheck_NotNullOrEmpty_Collection { + get { + return ResourceManager.GetString("ParameterCheck_NotNullOrEmpty_Collection", resourceCulture); + } + } + + /// + /// 查找类似 参数“{0}”不能为空引用或空字符串。 的本地化字符串。 + /// + internal static string ParameterCheck_NotNullOrEmpty_String { + get { + return ResourceManager.GetString("ParameterCheck_NotNullOrEmpty_String", resourceCulture); + } + } + + /// + /// 查找类似 类型“{0}”不是实体类型 的本地化字符串。 + /// + internal static string QueryCacheExtensions_TypeNotEntityType { + get { + return ResourceManager.GetString("QueryCacheExtensions_TypeNotEntityType", resourceCulture); + } + } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/Resources.resx b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/Resources.resx new file mode 100644 index 0000000..d73928a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Properties/Resources.resx @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 参数中的字符\"{0}\"不是 {1} 进制数的有效字符。 + + + 0 + + + 缓存功能尚未初始化,未找到可用的 ICacheProvider 实现。 + + + 标识为“{0}”的项重复定义 + + + 名称为“{0}”的类型不存在 + + + 请先初始化依赖注入服务,再使用OSharpContext.IocRegisterservices属性 + + + 上下文初始化类型“{0}”不存在 + + + 查询条件组中的操作类型错误,只能为And或者Or。 + + + 指定的属性“{0}”在类型“{1}”中不存在。 + + + 类型“{0}”不是仓储接口“IRepository<,>”的派生类。 + + + 类型“{0}”不是操作单元“IUnitOfWork”的派生类。 + + + 无法解析类型“{0}”的构造函数中类型为“{1}”的参数 + + + OSharp框架尚未初始化,请先初始化 + + + 类型“{0}”的实现类型无法找到 + {0}=service type + + + 类型“{0}”中找不到合适参数的构造函数 + + + 实现类型不能为“{0}”,因为该类型与注册为“{1}”的其他类型无法区分 + + + 创建名称为“{0}”的日志实例时“{1}”返回空实例。 + + + MapperExtensions.Mapper不能为空,请先设置值 + + + 当前Http上下文中不存在Request有效范围的Mef部件容器。 + + + 指定对象中不存在名称为“{0}”的属性。 + + + 指定名称“{0}”的属性类型不是“{1}”。 + + + 参数“{0}”的值必须在“{1}”与“{2}”之间。 + + + 参数“{0}”的值必须在“{1}”与“{2}”之间,且不能等于“{3}”。 + + + 指定的目录路径“{0}”不存在。 + + + 指定的文件路径“{0}”不存在。 + + + 集合“{0}”中不能包含null的项 + + + 参数“{0}”的值不能为Guid.Empty + + + 参数“{0}”的值必须大于“{1}”。 + + + 参数“{0}”的值必须大于或等于“{1}”。 + + + 参数“{0}”的值必须小于“{1}”。 + + + 参数“{0}”的值必须小于或等于“{1}”。 + + + 参数“{0}”不能为空引用。 + + + 参数“{0}”不能为空引用或空集合。 + + + 参数“{0}”不能为空引用或空字符串。 + + + 类型“{0}”不是实体类型 + + \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Result/ResultOutPut.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Result/ResultOutPut.cs new file mode 100644 index 0000000..c9ecea1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Result/ResultOutPut.cs @@ -0,0 +1,134 @@ +using System; +using System.Runtime.Serialization; + +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// 公共返回结果对象 + /// + [Serializable] + public class CommonResult + { + /// + /// BaseResult构造函数 + /// + public CommonResult() + { + } + + /// + /// BaseResult构造函数 + /// + /// 错误消息 + /// 错误代码 + public CommonResult(string errmsg, string errcode) + { + ErrMsg = errmsg; + ErrCode = errcode; + } + + /// + /// 构造函数 + /// + /// 错误消息 + /// 成功或失败 + /// 错误代码 + public CommonResult(string errmsg, bool success, string errcode) + { + ErrMsg = errmsg; + ErrCode = errcode; + Success = success; + } + + /// + /// 错误代码 + /// + private string m_ErrCode = "-1"; + + /// + /// 错误描述信息 + /// + private string m_ErrMsg; + + /// + /// 成功或失败 + /// + private bool m_Success = false; + + /// + /// 用来传递的object内容 + /// + [DataMember] private object m_ResData; + + /// + /// 错误代码 + /// + [DataMember] + public string ErrCode + { + get => m_ErrCode; + set + { + m_ErrCode = value; + if (value == "0") + { + Success = m_Success = true; + } + else + { + Success = m_Success = false; + } + } + } + + /// + /// 如果不成功,返回的错误描述信息 + /// + [DataMember] + public string ErrMsg + { + get => m_ErrMsg; + set => m_ErrMsg = value; + } + + /// + /// 成功返回true,失败返回false + /// + [DataMember] + public bool Success + { + get + { + if (ErrCode == "0") + { + m_Success = true; + } + + return m_Success; + } + set => m_Success = value; + } + + /// + /// 用来传递的object内容 + /// + [DataMember] + public object ResData + { + get => m_ResData; + set => m_ResData = value; + } + } + + /// + /// WEBAPI通用返回泛型基类 + /// + /// + public class CommonResult : CommonResult + { + /// + /// 回传的结果 + /// + public T Result { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Result/TokenResult.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Result/TokenResult.cs new file mode 100644 index 0000000..2ca33b6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Result/TokenResult.cs @@ -0,0 +1,49 @@ +namespace Znyc.Admin.Commons.Entitys +{ + /// + /// Token返回结果对象 + /// + public class TokenResult + { + /// + /// 构造函数 + /// + public TokenResult() + { + } + + private string m_AccessToken; + private int m_ExpiresIn; + + /// + /// 获取到的凭证值 + /// + public string AccessToken + { + get => m_AccessToken; + set => m_AccessToken = value; + } + + /// + /// 凭证有效时间,单位:分钟 + /// + public int ExpiresIn + { + get => m_ExpiresIn; + set => m_ExpiresIn = value; + } + } + + public class GrantType + { + /// + /// 密码校验。 + /// + public const string Password = "password"; + + /// + /// ClientCredential。 + /// + public const string ClientCredentials = "client_credential"; + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/JsTree.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/JsTree.cs new file mode 100644 index 0000000..8493ccc --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/JsTree.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.Json; + +namespace Znyc.Admin.Commons.Tree +{ + public static class JsTree + { + public static List JsTreeJson(this List data) + { + return JsTreeJson(data, 0, "").ToList(); + } + + private static string JsTreeJson(List data, long ParentId, string blank) + { + List list = new List(); + JsTreeModel jsTreeModel = new JsTreeModel(); + List ChildNodeList = data.FindAll(t => t.parent == ParentId); + string tabline = ""; + if (!string.IsNullOrEmpty(ParentId.ToString())) + { + tabline = ""; + } + + if (ChildNodeList.Count > 0) + { + tabline = tabline + blank; + } + + foreach (JsTreeModel entity in ChildNodeList) + { + jsTreeModel = entity; + jsTreeModel.children = JsTreeJson(data, entity.id, tabline).ToList(); + list.Add(jsTreeModel); + } + + return list.ToJson().ToString(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/JsTreeModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/JsTreeModel.cs new file mode 100644 index 0000000..494b667 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/JsTreeModel.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace Znyc.Admin.Commons.Tree +{ + /// + /// JsTree 数据模型实体 + /// { + /// id : "string" // required + /// parent : "string" // required + /// text : "string" // node text + /// icon : "string" // string for custom + /// state : { + /// opened : boolean // is the node open + /// disabled : boolean // is the node disabled + /// selected : boolean // is the node selected + /// }, + /// li_attr : {} // attributes for the generated LI node + /// a_attr : {} // attributes for the generated A node + /// } + /// + public class JsTreeModel + { + public long id { get; set; } + public long parent { get; set; } + public string text { get; set; } + public string icon { get; set; } + public JsTreeStateModel state { get; set; } + public List children { get; set; } + } + + public class JsTreeStateModel + { + public bool opened { get; set; } + public bool disabled { get; set; } + public bool selected { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeSelect.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeSelect.cs new file mode 100644 index 0000000..77a7ba7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeSelect.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.Text; +using Znyc.Admin.Commons.Json; + +namespace Znyc.Admin.Commons.Tree +{ + /// + /// + /// + public static class TreeSelect + { + /// + /// + /// + /// + /// + public static string TreeSelectJson(this List data) + { + StringBuilder sb = new StringBuilder(); + sb.Append("["); + sb.Append(TreeSelectJson(data, 0, "")); + sb.Append("]"); + return sb.ToString(); + } + + /// + /// + /// + /// + /// + /// + /// + private static string TreeSelectJson(List data, int ParentId, string blank) + { + StringBuilder sb = new StringBuilder(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId); + string tabline = ""; + if (!string.IsNullOrEmpty(ParentId.ToString())) + { + tabline = "  "; + } + + if (ChildNodeList.Count > 0) + { + tabline = tabline + blank; + } + + foreach (TreeSelectModel entity in ChildNodeList) + { + entity.text = tabline + entity.text; + string strJson = entity.ToJson(); + sb.Append(strJson); + sb.Append(TreeSelectJson(data, entity.Id, tabline)); + } + + return sb.ToString().Replace("}{", "},{"); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeSelectModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeSelectModel.cs new file mode 100644 index 0000000..ced1626 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeSelectModel.cs @@ -0,0 +1,33 @@ +namespace Znyc.Admin.Commons.Tree +{ + /// + /// + /// + public class TreeSelectModel + { + /// + /// + /// + public int Id { get; set; } + + /// + /// + /// + public string text { get; set; } + + /// + /// + /// + public int ParentId { get; set; } + + /// + /// + /// + public int ParentId1 { get; set; } + + /// + /// + /// + public object data { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeView.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeView.cs new file mode 100644 index 0000000..cdbb1d3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeView.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.Text; + +namespace Znyc.Admin.Commons.Tree +{ + /// + /// + /// + public static class TreeView + { + /// + /// + /// + /// + /// + /// + public static string TreeViewJson(this List data, int ParentId = 0) + { + StringBuilder strJson = new StringBuilder(); + //List item = data.FindAll(t => t.ParentId == ParentId); + //strJson.Append("["); + //if (item.Count > 0) + //{ + // foreach (TreeViewModel entity in item) + // { + // strJson.Append("{"); + // strJson.Append("\"id\":\"" + entity.id + "\","); + // strJson.Append("\"text\":\"" + entity.text.Replace(" ", "") + "\","); + // strJson.Append("\"value\":\"" + entity.value + "\","); + // if (entity.title != null && !string.IsNullOrEmpty(entity.title.Replace(" ", ""))) + // { + // strJson.Append("\"title\":\"" + entity.title.Replace(" ", "") + "\","); + // } + // if (entity.img != null && !string.IsNullOrEmpty(entity.img.Replace(" ", ""))) + // { + // strJson.Append("\"img\":\"" + entity.img.Replace(" ", "") + "\","); + // } + // if (entity.checkstate != null) + // { + // strJson.Append("\"checkstate\":" + entity.checkstate + ","); + // } + // if (entity.ParentId != null) + // { + // strJson.Append("\"parentnodes\":\"" + entity.ParentId + "\","); + // } + // strJson.Append("\"showcheck\":" + entity.showcheck.ToString().ToLower() + ","); + // strJson.Append("\"isexpand\":" + entity.isexpand.ToString().ToLower() + ","); + // if (entity.complete == true) + // { + // strJson.Append("\"complete\":" + entity.complete.ToString().ToLower() + ","); + // } + // strJson.Append("\"hasChildren\":" + entity.hasChildren.ToString().ToLower() + ","); + // strJson.Append("\"ChildNodes\":" + TreeViewJson(data, entity.id) + ""); + // strJson.Append("},"); + // } + // strJson = strJson.Remove(strJson.Length - 1, 1); + //} + //strJson.Append("]"); + return strJson.ToString(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeViewModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeViewModel.cs new file mode 100644 index 0000000..68eaff1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/TreeViewModel.cs @@ -0,0 +1,115 @@ +using System.Collections.Generic; + +namespace Znyc.Admin.Commons.Tree +{ + /// + /// 树形视图模型 + /// + public class TreeViewModel + { + /// + /// 构造函数 + /// + public TreeViewModel() + { + nodes = new List(); + } + + /// + /// 构造函数 + /// + /// j节点Id + /// 父节点Id + public TreeViewModel(int nodeId, int pId) + { + this.nodeId = nodeId; + pid = pId; + nodes = new List(); + } + + /** + * 生成一个节点 + * @param nodeId + * @param pId + * @param text + * @param icon + * @param href + */ + + public TreeViewModel(int nodeId, int pId, string text, string icon, string href) + { + this.nodeId = nodeId; + pid = pId; + this.text = text; + this.icon = icon; + this.href = href; + nodes = new List(); + } + + /// + /// 树的节点Id,区别于数据库中保存的数据Id + /// + public long nodeId { get; set; } + + /// + /// 树的父节点Id + /// + public long pid { get; set; } + + /// + /// 节点名称 + /// + public string text { get; set; } + + /// + /// 节点图标 + /// + public string icon { get; set; } + + /// + /// 点击节点触发的链接 + /// + public string href { get; set; } + + /// + /// 子节点 + /// + public List nodes { get; set; } + + /// + /// 节点标签 + /// + public long tags { get; set; } + + /// + /// 节点状态 + /// + public TreeViewSateModel state { get; set; } + } + + /// + /// 树形视图节点选择状态 + /// + public class TreeViewSateModel + { + /// + /// 选中 + /// + public bool @checked { get; set; } + + /// + /// 显示或隐藏 + /// + public bool? disabled { get; set; } + + /// + /// 展开 + /// + public bool? expanded { get; set; } + + /// + /// 选中 + /// + public bool? selected { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/VueRouterModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/VueRouterModel.cs new file mode 100644 index 0000000..bd21ad7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Tree/VueRouterModel.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; + +namespace Znyc.Admin.Commons.Tree +{ + /// + /// Vuex菜单模型 + /// + [Serializable] + public class VueRouterModel + { + /// + /// 设定路由的名字,一定要填写不然使用keep-alive时会出现各种问题 + /// + public string name { get; set; } + + /// + /// 路由地址,对应当前路由的路径,总是解析为绝对路径 + /// + public string path { get; set; } + + /// + /// 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 + /// + public bool hidden { get; set; } + + /// + /// 命名视图组件,组件地址 + /// + public string component { get; set; } + + /// + /// 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + /// + public string redirect { get; set; } + + /// + /// 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + /// + public bool alwaysShow { get; set; } + + /// + /// 在根路由设置权限,这样它下面所以的子路由都继承了这个权限 + /// + public Meta meta { get; set; } + + /// + /// 子路由,子菜单 + /// + public List children { get; set; } + } + + /// + /// 路由元信息模型 + /// + [Serializable] + public class Meta + { + /// + /// 构造函数 + /// + /// + /// + /// + public Meta(string title, string icon, bool noCache) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + /// + /// 设置该路由在侧边栏和面包屑中展示的名字 + /// + public string title { get; set; } + + /// + /// 设置该路由的图标 + /// + public string icon { get; set; } + + /// + /// 设置为true,则不会被keep-alive缓存 + /// + public bool noCache { get; set; } + + /// + /// 当路由设置了该属性,则会高亮相对应的侧边栏。 + /// 这在某些场景非常有用,比如:一个文章的列表页路由为:/article/list + /// 点击文章进入文章详情页,这时候路由为/article/1,但你想在侧边栏高亮文章列表的路由,就可以进行如下设置 + /// activeMenu: '/article/list' + /// + public string activeMenu { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/Captcha.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/Captcha.cs new file mode 100644 index 0000000..6b96ca3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/Captcha.cs @@ -0,0 +1,145 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Threading.Tasks; + +namespace Znyc.Admin.Commons.VerificationCode +{ + /// + /// 验证码实现 + /// + public class Captcha + { + private const string Letters = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z"; + + /// + /// 生成验证码图片 + /// + /// 验证码 + /// 图形宽度,默认为验证码长度x25 + /// 图形高度,默认30px + /// + public async Task GenerateCaptchaImageAsync(string captchaCode, int width = 0, int height = 30) + { + //验证码颜色集合 + Color[] c = + { + Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, + Color.Purple + }; + + //验证码字体集合 + string[] fonts = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial" }; + + //定义图像的大小,生成图像的实例 + Bitmap image = new Bitmap(width == 0 ? captchaCode.Length * 25 : width, height); + + Graphics g = Graphics.FromImage(image); + + //背景设为白色 + g.Clear(Color.White); + + Random random = new Random(); + // 画图片的背景噪音线 + for (int i = 0; i < 100; i++) + { + int x = random.Next(image.Width); + int y = random.Next(image.Height); + g.DrawRectangle(new Pen(Color.LightGray, 0), x, y, 1, 1); + } + + //验证码绘制在g中 + for (int i = 0; i < captchaCode.Length; i++) + { + //随机颜色索引值 + int cindex = random.Next(c.Length); + + //随机字体索引值 + int findex = random.Next(fonts.Length); + + //字体 + Font f = new Font(fonts[findex], 15, FontStyle.Bold); + + //颜色 + Brush b = new SolidBrush(c[cindex]); + + int ii = 4; + if ((i + 1) % 2 == 0) + { + ii = 2; + } + + //绘制一个验证字符 + g.DrawString(captchaCode.Substring(i, 1), f, b, 17 + i * 17, ii); + } + + //画图片的前景噪音点 + for (int i = 0; i < 100; i++) + { + int x = random.Next(image.Width); + int x1 = random.Next(image.Width); + int y = random.Next(image.Height); + int y1 = random.Next(image.Height); + if (i % 11 == 0) + { + g.DrawLine(new Pen(Color.Silver), x, y, x1, y1); + } + + image.SetPixel(x, y, Color.FromArgb(random.Next())); + } + + //画图片的边框线 + //g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1); + MemoryStream ms = new MemoryStream(); + image.Save(ms, ImageFormat.Png); + + g.Dispose(); + image.Dispose(); + + return await Task.FromResult(new CaptchaResult + { + CaptchaCode = captchaCode, + CaptchaMemoryStream = ms, + Timestamp = DateTime.Now + }); + } + + /// + /// 生成随机验证码字符 + /// + /// 验证码位数 + /// + public async Task GenerateRandomCaptchaAsync(int codeLength = 4) + { + string[] array = Letters.Split(new[] { ',' }); + + Random random = new Random(); + + int temp = -1; + + string captcheCode = string.Empty; + + for (int i = 0; i < codeLength; i++) + { + if (temp != -1) + { + random = new Random(i * temp * unchecked((int)DateTime.Now.Ticks)); + } + + int index = random.Next(array.Length); + + if (temp != -1 && temp == index) + { + return await GenerateRandomCaptchaAsync(codeLength); + } + + temp = index; + + captcheCode += array[index]; + } + + return await Task.FromResult(captcheCode); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/CaptchaResult.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/CaptchaResult.cs new file mode 100644 index 0000000..ae76f55 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/CaptchaResult.cs @@ -0,0 +1,26 @@ +using System; +using System.IO; + +namespace Znyc.Admin.Commons.VerificationCode +{ + /// + /// 验证码返回结果 + /// + public class CaptchaResult + { + /// + /// 验证码字符串 + /// + public string CaptchaCode { get; set; } + + /// + /// 验证码内存流 + /// + public MemoryStream CaptchaMemoryStream { get; set; } + + /// + /// 验证码生成时间 + /// + public DateTime Timestamp { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/ICaptcha.cs b/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/ICaptcha.cs new file mode 100644 index 0000000..de3fbb5 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/VerificationCode/ICaptcha.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; + +namespace Znyc.Admin.Commons.VerificationCode +{ + /// + /// 验证码接口 + /// + public interface ICaptcha + { + /// + /// 生成随机验证码 + /// + /// + /// + Task GenerateRandomCaptchaAsync(int codeLength = 4); + + /// + /// 生成验证码图片 + /// + /// 验证码 + /// 宽为0将根据验证码长度自动匹配合适宽度 + /// 高 + /// + Task GenerateCaptchaImageAsync(string captchaCode, int width = 0, int height = 30); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Commons/Znyc.Admin.Commons.csproj b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Znyc.Admin.Commons.csproj new file mode 100644 index 0000000..4c1d1b7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Commons/Znyc.Admin.Commons.csproj @@ -0,0 +1,173 @@ + + + + net6.0 + Znyc.Admin + + + + + true + + 1.0 + true + + + + + 1.3.1.32 + MIT + + + + bin\Debug\Znyc.Admin.Commons.xml + bin\Debug\ + + + + bin\Release\ + bin\Release\Znyc.Admin.Commons.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/AreaApp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/AreaApp.cs new file mode 100644 index 0000000..23591d6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/AreaApp.cs @@ -0,0 +1,283 @@ +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Linq; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Tree; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.Repositories; + +namespace Znyc.Admin.Security.Application +{ + /// + /// 地区 + /// + public class AreaApp + { + private readonly IAreaRepository service = new AreaRepository(); + + #region 适配于管理后端 + + /// + /// 树形展开treeview需要,数据字典管理页面 + /// + /// + public List ItemsTreeViewJson() + { + List list = new List(); + List listFunction = service.GetListWhere("Layers in (0,1,2)").OrderBy(t => t.SortCode).ToList(); + list = TreeViewJson(listFunction, 0); + return list; + } + + //public List AreaTreeViewJson() + //{ + //string where = "1=1 and Layers in(0,1,2)"; + //bool order = orderByDir == "asc" ? false : true; + //if (!string.IsNullOrEmpty(keywords)) + //{ + // where += string.Format(" and (FullName like '%{0}%' or EnCode like '%{0}%')", keywords); + //} + //List list = _service.GetListWhere(where).OrderBy(t => t.SortCode).ToList().MapTo(); + + //return ToJsonContent(list); + + //List list = new List(); + //List listFunction = service.GetListWhere("Layers in (3,4)").OrderBy(t => t.SortCode).ToList(); + //list = TreeViewJson(listFunction, ""); + //return list; + //} + /// + /// + /// + /// + /// + /// + public List TreeViewJson(List data, long ParentId) + { + List list = new List(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId).ToList(); + foreach (Area entity in ChildNodeList) + { + TreeViewModel treeViewModel = new TreeViewModel + { + nodeId = entity.Id, + pid = entity.ParentId, + text = entity.FullName, + nodes = ChildrenTreeViewList(data, entity.Id), + tags = entity.Id + }; + list.Add(treeViewModel); + } + + return list; + } + + /// + /// + /// + /// + /// + /// + public List ChildrenTreeViewList(List data, long ParentId) + { + List listChildren = new List(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId).ToList(); + foreach (Area entity in ChildNodeList) + { + TreeViewModel treeViewModel = new TreeViewModel + { + nodeId = entity.Id, + pid = entity.ParentId, + text = entity.FullName, + nodes = ChildrenTreeViewList(data, entity.Id), + tags = entity.Id + }; + listChildren.Add(treeViewModel); + } + + return listChildren; + } + + #endregion 适配于管理后端 + + #region 用于uniapp下拉选项 + + /// + /// 获取所有可用的地区,用于uniapp下拉选项 + /// + /// + public List GetAllByEnable() + { + List list = new List(); + CacheHelper cacheHelper = new CacheHelper(); + list = JsonConvert.DeserializeObject>(cacheHelper.Get("Area_Enable_Uniapp") + .ToJson()); + if (list == null || list.Count <= 0) + { + List listFunction = service.GetAllByIsNotDeleteAndEnabledMark("Layers in (0,1,2)") + .OrderBy(t => t.SortCode).ToList(); + list = UniappViewJson(listFunction, 0); + cacheHelper.Add("Area_Enable_Uniapp", list); + } + + return list; + } + + /// + /// 获取省、市、县/区三级可用的地区,用于uniapp下拉选项 + /// + /// + public List GetProvinceToAreaByEnable() + { + List list = new List(); + CacheHelper cacheHelper = new CacheHelper(); + list = JsonConvert.DeserializeObject>(cacheHelper + .Get("Area_ProvinceToArea_Enable_Uniapp").ToJson()); + if (list == null || list.Count <= 0) + { + List listFunctionTemp = service.GetAllByIsNotDeleteAndEnabledMark("Layers in (1,2,3)").OrderBy(t => t.Id) + .ToList(); + List listFunction = new List(); + foreach (Area item in listFunctionTemp) + { + if (item.Layers == 1) + { + item.ParentId = 0; + } + + listFunction.Add(item); + } + + list = UniappViewJson(listFunction, 0); + cacheHelper.Add("Area_ProvinceToArea_Enable_Uniapp", list); + } + + return list; + } + + /// + /// + /// + /// + /// + /// + public List UniappViewJson(List data, long ParentId) + { + List list = new List(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId).ToList(); + foreach (Area entity in ChildNodeList) + { + AreaPickerOutputDto treeViewModel = new AreaPickerOutputDto + { + value = entity.Id, + label = entity.FullName, + children = ChildrenUniappViewList(data, entity.Id) + }; + list.Add(treeViewModel); + } + + return list; + } + + /// + /// + /// + /// + /// + /// + public List ChildrenUniappViewList(List data, long ParentId) + { + List listChildren = new List(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId).ToList(); + foreach (Area entity in ChildNodeList) + { + AreaPickerOutputDto treeViewModel = new AreaPickerOutputDto + { + value = entity.Id, + label = entity.FullName, + children = ChildrenUniappViewList(data, entity.Id) + }; + listChildren.Add(treeViewModel); + } + + return listChildren; + } + + #endregion 用于uniapp下拉选项 + + #region 适用于select2省市县区级联选择 + + /// + /// 获取省可用的地区,用于select2下拉选项 + /// + /// + public List GetProvinceAll() + { + List list = new List(); + CacheHelper cacheHelper = new CacheHelper(); + list = JsonConvert.DeserializeObject>(cacheHelper + .Get("Area_ProvinceToArea_Select2").ToJson()); + if (list == null || list.Count <= 0) + { + list = service.GetAllByIsNotDeleteAndEnabledMark("Layers =1").OrderBy(t => t.Id).ToList() + .MapTo(); + + cacheHelper.Add("Area_ProvinceToArea_Select2", list); + } + + return list; + } + + /// + /// 获取城市,用于select2下拉选项 + /// + /// 省份Id + /// + public List GetCityByProvinceId(long id) + { + List list = new List(); + CacheHelper cacheHelper = new CacheHelper(); + list = JsonConvert.DeserializeObject>(cacheHelper + .Get("Area_CityToArea_Enable_Select2" + id).ToJson()); + if (list == null || list.Count <= 0) + { + string sqlWhere = string.Format("ParentId='{0}'", id); + list = service.GetAllByIsNotDeleteAndEnabledMark(sqlWhere).OrderBy(t => t.Id).ToList() + .MapTo(); + + cacheHelper.Add("Area_CityToArea_Enable_Select2" + id, list); + } + + return list; + } + + /// + /// 获取县区,用于select2下拉选项 + /// + /// 城市Id + /// + public List GetDistrictByCityId(long id) + { + List list = new List(); + CacheHelper cacheHelper = new CacheHelper(); + list = JsonConvert.DeserializeObject>(cacheHelper + .Get("Area_DistrictToArea_Enable_Select2" + id).ToJson()); + if (list == null || list.Count <= 0) + { + string sqlWhere = string.Format("ParentId='{0}'", id); + list = service.GetAllByIsNotDeleteAndEnabledMark(sqlWhere).OrderBy(t => t.Id).ToList() + .MapTo(); + + cacheHelper.Add("Area_DistrictToArea_Enable_Select2" + id, list); + } + + return list; + } + + #endregion 适用于select2省市县区级联选择 + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/MenuApp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/MenuApp.cs new file mode 100644 index 0000000..6c1ed76 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/MenuApp.cs @@ -0,0 +1,447 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Znyc.Admin.Commons.Core.App; +using Znyc.Admin.Commons.Extend; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Tree; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Application +{ + /// + /// + /// + public class MenuApp + { + private readonly IMenuService service = App.GetService(); + private readonly ISystemTypeService systemservice = App.GetService(); + private readonly IAdminUserService serviceUser = App.GetService(); + + /// + /// 获取菜单树JsTree模式 + /// + /// + public List MenuFuntionJsTree() + { + List list = new List(); + + List listMenu = service.GetAllByIsNotDeleteAndEnabledMark().OrderBy(t => t.SortCode).ToList(); + foreach (Menu item in listMenu) + { + JsTreeModel jsTreeModel = new JsTreeModel + { + id = item.Id, + text = item.FullName, + icon = item.Icon, + parent = item.ParentId + }; + JsTreeStateModel jsTreeStateModel = new JsTreeStateModel + { + disabled = false, + selected = true, + opened = true + }; + jsTreeModel.state = jsTreeStateModel; + list.Add(jsTreeModel); + } + + return list.JsTreeJson(); + } + + /// + /// + /// + /// + /// + public List GetMenu(long ParentId) + { + List list = new List(); + + return list; + } + + /// + /// 获取菜单树TreeView模式 + /// + /// + public List MenuFuntionTreeViewJson() + { + List list = new List(); + List listMenu = service.GetAll().OrderBy(t => t.SortCode).ToList(); + list = JsTreeJson(listMenu, 0, "").ToList(); + return list; + } + + /// + /// + /// + /// + /// + /// + /// + private static string JsTreeJson(List data, long ParentId, string blank) + { + List list = new List(); + TreeViewModel jsTreeModel = new TreeViewModel(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId); + string tabline = ""; + + if (ChildNodeList.Count > 0) + { + tabline = tabline + blank; + } + + foreach (Menu entity in ChildNodeList) + { + jsTreeModel.text = entity.FullName; + jsTreeModel.icon = entity.Icon; + //list.Add(jsTreeModel); + jsTreeModel.nodes = JsTreeJson(data, entity.Id, tabline).ToList(); + list.Add(jsTreeModel); + } + + return list.ToJson().ToString(); + } + + /// + /// 根据用户角色获取菜单树VuexMenusTree模式 + /// + /// 角色ID + /// 系统类型代码子系统代码 + /// + public List GetMenuFuntionJson(long roleIds, string systemCode) + { + List list = new List(); + try + { + SystemType systemType = systemservice.GetByCode(systemCode); + list = GetMenusByRole(roleIds, systemType.Id.ToString()).OrderBy(t => t.SortCode) + .MapTo(); + } + catch (Exception ex) + { + Log4NetHelper.Error("根据用户角色和子系统代码获取菜单异常", ex); + } + + return list; + } + + /// + /// 根据用户角色获取菜单树VuexMenusTree模式 + /// + /// 系统类型代码子系统代码 + /// + public List GetMenuFuntionJson(string systemCode) + { + List list = new List(); + try + { + SystemType systemType = systemservice.GetByCode(systemCode); + List listMenu = GetMenusByRole(systemType.Id).OrderBy(t => t.SortCode).ToList(); + list = listMenu.MapTo(); + } + catch (Exception ex) + { + Log4NetHelper.Error("根据用户角色和子系统代码获取菜单异常", ex); + } + + return list; + } + + /// + /// 构建菜单树 + /// + /// 菜单列表 + /// 父级Id + /// + public List BuildTreeMenus(List menus, long ParentId = 0) + { + List resultList = new List(); + List childNodeList = menus.FindAll(t => t.ParentId == ParentId); + foreach (Menu menu in childNodeList) + { + MenuOutputDto menuOutputDto = new MenuOutputDto(); + menuOutputDto = menu.MapTo(); + List subChildNodeList = menus.FindAll(t => t.ParentId == menu.Id); + if (subChildNodeList.Count > 0) + { + menuOutputDto.SubMenu = BuildTreeMenus(menus, menu.Id); + } + + resultList.Add(menuOutputDto); + } + + return resultList; + } + + #region 获取 Vue Router + + /// + /// 根据用户角色获取菜单树VueRouter模式 + /// + /// 角色ID + /// 系统类型代码子系统代码 + /// + public List GetVueRouter(long roleIds, string systemCode) + { + List list = new List(); + try + { + SystemType systemType = systemservice.GetByCode(systemCode); + List listMenu = GetMenusByRole(roleIds, systemType.Id.ToString()).OrderBy(t => t.SortCode).ToList(); + List listTree = BuildTreeMenus(listMenu); + list = BuildMenus(listTree); + } + catch (Exception ex) + { + Log4NetHelper.Error("根据用户角色和子系统代码获取菜单异常", ex); + } + + return list; + } + + /// + /// 构建前端路由所需要的菜单 + /// + /// 菜单列表 + /// + public List BuildMenus(List menus) + { + List routers = new List(); + foreach (MenuOutputDto menu in menus) + { + VueRouterModel router = new VueRouterModel + { + hidden = menu.IsShow ? false : true, + name = GetRouteName(menu), + path = GetRouterPath(menu), + component = GetComponent(menu) + }; + Meta meta = new Meta(menu.FullName, menu.Icon == null ? "" : menu.Icon, menu.IsCache); + if (!menu.IsShow && menu.MenuType.Contains("M")) + { + meta.activeMenu = menu.ActiveMenu; + } + + router.meta = meta; + List cMenus = menu.SubMenu; + if (cMenus != null && menu.MenuType == "C") + { + router.alwaysShow = true; + router.redirect = "noRedirect"; + router.children = BuildMenus(cMenus); + } + else if (IsMeunDoc(menu)) + { + List childrenList = new List(); + VueRouterModel childrenRouter = new VueRouterModel + { + path = menu.UrlAddress, + component = menu.Component, + name = menu.EnCode, + meta = new Meta(menu.FullName, menu.Icon == null ? "" : menu.Icon, menu.IsCache) + }; + childrenRouter.meta = meta; + childrenList.Add(childrenRouter); + router.children = childrenList; + } + else if (IsMeunFrame(menu) && cMenus != null) + { + if (!menu.IsShow) + { + router.hidden = true; + } + + router.children = BuildMenus(cMenus); + } + + routers.Add(router); + } + + return routers; + } + + /// + /// 获取路由名称 + /// + /// 菜单信息 + /// + public string GetRouteName(MenuOutputDto menu) + { + string routerName = menu.EnCode; + // 非外链并且是一级目录(类型为目录) + if (IsMeunDoc(menu)) + { + routerName = ""; + } + + return routerName; + } + + /// + /// 获取路由地址 + /// + /// 菜单信息 + /// + public string GetRouterPath(MenuOutputDto menu) + { + string routerPath = menu.UrlAddress; + // 非外链并且是一级目录(类型为目录) + if (0 == menu.ParentId && menu.MenuType == "C" && !menu.IsFrame) + { + routerPath = menu.UrlAddress; // "/" + menu.EnCode; + } + // 非外链并且是一级目录(类型为菜单) + else if (IsMeunDoc(menu)) + { + routerPath = "/"; + } + + return routerPath; + } + + /// + /// 获取组件信息 + /// + /// 菜单信息 + /// + public string GetComponent(MenuOutputDto menu) + { + string component = "Layout"; + if (!string.IsNullOrEmpty(menu.Component) && IsMeunFrame(menu) && !IsMeunDoc(menu)) + { + component = menu.Component; + } + else if (string.IsNullOrEmpty(menu.Component) && IsParentView(menu)) + { + component = "ParentView"; + } + + return component; + } + + /// + /// 是否为菜单内部跳转,并且是一级目录 + /// + /// 菜单信息 + /// + public bool IsMeunDoc(MenuOutputDto menu) + { + return menu.ParentId == 0 && menu.MenuType == "M" && !menu.IsFrame; + } + + /// + /// 是否为菜单内部跳转 + /// + /// 菜单信息 + /// + public bool IsMeunFrame(MenuOutputDto menu) + { + return menu.MenuType == "M" && !menu.IsFrame; + } + + /// + /// 是否为parent_view组件 + /// + /// 菜单信息 + /// + public bool IsParentView(MenuOutputDto menu) + { + return menu.ParentId != 0 && menu.MenuType == "C"; + } + + #endregion 获取 Vue Router + + /// + /// 根据用户获取功能菜单 + /// + /// 用户角色ID + /// 系统类型ID/子系统ID + /// + public List GetMenusByRole(long roleIds, string systemId) + { + List menuListResult = new List(); + if (roleIds == 0) + { + menuListResult = service.GetFunctions("", systemId, true); + } + else + { + // string roleIDsStr = string.Format("'{0}'", roleIds.Replace(",", "','")); + string roleIDsStr = ""; + menuListResult = service.GetFunctions(roleIDsStr, systemId, true); + } + + return menuListResult; + } + + /// + /// 根据用户获取功能菜单 + /// + /// 系统类型ID/子系统ID + /// + public List GetMenusByRole(long systemId) + { + List menuListResult = service + .GetAllByIsNotDeleteAndEnabledMark("MenuType in ('M','C') and SystemTypeId='" + systemId + "'") + .ToList(); + return menuListResult; + } + + /// + /// 根据用户ID,获取对应的功能列表 + /// + /// 用户ID + /// 系统类别ID + /// + public List GetFunctionsByUser(long userId, string typeID) + { + string where = string.Format(""); + string roleId = serviceUser.Get(userId).RoleId.ToString(); + List functions = new List(); + string roleIDsStr = string.Format("'{0}'", roleId.Replace(",", "','")); + if (roleIDsStr != "") + { + functions = service.GetFunctions(roleIDsStr, typeID).ToList().MapTo(); + } + + return functions; + } + + /// + /// 根据用户角色IDs,获取对应的功能列表 + /// + /// 用户角色ID + /// 系统类型ID/子系统ID + /// + public List GetFunctionsByRole(string roleIds, string systemId) + { + string where = string.Format(""); + List functions = new List(); + string roleIDsStr = string.Format("'{0}'", roleIds.Replace(",", "','")); + if (roleIDsStr != "") + { + functions = service.GetFunctions(roleIDsStr, systemId).ToList().MapTo(); + } + + return functions; + } + + /// + /// 根据用户角色IDs,获取对应的功能列表 + /// + /// 系统类型ID/子系统ID + /// + public List GetFunctionsBySystem(string systemId) + { + List functions = new List(); + functions = service.GetFunctions(systemId).ToList().MapTo(); + return functions; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/UploadFileApp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/UploadFileApp.cs new file mode 100644 index 0000000..5295705 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/UploadFileApp.cs @@ -0,0 +1,221 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.IO; +using Znyc.Admin.Commons.Core.App; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Options; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Application +{ + /// + /// 文件上传 + /// + public class UploadFileApp + { + private readonly ILogger _logger; + private readonly string _filePath; + private string _dbFilePath; //数据库中的文件路径 + private string _dbThumbnail; //数据库中的缩略图路径 + private string _belongApp; //所属应用 + private string _belongAppId; //所属应用ID + private readonly IUploadFileService service = App.GetService(); + + /// + /// + /// + public UploadFileApp() + { + } + + /// + /// + /// + /// + /// + public UploadFileApp(IOptions setOptions, ILogger logger) + { + _logger = logger; + _filePath = setOptions.Value.LocalPath; + if (string.IsNullOrEmpty(_filePath)) + { + _filePath = AppContext.BaseDirectory; + } + } + + /// + /// 根据应用Id和应用标识批量更新数据 + /// + /// 应用Id + /// 更新前旧的应用Id + /// 应用标识 + /// + public bool UpdateByBeLongAppId(string belongAppId, string oldBeLongAppId, string beLongApp = null) + { + return service.UpdateByBeLongAppId(belongAppId, oldBeLongAppId, beLongApp); + } + + /// + /// 新增 + /// + /// + /// + public long Insert(UploadFile info) + { + return service.Insert(info); + } + + /// + /// 同步查询单个实体。 + /// + /// 主键 + /// + public UploadFile Get(long id) + { + return service.Get(id); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 分页实体 + /// 排序字段 + /// 是否降序 + /// 指定对象的集合 + public List FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc) + { + return service.FindWithPager(condition, info, fieldToSort, desc, null).MapTo(); + } + + /// + /// 批量上传文件 + /// + /// 文件 + /// 所属应用,如文章article + /// 所属应用ID,如文章id + /// + public List Adds(IFormFileCollection files, string belongApp, string belongAppId) + { + List result = new List(); + foreach (IFormFile file in files) + { + if (file != null) + { + result.Add(Add(file, belongApp, belongAppId)); + } + } + + return result; + } + + /// + /// 单个上传文件 + /// + /// + /// 所属应用,如文章article + /// 所属应用ID,如文章id + /// + public UploadFileResultOuputDto Add(IFormFile file, string belongApp, string belongAppId) + { + _belongApp = belongApp; + _belongAppId = belongAppId; + if (file != null && file.Length > 0 && file.Length < 10485760) + { + using (BinaryReader binaryReader = new BinaryReader(file.OpenReadStream())) + { + string fileName = Path.GetFileName(file.FileName); + byte[] data = binaryReader.ReadBytes((int)file.Length); + UploadFile(fileName, data); + + UploadFile filedb = new UploadFile + { + FilePath = _dbFilePath, + Thumbnail = _dbThumbnail, + FileName = fileName, + FileSize = file.Length.ToInt(), + FileType = Path.GetExtension(fileName), + Extension = Path.GetExtension(fileName), + BelongApp = _belongApp, + BelongAppId = _belongAppId + }; + service.Insert(filedb); + return filedb.MapTo(); + } + } + else + { + Log4NetHelper.Error("文件过大"); + throw new Exception("文件过大"); + } + } + + /// + /// 实现文件上传到服务器保存,并生成缩略图 + /// + /// 文件名称 + /// 文件字节流 + private void UploadFile(string fileName, byte[] fileBuffers) + { + string folder = DateTime.Now.ToString("yyyyMMdd"); + + //判断文件是否为空 + if (string.IsNullOrEmpty(fileName)) + { + Log4NetHelper.Error("文件名不能为空"); + throw new Exception("文件名不能为空"); + } + + //判断文件是否为空 + if (fileBuffers.Length < 1) + { + Log4NetHelper.Error("文件不能为空"); + throw new Exception("文件不能为空"); + } + + string _tempfilepath = "/upload/" + _belongApp + "/" + folder + "/"; + string uploadPath = _filePath + _tempfilepath; + if (!Directory.Exists(uploadPath)) + { + Directory.CreateDirectory(uploadPath); + } + + string ext = Path.GetExtension(fileName).ToLower(); + string newName = 0 + ext; + + using (FileStream fs = new FileStream(uploadPath + newName, FileMode.Create)) + { + fs.Write(fileBuffers, 0, fileBuffers.Length); + fs.Close(); + //生成缩略图 + if (ext.Contains(".jpg") || ext.Contains(".jpeg") || ext.Contains(".png") || ext.Contains(".bmp") || + ext.Contains(".gif")) + { + string thumbnailName = 0 + ext; + ImgHelper.MakeThumbnail(uploadPath + newName, uploadPath + thumbnailName); + _dbThumbnail = folder + "/" + thumbnailName; + } + + _dbFilePath = _tempfilepath + "/" + newName; + } + } + + /// + /// 统计上传内容数 + /// + /// + public long GetCountTotal() + { + return service.GetCountByWhere("1=1"); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/UserApp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/UserApp.cs new file mode 100644 index 0000000..3692f1f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Application/UserApp.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.App; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Application +{ + /// + /// + /// + public class UserApp + { + private readonly IAdminUserService service = App.GetService(); + private readonly IAdminUserLogOnService userLogOnService = App.GetService(); + private readonly IRoleService roleService = App.GetService(); + + /// + /// 获取所有用户信息 + /// + /// + public IEnumerable GetAll() + { + return service.GetAll(); + } + + /// + /// 根据用户账号查询用户信息 + /// + /// + /// + public async Task GetByUserName(string userName) + { + return await service.GetByUserName(userName); + } + + /// + /// 根据第三方OpenId查询用户信息 + /// + /// 第三方类型 + /// OpenId值 + /// + public UserOutputDto GetUserOutDtoByOpenId(string openIdType, string openId) + { + return service.GetUserByOpenId(openIdType, openId).MapTo(); + } + + /// + /// 根据第三方OpenId查询用户信息 + /// + /// 第三方类型 + /// OpenId值 + /// + public AdminUser GetUserByOpenId(string openIdType, string openId) + { + return service.GetUserByOpenId(openIdType, openId); + } + + /// + /// 更新用户 + /// + /// 用户信息 + /// + public bool UpdateUser(AdminUser user) + { + return service.Update(user, user.Id); + } + + /// + /// 根据用户ID获取头像 + /// + /// 用户ID + /// + public string GetHeadIconById(long userId) + { + AdminUser user = service.Get(userId); + + if (user != null) + { + return user.HeadIcon; + } + else + { + return ""; + } + } + + /// + /// 查询用户信息 + /// + /// 用户Id + /// + public AdminUser GetUserById(long id) + { + return service.Get(id); + } + + /// + /// 根据用户id和第三方类型查询 + /// + /// + /// + /// + public UserOpenIds GetUserOpenIdById(long userId, string openIdType) + { + return service.GetUserOpenIdByuserId(openIdType, userId); + } + + /// + /// 根据微信统一ID(UnionID)查询用户 + /// + /// UnionID + /// + public AdminUser GetUserByUnionId(string unionId) + { + return service.GetUserByUnionId(unionId); + } + + /// + /// 统计用户数 + /// + /// + public long GetCountTotal() + { + return service.GetCountByWhere("1=1"); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminCurrentUser.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminCurrentUser.cs new file mode 100644 index 0000000..10158e3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminCurrentUser.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using Znyc.Admin.Commons.Tree; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 登录成功返回用户信息 + /// + [Serializable] + public class AdminCurrentUser + { + /// + /// 授权token码 + /// + public string AccessToken { get; set; } + + /// + /// appkey + /// + public string AppKey { get; set; } + + /// + /// 用户ID + /// + public long UserId { get; set; } + + /// + /// 用户账号 + /// + public string Account { get; set; } + + /// + /// 用户名 + /// + public string Name { get; set; } + + /// + /// 昵称 + /// + public string UserName { get; set; } + + /// + /// 姓名 + /// + public string RealName { get; set; } + + /// + /// 头像 + /// + public string HeadIcon { get; set; } + + /// + /// 性别 + /// + public int? Gender { get; set; } + + /// + /// 头像 + /// + public long MemberGradeId { get; set; } + + /// + /// 上级推广员 + /// + public long ReferralUserId { get; set; } + + /// + /// 注册时间 + /// + public DateTime CreateTime { get; set; } + + /// + /// 组织主键 + /// + public virtual long OrganizeId { get; set; } + + /// + /// 部门主键 + /// + public virtual long DeptId { get; set; } + + /// + /// 角色编码,多个角色,使用“,”分格 + /// + public string Role { get; set; } + + /// + /// 手机号码 + /// + public string MobilePhone { get; set; } + + /// + /// 其他对象 + /// + public object OtherOpenObj { get; set; } + + /// + /// 微信登录SessionId + /// + public string WxSessionId { get; set; } + + /// + /// 租户TenantId + /// + public long TenantId { get; set; } + + /// + /// 登录IP地址 + /// + public virtual string CurrentLoginIP { get; set; } + + /// + /// 登录IP地址 + /// + public virtual string IPAddressName { get; set; } + + /// + /// 当前访问的系统Id + /// + public long ActiveSystemId { get; set; } + + /// + /// 当前访问的系统名称 + /// + public string ActiveSystem { get; set; } + + /// + /// 当前访问的系统Url + /// + public string ActiveSystemUrl { get; set; } + + /// + /// 可以访问子系统 + /// + public List SubSystemList { get; set; } + + /// + /// 授权访问菜单 + /// + public List MenusList { get; set; } + + /// + /// 授权访问菜单 + /// + public List MenusRouter { get; set; } + + /// + /// 授权使用功能 + /// + public List Modules { get; set; } + + /// + /// 用户设置的软件主题 + /// + public string UserTheme { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminUser/AdminUserInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminUser/AdminUserInputDto.cs new file mode 100644 index 0000000..b6a46a8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminUser/AdminUserInputDto.cs @@ -0,0 +1,80 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(AdminUser))] + [Serializable] + public class AdminUserInputDto : IInputDto + { + /// + /// 主键 + /// + public long Id { get; set; } + + /// + /// 账号 + /// + public string Account { get; set; } + + /// + /// 用户名 + /// + public string UserName { get; set; } + + /// + /// 头像 + /// + public string HeadIcon { get; set; } + + /// + /// 性别 + /// + public int Gender { get; set; } + + /// + /// 手机号 + /// + public string MobilePhone { get; set; } + + /// + /// 组织主键 + /// + public long ManagerId { get; set; } + + /// + /// 组织主键 + /// + public long OrganizeId { get; set; } + + /// + /// 部门主键 + /// + public long DepartmentId { get; set; } + + /// + /// 角色主键 + /// + public long RoleId { get; set; } + + /// + /// 岗位主键 + /// + public long DutyId { get; set; } + + /// + ///是否管理员 + /// + public bool IsAdministrator { get; set; } + + /// + /// 状态 + /// + public int Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminUser/AdminUserOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminUser/AdminUserOutputDto.cs new file mode 100644 index 0000000..bee1d4c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/AdminUser/AdminUserOutputDto.cs @@ -0,0 +1,146 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class AdminUserOutputDto + { + /// + /// 用户主键 + /// + public virtual long Id { get; set; } + + /// + /// 账户 + /// + public virtual string Account { get; set; } + + /// + /// 姓名 + /// + public virtual string UserName { get; set; } + + /// + /// 头像 + /// + public virtual string HeadIcon { get; set; } + + /// + /// 性别 + /// + public virtual long Gender { get; set; } + + /// + /// 手机 + /// + public virtual string MobilePhone { get; set; } + + /// + /// 密码 + /// + public virtual string UserPassword { get; set; } + + /// + /// 主管主键 + /// + public virtual long ManagerId { get; set; } + + /// + /// 组织主键 + /// + public virtual long OrganizeId { get; set; } + + /// + /// 组织名称 + /// + public virtual string OrganizeName { get; set; } + + /// + /// 部门主键 + /// + public virtual long DepartmentId { get; set; } + + /// + /// 部门名称 + /// + public virtual string DepartmentName { get; set; } + + /// + /// 角色主键 + /// + public virtual string RoleId { get; set; } + + /// + /// 角色名称 + /// + public virtual string RoleName { get; set; } + + /// + /// 岗位主键 + /// + public virtual long DutyId { get; set; } + + /// + /// 岗位名称 + /// + public virtual string DutyName { get; set; } + + /// + /// 是否管理员 + /// + public virtual bool? IsAdministrator { get; set; } + + /// + /// 排序码 + /// + public virtual long? SortCode { get; set; } + + /// + /// 描述 + /// + public virtual string Description { get; set; } + + /// + /// 删除标志 + /// + public virtual bool? IsDeleted { get; set; } + + /// + /// 有效标志 + /// + public virtual bool IsEnabled { get; set; } + + /// + /// 创建日期 + /// + public virtual DateTime? CreatedTime { get; set; } + + /// + /// 创建用户主键 + /// + public virtual long CreatedUserId { get; set; } + + /// + /// 最后修改时间 + /// + public virtual DateTime? ModifiedTime { get; set; } + + /// + /// 最后修改用户 + /// + public virtual long ModifiedUserId { get; set; } + + /// + /// 删除时间 + /// + public virtual DateTime? DeleteTime { get; set; } + + /// + /// 删除用户 + /// + public virtual string DeleteUserId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Api/ApiInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Api/ApiInputDto.cs new file mode 100644 index 0000000..6fea990 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Api/ApiInputDto.cs @@ -0,0 +1,16 @@ +using Znyc.Admin.Commons.Dtos; + +namespace Znyc.Admin.Security.Dtos +{ + public class ApiInputDto : IInputDto + { + public long Id { get; set; } + public string ApiUrl { get; set; } + + + public string AuthKey { get; set; } + + + public string AuthValue { get; set; } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Api/ApiOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Api/ApiOutputDto.cs new file mode 100644 index 0000000..e5b7bba --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Api/ApiOutputDto.cs @@ -0,0 +1,19 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Znyc.Admin.Commons.Dtos; + +namespace Znyc.Admin.Security.Dtos +{ + [Serializable] + public class ApiOutputDto : IOutputDto + { + [MaxLength(50)] + public string ApiUrl { get; set; } + + [MaxLength(15)] + public string AuthKey { get; set; } + + [MaxLength(155)] + public string AuthValue { get; set; } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/App/AppInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/App/AppInputDto.cs new file mode 100644 index 0000000..1170ebc --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/App/AppInputDto.cs @@ -0,0 +1,60 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(APP))] + [Serializable] + public class APPInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public string AppId { get; set; } + + /// + /// 设置或获取 + /// + public string AppSecret { get; set; } + + /// + /// 设置或获取 + /// + public string EncodingAESKey { get; set; } + + /// + /// 设置或获取 + /// + public string RequestUrl { get; set; } + + /// + /// 设置或获取 + /// + public string Token { get; set; } + + /// + /// 设置或获取 + /// + public bool IsOpenAEKey { get; set; } + + /// + /// 设置或获取 + /// + public bool IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/App/AppOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/App/AppOutputDto.cs new file mode 100644 index 0000000..90a42b1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/App/AppOutputDto.cs @@ -0,0 +1,121 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class AppOutputDto : IOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string AppId { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string AppSecret { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(256)] + public string EncodingAESKey { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(256)] + public string RequestUrl { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(256)] + public string Token { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsOpenAEKey { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long CompanyId { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long DeptId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string DeleteUserId { get; set; } + + /// + /// + /// + public virtual AdminUser UserInfo { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaInputDto.cs new file mode 100644 index 0000000..af4ff4e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaInputDto.cs @@ -0,0 +1,70 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Area))] + [Serializable] + public class AreaInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public long ParentId { get; set; } + + /// + /// 设置或获取 + /// + public long? Layers { get; set; } + + /// + /// 设置或获取 + /// + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + public string SimpleSpelling { get; set; } + + /// + /// 设置或获取 + /// + public string FullIdPath { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsLast { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaOutputDto.cs new file mode 100644 index 0000000..13f480b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaOutputDto.cs @@ -0,0 +1,112 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class AreaOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long ParentId { get; set; } + + /// + /// 设置或获取 + /// + public long? Layers { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(400)] + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(200)] + public string SimpleSpelling { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(600)] + public string FullIdPath { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsLast { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string DeleteUserId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaPickerOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaPickerOutputDto.cs new file mode 100644 index 0000000..e4e5227 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaPickerOutputDto.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// uniapp 地区选择 + /// + [Serializable] + public class AreaPickerOutputDto + { + /// + /// 值 + /// + public long value { get; set; } + + /// + /// 显示内容 + /// + public string label { get; set; } + + /// + /// + /// + public List children { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaSelect2OutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaSelect2OutDto.cs new file mode 100644 index 0000000..0131333 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Area/AreaSelect2OutDto.cs @@ -0,0 +1,21 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// select2 地区选择 + /// + [Serializable] + public class AreaSelect2OutDto + { + /// + /// 值 + /// + public long Id { get; set; } + + /// + /// 显示内容 + /// + public string text { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Company/CompanyInPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Company/CompanyInPutDto.cs new file mode 100644 index 0000000..e0d8c8b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Company/CompanyInPutDto.cs @@ -0,0 +1,42 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Company))] + [Serializable] + public class CompanyInPutDto : IInputDto + { + public long Id { get; set; } + + ///// + ///// OpenId + ///// + //public string OpenId { get; set; } + + /// + /// 用户昵称 + /// + public string UserName { get; set; } + + /// + /// 用户头像 + /// + public string AvatarUrl { get; set; } + + /// + /// 手机号 + /// + public string Phone { get; set; } + + ///// + ///// 状态 + ///// + //public long Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Company/CompanyOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Company/CompanyOutputDto.cs new file mode 100644 index 0000000..4280d74 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Company/CompanyOutputDto.cs @@ -0,0 +1,88 @@ +using System; +using Znyc.Admin.Commons.Dtos; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class CompanyOutputDto : IOutputDto + + { + /// + ///id + /// + public long Id { get; set; } + + /// + /// 公司名称 + /// + public string CompanyName { get; set; } + + /// + /// 公司Logo + /// + public string CompanyLogo { get; set; } + + /// + /// 联系人 + /// + + public string ContactPerson { get; set; } + + /// + /// 联系人电话 + /// + + public string ContactPhone { get; set; } + + /// + /// 精度 + /// + public decimal Longitude { get; set; } + + /// + /// 纬度 + /// + public decimal Latitude { get; set; } + + /// + /// 地址 + /// + + public string Address { get; set; } + + /// + /// 状态(字典 0正常 1停用 2删除) + /// + public long Status { get; set; } + + /// + /// 审核时间 + /// + public DateTime AuditTime { get; set; } + + /// + /// 车辆总数 + /// + public long VehicleCount { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedTime { get; set; } + + + /// + /// 创建时间 + /// + public long CreatedUserId { get; set; } + + + /// + /// 更新时间 + /// + public DateTime ModifiedTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Currency/CurrencyOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Currency/CurrencyOutputDto.cs new file mode 100644 index 0000000..2d92577 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Currency/CurrencyOutputDto.cs @@ -0,0 +1,22 @@ +namespace Znyc.Admin.Security.Dtos +{ + public class CurrencyOutputDto + { + public long Id { get; set; } + + /// + /// 用户Id + /// + public long UserId { get; set; } + + /// + /// 总云币 + /// + public decimal TotalCredits { get; set; } + + /// + /// 可用云币 + /// + public decimal AvailableCredits { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/DashboardOutModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/DashboardOutModel.cs new file mode 100644 index 0000000..4b84d50 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/DashboardOutModel.cs @@ -0,0 +1,146 @@ +using System; + +namespace Znyc.Admin.WebApi.Areas.Security.Entitys +{ + /// + /// 控制台首页显示内容 + /// + [Serializable] + public class DashboardOutModel + { + /// + /// 许可使用公司名称 + /// + public string CertificatedCompany { get; set; } + + /// + /// 系统访问Url + /// + public string WebUrl { get; set; } + + /// + /// 服务器名称 + /// + public string MachineName { get; set; } + + /// + /// 操作系统 + /// + public string OSName { get; set; } + + /// + /// 正在其上运行应用的操作系统。 + /// + public string OSDescription { get; set; } + + /// + /// 获取正在其上运行应用的 .NET 安装的名称。 + /// + public string FrameworkDescription { get; set; } + + /// + /// 获取正在其上运行当前应用的平台体系结构。 + /// + public string OSArchitecture { get; set; } + + /// + /// 获取当前正在运行的应用的进程架构。 + /// + public string ProcessArchitecture { get; set; } + + /// + /// 获取当前计算机上的处理器数。 + /// + public long ProcessorCount { get; set; } + + /// + /// 获取操作系统的内存页的字节数。 + /// + public long SystemPageSize { get; set; } + + /// + /// 获取映射到进程上下文的物理内存量。 + /// + public long WorkingSet { get; set; } + + /// + /// 获取系统启动后经过的毫秒数。 + /// + public long TickCount { get; set; } + + /// + /// 运行时长 + /// + public string RunTimeLength { get; set; } + + /// + /// 部署目录 + /// + public string Directory { get; set; } + + /// + /// 系统版本 + /// + public string SystemVersion { get; set; } + + /// + /// 系统版本 + /// + public string Version { get; set; } + + /// + /// 软件厂商 + /// + public string Manufacturer { get; set; } + + /// + /// 网址 + /// + public string WebSite { get; set; } + + /// + /// 更新地址 + /// + public string UpdateUrl { get; set; } + + /// + /// 服务器IP地址 + /// + public string IPAdress { get; set; } + + /// + /// 服务器端口 + /// + public string Port { get; set; } + + /// + /// 系统名称 + /// + public string Title { get; set; } + + /// + /// 总用户数 + /// + public long TotalUser { get; set; } + + /// + /// 总模块数 + /// + public long TotalModule { get; set; } + + /// + /// 总上传文件数 + /// + public long TotalUploadFile { get; set; } + + /// + /// 定时任务 + /// + public long TotalTask { get; set; } + + /// + /// 总岗位角色数 + /// + public long TotalRole { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Dictionary/DictionaryInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Dictionary/DictionaryInputDto.cs new file mode 100644 index 0000000..98406d0 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Dictionary/DictionaryInputDto.cs @@ -0,0 +1,55 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Dictionary))] + [Serializable] + public class DictionaryInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 字典父级 + /// + public long ParentId { get; set; } + + /// + /// 字典编码 + /// + public string Code { get; set; } + + /// + /// 字典值 + /// + public string Value { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 字典名称 + /// + public string Name { get; set; } + + /// + /// 启用 + /// + public bool IsEnabled { get; set; } = true; + + /// + /// 排序 + /// + public int Sort { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Dictionary/DictionaryOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Dictionary/DictionaryOutputDto.cs new file mode 100644 index 0000000..378409c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Dictionary/DictionaryOutputDto.cs @@ -0,0 +1,53 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class DictionaryOutputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 字典父级 + /// + public long ParentId { get; set; } + + /// + /// 字典编码 + /// + public string Code { get; set; } + + /// + /// 字典值 + /// + public string Value { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 字典名称 + /// + public string Name { get; set; } + + /// + /// 启用 + /// + public bool IsEnabled { get; set; } = true; + + /// + /// 排序 + /// + public long Sort { get; set; } + + public DictionaryOutputDto Children { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Function/FunctionTreeTableOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Function/FunctionTreeTableOutputDto.cs new file mode 100644 index 0000000..bad0046 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Function/FunctionTreeTableOutputDto.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// vue树形表 + /// + [Serializable] + public class FunctionTreeTableOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string SystemTypeId { get; set; } + + /// + /// + /// + public string SystemTypeName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long ParentId { get; set; } + + /// + /// 设置或获取 + /// + public long? Layers { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Icon { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string UrlAddress { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Target { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsMenu { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsExpand { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsPublic { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowEdit { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowDelete { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string DeleteUserId { get; set; } + + /// + /// 子菜单 + /// + public List Children { get; set; } + + /// + /// 系统标记 + /// + public bool SystemTag { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Function/ModuleFunctionOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Function/ModuleFunctionOutputDto.cs new file mode 100644 index 0000000..c585a06 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Function/ModuleFunctionOutputDto.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 模块功能 + /// + [Serializable] + public class ModuleFunctionOutputDto + { + /// + /// 功能Id + /// + public long Id { get; set; } + + /// + /// 设置或获取 功能名称 + /// + public string FullName { get; set; } + + /// + /// 设置或获取 功能标识 0-子系统 1-标识菜单/模块,2标识按钮功能 + /// + public long FunctionTag { get; set; } + + /// + /// 设置或获取 是否禁止选择 + /// + public bool IsShow { get; set; } + + /// + /// 设置或获取 功能标识 M-标识菜单,F标识功能 + /// + public List listFunction { get; set; } + + /// + /// 子菜单 + /// + public List Children { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/LogExInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/LogExInputDto.cs new file mode 100644 index 0000000..bf34515 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/LogExInputDto.cs @@ -0,0 +1,70 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(LogEx))] + [Serializable] + public class LogExInputDto : IInputDto + { + /// + /// 主键Id + /// + public long Id { get; set; } + + /// + /// 操作人 + /// + 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; } + + /// + /// 异常信息 + /// + public string ExceptionMsg { get; set; } + + /// + /// 异常源 + /// + public string ExceptionSource { get; set; } + + /// + /// 堆栈信息 + /// + public string StackTrace { get; set; } + + /// + /// 参数对象 + /// + public string MyPrParamsObjoperty { get; set; } + + /// + /// 异常时间 + /// + public DateTime ExceptionTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/LogExOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/LogExOutputDto.cs new file mode 100644 index 0000000..e641ab4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/LogExOutputDto.cs @@ -0,0 +1,66 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class LogExOutputDto + { + /// + /// 主键Id + /// + public long Id { get; set; } + + /// + /// 操作人 + /// + 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; } + + /// + /// 异常信息 + /// + public string ExceptionMsg { get; set; } + + /// + /// 异常源 + /// + public string ExceptionSource { get; set; } + + /// + /// 堆栈信息 + /// + public string StackTrace { get; set; } + + /// + /// 参数对象 + /// + public string MyPrParamsObjoperty { get; set; } + + /// + /// 异常时间 + /// + public DateTime ExceptionTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/SearchLogExModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/SearchLogExModel.cs new file mode 100644 index 0000000..6d79d8f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogEx/SearchLogExModel.cs @@ -0,0 +1,26 @@ +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 日志搜索条件 + /// + public class SearchDbLogsModel : SearchInputDto + { + /// + /// 添加开始时间 + /// + public string CreatedTime1 { get; set; } + + /// + /// 添加结束时间 + /// + public string CreatedTime2 { get; set; } + + /// + /// 来源平台 + /// + public long PlatformType { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/LogOpInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/LogOpInputDto.cs new file mode 100644 index 0000000..f5e0c57 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/LogOpInputDto.cs @@ -0,0 +1,105 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(LogOp))] + [Serializable] + public class LogOpInputDto : IInputDto + { + /// + /// 主键 + /// + public long Id { get; set; } + + /// + /// 操作用户 + /// + public string Name { get; set; } + + /// + /// 是否执行成功 + /// + public string Success { get; set; } + + /// + /// 具体消息 + /// + public string Message { get; set; } + + /// + /// IP + /// + public string IP { get; set; } + + /// + /// 地址 + /// + public string Location { get; set; } + + /// + /// 浏览器 + /// + public string Browser { get; set; } + + /// + /// 堆栈信息 + /// + public string StackTrace { get; set; } + + /// + /// 操作系统 + /// + public string OS { get; set; } + + /// + /// 请求地址 + /// + public string Url { get; set; } + + /// + /// 类名称 + /// + public string ClassName { get; set; } + + /// + /// 方法名称 + /// + public string MethodName { get; set; } + + /// + /// 请求方式(GET POST PUT DELETE) + /// + public string ReqMethod { get; set; } + + /// + /// 请求参数 + /// + public string Param { get; set; } + + /// + /// 返回结果 + /// + public string Result { get; set; } + + /// + /// 耗时 + /// + public long ElapsedTime { get; set; } + + /// + /// 操作时间 + /// + public DateTime OpTime { get; set; } + + /// + /// 操作人 + /// + public string Account { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/LogOpOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/LogOpOutputDto.cs new file mode 100644 index 0000000..257e6d2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/LogOpOutputDto.cs @@ -0,0 +1,101 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class LogOpOutputDto + { + /// + /// 主键 + /// + public long Id { get; set; } + + /// + /// 操作用户 + /// + public string Name { get; set; } + + /// + /// 是否执行成功 + /// + public string Success { get; set; } + + /// + /// 具体消息 + /// + public string Message { get; set; } + + /// + /// IP + /// + public string IP { get; set; } + + /// + /// 地址 + /// + public string Location { get; set; } + + /// + /// 浏览器 + /// + public string Browser { get; set; } + + /// + /// 堆栈信息 + /// + public string StackTrace { get; set; } + + /// + /// 操作系统 + /// + public string OS { get; set; } + + /// + /// 请求地址 + /// + public string Url { get; set; } + + /// + /// 类名称 + /// + public string ClassName { get; set; } + + /// + /// 方法名称 + /// + public string MethodName { get; set; } + + /// + /// 请求方式(GET POST PUT DELETE) + /// + public string ReqMethod { get; set; } + + /// + /// 请求参数 + /// + public string Param { get; set; } + + /// + /// 返回结果 + /// + public string Result { get; set; } + + /// + /// 耗时 + /// + public long ElapsedTime { get; set; } + + /// + /// 操作时间 + /// + public DateTime OpTime { get; set; } + + /// + /// 操作人 + /// + public string Account { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/SearchLogOpModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/SearchLogOpModel.cs new file mode 100644 index 0000000..d421099 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogOp/SearchLogOpModel.cs @@ -0,0 +1,21 @@ +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 日志搜索条件 + /// + public class SearchLogOpModel : SearchInputDto + { + /// + /// 添加开始时间 + /// + public string CreatedTime1 { get; set; } + + /// + /// 添加结束时间 + /// + public string CreatedTime2 { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/LogVisInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/LogVisInputDto.cs new file mode 100644 index 0000000..351992f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/LogVisInputDto.cs @@ -0,0 +1,72 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(LogVis))] + [Serializable] + public class LogVisInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 是否执行成功 + /// + public string Success { get; set; } + + /// + /// 具体消息 + /// + public string Message { get; set; } + + /// + /// Ip + /// + public string Ip { get; set; } + + /// + /// 地址 + /// + public string Location { get; set; } + + /// + /// 浏览器 + /// + public string Browser { get; set; } + + /// + /// 访问类型 + /// + public string VisType { get; set; } + + /// + /// 操作系统 + /// + + public string Os { get; set; } + + /// + /// 操作账号 + /// + public string Account { get; set; } + + /// + /// 访问时间 + /// + + public DateTime VisTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/LogVisOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/LogVisOutputDto.cs new file mode 100644 index 0000000..b4c1d37 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/LogVisOutputDto.cs @@ -0,0 +1,68 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class LogVisOutputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 是否执行成功 + /// + public string Success { get; set; } + + /// + /// 具体消息 + /// + public string Message { get; set; } + + /// + /// Ip + /// + public string Ip { get; set; } + + /// + /// 地址 + /// + public string Location { get; set; } + + /// + /// 浏览器 + /// + public string Browser { get; set; } + + /// + /// 访问类型 + /// + public string VisType { get; set; } + + /// + /// 操作系统 + /// + + public string Os { get; set; } + + /// + /// 操作账号 + /// + public string Account { get; set; } + + /// + /// 访问时间 + /// + + public DateTime VisTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/SearchDbLogsModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/SearchDbLogsModel.cs new file mode 100644 index 0000000..67b15f1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/LogVis/SearchDbLogsModel.cs @@ -0,0 +1,21 @@ +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 日志搜索条件 + /// + public class SearchExceptionsLogsModel : SearchInputDto + { + /// + /// 添加开始时间 + /// + public string CreatedTime1 { get; set; } + + /// + /// 添加结束时间 + /// + public string CreatedTime2 { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuInputDto.cs new file mode 100644 index 0000000..cdc254b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuInputDto.cs @@ -0,0 +1,131 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Menu))] + [Serializable] + public class MenuInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public long SystemTypeId { get; set; } + + /// + /// 设置或获取 + /// + public long ParentId { get; set; } + + /// + /// 设置或获取 + /// + public long Layers { get; set; } + + /// + /// 设置或获取 + /// + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + public string Icon { get; set; } + + /// + /// 设置或获取路由 + /// + public virtual string UrlAddress { get; set; } + + /// + /// 设置或获取目标打开方式 + /// + public virtual string Target { get; set; } + + /// + /// 设置或获取菜单类型(C目录 M菜单 F按钮) + /// + public virtual string MenuType { get; set; } + + /// + /// 设置或获取组件路径 + /// + public virtual string Component { get; set; } + + /// + /// 设置当前选中菜单,用于新增、编辑、查看操作为单独的路由时指定选中菜单路由 + /// 同时设置为隐藏时才有效 + /// + public virtual string ActiveMenu { get; set; } + + /// + /// 设置或获取 + /// + public bool IsExpand { get; set; } + + /// + /// 设置或获取 是否显示 + /// + public bool IsShow { get; set; } + + /// + /// 设置或获取是否缓存 + /// + public bool IsCache { get; set; } + + /// + /// 设置或获取 是否外链 + /// + public bool IsFrame { get; set; } + + /// + /// 设置或获取 批量添加 + /// + public bool IsBatch { get; set; } + + /// + /// 设置或获取 + /// + public bool IsPublic { get; set; } + + /// + /// 设置或获取 + /// + public int SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + public string Description { get; set; } + + /// + /// 创建日期 + /// + public virtual DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + public string SystemTypeName { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuOutputDto.cs new file mode 100644 index 0000000..6d491c3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuOutputDto.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class MenuOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string SystemTypeId { get; set; } + + public string SystemTypeName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long ParentId { get; set; } + + /// + /// 设置或获取 + /// + public long? Layers { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Icon { get; set; } + + /// + /// 设置或获取路由 + /// + public virtual string UrlAddress { get; set; } + + /// + /// 设置或获取目标打开方式 + /// + public virtual string Target { get; set; } + + /// + /// 设置或获取菜单类型(C目录 M菜单 F按钮) + /// + public virtual string MenuType { get; set; } + + /// + /// 设置或获取组件路径 + /// + public virtual string Component { get; set; } + + /// + /// 设置当前选中菜单,用于新增、编辑、查看操作为单独的路由时指定选中菜单路由 + /// 同时设置为隐藏时才有效 + /// + public virtual string ActiveMenu { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsExpand { get; set; } + + /// + /// 设置或获取 是否显示 + /// + public bool IsShow { get; set; } + + /// + /// 设置或获取 是否外链 + /// + public bool IsFrame { get; set; } + + /// + /// 设置或获取是否缓存 + /// + public bool IsCache { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsPublic { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowEdit { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowDelete { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public bool IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string DeleteUserId { get; set; } + + /// + /// 子菜单集合 + /// + public List SubMenu { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuTreeTableOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuTreeTableOutputDto.cs new file mode 100644 index 0000000..191eb2e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Menu/MenuTreeTableOutputDto.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// vue树形表 + /// + public class MenuTreeTableOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string SystemTypeId { get; set; } + + /// + /// + /// + public string SystemTypeName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long ParentId { get; set; } + + /// + /// 设置或获取 + /// + public long? Layers { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Icon { get; set; } + + /// + /// 设置或获取路由 + /// + public virtual string UrlAddress { get; set; } + + /// + /// 设置或获取目标打开方式 + /// + public virtual string Target { get; set; } + + /// + /// 设置或获取菜单类型(C目录 M菜单 F按钮) + /// + public virtual string MenuType { get; set; } + + /// + /// 设置或获取组件路径 + /// + public virtual string Component { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsExpand { get; set; } + + /// + /// 设置或获取 是否显示 + /// + public bool? IsShow { get; set; } + + /// + /// 设置或获取 是否外链 + /// + public bool? IsFrame { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsPublic { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowEdit { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowDelete { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string DeleteUserId { get; set; } + + /// + /// 子菜单 + /// + public List Children { get; set; } + + /// + /// 系统标记 + /// + public bool SystemTag { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageInputDto.cs new file mode 100644 index 0000000..451f91a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageInputDto.cs @@ -0,0 +1,52 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Message))] + [Serializable] + public class MessageInputDto : IInputDto + { + public long Id { get; set; } + + /// + /// 消息内容 + /// + public string Content { get; set; } + + /// + /// 产品Id + /// + public long ProductId { get; set; } + + /// + /// 标题 + /// + public string Title { get; set; } + + /// + /// 用户Id + /// + public long UserId { get; set; } + + /// + /// 消息标题 + /// + public string MessageTitle { get; set; } + + /// + /// 产品类型 + /// + public long ProductType { get; set; } + + /// + /// 创建人 + /// + public long CreatedUserId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageLogsInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageLogsInputDto.cs new file mode 100644 index 0000000..b9f2774 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageLogsInputDto.cs @@ -0,0 +1,32 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(MessageRecord))] + [Serializable] + public class MessageLogsInputDto : IInputDto + { + public long Id { get; set; } + + /// + /// 接收者Id + /// + public long ReceiverId { get; set; } + + /// + /// 消息Id + /// + public long MessageId { get; set; } + + /// + /// 状态 + /// + public long Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageLogsOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageLogsOutputDto.cs new file mode 100644 index 0000000..48109cd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageLogsOutputDto.cs @@ -0,0 +1,26 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class MessageLogsOutputDto + { + /// + /// 接收者Id + /// + public long ReceiverId { get; set; } + + /// + /// 消息Id + /// + public long MessageId { get; set; } + + /// + /// 状态 + /// + public long Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageOutputDto.cs new file mode 100644 index 0000000..6a9611b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Message/MessageOutputDto.cs @@ -0,0 +1,46 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class MessageOutputDto + { + /// + /// 发送者Id + /// + public long SendId { get; set; } + + /// + /// 发送类型 + /// + public long Type { get; set; } + + /// + /// 组Id(不涉及组消息可不用) + /// + public long GroupId { get; set; } + + /// + /// 消息内容 + /// + public string Content { get; set; } + + /// + /// 发送时间 + /// + public DateTime SendTime { get; set; } + + /// + /// 产品Id + /// + public long ProductId { get; set; } + + /// + /// 标题 + /// + public string Title { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Organize/OrganizeInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Organize/OrganizeInputDto.cs new file mode 100644 index 0000000..70a0969 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Organize/OrganizeInputDto.cs @@ -0,0 +1,75 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Organize))] + [Serializable] + public class OrganizeInputDto : IInputDto + { + /// + /// 主键 + /// + public long Id { get; set; } + + /// + /// 父级id + /// + public long ParentId { get; set; } + + /// + /// 所属层级 + /// + public long Layers { get; set; } + + /// + /// 功能代码 + /// + public string EnCode { get; set; } + + /// + /// 名称 + /// + public string FullName { get; set; } + + /// + /// 类别Id + /// + public string CategoryId { get; set; } + + /// + /// 上级Id + /// + public string ManagerId { get; set; } + + /// + /// 区域Id + /// + public long AreaId { get; set; } + + /// + /// 是否可以编辑 + /// + public bool AllowEdit { get; set; } + + /// + /// 是否可以删除 + /// + public bool AllowDelete { get; set; } + + /// + /// 排序 + /// + public int SortCode { get; set; } + + /// + /// 备注 + /// + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Organize/OrganizeOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Organize/OrganizeOutputDto.cs new file mode 100644 index 0000000..f96c2b4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Organize/OrganizeOutputDto.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class OrganizeOutputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 父级 + /// + public long ParentId { get; set; } + + /// + /// 层次 + /// + public int Layers { get; set; } + + /// + /// 编码 + /// + public string EnCode { get; set; } + + /// + /// 名称 + /// + public string FullName { get; set; } + + /// + /// 负责人 + /// + public string ManagerName { get; set; } + + /// + /// 类型 + /// + public string CategoryName { get; set; } + + /// + /// 排序码 + /// + public long SortCode { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 是否有效 + /// + public bool IsEnabled { get; set; } + + /// + /// 子集 + /// + public List Children { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedTime { get; set; } + + /// + /// 修改时间 + /// + public DateTime ModifiedTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeDataInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeDataInputDto.cs new file mode 100644 index 0000000..324acee --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeDataInputDto.cs @@ -0,0 +1,31 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 角色授权输入模型 + /// + [Serializable] + public class RoleAuthorizeDataInputDto + { + /// + /// 设置角色功能 + /// + public long[] RoleFunctios { get; set; } + + /// + /// 设置角色可访问系统 + /// + public long[] RoleSystem { get; set; } + + /// + /// 设置角色可访问数据 + /// + public string[] RoleData { get; set; } + + /// + /// 设置角色Id + /// + public long RoleId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeInputDto.cs new file mode 100644 index 0000000..ea2db54 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeInputDto.cs @@ -0,0 +1,45 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(RoleAuthorize))] + [Serializable] + public class RoleAuthorizeInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public long? ItemType { get; set; } + + /// + /// 设置或获取 + /// + public string ItemId { get; set; } + + /// + /// 设置或获取 + /// + public long? ObjectType { get; set; } + + /// + /// 设置或获取 + /// + public string ObjectId { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeOutputDto.cs new file mode 100644 index 0000000..5ca6684 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleAuthorizeOutputDto.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class RoleAuthorizeOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public long? ItemType { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ItemId { get; set; } + + /// + /// 设置或获取 + /// + public long? ObjectType { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ObjectId { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + public List Children { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleDataInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleDataInputDto.cs new file mode 100644 index 0000000..9b712e8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleDataInputDto.cs @@ -0,0 +1,40 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(RoleData))] + [Serializable] + public class RoleDataInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public string RoleId { get; set; } + + /// + /// 类型,company-公司,dept-部门,person-个人 + /// + public virtual string DType { get; set; } + + /// + /// 数据数据,部门ID或个人ID + /// + public virtual string AuthorizeData { get; set; } + + /// + /// 设置或获取 + /// + public string Note { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleDataOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleDataOutputDto.cs new file mode 100644 index 0000000..230310d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleDataOutputDto.cs @@ -0,0 +1,40 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class RoleDataOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string RoleId { get; set; } + + /// + /// 类型,company-公司,dept-部门,person-个人 + /// + public virtual string DType { get; set; } + + /// + /// 数据数据,部门ID或个人ID + /// + public virtual string AuthorizeData { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(1073741823)] + public string Note { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleInputDto.cs new file mode 100644 index 0000000..3b7196e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleInputDto.cs @@ -0,0 +1,70 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Role))] + [Serializable] + public class RoleInputDto : IInputDto + { + /// + /// 主键 + /// + public long Id { get; set; } + + /// + /// 组织id + /// + public long OrganizeId { get; set; } + + /// + /// 类别 + /// + public long Category { get; set; } + + /// + /// 编码 + /// + public string EnCode { get; set; } + + /// + /// 名称 + /// + public string FullName { get; set; } + + /// + /// 类型 + /// + public string Type { get; set; } + + /// + ///是否可以编辑 + /// + public bool AllowEdit { get; set; } + + /// + /// 是否可以删除 + /// + public bool AllowDelete { get; set; } + + /// + /// 排序 + /// + public long SortCode { get; set; } + + /// + /// 是否可用 + /// + public bool IsEnabled { get; set; } + + /// + /// 详情描述 + /// + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleOutputDto.cs new file mode 100644 index 0000000..0e7e08b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Role/RoleOutputDto.cs @@ -0,0 +1,116 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class RoleOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long OrganizeId { get; set; } + + /// + /// 组织名称 + /// + public virtual string OrganizeName { get; set; } + + /// + /// 设置或获取 + /// + public long? Category { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Type { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowEdit { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowDelete { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string DeleteUserId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SecurityProfile.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SecurityProfile.cs new file mode 100644 index 0000000..aa8526d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SecurityProfile.cs @@ -0,0 +1,97 @@ +using AutoMapper; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// + /// + public class SecurityProfile : Profile + { + /// + /// / + /// + public SecurityProfile() + { + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(s => s.label, s => s.MapFrom(o => o.FullName)) + .ForMember(s => s.value, s => s.MapFrom(o => o.Id)); + CreateMap() + .ForMember(e => e.text, s => s.MapFrom(o => o.FullName)) + .ForMember(e => e.Id, s => s.MapFrom(o => o.Id)); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(s => s.Id, s => s.MapFrom(o => o.Id)) + .ForMember(s => s.FullName, s => s.MapFrom(o => o.FullName)); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap().ReverseMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + //CreateMap(); + //CreateMap(); + //CreateMap(); + //CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalInputDto.cs new file mode 100644 index 0000000..e50f699 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalInputDto.cs @@ -0,0 +1,61 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 控制台首页显示统计数据 + /// + [Serializable] + public class StatisticalInputDto + { + /// + /// 时间 + /// + public string Time { get; set; } + + /// + /// 今日新增用户数 + /// + public int UserAddTotal { get; set; } + + /// + /// 用户总数 + /// + public int UserSumTotal { get; set; } + + /// + /// 今日新增公司数 + /// + public int CompanyAddTotal { get; set; } + + /// + /// 公司总数 + /// + public int CompanySumTotal { get; set; } + + /// + /// 今日新增车辆数 + /// + public int VehicleAddTotal { get; set; } + + /// + /// 车辆总数 + /// + public int VehicleSumTotal { get; set; } + + /// + /// 今日车辆到期数 + /// + public int ExpireAddTotal { get; set; } + + /// + /// 车辆到期总数 + /// + public int ExpireSumTotal { get; set; } + + /// + /// 今日用户增长百分比 + /// + public decimal UserAddTotalPercent { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalListOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalListOutputDto.cs new file mode 100644 index 0000000..14fa902 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalListOutputDto.cs @@ -0,0 +1,61 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 控制台首页显示统计数据 + /// + [Serializable] + public class StatisticalListOutputDto + { + /// + /// 时间 + /// + public string Time { get; set; } + + /// + /// 今日新增用户数 + /// + public int UserAddTotal { get; set; } + + /// + /// 用户总数 + /// + public int UserSumTotal { get; set; } + + /// + /// 今日新增公司数 + /// + public int CompanyAddTotal { get; set; } + + /// + /// 公司总数 + /// + public int CompanySumTotal { get; set; } + + /// + /// 今日新增车辆数 + /// + public int VehicleAddTotal { get; set; } + + /// + /// 车辆总数 + /// + public int VehicleSumTotal { get; set; } + + /// + /// 今日车辆到期数 + /// + public int ExpireAddTotal { get; set; } + + /// + /// 车辆到期总数 + /// + public int ExpireSumTotal { get; set; } + + /// + /// 今日用户增长百分比 + /// + public decimal UserAddTotalPercent { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalOutputDto.cs new file mode 100644 index 0000000..37f3b4f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Statistical/StatisticalOutputDto.cs @@ -0,0 +1,61 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 控制台首页显示统计数据 + /// + [Serializable] + public class StatisticalOutputDto + { + /// + /// 时间 + /// + public string Time { get; set; } + + /// + /// 今日新增用户数 + /// + public int UserAddTotal { get; set; } + + /// + /// 用户总数 + /// + public int UserSumTotal { get; set; } + + /// + /// 今日新增公司数 + /// + public int CompanyAddTotal { get; set; } + + /// + /// 公司总数 + /// + public int CompanySumTotal { get; set; } + + /// + /// 今日新增车辆数 + /// + public int VehicleAddTotal { get; set; } + + /// + /// 车辆总数 + /// + public int VehicleSumTotal { get; set; } + + /// + /// 今日车辆到期数 + /// + public int ExpireAddTotal { get; set; } + + /// + /// 车辆到期总数 + /// + public int ExpireSumTotal { get; set; } + + /// + /// 今日用户增长百分比 + /// + public decimal UserAddTotalPercent { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SysSetting/SysSettingOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SysSetting/SysSettingOutputDto.cs new file mode 100644 index 0000000..7f5585b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SysSetting/SysSettingOutputDto.cs @@ -0,0 +1,321 @@ +using System; +using System.Xml.Serialization; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出Dto:SysSetting + /// + [Serializable] + public class SysSettingOutputDto + { + #region 系统基本信息 + + /// + /// 系统名称 + /// + [XmlElement("SoftName")] + public string SoftName { get; set; } + + /// + /// 系统简介 + /// + [XmlElement("SoftSummary")] + public string SoftSummary { get; set; } + + /// + /// 访问域名 + /// + [XmlElement("WebUrl")] + public string WebUrl { get; set; } + + /// + /// Logo + /// + [XmlElement("SysLogo")] + public string SysLogo { get; set; } + + /// + /// 公司名称 + /// + [XmlElement("CompanyName")] + public string CompanyName { get; set; } + + /// + /// 地址 + /// + [XmlElement("Address")] + public string Address { get; set; } + + /// + /// 电话 + /// + [XmlElement("Telphone")] + public string Telphone { get; set; } + + /// + /// Email + /// + [XmlElement("Email")] + public string Email { get; set; } + + /// + /// ICP备案号 + /// + [XmlElement("ICPCode")] + public string ICPCode { get; set; } + + /// + /// 公安备案号 + /// + [XmlElement("PublicSecurityCode")] + public string PublicSecurityCode { get; set; } + + /// + /// 分享标题 + /// + [XmlElement("ShareTitle")] + public string ShareTitle { get; set; } + + /// + /// 微信公众号分享图片 + /// + [XmlElement("ShareWeChatImage")] + public string ShareWeChatImage { get; set; } + + /// + /// 微信小程序分享图片 + /// + [XmlElement("ShareWxAppletImage")] + public string ShareWxAppletImage { get; set; } + + /// + /// 微信推广二维码背景图片 + /// + [XmlElement("ShareBackgroundImage")] + public string ShareBackgroundImage { get; set; } + + #endregion 系统基本信息 + + #region 功能权限设置 + + /// + /// URL重写开关 + /// + [XmlElement("Staticstatus")] + public string Staticstatus { get; set; } + + /// + /// 静态URL后缀 + /// + [XmlElement("Staticextension")] + public string Staticextension { get; set; } + + /// + /// 开启会员功能 + /// + [XmlElement("Memberstatus")] + public string Memberstatus { get; set; } + + /// + /// 是否开启网站 + /// + [XmlElement("Webstatus")] + public string Webstatus { get; set; } + + /// + /// 网站关闭原因 + /// + [XmlElement("Webclosereason")] + public string Webclosereason { get; set; } + + /// + /// 网站统计代码 + /// + [XmlElement("Webcountcode")] + public string Webcountcode { get; set; } + + #endregion 功能权限设置 + + #region 文件服务器 + + /// + /// 文件服务器 + /// + [XmlElement("Fileserver")] + public string Fileserver { get; set; } + + /// + /// 本地文件存储物理物理路径 + /// + [XmlElement("LocalPath")] + public string LocalPath { get; set; } + + /// + /// 阿里云KeyId + /// + [XmlElement("Osssecretid")] + public string Osssecretid { get; set; } + + /// + /// 阿里云SecretKey + /// + [XmlElement("Osssecretkey")] + public string Osssecretkey { get; set; } + + /// + /// 阿里云Bucket + /// + [XmlElement("Ossbucket")] + public string Ossbucket { get; set; } + + /// + /// 阿里云EndPoint + /// + [XmlElement("Ossendpoint")] + public string Ossendpoint { get; set; } + + /// + /// 阿里云绑定域名 + /// + [XmlElement("Ossdomain")] + public string Ossdomain { get; set; } + + #endregion 文件服务器 + + #region 文件上传设置 + + /// + /// 文件上传目录 + /// + [XmlElement("Filepath")] + public string Filepath { get; set; } + + /// + /// 文件保存方式 + /// + [XmlElement("Filesave")] + public string Filesave { get; set; } + + /// + /// 编辑器图片 + /// + [XmlElement("Fileremote")] + public string Fileremote { get; set; } + + /// + /// 文件上传类型 + /// + [XmlElement("Fileextension")] + public string Fileextension { get; set; } + + /// + /// 视频上传类型 + /// + [XmlElement("Videoextension")] + public string Videoextension { get; set; } + + /// + /// 附件上传大小 + /// + [XmlElement("Attachsize")] + public string Attachsize { get; set; } + + /// + /// 视频上传大小 + /// + [XmlElement("Videosize")] + public string Videosize { get; set; } + + /// + /// 图片上传大小 + /// + [XmlElement("Imgsize")] + public string Imgsize { get; set; } + + /// + /// 图片最大尺寸 高度 + /// + [XmlElement("Imgmaxheight")] + public string Imgmaxheight { get; set; } + + /// + /// 图片最大尺寸 宽度 + /// + [XmlElement("Imgmaxwidth")] + public string Imgmaxwidth { get; set; } + + /// + /// 缩略图生成尺寸 高度 + /// + [XmlElement("Thumbnailheight")] + public string Thumbnailheight { get; set; } + + /// + /// 缩略图生成尺寸 宽度 + /// + [XmlElement("Thumbnailwidth")] + public string Thumbnailwidth { get; set; } + + /// + /// 缩略图生成方式 + /// + [XmlElement("Thumbnailmode")] + public string Thumbnailmode { get; set; } + + /// + /// 图片水印类型 + /// + [XmlElement("Watermarktype")] + public string Watermarktype { get; set; } + + /// + /// 图片水印位置 + /// + [XmlElement("Watermarkposition")] + public string Watermarkposition { get; set; } + + /// + /// 图片生成质量 + /// + [XmlElement("Watermarkimgquality")] + public string Watermarkimgquality { get; set; } + + /// + /// 图片水印文件 + /// + [XmlElement("Watermarkpic")] + public string Watermarkpic { get; set; } + + /// + /// 水印透明度 + /// + [XmlElement("Watermarktransparency")] + public string Watermarktransparency { get; set; } + + /// + /// 水印文字 + /// + [XmlElement("Watermarktext")] + public string Watermarktext { get; set; } + + /// + /// 文字字体格式 + /// + [XmlElement("Watermarkfont")] + public string Watermarkfont { get; set; } + + /// + /// 文字字体大小 + /// + [XmlElement("Watermarkfontsize")] + public string Watermarkfontsize { get; set; } + + #endregion 文件上传设置 + + /// + /// 版权信息 + /// + public string CopyRight { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SystemType/SystemTypeInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SystemType/SystemTypeInputDto.cs new file mode 100644 index 0000000..eccef83 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SystemType/SystemTypeInputDto.cs @@ -0,0 +1,60 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(SystemType))] + [Serializable] + public class SystemTypeInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + public string Url { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowEdit { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowDelete { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SystemType/SystemTypeOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SystemType/SystemTypeOutputDto.cs new file mode 100644 index 0000000..4840ea2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/SystemType/SystemTypeOutputDto.cs @@ -0,0 +1,100 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class SystemTypeOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string EnCode { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string FullName { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(250)] + public string Url { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowEdit { get; set; } + + /// + /// 设置或获取 + /// + public bool? AllowDelete { get; set; } + + /// + /// 设置或获取 + /// + public long? SortCode { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string DeleteUserId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileInputDto.cs new file mode 100644 index 0000000..f0fad32 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileInputDto.cs @@ -0,0 +1,80 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(UploadFile))] + [Serializable] + public class UploadFileInputDto : IInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public string FileName { get; set; } + + /// + /// 设置或获取 + /// + public string FilePath { get; set; } + + /// + /// 设置或获取 + /// + public string Description { get; set; } + + /// + /// 设置或获取 + /// + public string FileType { get; set; } + + /// + /// 设置或获取 + /// + public long? FileSize { get; set; } + + /// + /// 设置或获取 + /// + public string Extension { get; set; } + + /// + /// 设置或获取 + /// + public bool IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + public long SortCode { get; set; } + + /// + /// 设置或获取 + /// + public string CreateUserName { get; set; } + + /// + /// 设置或获取 + /// + public string Thumbnail { get; set; } + + /// + /// 设置或获取 + /// + public string BelongApp { get; set; } + + /// + /// 设置或获取 + /// + public string BelongAppId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileOutputDto.cs new file mode 100644 index 0000000..ec06b06 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileOutputDto.cs @@ -0,0 +1,91 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出Dto:UploadFile + /// + [Serializable] + public class UploadFileOutputDto + { + /// + /// Id + /// + public long Id { get; set; } + + /// + /// 文件名称 + /// + public string FileName { get; set; } + + /// + /// 文件路径 + /// + public string FilePath { get; set; } + + /// + /// 文件路径物理路径 + /// + public string PhysicsFilePath { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 文件类型 + /// + public string FileType { get; set; } + + /// + /// 文件大小 + /// + public long FileSize { get; set; } + + /// + /// 扩展名称 + /// + public string Extension { get; set; } + + /// + /// 排序 + /// + public long SortCode { get; set; } + + /// + /// 删除标志 + /// + public virtual bool? IsDeleted { get; set; } + + /// + /// 有效标志 + /// + public virtual bool IsEnabled { get; set; } + + /// + /// 创建用户主键 + /// + public virtual long CreatedUserId { get; set; } + + /// + /// 上传时间 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 缩略图 + /// + public string Thumbnail { get; set; } + + /// + /// 所属应用 + /// + public string BelongApp { get; set; } + + /// + /// 所属应用ID + /// + public string BelongAppId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileResultOuputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileResultOuputDto.cs new file mode 100644 index 0000000..564926c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/UploadFile/UploadFileResultOuputDto.cs @@ -0,0 +1,47 @@ +using System; +using Znyc.Admin.Commons.Dtos; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 上传结束输出文件对象 + /// + [Serializable] + public class UploadFileResultOuputDto : IOutputDto + { + /// + /// + /// + public long Id { get; set; } + + /// + /// 文件名称 + /// + public string FileName { get; set; } + + /// + /// 文件路径物理路径 + /// + public string PhysicsFilePath { get; set; } + + /// + /// 缩略图 + /// + public string Thumbnail { get; set; } + + /// + /// 文件路径 + /// + public string FilePath { get; set; } + + /// + /// 文件大小 + /// + public long FileSize { get; set; } + + /// + /// 文件类型 + /// + public string FileType { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/DcUserInPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/DcUserInPutDto.cs new file mode 100644 index 0000000..80b18f2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/DcUserInPutDto.cs @@ -0,0 +1,61 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(User))] + [Serializable] + public class DcUserInPutDto : IInputDto + + { + public long Id { get; set; } + + /// + /// OpenId + /// + public string OpenId { get; set; } + + /// + /// 账号 + /// + public string Account { get; set; } + + /// + /// 密码 + /// + public string PassWord { get; set; } + + /// + /// 盐 + /// + public string Salt { get; set; } + + /// + /// 用户名 + /// + + public string UserName { get; set; } + + /// + /// 头像 + /// + public string AvatarUrl { get; set; } + + /// + /// 电话 + /// + + public string Phone { get; set; } + + /// + /// 电话 + /// + + public int Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/SearchUserModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/SearchUserModel.cs new file mode 100644 index 0000000..695d812 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/SearchUserModel.cs @@ -0,0 +1,35 @@ +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 用户搜索条件 + /// + public class SearchUserModel : SearchInputDto + { + + /// + /// 角色Id + /// + public string RoleId { get; set; } + + /// + /// 注册或添加时间 开始 + /// + public string StartTime { get; set; } + + /// + /// 注册或添加时间 结束 + /// + public string EndTime { get; set; } + + /// + /// 状态 + /// + public int Status { get; set; } + + + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserAllListFocusOutPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserAllListFocusOutPutDto.cs new file mode 100644 index 0000000..4e545bf --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserAllListFocusOutPutDto.cs @@ -0,0 +1,228 @@ +using AutoMapper; +using System; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// + /// + [Serializable] + [AutoMap(typeof(AdminUser))] + public class UserAllListFocusOutPutDto + { + #region Property Members + + /// + /// 用户主键 + /// + public virtual long id { get; set; } + + /// + /// 账户 + /// + public virtual string Account { get; set; } + + /// + /// 姓名 + /// + public virtual string RealName { get; set; } + + /// + /// 呢称 + /// + public virtual string UserName { get; set; } + + /// + /// 头像 + /// + public virtual string HeadIcon { get; set; } + + /// + /// 性别 + /// + public virtual long? Gender { get; set; } + + /// + /// 生日 + /// + public virtual DateTime? Birthday { get; set; } + + /// + /// 手机 + /// + public virtual string MobilePhone { get; set; } + + /// + /// 密码 + /// + public virtual string UserPassword { get; set; } + + /// + /// 邮箱 + /// + public virtual string Email { get; set; } + + /// + /// 微信 + /// + public virtual string WeChat { get; set; } + + /// + /// 是否会员 + /// + public virtual bool? IsMember { get; set; } + + /// + /// 头像 + /// + public string MemberGradeId { get; set; } + + /// + /// 上级推广员 + /// + public long ReferralUserId { get; set; } + + /// + /// 主管主键 + /// + public virtual string ManagerId { get; set; } + + /// + /// 安全级别 + /// + public virtual long? SecurityLevel { get; set; } + + /// + /// 个性签名 + /// + public virtual string Signature { get; set; } + + /// + /// 组织主键 + /// + public virtual long OrganizeId { get; set; } + + /// + /// 组织名称 + /// + public virtual string OrganizeName { get; set; } + + /// + /// 部门主键 + /// + public virtual string DepartmentId { get; set; } + + /// + /// 部门名称 + /// + public virtual string DepartmentName { get; set; } + + /// + /// 角色主键 + /// + public virtual long RoleId { get; set; } + + /// + /// 角色名称 + /// + public virtual string RoleName { get; set; } + + /// + /// 岗位主键 + /// + public virtual string DutyId { get; set; } + + /// + /// 岗位名称 + /// + public virtual string DutyName { get; set; } + + /// + /// 是否管理员 + /// + public virtual bool? IsAdministrator { get; set; } + + /// + /// 排序码 + /// + public virtual long? SortCode { get; set; } + + /// + /// 描述 + /// + public virtual string Description { get; set; } + + /// + /// 删除标志 + /// + public virtual bool? IsDeleted { get; set; } + + /// + /// 有效标志 + /// + public virtual bool IsEnabled { get; set; } + + /// + /// 创建日期 + /// + public virtual DateTime? CreatedTime { get; set; } + + /// + /// 创建用户主键 + /// + public virtual long CreatedUserId { get; set; } + + /// + /// 最后修改时间 + /// + public virtual DateTime? ModifiedTime { get; set; } + + /// + /// 最后修改用户 + /// + public virtual long ModifiedUserId { get; set; } + + /// + /// 删除时间 + /// + public virtual DateTime? DeleteTime { get; set; } + + /// + /// 删除用户 + /// + public virtual string DeleteUserId { get; set; } + + /// + /// 我是否关注 + /// + public virtual string IfFocus { get; set; } + + /// + /// 总关注人数 + /// + public virtual long TotalFocus { get; set; } + + /// + /// 是否认证 + /// + public virtual string VipGrade { get; set; } + + /// + /// 是否认证 + /// + public virtual bool IsAuthentication { get; set; } + + /// + /// 认证级别 + /// + public virtual long AuthenticationType { get; set; } + + /// + /// 记录总数 + /// + public virtual long RecordCount { get; set; } + + #endregion Property Members + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserExtendInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserExtendInputDto.cs new file mode 100644 index 0000000..1a14cb9 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserExtendInputDto.cs @@ -0,0 +1,104 @@ +using AutoMapper; +using System; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(UserExtend))] + [Serializable] + public class UserExtendInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取名片内容 + /// + public string CardContent { get; set; } + + /// + /// 设置或获取电话 + /// + public string Telphone { get; set; } + + /// + /// 设置或获取地址 + /// + public string Address { get; set; } + + /// + /// 设置或获取公司名称 + /// + public string CompanyName { get; set; } + + /// + /// 设置或获取职位名称 + /// + public string PositionTitle { get; set; } + + /// + /// 设置或获取个人微信二维码 + /// + public string WechatQrCode { get; set; } + + /// + /// 设置或获取行业 + /// + public string IndustryId { get; set; } + + /// + /// 设置或获取隐私:0-不公开,1-公开;2-部分公开 + /// + public long? OpenType { get; set; } + + /// + /// 设置或获取是否允许他人转发你的名片 + /// + public bool? IsOtherShare { get; set; } + + /// + /// 设置或获取转发标题 + /// + public string ShareTitle { get; set; } + + /// + /// 设置或获取网址 + /// + public string WebUrl { get; set; } + + /// + /// 设置或获取公司简介 + /// + public string CompanyDesc { get; set; } + + /// + /// 设置或获取名片样式 + /// + public string CardTheme { get; set; } + + /// + /// 设置或获取Vip等级 + /// + public string VipGrade { get; set; } + + /// + /// 设置或获取是否认证 + /// + public bool? IsAuthentication { get; set; } + + /// + /// 设置或获取认证类型1-企业;2-个人 + /// + public long? AuthenticationType { get; set; } + + /// + /// 设置或获取 + /// + public bool IsEnabled { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserExtendOutPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserExtendOutPutDto.cs new file mode 100644 index 0000000..e9f4aaa --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserExtendOutPutDto.cs @@ -0,0 +1,171 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class UserExtendOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取用户Id + /// + [MaxLength(50)] + public long UserId { get; set; } + + /// + /// 设置或获取名片内容 + /// + [MaxLength(2147483647)] + public string CardContent { get; set; } + + /// + /// 设置或获取电话 + /// + [MaxLength(50)] + public string Telphone { get; set; } + + /// + /// 设置或获取地址 + /// + [MaxLength(250)] + public string Address { get; set; } + + /// + /// 设置或获取公司名称 + /// + [MaxLength(250)] + public string CompanyName { get; set; } + + /// + /// 设置或获取职位名称 + /// + [MaxLength(250)] + public string PositionTitle { get; set; } + + /// + /// 设置或获取个人微信二维码 + /// + [MaxLength(250)] + public string WechatQrCode { get; set; } + + /// + /// 设置或获取行业 + /// + [MaxLength(500)] + public string IndustryId { get; set; } + + /// + /// 设置或获取隐私:0-不公开,1-公开;2-部分公开 + /// + public long? OpenType { get; set; } + + /// + /// 设置或获取是否允许他人转发你的名片 + /// + public bool? IsOtherShare { get; set; } + + /// + /// 设置或获取转发标题 + /// + [MaxLength(250)] + public string ShareTitle { get; set; } + + /// + /// 设置或获取网址 + /// + [MaxLength(250)] + public string WebUrl { get; set; } + + /// + /// 设置或获取公司简介 + /// + [MaxLength(2147483647)] + public string CompanyDesc { get; set; } + + /// + /// 设置或获取名片样式 + /// + [MaxLength(250)] + public string CardTheme { get; set; } + + /// + /// 设置或获取Vip等级 + /// + [MaxLength(50)] + public string VipGrade { get; set; } + + /// + /// 设置或获取是否认证 + /// + public bool? IsAuthentication { get; set; } + + /// + /// 设置或获取认证类型1-企业;2-个人 + /// + public long? AuthenticationType { get; set; } + + /// + /// 设置或获取 + /// + public bool IsEnabled { get; set; } + + /// + /// 设置或获取 + /// + public bool? IsDeleted { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? CreatedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string CreatedUserId { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long CompanyId { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long DeptId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ModifiedTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string ModifiedUserId { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? DeleteTime { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string DeleteUserId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserFocusExtendOutPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserFocusExtendOutPutDto.cs new file mode 100644 index 0000000..05d0916 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserFocusExtendOutPutDto.cs @@ -0,0 +1,69 @@ +using AutoMapper; +using System; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// + /// + [AutoMap(typeof(AdminUser))] + [Serializable] + public class UserFocusExtendOutPutDto : IOutputDto + { + #region Property Members + + /// + /// 用户主键 + /// + public virtual long id { get; set; } + + /// + /// 关注的用户ID + /// + public virtual string FocusUserId { get; set; } + + /// + /// 关注人 + /// + public virtual long CreatedUserId { get; set; } + + /// + /// 关注时间 + /// + public virtual DateTime? CreatedTime { get; set; } + + /// + /// 关注的用户昵称 + /// + public virtual string FUserUserName { get; set; } + + /// + /// 关注的用户头像 + /// + public virtual string FUserHeadIcon { get; set; } + + /// + /// 关注的用户手机 + /// + public virtual string FUserMobilePhone { get; set; } + + /// + /// 关注的用户资料开放程序 + /// + public virtual string FUserOpenType { get; set; } + + /// + /// 记录数 + /// + public virtual long RecordCount { get; set; } + + /// + /// 关注时间 + /// + public virtual string ShowAddTime { get; set; } + + #endregion Property Members + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserInPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserInPutDto.cs new file mode 100644 index 0000000..8c4db31 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserInPutDto.cs @@ -0,0 +1,41 @@ +using AutoMapper; +using System; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(AdminUser))] + [Serializable] + public class UserInputDto + { + public long Id { get; set; } + + ///// + ///// OpenId + ///// + //public string OpenId { get; set; } + + /// + /// 用户昵称 + /// + public string UserName { get; set; } + + /// + /// 用户头像 + /// + public string AvatarUrl { get; set; } + + /// + /// 手机号 + /// + public string Phone { get; set; } + + ///// + ///// 状态 + ///// + //public long Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserLogOnInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserLogOnInputDto.cs new file mode 100644 index 0000000..3673613 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserLogOnInputDto.cs @@ -0,0 +1,109 @@ +using AutoMapper; +using System; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(AdminUserLogOn))] + [Serializable] + public class UserLogOnInputDto + { + /// + /// 设置或获取 + /// + public long Id { get; set; } + + /// + /// 设置或获取 + /// + public string UserPassword { get; set; } + + /// + /// 设置或获取 + /// + public string UserSecretkey { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? AllowStartTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? AllowEndTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? LockStartDate { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? LockEndDate { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? FirstVisitTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? PreviousVisitTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? LastVisitTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ChangePasswordDate { get; set; } + + /// + /// 设置或获取 + /// + public bool? MultiUserLogin { get; set; } + + /// + /// 设置或获取 + /// + public long? LogOnCount { get; set; } + + /// + /// 设置或获取 + /// + public bool? UserOnLine { get; set; } + + /// + /// 设置或获取 + /// + public string Question { get; set; } + + /// + /// 设置或获取 + /// + public string AnswerQuestion { get; set; } + + /// + /// 设置或获取 + /// + public bool? CheckIPAddress { get; set; } + + /// + /// 设置或获取 + /// + public string Language { get; set; } + + /// + /// 设置或获取 + /// + public string Theme { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserLogOnOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserLogOnOutputDto.cs new file mode 100644 index 0000000..c793081 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserLogOnOutputDto.cs @@ -0,0 +1,120 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class UserLogOnOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long Id { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long UserId { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string UserPassword { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string UserSecretkey { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? AllowStartTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? AllowEndTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? LockStartDate { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? LockEndDate { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? FirstVisitTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? PreviousVisitTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? LastVisitTime { get; set; } + + /// + /// 设置或获取 + /// + public DateTime? ChangePasswordDate { get; set; } + + /// + /// 设置或获取 + /// + public bool? MultiUserLogin { get; set; } + + /// + /// 设置或获取 + /// + public long? LogOnCount { get; set; } + + /// + /// 设置或获取 + /// + public bool? UserOnLine { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Question { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(500)] + public string AnswerQuestion { get; set; } + + /// + /// 设置或获取 + /// + public bool? CheckIPAddress { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Language { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(50)] + public string Theme { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOpenIdsInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOpenIdsInputDto.cs new file mode 100644 index 0000000..3bf751d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOpenIdsInputDto.cs @@ -0,0 +1,24 @@ +using AutoMapper; +using System; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(UserOpenIds))] + [Serializable] + public class UserOpenIdsInputDto + { + /// + /// 设置或获取 + /// + public string OpenIdType { get; set; } + + /// + /// 设置或获取 + /// + public string OpenId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOpenIdsOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOpenIdsOutputDto.cs new file mode 100644 index 0000000..152294e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOpenIdsOutputDto.cs @@ -0,0 +1,30 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class UserOpenIdsOutputDto + { + /// + /// 设置或获取 + /// + [MaxLength(50)] + public long UserId { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(256)] + public string OpenIdType { get; set; } + + /// + /// 设置或获取 + /// + [MaxLength(128)] + public string OpenId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOutputDto.cs new file mode 100644 index 0000000..2812381 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserOutputDto.cs @@ -0,0 +1,59 @@ +using System; +using Znyc.Admin.Commons.Dtos; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class UserOutputDto : IOutputDto + + { + public long Id { get; set; } + + /// + /// 账号 + /// + public string Account { get; set; } + + /// + /// 用户名 + /// + + public string UserName { get; set; } + + /// + /// 头像 + /// + public string AvatarUrl { get; set; } + + /// + /// 电话 + /// + + public string Phone { get; set; } + + /// + /// 状态 + /// + + public int Status { get; set; } + + /// + /// 角色名称 + /// + public string RoleName { get; set; } + + /// + /// 公司名称 + /// + public string CompanyName { get; set; } + + /// + /// 创建时间 + /// + + public string CreatedTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserThemeInputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserThemeInputDto.cs new file mode 100644 index 0000000..792ee8c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserThemeInputDto.cs @@ -0,0 +1,36 @@ +using System; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 用户自定义主题 + /// + [Serializable] + public class UserThemeInputDto + { + /// + /// 主题颜色 + /// + public string Theme { set; get; } + + /// + /// 主题风格 + /// + public string SideTheme { set; get; } + + /// + /// 是否固定 Header + /// + public bool FixedHeader { set; get; } + + /// + /// 是否开启 Tags-Views + /// + public bool TagsView { set; get; } + + /// + /// 是否显示 Logo + /// + public bool SidebarLogo { set; get; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserWithAccessedCtrls.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserWithAccessedCtrls.cs new file mode 100644 index 0000000..bc6cb88 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/User/UserWithAccessedCtrls.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 包括用户及用户可访问的机构/资源/模块/角色 + /// + [Serializable] + public class UserWithAccessedCtrls + { + /// + /// 用户可以访问到的模块(包括所属角色与自己的所有模块) + /// + public List Modules { get; set; } + + /// + /// 用户可以访问的资源 + /// + public List RoleDatas { get; set; } + + /// + /// 用户所属机构 + /// + public List Organizes { get; set; } + + /// + /// 用户所属角色 + /// + public List Roles { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/SearchVehicleModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/SearchVehicleModel.cs new file mode 100644 index 0000000..6db4127 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/SearchVehicleModel.cs @@ -0,0 +1,31 @@ +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 用户搜索条件 + /// + public class SearchVehicleModel : SearchInputDto + { + /// + /// 公司Id + /// + public long CompanyId { get; set; } + + /// + /// 注册或添加时间 开始 + /// + public string StartTime { get; set; } + + /// + /// 注册或添加时间 结束 + /// + public string EndTime { get; set; } + + /// + /// 状态 + /// + public int Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleInPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleInPutDto.cs new file mode 100644 index 0000000..56b14cb --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleInPutDto.cs @@ -0,0 +1,75 @@ +using AutoMapper; +using System; +using System.ComponentModel.DataAnnotations; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(Vehicle))] + [Serializable] + public class VehicleInPutDto + { + public long CompanyId { get; set; } + + /// + /// 车辆编号 + /// + public string VehicleCode { get; set; } + + /// + /// 车牌号 + /// + [Required(ErrorMessage = "车牌号不能为空!")] + [MaxLength(8, ErrorMessage = "车牌号不得超过8个字")] + public string VehiclePlate { get; set; } + + /// + /// 物联卡类型 + /// + public int CardType { get; set; } + + /// + /// SIM卡号 + /// + [Required(ErrorMessage = "SimNo不能为空!")] + [MaxLength(25, ErrorMessage = "SimNo不得超过25个字")] + public string SimNo { get; set; } + + /// + /// 设备类型 + /// + public long TerminalType { get; set; } + + /// + /// GPS协议号 + /// + public string AgreementNo { get; set; } + + /// + /// IEML号 + /// + [Required(ErrorMessage = "IMEI号不能为空!")] + [MaxLength(25, ErrorMessage = "IMEI号不得超过25个字")] + public string ImeiNo { get; set; } + + /// + /// 开通时间 + /// + public DateTime OpenTime { get; set; } + + /// + /// 到期时间 + /// + public DateTime ExpireTime { get; set; } + + #region v1.2.2 + /// + /// 排序 + /// + public int Sort { get; set; } + #endregion + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleOutputDto.cs new file mode 100644 index 0000000..08206df --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleOutputDto.cs @@ -0,0 +1,140 @@ +using System; +using Znyc.Admin.Commons.Dtos; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class VehicleOutputDto : IOutputDto + { + public long Id { get; set; } + + /// + /// 所属公司 + /// + public long CompanyId { get; set; } + + /// + /// 车辆编号 + /// + public string VehicleCode { get; set; } + + /// + /// 车牌号 + /// + public string VehiclePlate { get; set; } + + /// + /// 车辆类型 + /// + public long VehicleType { get; set; } + + /// + /// 所属车组 + /// + public long VehicleGroup { get; set; } + + /// + /// SIM卡号 + /// + public string SimNo { get; set; } + + /// + /// 设备类型 + /// + public int TerminalType { get; set; } + + /// + /// 设备类型名称 + /// + public string TerminalTypeName { get; set; } + + /// + /// 设备号 + /// + public string TerminalNo { get; set; } + + /// + /// 物联卡类型 + /// + public int CardType { get; set; } + + /// + /// 物联卡名称 + /// + public string CardTypeName { get; set; } + + /// + /// Imei号 + /// + public string ImeiNo { get; set; } + + /// + /// 是否激活 + /// + public bool IsActivate { get; set; } + + /// + /// 是否开启GPS + /// + public bool IsGps { get; set; } + + /// + /// 司机 + /// + public long VehicleDriver { get; set; } + + /// + /// 司机电话 + /// + public string DriverPhone { get; set; } + + /// + /// 联系人 + /// + public string ContactPerson { get; set; } + + /// + /// 联系电话 + /// + public string ContactPhone { get; set; } + + /// + /// 状态 + /// + public int Status { get; set; } + + /// + /// 打火状态 + /// + public int Acc { get; set; } + + /// + /// 工作状态 + /// + public int Work { get; set; } + + /// + /// GPS时间 + /// + public DateTime GpsTime { get; set; } + + /// + /// 开通时间 + /// + public DateTime OpenTime { get; set; } + + /// + /// 到期时间 + /// + public DateTime ExpireTime { get; set; } + + + /// + /// 排序 + /// + public int Sort { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleUpdateInPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleUpdateInPutDto.cs new file mode 100644 index 0000000..58df6ae --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/Vehicle.cs/VehicleUpdateInPutDto.cs @@ -0,0 +1,16 @@ +using AutoMapper; +using System; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + ///车辆修改输入模型 + /// + [AutoMap(typeof(Vehicle))] + [Serializable] + public class VehicleUpdateInPutDto : VehicleInPutDto + { + public long Id { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/SearchVehicleChangeModel.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/SearchVehicleChangeModel.cs new file mode 100644 index 0000000..1ebb31a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/SearchVehicleChangeModel.cs @@ -0,0 +1,26 @@ +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 车辆换装搜索条件 + /// + public class SearchVehicleChangeModel : SearchInputDto + { + /// + /// 车辆Id + /// + public long VehicleId { get; set; } + + /// + /// 注册或添加时间 开始 + /// + public string StartTime { get; set; } + + /// + /// 注册或添加时间 结束 + /// + public string EndTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/VehicleChangeInPutDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/VehicleChangeInPutDto.cs new file mode 100644 index 0000000..0d853d6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/VehicleChangeInPutDto.cs @@ -0,0 +1,69 @@ +using AutoMapper; +using System; +using System.ComponentModel.DataAnnotations; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输入对象模型 + /// + [AutoMap(typeof(VehicleChange))] + [Serializable] + public class VehicleChangeInPutDto + { + /// + /// 公司Id + /// + public long CompanyId { get; set; } + + /// + /// 车辆Id + /// + public long VehicleId { get; set; } + + /// + /// 物联卡类型 + /// + public long CardType { get; set; } + + /// + /// SIM卡号 + /// + [Required(ErrorMessage = "物联卡号码不能为空!")] + [MaxLength(25, ErrorMessage = "物联卡号码不得超过25个字")] + public string SimNo { get; set; } + + /// + /// 设备类型 + /// + public long TerminalType { get; set; } + + /// + /// GPS协议号 + /// + public string AgreementNo { get; set; } + + /// + /// IEML号 + /// + [Required(ErrorMessage = "GPSIMEI号不能为空!")] + [MaxLength(25, ErrorMessage = "GPSIMEI号不得超过25个字")] + public string ImeiNo { get; set; } + + /// + /// 开通时间 + /// + public DateTime ChangeTime { get; set; } + + /// + /// 修改日期 + /// + public DateTime UpdateTime { get; set; } + + /// + /// 备注 + /// + public string Note { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/VehicleChangeOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/VehicleChangeOutputDto.cs new file mode 100644 index 0000000..f751346 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/VehicleChange/VehicleChangeOutputDto.cs @@ -0,0 +1,72 @@ +using System; +using Znyc.Admin.Commons.Dtos; + +namespace Znyc.Admin.Security.Dtos +{ + /// + /// 输出对象模型 + /// + [Serializable] + public class VehicleChangeOutputDto : IOutputDto + { + /// + /// 公司Id + /// + public long CompanyId { get; set; } + + /// + /// 车辆Id + /// + public long VehicleId { get; set; } + + /// + /// 物联卡类型 + /// + public int CardType { get; set; } + + /// + /// 物联卡类型名称 + /// + public string CardTypeName { get; set; } + + /// + /// SIM卡号 + /// + public string SimNo { get; set; } + + /// + /// 设备类型 + /// + public int TerminalType { get; set; } + + /// + /// 设备号 + /// + public string TerminalNo { get; set; } + + /// + /// GPS设备类型名称 + /// + public string TerminalTypeName { get; set; } + + /// + /// IEML号 + /// + public string ImeiNo { get; set; } + + /// + /// 开通时间 + /// + public DateTime ChangeTime { get; set; } + + /// + /// 修改日期 + /// + public DateTime UpdateTime { get; set; } + + /// + /// 备注 + /// + public string Note { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/WxUserRelation/WxUserRelationInput.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/WxUserRelation/WxUserRelationInput.cs new file mode 100644 index 0000000..73ace25 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/WxUserRelation/WxUserRelationInput.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Znyc.Admin.Security.Dtos.WxUserRelation +{ + public class WxUserRelationInput + { + /// + /// UnionId + /// + + public string UnionId { get; set; } + + /// + /// OpenId + /// + + public string OpenId { get; set; } + + /// + /// 用户Id + /// + + public long UserId { get; set; } + + /// + /// 公众号OpenId + /// + + public string WxOfficialOpenId { get; set; } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/WxUserRelation/WxUserRelationOutputDto.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/WxUserRelation/WxUserRelationOutputDto.cs new file mode 100644 index 0000000..28fd15c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Dtos/WxUserRelation/WxUserRelationOutputDto.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Znyc.Admin.Security.Dtos.WxUserRelation +{ + public class WxUserRelationOutputDto + { + /// + /// UnionId + /// + + public string UnionId { get; set; } + + /// + /// OpenId + /// + + public string OpenId { get; set; } + + /// + /// 用户Id + /// + + public long UserId { get; set; } + + /// + /// 公众号OpenId + /// + + public string WxOfficialOpenId { get; set; } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/APP.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/APP.cs new file mode 100644 index 0000000..6e7dbc8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/APP.cs @@ -0,0 +1,45 @@ +using System; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 系统应用表,数据实体对象 + /// + [Table("sys_app")] + [Serializable] + public class APP : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public APP() + { + CreatedTime = DateTime.Now; + ModifiedTime = DateTime.Now; + IsDeleted = false; + } + + /// + /// 应用Id + /// + [MaxLength(50)] + [Description("应用Id")] + public virtual string AppId { get; set; } + + /// + /// 应用密钥 + /// + [MaxLength(256)] + [Description("应用密钥")] + public virtual string AppSecret { get; set; } + + /// + /// 有效标志 + /// + public virtual bool IsEnabled { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/AdminUser.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/AdminUser.cs new file mode 100644 index 0000000..d740e28 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/AdminUser.cs @@ -0,0 +1,71 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 用户表,数据实体对象 + /// + [Table("sys_adminuser")] + [Serializable] + public class AdminUser : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public AdminUser() + { + } + + /// + /// 账户 + /// + public string Account { get; set; } + + /// + /// 姓名 + /// + public string UserName { get; set; } + + /// + /// 头像 + /// + public string HeadIcon { get; set; } + + /// + /// 性别,1=男,0=未知,2=女 + /// + public int Gender { get; set; } + + /// + /// 手机 + /// + public string MobilePhone { get; set; } + + /// + /// 组织主键 + /// + public long OrganizeId { get; set; } + + /// + /// 部门主键 + /// + public long DepartmentId { get; set; } + + /// + /// 角色主键 + /// + public long RoleId { get; set; } + + /// + /// 是否管理员 + /// + public bool IsAdministrator { get; set; } + + /// + /// 状态 + /// + public long Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/AdminUserLogOn.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/AdminUserLogOn.cs new file mode 100644 index 0000000..ebeb6ee --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/AdminUserLogOn.cs @@ -0,0 +1,66 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 用户登录信息表,数据实体对象 + /// + [Table("sys_adminuser_logon")] + [Serializable] + public class AdminUserLogOn : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public AdminUserLogOn() + { + } + + /// + /// 用户主键 + /// + public virtual long AdminUserId { get; set; } + + /// + /// 用户密码 + /// + public virtual string AdminUserPassword { get; set; } + + /// + /// 用户秘钥 + /// + public virtual string AdminUserSecretkey { get; set; } + + /// + /// 最后访问时间 + /// + public virtual DateTime LastVisitTime { get; set; } + + /// + /// 最后修改密码日期 + /// + public virtual DateTime ChangePasswordDate { get; set; } + + /// + /// 登录次数 + /// + public virtual long LogOnCount { get; set; } + + /// + /// 在线状态 + /// + public virtual bool UserOnLine { get; set; } + + /// + /// 系统语言 + /// + public virtual string Language { get; set; } + + /// + /// 系统样式 + /// + public virtual string Theme { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Area.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Area.cs new file mode 100644 index 0000000..dfb17dc --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Area.cs @@ -0,0 +1,74 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 行政区域表,数据实体对象 + /// + [Table("sys_area")] + [Serializable] + public class Area : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public Area() + { + } + + /// + /// 父级 + /// + [MaxLength(50)] + public long ParentId { get; set; } + + /// + /// 层次 + /// + public int? Layers { get; set; } + + /// + /// 编码 + /// + [MaxLength(50)] + public string EnCode { get; set; } + + /// + /// 名称 + /// + [MaxLength(100)] + public string FullName { get; set; } + + /// + /// 简拼 + /// + [MaxLength(200)] + public string SimpleSpelling { get; set; } + + /// + /// 父级路径 + /// + [MaxLength(600)] + public string FullIdPath { get; set; } + + /// + /// 是否是最后一级 + /// + public bool IsLast { get; set; } + + /// + /// 排序码 + /// + public int SortCode { get; set; } + + /// + /// 有效标志 + /// + public bool IsEnabled { get; set; } + + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Log.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Log.cs new file mode 100644 index 0000000..b60807b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Log.cs @@ -0,0 +1,85 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Core.DataManager; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 系统日志,数据实体对象 + /// + [AppDBContext("DefaultDb")] + [Table("sys_log")] + [Serializable] + public class Log : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public Log() + { + IsDeleted = false; + CreatedTime = DateTime.Now; + } + + /// + /// 日期 + /// + public DateTime? Date { get; set; } + + /// + /// 用户名 + /// + public string Account { get; set; } + + /// + /// 姓名 + /// + public string UserName { get; set; } + + /// + /// 组织主键 + /// + public long OrganizeId { get; set; } + + /// + /// 类型 + /// + public string Type { get; set; } + + /// + /// IP地址 + /// + public string IPAddress { get; set; } + + /// + /// IP所在城市 + /// + public string IPAddressName { get; set; } + + /// + /// 系统模块Id + /// + public long ModuleId { get; set; } + + /// + /// 系统模块 + /// + public string ModuleName { get; set; } + + /// + /// 结果 + /// + public bool? Result { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 有效标志 + /// + public bool IsEnabled { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogEx.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogEx.cs new file mode 100644 index 0000000..54eb6cb --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogEx.cs @@ -0,0 +1,75 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Core.DataManager; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 系统日志,数据实体对象 + /// + [AppDBContext("DefaultDb")] + [Table("dc_log_ex")] + [Serializable] + public class LogEx : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public LogEx() + { + IsDeleted = false; + CreatedTime = DateTime.Now; + } + + /// + /// 操作人 + /// + 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; } + + /// + /// 异常信息 + /// + public string ExceptionMsg { get; set; } + + /// + /// 异常源 + /// + public string ExceptionSource { get; set; } + + /// + /// 堆栈信息 + /// + public string StackTrace { get; set; } + + /// + /// 参数对象 + /// + public string ParamsObj { get; set; } + + /// + /// 异常时间 + /// + public DateTime ExceptionTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogOp.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogOp.cs new file mode 100644 index 0000000..2b7531a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogOp.cs @@ -0,0 +1,113 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Core.DataManager; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 操作日志表 + /// + [AppDBContext("DefaultDb")] + [Table("dc_log_op")] + [Serializable] + public class LogOp : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public LogOp() + { + IsDeleted = false; + CreatedTime = DateTime.Now; + ModifiedTime = DateTime.Now; + } + + /// + /// 操作用户 + /// + public string Name { get; set; } + + /// + /// 是否执行成功 + /// + public string Success { get; set; } + + /// + /// 具体消息 + /// + public string Message { get; set; } + + /// + /// IP + /// + public string IP { get; set; } + + /// + /// 地址 + /// + public string Location { get; set; } + + /// + /// 浏览器 + /// + public string Browser { get; set; } + + /// + /// 堆栈信息 + /// + public string StackTrace { get; set; } + + /// + /// 操作系统 + /// + public string OS { get; set; } + + /// + /// 请求地址 + /// + public string Url { get; set; } + + /// + /// 类名称 + /// + public string ClassName { get; set; } + + /// + /// 方法名称 + /// + public string MethodName { get; set; } + + /// + /// 请求方式(GET POST PUT DELETE) + /// + public string ReqMethod { get; set; } + + /// + /// 请求参数 + /// + public string Param { get; set; } + + /// + /// 返回结果 + /// + public string Result { get; set; } + + /// + /// 耗时 + /// + public long ElapsedTime { get; set; } + + /// + /// 操作时间 + /// + public DateTime OpTime { get; set; } + + /// + /// 操作人 + /// + public string Account { get; set; } + + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogVis.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogVis.cs new file mode 100644 index 0000000..faa6f59 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/LogVis.cs @@ -0,0 +1,77 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Core.DataManager; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 访问日志表 + /// + [AppDBContext("DefaultDb")] + [Table("dc_log_vis")] + [Serializable] + public class LogVis : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public LogVis() + { + IsDeleted = false; + CreatedTime = DateTime.Now; + } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 是否执行成功 + /// + public string Success { get; set; } + + /// + /// 具体消息 + /// + public string Message { get; set; } + + /// + /// Ip + /// + public string Ip { get; set; } + + /// + /// 地址 + /// + public string Location { get; set; } + + /// + /// 浏览器 + /// + public string Browser { get; set; } + + /// + /// 访问类型 + /// + public string VisType { get; set; } + + /// + /// 操作系统 + /// + + public string Os { get; set; } + + /// + /// 操作账号 + /// + public string Account { get; set; } + + /// + /// 访问时间 + /// + + public DateTime VisTime { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Menu.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Menu.cs new file mode 100644 index 0000000..aca1095 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Menu.cs @@ -0,0 +1,117 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 系统菜单,数据实体对象 + /// + [Table("sys_menu")] + [Serializable] + public class Menu : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public Menu() + { + } + + /// + /// 所属系统主键 + /// + public long SystemTypeId { get; set; } + + /// + /// 父级 + /// + public long ParentId { get; set; } + + /// + /// 层次 + /// + public int Layers { get; set; } + + /// + /// 编码 + /// + public string EnCode { get; set; } + + /// + /// 名称 + /// + public string FullName { get; set; } + + /// + /// 图标 + /// + public string Icon { get; set; } + + /// + /// 路由 + /// + public string UrlAddress { get; set; } + + /// + /// 目标打开方式 + /// + public string Target { get; set; } + + /// + /// 菜单类型(C目录 M菜单 F按钮) + /// + public string MenuType { get; set; } + + /// + /// 组件路径 + /// + public string Component { get; set; } + + /// + /// 设置当前选中菜单,用于新增、编辑、查看操作为单独的路由时指定选中菜单路由 + /// 同时设置为隐藏时才有效 + /// + public string ActiveMenu { get; set; } + + /// + /// 展开 + /// + public bool IsExpand { get; set; } + + /// + /// 设置或获取 是否显示 + /// + public bool IsShow { get; set; } + + /// + /// 设置或获取 是否外链 + /// + public bool IsFrame { get; set; } + + /// + /// 设置或获取是否缓存 + /// + public bool IsCache { get; set; } + + /// + /// 公共 + /// + public bool IsPublic { get; set; } + + /// + /// 排序码 + /// + public int SortCode { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 有效标志 + /// + public bool IsEnabled { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Organize.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Organize.cs new file mode 100644 index 0000000..09fbb68 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Organize.cs @@ -0,0 +1,63 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 组织表,数据实体对象 + /// + [Table("sys_organize")] + [Serializable] + public class Organize : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public Organize() + { + } + + /// + /// 父级 + /// + public long ParentId { get; set; } + + /// + /// 层次 + /// + public int Layers { get; set; } + + /// + /// 编码 + /// + public string EnCode { get; set; } + + /// + /// 名称 + /// + public string FullName { get; set; } + + /// + /// 负责人 + /// + public string ManagerName { get; set; } + + public string CategoryName { get; set; } + + /// + /// 排序码 + /// + public int SortCode { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 是否有效 + /// + public bool IsEnabled { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Role.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Role.cs new file mode 100644 index 0000000..14e5e73 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/Role.cs @@ -0,0 +1,54 @@ +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 角色表,数据实体对象 + /// + [Table("sys_role")] + public class Role : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public Role() + { + } + + /// + /// 组织主键 + /// + public long OrganizeId { get; set; } + + /// + /// 角色编码 + /// + public string EnCode { get; set; } + + /// + /// 名称 + /// + public string FullName { get; set; } + + /// + /// 类型 + /// + public string Type { get; set; } + + /// + /// 排序码 + /// + public long SortCode { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 有效标志 + /// + public bool IsEnabled { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/RoleData.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/RoleData.cs new file mode 100644 index 0000000..236e346 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/RoleData.cs @@ -0,0 +1,34 @@ +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 角色的数据权限,数据实体对象 + /// + [Table("sys_role_data")] + public class RoleData : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public RoleData() + { + } + + /// + /// 角色ID + /// + public long RoleId { get; set; } + + /// + /// 类型,company-公司,dept-部门,person-个人 + /// + public string DType { get; set; } + + /// + /// 数据数据,部门ID或个人ID + /// + public string AuthorizeData { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/SysSetting.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/SysSetting.cs new file mode 100644 index 0000000..fad755c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/SysSetting.cs @@ -0,0 +1,13 @@ +using System; +using Znyc.Admin.Commons.Options; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 系统配置 + /// + [Serializable] + public class SysSetting : AppSetting + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/SystemType.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/SystemType.cs new file mode 100644 index 0000000..51a9b7c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Area/SystemType.cs @@ -0,0 +1,51 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 子系统 + /// + [Table("sys_systemtype")] + [Serializable] + public class SystemType : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public SystemType() + { + } + + /// + /// 编码 + /// + public virtual string EnCode { get; set; } + + /// + /// 系统名称 + /// + public virtual string FullName { get; set; } + + /// + /// 链接 + /// + public virtual string Url { get; set; } + + /// + /// 排序码 + /// + public virtual int SortCode { get; set; } + + /// + /// 描述 + /// + public virtual string Description { get; set; } + + /// + /// 有效标志 + /// + public virtual bool IsEnabled { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Api.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Api.cs new file mode 100644 index 0000000..7121773 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Api.cs @@ -0,0 +1,17 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + [Table("sys_api")] + [Serializable] + public class Api : BaseEntity + { + public string ApiUrl { get; set; } + + public string AuthKey { get; set; } + + public string AuthValue { get; set; } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Company.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Company.cs new file mode 100644 index 0000000..673f031 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Company.cs @@ -0,0 +1,78 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 公司表 + /// + [Table("dc_company")] + [Comment("公司表")] + public class Company : BaseEntity + { + /// + /// 公司名称 + /// + [Comment("公司名称")] + public string CompanyName { get; set; } + + /// + /// 公司Logo + /// + [Comment("公司Logo")] + public string CompanyLogo { get; set; } + + /// + /// 联系人 + /// + [Comment("联系人")] + [Required, MaxLength(30)] + public string ContactPerson { get; set; } + + /// + /// 联系人电话 + /// + [Comment("联系人电话")] + [Required, MaxLength(11)] + public string ContactPhone { get; set; } + + /// + /// 精度 + /// + [Comment("精度")] + public decimal Longitude { get; set; } + + /// + /// 纬度 + /// + [Comment("纬度")] + public decimal Latitude { get; set; } + + /// + /// 地址 + /// + [Comment("地址")] + [MaxLength(35)] + public string Address { get; set; } + + /// + /// 审核时间 + /// + public DateTime AuditTime { get; set; } + + /// + /// 状态(字典 0正常 1停用 2删除) + /// + [Comment("状态")] + public int Status { get; set; } + + /// + /// 停留标示Id + /// + [Comment("停留标示Id")] + public long StopTag { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Dictionary.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Dictionary.cs new file mode 100644 index 0000000..98ef54e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Dictionary.cs @@ -0,0 +1,56 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 数据字典选项主表,数据实体对象 + /// + [Table("dc_dictionary")] + [Serializable] + public class Dictionary : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public Dictionary() + { + } + + /// + /// 字典父级 + /// + public long ParentId { get; set; } + + /// + /// 字典编码 + /// + public string Code { get; set; } + + /// + /// 字典值 + /// + public string Value { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 字典名称 + /// + public string Name { get; set; } + + /// + /// 启用 + /// + public bool IsEnabled { get; set; } = true; + + /// + /// 排序 + /// + public int Sort { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Employee.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Employee.cs new file mode 100644 index 0000000..6d986e7 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Employee.cs @@ -0,0 +1,71 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys.Dispatching +{ + /// + /// 员工表 + /// + [Table("dc_employee")] + [Comment("员工表")] + public class Employee : BaseEntity + { + /// + /// 用户Id + /// + public long UserId { get; set; } + + /// + /// 员工名 + /// + [Comment("员工名")] + [MaxLength(8)] + public string EmployeeName { get; set; } + + /// + /// 手机号 + /// + [Comment("手机号")] + [MaxLength(11)] + public string EmployeePhone { get; set; } + + /// + /// 机构Id + /// + [Comment("所属公司")] + public long CompanyId { get; set; } + + /// + /// 机构名称 + /// + [Comment("所属公司名称")] + [MaxLength(50)] + public string CompanyName { get; set; } + + /// + /// CommonStatus + /// + [Comment("状态")] + public int Status { get; set; } + + /// + /// RoleStatus + /// + [Comment("角色")] + public long RoleId { get; set; } + + /// + /// RoleStatus + /// + [Comment("角色名称")] + public string RoleName { get; set; } + + /// + /// 是否默认登录 + /// + [Comment("是否默认登录")] + public bool IsDefault { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Message.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Message.cs new file mode 100644 index 0000000..d21fb12 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Message.cs @@ -0,0 +1,56 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 站内消息表,数据实体对象 + /// + [Table("dc_message")] + [Serializable] + public class Message : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public Message() + { + } + + /// + /// 发送者Id + /// + public long SendId { get; set; } + + /// + /// 发送类型 + /// + public int Type { get; set; } + + /// + /// 组Id(不涉及组消息可不用) + /// + public int GroupId { get; set; } + + /// + /// 消息内容 + /// + public string Content { get; set; } + + /// + /// 发送时间 + /// + public DateTime SendTime { get; set; } + + /// + /// 消息标题 + /// + public string MessageTitle { get; set; } + + /// + /// 产品类型 + /// + public int MessageType { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/MessageRecord.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/MessageRecord.cs new file mode 100644 index 0000000..71c274a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/MessageRecord.cs @@ -0,0 +1,36 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 消息记录表 + /// + [Table("dc_message_record")] + [Serializable] + public class MessageRecord : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public MessageRecord() + { + } + + /// + /// 接收者Id + /// + public long ReceiverId { get; set; } + + /// + /// 消息Id + /// + public long MessageId { get; set; } + + /// + /// 状态 + /// + public int Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/RoleAuthorize.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/RoleAuthorize.cs new file mode 100644 index 0000000..f025edc --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/RoleAuthorize.cs @@ -0,0 +1,50 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 角色授权表,数据实体对象 + /// + [Table("dc_role_authorize")] + [Serializable] + public class RoleAuthorize : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public RoleAuthorize() + { + } + + #region Property Members + + /// + /// 项目类型功能标识 0-子系统 1-标识菜单/模块,2标识按钮功能 + /// + public virtual long? ItemType { get; set; } + + /// + /// 项目主键 + /// + public virtual long ItemId { get; set; } + + /// + /// 对象分类/类型1-角色,2-部门,3-用户 + /// + public virtual long? ObjectType { get; set; } + + /// + /// 对象主键,对象分类/类型为角色时就是角色ID,部门就是部门ID,用户就是用户ID + /// + public virtual long ObjectId { get; set; } + + /// + /// 排序码 + /// + public virtual long? SortCode { get; set; } + + #endregion Property Members + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Statistical.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Statistical.cs new file mode 100644 index 0000000..b148cab --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Statistical.cs @@ -0,0 +1,64 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 统计数据 + /// + [Table("sys_statistical")] + [Serializable] + public class Statistical : BaseEntity + { + /// + /// 时间 + /// + public string Time { get; set; } + + /// + /// 今日新增用户数 + /// + public int UserAddTotal { get; set; } + + /// + /// 用户总数 + /// + public int UserSumTotal { get; set; } + + /// + /// 今日新增公司数 + /// + public int CompanyAddTotal { get; set; } + + /// + /// 公司总数 + /// + public int CompanySumTotal { get; set; } + + /// + /// 今日新增车辆数 + /// + public int VehicleAddTotal { get; set; } + + /// + /// 车辆总数 + /// + public int VehicleSumTotal { get; set; } + + /// + /// 今日车辆到期数 + /// + public int ExpireAddTotal { get; set; } + + /// + /// 车辆到期总数 + /// + public int ExpireSumTotal { get; set; } + + /// + /// 今日用户增长百分比 + /// + public decimal UserAddTotalPercent { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UploadFile.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UploadFile.cs new file mode 100644 index 0000000..9bdb386 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UploadFile.cs @@ -0,0 +1,87 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 文件 + /// + [Table("sys_uploadfile")] + public class UploadFile : BaseEntity, ICreationAudited + { + /// + /// + /// + public UploadFile() + { + Id = 0; + FileName = string.Empty; + FilePath = string.Empty; + Description = string.Empty; + FileType = string.Empty; + Extension = string.Empty; + SortCode = 0; + CreatedTime = DateTime.Now; + Thumbnail = string.Empty; + BelongApp = string.Empty; + BelongAppId = string.Empty; + IsDeleted = false; + } + + /// + /// 文件名称 + /// + public string FileName { get; set; } + + /// + /// 文件路径 + /// + public string FilePath { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 文件类型 + /// + public string FileType { get; set; } + + /// + /// 文件大小 + /// + public long FileSize { get; set; } + + /// + /// 扩展名称 + /// + public string Extension { get; set; } + + /// + /// 排序 + /// + public long SortCode { get; set; } + + /// + /// 有效标志 + /// + public virtual bool? IsEnabled { get; set; } + + /// + /// 缩略图 + /// + public string Thumbnail { get; set; } + + /// + /// 所属应用 + /// + public string BelongApp { get; set; } + + /// + /// 所属应用ID + /// + public string BelongAppId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/User.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/User.cs new file mode 100644 index 0000000..c0d7311 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/User.cs @@ -0,0 +1,65 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 用户表,数据实体对象 + /// + [Table("dc_user")] + [Serializable] + public class User : BaseEntity + { + /// + /// OpenId + /// + [Comment("OpenId")] + [Required, MaxLength(32)] + public string OpenId { get; set; } + + /// + /// 账号 + /// + public string Account { get; set; } + + /// + /// 密码 + /// + public string PassWord { get; set; } + + /// + /// 盐 + /// + public string Salt { get; set; } + + /// + /// 用户名 + /// + [Comment("用户名")] + [MaxLength(8)] + public string UserName { get; set; } + + /// + /// 头像 + /// + [Comment("头像")] + public string AvatarUrl { get; set; } + + /// + /// 电话 + /// + [Comment("电话")] + [MaxLength(11)] + public string Phone { get; set; } + + /// + /// 状态 + /// + [Comment("状态")] + [MaxLength(20)] + public long Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserExtend.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserExtend.cs new file mode 100644 index 0000000..00a2706 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserExtend.cs @@ -0,0 +1,133 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 用户表,数据实体对象 + /// + [Table("sys_userextend")] + [Serializable] + public class UserExtend : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public UserExtend() + { + } + + #region Property Members + + /// + /// 账户 + /// + public virtual long userId { get; set; } + + /// + /// 名片 + /// + public virtual string CardContent { get; set; } + + /// + /// 手机 + /// + public virtual string Telphone { get; set; } + + /// + /// 地址 + /// + public virtual string Address { get; set; } + + /// + /// 公司名称 + /// + public virtual string CompanyName { get; set; } + + /// + /// 职位 + /// + public virtual string PositionTitle { get; set; } + + /// + /// 微信二维码 + /// + public virtual string WeChatQrCode { get; set; } + + /// + /// 地区 + /// + public virtual string IndustryId { get; set; } + + /// + /// 公开情况 + /// + public virtual long OpenType { get; set; } + + /// + /// IsOtherShare + /// + [DataMember] + public virtual bool IsOtherShare { get; set; } + + /// + /// sharetitle + /// + [DataMember] + public virtual string ShareTitle { get; set; } + + /// + /// 主页 + /// + [DataMember] + public virtual string WebUrl { get; set; } + + /// + /// 公司简介 + /// + [DataMember] + public virtual string CompanyDesc { get; set; } + + /// + /// 主题 + /// + public virtual string CardTheme { get; set; } + + /// + /// VIP + /// + public virtual string VipGrade { get; set; } + + /// + /// 是否认证 + /// + public virtual bool IsAuthentication { get; set; } + + /// + /// 认证类型 + /// + public virtual long AuthenticationType { get; set; } + + /// + /// 有效标志 + /// + public virtual bool IsEnabled { get; set; } + + /// + /// 公司id + /// + [MaxLength(50)] + public virtual long CompanyId { get; set; } + + /// + /// 部门id + /// + [MaxLength(50)] + public virtual long DeptId { get; set; } + + #endregion Property Members + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserFocus.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserFocus.cs new file mode 100644 index 0000000..fe557e8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserFocus.cs @@ -0,0 +1,31 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 用户表,数据实体对象 + /// + [Table("sys_userfocus")] + [Serializable] + public class UserFocus : BaseEntity, ICreationAudited + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public UserFocus() + { + Id = 0; + } + + #region Property Members + + /// + /// 关注的用户ID + /// + public virtual string FocusUserId { get; set; } + + #endregion Property Members + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserNameCardView.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserNameCardView.cs new file mode 100644 index 0000000..3d28995 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserNameCardView.cs @@ -0,0 +1,181 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 用户表,数据实体对象 + /// + [Table("sys_vw_namecard")] + [Serializable] + [NotMapped] + public class UserNameCardView : BaseEntity + { + /// + /// 默认构造函数(需要初始化属性的在此处理) + /// + public UserNameCardView() + { + } + + #region Property Members + + /// + /// 用户id + /// + public virtual long userId { get; set; } + + /// + /// 名片详情 + /// + public virtual string CardContent { get; set; } + + /// + /// 电话 + /// + public virtual string Telphone { get; set; } + + /// + /// 地址 + /// + public virtual string Address { get; set; } + + /// + /// 公司名称 + /// + public virtual string CompanyName { get; set; } + + /// + /// 职位 + /// + public virtual string PositionTitle { get; set; } + + /// + /// 微信二维码 + /// + public virtual string WeChatQrCode { get; set; } + + /// + /// 行业代码 + /// + public virtual string IndustryId { get; set; } + + /// + /// 公开标识 + /// + public virtual long OpenType { get; set; } + + /// + /// IsOtherShare + /// + public virtual bool? IsOtherShare { get; set; } + + /// + /// ShareTitle + /// + public virtual string ShareTitle { get; set; } + + /// + /// 主页 + /// + public string WebUrl { get; set; } + + /// + /// 公司描述 + /// + public string CompanyDesc { get; set; } + + /// + /// 名片主题 + /// + public virtual string CardTheme { get; set; } + + /// + /// vip等级 + /// + public virtual string VipGrade { get; set; } + + /// + /// 是否认证 + /// + public virtual bool? IsAuthentication { get; set; } + + /// + /// 认证类型 + /// + public virtual long? AuthenticationType { get; set; } + + /// + /// 可以标识 + /// + public virtual bool? IsEnabled { get; set; } + + /// + /// 公司ID + /// + public virtual long CompanyId { get; set; } + + /// + /// 部门ID + /// + public virtual long DeptId { get; set; } + + /// + /// 真实名称 + /// + public virtual string RealName { get; set; } + + /// + /// 昵称 + /// + public virtual string UserName { get; set; } + + /// + /// 头像 + /// + public virtual string HeadIcon { get; set; } + + /// + /// 手机 + /// + public virtual string MobilePhone { get; set; } + + /// + /// Email + /// + public virtual string EMail { get; set; } + + /// + /// 微信 + /// + public virtual string WeChat { get; set; } + + /// + /// 国家 + /// + public virtual string Country { get; set; } + + /// + /// 省份 + /// + public virtual string Province { get; set; } + + /// + /// 城市 + /// + public virtual string City { get; set; } + + /// + /// 性别 + /// + public virtual string Gender { get; set; } + + /// + /// 用户主表id + /// + public virtual string MUserId { get; set; } + + #endregion Property Members + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserOpenIds.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserOpenIds.cs new file mode 100644 index 0000000..34dc0b5 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/UserOpenIds.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 第三方登录与用户绑定表,数据实体对象 + /// + [Table("sys_useropenids")] + public class UserOpenIds : BaseEntity + { + #region Property Members + + /// + /// 用户编号 + /// + public virtual long UserId { get; set; } + + /// + /// 第三方类型 + /// + public virtual string OpenIdType { get; set; } + + /// + /// OpenId + /// + public virtual string OpenId { get; set; } + + #endregion Property Members + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Vehicle.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Vehicle.cs new file mode 100644 index 0000000..3241c6f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/Vehicle.cs @@ -0,0 +1,176 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 公司表 + /// + [Table("dc_vehicle")] + [Comment("公司表")] + public class Vehicle : BaseEntity + { + /// + /// 所属公司 + /// + [Comment("所属公司")] + public long CompanyId { get; set; } + + /// + /// 车辆编号 + /// + [Comment("车辆编号")] + public string VehicleCode { get; set; } + + /// + /// 车牌号 + /// + [Comment("车牌号")] + public string VehiclePlate { get; set; } + + /// + /// 车辆类型 + /// + [Comment("车辆类型")] + public long VehicleType { get; set; } + + /// + /// 所属车组 + /// + [Comment("所属车组")] + public long VehicleGroup { get; set; } + + /// + /// 物联卡类型 + /// + [Comment("物联卡类型")] + public long CardType { get; set; } + + /// + /// SIM卡号 + /// + [Comment("SIM卡号")] + public string SimNo { get; set; } + + /// + /// 设备类型 + /// + [Comment("设备类型")] + public long TerminalType { get; set; } + + /// + /// 设备号 + /// + [Comment("设备号")] + public string TerminalNo { get; set; } + + /// + /// GPS协议号 + /// + [Comment("GPS协议号")] + public string AgreementNo { get; set; } + + /// + /// 是否激活 + /// + [Comment("是否激活")] + public bool IsActivate { get; set; } + + /// + /// 是否开启GPS + /// + [Comment("是否开启GPS")] + public bool IsGps { get; set; } + + /// + /// 所属司机 + /// + [Comment("所属司机")] + public long VehicleDriver { get; set; } + + /// + /// 司机电话 + /// + [Comment("司机电话")] + public string DriverPhone { get; set; } + + /// + /// 联系人 + /// + [Comment("联系人")] + public string ContactPerson { get; set; } + + /// + /// 联系电话 + /// + [Comment("联系电话")] + public string ContactPhone { get; set; } + + /// + /// 状态 + /// + [Comment("状态")] + public int Status { get; set; } + + /// + /// Gps状态 + /// + [Comment("Gps状态")] + public int GpsState { get; set; } + + /// + /// 打火状态 + /// + [Comment("打火状态")] + public int Acc { get; set; } + + /// + /// 工作状态 + /// + [Comment("工作状态")] + public int Work { get; set; } + + /// + /// Imei号 + /// + [Comment("Imei号")] + public string ImeiNo { get; set; } + + /// + /// GPS时间 + /// + [Comment("GPS时间")] + public DateTime? GpsTime { get; set; } + + /// + /// 开通时间 + /// + [Comment("开通时间")] + public DateTime OpenTime { get; set; } + + /// + /// 到期时间 + /// + [Comment("到期时间")] + public DateTime ExpireTime { get; set; } + + /// + /// 是否开启超速报警 + /// + [Comment("是否开启超速报警")] + public bool IsOverspeedAlarm { get; set; } + + /// + /// 超速速度 + /// + [Comment("超速速度")] + public int Overspeed { get; set; } + + /// + /// 排序 + /// + public int Sort { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleChange.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleChange.cs new file mode 100644 index 0000000..fb45387 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleChange.cs @@ -0,0 +1,81 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 车辆换装记录表 + /// + [Table("dc_vehicle_change")] + [Comment("车辆换装记录表")] + public class VehicleChange : BaseEntity + { + /// + /// 所属公司 + /// + [Comment("所属公司")] + public long CompanyId { get; set; } + + /// + /// 车辆Id + /// + [Comment("车辆Id")] + public long VehicleId { get; set; } + + /// + /// 物联卡类型 + /// + [Comment("物联卡类型")] + public long CardType { get; set; } + + /// + /// SIM卡号 + /// + [Comment("SIM卡号")] + public string SimNo { get; set; } + + /// + /// 设备类型 + /// + [Comment("设备类型")] + public long TerminalType { get; set; } + + /// + /// 设备号 + /// + [Comment("设备号")] + public string TerminalNo { get; set; } + + /// + /// Imei号 + /// + [Comment("Imei号")] + public string ImeiNo { get; set; } + + /// + /// GPS协议号 + /// + [Comment("GPS协议号")] + public string AgreementNo { get; set; } + + /// + /// 换卡日期 + /// + [Comment("换卡日期")] + public DateTime ChangeTime { get; set; } + + /// + /// 修改日期 + /// + [Comment("修改日期")] + public DateTime UpdateTime { get; set; } + + /// + /// 备注 + /// + [Comment("备注")] + public string Note { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleGroup.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleGroup.cs new file mode 100644 index 0000000..024f0ae --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleGroup.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 车辆表分组 + /// + [Table("dc_vehicle_group")] + [Comment("车辆表分组")] + public class VehicleGroup : BaseEntity + { + public new long Id { get; set; } + + /// + /// 公司Id + /// + [Comment("公司Id")] + public long CompanyId { get; set; } + + /// + /// 名称 + /// + [Comment("名称")] + public string Name { get; set; } + + /// + /// 父级权限Id + /// + [Comment("父级权限Id")] + public long ParentId { get; set; } + + /// + /// 状态(字典 0正常 1停用 2删除) + /// + [Comment("状态")] + public int Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleType.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleType.cs new file mode 100644 index 0000000..cfb4997 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/VehicleType.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + +namespace Znyc.Admin.Security.Entitys +{ + /// + /// 车辆类型表 + /// + [Table("dc_vehicle_type")] + [Comment("车辆类型表")] + public class VehicleType : BaseEntity + { + /// + /// 名称 + /// + [Comment("所属公司")] + public string Name { get; set; } + + /// + /// 父级权限Id + /// + [Comment("父级权限Id")] + public long ParentId { get; set; } + + /// + /// 父级权限Id + /// + [Comment("父级权限Id")] + public long CompanyId { get; set; } + + /// + /// 状态(字典 0正常 1停用 2删除) + /// + [Comment("状态")] + public int Status { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/WxUserRelation.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/WxUserRelation.cs new file mode 100644 index 0000000..33f0633 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Entitys/Dispatching/WxUserRelation.cs @@ -0,0 +1,38 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Znyc.Admin.Commons.Entitys; + + +namespace Znyc.Admin.Security.Entitys.Dispatching +{ + /// + /// 微信中间表 + /// + [Table("dc_wxuserrelation")] + public class WxUserRelation : BaseEntity + { + /// + /// UnionId + /// + + public string UnionId { get; set; } + + /// + /// OpenId + /// + + public string OpenId { get; set; } + + /// + /// 用户Id + /// + + public long UserId { get; set; } + + /// + /// 公众号OpenId + /// + + public string WxOfficialOpenId { get; set; } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAPPRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAPPRepository.cs new file mode 100644 index 0000000..9df74ce --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAPPRepository.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + /// + /// + /// + public interface IAPPRepository : IRepository + { + /// + /// ȡapp + /// + /// ӦID + /// ӦԿAppSecret + /// + APP GetAPP(string appid, string secret); + + /// + /// ȡapp + /// + /// ӦID + /// + APP GetAPP(string appid); + + /// + /// + /// + /// + IList SelectApp(); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAdminUserLogOnRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAdminUserLogOnRepository.cs new file mode 100644 index 0000000..39862a8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAdminUserLogOnRepository.cs @@ -0,0 +1,15 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IAdminUserLogOnRepository : IRepository + { + /// + /// ݻԱIDȡû¼Ϣʵ + /// + /// + /// + AdminUserLogOn GetByUserId(long userId); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAdminUserRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAdminUserRepository.cs new file mode 100644 index 0000000..89f0976 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAdminUserRepository.cs @@ -0,0 +1,108 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + /// + /// + /// + public interface IAdminUserRepository : IRepository + { + /// + /// û˺ŲѯûϢ + /// + /// + /// + Task GetByUserName(string userName); + + /// + /// ûֻѯûϢ + /// + /// ֻ + /// + Task GetUserByMobilePhone(string mobilePhone); + + /// + /// AccountֻŲѯûϢ + /// + /// ¼˺ + /// + Task GetUserByLogin(string account); + + /// + /// ݵOpenIdѯûϢ + /// + /// + /// OpenIdֵ + /// + AdminUser GetUserByOpenId(string openIdType, string openId); + + /// + /// ΢UnionIdѯûϢ + /// + /// UnionIdֵ + /// + AdminUser GetUserByUnionId(string unionId); + + /// + /// userIdѯûϢ + /// + /// + /// userId + /// + UserOpenIds GetUserOpenIdByuserId(string openIdType, long userId); + + /// + /// ûϢ,ƽ̨ + /// + /// + /// + /// + bool UpdateUserByOpenId(AdminUser entity, AdminUserLogOn userLogOnEntity, UserOpenIds userOpenIds, + IDbTransaction trans = null); + + /// + /// ûIDõƬϢ + /// + /// + /// + //UserNameCardOutPutDto GetUserNameCardInfo(long userId); + + /// + /// Ƭ + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ////bool SaveNameCard(long userId,string headicon, string UserName, string name, string company, string position, + // string weburl, string mobile, string email, string wx, string wximg, + // string industry, string area, string address, long openflag); + + /// + /// ûϢڹע + /// + /// + /// + /// + /// + IEnumerable GetUserAllListFocusByPage(string currentpage, + string pagesize, long userId); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IApiRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IApiRepository.cs new file mode 100644 index 0000000..deb2319 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IApiRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IApiRepository : IRepository + { + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAreaRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAreaRepository.cs new file mode 100644 index 0000000..f8f2294 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IAreaRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IAreaRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ICompanyRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ICompanyRepository.cs new file mode 100644 index 0000000..0c9bf4b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ICompanyRepository.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface ICompanyRepository : IRepository + { + /// + /// ˹˾״̬ + /// + /// + /// + /// + Task AuditAsync(long id, int status); + + /// + /// ޸Ĺ˾״̬ + /// + /// + /// + Task UpdateStatusAsync(long id, int status); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IDictionaryRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IDictionaryRepository.cs new file mode 100644 index 0000000..c7e2bfa --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IDictionaryRepository.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IDictionaryRepository : IRepository + { + /// + /// ݱѯֵ + /// + /// + /// + Task GetByEnCodAsynce(string enCode); + + /// + /// ʱжϷǷڣųԼ + /// + /// Id + /// + Task GetByEnCodAsynce(string enCode, long id); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogExRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogExRepository.cs new file mode 100644 index 0000000..132c762 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogExRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface ILogExRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogOpRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogOpRepository.cs new file mode 100644 index 0000000..bf75d66 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogOpRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface ILogOpRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogVisRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogVisRepository.cs new file mode 100644 index 0000000..ddec024 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ILogVisRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface ILogVisRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMenuRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMenuRepository.cs new file mode 100644 index 0000000..c28b96c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMenuRepository.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IMenuRepository : IRepository + { + /// + /// ݽɫIDַŷֿ)ϵͳIDȡӦIJб + /// + /// ɫID + /// ϵͳID + /// ǷDz˵ + /// + IEnumerable GetFunctions(string roleIds, string typeID, bool isMenu = false); + + /// + /// ϵͳIDȡӦIJб + /// + /// ϵͳID + /// + IEnumerable GetFunctions(string typeID); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMessageLogsRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMessageLogsRepository.cs new file mode 100644 index 0000000..c29a749 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMessageLogsRepository.cs @@ -0,0 +1,12 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + /// + /// + /// + public interface IMessageLogsRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMessageRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMessageRepository.cs new file mode 100644 index 0000000..c225375 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IMessageRepository.cs @@ -0,0 +1,12 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + /// + /// + /// + public interface IMessageRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IOrganizeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IOrganizeRepository.cs new file mode 100644 index 0000000..2be96ed --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IOrganizeRepository.cs @@ -0,0 +1,19 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + /// + /// ִ֯ӿ + /// õOrganizeҵ + /// + public interface IOrganizeRepository : IRepository + { + /// + /// ȡڵ֯ + /// + /// ֯Id + /// + Organize GetRootOrganize(long id); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleAuthorizeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleAuthorizeRepository.cs new file mode 100644 index 0000000..b2026ce --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleAuthorizeRepository.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IRoleAuthorizeRepository : IRepository + { + /// + /// ɫȨ + /// + /// ɫId + /// ɫģ + /// ɫɷ + /// + /// ִгɹtrueΪfalse + Task SaveRoleAuthorize(long roleId, List roleAuthorizesList, List roleDataList, + IDbTransaction trans = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleDataRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleDataRepository.cs new file mode 100644 index 0000000..b4a8200 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleDataRepository.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IRoleDataRepository : IRepository + { + /// + /// ݽɫȨʲ + /// + /// + /// + List GetListDeptByRole(string roleIds); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleRepository.cs new file mode 100644 index 0000000..7297b7c --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IRoleRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IRoleRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IStatisticalRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IStatisticalRepository.cs new file mode 100644 index 0000000..e937365 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IStatisticalRepository.cs @@ -0,0 +1,14 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + /// + /// + /// + public interface IStatisticalRepository : IRepository + { + Task GetStatisticalAsync(); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ISystemTypeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ISystemTypeRepository.cs new file mode 100644 index 0000000..9723c36 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/ISystemTypeRepository.cs @@ -0,0 +1,15 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface ISystemTypeRepository : IRepository + { + /// + /// 根据系统编码查询系统对象 + /// + /// 系统编码 + /// + SystemType GetByCode(string appkey); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IUploadFileRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IUploadFileRepository.cs new file mode 100644 index 0000000..c7976fd --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IUploadFileRepository.cs @@ -0,0 +1,20 @@ +using System.Data; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IUploadFileRepository : IRepository + { + /// + /// 根据应用Id和应用标识批量更新数据 + /// + /// 应用Id + /// 更新前旧的应用Id + /// 应用标识 + /// + /// + bool UpdateByBeLongAppId(string beLongAppId, string oldBeLongAppId, string belongApp = null, + IDbTransaction trans = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IUserRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IUserRepository.cs new file mode 100644 index 0000000..1d65507 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IUserRepository.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IUserRepository : IRepository + { + /// + /// ѯݿ,û󼯺(ڷҳʾ) + /// + /// ѯ + /// ҳʵ + /// ֶ + /// ʽ trueΪdescfalseΪasc + /// + /// ָļ + Task> UserPagerAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleChangeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleChangeRepository.cs new file mode 100644 index 0000000..d750778 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleChangeRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IVehicleChangeRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleGroupRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleGroupRepository.cs new file mode 100644 index 0000000..2399b63 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleGroupRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IVehicleGroupRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleRepository.cs new file mode 100644 index 0000000..1a9e9e5 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleRepository.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IVehicleRepository : IRepository + { + Task InsertVehicleAsync(Vehicle vehicle); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleTypeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleTypeRepository.cs new file mode 100644 index 0000000..493add8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IVehicleTypeRepository.cs @@ -0,0 +1,9 @@ +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IRepositories +{ + public interface IVehicleTypeRepository : IRepository + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IWxUserRelationRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IWxUserRelationRepository.cs new file mode 100644 index 0000000..531fbf2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IRepositories/Dispatching/IWxUserRelationRepository.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IRepositories; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.Entitys.Dispatching; + +namespace Znyc.Admin.Security.IRepositories +{ + /// + /// + /// + public interface IWxUserRelationRepository : IRepository + { + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAPPService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAPPService.cs new file mode 100644 index 0000000..f30adb4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAPPService.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IAPPService : IService + { + /// + /// ȡapp + /// + /// ӦID + /// ӦԿAppSecret + /// + APP GetAPP(string appid, string secret); + + /// + /// ȡapp + /// + /// ӦID + /// + APP GetAPP(string appid); + + /// + /// + /// + /// + IList SelectApp(); + + /// + /// ¿õӦõ + /// + void UpdateCacheAllowApp(); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAdminUserLogOnService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAdminUserLogOnService.cs new file mode 100644 index 0000000..2177080 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAdminUserLogOnService.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IAdminUserLogOnService : IService + { + /// + /// ݻԱIDȡû¼Ϣʵ + /// + /// ûId + /// + AdminUserLogOn GetByUserId(long userId); + + /// + /// ݻԱIDȡû¼Ϣʵ + /// + /// Ϣ + /// ûId + /// + Task SaveUserTheme(UserThemeInputDto info, long userId); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAdminUserService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAdminUserService.cs new file mode 100644 index 0000000..bd6097d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAdminUserService.cs @@ -0,0 +1,108 @@ +using System; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// ûӿ + /// + public interface IAdminUserService : IService + { + /// + /// û½֤ + /// + /// û + /// 루һmd5ܺ + /// ֤ɹûʵ壬֤ʧܷnull|ʾϢ + Task> Validate(string userName, string password); + + /// + /// û½֤ + /// + /// û + /// 루һmd5ܺ + /// û + /// ֤ɹûʵ壬֤ʧܷnull|ʾϢ + Task> Validate(string userName, string password, UserType userType); + + /// + /// û˺ŲѯûϢ + /// + /// + /// + Task GetByUserName(string userName); + + /// + /// ûֻѯûϢ + /// + /// ֻ + /// + Task GetUserByMobilePhone(string mobilePhone); + + /// + /// AccountֻŲѯûϢ + /// + /// ¼˺ + /// + Task GetUserByLogin(string account); + + /// + /// ݵOpenIdѯûϢ + /// + /// + /// OpenIdֵ + /// + AdminUser GetUserByOpenId(string openIdType, string openId); + + /// + /// ΢UnionIdѯûϢ + /// + /// UnionIdֵ + /// + AdminUser GetUserByUnionId(string unionId); + + /// + /// userIdѯûϢ + /// + /// + /// userId + /// + UserOpenIds GetUserOpenIdByuserId(string openIdType, long userId); + + /// + /// ûϢ,ƽ̨ + /// + /// + /// + /// + bool UpdateUserByOpenId(AdminUser entity, AdminUserLogOn userLogOnEntity, UserOpenIds userOpenIds, + IDbTransaction trans = null); + + /// + /// ΢עͨԱû + /// + /// + /// + bool CreateUserByWxOpenId(UserInputDto userInPut); + + /// + /// û + /// + /// + /// + bool UpdateUserByOpenId(UserInputDto userInPut); + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + Task> FindWithPagerSearchAsync(SearchUserModel search); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IApiService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IApiService.cs new file mode 100644 index 0000000..3f33701 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IApiService.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IApiService : IService + { + Task GetApiAsync(string apiUrl); + } +} + diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAreaService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAreaService.cs new file mode 100644 index 0000000..5f8d756 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IAreaService.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IAreaService : IService + { + #region uniappѡ + + /// + /// ȡпõĵuniappѡ + /// + /// + List GetAllByEnable(); + + /// + /// ȡʡС/õĵuniappѡ + /// + /// + List GetProvinceToAreaByEnable(); + + #endregion uniappѡ + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ICompanyService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ICompanyService.cs new file mode 100644 index 0000000..0f8f23b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ICompanyService.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface ICompanyService : IService + { + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 指定对象的集合 + Task> FindWithPagerSearchAsync(SearchUserModel search); + + /// + /// 审核公司状态 + /// + /// + /// + /// + Task AuditAsync(long id, int status); + + /// + /// 修改公司状态 + /// + /// + /// + /// + Task UpdateAsync(long id, int status); + + + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IDictionaryService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IDictionaryService.cs new file mode 100644 index 0000000..e768c32 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IDictionaryService.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IDictionaryService : IService + { + /// + /// ȡܲ˵Vue б + /// + /// + Task> GetAllItemsTreeTable(); + + /// + /// ݱѯֵ + /// + /// + /// + Task GetByEnCodAsynce(string enCode); + + /// + /// ʱжϷǷڣųԼ + /// + /// Id + /// + Task GetByEnCodAsynce(string enCode, long id); + + /// + /// ѯֵб + /// + /// + /// + /// + Task> GetDictionaryListByWhere(string ids, string code); + + /// + /// ѯֵ + /// + /// + /// + Task GetDictionaryById(long id); + + Task> FindWithPagerSearchAsync(SearchUserModel search); + + Task> SyncDictionaryCache(); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogExService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogExService.cs new file mode 100644 index 0000000..a27d175 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogExService.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// ־¼ + /// + public interface ILogExService : IService + { + /// + /// ϢдûIJ־¼ + /// Ҫдݿ־ + /// + /// + /// + /// ϸ + /// + bool OnOperationLog(string tableName, string operationType, string note); + + /// + /// ϢдûIJ־¼ + /// Ҫдģ־ + /// + /// ģ + /// + /// ϸ + /// û + /// + bool OnOperationLog(string module, string operationType, string note, AdminCurrentUser AdminCurrentUser); + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + Task> FindWithPagerSearchAsync(SearchExceptionsLogsModel search); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogOpService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogOpService.cs new file mode 100644 index 0000000..d6ad835 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogOpService.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// ־¼ + /// + public interface ILogOpService : IService + { + /// + /// ϢдûIJ־¼ + /// Ҫдݿ־ + /// + /// + /// + /// ϸ + /// + bool OnOperationLog(string tableName, string operationType, string note); + + /// + /// ϢдûIJ־¼ + /// Ҫдģ־ + /// + /// ģ + /// + /// ϸ + /// û + /// + bool OnOperationLog(string module, string operationType, string note, AdminCurrentUser AdminCurrentUser); + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + Task> FindWithPagerSearchAsync(SearchLogOpModel search); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogVisService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogVisService.cs new file mode 100644 index 0000000..41c527b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ILogVisService.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// ־¼ + /// + public interface ILogVisService : IService + { + /// + /// ϢдûIJ־¼ + /// Ҫдݿ־ + /// + /// + /// + /// ϸ + /// + bool OnOperationLog(string tableName, string operationType, string note); + + /// + /// ϢдûIJ־¼ + /// Ҫдģ־ + /// + /// ģ + /// + /// ϸ + /// û + /// + bool OnOperationLog(string module, string operationType, string note, AdminCurrentUser AdminCurrentUser); + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + Task> FindWithPagerSearchAsync(SearchDbLogsModel search); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMenuService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMenuService.cs new file mode 100644 index 0000000..2a48780 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMenuService.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.Dtos; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IMenuService : IService + { + /// + /// ûȡܲ˵ + /// + /// ûID + /// + List GetMenuByUser(long userId); + + /// + /// ȡܲ˵Vue б + /// + /// ϵͳId + /// + Task> GetAllMenuTreeTable(string systemTypeId); + + /// + /// ݽɫIDַŷֿ)ϵͳIDȡӦIJб + /// + /// ɫID + /// ϵͳID + /// ǷDz˵ + /// + List GetFunctions(string roleIds, string typeID, bool isMenu = false); + + /// + /// ϵͳIDȡӦIJб + /// + /// ϵͳID + /// + List GetFunctions(string typeID); + + /// + /// ݸܱѯӼܣҪҳťȨ + /// + /// ˵ܱ + /// + Task> GetListByParentEnCode(string enCode); + + /// + /// ɾ + /// + /// Id + /// + /// + CommonResult DeleteBatchWhere(DeletesInputDto ids, IDbTransaction trans = null); + + /// + /// 첽ɾ + /// + /// Id + /// + /// + Task DeleteBatchWhereAsync(DeletesInputDto ids, IDbTransaction trans = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMessageLogsService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMessageLogsService.cs new file mode 100644 index 0000000..f310aca --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMessageLogsService.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IMessageLogsService : IService + { + Task AddAsync(MessageInputDto input); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMessageService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMessageService.cs new file mode 100644 index 0000000..243f1ea --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IMessageService.cs @@ -0,0 +1,13 @@ +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IMessageService : IService + { + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IOrganizeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IOrganizeService.cs new file mode 100644 index 0000000..906b78f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IOrganizeService.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.Dtos; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// ֯ + /// + public interface IOrganizeService : IService + { + /// + /// ȡ֯Vue б + /// + /// + Task> GetAllOrganizeTreeTable(); + + /// + /// ȡڵ֯ + /// + /// ֯Id + /// + Organize GetRootOrganize(long id); + + /// + /// ɾ + /// + /// Id + /// + /// + CommonResult DeleteBatchWhere(DeletesInputDto ids, IDbTransaction trans = null); + + /// + /// 첽ɾ + /// + /// Id + /// + /// + Task DeleteBatchWhereAsync(DeletesInputDto ids, IDbTransaction trans = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleAuthorizeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleAuthorizeService.cs new file mode 100644 index 0000000..d520c53 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleAuthorizeService.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IRoleAuthorizeService : IService + { + /// + /// ݽɫĿͲѯȨ + /// + /// + /// + /// + IEnumerable GetListRoleAuthorizeByRoleId(string roleIds, string itemType); + + /// + /// ȡܲ˵Vue Tree + /// + /// + Task> GetAllFunctionTree(); + + /// + /// ɫȨ + /// + /// ɫId + /// ɫģ + /// ɫɷ + /// + /// ִгɹtrueΪfalse + Task SaveRoleAuthorize(long roleId, List roleAuthorizesList, List roleDataList, + IDbTransaction trans = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleDataService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleDataService.cs new file mode 100644 index 0000000..7a8d853 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleDataService.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IRoleDataService : IService + { + /// + /// ݽɫȨʲ + /// + /// + /// + List GetListDeptByRole(string roleIds); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleService.cs new file mode 100644 index 0000000..afbb452 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IRoleService.cs @@ -0,0 +1,33 @@ +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IRoleService : IService + { + /// + /// ݽɫȡɫ + /// + /// + /// + Role GetRole(string enCode); + + /// + /// ûɫIDȡɫ + /// + /// ɫIDַá,ָ + /// + string GetRoleEnCode(string ids); + + /// + /// ûɫIDȡɫ + /// + /// ɫIDַá,ָ + /// + string GetRoleNameStr(string ids); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IStatisticalService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IStatisticalService.cs new file mode 100644 index 0000000..24ae5fe --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IStatisticalService.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IStatisticalService : IService + { + Task> FindWithPagerSearchAsync(SearchUserModel search); + + /// + /// 첽 + /// + /// + Task InsertAsync(); + + Task GetStatisticalAsync(); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ISystemTypeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ISystemTypeService.cs new file mode 100644 index 0000000..ffe9383 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/ISystemTypeService.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// 子系统服务接口 + /// + public interface ISystemTypeService : IService + { + /// + /// 根据系统编码查询系统对象 + /// + /// 系统编码 + /// + SystemType GetByCode(string appkey); + + /// + /// 根据角色获取可以访问子系统 + /// + /// 角色Id,用','隔开 + /// + List GetSubSystemList(string roleIds); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IUploadFileService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IUploadFileService.cs new file mode 100644 index 0000000..4d18e92 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IUploadFileService.cs @@ -0,0 +1,21 @@ +using System.Data; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IUploadFileService : IService + { + /// + /// 根据应用Id和应用标识批量更新数据 + /// + /// 应用Id + /// 更新前旧的应用Id + /// 应用标识 + /// + /// + bool UpdateByBeLongAppId(string beLongAppId, string oldBeLongAppId, string belongApp = null, + IDbTransaction trans = null); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IUserService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IUserService.cs new file mode 100644 index 0000000..0985a48 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IUserService.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IUserService : IService + { + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 指定对象的集合 + Task> FindWithPagerSearchAsync(SearchUserModel search); + + /// + /// 修改用户状态 + /// + /// + /// + /// + Task UpdateStatusAsync(long id, int status); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IVehicleChangeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IVehicleChangeService.cs new file mode 100644 index 0000000..6343f32 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IVehicleChangeService.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IVehicleChangeService : IService + { + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 指定对象的集合 + Task> FindWithPagerSearchAsync(SearchVehicleChangeModel search); + + /// + /// 新增车辆换装记录 + /// + /// + /// + Task InsertAsync(VehicleChange entity); + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IVehicleService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IVehicleService.cs new file mode 100644 index 0000000..ea23b48 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IVehicleService.cs @@ -0,0 +1,57 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.Security.IServices +{ + public interface IVehicleService : IService + { + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 指定对象的集合 + Task> FindWithPagerSearchAsync(SearchVehicleModel search); + + /// + /// 新增车辆信息 + /// + /// + /// + Task InsertAsync(Vehicle entity); + + /// + /// 修改车辆信息 + /// + /// + /// + Task UpdateAsync(Vehicle tinfo); + + /// + /// 修改车辆状态 + /// + /// + /// 状态 + /// + Task UpdateStatusAsync(long id, int status); + + /// + /// 修改车辆是否激活 + /// + /// + /// 状态 + /// + Task UpdateIsActivateAsync(long id, bool isActivate); + + /// + /// 修改车辆是否开启GPS + /// + /// + /// 状态 + /// + Task UpdateIsGpsAsync(long id, bool isGps); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IWxUserRelationService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IWxUserRelationService.cs new file mode 100644 index 0000000..10391e6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/IServices/Dispatching/IWxUserRelationService.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.IServices; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Dtos.WxUserRelation; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.Entitys.Dispatching; + +namespace Znyc.Admin.Security.IServices +{ + /// + /// + /// + public interface IWxUserRelationService : IService + { + /// + /// + /// + /// + /// + Task UpdateAsync(string wxOpenId); + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/APPRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/APPRepository.cs new file mode 100644 index 0000000..ea4dcd3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/APPRepository.cs @@ -0,0 +1,59 @@ +using Dapper; +using System.Collections.Generic; +using System.Linq; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// Ӧòִʵ + /// + public class APPRepository : BaseRepository, IAPPRepository + { + public APPRepository() + { + } + + public APPRepository(IDbContextCore context) : base(context) + { + } + + /// + /// ȡapp + /// + /// ӦID + /// ӦԿAppSecret + /// + public APP GetAPP(string appid, string secret) + { + string sql = @"SELECT * FROM sys_app t WHERE t.AppId = @AppId and AppSecret=@AppSecret and IsDeleted=0"; + return DapperConnRead.QueryFirstOrDefault(sql, new { AppId = appid, AppSecret = secret }); + } + + /// + /// ȡapp + /// + /// ӦID + /// + public APP GetAPP(string appid) + { + string sql = @"SELECT * FROM sys_app t WHERE t.AppId = @AppId and IsDeleted=0"; + return DapperConnRead.QueryFirstOrDefault(sql, new { AppId = appid }); + } + + public IList SelectApp() + { + const string query = + @"select a.*,u.id as Id,u.UserName,u.Account,u.HeadIcon from sys_app a,sys_adminuser u where a.CreatedUserId=u.Id "; + return DapperConnRead.Query(query, (app, user) => + { + app.UserInfo = user; + return app; + }, null, splitOn: "Id").ToList(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AdminUserLogOnRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AdminUserLogOnRepository.cs new file mode 100644 index 0000000..4fe1d15 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AdminUserLogOnRepository.cs @@ -0,0 +1,30 @@ +using Dapper; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class AdminUserLogOnRepository : BaseRepository, IAdminUserLogOnRepository + { + public AdminUserLogOnRepository() + { + } + + public AdminUserLogOnRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ݻԱIDȡû¼Ϣʵ + /// + /// + /// + public AdminUserLogOn GetByUserId(long userId) + { + string sql = @"SELECT * FROM sys_adminuser_logon t WHERE t.AdminUserId = @UserId"; + return DapperConn.QueryFirstOrDefault(sql, new { UserId = userId }); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AdminUserRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AdminUserRepository.cs new file mode 100644 index 0000000..2c3a64e --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AdminUserRepository.cs @@ -0,0 +1,188 @@ +using Dapper; +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// Ӧòִʵ + /// + public class AdminUserRepository : BaseRepository, IAdminUserRepository + { + public AdminUserRepository() + { + } + + public AdminUserRepository(IDbContextCore context) : base(context) + { + } + + /// + /// û˺ŲѯûϢ + /// + /// + /// + public async Task GetByUserName(string userName) + { + string sql = @"SELECT * FROM sys_adminuser t WHERE t.Account = @UserName"; + return await DapperConn.QueryFirstOrDefaultAsync(sql, new { @UserName = userName }); + } + + /// + /// ûֻѯûϢ + /// + /// ֻ + /// + public async Task GetUserByMobilePhone(string mobilephone) + { + string sql = @"SELECT * FROM sys_adminuser t WHERE t.MobilePhone = @MobilePhone"; + return await DapperConn.QueryFirstOrDefaultAsync(sql, new { @MobilePhone = mobilephone }); + } + + /// + /// EmailAccountֻŲѯûϢ + /// + /// ¼˺ + /// + public async Task GetUserByLogin(string account) + { + string sql = + @"SELECT * FROM sys_adminuser t WHERE (t.Account = @Account or t.MobilePhone = @Account)"; + return await DapperConn.QueryFirstOrDefaultAsync(sql, new { @Account = account }); + } + + /// + /// ΢UnionIdѯûϢ + /// + /// UnionIdֵ + /// + public AdminUser GetUserByUnionId(string unionId) + { + string sql = string.Format("select * from sys_adminuser where UnionId = '{0}'", unionId); + return DapperConn.QueryFirstOrDefault(sql); + } + + /// + /// ݵOpenIdѯûϢ + /// + /// + /// OpenIdֵ + /// + public AdminUser GetUserByOpenId(string openIdType, string openId) + { + string sql = string.Format( + "select * from sys_adminuser as u join sys_adminuserOpenIds as o on u.Id = o.UserId and o.OpenIdType = '{0}' and o.OpenId = '{1}'", + openIdType, openId); + return DapperConn.QueryFirstOrDefault(sql); + } + + /// + /// userIdѯûϢ + /// + /// + /// userId + /// + public UserOpenIds GetUserOpenIdByuserId(string openIdType, long userId) + { + string sql = string.Format("select * from sys_adminuserOpenIds where OpenIdType = '{0}' and UserId = '{1}'", + openIdType, userId); + return DapperConn.QueryFirstOrDefault(sql); + } + + /// + /// ûϢ,ƽ̨ + /// + /// + /// + /// + public bool UpdateUserByOpenId(AdminUser entity, AdminUserLogOn userLogOnEntity, UserOpenIds userOpenIds, + IDbTransaction trans = null) + { + DbContext.GetDbSet().Add(entity); + DbContext.GetDbSet().Add(userOpenIds); + return DbContext.SaveChanges() > 0; + } + + /// + /// ҳõûڹע + /// + /// + /// + /// + /// + public IEnumerable GetUserAllListFocusByPage(string currentpage, + string pagesize, long userId) + { + string sqlRecord = ""; + string sql = ""; + + long countNotIn = (long.Parse(currentpage) - 1) * long.Parse(pagesize); + + sqlRecord = @"select * from sys_adminuser where UserName <> 'ο' and ismember=1 "; + + sql = @"SELECT TOP " + pagesize + + @" +case when t2.Id is null then 'n' +else 'y' end as IfFocus , +IsNull(t3.totalFocus,0) as TotalFocus, +t1.* +from +(select ISNULL(tin2.VipGrade,0) as VipGrade, +ISNULL(tin2.IsAuthentication,0) as IsAuthentication, +ISNULL(tin2.AuthenticationType,0) as AuthenticationType, +tin1.* from sys_adminuser tin1 +left join sys_adminuserExtend tin2 on tin1.Id=tin2.UserId +where UserName <> 'ο' and ismember=1) t1 +left join +(select * from sys_adminuserFocus where CreatedUserId='" + userId + @"') t2 +on t1.id=t2.focususerid +left join +(select top 100 percent focusUserID,count(*) as totalFocus from sys_adminuserFocus group by focusUserID order by totalfocus desc) t3 +on t1.Id=t3.focusUserID + +where t1.Id not in +( +select top " + countNotIn + @" +tt1.Id +from +(select ISNULL(tin2.VipGrade,0) as VipGrade, +ISNULL(tin2.IsAuthentication,0) as IsAuthentication, +ISNULL(tin2.AuthenticationType,0) as AuthenticationType, +tin1.* from sys_adminuser tin1 +left join sys_adminuserExtend tin2 on tin1.Id=tin2.UserId +where UserName <> 'ο' and ismember=1) tt1 +left join +(select * from sys_adminuserFocus where CreatedUserId='" + userId + @"') tt2 +on tt1.id=tt2.focususerid +left join +(select top 100 percent focusUserID,count(*) as totalFocus from sys_adminuserFocus group by focusUserID order by totalfocus desc) tt3 +on tt1.Id=tt3.focusUserID + +order by tt3.totalFocus desc +) + +order by t3.totalFocus desc"; + + List list = new List(); + + IEnumerable infoOutputDto = DapperConn.Query(sql); + + //õܼ¼ + List recordCountList = DapperConn.Query(sqlRecord).AsList(); + + list = infoOutputDto.AsList(); + for (int i = 0; i < list.Count; i++) + { + list[i].RecordCount = recordCountList.Count; + } + + return list; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/ApiRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/ApiRepository.cs new file mode 100644 index 0000000..c22a6b9 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/ApiRepository.cs @@ -0,0 +1,18 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class ApiRepository : BaseRepository, IApiRepository + { + public ApiRepository() + { + } + + public ApiRepository(IDbContextCore context) : base(context) + { + } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AreaRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AreaRepository.cs new file mode 100644 index 0000000..9fb35e6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/AreaRepository.cs @@ -0,0 +1,18 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class AreaRepository : BaseRepository, IAreaRepository + { + public AreaRepository() + { + } + + public AreaRepository(IDbContextCore dbContext) : base(dbContext) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/CompanyRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/CompanyRepository.cs new file mode 100644 index 0000000..cdec44a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/CompanyRepository.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class CompanyRepository : BaseRepository, ICompanyRepository + { + public CompanyRepository() + { + } + + public CompanyRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ˹˾״̬ + /// + /// + /// + /// + public async Task AuditAsync(long id, int status) + { + string sql = string.Format("UPDATE dc_company SET Status={0},AuditTime=NOW(),ModifiedTime=NOW() WHERE Id={1}", + status, id); + return await DbContext.ExecuteSqlWithNonQueryAsync(sql) > 0; + } + + /// + /// ޸Ĺ˾״̬ + /// + /// + /// + /// + public async Task UpdateStatusAsync(long id, int status) + { + string sql = string.Format("UPDATE dc_company SET Status={0},ModifiedTime=NOW() WHERE Id={1}", + status, id); + return await DbContext.ExecuteSqlWithNonQueryAsync(sql) > 0; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/DictionaryRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/DictionaryRepository.cs new file mode 100644 index 0000000..7d60115 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/DictionaryRepository.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class DictionaryRepository : BaseRepository, IDictionaryRepository + { + public DictionaryRepository() + { + } + + public DictionaryRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ݱѯֵ + /// + /// + /// + public async Task GetByEnCodAsynce(string enCode) + { + return await DbContext.GetSingleOrDefaultAsync(u => u.Code == enCode); + } + + /// + /// ʱжϷǷڣųԼ + /// + /// Id + /// + public async Task GetByEnCodAsynce(string enCode, long id) + { + return await DbContext.GetSingleOrDefaultAsync(u => u.Code == enCode && u.Id != id); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogExRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogExRepository.cs new file mode 100644 index 0000000..39e650a --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogExRepository.cs @@ -0,0 +1,28 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// ־ִʵ + /// + public class LogExRepository : BaseRepository, ILogExRepository + { + /// + /// + /// + public LogExRepository() + { + } + + /// + /// + /// + /// + public LogExRepository(IDbContextCore dbContext) : base(dbContext) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogOpRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogOpRepository.cs new file mode 100644 index 0000000..85e69ed --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogOpRepository.cs @@ -0,0 +1,28 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// ־ִʵ + /// + public class LogOpRepository : BaseRepository, ILogOpRepository + { + /// + /// + /// + public LogOpRepository() + { + } + + /// + /// + /// + /// + public LogOpRepository(IDbContextCore dbContext) : base(dbContext) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogVisRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogVisRepository.cs new file mode 100644 index 0000000..b5a3033 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/LogVisRepository.cs @@ -0,0 +1,28 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// ־ִʵ + /// + public class LogVisRepository : BaseRepository, ILogVisRepository + { + /// + /// + /// + public LogVisRepository() + { + } + + /// + /// + /// + /// + public LogVisRepository(IDbContextCore dbContext) : base(dbContext) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MenuRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MenuRepository.cs new file mode 100644 index 0000000..f8c94e2 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MenuRepository.cs @@ -0,0 +1,66 @@ +using Dapper; +using System.Collections.Generic; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class MenuRepository : BaseRepository, IMenuRepository + { + public MenuRepository() + { + } + + public MenuRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ݽɫIDַŷֿ)ϵͳIDȡӦIJб + /// + /// ɫID + /// ϵͳID + /// ǷDz˵ + /// + public IEnumerable GetFunctions(string roleIds, string typeID, bool isMenu = false) + { + string sql = + $"SELECT DISTINCT b.* FROM sys_menu as b INNER JOIN Sys_RoleAuthorize as a On b.Id = a.ItemId WHERE ObjectId IN (" + + roleIds + ")"; + if (roleIds == "") + { + sql = $"SELECT DISTINCT b.* FROM sys_menu as b where 1=1 "; + } + + if (isMenu) + { + sql = sql + "and menutype in('M','C')"; + } + + if (!string.IsNullOrEmpty(typeID)) + { + sql = sql + string.Format(" AND SystemTypeId='{0}' ", typeID); + } + + return DapperConnRead.Query(sql); + } + + /// + /// ϵͳIDȡӦIJб + /// + /// ϵͳID + /// + public IEnumerable GetFunctions(string typeID) + { + string sql = $"SELECT DISTINCT b.* FROM sys_menu as b "; + if (!string.IsNullOrEmpty(typeID)) + { + sql = sql + string.Format(" Where SystemTypeId='{0}' ", typeID); + } + + return DapperConnRead.Query(sql); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MessageLogsRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MessageLogsRepository.cs new file mode 100644 index 0000000..a0585f1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MessageLogsRepository.cs @@ -0,0 +1,21 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// Ӧòִʵ + /// + public class MessageLogsRepository : BaseRepository, IMessageLogsRepository + { + public MessageLogsRepository() + { + } + + public MessageLogsRepository(IDbContextCore context) : base(context) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MessageRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MessageRepository.cs new file mode 100644 index 0000000..f0c028d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/MessageRepository.cs @@ -0,0 +1,40 @@ +using Dapper; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// Ӧòִʵ + /// + public class MessageRepository : BaseRepository, IMessageRepository + { + public MessageRepository() + { + } + + public MessageRepository(IDbContextCore context) : base(context) + { + } + + /// + /// Ϣ + /// + /// + public async Task InsertAsync(Message entity) + { + string sql = string.Format( + @"INSERT INTO `rm_message`(`CreatedUserId`, `CreatedTime`, `IsDeleted`, `SendId`, `Type`, `GroupId`, + `Content`, `SendTime`, `ProductId`, `Title`, `MessageTitle`, `ProductType`) VALUES + ({0}, now(), 0, {1},{2},{3}, '{4}', now(),'{5}'); SELECT LAST_INSERT_ID();", + entity.SendId, entity.SendId, entity.Type, entity.GroupId, entity.Content, + entity.MessageTitle); + //var input= await DapperConn.QueryFirstOrDefaultAsync(sql); + long input = await DapperConn.ExecuteScalarAsync(sql, entity); + return input; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/OrganizeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/OrganizeRepository.cs new file mode 100644 index 0000000..40e6c04 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/OrganizeRepository.cs @@ -0,0 +1,43 @@ +using Dapper; +using System.Text; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class OrganizeRepository : BaseRepository, IOrganizeRepository + { + public OrganizeRepository() + { + } + + public OrganizeRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ȡڵ֯ + /// + /// ֯Id + /// + public Organize GetRootOrganize(long id) + { + StringBuilder sb = new StringBuilder(";WITH "); + if (dbConnectionOptions.DatabaseType == DatabaseType.MySql) + { + sb.Append(" Recursive "); + } + + sb.Append(" T AS ("); + sb.Append(" SELECT Id, ParentId, FullName, Layers FROM sys_organize"); + sb.AppendFormat(" WHERE Id = '{0}'", id); + sb.Append(" UNION ALL "); + sb.Append( + " SELECT A.Id, A.ParentId, A.FullName, A.Layers FROM sys_organize AS A JOIN T AS B ON A.Id = B.ParentId ) SELECT* FROM T ORDER BY Layers"); + return DapperConn.QueryFirstOrDefault(sb.ToString()); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleAuthorizeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleAuthorizeRepository.cs new file mode 100644 index 0000000..7c7d987 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleAuthorizeRepository.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class RoleAuthorizeRepository : BaseRepository, IRoleAuthorizeRepository + { + public RoleAuthorizeRepository() + { + } + + public RoleAuthorizeRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ɫȨ + /// + /// ɫId + /// ɫģ + /// ɫɷ + /// + /// ִгɹtrueΪfalse + public async Task SaveRoleAuthorize(long roleId, List roleAuthorizesList, + List roleDataList, + IDbTransaction trans = null) + { + List> param = new List>(); + Tuple tupel; + tupel = new Tuple(@"delete from Sys_RoleAuthorize where ObjectId=@RoleId;", + new { RoleId = roleId }); + param.Add(tupel); + tupel = new Tuple(@"delete from Sys_RoleData where RoleId=@RoleId;", new { RoleId = roleId }); + param.Add(tupel); + foreach (RoleAuthorize item in roleAuthorizesList) + { + tupel = new Tuple(@" INSERT INTO Sys_RoleAuthorize + (Id + ,ItemType + ,ItemId + ,ObjectType + ,ObjectId + ,SortCode + ,CreatedTime + ,CreatedUserId) + VALUES(@Id + ,@ItemType + ,@ItemId + ,@ObjectType + ,@ObjectId + ,@SortCode + ,@CreatedTime + ,@CreatedUserId) ", new + { + Id = item.Id, + ItemType = item.ItemType, + ItemId = item.ItemId, + ObjectType = item.ObjectType, + ObjectId = item.ObjectId, + SortCode = item.SortCode, + CreatedTime = item.CreatedTime, + CreatedUserId = item.CreatedUserId + }); + param.Add(tupel); + } + + foreach (RoleData roleData in roleDataList) + { + tupel = new Tuple(@" INSERT INTO Sys_RoleData + (Id + ,RoleId + ,AuthorizeData + ,DType) + VALUES + (@Id + ,@RoleId + ,@AuthorizeData + ,@DType) ", new + { + Id = roleData.Id, + RoleId = roleData.RoleId, + AuthorizeData = roleData.AuthorizeData, + DType = roleData.DType + }); + param.Add(tupel); + } + + Tuple result = await ExecuteTransactionAsync(param); + return result.Item1; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleDataRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleDataRepository.cs new file mode 100644 index 0000000..482abd1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleDataRepository.cs @@ -0,0 +1,50 @@ +using Dapper; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class RoleDataRepository : BaseRepository, IRoleDataRepository + { + public RoleDataRepository() + { + } + + public RoleDataRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ݽɫȨʲ + /// + /// + /// + public List GetListDeptByRole(string roleIds) + { + string roleIDsStr = string.Format("'{0}'", roleIds.Replace(",", "','")); + string where = " RoleId in(" + roleIDsStr + ") and DType='dept'"; + string sql = $"select AuthorizeData from {tableName} "; + if (!string.IsNullOrWhiteSpace(where)) + { + sql += " where " + @where; + } + + using (IDbConnection connection = DapperConn) + { + bool isClosed = connection.State == ConnectionState.Closed; + if (isClosed) + { + connection.Open(); + } + + IEnumerable resultList = connection.Query(sql); + return resultList.ToList(); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleRepository.cs new file mode 100644 index 0000000..2cf4aae --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/RoleRepository.cs @@ -0,0 +1,18 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class RoleRepository : BaseRepository, IRoleRepository + { + public RoleRepository() + { + } + + public RoleRepository(IDbContextCore dbContext) : base(dbContext) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/StatisticalRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/StatisticalRepository.cs new file mode 100644 index 0000000..4c4d2f8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/StatisticalRepository.cs @@ -0,0 +1,36 @@ +using Dapper; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// + /// + public class StatisticalRepository : BaseRepository, IStatisticalRepository + { + /// + /// + /// + public StatisticalRepository() + { + } + + public StatisticalRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ȡǰһͳ + /// + /// + public async Task GetStatisticalAsync() + { + string sql = @"SELECT * FROM sys_statistical ORDER BY CreatedTime DESC"; + return await DapperConn.QueryFirstOrDefaultAsync(sql); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/SystemTypeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/SystemTypeRepository.cs new file mode 100644 index 0000000..709d5ed --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/SystemTypeRepository.cs @@ -0,0 +1,33 @@ +using Dapper; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + /// + /// 系统类型,也是子系统 + /// + public class SystemTypeRepository : BaseRepository, ISystemTypeRepository + { + public SystemTypeRepository() + { + } + + public SystemTypeRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// 根据系统编码查询系统对象 + /// + /// 系统编码 + /// + public SystemType GetByCode(string appkey) + { + string sql = @"SELECT * FROM " + tableName + " t WHERE t.EnCode = @EnCode"; + return DapperConn.QueryFirstOrDefault(sql, new { EnCode = appkey }); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/UploadFileRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/UploadFileRepository.cs new file mode 100644 index 0000000..ea7787d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/UploadFileRepository.cs @@ -0,0 +1,53 @@ +using Dapper; +using System; +using System.Data; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class UploadFileRepository : BaseRepository, IUploadFileRepository + { + public UploadFileRepository() + { + } + + public UploadFileRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// 根据应用Id和应用标识批量更新数据 + /// + /// 更新后的应用Id + /// 更新前旧的应用Id + /// 应用标识 + /// + /// + public bool UpdateByBeLongAppId(string beLongAppId, string oldBeLongAppId, string belongApp = null, + IDbTransaction trans = null) + { + try + { + trans = DapperConn.BeginTransaction(); + string sqlStr = string.Format("update {0} set beLongAppId='{1}' where beLongAppId='{2}'", tableName, + beLongAppId, oldBeLongAppId); + if (!string.IsNullOrEmpty(belongApp)) + { + sqlStr = string.Format(" and BelongApp='{0}'", belongApp); + } + + long num = DapperConn.Execute(sqlStr, null, trans); + trans.Commit(); + return num >= 0; + } + catch (Exception) + { + trans.Rollback(); + throw; + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/UserRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/UserRepository.cs new file mode 100644 index 0000000..394a25b --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/UserRepository.cs @@ -0,0 +1,101 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using static Dapper.SqlMapper; + +namespace Znyc.Admin.Security.Repositories +{ + public class UserRepository : BaseRepository, IUserRepository + { + public UserRepository() + { + } + + public UserRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + /// + /// ݻԱIDȡû¼Ϣʵ + /// + /// + /// + public AdminUserLogOn GetByUserId(long userId) + { + string sql = @"SELECT * FROM sys_adminuser_logon t WHERE t.UserId = @UserId"; + return DapperConn.QueryFirstOrDefault(sql, new { UserId = userId }); + } + + + /// + /// ѯݿ,û󼯺(ڷҳʾ) + /// + /// ѯ + /// ҳʵ + /// ֶ + /// ʽ trueΪdescfalseΪasc + /// + /// ָļ + public virtual async Task> UserPagerAsync(string condition, PagerInfo info, string fieldToSort, + bool desc, IDbTransaction trans = null) + { + List list = new List(); + + if (HasInjectionData(condition)) + { + Log4NetHelper.Info(string.Format("SQLעĶ, {0}", condition)); + throw new Exception("SQLעĶ"); + } + + if (string.IsNullOrEmpty(condition)) + { + condition = "1=1"; + } + + PagerHelper pagerHelper = new PagerHelper(tableName, selectedFields, fieldToSort, info.PageSize, + info.CurrenetPageIndex, desc, condition); + + string sql = ""; + if (string.IsNullOrEmpty(condition)) + { + condition = " (1=1) "; + } + + //ִͳ + + sql = string.Format("SELECT count(u.Id) AS Total from dc_user u "+ + "INNER JOIN dc_employee e ON u.Id = e.UserId "+ + "INNER JOIN dc_company c on e.CompanyId = c.Id "+ + "WHERE u.IsDeleted = 0 AND e.`Status`= 1 AND c.`Status`= 1 and {0}",condition); + + //SELECT * FROM LIMIT M,N + string strOrder = string.Format(" order by u.{0} {1}", fieldToSort, isDescending ? "DESC" : "ASC"); + + int minRow = info.PageSize * (info.CurrenetPageIndex - 1); + int maxRow = info.PageSize * info.CurrenetPageIndex; + sql += string.Format(";"+ + "SELECT u.Id,u.AvatarUrl,u.UserName,u.Phone,u.`Status`,e.CompanyId,e.RoleName,c.CompanyName,u.CreatedTime FROM dc_user u "+ + "INNER JOIN dc_employee e ON u.Id = e.UserId "+ + "INNER JOIN dc_company c ON e.CompanyId = c.Id "+ + "WHERE u.IsDeleted = 0 AND e.`Status`= 1 AND c.`Status`= 1 and {0} {1} limit {2},{3};", + condition, strOrder, minRow, info.PageSize); + + + //return sql; + + GridReader reader = await DapperConnRead.QueryMultipleAsync(sql); + info.RecordCount = reader.ReadFirst(); + list = reader.Read().AsList(); + return list; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleChangeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleChangeRepository.cs new file mode 100644 index 0000000..3033188 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleChangeRepository.cs @@ -0,0 +1,20 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class VehicleChangeRepository : BaseRepository, IVehicleChangeRepository + { + public VehicleChangeRepository() + { + } + + public VehicleChangeRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleGroupRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleGroupRepository.cs new file mode 100644 index 0000000..c7f1f72 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleGroupRepository.cs @@ -0,0 +1,18 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class VehicleGroupRepository : BaseRepository, IVehicleGroupRepository + { + public VehicleGroupRepository() + { + } + + public VehicleGroupRepository(IDbContextCore dbContext) : base(dbContext) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleRepository.cs new file mode 100644 index 0000000..94bd2ca --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleRepository.cs @@ -0,0 +1,36 @@ +using Dapper; +using System.Threading.Tasks; +using Yitter.IdGenerator; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class VehicleRepository : BaseRepository, IVehicleRepository + { + public VehicleRepository() + { + } + + public VehicleRepository(IDbContextCore dbContext) : base(dbContext) + { + } + + public async Task InsertVehicleAsync(Vehicle vehicle) + { + vehicle.Id = YitIdHelper.NextId(); + //string sql = string.Format(@"INSERT INTO dc_vehicle + // (Id,CompanyId,VehicleCode,VehiclePlate,VehicleType,VehicleGroup,CardType,SimNo,TerminalType,TerminalNo,IsActivate,IsGps,VehicleDriver,DriverPhone + // ,ContactPhone,ContactPerson,Status,GpsState,Acc,`Work`,IemlNo,GpsTime,OpenTime,ExpireTime) VALUES + // ({0},157463753162821,'z02','A888888',1,1,3,'',1,'',1,1,0,'', + // '', 'ϵ', 1, 0, 0, 0, '', '1990-01-01 00:00:00', NOW(), NOW()); ",vehicle.Id); + DbContext.GetDbSet().Add(vehicle); + await DbContext.SaveChangesAsync(); + string sql = string.Format("select * from dc_vehicle where CompanyId = '{0}' and VehiclePlate = '{1}' and VehicleCode='{2}'", + vehicle.CompanyId, vehicle.VehiclePlate, vehicle.VehicleCode); + return DapperConn.QueryFirstOrDefault(sql); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleTypeRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleTypeRepository.cs new file mode 100644 index 0000000..e5aa144 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/VehicleTypeRepository.cs @@ -0,0 +1,18 @@ +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; + +namespace Znyc.Admin.Security.Repositories +{ + public class VehicleTypeRepository : BaseRepository, IVehicleTypeRepository + { + public VehicleTypeRepository() + { + } + + public VehicleTypeRepository(IDbContextCore dbContext) : base(dbContext) + { + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/WxUserRelationRepository.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/WxUserRelationRepository.cs new file mode 100644 index 0000000..a872531 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Repositories/Dispatching/WxUserRelationRepository.cs @@ -0,0 +1,30 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Repositories; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.Entitys.Dispatching; +using Znyc.Admin.Security.IRepositories; +using static Dapper.SqlMapper; + +namespace Znyc.Admin.Security.Repositories +{ + public class WxUserRelationRepository: BaseRepository, IWxUserRelationRepository + { + public WxUserRelationRepository() + { + + } + + public WxUserRelationRepository(IDbContextCore dbContext) : base(dbContext) + { + + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/APPService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/APPService.cs new file mode 100644 index 0000000..939f711 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/APPService.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class APPService : BaseService, IAPPService + { + private readonly IAPPRepository _appRepository; + + public APPService(IAPPRepository repository) : base(repository) + { + _appRepository = repository; + } + + /// + /// ͬʵ塣 + /// + /// ʵ + /// + /// + public override long Insert(APP entity, IDbTransaction trans = null) + { + long result = repository.Insert(entity, trans); + UpdateCacheAllowApp(); + return result; + } + + /// + /// 첽ʵ塣 + /// + /// ʵ + /// ID + /// + /// + public override async Task UpdateAsync(APP entity, long id, IDbTransaction trans = null) + { + bool result = await repository.UpdateAsync(entity, id, trans); + UpdateCacheAllowApp(); + return result; + } + + /// + /// 첽ʵ塣 + /// + /// ʵ + /// + /// + public override async Task InsertAsync(APP entity, IDbTransaction trans = null) + { + int result = await repository.InsertAsync(entity, trans); + UpdateCacheAllowApp(); + return result; + } + + /// + /// ȡapp + /// + /// ӦID + /// ӦԿAppSecret + /// + public APP GetAPP(string appid, string secret) + { + return _appRepository.GetAPP(appid, secret); + } + + /// + /// ȡapp + /// + /// ӦID + /// + public APP GetAPP(string appid) + { + return _appRepository.GetAPP(appid); + } + + public IList SelectApp() + { + return _appRepository.SelectApp(); + } + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + public override async Task> FindWithPagerAsync(SearchInputDto search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and (AppId like '%{0}%' or RequestUrl like '%{0}%')", search.Keywords); + }; + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + public void UpdateCacheAllowApp() + { + CacheHelper cacheHelper = new CacheHelper(); + IEnumerable appList = repository.GetAllByIsNotDeleteAndEnabledMark(); + cacheHelper.Add("AllowAppId", appList); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AdminUserLogOnService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AdminUserLogOnService.cs new file mode 100644 index 0000000..6c818ad --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AdminUserLogOnService.cs @@ -0,0 +1,43 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + public class AdminUserLogOnService : BaseService, IAdminUserLogOnService + { + private readonly IAdminUserLogOnRepository _userLogOnRepository; + + public AdminUserLogOnService(IAdminUserLogOnRepository repository) : base(repository) + { + _userLogOnRepository = repository; + } + + /// + /// ݻԱIDȡû¼Ϣʵ + /// + /// + /// + public AdminUserLogOn GetByUserId(long userId) + { + return _userLogOnRepository.GetByUserId(userId); + } + + /// + /// ݻԱIDȡû¼Ϣʵ + /// + /// Ϣ + /// ûId + /// + public async Task SaveUserTheme(UserThemeInputDto info, long userId) + { + string themeJsonStr = info.ToJson(); + string where = $"UserId='{userId}'"; + return await _userLogOnRepository.UpdateTableFieldAsync("Theme", themeJsonStr, where); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AdminUserService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AdminUserService.cs new file mode 100644 index 0000000..bc7d54d --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AdminUserService.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Const; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class AdminUserService : BaseService, IAdminUserService + { + private readonly IAdminUserRepository _adminUserRepository; + private readonly IAdminUserLogOnRepository _adminUserLogOnRepository; + private readonly IRoleService _roleService; + private readonly IOrganizeService _organizeService; + + /// + /// + /// + /// + /// + /// + /// + /// + public AdminUserService(IAdminUserRepository repository, IAdminUserLogOnRepository adminUserLogOnRepository, + IRoleService roleService, IOrganizeService organizeService) : base(repository) + { + _adminUserRepository = repository; + _roleService = roleService; + _organizeService = organizeService; + _adminUserLogOnRepository = adminUserLogOnRepository; + } + + /// + /// û½֤ + /// + /// û + /// 루һmd5ܺ + /// ֤ɹûʵ壬֤ʧܷnull|ʾϢ + public async Task> Validate(string userName, string password) + { + AdminUser userEntity = await _adminUserRepository.GetUserByLogin(userName); + + if (userEntity == null) + { + return new Tuple(null, ReturnConst.User_Not_Exist); + } + + if (userEntity.Status == -1) + { + return new Tuple(null,ReturnConst.User_Disable); + } + + AdminUserLogOn userSinginEntity = _adminUserLogOnRepository.GetByUserId(userEntity.Id); + string inputPassword = MD5Util + .GetMD5_32(DEncrypt.Encrypt(MD5Util.GetMD5_32(password).ToLower(), userSinginEntity.AdminUserSecretkey) + .ToLower()).ToLower(); + + if (inputPassword != userSinginEntity.AdminUserPassword) + { + return new Tuple(null, ReturnConst.Password_Error); + } + else + { + AdminUserLogOn userLogOn = _adminUserLogOnRepository.GetWhere("AdminUserId='" + userEntity.Id + "'"); + // if (userLogOn.AllowEndTime < DateTime.Now) + // return new Tuple(null, "˺ѹڣϵϵͳԱ"); + // if (userLogOn.LockEndDate > DateTime.Now) + // { + // var dateStr = userLogOn.LockEndDate.ToEasyStringDQ(); + // return new Tuple(null, "ǰ" + dateStr + "¼"); + // } + + // if (userLogOn.FirstVisitTime == null) + // userLogOn.FirstVisitTime = userLogOn.PreviousVisitTime = DateTime.Now; + // else + // userLogOn.PreviousVisitTime = DateTime.Now; + userLogOn.LogOnCount++; + userLogOn.LastVisitTime = DateTime.Now; + userLogOn.UserOnLine = true; + await _adminUserLogOnRepository.UpdateAsync(userLogOn, userLogOn.Id); + return new Tuple(userEntity, ""); + } + } + + /// + /// û½֤ + /// + /// û + /// 루һmd5ܺ + /// û + /// ֤ɹûʵ壬֤ʧܷnull|ʾϢ + public async Task> Validate(string userName, string password, UserType userType) + { + AdminUser userEntity = await _adminUserRepository.GetUserByLogin(userName); + + if (userEntity == null) + { + return new Tuple(null, ReturnConst.User_Not_Exist); + } + + if (userEntity.Status == -1) + { + return new Tuple(null,ReturnConst.User_Disable); + } + + AdminUserLogOn userSinginEntity = _adminUserLogOnRepository.GetByUserId(userEntity.Id); + + string inputPassword = MD5Util + .GetMD5_32(DEncrypt.Encrypt(MD5Util.GetMD5_32(password).ToLower(), userSinginEntity.AdminUserSecretkey) + .ToLower()).ToLower(); + + if (inputPassword != userSinginEntity.AdminUserPassword) + { + return new Tuple(null,ReturnConst.Password_Error); + } + else + { + AdminUserLogOn userLogOn = _adminUserLogOnRepository.GetWhere("UserId='" + userEntity.Id + "'"); + //if (userLogOn.AllowEndTime < DateTime.Now) + // return new Tuple(null, "˺ѹڣϵϵͳԱ"); + //if (userLogOn.LockEndDate > DateTime.Now) + //{ + // var dateStr = userLogOn.LockEndDate.ToEasyStringDQ(); + // return new Tuple(null, "ǰ" + dateStr + "¼"); + //} + + //if (userLogOn.FirstVisitTime == null) + // userLogOn.FirstVisitTime = userLogOn.PreviousVisitTime = DateTime.Now; + //else + // userLogOn.PreviousVisitTime = DateTime.Now; + userLogOn.LogOnCount++; + userLogOn.LastVisitTime = DateTime.Now; + userLogOn.UserOnLine = true; + await _adminUserLogOnRepository.UpdateAsync(userLogOn, userLogOn.Id); + return new Tuple(userEntity, ""); + } + } + + /// + /// û˺ŲѯûϢ + /// + /// + /// + public async Task GetByUserName(string userName) + { + return await _adminUserRepository.GetByUserName(userName); + } + + /// + /// ûֻѯûϢ + /// + /// ֻ + /// + public async Task GetUserByMobilePhone(string mobilephone) + { + return await _adminUserRepository.GetUserByMobilePhone(mobilephone); + } + + /// + /// AccountֻŲѯûϢ + /// + /// ¼˺ + /// + public async Task GetUserByLogin(string account) + { + return await _adminUserRepository.GetUserByLogin(account); + } + + /// + /// ݵOpenIdѯûϢ + /// + /// + /// OpenIdֵ + /// + public AdminUser GetUserByOpenId(string openIdType, string openId) + { + return _adminUserRepository.GetUserByOpenId(openIdType, openId); + } + + /// + /// userIdѯûϢ + /// + /// + /// userId + /// + public UserOpenIds GetUserOpenIdByuserId(string openIdType, long userId) + { + return _adminUserRepository.GetUserOpenIdByuserId(openIdType, userId); + } + + /// + /// ûϢ,ƽ̨ + /// + /// + /// + /// + /// + public bool UpdateUserByOpenId(AdminUser entity, AdminUserLogOn userLogOnEntity, UserOpenIds userOpenIds, + IDbTransaction trans = null) + { + return _adminUserRepository.UpdateUserByOpenId(entity, userLogOnEntity, userOpenIds, trans); + } + + /// + /// ΢UnionIdѯûϢ + /// + /// UnionIdֵ + /// + public AdminUser GetUserByUnionId(string unionId) + { + return _adminUserRepository.GetUserByUnionId(unionId); + } + + /// + /// û + /// + /// + /// + //public bool UpdateUserByOpenId(AdminUserInputDto userInPut) + //{ + // var user = GetUserByOpenId(userInPut.OpenIdType, userInPut.OpenId); + // user.HeadIcon = userInPut.HeadIcon; + // user.UserName = userInPut.UserName; + // user.Gender = userInPut.Gender; + // return _adminUserRepository.Update(user, user.Id); + //} + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + public async Task> FindWithPagerSearchAsync(SearchUserModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format( + " and (UserName like '%{0}%' or Account like '%{0}%' or MobilePhone like '%{0}%')", + search.Keywords); + } + + + + if (!string.IsNullOrEmpty(search.StartTime)) + { + @where += " and CreatedTime >='" + search.StartTime + " 00:00:00'"; + } + + if (!string.IsNullOrEmpty(search.EndTime)) + { + @where += " and CreatedTime <='" + search.EndTime + " 23:59:59'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + List resultList = list.MapTo(); + List listResult = new List(); + foreach (AdminUserOutputDto item in resultList) + { + if (!string.IsNullOrEmpty(item.OrganizeId.ToString())) + { + item.OrganizeName = _organizeService.Get(item.OrganizeId)?.FullName; + } + + if (!string.IsNullOrEmpty(item.RoleId.ToString().ToString())) + { + item.RoleName = _roleService.GetRoleNameStr(item.RoleId.ToString()); + } + + if (!string.IsNullOrEmpty(item.DepartmentId.ToString())) + { + item.DepartmentName = _organizeService.Get(item.DepartmentId).FullName; + } + //if (!string.IsNullOrEmpty(item.DutyId)) + //{ + // item.DutyName = _roleService.Get(item.DutyId).FullName; + //} + listResult.Add(item); + } + + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = listResult, + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + public bool CreateUserByWxOpenId(UserInputDto userInPut) + { + throw new NotImplementedException(); + } + + public bool UpdateUserByOpenId(UserInputDto userInPut) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/ApiService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/ApiService.cs new file mode 100644 index 0000000..6710b46 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/ApiService.cs @@ -0,0 +1,30 @@ +using System.Threading.Tasks; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + public class ApiService : BaseService, IApiService + { + private readonly IApiRepository _apiRepository; + + /// + /// + /// + /// + public ApiService(IApiRepository repository) : base(repository) + { + _apiRepository = repository; + } + + public async Task GetApiAsync(string apiUrl) + { + string key = string.Format(@"ApiUrl='{0}'", apiUrl); + var result = await _apiRepository.GetWhereAsync(key);//x => x.ApiUrl == apiUrl + return result; + } + } +} diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AreaService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AreaService.cs new file mode 100644 index 0000000..a7340f9 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/AreaService.cs @@ -0,0 +1,131 @@ +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Linq; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// Ϣ + /// + public class AreaService : BaseService, IAreaService + { + private readonly IAreaRepository _repository; + + public AreaService(IAreaRepository repository) : base(repository) + { + _repository = repository; + } + + #region uniappѡ + + /// + /// ȡпõĵuniappѡ + /// + /// + public List GetAllByEnable() + { + List list = new List(); + CacheHelper cacheHelper = new CacheHelper(); + list = JsonConvert.DeserializeObject>(cacheHelper.Get("Area_Enable_Uniapp") + .ToJson()); + if (list == null || list.Count <= 0) + { + List listFunction = _repository.GetAllByIsNotDeleteAndEnabledMark("Layers in (0,1,2)") + .OrderBy(t => t.SortCode).ToList(); + list = UniappViewJson(listFunction, 0); + cacheHelper.Add("Area_Enable_Uniapp", list); + } + + return list; + } + + /// + /// ȡʡС/õĵuniappѡ + /// + /// + public List GetProvinceToAreaByEnable() + { + List list = new List(); + CacheHelper cacheHelper = new CacheHelper(); + list = JsonConvert.DeserializeObject>(cacheHelper + .Get("Area_ProvinceToArea_Enable_Uniapp").ToJson()); + if (list == null || list.Count <= 0) + { + List listFunctionTemp = _repository.GetAllByIsNotDeleteAndEnabledMark("Layers in (1,2,3)") + .OrderBy(t => t.Id).ToList(); + List listFunction = new List(); + foreach (Area item in listFunctionTemp) + { + if (item.Layers == 1) + { + item.ParentId = 0; + } + + listFunction.Add(item); + } + + list = UniappViewJson(listFunction, 0); + cacheHelper.Add("Area_ProvinceToArea_Enable_Uniapp", list); + } + + return list; + } + + /// + /// + /// + /// + /// + /// + public List UniappViewJson(List data, long ParentId) + { + List list = new List(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId).ToList(); + foreach (Area entity in ChildNodeList) + { + AreaPickerOutputDto treeViewModel = new AreaPickerOutputDto + { + value = entity.Id, + label = entity.FullName, + children = ChildrenUniappViewList(data, entity.Id) + }; + list.Add(treeViewModel); + } + + return list; + } + + /// + /// + /// + /// + /// + /// + public List ChildrenUniappViewList(List data, long ParentId) + { + List listChildren = new List(); + List ChildNodeList = data.FindAll(t => t.ParentId == ParentId).ToList(); + foreach (Area entity in ChildNodeList) + { + AreaPickerOutputDto treeViewModel = new AreaPickerOutputDto + { + value = entity.Id, + label = entity.FullName, + children = ChildrenUniappViewList(data, entity.Id) + }; + listChildren.Add(treeViewModel); + } + + return listChildren; + } + + #endregion uniappѡ + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/CompanyService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/CompanyService.cs new file mode 100644 index 0000000..974cae1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/CompanyService.cs @@ -0,0 +1,169 @@ +using Senparc.Weixin.Entities.TemplateMessage; +using System.Collections.Generic; +using System.Threading.Tasks; +using Wx; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Const; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class CompanyService : BaseService, ICompanyService + { + private readonly ICompanyRepository _companyRepository; + private readonly IVehicleRepository _vehicleRepository; + private readonly IUserRepository _userRepository; + private readonly ICacheService _cacheService; + public CompanyService(ICompanyRepository companyRepository, + IVehicleRepository vehicleRepository, + IUserRepository userRepository, + ICacheService cacheService + + ) : base(companyRepository) + { + _companyRepository = companyRepository; + _vehicleRepository = vehicleRepository; + _userRepository = userRepository; + _cacheService = cacheService; + + } + + public async Task> FindWithPagerSearchAsync(SearchUserModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and (CompanyName like '%{0}%')", search.Keywords); + } + + if (search.Status > (int)CommonStatus.DELETED) + { + @where += string.Format(" and Status={0}", search.Status); + } + if (!string.IsNullOrEmpty(search.StartTime)) + { + @where += " and CreatedTime >='" + search.StartTime + " 00:00:00'"; + } + + if (!string.IsNullOrEmpty(search.EndTime)) + { + @where += " and CreatedTime <='" + search.EndTime + " 23:59:59'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + List companyOutput = list.MapTo(); + foreach (var item in companyOutput) + { + //string condition = string.Format(@" CompanyId=" + item.Id + " Status=1"); + item.VehicleCount = await _vehicleRepository.GetCountByWhereAsync(" CompanyId=" + item.Id + " and Status=1"); + item.CompanyLogo = CommonConst.Default_Image_Prefix + item.CompanyLogo; + } + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = companyOutput, + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// ˹˾״̬ + /// + /// + /// + /// + public async Task AuditAsync(long id, int status) + { + CommonResult result = new CommonResult(); + string where = $@" Id={id}"; + Company company = await _companyRepository.GetWhereAsync(where); + User user = await _userRepository.GetWhereAsync($@"Phone={company.ContactPhone}"); + var isExistCount = await _companyRepository.GetCountByWhereAsync($@"ContactPhone={company.ContactPhone} and Status=1"); + if (isExistCount > 0) + { + result.ResData = ReturnConst.Audit_Repeat; + result.Success = false; + result.ErrMsg = ReturnConst.Audit_Repeat; + return result; + } + if (company.Status != (int)CommonStatus.ENABLE) + { + result.Success = await _companyRepository.AuditAsync(id, status); + string phrase2 = ReturnConst.Audit_Failed; + string thing3 = ReturnConst.Audit_Failed_Note; + if (status == (int)CommonStatus.ENABLE) + { + phrase2 = ReturnConst.Audit_Success; + thing3 = ReturnConst.Audit_Success_Note; + } + await CommonHelper.SendCompanyAuditAsync(company.CompanyName, phrase2, thing3, user.OpenId).ConfigureAwait(false); + + return result; + } + else + { + result.ResData = ReturnConst.Audit_Error; + result.Success = false; + return result; + } + } + + /// + /// ޸Ĺ˾״̬ + /// + /// + /// + /// + public async Task UpdateAsync(long id, int status) + { + CommonResult result = new CommonResult(); + string where = string.Format(@" Id={0}", id); + Company company = await _companyRepository.GetWhereAsync(where); + if (company.Status == (int)CommonStatus.ENABLE) + { + result.Success = await _companyRepository.UpdateStatusAsync(id, status); + await ClearCompanyCacheAsync(company.Id); + return result; + } + else + { + result.ResData = "ù˾ͣ"; + result.Success = false; + return result; + } + } + + + /// + /// + /// + /// + /// + public async Task ClearCompanyCacheAsync(long companyId) + { + // + await _cacheService.RemoveAsync(CacheKey.CACHE_KEY_COMPANY + $"{companyId}"); + } + + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/DictionaryService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/DictionaryService.cs new file mode 100644 index 0000000..89c3a4f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/DictionaryService.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + public class DictionaryService : BaseService, IDictionaryService + { + private readonly IDictionaryRepository _repository; + + public DictionaryService(IDictionaryRepository repository) : base(repository) + { + _repository = repository; + } + + /// + /// ȡܲ˵Vue б + /// + /// + public async Task> GetAllItemsTreeTable() + { + List reslist = new List(); + IEnumerable elist = await _repository.GetListWhereAsync("1=1"); + List list = elist.OrderBy(t => t.Sort).ToList(); + List oneMenuList = list.FindAll(t => t.ParentId == 0); + foreach (Dictionary item in oneMenuList) + { + DictionaryOutputDto menuTreeTableOutputDto = new DictionaryOutputDto(); + menuTreeTableOutputDto = item.MapTo(); + // menuTreeTableOutputDto.Children = GetSubMenus(list, item.Id).ToList(); + reslist.Add(menuTreeTableOutputDto); + } + + return reslist; + } + + /// + /// ݱѯֵ + /// + /// + /// + public async Task GetByEnCodAsynce(string enCode) + { + return await _repository.GetByEnCodAsynce(enCode); + } + + /// + /// ʱжϷǷڣųԼ + /// + /// Id + /// + public async Task GetByEnCodAsynce(string enCode, long id) + { + return await _repository.GetByEnCodAsynce(enCode, id); + } + + /// + /// ȡӲ˵ݹ + /// + /// + /// Id + /// + private List GetSubMenus(List data, long ParentId) + { + List list = new List(); + DictionaryOutputDto menuTreeTableOutputDto = new DictionaryOutputDto(); + List ChilList = data.FindAll(t => t.ParentId == ParentId); + foreach (Dictionary entity in ChilList) + { + menuTreeTableOutputDto = entity.MapTo(); + //menuTreeTableOutputDto.Children = + // GetSubMenus(data, entity.Id).OrderBy(t => t.Sort); + list.Add(menuTreeTableOutputDto); + } + + return list; + } + + /// + /// ѯֵб + /// + /// + /// + /// + public async Task> GetDictionaryListByWhere(string ids, string code) + { + CacheHelper cacheHelper = new CacheHelper(); + List list = cacheHelper.Get>("dictionary:list"); + if (list == null) + { + list = await SyncDictionaryCache(); + } + + string[] idsInput = { }; + if (!string.IsNullOrEmpty(ids)) + { + idsInput = ids.Split(","); + } + if (!string.IsNullOrEmpty(code)) + { + list = list.Where(x => x.Code == code).ToList(); + } + + if (!string.IsNullOrEmpty(ids) && !string.IsNullOrEmpty(code)) + { + list = list.Where(x => idsInput.Contains(x.Id.ToString()) && x.Code == code).ToList(); + } + return list; + } + + /// + /// ѯֵ + /// + /// + /// + public async Task GetDictionaryById(long id) + { + CacheHelper cacheHelper = new CacheHelper(); + List list = cacheHelper.Get>("dcdictionary:list"); + if (list == null) + { + list = await SyncDictionaryCache(); + } + + DictionaryOutputDto result = list.Find(x => x.Id == id); + return result; + } + + /// + /// 첽ҳѯ + /// + /// + /// + public async Task> FindWithPagerSearchAsync(SearchUserModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format( + " and ( Name like '%{0}%' or Value like '%{0}%' or Description like '%{0}%')", + search.Keywords); + } + + if (!string.IsNullOrEmpty(search.StartTime)) + { + @where += " and ModifiedTime >='" + search.StartTime + " 00:00:00'"; + } + + if (!string.IsNullOrEmpty(search.EndTime)) + { + @where += " and ModifiedTime <='" + search.EndTime + " 23:59:59'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + List listDto = list.MapTo(); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = listDto, + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// ͬ + /// + /// + public async Task> SyncDictionaryCache() + { + CacheHelper cacheHelper = new CacheHelper(); + IEnumerable list = await repository.GetListWhereAsync(" IsDeleted=0 and IsEnabled=1 order by Sort"); + List dicList = list.MapTo(); + cacheHelper.Add("dcdictionary:list", dicList, TimeSpan.FromDays(30)); + return dicList; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogExService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogExService.cs new file mode 100644 index 0000000..d30cda8 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogExService.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class LogExService : BaseService, ILogExService + { + private readonly ILogExRepository _iLogRepository; + private readonly IUserRepository _iuserRepository; + + /// + /// + /// + /// + /// + public LogExService(ILogExRepository repository, IUserRepository userRepository) : base(repository) + { + _iLogRepository = repository; + _iuserRepository = userRepository; + } + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + public async Task> FindWithPagerSearchAsync(SearchExceptionsLogsModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.CreatedTime1)) + { + @where += " and CreatedTime >='" + search.CreatedTime1.ToDateTime() + "'"; + } + + if (!string.IsNullOrEmpty(search.CreatedTime2)) + { + @where += " and CreatedTime <='" + search.CreatedTime2.ToDateTime() + "'"; + } + + if (!string.IsNullOrEmpty(search.Filter.IPAddress)) + { + @where += string.Format(" and IPAddress = '{0}'", search.Filter.IPAddress); + }; + if (!string.IsNullOrEmpty(search.Filter.Account)) + { + @where += string.Format(" and Account = '{0}'", search.Filter.Account); + }; + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + + //Expression> filter = log => true; + //if (!string.IsNullOrEmpty(search.Keywords)) + //{ + // filter = filter.And(log => log.Account.StartsWith(search.Keywords) || log.ModuleName.StartsWith(search.Keywords) || log.IPAddress.StartsWith(search.Keywords) + // || log.IPAddressName.StartsWith(search.Keywords) || log.Description.StartsWith(search.Keywords)); + //} + //if (!string.IsNullOrEmpty(search.EnCode)) + //{ + // filter = filter.And(log=>search.EnCode.Contains(log.Type)); + //} + List list = await _iLogRepository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// ϢдûIJ־¼ + /// + /// + /// + /// ϸ + /// + public bool OnOperationLog(string tableName, string operationType, string note) + { + try + { + //Ȼʵ¼ǻҪжϸñǷñ棬ڣ򲻼¼־ + //var identities = _httpContextAccessor.HttpContext.User.Identities; + if (HttpContextHelper.HttpContext == null) + { + return false; + } + + IEnumerable identities = HttpContextHelper.HttpContext.User.Identities; + ClaimsIdentity claimsIdentity = identities.First(); + List claimlist = claimsIdentity.Claims as List; + string userId = claimlist[0].Value; + CacheHelper cacheHelper = new CacheHelper(); + AdminCurrentUser AdminCurrentUser = new AdminCurrentUser(); + AdminCurrentUser user = cacheHelper.Get("login_user_" + userId).ToJson().ToObject(); + if (user != null) + { + AdminCurrentUser = user; + bool insert = operationType == DbLogType.Create.ToString(); + ; //&& settingInfo.InsertLog; + bool update = operationType == DbLogType.Update.ToString(); // && settingInfo.UpdateLog; + bool delete = operationType == DbLogType.Delete.ToString(); // && settingInfo.DeleteLog; + bool deletesoft = operationType == DbLogType.DeleteSoft.ToString(); // && settingInfo.DeleteLog; + bool exception = operationType == DbLogType.Exception.ToString(); // && settingInfo.DeleteLog; + bool sql = operationType == DbLogType.SQL.ToString(); // && settingInfo.DeleteLog; + + if (insert || update || delete || deletesoft || exception || sql) + { + LogEx info = new LogEx(); + info.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + //info.ModuleName = tableName; + //info.Type = operationType; + //info.Description = note; + //info.Date = info.CreatedTime = DateTime.Now; + //info.CreatedUserId = CurrentUser.UserId; + //info.Account = AdminCurrentUser.Account; + //info.UserName = AdminCurrentUser.UserName; + //info.OrganizeId = AdminCurrentUser.OrganizeId; + //info.IPAddress = AdminCurrentUser.CurrentLoginIP; + //info.IPAddressName = AdminCurrentUser.IPAddressName; + //info.Result = true; + long lg = _iLogRepository.Insert(info); + if (lg > 0) + { + return true; + } + } + } + } + catch (Exception ex) + { + Log4NetHelper.Error("", ex); + return false; + } + + return false; + } + + /// + /// ϢдûIJ־¼ + /// Ҫдģ־ + /// + /// ģ + /// + /// ϸ + /// û + /// + public bool OnOperationLog(string module, string operationType, string note, AdminCurrentUser AdminCurrentUser) + { + //Ȼʵ¼ǻҪжϸñǷñ棬ڣ򲻼¼־ + //OperationLogSettingInfo settingInfo = BLLFactory.Instance.FindByTableName(tableName, trans); + + if (AdminCurrentUser != null) + { + bool login = operationType == DbLogType.Login.ToString(); + bool visit = operationType == DbLogType.Visit.ToString(); + bool exit = operationType == DbLogType.Exit.ToString(); + bool other = operationType == DbLogType.Other.ToString(); + bool insert = operationType == DbLogType.Create.ToString(); + bool update = operationType == DbLogType.Update.ToString(); + bool delete = operationType == DbLogType.Delete.ToString(); + bool deletesoft = operationType == DbLogType.DeleteSoft.ToString(); + bool exception = operationType == DbLogType.Exception.ToString(); + if (login || visit || exit || other || insert || update || delete || deletesoft || exception) + { + LogEx info = new LogEx(); + info.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + //info.ModuleName = module; + //info.Type = operationType; + //info.Description = note; + //info.Date = info.CreatedTime = DateTime.Now; + //info.CreatedUserId = CurrentUser.UserId; + //info.Account = AdminCurrentUser.Account; + //info.UserName = AdminCurrentUser.UserName; + //info.OrganizeId = AdminCurrentUser.OrganizeId; + //info.IPAddress = AdminCurrentUser.CurrentLoginIP; + //info.IPAddressName = IpAddressUtil.GetCityByIp(AdminCurrentUser.CurrentLoginIP); + //info.Result = true; + long lg = _iLogRepository.Insert(info); + if (lg > 0) + { + return true; + } + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogOpService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogOpService.cs new file mode 100644 index 0000000..4d5b1e4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogOpService.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// ־ + /// + public class LogOpService : BaseService, ILogOpService + { + private readonly ILogOpRepository _operationLogsRepository; + private readonly IUserRepository _userRepository; + + /// + /// + /// + /// + /// + public LogOpService(ILogOpRepository repository, + IUserRepository userRepository + ) : base(repository) + { + _operationLogsRepository = repository; + _userRepository = userRepository; + } + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + public async Task> FindWithPagerSearchAsync(SearchLogOpModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.CreatedTime1)) + { + @where += " and CreatedTime >='" + search.CreatedTime1.ToDateTime() + "'"; + } + + if (!string.IsNullOrEmpty(search.CreatedTime2)) + { + @where += " and CreatedTime <='" + search.CreatedTime2.ToDateTime() + "'"; + } + + if (search.Filter != null) + { + if (!string.IsNullOrEmpty(search.Filter.IPAddress)) + { + @where += string.Format(" and IPAddress = '{0}'", search.Filter.IPAddress); + }; + if (!string.IsNullOrEmpty(search.Filter.Account)) + { + @where += string.Format(" and Account = '{0}'", search.Filter.Account); + }; + } + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + + //Expression> filter = log => true; + //if (!string.IsNullOrEmpty(search.Keywords)) + //{ + // filter = filter.And(log => log.Account.StartsWith(search.Keywords) || log.ModuleName.StartsWith(search.Keywords) || log.IPAddress.StartsWith(search.Keywords) + // || log.IPAddressName.StartsWith(search.Keywords) || log.Description.StartsWith(search.Keywords)); + //} + //if (!string.IsNullOrEmpty(search.EnCode)) + //{ + // filter = filter.And(log=>search.EnCode.Contains(log.Type)); + //} + List list = await _operationLogsRepository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// ϢдûIJ־¼ + /// + /// + /// + /// ϸ + /// + public bool OnOperationLog(string tableName, string operationType, string note) + { + try + { + //Ȼʵ¼ǻҪжϸñǷñ棬ڣ򲻼¼־ + //var identities = _httpContextAccessor.HttpContext.User.Identities; + if (HttpContextHelper.HttpContext == null) + { + return false; + } + + IEnumerable identities = HttpContextHelper.HttpContext.User.Identities; + ClaimsIdentity claimsIdentity = identities.First(); + List claimlist = claimsIdentity.Claims as List; + string userId = claimlist[0].Value; + CacheHelper cacheHelper = new CacheHelper(); + AdminCurrentUser AdminCurrentUser = new AdminCurrentUser(); + AdminCurrentUser user = cacheHelper.Get("login_user_" + userId).ToJson().ToObject(); + if (user != null) + { + AdminCurrentUser = user; + bool insert = operationType == DbLogType.Create.ToString(); + ; //&& settingInfo.InsertLog; + bool update = operationType == DbLogType.Update.ToString(); // && settingInfo.UpdateLog; + bool delete = operationType == DbLogType.Delete.ToString(); // && settingInfo.DeleteLog; + bool deletesoft = operationType == DbLogType.DeleteSoft.ToString(); // && settingInfo.DeleteLog; + bool exception = operationType == DbLogType.Exception.ToString(); // && settingInfo.DeleteLog; + bool sql = operationType == DbLogType.SQL.ToString(); // && settingInfo.DeleteLog; + + if (insert || update || delete || deletesoft || exception || sql) + { + LogOp info = new LogOp(); + info.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + //info.ModuleName = tableName; + //info.Type = operationType; + //info.Description = note; + //info.Date = info.CreatedTime = DateTime.Now; + //info.CreatedUserId = CurrentUser.UserId; + //info.Account = AdminCurrentUser.Account; + //info.UserName = AdminCurrentUser.UserName; + //info.OrganizeId = AdminCurrentUser.OrganizeId; + //info.IPAddress = AdminCurrentUser.CurrentLoginIP; + //info.IPAddressName = AdminCurrentUser.IPAddressName; + //info.Result = true; + long lg = _operationLogsRepository.Insert(info); + if (lg > 0) + { + return true; + } + } + } + } + catch (Exception ex) + { + Log4NetHelper.Error("", ex); + return false; + } + + return false; + } + + /// + /// ϢдûIJ־¼ + /// Ҫдģ־ + /// + /// ģ + /// + /// ϸ + /// û + /// + public bool OnOperationLog(string module, string operationType, string note, AdminCurrentUser AdminCurrentUser) + { + //Ȼʵ¼ǻҪжϸñǷñ棬ڣ򲻼¼־ + //OperationLogSettingInfo settingInfo = BLLFactory.Instance.FindByTableName(tableName, trans); + + if (AdminCurrentUser != null) + { + bool login = operationType == DbLogType.Login.ToString(); + bool visit = operationType == DbLogType.Visit.ToString(); + bool exit = operationType == DbLogType.Exit.ToString(); + bool other = operationType == DbLogType.Other.ToString(); + bool insert = operationType == DbLogType.Create.ToString(); + bool update = operationType == DbLogType.Update.ToString(); + bool delete = operationType == DbLogType.Delete.ToString(); + bool deletesoft = operationType == DbLogType.DeleteSoft.ToString(); + bool exception = operationType == DbLogType.Exception.ToString(); + if (login || visit || exit || other || insert || update || delete || deletesoft || exception) + { + LogOp info = new LogOp(); + info.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + //info.ModuleName = module; + //info.Type = operationType; + //info.Description = note; + //info.Date = info.CreatedTime = DateTime.Now; + //info.CreatedUserId = CurrentUser.UserId; + //info.Account = AdminCurrentUser.Account; + //info.UserName = AdminCurrentUser.UserName; + //info.OrganizeId = AdminCurrentUser.OrganizeId; + //info.IPAddress = AdminCurrentUser.CurrentLoginIP; + //info.IPAddressName = IpAddressUtil.GetCityByIp(AdminCurrentUser.CurrentLoginIP); + //info.Result = true; + long lg = _operationLogsRepository.Insert(info); + if (lg > 0) + { + return true; + } + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogVisService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogVisService.cs new file mode 100644 index 0000000..2fa0c82 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/LogVisService.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class LogVisService : BaseService, ILogVisService + { + private readonly ILogVisRepository _dbLogsRepository; + private readonly IUserRepository _userRepository; + + /// + /// + /// + /// + /// + public LogVisService(ILogVisRepository repository, IUserRepository userRepository) : base(repository) + { + _dbLogsRepository = repository; + _userRepository = userRepository; + } + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + public async Task> FindWithPagerSearchAsync(SearchDbLogsModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format( + " and (UserName like '%{0}%' or ExecuteDate like '%{0}%' or SQL like '%{0}%')", + search.Keywords); + } + + if (!string.IsNullOrEmpty(search.CreatedTime1)) + { + @where += " and CreatedTime >='" + search.CreatedTime1.ToDateTime() + "'"; + } + + if (!string.IsNullOrEmpty(search.CreatedTime2)) + { + @where += " and CreatedTime <='" + search.CreatedTime2.ToDateTime() + "'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + + //Expression> filter = log => true; + //if (!string.IsNullOrEmpty(search.Keywords)) + //{ + // filter = filter.And(log => log.Account.StartsWith(search.Keywords) || log.ModuleName.StartsWith(search.Keywords) || log.IPAddress.StartsWith(search.Keywords) + // || log.IPAddressName.StartsWith(search.Keywords) || log.Description.StartsWith(search.Keywords)); + //} + //if (!string.IsNullOrEmpty(search.EnCode)) + //{ + // filter = filter.And(log=>search.EnCode.Contains(log.Type)); + //} + List list = await _dbLogsRepository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// ϢдûIJ־¼ + /// + /// + /// + /// ϸ + /// + public bool OnOperationLog(string tableName, string operationType, string note) + { + try + { + //Ȼʵ¼ǻҪжϸñǷñ棬ڣ򲻼¼־ + //var identities = _httpContextAccessor.HttpContext.User.Identities; + if (HttpContextHelper.HttpContext == null) + { + return false; + } + + IEnumerable identities = HttpContextHelper.HttpContext.User.Identities; + ClaimsIdentity claimsIdentity = identities.First(); + List claimlist = claimsIdentity.Claims as List; + string userId = claimlist[0].Value; + CacheHelper cacheHelper = new CacheHelper(); + AdminCurrentUser AdminCurrentUser = new AdminCurrentUser(); + AdminCurrentUser user = cacheHelper.Get("login_user_" + userId).ToJson().ToObject(); + if (user != null) + { + AdminCurrentUser = user; + bool insert = operationType == DbLogType.Create.ToString(); + ; //&& settingInfo.InsertLog; + bool update = operationType == DbLogType.Update.ToString(); // && settingInfo.UpdateLog; + bool delete = operationType == DbLogType.Delete.ToString(); // && settingInfo.DeleteLog; + bool deletesoft = operationType == DbLogType.DeleteSoft.ToString(); // && settingInfo.DeleteLog; + bool exception = operationType == DbLogType.Exception.ToString(); // && settingInfo.DeleteLog; + bool sql = operationType == DbLogType.SQL.ToString(); // && settingInfo.DeleteLog; + + if (insert || update || delete || deletesoft || exception || sql) + { + LogVis info = new LogVis(); + info.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + //info.ModuleName = tableName; + //info.Type = operationType; + //info.Description = note; + //info.Date = info.CreatedTime = DateTime.Now; + //info.CreatedUserId = CurrentUser.UserId; + //info.Account = AdminCurrentUser.Account; + //info.UserName = AdminCurrentUser.UserName; + //info.OrganizeId = AdminCurrentUser.OrganizeId; + //info.IPAddress = AdminCurrentUser.CurrentLoginIP; + //info.IPAddressName = AdminCurrentUser.IPAddressName; + //info.Result = true; + long lg = _dbLogsRepository.Insert(info); + if (lg > 0) + { + return true; + } + } + } + } + catch (Exception ex) + { + Log4NetHelper.Error("", ex); + return false; + } + + return false; + } + + /// + /// ϢдûIJ־¼ + /// Ҫдģ־ + /// + /// ģ + /// + /// ϸ + /// û + /// + public bool OnOperationLog(string module, string operationType, string note, AdminCurrentUser AdminCurrentUser) + { + //Ȼʵ¼ǻҪжϸñǷñ棬ڣ򲻼¼־ + //OperationLogSettingInfo settingInfo = BLLFactory.Instance.FindByTableName(tableName, trans); + + if (AdminCurrentUser != null) + { + bool login = operationType == DbLogType.Login.ToString(); + bool visit = operationType == DbLogType.Visit.ToString(); + bool exit = operationType == DbLogType.Exit.ToString(); + bool other = operationType == DbLogType.Other.ToString(); + bool insert = operationType == DbLogType.Create.ToString(); + bool update = operationType == DbLogType.Update.ToString(); + bool delete = operationType == DbLogType.Delete.ToString(); + bool deletesoft = operationType == DbLogType.DeleteSoft.ToString(); + bool exception = operationType == DbLogType.Exception.ToString(); + if (login || visit || exit || other || insert || update || delete || deletesoft || exception) + { + LogVis info = new LogVis(); + //info.ModuleName = module; + //info.Type = operationType; + //info.Description = note; + //info.Date = info.CreatedTime = DateTime.Now; + //info.CreatedUserId = CurrentUser.UserId; + //info.Account = AdminCurrentUser.Account; + //info.UserName = AdminCurrentUser.UserName; + //info.OrganizeId = AdminCurrentUser.OrganizeId; + //info.IPAddress = AdminCurrentUser.CurrentLoginIP; + //info.IPAddressName = IpAddressUtil.GetCityByIp(AdminCurrentUser.CurrentLoginIP); + //info.Result = true; + long lg = _dbLogsRepository.Insert(info); + if (lg > 0) + { + return true; + } + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MenuService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MenuService.cs new file mode 100644 index 0000000..a090849 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MenuService.cs @@ -0,0 +1,264 @@ +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.Dtos; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extend; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// ˵ + /// + public class MenuService : BaseService, IMenuService + { + private readonly IMenuRepository _MenuRepository; + private readonly IAdminUserRepository _adminUserRepository; + private readonly ISystemTypeRepository systemTypeRepository; + private readonly IRoleAuthorizeRepository roleAuthorizeRepository; + + /// + /// + /// + /// + /// + /// + /// + /// + public MenuService(IMenuRepository repository, IAdminUserRepository adminUserRepository, + IRoleAuthorizeRepository _roleAuthorizeRepository, ISystemTypeRepository _systemTypeRepository + ) : base(repository) + { + _MenuRepository = repository; + _adminUserRepository = adminUserRepository; + roleAuthorizeRepository = _roleAuthorizeRepository; + systemTypeRepository = _systemTypeRepository; + } + + /// + /// ûȡܲ˵ + /// + /// ûID + /// + public List GetMenuByUser(long userId) + { + List result = new List(); + List allMenuls = new List(); + List subMenuls = new List(); + string where = string.Format("Layers=1"); + IEnumerable allMenus = _MenuRepository.GetAllByIsNotDeleteAndEnabledMark(); + allMenuls = allMenus.ToList(); + if (userId.ToString() == string.Empty) //Ա + { + return allMenuls; + } + + AdminUser user = _adminUserRepository.Get(userId); + if (user == null) + { + return result; + } + + long userRoles = user.RoleId; + where = string.Format("ItemType = 1 and ObjectType = 1 and ObjectId='{0}'", userRoles); + IEnumerable Menus = roleAuthorizeRepository.GetListWhere(where); + foreach (RoleAuthorize item in Menus) + { + Menu MenuEntity = allMenuls.Find(t => t.Id == item.ItemId); + if (MenuEntity != null) + { + result.Add(MenuEntity); + } + } + + return result.OrderBy(t => t.SortCode).ToList(); + } + + /// + /// ȡܲ˵Vue б + /// + /// ϵͳId + /// + public async Task> GetAllMenuTreeTable(string systemTypeId) + { + string where = "1=1"; + List reslist = new List(); + if (!string.IsNullOrEmpty(systemTypeId)) + { + IEnumerable elist = await _MenuRepository.GetListWhereAsync("SystemTypeId='" + systemTypeId + "'"); + List list = elist.OrderBy(t => t.SortCode).ToList(); + List oneMenuList = list.FindAll(t => t.ParentId == 0); + foreach (Menu item in oneMenuList) + { + MenuTreeTableOutputDto menuTreeTableOutputDto = new MenuTreeTableOutputDto(); + menuTreeTableOutputDto = item.MapTo(); + menuTreeTableOutputDto.Children = GetSubMenus(list, item.Id).ToList(); + reslist.Add(menuTreeTableOutputDto); + } + } + else + { + IEnumerable listSystemType = await systemTypeRepository.GetListWhereAsync(where); + + foreach (SystemType systemType in listSystemType) + { + MenuTreeTableOutputDto menuTreeTableOutputDto = new MenuTreeTableOutputDto + { + Id = systemType.Id, + FullName = systemType.FullName, + EnCode = systemType.EnCode, + UrlAddress = systemType.Url, + IsEnabled = systemType.IsEnabled, + + SystemTag = true + }; + + IEnumerable elist = await _MenuRepository.GetListWhereAsync("SystemTypeId='" + systemType.Id + "'"); + if (elist.Count() > 0) + { + List list = elist.OrderBy(t => t.SortCode).ToList(); + menuTreeTableOutputDto.Children = GetSubMenus(list, 0).ToList(); + } + + reslist.Add(menuTreeTableOutputDto); + } + } + + return reslist; + } + + /// + /// ȡӲ˵ݹ + /// + /// + /// Id + /// + private List GetSubMenus(List data, long ParentId) + { + List list = new List(); + MenuTreeTableOutputDto menuTreeTableOutputDto = new MenuTreeTableOutputDto(); + List ChilList = data.FindAll(t => t.ParentId == ParentId); + foreach (Menu entity in ChilList) + { + menuTreeTableOutputDto = entity.MapTo(); + menuTreeTableOutputDto.Children = GetSubMenus(data, entity.Id).OrderBy(t => t.SortCode) + .MapTo(); + list.Add(menuTreeTableOutputDto); + } + + return list; + } + + /// + /// ݽɫIDַŷֿ)ϵͳIDȡӦIJб + /// + /// ɫID + /// ϵͳID + /// ǷDz˵ + /// + public List GetFunctions(string roleIds, string typeID, bool isMenu = false) + { + return _MenuRepository.GetFunctions(roleIds, typeID, isMenu).ToList(); + } + + /// + /// ϵͳIDȡӦIJб + /// + /// ϵͳID + /// + public List GetFunctions(string typeID) + { + return _MenuRepository.GetFunctions(typeID).ToList(); + } + + /// + /// ݸܱѯӼܣҪҳťȨ + /// + /// ˵ܱ + /// + public async Task> GetListByParentEnCode(string enCode) + { + string where = string.Format("EnCode='{0}'", enCode); + Menu function = await repository.GetWhereAsync(where); + where = string.Format("ParentId='{0}'", function.ParentId); + IEnumerable list = await repository.GetAllByIsNotEnabledMarkAsync(where); + return list.MapTo().ToList(); + } + + /// + /// ɾ + /// + /// Id + /// + /// + public CommonResult DeleteBatchWhere(DeletesInputDto idsInfo, IDbTransaction trans = null) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + for (long i = 0; i < idsInfo.Ids.Length; i++) + { + if (idsInfo.Ids[0] != null) + { + @where = string.Format("ParentId='{0}'", idsInfo.Ids[0]); + IEnumerable list = _MenuRepository.GetListWhere(@where); + if (list.Count() > 0) + { + result.ErrMsg = "ܴӼݣɾ"; + return result; + } + } + } + + where = "id in ('" + idsInfo.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + bool bl = repository.DeleteBatchWhere(where); + if (bl) + { + result.ErrCode = "0"; + } + + return result; + } + + /// + /// ɾ + /// + /// Id + /// + /// + public async Task DeleteBatchWhereAsync(DeletesInputDto idsInfo, IDbTransaction trans = null) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + for (long i = 0; i < idsInfo.Ids.Length; i++) + { + if (idsInfo.Ids[0].ToString().Length > 0) + { + @where = string.Format("ParentId='{0}'", idsInfo.Ids[0]); + IEnumerable list = _MenuRepository.GetListWhere(@where); + if (list.Count() > 0) + { + result.ErrMsg = "ܴӼݣɾ"; + return result; + } + } + } + + where = "id in ('" + idsInfo.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + bool bl = await repository.DeleteBatchWhereAsync(where); + if (bl) + { + result.ErrCode = "0"; + } + + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MessageLogsService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MessageLogsService.cs new file mode 100644 index 0000000..294a426 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MessageLogsService.cs @@ -0,0 +1,107 @@ +using System; +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class MessageLogsService : BaseService, IMessageLogsService + { + private readonly IMessageLogsRepository _messageLogsRepository; + private readonly IMessageRepository _messageRepository; + + public MessageLogsService( + IMessageLogsRepository messageLogsRepository, + IMessageRepository messageRepository + ) : base(messageLogsRepository) + { + _messageLogsRepository = messageLogsRepository; + _messageRepository = messageRepository; + } + + /// + /// ͬʵ塣 + /// + /// ʵ + /// + /// + public override long Insert(MessageRecord entity, IDbTransaction trans = null) + { + entity.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + long result = repository.Insert(entity, trans); + return result; + } + + /// + /// 첽ʵ塣 + /// + /// ʵ + /// ID + /// + /// + public override async Task UpdateAsync(MessageRecord entity, long id, IDbTransaction trans = null) + { + bool result = await repository.UpdateAsync(entity, id, trans); + return result; + } + + /// + /// 첽ʵ塣 + /// + /// ʵ + /// + /// + public override async Task InsertAsync(MessageRecord entity, IDbTransaction trans = null) + { + entity.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + int result = await repository.InsertAsync(entity, trans); + return result; + } + + /// + /// Ϣ¼ + /// + /// + /// + public async Task AddAsync(MessageInputDto input) + { + Message entity = new Message() + { + Id = Yitter.IdGenerator.YitIdHelper.NextId(), + SendId = input.CreatedUserId, + MessageTitle = input.MessageTitle, + Type = 2, + GroupId = 0, + Content = "", + SendTime = DateTime.Now, + CreatedTime = DateTime.Now, + CreatedUserId = input.CreatedUserId, + ModifiedTime = DateTime.Now + }; + int id = await _messageRepository.InsertAsync(entity); + MessageRecord messageLogs = new MessageRecord() + { + Id = Yitter.IdGenerator.YitIdHelper.NextId(), + ReceiverId = input.UserId, + MessageId = entity.Id, + Status = 0, //δ + CreatedTime = DateTime.Now, + ModifiedTime = DateTime.Now, + CreatedUserId = input.CreatedUserId + }; + await _messageLogsRepository.InsertAsync(messageLogs); + CacheHelper cacheHelper = new CacheHelper(); + string key = string.Format("unread:number:{0}", input.UserId); + cacheHelper.Remove(key); + return true; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MessageService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MessageService.cs new file mode 100644 index 0000000..3246d0f --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/MessageService.cs @@ -0,0 +1,65 @@ +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class MessageService : BaseService, IMessageService + { + private readonly IMessageRepository _messageRepository; + + public MessageService( + IMessageRepository repository + ) : base(repository) + { + _messageRepository = repository; + } + + /// + /// ͬʵ塣 + /// + /// ʵ + /// + /// + public override long Insert(Message entity, IDbTransaction trans = null) + { + entity.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + long result = repository.Insert(entity, trans); + return result; + } + + /// + /// 첽ʵ塣 + /// + /// ʵ + /// ID + /// + /// + public override async Task UpdateAsync(Message entity, long id, IDbTransaction trans = null) + { + bool result = await repository.UpdateAsync(entity, id, trans); + return result; + } + + /// + /// 첽ʵ塣 + /// + /// ʵ + /// + /// + public override async Task InsertAsync(Message entity, IDbTransaction trans = null) + { + entity.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + int result = await repository.InsertAsync(entity, trans); + return result; + } + + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/OrganizeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/OrganizeService.cs new file mode 100644 index 0000000..e4606df --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/OrganizeService.cs @@ -0,0 +1,155 @@ +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Core.Dtos; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// ֯ + /// + public class OrganizeService : BaseService, IOrganizeService + { + private readonly IOrganizeRepository _repository; + + /// + /// + /// + /// + /// + public OrganizeService(IOrganizeRepository repository) : base(repository) + { + _repository = repository; + } + + /// + /// ȡ֯Vue б + /// + /// + public async Task> GetAllOrganizeTreeTable() + { + List reslist = new List(); + IEnumerable elist = await _repository.GetAllAsync(); + List list = elist.OrderBy(t => t.SortCode).ToList(); + List oneMenuList = list.FindAll(t => t.ParentId == 0); + foreach (Organize item in oneMenuList) + { + OrganizeOutputDto menuTreeTableOutputDto = new OrganizeOutputDto(); + menuTreeTableOutputDto = item.MapTo(); + menuTreeTableOutputDto.Children = GetSubOrganizes(list, item.Id).ToList(); + reslist.Add(menuTreeTableOutputDto); + } + + return reslist; + } + + /// + /// ȡӼݹ + /// + /// + /// Id + /// + private List GetSubOrganizes(List data, long ParentId) + { + List list = new List(); + OrganizeOutputDto OrganizeOutputDto = new OrganizeOutputDto(); + List ChilList = data.FindAll(t => t.ParentId == ParentId); + foreach (Organize entity in ChilList) + { + OrganizeOutputDto = entity.MapTo(); + OrganizeOutputDto.Children = GetSubOrganizes(data, entity.Id).OrderBy(t => t.SortCode) + .MapTo(); + list.Add(OrganizeOutputDto); + } + + return list; + } + + /// + /// ȡڵ֯ + /// + /// ֯Id + /// + public Organize GetRootOrganize(long id) + { + return _repository.Get(id); + } + + /// + /// ɾ + /// + /// Id + /// + /// + public CommonResult DeleteBatchWhere(DeletesInputDto idsInfo, IDbTransaction trans = null) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + for (long i = 0; i < idsInfo.Ids.Length; i++) + { + if (idsInfo.Ids[0] != null) + { + @where = string.Format("ParentId='{0}'", idsInfo.Ids[0]); + IEnumerable list = _repository.GetListWhere(@where); + if (list.Count() > 0) + { + result.ErrMsg = "ܴӼݣɾ"; + return result; + } + } + } + + where = "id in ('" + idsInfo.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + bool bl = repository.DeleteBatchWhere(where); + if (bl) + { + result.ErrCode = "0"; + } + + return result; + } + + /// + /// ɾ + /// + /// Id + /// + /// + public async Task DeleteBatchWhereAsync(DeletesInputDto idsInfo, IDbTransaction trans = null) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + for (long i = 0; i < idsInfo.Ids.Length; i++) + { + if (idsInfo.Ids[0].ToString().Length > 0) + { + @where = string.Format("ParentId='{0}'", idsInfo.Ids[0]); + IEnumerable list = _repository.GetListWhere(@where); + if (list.Count() > 0) + { + result.ErrMsg = "ûӼݣɾ"; + return result; + } + } + } + + where = "id in ('" + idsInfo.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + bool bl = await repository.DeleteBatchWhereAsync(where); + if (bl) + { + result.ErrCode = "0"; + } + + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleAuthorizeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleAuthorizeService.cs new file mode 100644 index 0000000..be8c578 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleAuthorizeService.cs @@ -0,0 +1,133 @@ +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class RoleAuthorizeService : BaseService, IRoleAuthorizeService + { + private readonly IRoleAuthorizeRepository _repository; + + private readonly IMenuRepository menuRepository; + private readonly ISystemTypeRepository systemTypeRepository; + + /// + /// + /// + /// + /// + /// + /// + public RoleAuthorizeService(IRoleAuthorizeRepository repository, IMenuRepository _menuRepository, + ISystemTypeRepository _systemTypeRepository) : base(repository) + { + _repository = repository; + menuRepository = _menuRepository; + systemTypeRepository = _systemTypeRepository; + } + + /// + /// ݽɫĿͲѯȨ + /// + /// ɫId + /// + /// + public IEnumerable GetListRoleAuthorizeByRoleId(string roleIds, string itemType) + { + IEnumerable list = _repository.GetListWhere(string.Format("ItemType in({0}) and ObjectId in ({1}) and ObjectType=1", + itemType, roleIds)); + return list; + } + + /// + /// ȡܲ˵Vue Tree + /// + /// + public async Task> GetAllFunctionTree() + { + string where = " 1=1"; + List reslist = new List(); + IEnumerable listSystemType = await systemTypeRepository.GetListWhereAsync(where); + foreach (SystemType systemType in listSystemType) + { + ModuleFunctionOutputDto menuTreeTableOutputDto = new ModuleFunctionOutputDto + { + Id = systemType.Id, + FullName = systemType.FullName, + FunctionTag = 0, + IsShow = true + }; + + IEnumerable elist = await menuRepository.GetListWhereAsync(" SystemTypeId='" + systemType.Id + "'"); + if (elist.Count() > 0) + { + List list = elist.OrderBy(t => t.SortCode).ToList(); + menuTreeTableOutputDto.Children = GetSubMenus(list, 0).ToList(); + } + + reslist.Add(menuTreeTableOutputDto); + } + + return reslist; + } + + /// + /// ȡӲ˵ݹ + /// + /// + /// Id + /// + private List GetSubMenus(List data, long ParentId) + { + List list = new List(); + List ChilList = data.FindAll(t => t.ParentId == ParentId); + foreach (Menu entity in ChilList) + { + ModuleFunctionOutputDto menuTreeTableOutputDto = new ModuleFunctionOutputDto + { + Id = entity.Id, + FullName = entity.FullName, + IsShow = false + }; + if (entity.MenuType == "F") + { + menuTreeTableOutputDto.FunctionTag = 2; + } + else + { + menuTreeTableOutputDto.FunctionTag = 1; + } + + menuTreeTableOutputDto.Children = GetSubMenus(data, entity.Id).MapTo(); + list.Add(menuTreeTableOutputDto); + } + + return list; + } + + /// + /// ɫȨ + /// + /// ɫId + /// ɫģ + /// ɫɷ + /// + /// ִгɹtrueΪfalse + public async Task SaveRoleAuthorize(long roleId, List roleAuthorizesList, + List roleDataList, + IDbTransaction trans = null) + { + return await _repository.SaveRoleAuthorize(roleId, roleAuthorizesList, roleDataList); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleDataService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleDataService.cs new file mode 100644 index 0000000..b059ed1 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleDataService.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + public class RoleDataService : BaseService, IRoleDataService + { + private readonly IRoleDataRepository _repository; + + public RoleDataService(IRoleDataRepository repository) : base(repository) + { + _repository = repository; + } + + /// + /// ݽɫȨʲ + /// + /// + /// + public List GetListDeptByRole(string roleIds) + { + return _repository.GetListDeptByRole(roleIds); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleService.cs new file mode 100644 index 0000000..d0923c3 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/RoleService.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + public class RoleService : BaseService, IRoleService + { + private readonly IRoleRepository _repository; + private readonly IOrganizeService _organizeService; + + public RoleService(IRoleRepository repository, IOrganizeService organizeService) : + base(repository) + { + _repository = repository; + _organizeService = organizeService; + } + + /// + /// ݽɫȡɫ + /// + /// + /// + public Role GetRole(string enCode) + { + string where = string.Format("EnCode='{0}'", enCode); + return _repository.GetWhere(where); + } + + /// + /// ûɫIDȡɫ + /// + /// ɫIDַá,ָ + /// + public string GetRoleEnCode(string ids) + { + string roleIDsStr = string.Format("'{0}'", ids.Replace(",", "','")); + string sqlWhere = string.Format("Id in({0})", roleIDsStr); + IEnumerable listRoles = _repository.GetListWhere(sqlWhere); + string strEnCode = string.Empty; + foreach (Role item in listRoles) + { + strEnCode += item.EnCode + ","; + } + + return strEnCode; + } + + /// + /// ûɫIDȡɫ + /// + /// ɫIDַá,ָ + /// + public string GetRoleNameStr(string ids) + { + string roleIDsStr = string.Format("'{0}'", ids.Replace(",", "','")); + string sqlWhere = string.Format("Id in({0})", roleIDsStr); + IEnumerable listRoles = _repository.GetListWhere(sqlWhere); + string strEnCode = string.Empty; + foreach (Role item in listRoles) + { + strEnCode += item.FullName + ","; + } + + return strEnCode; + } + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + public override async Task> FindWithPagerAsync(SearchInputDto search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and (FullName like '%{0}%' or EnCode like '%{0}%')", search.Keywords); + }; + where += " and Category=1"; + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + List resultList = list.MapTo(); + List listResult = new List(); + foreach (RoleOutputDto item in resultList) + { + if (!string.IsNullOrEmpty(item.OrganizeId.ToString())) + { + item.OrganizeName = _organizeService.Get(item.OrganizeId).FullName; + } + + listResult.Add(item); + } + + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = listResult.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/StatisticalService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/StatisticalService.cs new file mode 100644 index 0000000..d2c4664 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/StatisticalService.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + public class StatisticalService : BaseService, IStatisticalService + { + private readonly IStatisticalRepository _statisticalRepository; + private readonly IUserService _userService; + private readonly ICompanyService _companyService; + private readonly IVehicleService _vehicleService; + + public StatisticalService(IStatisticalRepository repository, + IUserService userService, + ICompanyService companyService, + IVehicleService vehicleService + ) : base(repository) + { + _statisticalRepository = repository; + _userService = userService; + _companyService = companyService; + _vehicleService = vehicleService; + } + + /// + /// 첽ҳѯ + /// + /// + /// + public async Task> FindWithPagerSearchAsync(SearchUserModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.StartTime)) + { + @where += " and CreatedTime >='" + search.StartTime + " 00:00:00'"; + } + + if (!string.IsNullOrEmpty(search.EndTime)) + { + @where += " and CreatedTime <='" + search.EndTime + " 23:59:59'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await _statisticalRepository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + List listDto = list.MapTo(); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = listDto, + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// 첽 + /// + /// + public async Task InsertAsync() + { + CommonResult result = new CommonResult(); + var statistical = await _statisticalRepository.GetStatisticalAsync(); + var userAddTotal = await _userService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"); + Statistical info = new Statistical() + { + Id = Yitter.IdGenerator.YitIdHelper.NextId(), + Time = DateTime.Now.ToString("yyyy-MM-dd"), + UserAddTotal = userAddTotal, + UserSumTotal = await _userService.GetCountByWhereAsync(" Status=1"), + CompanyAddTotal = await _companyService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"), + CompanySumTotal = await _companyService.GetCountByWhereAsync("Status = 1"), + VehicleAddTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"), + VehicleSumTotal = await _vehicleService.GetCountByWhereAsync("Status = 1"), + ExpireAddTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(ExpireTime) = dayofmonth(now()) and Status=1"), + ExpireSumTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(ExpireTime) < dayofmonth(now()) and Status=1"), + ModifiedTime = DateTime.Now, + CreatedTime = DateTime.Now + }; + if (statistical == null) + { + info.UserAddTotalPercent = 0; + } + else + { + info.UserAddTotalPercent = StringHelper.GetPercent(userAddTotal, statistical.UserSumTotal); + } + long ln = await _statisticalRepository.InsertAsync(info).ConfigureAwait(false); + result.Success = ln > 0 ? true : false; + return result; + } + + /// + /// ȡһ + /// + /// + public async Task GetStatisticalAsync() + { + var statistical = await _statisticalRepository.GetStatisticalAsync(); + return statistical; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/SystemTypeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/SystemTypeService.cs new file mode 100644 index 0000000..8de16d6 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/SystemTypeService.cs @@ -0,0 +1,111 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class SystemTypeService : BaseService, ISystemTypeService + { + private readonly ISystemTypeRepository _repository; + private readonly IRoleAuthorizeService roleAuthorizeService; + + /// + /// + /// + /// + /// + public SystemTypeService( + ISystemTypeRepository repository, + IRoleAuthorizeService _roleAuthorizeService) : base(repository) + { + _repository = repository; + roleAuthorizeService = _roleAuthorizeService; + } + + /// + /// ϵͳѯϵͳ + /// + /// ϵͳ + /// + public SystemType GetByCode(string appkey) + { + return _repository.GetByCode(appkey); + } + + /// + /// ݽɫȡԷϵͳ + /// + /// ɫId',' + /// + public List GetSubSystemList(string roleIds) + { + string roleIDsStr = string.Empty; + if (roleIds.IndexOf(',') > 0) + { + roleIDsStr = string.Format("'{0}'", roleIds.Replace(",", "','")); + } + else + { + roleIDsStr = string.Format("'{0}'", roleIds); + } + + IEnumerable roleAuthorizes = roleAuthorizeService.GetListRoleAuthorizeByRoleId(roleIDsStr, "0"); + string strWhere = string.Empty; + if (roleAuthorizes.Count() > 0) + { + strWhere = " Id in ("; + foreach (RoleAuthorize item in roleAuthorizes) + { + strWhere += "'" + item.ItemId + "',"; + } + + strWhere = strWhere.Substring(0, strWhere.Length - 1) + ")"; + } + + List list = _repository.GetAllByIsNotDeleteAndEnabledMark(strWhere).OrderBy(t => t.SortCode).ToList() + .MapTo(); + return list; + } + + /// + /// ѯݿ,ض󼯺(ڷҳʾ) + /// + /// ѯ + /// ָļ + public override async Task> FindWithPagerAsync( + SearchInputDto search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and (FullName like '%{0}%' or EnCode like '%{0}%')", search.Keywords); + }; + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/UploadFileService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/UploadFileService.cs new file mode 100644 index 0000000..920d0ab --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/UploadFileService.cs @@ -0,0 +1,70 @@ +using System.Data; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class UploadFileService : BaseService, IUploadFileService + { + private readonly IUploadFileRepository _uploadFileRepository; + + public UploadFileService(IUploadFileRepository repository) : base(repository) + { + _uploadFileRepository = repository; + } + + /// + /// 根据应用Id和应用标识批量更新数据 + /// + /// 应用Id + /// 更新前旧的应用Id + /// 应用标识 + /// + /// + public bool UpdateByBeLongAppId(string beLongAppId, string oldBeLongAppId, string belongApp = null, + IDbTransaction trans = null) + { + return _uploadFileRepository.UpdateByBeLongAppId(beLongAppId, oldBeLongAppId, belongApp, trans); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// 查询的条件 + /// 指定对象的集合 + public override async Task> FindWithPagerAsync( + SearchInputDto search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and FileName like '%{0}%' ", search.Keywords); + }; + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + System.Collections.Generic.List list = await repository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list.MapTo(), + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/UserService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/UserService.cs new file mode 100644 index 0000000..dae08a4 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/UserService.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Const; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class UserService : BaseService, IUserService + { + private readonly IUserRepository _dcUserRepository; + + public UserService(IUserRepository repository + ) : base(repository) + { + _dcUserRepository = repository; + } + + public async Task> FindWithPagerSearchAsync(SearchUserModel search) + { + bool order = search.Order != "asc"; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and (UserName like '%{0}%' or Account like '%{0}%' )", search.Keywords); + } + + //if (search.Status > (int)CommonStatus.DELETED) + //{ + // @where += string.Format(" and Status={0}", search.Status); + //} + if (!string.IsNullOrEmpty(search.StartTime)) + { + @where += " and CreatedTime >='" + search.StartTime + " 00:00:00'"; + } + + if (!string.IsNullOrEmpty(search.EndTime)) + { + @where += " and CreatedTime <='" + search.EndTime + " 23:59:59'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await _dcUserRepository.UserPagerAsync(where, pagerInfo, search.Sort, order); + foreach (var item in list) + { + item.AvatarUrl = CommonConst.Default_Image_Prefix + item.AvatarUrl; + } + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = list, + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// ޸û״̬ + /// + /// + /// ״̬ + /// + public async Task UpdateStatusAsync(long id, int status) + { + CommonResult result = new CommonResult(); + User info = await _dcUserRepository.GetAsync(id); + if (!(info?.Id > 0)) + { + result.Success = false; + result.ErrMsg = "ûϢ"; + return result; + } + info.Status = status; + await _dcUserRepository.UpdateAsync(info, info.Id).ConfigureAwait(false); + result.Success = true; + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/VehicleChangeService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/VehicleChangeService.cs new file mode 100644 index 0000000..65befde --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/VehicleChangeService.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Yitter.IdGenerator; +using Znyc.Admin.Commons.Const; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.MongoDb.Core.Collection; +using Znyc.Admin.MongoDb.Core.IRepositorys; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class VehicleChangeService : BaseService, IVehicleChangeService + { + private readonly IVehicleChangeRepository _vehicleChangeRepository; + private readonly IVehicleRepository _vehicleRepository; + private readonly IGpsRealTimeRepository _gpsRealTimeRepository; + private readonly ICompanyRepository _companyRepository; + private readonly IVehicleGroupRepository _vehicleGroupRepository; + private readonly IDictionaryService _dcDictionaryService; + + public VehicleChangeService(IVehicleChangeRepository vehicleChangeRepository, + IVehicleRepository vehicleRepository, + IGpsRealTimeRepository gpsRealTimeRepository, + ICompanyRepository companyRepository, + IVehicleGroupRepository vehicleGroupRepository, + IDictionaryService dcDictionaryService + ) : base(vehicleChangeRepository) + { + _vehicleChangeRepository = vehicleChangeRepository; + _vehicleRepository = vehicleRepository; + _gpsRealTimeRepository = gpsRealTimeRepository; + _companyRepository = companyRepository; + _vehicleGroupRepository = vehicleGroupRepository; + _dcDictionaryService = dcDictionaryService; + } + + /// + /// ҳѯװ¼ + /// + /// + /// + public async Task> FindWithPagerSearchAsync(SearchVehicleChangeModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + @where += string.Format(@" and VehicleId = {0}", search.VehicleId); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and (ImeiNo like '%{0}%' or SimNo like '%{0}%' or TerminalNo like '{0}')", search.Keywords); + } + + if (!string.IsNullOrEmpty(search.StartTime)) + { + @where += " and CreatedTime >='" + search.StartTime + " 00:00:00'"; + } + + if (!string.IsNullOrEmpty(search.EndTime)) + { + @where += " and CreatedTime <='" + search.EndTime + " 23:59:59'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await _vehicleChangeRepository.FindWithPagerAsync(where, pagerInfo, search.Sort, order); + List outputDtos = list.MapTo(); + foreach (var item in outputDtos) + { + item.TerminalTypeName = EnumExtensions.GetDescription(typeof(TerminalTypeEnum), (int)TerminalTypeEnum.BSJKGM_08) ?? CommonConst.Unknown_TerminalType; + item.CardTypeName = EnumExtensions.GetDescription(typeof(CardTypeEnum), (int)CardTypeEnum.Beijing_Mobile) ?? CommonConst.Unknown_CardType; + } + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = outputDtos, + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + /// + /// װ¼ + /// + /// + /// + public async Task InsertAsync(VehicleChange entity) + { + CommonResult result = new CommonResult(); + Vehicle info = await _vehicleRepository.GetAsync(entity.VehicleId); + if (!(info?.Id > 0)) + { + result.Success = false; + result.ErrMsg = ReturnConst.Vehicle_Not_Exist; + return result; + } + string where = string.Format(@" (SimNo='{0}' or ImeiNo='{1}') AND Status=1 AND Id!={2}", entity.SimNo, entity.ImeiNo,entity.VehicleId); + Vehicle repeatVehicle = await _vehicleRepository.GetWhereAsync(where); + if (repeatVehicle != null) + { + result.Success = false; + result.ErrMsg = string.Format(ReturnConst.Vehicle_Equipment_Repeat, repeatVehicle.VehiclePlate); + return result; + } + VehicleChange vehicleChange = new VehicleChange() + { + Id = YitIdHelper.NextId(), + CompanyId = info.CompanyId, + VehicleId = info.Id, + CardType = info.CardType, + TerminalType = info.TerminalType, + SimNo = info.SimNo, + ImeiNo = info.ImeiNo, + AgreementNo=info.AgreementNo, + TerminalNo = info.TerminalNo, + ChangeTime = entity.ChangeTime, + UpdateTime = entity.UpdateTime, + Note = entity.Note, + CreatedTime = DateTime.Now, + CreatedUserId = entity.CreatedUserId + }; + await _vehicleChangeRepository.InsertAsync(vehicleChange); + + info.CardType = entity.CardType; + info.TerminalType = entity.TerminalType; + info.SimNo = entity.SimNo; + info.ImeiNo = entity.ImeiNo; + info.TerminalNo = entity.ImeiNo; + info.AgreementNo = entity.AgreementNo ?? ""; + info.ModifiedUserId = entity.ModifiedUserId; + info.ModifiedTime = entity.ModifiedTime; + await _vehicleRepository.UpdateAsync(info, info.Id).ConfigureAwait(false); + + GpsRealTime gpsRealTime = await _gpsRealTimeRepository.GetGpsRealTime(info.Id); + gpsRealTime.SimNo = entity.SimNo; + gpsRealTime.TerminalNo = info.TerminalNo; + gpsRealTime.Status = info.Status; + result.Success = await _gpsRealTimeRepository.UpdateGpsRealTime(gpsRealTime); + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/VehicleService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/VehicleService.cs new file mode 100644 index 0000000..35fa9fa --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/VehicleService.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Yitter.IdGenerator; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Const; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.MongoDb.Core.Collection; +using Znyc.Admin.MongoDb.Core.IRepositorys; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class VehicleService : BaseService, IVehicleService + + { + private readonly IVehicleRepository _vehicleRepository; + private readonly IGpsRealTimeRepository _gpsRealTimeRepository; + private readonly ICompanyRepository _companyRepository; + private readonly IVehicleGroupRepository _vehicleGroupRepository; + private readonly ICacheService _cacheService; + public VehicleService(IVehicleRepository repository, + IGpsRealTimeRepository gpsRealTimeRepository, + ICompanyRepository companyRepository, + IVehicleGroupRepository vehicleGroupRepository, + ICacheService cacheService + ) : base(repository) + { + _vehicleRepository = repository; + _gpsRealTimeRepository = gpsRealTimeRepository; + _companyRepository = companyRepository; + _vehicleGroupRepository = vehicleGroupRepository; + _cacheService = cacheService; + } + + /// + /// ҳѯϢ + /// + /// + /// + public async Task> FindWithPagerSearchAsync(SearchVehicleModel search) + { + bool order = search.Order == "asc" ? false : true; + string where = GetDataPrivilege(false); + if (!string.IsNullOrEmpty(search.Keywords)) + { + @where += string.Format(" and (VehicleCode like '%{0}%' or SimNo like '%{0}%' or VehiclePlate like '%{0}%' or ImeiNo like '%{0}%' )", search.Keywords); + } + if (search.CompanyId > 0) + { + @where += string.Format(" and CompanyId={0}", search.CompanyId); + } + if (search.Status > (int)CommonStatus.DELETED) + { + @where += string.Format(" and Status={0}", search.Status); + } + if (!string.IsNullOrEmpty(search.StartTime)) + { + @where += " and CreatedTime >='" + search.StartTime + " 00:00:00'"; + } + + if (!string.IsNullOrEmpty(search.EndTime)) + { + @where += " and CreatedTime <='" + search.EndTime + " 23:59:59'"; + } + + PagerInfo pagerInfo = new PagerInfo + { + CurrenetPageIndex = search.CurrenetPageIndex, + PageSize = search.PageSize + }; + List list = await repository.FindWithPagerAsync(where, pagerInfo, "ImeiNo", order); + List vehicleOutputDto = list.MapTo(); + foreach (var item in vehicleOutputDto) + { + item.TerminalTypeName = EnumExtensions.GetDescription(typeof(TerminalTypeEnum), (int)TerminalTypeEnum.BSJKGM_08) ?? CommonConst.Unknown_TerminalType; + item.CardTypeName = EnumExtensions.GetDescription(typeof(CardTypeEnum), (int)CardTypeEnum.Beijing_Mobile) ?? CommonConst.Unknown_CardType; + } + PageResult pageResult = new PageResult + { + CurrentPage = pagerInfo.CurrenetPageIndex, + Items = vehicleOutputDto, + ItemsPerPage = pagerInfo.PageSize, + TotalItems = pagerInfo.RecordCount + }; + return pageResult; + } + + /// + /// Ϣ + /// + /// + /// + public async Task InsertAsync(Vehicle entity) + { + CommonResult result = new CommonResult(); + //1. + //2.ʼgpsϢ + VehicleGroup vehicleGroup = await _vehicleGroupRepository.GetWhereAsync(" CompanyId=" + entity.CompanyId); + string where = string.Format(@"(CompanyId={0} and VehicleCode='{1}') or (VehiclePlate='{2}' AND Status=1)", entity.CompanyId, entity.VehicleCode, entity.VehiclePlate); + Vehicle car = await _vehicleRepository.GetWhereAsync(where); + if (car != null) + { + result.Success = false; + result.ErrMsg = ReturnConst.Vehicle_Repeat; + return result; + } + string key = string.Format(@" (SimNo='{0}' or ImeiNo='{1}') AND Status=1", entity.SimNo, entity.ImeiNo); + Vehicle repeatVehicle = await _vehicleRepository.GetWhereAsync(key); + if (repeatVehicle != null) + { + result.Success = false; + result.ErrMsg = string.Format(ReturnConst.Vehicle_Equipment_Repeat, repeatVehicle.VehiclePlate); + return result; + } + entity.Id = YitIdHelper.NextId(); + entity.VehicleType = 1; + entity.VehicleGroup = vehicleGroup.Id; + entity.TerminalNo = entity.ImeiNo; + entity.AgreementNo = entity.AgreementNo ?? ""; + entity.DriverPhone = ""; + entity.VehicleDriver = 0; + entity.ContactPerson = ""; + entity.ContactPhone = ""; + entity.Acc = 0; + entity.Work = 0; + entity.GpsState = 0; + entity.IsActivate = true; + entity.IsGps = true; + entity.Status = (int)CommonStatus.ENABLE; + entity.GpsTime = new DateTime(1990, 1, 1); + entity.IsOverspeedAlarm = false; + entity.Overspeed = CommonConst.DEFAULT_OVERSPEED; + entity.Sort = entity.Sort; + await _vehicleRepository.InsertAsync(entity); + Vehicle vehicle = await _vehicleRepository.GetWhereAsync(" Id=" + entity.Id); + Company company = await _companyRepository.GetWhereAsync(" Id=" + entity.CompanyId); + GpsRealTime gpsRealTime = new GpsRealTime + { + VehicleId = vehicle.Id, + VehicleCode = vehicle.VehicleCode, + VehiclePlate = vehicle.VehiclePlate, + VehicleDriver = vehicle.VehicleDriver, + DriverPhone = vehicle.DriverPhone, + Status = (int)CommonStatus.ENABLE, + GpsState = 0, + GpsTime = Convert.ToDateTime("1900-01-01 8:00:00.000"), //new DateTime(1990, 1, 1), + RecTime = Convert.ToDateTime("1900-01-01 8:00:00.000"), //new DateTime(1990, 1, 1), + Longitude = company.Longitude, + Latitude = company.Latitude, + Direct = 0, + Speed = 0, + Acc = 0, + Address = "", + DurationTime = "", + AccDurationTime = "", + SimNo = vehicle.SimNo, + CompanyId = company.Id, + TerminalNo = vehicle.TerminalNo, + ModifiedTime = DateTime.Now, + CreatedTime = DateTime.Now + }; + await _gpsRealTimeRepository.InsertGpsRealTime(gpsRealTime); + result.Success = true; + //б + await _cacheService.RemoveAsync(CacheKey.CACHE_KEY_VehicleByCompanyId + $"{company.Id}"); + return result; + } + + /// + /// ³Ϣ + /// + /// + /// + public async Task UpdateAsync(Vehicle tinfo) + { + CommonResult result = new CommonResult(); + Vehicle info = await repository.GetAsync(tinfo.Id); + GpsRealTime gpsRealTime = await _gpsRealTimeRepository.GetGpsRealTime(info.Id); + if (!(info?.Id > 0) || gpsRealTime == null) + { + result.Success = false; + result.ErrMsg = ReturnConst.Vehicle_Not_Exist; + return result; + } + string where = string.Format(@" (SimNo='{0}' or ImeiNo='{1}') AND Status=1 AND Id !={2}", tinfo.SimNo, tinfo.ImeiNo, tinfo.Id); + Vehicle repeatVehicle = await _vehicleRepository.GetWhereAsync(where); + if (repeatVehicle != null) + { + result.Success = false; + result.ErrMsg = string.Format(ReturnConst.Vehicle_Equipment_Repeat, repeatVehicle.VehiclePlate); + return result; + } + info.VehicleCode = tinfo.VehicleCode; + info.VehiclePlate = tinfo.VehiclePlate; + info.CardType = tinfo.CardType; + info.TerminalType = tinfo.TerminalType; + info.SimNo = tinfo.SimNo; + info.ImeiNo = tinfo.ImeiNo; + info.TerminalNo = tinfo.ImeiNo; + info.OpenTime = tinfo.OpenTime; + info.ExpireTime = tinfo.ExpireTime; + info.ModifiedUserId = tinfo.ModifiedUserId; + info.ModifiedTime = tinfo.ModifiedTime; + info.Sort = tinfo.Sort; + await repository.UpdateAsync(info, tinfo.Id).ConfigureAwait(false); + gpsRealTime.VehicleCode = tinfo.VehicleCode; + gpsRealTime.VehiclePlate = tinfo.VehiclePlate; + gpsRealTime.SimNo = tinfo.SimNo; + gpsRealTime.TerminalNo = info.TerminalNo; + gpsRealTime.Status = info.Status; + + result.Success = await _gpsRealTimeRepository.UpdateGpsRealTime(gpsRealTime); + await ClearVelicleCacheAsync(info.Id, info.CompanyId); + return result; + } + + /// + /// ޸ij״̬ + /// + /// + /// ״̬ + /// + public async Task UpdateStatusAsync(long id, int status) + { + CommonResult result = new CommonResult(); + Vehicle info = await repository.GetAsync(id); + GpsRealTime gpsRealTime = await _gpsRealTimeRepository.GetGpsRealTime(id); + if (!(info?.Id > 0) || gpsRealTime == null) + { + result.Success = false; + result.ErrMsg = ReturnConst.Vehicle_Not_Exist; + return result; + } + info.Status = status; + gpsRealTime.Status = status; + await repository.UpdateAsync(info, info.Id).ConfigureAwait(false); + result.Success = await _gpsRealTimeRepository.UpdateGpsRealTime(gpsRealTime); + + await ClearVelicleCacheAsync(info.Id, info.CompanyId); + + return result; + } + + /// + /// ޸ijǷ񼤻 + /// + /// + /// ״̬ + /// + public async Task UpdateIsActivateAsync(long id, bool isActivate) + { + CommonResult result = new CommonResult(); + Vehicle info = await repository.GetAsync(id); + if (!(info?.Id > 0)) + { + result.Success = false; + result.ErrMsg = ReturnConst.Vehicle_Not_Exist; + return result; + } + info.IsActivate = isActivate; + await repository.UpdateAsync(info, info.Id).ConfigureAwait(false); + await ClearVelicleCacheAsync(info.Id, info.CompanyId); + + result.Success = true; + return result; + } + + /// + /// ޸ijǷGPS + /// + /// + /// ״̬ + /// + public async Task UpdateIsGpsAsync(long id, bool isGps) + { + CommonResult result = new CommonResult(); + Vehicle info = await repository.GetAsync(id); + if (!(info?.Id > 0)) + { + result.Success = false; + result.ErrMsg = ReturnConst.Vehicle_Not_Exist; + return result; + } + info.IsGps = isGps; + await repository.UpdateAsync(info, info.Id).ConfigureAwait(false); + result.Success = true; + await ClearVelicleCacheAsync(info.Id, info.CompanyId); + + return result; + } + + + /// + /// + /// + /// + /// + /// + public async Task ClearVelicleCacheAsync(long velicId, long companyId) + { + // + await _cacheService.RemoveAsync(CacheKey.CACHE_KEY_VehicleByCompanyId + $"{companyId}"); + await _cacheService.RemoveAsync(CacheKey.CACHE_KEY_Vehicle + $"{velicId}"); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/WxUserRelationService.cs b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/WxUserRelationService.cs new file mode 100644 index 0000000..f8c0e79 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Services/Dispatching/WxUserRelationService.cs @@ -0,0 +1,71 @@ +using Senparc.Weixin.MP.CommonAPIs; +using Senparc.Weixin.MP.Containers; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Yitter.IdGenerator; +using Znyc.Admin.Commons.Const; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Commons.Services; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Dtos.WxUserRelation; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.Entitys.Dispatching; +using Znyc.Admin.Security.IRepositories; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.Security.Services +{ + /// + /// + /// + public class WxUserRelationService : BaseService, IWxUserRelationService + { + private readonly IWxUserRelationRepository _repository; + + public WxUserRelationService(IWxUserRelationRepository repository + ) : base(repository) + { + _repository = repository; + } + + /// + /// + /// + /// + /// + public async Task UpdateAsync(string wxOpenId) + { + CommonResult result = new CommonResult(); + await AccessTokenContainer.RegisterAsync("wx07c574aca93ae8d9", "2d202f91258131f63565e11bdb065f6b"); + var wxUser = CommonApi.GetUserInfo("wx07c574aca93ae8d9", wxOpenId); + + + string where = string.Format("unionId='{0}'", wxUser.unionid); + var wxUserRelation = await GetWhereAsync(where); + if (wxUserRelation != null) + { + wxUserRelation.WxOfficialOpenId = wxOpenId; + wxUserRelation.ModifiedTime = DateTime.Now; + await _repository.UpdateAsync(wxUserRelation, wxUserRelation.Id); + } + else + { + await _repository.InsertAsync(new WxUserRelation() + { + Id = YitIdHelper.NextId(), + OpenId = "", + UnionId = wxUser.unionid, + WxOfficialOpenId = wxOpenId + }); + + } + + result.Success = true; + return result; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Yuebon.Security.Core.csproj b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Yuebon.Security.Core.csproj new file mode 100644 index 0000000..19c7747 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Yuebon.Security.Core.csproj @@ -0,0 +1,92 @@ + + + + Library + net5.0 + + + ZNYC.Admin.Security + 上海越邦网络科技有限公司 + 上海越邦网络科技有限公司 版权所有 + YuebonNetCore开发框架权限管理系统类库 + YuebonNetCore开发框架权限管理系统类库 + true + 1.3.2.32 + 更新最新公共库 + Yuebon + true + + https://gitee.com/yuebon/YuebonNetCore + + https://gitee.com/yuebon/YuebonNetCore + LICENSE + logo.png + 1.3.2.32 + 1.3.2.32 + + + + + + + + + bin\Release\ + bin\Release\ZNYC.Admin.Security.Core.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + + + + True + + + + + + + + + diff --git a/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Znyc.Admin.Security.Core.csproj b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Znyc.Admin.Security.Core.csproj new file mode 100644 index 0000000..49a5576 --- /dev/null +++ b/Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Znyc.Admin.Security.Core.csproj @@ -0,0 +1,82 @@ + + + + Library + net6.0 + + + Znyc.Admin.Security + + + + + true + 1.0 + 更新最新公共库 + Znyc.Admin + true + + + + + + 1.3.2.32 + 1.3.2.32 + MIT + + + + + + + + + bin\Release\ + bin\Release\Znyc.Admin.Security.Core.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/Download/CodeRecord.cs b/Znyc.Admin.WeChat.Core/CommonService/Download/CodeRecord.cs new file mode 100644 index 0000000..b5a488c --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/Download/CodeRecord.cs @@ -0,0 +1,15 @@ +using Senparc.Weixin.MP.AdvancedAPIs.QrCode; + +namespace Znyc.Admin.WeChat.CommonService.Download +{ + public class CodeRecord + { + public string Key { get; set; } + public int QrCodeId { get; set; } + public CreateQrCodeResult QrCodeTicket { get; set; } + public string Version { get; set; } + public bool Used { get; set; } + public bool AllowDownload { get; set; } + public bool IsWebVersion { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/Download/Config.cs b/Znyc.Admin.WeChat.Core/CommonService/Download/Config.cs new file mode 100644 index 0000000..fe13bc5 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/Download/Config.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace Znyc.WeChat.CommonService.Download +{ + public class Config + { + public int QrCodeId { get; set; } + + /// + /// chm版 + /// + public List Versions { get; set; } + + /// + /// 网页版 + /// + public List WebVersions { get; set; } + + public int DownloadCount { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/Download/ConfigHelper.cs b/Znyc.Admin.WeChat.Core/CommonService/Download/ConfigHelper.cs new file mode 100644 index 0000000..18003a2 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/Download/ConfigHelper.cs @@ -0,0 +1,111 @@ +using Senparc.CO2NET.Utilities; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Znyc.WeChat.CommonService.Download; + +namespace Znyc.Admin.WeChat.CommonService.Download +{ + public class ConfigHelper + { + //Key:guid,Value: + public static Dictionary CodeCollection = + new Dictionary(StringComparer.OrdinalIgnoreCase); + + public static object Lock = new object(); + + public ConfigHelper() + { + } + + private string GetDatabaseFilePath() + { + return ServerUtility.ContentRootMapPath("~/App_Data/Document/Config.xml"); + } + + private XDocument GetXDocument() + { + XDocument doc = XDocument.Load(GetDatabaseFilePath()); + return doc; + } + + /// + /// 获取配置文件 + /// + /// + /// + public Config GetConfig() + { + XDocument doc = GetXDocument(); + Config config = new Config() + { + QrCodeId = int.Parse(doc.Root.Element("QrCodeId").Value), + DownloadCount = int.Parse(doc.Root.Element("DownloadCount").Value), + Versions = doc.Root.Element("Versions").Elements("Version").Select(z => z.Value).ToList(), + WebVersions = doc.Root.Element("WebVersions").Elements("Version").Select(z => z.Value).ToList() + }; + return config; + } + + /// + /// 获取一个二维码场景标示(自增,唯一) + /// + /// + public int GetQrCodeId() + { + lock (Lock) + { + Config config = GetConfig(); + config.QrCodeId++; + Save(config); + return config.QrCodeId; + } + } + + public void Save(Config config) + { + XDocument doc = GetXDocument(); + doc.Root.Element("QrCodeId").Value = config.QrCodeId.ToString(); + doc.Root.Element("DownloadCount").Value = config.DownloadCount.ToString(); + doc.Root.Element("Versions").Elements().Remove(); + foreach (string version in config.Versions) + { + doc.Root.Element("Versions").Add(new XElement("Version", version)); + } +#if NET45 + doc.Save(GetDatabaseFilePath()); +#else + using (FileStream fs = new FileStream(GetDatabaseFilePath(), FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { + doc.Save(fs); + } +#endif + } + + public string Download(string version, bool isWebVersion) + { + lock (Lock) + { + Config config = GetConfig(); + config.DownloadCount++; + Save(config); + } + + //打包下载文件 + //FileStream fs = new FileStream(_context.ServerUtility.ContentRootMapPath(string.Format("~/App_Data/Document/Files/Senparc.Weixin-v{0}.rar", version)), FileMode.Open); + //return fs; + + string filePath = ServerUtility.ContentRootMapPath(string.Format( + "~/App_Data/Document/Files/Senparc.Weixin{0}-v{1}.rar", isWebVersion ? "-Web" : "", version)); + if (!File.Exists(filePath)) + { + //使用.zip文件 + filePath = filePath.Replace(".rar", ".zip"); + } + + return filePath; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/EventService.cs b/Znyc.Admin.WeChat.Core/CommonService/EventService.cs new file mode 100644 index 0000000..76fd576 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/EventService.cs @@ -0,0 +1,166 @@ +using Senparc.CO2NET.Trace; +using Senparc.CO2NET.Utilities; +using Senparc.NeuChar.Entities; +using Senparc.NeuChar.Helpers; +using Senparc.Weixin; +using Senparc.Weixin.Exceptions; +using Senparc.Weixin.MP; +using Senparc.Weixin.MP.Entities; +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Znyc.Admin.WeChat.CommonService.TemplateMessage; + +namespace Znyc.Admin.WeChat.CommonService +{ + /// + /// 全局微信事件有关的处理程序 + /// + public class EventService + { + /// + /// 微信MessageHandler事件处理,此代码的简化MessageHandler方法已由/CustomerMessageHandler/CustomerMessageHandler_Event.cs完成, + /// 此方法不再更新 + /// + /// + /// + public ResponseMessageBase GetResponseMessage(RequestMessageEventBase requestMessage) + { + ResponseMessageBase responseMessage = null; + switch (requestMessage.Event) + { + case Event.ENTER: + { + ResponseMessageText strongResponseMessage = requestMessage.CreateResponseMessage(); + strongResponseMessage.Content = "您刚才发送了ENTER事件请求。"; + responseMessage = strongResponseMessage; + break; + } + case Event.LOCATION: + throw new Exception("暂不可用"); + //break; + case Event.subscribe: //订阅 + { + ResponseMessageText strongResponseMessage = requestMessage.CreateResponseMessage(); + + //获取Senparc.Weixin.MP.dll版本信息 +#if NET45 + var dllPath = HttpContext.Current.Server.MapPath("~/bin/Senparc.Weixin.MP.dll"); +#else + //var dllPath = ServerUtility.ContentRootMapPath("~/bin/Release/netcoreapp2.2/Senparc.Weixin.MP.dll");//本地测试路径 + string dllPath = ServerUtility.ContentRootMapPath("~/Senparc.Weixin.MP.dll"); //发布路径 +#endif + + FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(dllPath); + + string version = fileVersionInfo.FileVersion; + strongResponseMessage.Content = string.Format( + "欢迎关注【Senparc.Weixin.MP 微信公众平台SDK】,当前运行版本:v{0}。\r\n您还可以发送【位置】【图片】【语音】信息,查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com", + version); + responseMessage = strongResponseMessage; + break; + } + case Event.unsubscribe: //退订 + { + //实际上用户无法收到非订阅账号的消息,所以这里可以随便写。 + //unsubscribe事件的意义在于及时删除网站应用中已经记录的OpenID绑定,消除冗余数据。 + ResponseMessageText strongResponseMessage = requestMessage.CreateResponseMessage(); + strongResponseMessage.Content = "有空再来"; + responseMessage = strongResponseMessage; + break; + } + case Event.CLICK: //菜单点击事件,根据自己需要修改 + //这里的CLICK在此DEMO中不会被执行到,因为已经重写了OnEvent_ClickRequest + break; + + default: + throw new ArgumentOutOfRangeException(); + } + + return responseMessage; + } + + public void ConfigOnWeixinExceptionFunc(WeixinException ex) + { + SenparcTrace.SendCustomLog("进入 ConfigOnWeixinExceptionFunc() 方法", ex.Message); + try + { + Task.Factory.StartNew(async () => + { + string appId = Config.SenparcWeixinSetting.WeixinAppId; + + string openId = ""; //收到通知的管理员OpenId + string host = "A1 / AccessTokenOrAppId:" + (ex.AccessTokenOrAppId ?? "null"); + string service = null; + string message = ex.Message; + string status = ex.GetType().Name; + string remark = "\r\n这是一条通过OnWeixinExceptionFunc事件发送的异步模板消息"; + string url = + "https://github.com/JeffreySu/WeiXinMPSDK/blob/24aca11630bf833f6a4b6d36dce80c5b171281d3/src/Senparc.Weixin.MP.Sample/Senparc.Weixin.MP.Sample/Global.asax.cs#L246"; //需要点击打开的URL + + bool sendTemplateMessage = true; + + if (ex is ErrorJsonResultException) + { + ErrorJsonResultException jsonEx = (ErrorJsonResultException)ex; + service = jsonEx.Url; + message = jsonEx.Message; + + //需要忽略的类型 + ReturnCode[] ignoreErrorCodes = new[] + { + ReturnCode.获取access_token时AppSecret错误或者access_token无效, + ReturnCode.template_id不正确, + ReturnCode.缺少access_token参数, + ReturnCode.api功能未授权, + ReturnCode.用户未授权该api, + ReturnCode.参数错误invalid_parameter, + ReturnCode.接口调用超过限制, + ReturnCode.需要接收者关注 //43004 + + //其他更多可能的情况 + }; + if (ignoreErrorCodes.Contains(jsonEx.JsonResult.errcode)) + { + sendTemplateMessage = false; //防止无限递归,这种请款那个下不发送消息 + } + + //TODO:防止更多的接口自身错误导致的无限递归。 + } + else + { + if (ex.Message.StartsWith("openid:")) + { + openId = ex.Message.Split(':')[1]; //发送给指定OpenId + } + + service = "WeixinException"; + message = ex.Message; + } + + if (sendTemplateMessage) // DPBMARK MP + { + int sleepSeconds = 3; + Thread.Sleep(sleepSeconds * 1000); + WeixinTemplate_ExceptionAlert data = new WeixinTemplate_ExceptionAlert(string.Format("微信发生异常(延时{0}秒)", sleepSeconds), + host, service, status, message, remark); + + //修改OpenId、启用以下代码后即可收到模板消息 + if (!string.IsNullOrEmpty(openId)) + { + Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage.SendTemplateMessageResult result = await Senparc.Weixin.MP.AdvancedAPIs.TemplateApi.SendTemplateMessageAsync( + appId, openId, data.TemplateId, + url, data); + } + } // DPBMARK_END + }); + } + catch (Exception e) + { + SenparcTrace.SendCustomLog("OnWeixinExceptionFunc过程错误", e.Message); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/LocationService.cs b/Znyc.Admin.WeChat.Core/CommonService/LocationService.cs new file mode 100644 index 0000000..0954803 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/LocationService.cs @@ -0,0 +1,92 @@ +using Senparc.CO2NET.Helpers; +using Senparc.CO2NET.Helpers.BaiduMap; +using Senparc.CO2NET.Helpers.GoogleMap; +using Senparc.NeuChar.Entities; +using Senparc.Weixin.MP.Entities; +using System.Collections.Generic; + +namespace Znyc.Admin.WeChat.CommonService +{ + /// + /// 地理位置信息处理 + /// + public class LocationService + { + public ResponseMessageNews GetResponseMessage(RequestMessageLocation requestMessage) + { + ResponseMessageNews responseMessage = ResponseMessageBase.CreateFromRequestMessage(requestMessage); + + #region 百度地图 + + { + List markersList = new List + { + new BaiduMarkers() + { + Longitude = requestMessage.Location_X, + Latitude = requestMessage.Location_Y, + Color = "red", + Label = "S", + Size = BaiduMarkerSize.m + } + }; + + string mapUrl = BaiduMapHelper.GetBaiduStaticMap(requestMessage.Location_X, requestMessage.Location_Y, 1, + 6, markersList); + responseMessage.Articles.Add(new Article() + { + Description = string.Format("【来自百度地图】您刚才发送了地理位置信息。Location_X:{0},Location_Y:{1},Scale:{2},标签:{3}", + requestMessage.Location_X, requestMessage.Location_Y, + requestMessage.Scale, requestMessage.Label), + PicUrl = mapUrl, + Title = "定位地点周边地图", + Url = mapUrl + }); + } + + #endregion 百度地图 + + #region GoogleMap + + { + List markersList = new List + { + new GoogleMapMarkers() + { + X = requestMessage.Location_X, + Y = requestMessage.Location_Y, + Color = "red", + Label = "S", + Size = GoogleMapMarkerSize.Default + } + }; + string mapSize = "480x600"; + string mapUrl = GoogleMapHelper.GetGoogleStaticMap( + 19 /*requestMessage.Scale*/ /*微信和GoogleMap的Scale不一致,这里建议使用固定值*/, + markersList, mapSize); + responseMessage.Articles.Add(new Article() + { + Description = string.Format( + "【来自GoogleMap】您刚才发送了地理位置信息。Location_X:{0},Location_Y:{1},Scale:{2},标签:{3}", + requestMessage.Location_X, requestMessage.Location_Y, + requestMessage.Scale, requestMessage.Label), + PicUrl = mapUrl, + Title = "定位地点周边地图", + Url = mapUrl + }); + } + + #endregion GoogleMap + + responseMessage.Articles.Add(new Article() + { + Title = "微信公众平台SDK 官网链接", + Description = "Senparc.Weixin.MK SDK地址", + PicUrl = "https://sdk.weixin.senparc.com/images/logo.jpg", + Url = "https://sdk.weixin.senparc.com" + }); + + return responseMessage; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/Async/CustomMessageHandlerAsync_Events.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/Async/CustomMessageHandlerAsync_Events.cs new file mode 100644 index 0000000..eeb55a4 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/Async/CustomMessageHandlerAsync_Events.cs @@ -0,0 +1,29 @@ +using Senparc.NeuChar.Entities; +using Senparc.Weixin.MP.Entities; +using System.Threading.Tasks; + +namespace Znyc.Admin.WeChat.CommonService.CustomMessageHandler +{ + /// + /// 自定义MessageHandler + /// + public partial class CustomMessageHandler + { + public override Task OnEvent_ClickRequestAsync(RequestMessageEvent_Click requestMessage) + { + return Task.Factory.StartNew(() => + { + IResponseMessageBase syncResponseMessage = + OnEvent_ClickRequest(requestMessage); //这里为了保持Demo的连贯性,结果先从同步方法获取,实际使用过程中可以全部直接定义异步方法 + //常识获取Click事件的同步方法 + if (syncResponseMessage is ResponseMessageText) + { + ResponseMessageText textResponseMessage = syncResponseMessage as ResponseMessageText; + textResponseMessage.Content += "\r\n\r\n -- 来自【异步MessageHandler】的回复"; + } + + return syncResponseMessage; + }); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageContext.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageContext.cs new file mode 100644 index 0000000..e02ea7e --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageContext.cs @@ -0,0 +1,52 @@ +using Senparc.NeuChar; +using Senparc.NeuChar.Context; +using Senparc.NeuChar.Entities; +using System; +using System.Xml.Linq; + +namespace Znyc.Admin.WeChat.CommonService.CustomMessageHandler +{ + public class CustomMessageContext : MessageContext + { + public CustomMessageContext() + { + base.MessageContextRemoved += CustomMessageContext_MessageContextRemoved; + } + + public override IRequestMessageBase GetRequestEntityMappingResult(RequestMsgType requestMsgType, + XDocument doc = null) + { + throw new NotImplementedException(); + } + + public override IResponseMessageBase GetResponseEntityMappingResult(ResponseMsgType responseMsgType, + XDocument doc = null) + { + throw new NotImplementedException(); + } + + /// + /// 当上下文过期,被移除时触发的时间 + /// + /// + /// + private void CustomMessageContext_MessageContextRemoved(object sender, + WeixinContextRemovedEventArgs e) + { + /* 注意,这个事件不是实时触发的(当然你也可以专门写一个线程监控) + * 为了提高效率,根据WeixinContext中的算法,这里的过期消息会在过期后下一条请求执行之前被清除 + */ + + CustomMessageContext messageContext = e.MessageContext as CustomMessageContext; + if (messageContext == null) + { + return; //如果是正常的调用,messageContext不会为null + } + + //TODO:这里根据需要执行消息过期时候的逻辑,下面的代码仅供参考 + + //Log.InfoFormat("{0}的消息上下文已过期",e.OpenId); + //api.SendMessage(e.OpenId, "由于长时间未搭理客服,您的客服状态已退出!"); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageHandler.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageHandler.cs new file mode 100644 index 0000000..86e3c8e --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageHandler.cs @@ -0,0 +1,656 @@ +/*---------------------------------------------------------------- + Copyright (C) 2019 Senparc + + 文件名:CustomMessageHandler.cs + 文件功能描述:微信公众号自定义MessageHandler + + 创建标识:Senparc - 20150312 + + 修改标识:Senparc - 20171027 + 修改描述:v14.8.3 添加OnUnknownTypeRequest()方法Demo + + 修改标识:Senparc - 20191002 + 修改描述:v16.9.102 提供 MessageHandler 中间件 + +----------------------------------------------------------------*/ + +//DPBMARK_FILE MP + +using Senparc.CO2NET.Helpers; +using Senparc.CO2NET.Trace; +using Senparc.CO2NET.Utilities; +using Senparc.NeuChar.Agents; +using Senparc.NeuChar.Entities; +using Senparc.NeuChar.Entities.Request; +using Senparc.NeuChar.Helpers; +using Senparc.Weixin; +using Senparc.Weixin.Exceptions; +using Senparc.Weixin.MP; +using Senparc.Weixin.MP.AdvancedAPIs; +using Senparc.Weixin.MP.Entities; +using Senparc.Weixin.MP.Entities.Request; +using Senparc.Weixin.MP.MessageHandlers; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Linq; + +#if NET45 +using System.Web; +using System.Configuration; +using System.Web.Configuration; +using Senparc.Weixin.MP.Sample.CommonService.Utilities; +#else +#endif + +namespace Znyc.Admin.WeChat.CommonService.CustomMessageHandler +{ + /// + /// 自定义MessageHandler + /// 把MessageHandler作为基类,重写对应请求的处理方法 + /// + public partial class + CustomMessageHandler : MessageHandler /*如果不需要自定义,可以直接使用:MessageHandler */ + { + /* + * 重要提示:v1.5起,MessageHandler提供了一个DefaultResponseMessage的抽象方法, + * DefaultResponseMessage必须在子类中重写,用于返回没有处理过的消息类型(也可以用于默认消息,如帮助信息等); + * 其中所有原OnXX的抽象方法已经都改为虚方法,可以不必每个都重写。若不重写,默认返回DefaultResponseMessage方法中的结果。 + */ + +#if !DEBUG || NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2 || NETCOREAPP3_0 + string agentUrl = "http://localhost:12222/App/Weixin/4"; + string agentToken = "27C455F496044A87"; + string wiweihiKey = "CNadjJuWzyX5bz5Gn+/XoyqiqMa5DjXQ"; +#else + + //下面的Url和Token可以用其他平台的消息,或者到www.weiweihi.com注册微信用户,将自动在“微信营销工具”下得到 + private string agentUrl = Config.SenparcWeixinSetting.AgentUrl; //这里使用了www.weiweihi.com微信自动托管平台 + + private readonly string agentToken = Config.SenparcWeixinSetting.AgentToken; //Token + + private readonly string + wiweihiKey = + Config.SenparcWeixinSetting + .SenparcWechatAgentKey; //WeiweihiKey专门用于对接www.Weiweihi.com平台,获取方式见:http://www.weiweihi.com/ApiDocuments/Item/25#51 + +#endif + + private readonly string appId = Config.SenparcWeixinSetting.WeixinAppId; + private readonly string appSecret = Config.SenparcWeixinSetting.WeixinAppSecret; + + /// + /// 模板消息集合(Key:checkCode,Value:OpenId) + /// 注意:这里只做测试,只适用于单服务器 + /// + public static Dictionary TemplateMessageCollection = new Dictionary(); + + /// + /// 为中间件提供生成当前类的委托 + /// + public static Func GenerateMessageHandler = + (stream, postModel, maxRecordCount) + => new CustomMessageHandler(stream, postModel, maxRecordCount, false /* 是否只允许处理加密消息,以提高安全性 */); + + public CustomMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = 0, + bool onlyAllowEcryptMessage = false) + : base(inputStream, postModel, maxRecordCount, onlyAllowEcryptMessage) + { + //这里设置仅用于测试,实际开发可以在外部更全局的地方设置, + //比如MessageHandler.GlobalGlobalMessageContext.ExpireMinutes = 3。 + GlobalMessageContext.ExpireMinutes = 3; + + //OnlyAllowEcryptMessage = true;//是否只允许接收加密消息,默认为 false + + if (!string.IsNullOrEmpty(postModel.AppId)) + { + appId = postModel.AppId; //通过第三方开放平台发送过来的请求 + } + + //在指定条件下,不使用消息去重 + OmitRepeatedMessageFunc = requestMessage => + { + RequestMessageText textRequestMessage = requestMessage as RequestMessageText; + if (textRequestMessage != null && textRequestMessage.Content == "容错") + { + return false; + } + + return true; + }; + } + + /// + /// 处理文字请求 + /// + /// 请求消息 + /// + public override async Task OnTextRequestAsync(RequestMessageText requestMessage) + { + //说明:实际项目中这里的逻辑可以交给Service处理具体信息,参考OnLocationRequest方法或/Service/LocationSercice.cs + + #region 书中例子 + + //if (requestMessage.Content == "你好") + //{ + // var responseMessage = base.CreateResponseMessage(); + // var title = "Title"; + // var description = "Description"; + // var picUrl = "PicUrl"; + // var url = "Url"; + // responseMessage.Articles.Add(new Article() + // { + // Title = title, + // Description = description, + // PicUrl = picUrl, + // Url = url + // }); + // return responseMessage; + //} + //else if (requestMessage.Content == "Senparc") + //{ + // //相似处理逻辑 + //} + //else + //{ + // //... + //} + + #endregion 书中例子 + + #region 历史方法 + + //方法一(v0.1),此方法调用太过繁琐,已过时(但仍是所有方法的核心基础),建议使用方法二到四 + //var responseMessage = + // ResponseMessageBase.CreateFromRequestMessage(RequestMessage, ResponseMsgType.Text) as + // ResponseMessageText; + + //方法二(v0.4) + //var responseMessage = ResponseMessageBase.CreateFromRequestMessage(RequestMessage); + + //方法三(v0.4),扩展方法,需要using Senparc.Weixin.MP.Helpers; + //var responseMessage = RequestMessage.CreateResponseMessage(); + + //方法四(v0.6+),仅适合在HandlerMessage内部使用,本质上是对方法三的封装 + //注意:下面泛型ResponseMessageText即返回给客户端的类型,可以根据自己的需要填写ResponseMessageNews等不同类型。 + + #endregion 历史方法 + + ResponseMessageText defaultResponseMessage = base.CreateResponseMessage(); + + RequestMessageTextKeywordHandler requestHandler = await requestMessage.StartHandler() + //关键字不区分大小写,按照顺序匹配成功后将不再运行下面的逻辑 + .Keyword("约束", () => + { + defaultResponseMessage.Content = + @"您正在进行微信内置浏览器约束判断测试。您可以: +点击这里进行客户端约束测试(地址:https://sdk.weixin.senparc.com/FilterTest/),如果在微信外打开将直接返回文字。 +或: +点击这里进行客户端约束测试(地址:https://sdk.weixin.senparc.com/FilterTest/Redirect),如果在微信外打开将重定向一次URL。"; + return defaultResponseMessage; + }). + //匹配任一关键字 + Keywords(new[] { "托管", "代理" }, () => + { + //开始用代理托管,把请求转到其他服务器上去,然后拿回结果 + //甚至也可以将所有请求在DefaultResponseMessage()中托管到外部。 + + DateTimeOffset dt1 = SystemTime.Now; //计时开始 + + string agentXml = RequestDocument.ToString(); + + #region 暂时转发到SDK线上Demo + + agentUrl = "https://sdk.weixin.senparc.com/weixin"; + //agentToken = WebConfigurationManager.AppSettings["WeixinToken"];//Token + + //修改内容,防止死循环 + XDocument agentDoc = XDocument.Parse(agentXml); + agentDoc.Root.Element("Content").SetValue("代理转发文字:" + requestMessage.Content); + agentDoc.Root.Element("CreateTime") + .SetValue(DateTimeHelper.GetUnixDateTime(SystemTime.Now)); //修改时间,防止去重 + agentDoc.Root.Element("MsgId").SetValue("123"); //防止去重 + agentXml = agentDoc.ToString(); + + #endregion 暂时转发到SDK线上Demo + + string responseXml = MessageAgent.RequestXml(this, Senparc.CO2NET.SenparcDI.GetServiceProvider(), + agentUrl, agentToken, agentXml); + //获取返回的XML + //上面的方法也可以使用扩展方法:this.RequestResponseMessage(this,agentUrl, agentToken, RequestDocument.ToString()); + + /* 如果有WeiweihiKey,可以直接使用下面的这个MessageAgent.RequestWeiweihiXml()方法。 + * WeiweihiKey专门用于对接www.weiweihi.com平台,获取方式见:https://www.weiweihi.com/ApiDocuments/Item/25#51 + */ + //var responseXml = MessageAgent.RequestWeiweihiXml(weiweihiKey, RequestDocument.ToString());//获取Weiweihi返回的XML + + DateTimeOffset dt2 = SystemTime.Now; //计时结束 + + //转成实体。 + /* 如果要写成一行,可以直接用: + * responseMessage = MessageAgent.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString()); + * 或 + * + */ + string msg = string.Format("\r\n\r\n代理过程总耗时:{0}毫秒", (dt2 - dt1).Milliseconds); + IResponseMessageBase agentResponseMessage = responseXml.CreateResponseMessage(MessageEntityEnlightener); + if (agentResponseMessage is ResponseMessageText) + { + (agentResponseMessage as ResponseMessageText).Content += msg; + } + else if (agentResponseMessage is ResponseMessageNews) + { + (agentResponseMessage as ResponseMessageNews).Articles[0].Description += msg; + } + + return agentResponseMessage; //可能出现多种类型,直接在这里返回 + }) + .Keywords(new[] { "测试", "退出" }, () => + { + /* + * 这是一个特殊的过程,此请求通常来自于微微嗨(http://www.weiweihi.com)的“盛派网络小助手”应用请求(https://www.weiweihi.com/User/App/Detail/1), + * 用于演示微微嗨应用商店的处理过程,由于微微嗨的应用内部可以单独设置对话过期时间,所以这里通常不需要考虑对话状态,只要做最简单的响应。 + */ + if (defaultResponseMessage.Content == "测试") + { + //进入APP测试 + defaultResponseMessage.Content = + "您已经进入【盛派网络小助手】的测试程序,请发送任意信息进行测试。发送文字【退出】退出测试对话。10分钟内无任何交互将自动退出应用对话状态。"; + } + else + { + //退出APP测试 + defaultResponseMessage.Content = "您已经退出【盛派网络小助手】的测试程序。"; + } + + return defaultResponseMessage; + }) + .Keyword("AsyncTest", () => + { + //异步并发测试(提供给单元测试使用) +#if NET45 + var begin = SystemTime.Now; + int t1, t2, t3; + System.Threading.ThreadPool.GetAvailableThreads(out t1, out t3); + System.Threading.ThreadPool.GetMaxThreads(out t2, out t3); + System.Threading.Thread.Sleep(TimeSpan.FromSeconds(4)); + var end = SystemTime.Now; + var thread = System.Threading.Thread.CurrentThread; + defaultResponseMessage.Content = + string.Format("TId:{0}\tApp:{1}\tBegin:{2:mm:ss,ffff}\tEnd:{3:mm:ss,ffff}\tTPool:{4}", + thread.ManagedThreadId, + HttpContext.Current != null ? HttpContext.Current.ApplicationInstance.GetHashCode() : -1, + begin, + end, + t2 - t1 + ); +#endif + + return defaultResponseMessage; + }) + .Keyword("OPEN", () => + { + ResponseMessageNews openResponseMessage = requestMessage.CreateResponseMessage(); + openResponseMessage.Articles.Add(new Article() + { + Title = "开放平台微信授权测试!", + Description = @"点击进入Open授权页面。 + +授权之后,您的微信所收到的消息将转发到第三方(盛派网络小助手)的服务器上,并获得对应的回复。 + +测试完成后,您可以登陆公众号后台取消授权。", + Url = "https://sdk.weixin.senparc.com/OpenOAuth/JumpToMpOAuth" + }); + return openResponseMessage; + }) + .Keyword("错误", () => + { + ResponseMessageText errorResponseMessage = requestMessage.CreateResponseMessage(); + //因为没有设置errorResponseMessage.Content,所以这小消息将无法正确返回。 + return errorResponseMessage; + }) + .Keyword("容错", () => + { + Thread.Sleep(4900); //故意延时1.5秒,让微信多次发送消息过来,观察返回结果 + ResponseMessageText faultTolerantResponseMessage = requestMessage.CreateResponseMessage(); + faultTolerantResponseMessage.Content = string.Format("测试容错,MsgId:{0},Ticks:{1}", + requestMessage.MsgId, + SystemTime.Now.Ticks); + return faultTolerantResponseMessage; + }) + .Keyword("TM", () => + { + string openId = requestMessage.FromUserName; + string checkCode = Guid.NewGuid().ToString("n").Substring(0, 3); //为了防止openId泄露造成骚扰,这里启用验证码 + TemplateMessageCollection[checkCode] = openId; + defaultResponseMessage.Content = + string.Format(@"新的验证码为:{0},请在网页上输入。网址:https://sdk.weixin.senparc.com/AsyncMethods", checkCode); + return defaultResponseMessage; + }) + .Keyword("OPENID", () => + { + string openId = requestMessage.FromUserName; //获取OpenId + Senparc.Weixin.MP.AdvancedAPIs.User.UserInfoJson userInfo = UserApi.Info(appId, openId, Language.zh_CN); + + defaultResponseMessage.Content = string.Format( + "您的OpenID为:{0}\r\n昵称:{1}\r\n性别:{2}\r\n地区(国家/省/市):{3}/{4}/{5}\r\n关注时间:{6}\r\n关注状态:{7}", + requestMessage.FromUserName, userInfo.nickname, (WeixinSex)userInfo.sex, userInfo.country, + userInfo.province, userInfo.city, DateTimeHelper.GetDateTimeFromXml(userInfo.subscribe_time), + userInfo.subscribe); + return defaultResponseMessage; + }) + .Keyword("EX", () => + { + WeixinException ex = new WeixinException("openid:" + requestMessage.FromUserName + + ":这是一条测试异常信息"); //回调过程在global的ConfigWeixinTraceLog()方法中 + defaultResponseMessage.Content = "请等待异步模板消息发送到此界面上(自动延时数秒)。\r\n当前时间:" + SystemTime.Now.ToString(); + return defaultResponseMessage; + }) + .Keyword("MUTE", () => //不回复任何消息 + { + //方案一: + return new SuccessResponseMessage(); + + //方案二: + ResponseMessageNoResponse muteResponseMessage = base.CreateResponseMessage(); + return muteResponseMessage; + + //方案三: + TextResponseMessage = "success"; + return null; + + //方案四: + return null; //在 Action 中结合使用 return new FixWeixinBugWeixinResult(messageHandler); + }) + .Keyword("JSSDK", () => + { + defaultResponseMessage.Content = "点击打开:https://sdk.weixin.senparc.com/WeixinJsSdk"; + return defaultResponseMessage; + }) + + //选择菜单,关键字:101(微信服务器端最终格式:id="s:101",content="满意") + .SelectMenuKeyword("101", () => + { + defaultResponseMessage.Content = $"感谢您的评价({requestMessage.Content})!我们会一如既往为提高企业和开发者生产力而努力!"; + return defaultResponseMessage; + }) + //选择菜单,关键字:102(微信服务器端最终格式:id="s:102",content="一般") + .SelectMenuKeyword("102", () => + { + defaultResponseMessage.Content = $"感谢您的评价({requestMessage.Content})!希望我们的服务能让您越来越满意!"; + return defaultResponseMessage; + }) + //选择菜单,关键字:103(微信服务器端最终格式:id="s:103",content="不满意") + .SelectMenuKeyword("103", () => + { + defaultResponseMessage.Content = + $"感谢您的评价({requestMessage.Content})!我们需要您的意见或建议,欢迎向我们反馈! 点击这里"; + return defaultResponseMessage; + }) + .SelectMenuKeywords(new[] { "110", "111" }, () => + { + defaultResponseMessage.Content = $"这里只是演示,可以同时支持多个选择菜单"; + return defaultResponseMessage; + }) + + //“一次订阅消息”接口测试 + .Keyword("订阅", () => + { + defaultResponseMessage.Content = "点击打开:https://sdk.weixin.senparc.com/SubscribeMsg"; + return defaultResponseMessage; + }) + //正则表达式 + .Regex(@"^\d+#\d+$", () => + { + defaultResponseMessage.Content = + string.Format("您输入了:{0},符合正则表达式:^\\d+#\\d+$", requestMessage.Content); + return defaultResponseMessage; + }) + + //当 Default 使用异步方法时,需要写在最后一个,且 requestMessage.StartHandler() 前需要使用 await 等待异步方法执行; + //当 Default 使用同步方法,不一定要在最后一个,并且不需要使用 await + .Default(async () => + { + StringBuilder result = new StringBuilder(); + result.AppendFormat("您刚才发送了文字信息:{0}\r\n\r\n", requestMessage.Content); + + CustomMessageContext currentMessageContext = await base.GetCurrentMessageContext(); + if (currentMessageContext.RequestMessages.Count > 1) + { + result.AppendFormat("您刚才还发送了如下消息({0}/{1}):\r\n", currentMessageContext.RequestMessages.Count, + currentMessageContext.StorageData); + for (int i = currentMessageContext.RequestMessages.Count - 2; i >= 0; i--) + { + IRequestMessageBase historyMessage = currentMessageContext.RequestMessages[i]; + result.AppendFormat("{0} 【{1}】{2}\r\n", + historyMessage.CreateTime.ToString("HH:mm:ss"), + historyMessage.MsgType.ToString(), + historyMessage is RequestMessageText + ? (historyMessage as RequestMessageText).Content + : "[非文字类型]" + ); + } + + result.AppendLine("\r\n"); + } + + result.AppendFormat("如果您在{0}分钟内连续发送消息,记录将被自动保留(当前设置:最多记录{1}条)。过期后记录将会自动清除。\r\n", + GlobalMessageContext.ExpireMinutes, GlobalMessageContext.MaxRecordCount); + result.AppendLine("\r\n"); + result.AppendLine( + "您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com"); + + defaultResponseMessage.Content = result.ToString(); + + return defaultResponseMessage; + }); + + return requestHandler.GetResponseMessage(); + } + + /// + /// 处理位置请求 + /// + /// + /// + public override async Task OnLocationRequestAsync(RequestMessageLocation requestMessage) + { + LocationService locationService = new LocationService(); + ResponseMessageNews responseMessage = locationService.GetResponseMessage(requestMessage); + return responseMessage; + } + + public override async Task OnShortVideoRequestAsync( + RequestMessageShortVideo requestMessage) + { + ResponseMessageText responseMessage = CreateResponseMessage(); + responseMessage.Content = "您刚才发送的是小视频"; + return responseMessage; + } + + /// + /// 处理图片请求 + /// + /// + /// + public override async Task OnImageRequestAsync(RequestMessageImage requestMessage) + { + //一隔一返回News或Image格式 + if (base.GlobalMessageContext.GetMessageContext(requestMessage).RequestMessages.Count() % 2 == 0) + { + ResponseMessageNews responseMessage = CreateResponseMessage(); + + responseMessage.Articles.Add(new Article() + { + Title = "您刚才发送了图片信息", + Description = "您发送的图片将会显示在边上", + PicUrl = requestMessage.PicUrl, + Url = "https://sdk.weixin.senparc.com" + }); + responseMessage.Articles.Add(new Article() + { + Title = "第二条", + Description = "第二条带连接的内容", + PicUrl = requestMessage.PicUrl, + Url = "https://sdk.weixin.senparc.com" + }); + + return responseMessage; + } + else + { + ResponseMessageImage responseMessage = CreateResponseMessage(); + responseMessage.Image.MediaId = requestMessage.MediaId; + return responseMessage; + } + } + + /// + /// 处理语音请求 + /// + /// + /// + public override async Task OnVoiceRequestAsync(RequestMessageVoice requestMessage) + { + ResponseMessageMusic responseMessage = CreateResponseMessage(); + //上传缩略图 + //var accessToken = Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret); + Senparc.Weixin.MP.AdvancedAPIs.Media.UploadTemporaryMediaResult uploadResult = MediaApi.UploadTemporaryMedia(appId, UploadMediaFileType.image, + ServerUtility.ContentRootMapPath("~/Images/Logo.jpg")); + + //设置音乐信息 + responseMessage.Music.Title = "天籁之音"; + responseMessage.Music.Description = "播放您上传的语音"; + responseMessage.Music.MusicUrl = + "https://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId; + responseMessage.Music.HQMusicUrl = + "https://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId; + responseMessage.Music.ThumbMediaId = uploadResult.media_id; + + //推送一条客服消息 + try + { + CustomApi.SendText(appId, OpenId, "本次上传的音频MediaId:" + requestMessage.MediaId); + } + catch + { + } + + return responseMessage; + } + + /// + /// 处理视频请求 + /// + /// + /// + public override async Task OnVideoRequestAsync(RequestMessageVideo requestMessage) + { + ResponseMessageText responseMessage = CreateResponseMessage(); + responseMessage.Content = "您发送了一条视频信息,ID:" + requestMessage.MediaId; + + #region 上传素材并推送到客户端 + + Task.Factory.StartNew(async () => + { + //上传素材 + string dir = ServerUtility.ContentRootMapPath("~/App_Data/TempVideo/"); + string file = await MediaApi.GetAsync(appId, requestMessage.MediaId, dir); + Senparc.Weixin.MP.AdvancedAPIs.Media.UploadTemporaryMediaResult uploadResult = + await MediaApi.UploadTemporaryMediaAsync(appId, UploadMediaFileType.video, file, 50000); + await CustomApi.SendVideoAsync(appId, WeixinOpenId, uploadResult.media_id, "这是您刚才发送的视频", "这是一条视频消息"); + }).ContinueWith(async task => + { + if (task.Exception != null) + { + WeixinTrace.Log("OnVideoRequest()储存Video过程发生错误:", task.Exception.Message); + + string msg = string.Format("上传素材出错:{0}\r\n{1}", + task.Exception.Message, + task.Exception.InnerException != null + ? task.Exception.InnerException.Message + : null); + await CustomApi.SendTextAsync(appId, WeixinOpenId, msg); + } + }); + + #endregion 上传素材并推送到客户端 + + return responseMessage; + } + + /// + /// 处理链接消息请求 + /// + /// + /// + public override async Task OnLinkRequestAsync(RequestMessageLink requestMessage) + { + ResponseMessageText responseMessage = ResponseMessageBase.CreateFromRequestMessage(requestMessage); + responseMessage.Content = string.Format(@"您发送了一条连接信息: +Title:{0} +Description:{1} +Url:{2}", requestMessage.Title, requestMessage.Description, requestMessage.Url); + return responseMessage; + } + + public override async Task OnFileRequestAsync(RequestMessageFile requestMessage) + { + ResponseMessageText responseMessage = requestMessage.CreateResponseMessage(); + responseMessage.Content = string.Format(@"您发送了一个文件: +文件名:{0} +说明:{1} +大小:{2} +MD5:{3}", requestMessage.Title, requestMessage.Description, requestMessage.FileTotalLen, requestMessage.FileMd5); + return responseMessage; + } + + /// + /// 处理事件请求(这个方法一般不用重写,这里仅作为示例出现。除非需要在判断具体Event类型以外对Event信息进行统一操作 + /// + /// + /// + public override async Task OnEventRequestAsync(IRequestMessageEventBase requestMessage) + { + IResponseMessageBase eventResponseMessage = + await base.OnEventRequestAsync(requestMessage); //对于Event下属分类的重写方法,见:CustomerMessageHandler_Events.cs + //TODO: 对Event信息进行统一操作 + return eventResponseMessage; + } + + public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage) + { + /* 所有没有被处理的消息会默认返回这里的结果, + * 因此,如果想把整个微信请求委托出去(例如需要使用分布式或从其他服务器获取请求), + * 只需要在这里统一发出委托请求,如: + * var responseMessage = MessageAgent.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString()); + * return responseMessage; + */ + + ResponseMessageText responseMessage = CreateResponseMessage(); + responseMessage.Content = "这条消息来自DefaultResponseMessage。"; + return responseMessage; + } + + public override async Task OnUnknownTypeRequestAsync( + RequestMessageUnknownType requestMessage) + { + /* + * 此方法用于应急处理SDK没有提供的消息类型, + * 原始XML可以通过requestMessage.RequestDocument(或this.RequestDocument)获取到。 + * 如果不重写此方法,遇到未知的请求类型将会抛出异常(v14.8.3 之前的版本就是这么做的) + */ + string msgType = MsgTypeHelper.GetRequestMsgTypeString(requestMessage.RequestDocument); + ResponseMessageText responseMessage = CreateResponseMessage(); + responseMessage.Content = "未知消息类型:" + msgType; + + SenparcTrace.SendCustomLog("未知请求消息类型", requestMessage.RequestDocument.ToString()); //记录到日志中 + + return responseMessage; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageHandler_Events.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageHandler_Events.cs new file mode 100644 index 0000000..bc03ce0 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/CustomMessageHandler/CustomMessageHandler_Events.cs @@ -0,0 +1,612 @@ +using Senparc.CO2NET.Extensions; +using Senparc.CO2NET.Trace; +using Senparc.CO2NET.Utilities; +using Senparc.NeuChar.Agents; +using Senparc.NeuChar.Entities; +using Senparc.Weixin.Exceptions; +using Senparc.Weixin.MP; +using Senparc.Weixin.MP.AdvancedAPIs; +using Senparc.Weixin.MP.Entities; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.WeChat.CommonService.Download; + +namespace Znyc.Admin.WeChat.CommonService.CustomMessageHandler +{ + /// + /// 自定义MessageHandler + /// + public partial class CustomMessageHandler + { + private string GetWelcomeInfo() + { + //获取Senparc.Weixin.MP.dll版本信息 +#if NET45 + var filePath = ServerUtility.ContentRootMapPath("~/bin/Senparc.Weixin.MP.dll");//发布路径 +#else + //var filePath = ServerUtility.ContentRootMapPath("~/bin/Release/netcoreapp2.2/Senparc.Weixin.MP.dll");//本地测试路径 + string filePath = ServerUtility.ContentRootMapPath("~/Senparc.Weixin.MP.dll"); //发布路径 +#endif + FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(filePath); + + string version = fileVersionInfo == null + ? "-" + : string.Format("{0}.{1}.{2}", fileVersionInfo.FileMajorPart, fileVersionInfo.FileMinorPart, + fileVersionInfo.FileBuildPart); + + return string.Format( + @"欢迎关注【Senparc.Weixin 微信公众平台SDK】,当前运行版本:v{0}。 +您可以发送【文字】【位置】【图片】【语音】【文件】等不同类型的信息,查看不同格式的回复。 +您也可以直接点击菜单查看各种类型的回复。 +还可以点击菜单体验微信支付。 +SDK官方地址:https://weixin.senparc.com +SDK Demo:https://sdk.weixin.senparc.com +源代码及Demo下载地址:https://github.com/JeffreySu/WeiXinMPSDK +Nuget地址:https://www.nuget.org/packages/Senparc.Weixin.MP +QQ群:289181996 +=============== +更多: +1、JSSDK测试:https://sdk.weixin.senparc.com/WeixinJSSDK +2、开放平台测试(建议PC上打开):https://sdk.weixin.senparc.com/OpenOAuth/JumpToMpOAuth +3、回复关键字: +【open】 进入第三方开放平台(Senparc.Weixin.Open)测试 +【tm】 测试异步模板消息 +【openid】 获取OpenId等用户信息 +【约束】 测试微信浏览器约束 +【AsyncTest】 异步并发测试 +【错误】 体验发生错误无法返回正确信息 +【容错】 体验去重容错 +【ex】 体验错误日志推送提醒 +【mute】 不返回任何消息,也无出错信息 +【jssdk】 测试JSSDK图文转发接口 +格式:【数字#数字】,如2010#0102,调用正则表达式匹配 +【订阅】 测试“一次性订阅消息”接口 +", + version); + } + + public string GetDownloadInfo(CodeRecord codeRecord) + { + return string.Format(@"您已通过二维码验证,浏览器即将开始下载 Senparc.Weixin SDK 帮助文档。 +当前选择的版本:v{0}({1}) +我们期待您的意见和建议,客服热线:400-031-8816。 +感谢您对盛派网络的支持! +© {2} Senparc", codeRecord.Version, codeRecord.IsWebVersion ? "网页版" : ".chm文档版", SystemTime.Now.Year); + } + + public override IResponseMessageBase OnTextOrEventRequest(RequestMessageText requestMessage) + { + // 预处理文字或事件类型请求。 + // 这个请求是一个比较特殊的请求,通常用于统一处理来自文字或菜单按钮的同一个执行逻辑, + // 会在执行OnTextRequest或OnEventRequest之前触发,具有以下一些特征: + // 1、如果返回null,则继续执行OnTextRequest或OnEventRequest + // 2、如果返回不为null,则终止执行OnTextRequest或OnEventRequest,返回最终ResponseMessage + // 3、如果是事件,则会将RequestMessageEvent自动转为RequestMessageText类型,其中RequestMessageText.Content就是RequestMessageEvent.EventKey + + if (requestMessage.Content == "OneClick") + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + strongResponseMessage.Content = "您点击了底部按钮。\r\n为了测试微信软件换行bug的应对措施,这里做了一个——\r\n换行"; + return strongResponseMessage; + } + + return null; //返回null,则继续执行OnTextRequest或OnEventRequest + } + + /// + /// 点击事件 + /// + /// 请求消息 + /// + public override IResponseMessageBase OnEvent_ClickRequest(RequestMessageEvent_Click requestMessage) + { + IResponseMessageBase reponseMessage = null; + //菜单点击,需要跟创建菜单时的Key匹配 + + switch (requestMessage.EventKey) + { + case "OneClick": + { + //这个过程实际已经在OnTextOrEventRequest中命中“OneClick”关键字,并完成回复,这里不会执行到。 + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Content = "您点击了底部按钮。\r\n为了测试微信软件换行bug的应对措施,这里做了一个——\r\n换行"; + } + break; + + case "SubClickRoot_Text": + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Content = "您点击了子菜单按钮。"; + } + break; + + case "SubClickRoot_News": + { + ResponseMessageNews strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Articles.Add(new Article() + { + Title = "您点击了子菜单图文按钮", + Description = "您点击了子菜单图文按钮,这是一条图文信息。这个区域是Description内容\r\n可以使用\\r\\n进行换行。", + PicUrl = "https://sdk.weixin.senparc.com/Images/qrcode.jpg", + Url = "https://sdk.weixin.senparc.com" + }); + + //随机添加一条图文,或只输出一条图文信息 + if (SystemTime.Now.Second % 2 == 0) + { + strongResponseMessage.Articles.Add(new Article() + { + Title = "这是随机产生的第二条图文信息,用于测试多条图文的样式", + Description = "这是随机产生的第二条图文信息,用于测试多条图文的样式", + PicUrl = "https://sdk.weixin.senparc.com/Images/qrcode.jpg", + Url = "https://sdk.weixin.senparc.com" + }); + } + } + break; + + case "SubClickRoot_Music": + { + //上传缩略图 + string filePath = "~/wwwroot/Images/Logo.thumb.jpg"; + Senparc.Weixin.MP.AdvancedAPIs.Media.UploadTemporaryMediaResult uploadResult = MediaApi.UploadTemporaryMedia(appId, UploadMediaFileType.thumb, + ServerUtility.ContentRootMapPath(filePath)); + //PS:缩略图官方没有特别提示文件大小限制,实际测试哪怕114K也会返回文件过大的错误,因此尽量控制在小一点(当前图片39K) + + //设置音乐信息 + ResponseMessageMusic strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Music.Title = "天籁之音"; + strongResponseMessage.Music.Description = "真的是天籁之音"; + strongResponseMessage.Music.MusicUrl = "https://sdk.weixin.senparc.com/Content/music1.mp3"; + strongResponseMessage.Music.HQMusicUrl = "https://sdk.weixin.senparc.com/Content/music1.mp3"; + strongResponseMessage.Music.ThumbMediaId = uploadResult.thumb_media_id; + } + break; + + case "SubClickRoot_Image": + { + string filePath = "~/wwwroot/Images/Logo.jpg"; + Senparc.Weixin.MP.AdvancedAPIs.Media.UploadTemporaryMediaResult uploadResult = MediaApi.UploadTemporaryMedia(appId, UploadMediaFileType.image, + ServerUtility.ContentRootMapPath(filePath)); + //设置图片信息 + ResponseMessageImage strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Image.MediaId = uploadResult.media_id; + } + break; + + case "SendMenu": //菜单消息 + { + //注意: + //1、此接口可以在任意地方调用(包括后台线程),此处演示为通过 + //2、一下"s:"前缀只是 Senparc.Weixin 的内部约定,可以使用 OnTextRequest事件中的 requestHandler.SelectMenuKeyword() 方法自动匹配到后缀(如101) + + List menuContentList = new List() + { + new SendMenuContent("101", "满意"), + new SendMenuContent("102", "一般"), + new SendMenuContent("103", "不满意") + }; + //使用异步接口 + CustomApi.SendMenuAsync(appId, OpenId, "请对 Senparc.Weixin SDK 给出您的评价", menuContentList, "感谢您的参与!"); + + reponseMessage = new ResponseMessageNoResponse(); //不返回任何消息 + } + break; + + case "SubClickRoot_Agent": //代理消息 + { + //获取返回的XML + DateTimeOffset dt1 = SystemTime.Now; + reponseMessage = MessageAgent.RequestResponseMessage(this, + Senparc.CO2NET.SenparcDI.GetServiceProvider(), agentUrl, agentToken, + RequestDocument.ToString()); + //上面的方法也可以使用扩展方法:this.RequestResponseMessage(this,agentUrl, agentToken, RequestDocument.ToString()); + + DateTimeOffset dt2 = SystemTime.Now; + + if (reponseMessage is ResponseMessageNews) + { + (reponseMessage as ResponseMessageNews) + .Articles[0] + .Description += string.Format("\r\n\r\n代理过程总耗时:{0}毫秒", (dt2 - dt1).Milliseconds); + } + } + break; + + case "Member": //托管代理会员信息 + { + //原始方法为:MessageAgent.RequestXml(this,agentUrl, agentToken, RequestDocument.ToString());//获取返回的XML + reponseMessage = this.RequestResponseMessage(Senparc.CO2NET.SenparcDI.GetServiceProvider(), + agentUrl, agentToken, RequestDocument.ToString()); + } + break; + + case "OAuth": //OAuth授权测试 + { + ResponseMessageNews strongResponseMessage = CreateResponseMessage(); + + strongResponseMessage.Articles.Add(new Article() + { + Title = "OAuth2.0测试", + Description = "选择下面两种不同的方式进行测试,区别在于授权成功后,最后停留的页面。" + //Url = "https://sdk.weixin.senparc.com/oauth2", + //PicUrl = "https://sdk.weixin.senparc.com/Images/qrcode.jpg" + }); + + strongResponseMessage.Articles.Add(new Article() + { + Title = "OAuth2.0测试(不带returnUrl),测试环境可使用", + Description = "OAuth2.0测试(不带returnUrl)", + Url = "https://sdk.weixin.senparc.com/oauth2", + PicUrl = "https://sdk.weixin.senparc.com/Images/qrcode.jpg" + }); + + string returnUrl = "/OAuth2/TestReturnUrl"; + strongResponseMessage.Articles.Add(new Article() + { + Title = "OAuth2.0测试(带returnUrl),生产环境强烈推荐使用", + Description = "OAuth2.0测试(带returnUrl)", + Url = "https://sdk.weixin.senparc.com/oauth2?returnUrl=" + returnUrl.UrlEncode(), + PicUrl = "https://sdk.weixin.senparc.com/Images/qrcode.jpg" + }); + + reponseMessage = strongResponseMessage; + } + break; + + case "Description": + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + strongResponseMessage.Content = GetWelcomeInfo(); + reponseMessage = strongResponseMessage; + } + break; + + case "SubClickRoot_PicPhotoOrAlbum": + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Content = "您点击了【微信拍照】按钮。系统将会弹出拍照或者相册发图。"; + } + break; + + case "SubClickRoot_ScancodePush": + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Content = "您点击了【微信扫码】按钮。"; + } + break; + + case "ConditionalMenu_Male": + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Content = "您点击了个性化菜单按钮,您的微信性别设置为:男。"; + } + break; + + case "ConditionalMenu_Femle": + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + reponseMessage = strongResponseMessage; + strongResponseMessage.Content = "您点击了个性化菜单按钮,您的微信性别设置为:女。"; + } + break; + + case "GetNewMediaId": //获取新的MediaId + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + try + { + Senparc.Weixin.MP.AdvancedAPIs.Media.UploadForeverMediaResult result = MediaApi.UploadForeverMedia(appId, + ServerUtility.ContentRootMapPath("~/Images/logo.jpg")); + strongResponseMessage.Content = result.media_id; + } + catch (Exception e) + { + strongResponseMessage.Content = "发生错误:" + e.Message; + SenparcTrace.SendCustomLog("调用UploadForeverMedia()接口发生异常", e.Message); + } + } + break; + + default: + { + ResponseMessageText strongResponseMessage = CreateResponseMessage(); + strongResponseMessage.Content = "您点击了按钮,EventKey:" + requestMessage.EventKey; + reponseMessage = strongResponseMessage; + } + break; + } + + return reponseMessage; + } + + /// + /// 进入事件 + /// + /// + /// + public override IResponseMessageBase OnEvent_EnterRequest(RequestMessageEvent_Enter requestMessage) + { + ResponseMessageText responseMessage = ResponseMessageBase.CreateFromRequestMessage(requestMessage); + responseMessage.Content = "您刚才发送了ENTER事件请求。"; + return responseMessage; + } + + /// + /// 位置事件 + /// + /// + /// + public override IResponseMessageBase OnEvent_LocationRequest(RequestMessageEvent_Location requestMessage) + { + //这里是微信客户端(通过微信服务器)自动发送过来的位置信息 + ResponseMessageText responseMessage = CreateResponseMessage(); + responseMessage.Content = "这里写什么都无所谓,比如:上帝爱你!"; + return responseMessage; //这里也可以返回null(需要注意写日志时候null的问题) + } + + /// + /// 通过二维码扫描关注扫描事件 + /// + /// + /// + public override IResponseMessageBase OnEvent_ScanRequest(RequestMessageEvent_Scan requestMessage) + { + //通过扫描关注 + ResponseMessageText responseMessage = CreateResponseMessage(); + + //下载文档 + if (!string.IsNullOrEmpty(requestMessage.EventKey)) + { + long sceneId = long.Parse(requestMessage.EventKey.Replace("qrscene_", "")); + //var configHelper = new ConfigHelper(new HttpContextWrapper(HttpContext.Current)); + CodeRecord codeRecord = + ConfigHelper.CodeCollection.Values.FirstOrDefault(z => + z.QrCodeTicket != null && z.QrCodeId == sceneId); + + if (codeRecord != null) + { + //确认可以下载 + codeRecord.AllowDownload = true; + responseMessage.Content = GetDownloadInfo(codeRecord); + } + } + + responseMessage.Content = + responseMessage.Content ?? string.Format("通过扫描二维码进入,场景值:{0}", requestMessage.EventKey); + + return responseMessage; + } + + /// + /// 打开网页事件 + /// + /// + /// + public override IResponseMessageBase OnEvent_ViewRequest(RequestMessageEvent_View requestMessage) + { + //说明:这条消息只作为接收,下面的responseMessage到达不了客户端,类似OnEvent_UnsubscribeRequest + ResponseMessageText responseMessage = CreateResponseMessage(); + responseMessage.Content = "您点击了view按钮,将打开网页:" + requestMessage.EventKey; + return responseMessage; + } + + /// + /// 群发完成事件 + /// + /// + /// + public override IResponseMessageBase OnEvent_MassSendJobFinishRequest( + RequestMessageEvent_MassSendJobFinish requestMessage) + { + ResponseMessageText responseMessage = CreateResponseMessage(); + responseMessage.Content = "接收到了群发完成的信息。"; + return responseMessage; + } + + /// + /// 订阅(关注)事件 + /// + /// + public override IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage) + { + ResponseMessageText responseMessage = ResponseMessageBase.CreateFromRequestMessage(requestMessage); + responseMessage.Content = GetWelcomeInfo(); + if (!string.IsNullOrEmpty(requestMessage.EventKey)) + { + responseMessage.Content += "\r\n============\r\n场景值:" + requestMessage.EventKey; + } + + //推送消息 + //下载文档 + if (requestMessage.EventKey.StartsWith("qrscene_")) + { + long sceneId = long.Parse(requestMessage.EventKey.Replace("qrscene_", "")); + //var configHelper = new ConfigHelper(new HttpContextWrapper(HttpContext.Current)); + CodeRecord codeRecord = + ConfigHelper.CodeCollection.Values.FirstOrDefault(z => + z.QrCodeTicket != null && z.QrCodeId == sceneId); + + if (codeRecord != null) + { + if (codeRecord.AllowDownload) + { + Task.Factory.StartNew(() => + CustomApi.SendTextAsync(null, OpenId, "下载已经开始,如需下载其他版本,请刷新页面后重新扫一扫。")); + } + else + { + //确认可以下载 + codeRecord.AllowDownload = true; + Task.Factory.StartNew(() => CustomApi.SendTextAsync(null, OpenId, GetDownloadInfo(codeRecord))); + } + } + } + + return responseMessage; + } + + /// + /// 退订 + /// 实际上用户无法收到非订阅账号的消息,所以这里可以随便写。 + /// unsubscribe事件的意义在于及时删除网站应用中已经记录的OpenID绑定,消除冗余数据。并且关注用户流失的情况。 + /// + /// + public override IResponseMessageBase OnEvent_UnsubscribeRequest(RequestMessageEvent_Unsubscribe requestMessage) + { + ResponseMessageText responseMessage = base.CreateResponseMessage(); + responseMessage.Content = "有空再来"; + return responseMessage; + } + + /// + /// 事件之扫码推事件(scancode_push) + /// + /// + /// + public override IResponseMessageBase OnEvent_ScancodePushRequest( + RequestMessageEvent_Scancode_Push requestMessage) + { + ResponseMessageText responseMessage = base.CreateResponseMessage(); + responseMessage.Content = "事件之扫码推事件"; + return responseMessage; + } + + /// + /// 事件之扫码推事件且弹出“消息接收中”提示框(scancode_waitmsg) + /// + /// + /// + public override IResponseMessageBase OnEvent_ScancodeWaitmsgRequest( + RequestMessageEvent_Scancode_Waitmsg requestMessage) + { + ResponseMessageText responseMessage = base.CreateResponseMessage(); + responseMessage.Content = "事件之扫码推事件且弹出“消息接收中”提示框"; + return responseMessage; + } + + /// + /// 事件之弹出拍照或者相册发图(pic_photo_or_album) + /// + /// + /// + public override IResponseMessageBase OnEvent_PicPhotoOrAlbumRequest( + RequestMessageEvent_Pic_Photo_Or_Album requestMessage) + { + ResponseMessageText responseMessage = base.CreateResponseMessage(); + responseMessage.Content = "事件之弹出拍照或者相册发图"; + return responseMessage; + } + + /// + /// 事件之弹出系统拍照发图(pic_sysphoto) + /// 实际测试时发现微信并没有推送RequestMessageEvent_Pic_Sysphoto消息,只能接收到用户在微信中发送的图片消息。 + /// + /// + /// + public override IResponseMessageBase OnEvent_PicSysphotoRequest(RequestMessageEvent_Pic_Sysphoto requestMessage) + { + ResponseMessageText responseMessage = base.CreateResponseMessage(); + responseMessage.Content = "事件之弹出系统拍照发图"; + return responseMessage; + } + + /// + /// 事件之弹出微信相册发图器(pic_weixin) + /// + /// + /// + public override IResponseMessageBase OnEvent_PicWeixinRequest(RequestMessageEvent_Pic_Weixin requestMessage) + { + ResponseMessageText responseMessage = base.CreateResponseMessage(); + responseMessage.Content = "事件之弹出微信相册发图器"; + return responseMessage; + } + + /// + /// 事件之弹出地理位置选择器(location_select) + /// + /// + /// + public override IResponseMessageBase OnEvent_LocationSelectRequest( + RequestMessageEvent_Location_Select requestMessage) + { + ResponseMessageText responseMessage = base.CreateResponseMessage(); + responseMessage.Content = "事件之弹出地理位置选择器"; + return responseMessage; + } + + /// + /// 事件之发送模板消息返回结果 + /// + /// + /// + public override IResponseMessageBase OnEvent_TemplateSendJobFinishRequest( + RequestMessageEvent_TemplateSendJobFinish requestMessage) + { + switch (requestMessage.Status) + { + case "success": + //发送成功 + + break; + + case "failed:user block": + //送达由于用户拒收(用户设置拒绝接收公众号消息)而失败 + break; + + case "failed: system failed": + //送达由于其他原因失败 + break; + + default: + throw new WeixinException("未知模板消息状态:" + requestMessage.Status); + } + + //注意:此方法内不能再发送模板消息,否则会造成无限循环! + + try + { + string msg = @"已向您发送模板消息 +状态:{0} +MsgId:{1} +(这是一条来自MessageHandler的客服消息)".FormatWith(requestMessage.Status, requestMessage.MsgID); + CustomApi.SendText(appId, OpenId, msg); //发送客服消息 + } + catch (Exception e) + { + SenparcTrace.SendCustomLog("模板消息发送失败", e.ToString()); + } + + //无需回复文字内容 + //return requestMessage + // .CreateResponseMessage(); + return null; + } + + #region 微信认证事件推送 + + public override IResponseMessageBase OnEvent_QualificationVerifySuccessRequest( + RequestMessageEvent_QualificationVerifySuccess requestMessage) + { + //以下方法可以强制定义返回的字符串值 + //TextResponseMessage = "your content"; + //return null; + + return new SuccessResponseMessage(); //返回"success"字符串 + } + + #endregion 微信认证事件推送 + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/OpenMessageHandler/OpenCheckMessageHandler.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/OpenMessageHandler/OpenCheckMessageHandler.cs new file mode 100644 index 0000000..4701f90 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/OpenMessageHandler/OpenCheckMessageHandler.cs @@ -0,0 +1,85 @@ +using Senparc.NeuChar.Entities; +using Senparc.NeuChar.Helpers; +using Senparc.Weixin.MP.Entities; +using Senparc.Weixin.MP.Entities.Request; +using Senparc.Weixin.MP.MessageHandlers; +using Senparc.Weixin.Open.ComponentAPIs; +using System; +using System.IO; +using Znyc.Admin.WeChat.CommonService.CustomMessageHandler; +using Znyc.Admin.WeChat.CommonService.OpenTicket; + +namespace Znyc.Admin.WeChat.CommonService.OpenMessageHandler +{ + /// + /// 开放平台全网发布之前需要做的验证 + /// + public class OpenCheckMessageHandler : MessageHandler + { + /* + https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318611&lang=zh_CN + 自动化测试的专用测试公众号的信息如下: + (1)appid: wx570bc396a51b8ff8 + (2)Username: gh_3c884a361561 + */ + + //private string testAppId = "wx570bc396a51b8ff8"; + + private readonly string componentAppId = "ComponentAppId"; + private readonly string componentSecret = "Component_Secret"; + + public OpenCheckMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = 0) + : base(inputStream, postModel, maxRecordCount) + { + } + + public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage) + { + if (requestMessage.Content == "TESTCOMPONENT_MSG_TYPE_TEXT") + { + ResponseMessageText responseMessage = requestMessage.CreateResponseMessage(); + responseMessage.Content = + requestMessage.Content + "_callback"; //固定为TESTCOMPONENT_MSG_TYPE_TEXT_callback + return responseMessage; + } + + if (requestMessage.Content.StartsWith("QUERY_AUTH_CODE:")) + { + string openTicket = OpenTicketHelper.GetOpenTicket(componentAppId); + string query_auth_code = requestMessage.Content.Replace("QUERY_AUTH_CODE:", ""); + try + { + string component_access_token = ComponentApi + .GetComponentAccessToken(componentAppId, componentSecret, openTicket).component_access_token; + QueryAuthResult oauthResult = ComponentApi.QueryAuth(component_access_token, componentAppId, query_auth_code); + + //调用客服接口 + string content = query_auth_code + "_from_api"; + Senparc.Weixin.Entities.WxJsonResult sendResult = Senparc.Weixin.MP.AdvancedAPIs.CustomApi.SendText( + oauthResult.authorization_info.authorizer_access_token, + requestMessage.FromUserName, content); + } + catch (Exception) + { + throw; + } + } + + return null; + } + + public override IResponseMessageBase OnEventRequest(IRequestMessageEventBase requestMessage) + { + ResponseMessageText responseMessage = requestMessage.CreateResponseMessage(); + responseMessage.Content = requestMessage.Event + "from_callback"; + return responseMessage; + } + + public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage) + { + ResponseMessageText responseMessage = requestMessage.CreateResponseMessage(); + responseMessage.Content = "默认消息"; + return responseMessage; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WebSocket/CustomNetCoreWebSocketMessageHandler.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WebSocket/CustomNetCoreWebSocketMessageHandler.cs new file mode 100644 index 0000000..f32c224 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WebSocket/CustomNetCoreWebSocketMessageHandler.cs @@ -0,0 +1,77 @@ +using Senparc.CO2NET.Trace; +using Senparc.WebSocket; +using Senparc.Weixin; +using Senparc.Weixin.WxOpen.Containers; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace Znyc.Admin.WeChat.CommonService.MessageHandlers.WebSocket +{ + /// + /// .NET Core 自定义 WebSocket 处理类 + /// + public class CustomNetCoreWebSocketMessageHandler : WebSocketMessageHandler + { + public override Task OnConnecting(WebSocketHelper webSocketHandler) + { + //TODO:处理连接时的逻辑 + return base.OnConnecting(webSocketHandler); + } + + public override Task OnDisConnected(WebSocketHelper webSocketHandler) + { + //TODO:处理断开连接时的逻辑 + return base.OnDisConnected(webSocketHandler); + } + + public override async Task OnMessageReceiced(WebSocketHelper webSocketHandler, ReceivedMessage receivedMessage, + string originalData) + { + if (receivedMessage == null || string.IsNullOrEmpty(receivedMessage.Message)) + { + return; + } + + string message = receivedMessage.Message; + + await webSocketHandler.SendMessage("originalData:" + originalData, + webSocketHandler.WebSocket.Clients.Caller); + await webSocketHandler.SendMessage("您发送了文字:" + message, webSocketHandler.WebSocket.Clients.Caller); + await webSocketHandler.SendMessage("正在处理中(反转文字)...", webSocketHandler.WebSocket.Clients.Caller); + + await Task.Delay(1000); + + //处理文字 + string result = string.Concat(message.Reverse()); + await webSocketHandler.SendMessage(result, webSocketHandler.WebSocket.Clients.Caller); + + string appId = Config.SenparcWeixinSetting.WxOpenAppId; //与微信小程序账号后台的AppId设置保持一致,区分大小写。 + + try + { + SessionBag sessionBag = SessionContainer.GetSession(receivedMessage.SessionId); + + //临时演示使用固定openId + string openId = sessionBag != null ? sessionBag.OpenId : "onh7q0DGM1dctSDbdByIHvX4imxA"; // "用户未正确登陆"; + + //await webSocketHandler.SendMessage("OpenId:" + openId, webSocketHandler.WebSocket.Clients.Caller); + //await webSocketHandler.SendMessage("FormId:" + formId); + + //群发 + await webSocketHandler.SendMessage( + $"[群发消息] [来自 OpenId:***{openId.Substring(openId.Length - 10, 10)},昵称:{sessionBag.DecodedUserInfo?.nickName}]:{message}", + webSocketHandler.WebSocket.Clients.All); + } + catch (Exception ex) + { + string msg = ex.Message + "\r\n\r\n" + originalData + "\r\n\r\nAPPID:" + appId; + + await webSocketHandler.SendMessage(msg, + webSocketHandler.WebSocket.Clients.Caller); //VS2017以下如果编译不通过,可以注释掉这一行 + + SenparcTrace.SendCustomLog("WebSocket OnMessageReceiced()过程出错", msg); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WxOpenMessageHandler/CustomWxOpenMessageContext.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WxOpenMessageHandler/CustomWxOpenMessageContext.cs new file mode 100644 index 0000000..d4ea6e0 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WxOpenMessageHandler/CustomWxOpenMessageContext.cs @@ -0,0 +1,52 @@ +using Senparc.NeuChar; +using Senparc.NeuChar.Context; +using Senparc.NeuChar.Entities; +using System; +using System.Xml.Linq; + +namespace Znyc.Admin.WeChat.MessageHandlers.WxOpenMessageHandler +{ + public class CustomWxOpenMessageContext : MessageContext + { + public CustomWxOpenMessageContext() + { + base.MessageContextRemoved += CustomMessageContext_MessageContextRemoved; + } + + public override IRequestMessageBase GetRequestEntityMappingResult(RequestMsgType requestMsgType, + XDocument doc = null) + { + throw new NotImplementedException(); + } + + public override IResponseMessageBase GetResponseEntityMappingResult(ResponseMsgType responseMsgType, + XDocument doc = null) + { + throw new NotImplementedException(); + } + + /// + /// 当上下文过期,被移除时触发的时间 + /// + /// + /// + private void CustomMessageContext_MessageContextRemoved(object sender, + WeixinContextRemovedEventArgs e) + { + /* 注意,这个事件不是实时触发的(当然你也可以专门写一个线程监控) + * 为了提高效率,根据WeixinContext中的算法,这里的过期消息会在过期后下一条请求执行之前被清除 + */ + + CustomWxOpenMessageContext messageContext = e.MessageContext as CustomWxOpenMessageContext; + if (messageContext == null) + { + return; //如果是正常的调用,messageContext不会为null + } + + //TODO:这里根据需要执行消息过期时候的逻辑,下面的代码仅供参考 + + //Log.InfoFormat("{0}的消息上下文已过期",e.OpenId); + //api.SendMessage(e.OpenId, "由于长时间未搭理客服,您的客服状态已退出!"); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WxOpenMessageHandler/CustomWxOpenMessageHandler.cs b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WxOpenMessageHandler/CustomWxOpenMessageHandler.cs new file mode 100644 index 0000000..e97e547 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/MessageHandlers/WxOpenMessageHandler/CustomWxOpenMessageHandler.cs @@ -0,0 +1,83 @@ +using Senparc.NeuChar.Entities; +using Senparc.Weixin; +using Senparc.Weixin.WxOpen.Entities; +using Senparc.Weixin.WxOpen.Entities.Request; +using Senparc.Weixin.WxOpen.MessageHandlers; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Znyc.Admin.WeChat.MessageHandlers.WxOpenMessageHandler +{ + /// + /// 自定义MessageHandler + /// 把MessageHandler作为基类,重写对应请求的处理方法 + /// + public partial class CustomWxOpenMessageHandler : WxOpenMessageHandler + { + private readonly string appId = Config.SenparcWeixinSetting.WxOpenAppId; + private readonly string appSecret = Config.SenparcWeixinSetting.WxOpenAppSecret; + + /// + /// 为中间件提供生成当前类的委托 + /// + public static Func GenerateMessageHandler = + (stream, postModel, maxRecordCount) => new CustomWxOpenMessageHandler(stream, postModel, maxRecordCount); + + public CustomWxOpenMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = 0) + : base(inputStream, postModel, maxRecordCount) + { + //这里设置仅用于测试,实际开发可以在外部更全局的地方设置, + //比如MessageHandler.GlobalGlobalMessageContext.ExpireMinutes = 3。 + GlobalMessageContext.ExpireMinutes = 3; + + if (!string.IsNullOrEmpty(postModel.AppId)) + { + appId = postModel.AppId; //通过第三方开放平台发送过来的请求 + } + + //在指定条件下,不使用消息去重 + OmitRepeatedMessageFunc = requestMessage => + { + RequestMessageText textRequestMessage = requestMessage as RequestMessageText; + if (textRequestMessage != null && textRequestMessage.Content == "容错") + { + return false; + } + + return true; + }; + } + + public override async Task OnExecutingAsync(CancellationToken cancellationToken) + { + //测试MessageContext.StorageData + CustomWxOpenMessageContext currentMessageContext = await base.GetCurrentMessageContext(); + if (currentMessageContext.StorageData == null || currentMessageContext.StorageData is int) + { + currentMessageContext.StorageData = 0; + } + + await base.OnExecutingAsync(cancellationToken); + } + + public override async Task OnExecutedAsync(CancellationToken cancellationToken) + { + await base.OnExecutedAsync(cancellationToken); + CustomWxOpenMessageContext currentMessageContext = await base.GetCurrentMessageContext(); + currentMessageContext.StorageData = (int)currentMessageContext.StorageData + 1; + } + + public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage) + { + //所有没有被处理的消息会默认返回这里的结果 + + return new SuccessResponseMessage(); + + //return new SuccessResponseMessage();等效于: + //base.TextResponseMessage = "success"; + //return null; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/OpenTicket/OpenTicketHelper.cs b/Znyc.Admin.WeChat.Core/CommonService/OpenTicket/OpenTicketHelper.cs new file mode 100644 index 0000000..683bbe5 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/OpenTicket/OpenTicketHelper.cs @@ -0,0 +1,38 @@ +using Senparc.CO2NET.Utilities; +using Senparc.Weixin.Exceptions; +using System.IO; + +namespace Znyc.Admin.WeChat.CommonService.OpenTicket +{ + /// + /// OpenTicket即ComponentVerifyTicket + /// + public class OpenTicketHelper + { + public static string GetOpenTicket(string componentAppId) + { + //实际开发过程不一定要用文件记录,也可以用数据库。 + string openTicketPath = ServerUtility.ContentRootMapPath("~/App_Data/OpenTicket"); + string openTicket = null; + string filePath = Path.Combine(openTicketPath, string.Format("{0}.txt", componentAppId)); + if (File.Exists(filePath)) + { + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + using (TextReader tr = new StreamReader(fs)) + { + openTicket = tr.ReadToEnd(); + } + } + } + else + { + throw new WeixinException("OpenTicket不存在!"); + } + + //其他逻辑 + + return openTicket; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/SubscribeMessage/WxApplet/WxAppletSubscribeMessage.cs b/Znyc.Admin.WeChat.Core/CommonService/SubscribeMessage/WxApplet/WxAppletSubscribeMessage.cs new file mode 100644 index 0000000..c9d1f79 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/SubscribeMessage/WxApplet/WxAppletSubscribeMessage.cs @@ -0,0 +1,132 @@ +using Senparc.Weixin.Entities; +using Senparc.Weixin.Entities.TemplateMessage; +using Senparc.Weixin.WxOpen.AdvancedAPIs; +using Znyc.Admin.Commons.Core.App; + +namespace Znyc.Admin.WeChat.CommonService.SubscribeMessage.WxApplet +{ + /// + /// 小程序订阅消息 + /// + public class WxAppletSubscribeMessage + { + private static readonly SenparcWeixinSetting senparcWeixinSetting = App.GetService(); + private static readonly string weixinAppId = senparcWeixinSetting.WxOpenAppId; + + /// + /// 留言提醒,模板编号:1069 + /// + /// 接收者(用户)的 openid + /// 消息模板Id + /// 留言内容,20个以内字符 + /// 留言时间,4小时制时间格式(支持+年月日) 例如:15:01,或:2019年10月1日 15:01 + /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + public static WxJsonResult SendCommentNotice(string toUser, string templateId, string text, string date, + string page) + { + TemplateMessageData data = new TemplateMessageData + { + ["thing1"] = new TemplateMessageDataValue(text), + ["time2"] = new TemplateMessageDataValue(date) + }; + var submitData = new + { + touser = toUser, + template_id = templateId, + page = page, + data = data + }; + return MessageApi.SendSubscribe(weixinAppId, toUser, templateId, data, page); + } + + /// + /// 新的评论提醒 ,模板编号:484 + /// + /// 接收者(用户)的 openid + /// 消息模板Id + /// 文章标题,20个以内字符 + /// 评论内容,20个以内字符 + /// 评论时间,4小时制时间格式(支持+年月日) 例如:15:01,或:2019年10月1日 15:01 + /// 评论用户,20个以内字符 + /// + public static WxJsonResult SendRemarkNotice(string toUser, string templateId, string title, string desc, + string date, string userNick, string page) + { + TemplateMessageData data = new TemplateMessageData + { + { "thing1", new TemplateMessageDataValue(title) }, + { "thing2", new TemplateMessageDataValue(desc) }, + { "time3", new TemplateMessageDataValue(date) }, + { "thing5", new TemplateMessageDataValue(userNick) } + }; + return MessageApi.SendSubscribe(weixinAppId, toUser, templateId, data, page); + } + + /// + /// 动态点赞通知,模板编号:579 + /// + /// 接收者(用户)的 openid + /// 消息模板Id + /// 点赞用户,20个以内字符 + /// 点赞时间,4小时制时间格式(支持+年月日) 例如:15:01,或:2019年10月1日 15:01 + /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + public static WxJsonResult SendGoodNotice(string toUser, string templateId, string name, string date, + string page) + { + TemplateMessageData data = new TemplateMessageData + { + { "name1", new TemplateMessageDataValue(name) }, + { "date2", new TemplateMessageDataValue(date) } + }; + return MessageApi.SendSubscribe(weixinAppId, toUser, templateId, data, page); + } + + /// + /// 资讯早报通知,模板编号:269 + /// + /// 接收者(用户)的 openid + /// 消息模板Id + /// 更新内容,20个以内字符 + /// 备注,20个以内字符 + /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + public static WxJsonResult SendNewsMorningNotice(string toUser, string templateId, string title, string remark, + string page) + { + TemplateMessageData data = new TemplateMessageData + { + ["thing1"] = new TemplateMessageDataValue(title), + ["thing2"] = new TemplateMessageDataValue(remark) + }; + var submitData = new + { + touser = toUser, + template_id = templateId, + page = page, + data = data + }; + return MessageApi.SendSubscribe(weixinAppId, toUser, templateId, data, page); + } + + /// + /// 校验一张图片是否含有违法违规内容 + /// https://developers.weixin.qq.com/miniprogram/dev/api/imgSecCheck.html + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// 文件完整物理路径格式支持PNG、JPEG、JPG、GIF,图片尺寸不超过 750px * 1334px + /// + /// + //[ApiBind(Senparc.NeuChar.PlatformType.WeChat_MiniProgram, "WxAppApi.ImgSecCheck", true)] + //public async static Task ImgSecCheck(string accessTokenOrAppId, string filePath, int timeOut = Config.TIME_OUT) + //{ + // return WxOpenApiHandlerWapper.TryCommonApi(async accessToken => + // { + // string urlFormat = Config.ApiMpHost + "/wxa/img_sec_check?access_token={0}"; + // var url = urlFormat.FormatWith(accessToken); + // var fileDic = new Dictionary(); + // fileDic["media"] = filePath; + // return await Senparc.CO2NET.HttpUtility.Post.PostFileGetJsonAsync(url,fileDictionary: fileDic); + + // }, accessTokenOrAppId); + //} + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage.cs b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage.cs new file mode 100644 index 0000000..7966d75 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage.cs @@ -0,0 +1,77 @@ +using Senparc.CO2NET.Cache; +using Senparc.Weixin.TenPay.V3; +using Senparc.Weixin.WxOpen.Containers; +using System; +using System.Threading.Tasks; +using Znyc.Admin.WeChat.CommonService.TemplateMessage.WxOpen; + +namespace Znyc.Admin.WeChat.CommonService +{ + public class TemplateMessageService + { + public async Task RunTemplateTestAsync(string wxOpenAppId, string sessionId, string formId) + { + SessionBag sessionBag = await SessionContainer.GetSessionAsync(sessionId); + string openId = sessionBag != null ? sessionBag.OpenId : "用户未正确登陆"; + + string title = null; + decimal price = 1; //单位:分,实际使用过程中,通过数据库获取订单并读取 + string productName = null; + string orderNumber = null; + + if (formId.StartsWith("prepay_id=")) + { + formId = formId.Replace("prepay_id=", ""); + title = "这是来自小程序支付的模板消息(仅测试接收,数据不一定真实)"; + + IBaseObjectCacheStrategy cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance(); + TenPayV3UnifiedorderRequestData unifiedorderRequestData = + await cacheStrategy.GetAsync( + $"WxOpenUnifiedorderRequestData-{openId}"); //获取订单请求信息缓存 + UnifiedorderResult unifedorderResult = + await cacheStrategy.GetAsync( + $"WxOpenUnifiedorderResultData-{openId}"); //获取订单信息缓存 + + if (unifedorderResult != null && formId == unifedorderResult.prepay_id) + { + price = unifiedorderRequestData.TotalFee; + productName = unifiedorderRequestData.Body + "/缓存获取 prepay_id 成功"; + orderNumber = unifiedorderRequestData.OutTradeNo; + } + else + { + productName = "缓存获取 prepay_id 失败"; + orderNumber = "1234567890"; + } + + productName += " | 注意:这条消息是从小程序发起的!仅作为UI上支付成功的演示!不能确定支付真实成功! | prepay_id:" + + unifedorderResult.prepay_id; + } + else + { + title = "在线购买(仅测试小程序接收模板消息,数据不一定真实)"; + productName = "商品名称-模板消息测试"; + orderNumber = "9876543210"; + } + + WxOpenTemplateMessage_PaySuccessNotice data = new WxOpenTemplateMessage_PaySuccessNotice(title, SystemTime.Now, productName, orderNumber, + price, + "400-031-8816", "https://sdk.senparc.weixin.com"); + + //await Senparc.Weixin.WxOpen.AdvancedAPIs + // .Template.TemplateApi + // .SendTemplateMessageAsync( + // wxOpenAppId, openId, data.TemplateId, data, formId, "pages/index/index", "图书", "#fff00"); + + return sessionBag; + } + + [Obsolete("建议使用 RunTemplateTestAsync 方法")] + public SessionBag RunTemplateTest(string wxOpenAppId, string sessionId, string formId) + { + SessionBag sessionBag = RunTemplateTestAsync(wxOpenAppId, sessionId, formId).ConfigureAwait(false).GetAwaiter() + .GetResult(); + return sessionBag; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WeixinTemplate_ExceptionAlert.cs b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WeixinTemplate_ExceptionAlert.cs new file mode 100644 index 0000000..ecdfa8e --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WeixinTemplate_ExceptionAlert.cs @@ -0,0 +1,65 @@ +//DPBMARK_FILE MP + +using Senparc.Weixin.Entities.TemplateMessage; +using Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage; +using System; + +namespace Znyc.Admin.WeChat.CommonService.TemplateMessage +{ + /* + {{first.DATA}} + Time:{{keyword1.DATA}} + Host:{{keyword2.DATA}} + Service:{{keyword3.DATA}} + Status:{{keyword4.DATA}} + Message:{{keyword5.DATA}} + {{remark.DATA}} + */ + + public class WeixinTemplate_ExceptionAlert : TemplateMessageBase + { + private const string TEMPLATE_ID = "ur6TqESOo-32FEUk4qJxeWZZVt4KEOPjqbAFDGWw6gg"; //每个公众号都不同,需要根据实际情况修改 + + public TemplateDataItem first { get; set; } + + /// + /// Time + /// + public TemplateDataItem keyword1 { get; set; } + + /// + /// Host + /// + public TemplateDataItem keyword2 { get; set; } + + /// + /// Service + /// + public TemplateDataItem keyword3 { get; set; } + + /// + /// Status + /// + public TemplateDataItem keyword4 { get; set; } + + /// + /// Message + /// + public TemplateDataItem keyword5 { get; set; } + + public TemplateDataItem remark { get; set; } + + public WeixinTemplate_ExceptionAlert(string _first, string host, string service, string status, string message, + string _remark, string url = null, string templateId = TEMPLATE_ID) + : base(templateId, url, "系统异常告警通知") + { + first = new TemplateDataItem(_first); + keyword1 = new TemplateDataItem(SystemTime.Now.LocalDateTime.ToString()); + keyword2 = new TemplateDataItem(host); + keyword3 = new TemplateDataItem(service); + keyword4 = new TemplateDataItem(status); + keyword5 = new TemplateDataItem(message); + remark = new TemplateDataItem(_remark); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WeixinTemplate_PaySuccess.cs b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WeixinTemplate_PaySuccess.cs new file mode 100644 index 0000000..bef05a6 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WeixinTemplate_PaySuccess.cs @@ -0,0 +1,29 @@ +//DPBMARK_FILE MP + +using Senparc.Weixin.Entities.TemplateMessage; +using Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage; + +namespace Znyc.Admin.WeChat.CommonService.TemplateMessage +{ + /// + /// 支付成功模板消息(购买成功通知) + /// + public class WeixinTemplate_PaySuccess : TemplateMessageBase + { + private const string TEMPLATE_ID = "66Gf81swxfWt_P_HkH0Bapvj1nlpiWGmEkXDeCvWcVo"; //每个公众号都不同,需要根据实际情况修改 + + public TemplateDataItem name { get; set; } + + /// + /// Time + /// + public TemplateDataItem remark { get; set; } + + public WeixinTemplate_PaySuccess(string url, string productName, string notice) + : base(TEMPLATE_ID, url, "购买成功通知") + { + name = new TemplateDataItem(productName); + remark = new TemplateDataItem(notice); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WxOpen/WxOpenTemplateMessage_PaySuccessNotice.cs b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WxOpen/WxOpenTemplateMessage_PaySuccessNotice.cs new file mode 100644 index 0000000..e620c31 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/TemplateMessage/WxOpen/WxOpenTemplateMessage_PaySuccessNotice.cs @@ -0,0 +1,55 @@ +//DPBMARK_FILE MiniProgram + +using Senparc.Weixin.Entities.TemplateMessage; +using Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage; +using System; + +namespace Znyc.Admin.WeChat.CommonService.TemplateMessage.WxOpen +{ + public class WxOpenTemplateMessage_PaySuccessNotice : TemplateMessageBase + { + public TemplateDataItem keyword1 { get; set; } + public TemplateDataItem keyword2 { get; set; } + public TemplateDataItem keyword3 { get; set; } + public TemplateDataItem keyword4 { get; set; } + public TemplateDataItem keyword5 { get; set; } + public TemplateDataItem keyword6 { get; set; } + + /// + /// “购买成功通知”模板消息数据 + /// + /// 购买地点 + /// 购买时间 + /// 物品名称 + /// 交易单号 + /// 购买价格 + /// 售后电话 + /// + /// + public WxOpenTemplateMessage_PaySuccessNotice( + string payAddress, DateTimeOffset payTime, string productName, + string orderNumber, decimal orderPrice, string hotLine, + string url, + //根据实际的“模板ID”进行修改 + string templateId = "Ap1S3tRvsB8BXsWkiILLz93nhe7S8IgAipZDfygy9Bg") + : base(templateId, url, "购买成功通知") + { + /* + 关键词 + 购买地点 {{keyword1.DATA}} + 购买时间 {{keyword2.DATA}} + 物品名称 {{keyword3.DATA}} + 交易单号 {{keyword4.DATA}} + 购买价格 {{keyword5.DATA}} + 售后电话 {{keyword6.DATA}} + */ + + keyword1 = new TemplateDataItem(payAddress); + keyword2 = new TemplateDataItem(payTime.LocalDateTime.ToString()); + keyword3 = new TemplateDataItem(productName); + keyword4 = new TemplateDataItem(orderNumber); + keyword5 = new TemplateDataItem(orderPrice.ToString("C")); + keyword6 = new TemplateDataItem(hotLine); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/CommonService/Utilities/FixWeixinBugWeixinResult.cs b/Znyc.Admin.WeChat.Core/CommonService/Utilities/FixWeixinBugWeixinResult.cs new file mode 100644 index 0000000..da794ad --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/Utilities/FixWeixinBugWeixinResult.cs @@ -0,0 +1,142 @@ +using Microsoft.AspNetCore.Mvc; +using Senparc.NeuChar.MessageHandlers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CommonService.Utilities +{ + /// + /// 修复微信换行 bug + /// + public class FixWeixinBugWeixinResult : ContentResult + { + //private string _content; + protected IMessageHandlerDocument _messageHandlerDocument; + + /// + /// 这个类型只用于特殊阶段:目前IOS版本微信有换行的bug,\r\n会识别为2行 + /// + public FixWeixinBugWeixinResult(IMessageHandlerDocument messageHandlerDocument) + { + _messageHandlerDocument = messageHandlerDocument; + } + + public FixWeixinBugWeixinResult(string content) + { + //_content = content; + base.Content = content; + } + + + public new string Content + { + get + { + if (base.Content != null) + { + return base.Content; + } + + if (_messageHandlerDocument != null) + { + //var textResponseMessag = _messageHandlerDocument.TextResponseMessage; + if (_messageHandlerDocument.TextResponseMessage != null) + { + return _messageHandlerDocument.TextResponseMessage.Replace("\r\n", "\n"); + } + + //if (_messageHandlerDocument.TextResponseMessage.Equals(String.Empty)) + //{ + // //无需响应,开发者返回了ResponseNoResponse + // return null; + //} + + //if (_messageHandlerDocument.ResponseDocument != null) + //{ + // //返回XML响应信息 + // return _messageHandlerDocument.TextResponseMessage.Replace("\r\n", "\n"); + //} + //else + //{ + // //返回XML响应信息或用户指定的文本内容 + // return _messageHandlerDocument.TextResponseMessage; + //} + } + return null; + } + set { base.Content = value; } + } + +#if NET45 + public override void ExecuteResult(ControllerContext context) + { + var content = this.Content; + + if (content == null) + { + //使用IMessageHandler输出 + if (_messageHandlerDocument == null) + { + throw new Senparc.Weixin.Exceptions.WeixinException("执行WeixinResult时提供的MessageHandler不能为Null!", null); + } + var finalResponseDocument = _messageHandlerDocument.FinalResponseDocument; + + + if (finalResponseDocument == null) + { + //throw new Senparc.Weixin.MP.WeixinException("FinalResponseDocument不能为Null!", null); + } + else + { + content = finalResponseDocument.ToString(); + } + } + + context.HttpContext.Response.ClearContent(); + context.HttpContext.Response.ContentType = "text/xml"; + content = (content ?? "").Replace("\r\n", "\n"); + + var bytes = Encoding.UTF8.GetBytes(content); + context.HttpContext.Response.OutputStream.Write(bytes, 0, bytes.Length); + } + +#else + public override async Task ExecuteResultAsync(ActionContext context) + { + var content = this.Content; + + if (content == null) + { + //使用IMessageHandler输出 + if (_messageHandlerDocument == null) + { + throw new Senparc.Weixin.Exceptions.WeixinException("执行WeixinResult时提供的MessageHandler不能为Null!", null); + } + var finalResponseDocument = _messageHandlerDocument.FinalResponseDocument; + + + if (finalResponseDocument == null) + { + //throw new Senparc.Weixin.MP.WeixinException("FinalResponseDocument不能为Null!", null); + } + else + { + content = finalResponseDocument.ToString(); + } + } + + context.HttpContext.Response.ContentType = "text/xml"; + content = (content ?? "").Replace("\r\n", "\n"); + + var bytes = Encoding.UTF8.GetBytes(content); + //context.HttpContext.Response.Body.Seek(0, SeekOrigin.Begin); + await context.HttpContext.Response.Body.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + + // return base.ExecuteResultAsync(context); + } +#endif + } +} diff --git a/Znyc.Admin.WeChat.Core/CommonService/Utilities/Server.cs b/Znyc.Admin.WeChat.Core/CommonService/Utilities/Server.cs new file mode 100644 index 0000000..31f063f --- /dev/null +++ b/Znyc.Admin.WeChat.Core/CommonService/Utilities/Server.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Http; + +namespace Znyc.Admin.WeChat.CommonService.Utilities +{ + public static class Server + { + public static HttpContext HttpContext + { + get + { + HttpContext context = new DefaultHttpContext(); + return context; + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/Model/WxUserInfo.cs b/Znyc.Admin.WeChat.Core/Model/WxUserInfo.cs new file mode 100644 index 0000000..84d2672 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/Model/WxUserInfo.cs @@ -0,0 +1,73 @@ +namespace Znyc.Admin.WeChat.Model +{ + /// + /// 微信用户信息实体对象 + /// + public class WxUserInfo + { + /// + /// 设置或获取昵称 + /// + public string UserName { get; set; } + + /// + /// 设置或获取用户头像图片的 URL + /// + public string avatarUrl { get; set; } + + /// + /// 设置或获取用户性别 + /// + public int gender { get; set; } + + /// + /// 设置或获取用户所在国家 + /// + public string country { get; set; } + + /// + /// 设置或获取用户所在省份 + /// + public string province { get; set; } + + /// + /// 设置或获取所在城市 + /// + public string city { get; set; } + + /// + /// 设置或获取用户所在国家 + /// + public string language { get; set; } + + /// + /// 设置或获取用户openId + /// + public string openId { get; set; } + + /// + /// 设置或获取用户openIdType + /// + public string openIdType { get; set; } + + /// + /// 设置或获取推广者ReferralUserId + /// + public int ReferralUserId { get; set; } + + /// + /// 设置或获取包括敏感数据在内的完整用户信息的加密数据 + /// + public string EncryptedData { get; set; } + + /// + /// 设置或获取加密算法的初始向量 + /// + public string Iv { get; set; } + + /// + /// 设置或获取微信登录的SessionId + /// + public string SessionId { get; set; } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/Properties/PublishProfiles/FolderProfile.pubxml b/Znyc.Admin.WeChat.Core/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..ccb19b1 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,13 @@ + + + + + FileSystem + Release + Any CPU + netcoreapp3.1 + bin\Release\netcoreapp3.1\publish\ + + \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/Wx/CommonHelper.cs b/Znyc.Admin.WeChat.Core/Wx/CommonHelper.cs new file mode 100644 index 0000000..293b0ff --- /dev/null +++ b/Znyc.Admin.WeChat.Core/Wx/CommonHelper.cs @@ -0,0 +1,325 @@ +using Senparc.CO2NET.Extensions; +using Senparc.CO2NET.HttpUtility; +using Senparc.Weixin; +using Senparc.Weixin.CommonAPIs; +using Senparc.Weixin.Entities; +using Senparc.Weixin.Entities.TemplateMessage; +using Senparc.Weixin.Exceptions; +using Senparc.Weixin.MP; +using Senparc.Weixin.MP.Containers; +using Senparc.Weixin.MP.Entities; +using System; +using System.Threading.Tasks; +using Znyc.Admin.Commons.Cache; + +namespace Wx +{ + /// + /// 通用接口 + /// 通用接口用于和微信服务器通讯,一般不涉及自有网站服务器的通讯 + /// + public static class CommonHelper + { + #region 同步方法 + + /// + /// 获取凭证接口 + /// + /// 获取access_token填写client_credential + /// 第三方用户唯一凭证 + /// 第三方用户唯一凭证密钥,既appsecret + /// + public static AccessTokenResult GetToken(string appid, string secret, string grant_type = "client_credential") + { + //注意:此方法不能再使用ApiHandlerWapper.TryCommonApi(),否则会循环 + string url = string.Format(Config.ApiMpHost + "/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", + grant_type.AsUrlData(), appid.AsUrlData(), secret.AsUrlData()); + + AccessTokenResult result = Get.GetJson(CommonDI.CommonSP, url); //此处为最原始接口,不再使用重试获取的封装 + + if (Config.ThrownWhenJsonResultFaild && result.errcode != ReturnCode.请求成功) + { + throw new ErrorJsonResultException( + string.Format("微信请求发生错误(CommonApi.GetToken)!错误代码:{0},说明:{1}", + (int)result.errcode, result.errmsg), null, result); + } + + return result; + } + + /// + /// 用户信息接口 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// + /// + public static WeixinUserInfoResult GetUserInfo(string accessTokenOrAppId, string openId) + { + return ApiHandlerWapper.TryCommonApi(accessToken => + { + string url = string.Format(Config.ApiMpHost + "/cgi-bin/user/info?access_token={0}&openid={1}", + accessToken.AsUrlData(), openId.AsUrlData()); + WeixinUserInfoResult result = CommonJsonSend.Send(null, url, null, CommonJsonSendType.GET); + return result; + }, accessTokenOrAppId); + } + + /// + /// 获取调用微信JS接口的临时票据 + /// + /// + /// + /// 默认为jsapi,当作为卡券接口使用时,应当为wx_card + /// + public static JsApiTicketResult GetTicket(string appId, string secret, string type = "jsapi") + { + string accessToken = AccessTokenContainer.TryGetAccessToken(appId, secret); + return GetTicketByAccessToken(accessToken, type); + } + + /// + /// 获取调用微信JS接口的临时票据 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// 默认为jsapi,当作为卡券接口使用时,应当为wx_card + /// + public static JsApiTicketResult GetTicketByAccessToken(string accessTokenOrAppId, string type = "jsapi") + { + return ApiHandlerWapper.TryCommonApi(accessToken => + { + string url = string.Format(Config.ApiMpHost + "/cgi-bin/ticket/getticket?access_token={0}&type={1}", + accessToken.AsUrlData(), type.AsUrlData()); + + JsApiTicketResult result = CommonJsonSend.Send(null, url, null, CommonJsonSendType.GET); + return result; + }, accessTokenOrAppId); + } + + /// + /// 获取微信服务器的ip段 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// + public static GetCallBackIpResult GetCallBackIp(string accessTokenOrAppId) + { + return ApiHandlerWapper.TryCommonApi(accessToken => + { + string url = string.Format(Config.ApiMpHost + "/cgi-bin/getcallbackip?access_token={0}", + accessToken.AsUrlData()); + + return CommonJsonSend.Send(null, url, null, CommonJsonSendType.GET); + }, accessTokenOrAppId); + } + + /// + /// 公众号调用或第三方平台帮公众号调用对公众号的所有api调用(包括第三方帮其调用)次数进行清零 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// + /// + /// + public static WxJsonResult Clear_quota(string accessTokenOrAppId, string appId, int timeOut = Config.TIME_OUT) + { + return ApiHandlerWapper.TryCommonApi(accessToken => + { + string urlFormat = string.Format(Config.ApiMpHost + "/cgi-bin/clear_quota?access_token={0}", + accessToken.AsUrlData()); + var data = new + { + appid = appId + }; + + return CommonJsonSend.Send(null, urlFormat, data, timeOut: timeOut); + }, accessTokenOrAppId); + } + + #endregion 同步方法 + + #region 异步方法 + + /// + /// 【异步方法】获取凭证接口 + /// + /// 获取access_token填写client_credential + /// 第三方用户唯一凭证 + /// 第三方用户唯一凭证密钥,既appsecret + /// + public static async Task GetTokenAsync(string appid, string secret, + string grant_type = "client_credential") + { + CacheHelper cacheHelper = new CacheHelper(); + AccessTokenResult result; + result = cacheHelper.Get(appid); + if (result == null) + { + string url = string.Format(Config.ApiMpHost + "/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", + grant_type.AsUrlData(), appid.AsUrlData(), secret.AsUrlData()); + + result = await Get.GetJsonAsync(CommonDI.CommonSP, url); //此处为最原始接口,不再使用重试获取的封装 + + if (Config.ThrownWhenJsonResultFaild && result.errcode != ReturnCode.请求成功) + { + throw new ErrorJsonResultException( + string.Format("微信请求发生错误(CommonApi.GetToken)!错误代码:{0},说明:{1}", + (int)result.errcode, result.errmsg), null, result); + } + + TimeSpan expiresSliding = DateTime.Now.AddSeconds(7200) - DateTime.Now; + cacheHelper.Add(appid, result, expiresSliding); + } + + return result; + } + + /// + /// 【异步方法】用户信息接口 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// + /// + public static async Task GetUserInfoAsync(string accessTokenOrAppId, string openId) + { + return await ApiHandlerWapper.TryCommonApiAsync(async accessToken => + { + string url = string.Format(Config.ApiMpHost + "/cgi-bin/user/info?access_token={0}&openid={1}", + accessToken.AsUrlData(), openId.AsUrlData()); + Task result = CommonJsonSend.SendAsync(null, url, null, CommonJsonSendType.GET); + return await result.ConfigureAwait(false); + }, accessTokenOrAppId).ConfigureAwait(false); + } + + /// + /// 【异步方法】获取调用微信JS接口的临时票据 + /// + /// + /// + /// 默认为jsapi,当作为卡券接口使用时,应当为wx_card + /// + public static async Task GetTicketAsync(string appId, string secret, string type = "jsapi") + { + string accessToken = await AccessTokenContainer.TryGetAccessTokenAsync(appId, secret).ConfigureAwait(false); + return GetTicketByAccessToken(accessToken, type); + } + + /// + /// 【异步方法】获取调用微信JS接口的临时票据 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// 默认为jsapi,当作为卡券接口使用时,应当为wx_card + /// + public static async Task GetTicketByAccessTokenAsync(string accessTokenOrAppId, + string type = "jsapi") + { + return await ApiHandlerWapper.TryCommonApiAsync(async accessToken => + { + string url = string.Format(Config.ApiMpHost + "/cgi-bin/ticket/getticket?access_token={0}&type={1}", + accessToken.AsUrlData(), type.AsUrlData()); + + Task result = CommonJsonSend.SendAsync(null, url, null, CommonJsonSendType.GET); + return await result.ConfigureAwait(false); + }, accessTokenOrAppId).ConfigureAwait(false); + } + + /// + /// 【异步方法】获取微信服务器的ip段 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// + public static async Task GetCallBackIpAsync(string accessTokenOrAppId) + { + return await ApiHandlerWapper.TryCommonApiAsync(async accessToken => + { + string url = string.Format(Config.ApiMpHost + "/cgi-bin/getcallbackip?access_token={0}", + accessToken.AsUrlData()); + + return await CommonJsonSend.SendAsync(null, url, null, CommonJsonSendType.GET) + .ConfigureAwait(false); + }, accessTokenOrAppId).ConfigureAwait(false); + } + + /// + /// 【异步方法】公众号调用或第三方平台帮公众号调用对公众号的所有api调用(包括第三方帮其调用)次数进行清零 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// + /// + /// + public static async Task Clear_quotaAsync(string accessTokenOrAppId, string appId, + int timeOut = Config.TIME_OUT) + { + return await ApiHandlerWapper.TryCommonApiAsync(async accessToken => + { + string urlFormat = string.Format(Config.ApiMpHost + "/cgi-bin/clear_quota?access_token={0}", + accessToken.AsUrlData()); + var data = new + { + appid = appId + }; + + return await CommonJsonSend.SendAsync(null, urlFormat, data, timeOut: timeOut) + .ConfigureAwait(false); + }, accessTokenOrAppId).ConfigureAwait(false); + } + + /// + /// 发送公司审核通知 + /// + /// + /// + /// + /// + /// + public static async Task SendCompanyAuditAsync(string thing13,string phrase2, string thing3, string toUser) + { + TemplateMessageData templateMessageData = new TemplateMessageData + { + ["thing13"] = new TemplateMessageDataValue(thing13), + ["date4"] = new TemplateMessageDataValue(SystemTime.Now.ToString("yyyy年MM月dd日 HH:mm")), + ["phrase2"] = new TemplateMessageDataValue(phrase2), + ["thing3"] = new TemplateMessageDataValue(thing3) + }; + await MessageHelper.SendSubscribeAsync(templateMessageData, + "2t_x25fDv2ekqJJPfCiLj-_Sc94bT9J9XzaR3-6FlCM", toUser, "pages/login/login"); + } + + /// + /// 实名认证失败发送通知 + /// + /// + public static async Task SendAuditFailAsync(string toUser) + { + string thing1 = "实名认证信息"; + TemplateMessageData templateMessageData = new TemplateMessageData + { + ["thing1"] = new TemplateMessageDataValue(thing1), + ["time2"] = new TemplateMessageDataValue(SystemTime.Now.ToString("yyyy年MM月dd日 HH:mm")), + ["phrase3"] = new TemplateMessageDataValue("审核失败"), + ["thing4"] = new TemplateMessageDataValue("") + }; + await MessageHelper.SendSubscribeAsync(templateMessageData, + "dm1yuO5nVqiRQyMWcS4VZOjOZY5rDCjhiqiUcueyMJc", toUser, "/page/index/index"); + } + + /// + /// 实名认证审核成功 + /// + /// + /// + public static async Task SendAuditSuccessAsync(string toUser) + { + string thing1 = "实名认证信息"; + //toUser = "oX5AI5rhIvgBDtuy3ytvkSao7eG4"; + TemplateMessageData templateMessageData = new TemplateMessageData + { + ["thing1"] = new TemplateMessageDataValue(thing1), + ["time2"] = new TemplateMessageDataValue(SystemTime.Now.ToString("yyyy年MM月dd日 HH:mm")), + ["phrase3"] = new TemplateMessageDataValue("审核通过"), + ["thing4"] = new TemplateMessageDataValue("满足通过条件") + }; + await MessageHelper.SendSubscribeAsync(templateMessageData, + "dm1yuO5nVqiRQyMWcS4VZOjOZY5rDCjhiqiUcueyMJc", toUser, "/page/index/index"); + } + + #endregion 异步方法 + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/Wx/MessageHelper.cs b/Znyc.Admin.WeChat.Core/Wx/MessageHelper.cs new file mode 100644 index 0000000..fd86db4 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/Wx/MessageHelper.cs @@ -0,0 +1,101 @@ +using Senparc.Weixin; +using Senparc.Weixin.CommonAPIs; +using Senparc.Weixin.Entities; +using Senparc.Weixin.Entities.TemplateMessage; +using Senparc.Weixin.WxOpen; +using System; +using System.Threading.Tasks; +using Znyc.Admin.Commons; +using Znyc.Admin.Commons.Log; + +namespace Wx +{ + /// + /// 小程序订阅消息接口 + /// + public class MessageHelper + { + #region 同步方法 + + /// + /// 发送订阅消息 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// 接收者(用户)的 openid + /// 所需下发的订阅模板id + /// 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } } + /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + /// + /// + public static WxJsonResult SendSubscribe(string accessTokenOrAppId, string toUser, string templateId, + TemplateMessageData data, string page = null, int timeOut = Config.TIME_OUT) + { + return WxOpenApiHandlerWapper.TryCommonApi(accessToken => + { + string urlFormat = Config.ApiMpHost + "/cgi-bin/message/subscribe/send?access_token={0}"; + var submitData = new + { + touser = toUser, + template_id = templateId, + page, + data + }; + return CommonJsonSend.Send(accessToken, urlFormat, submitData, timeOut: timeOut); + }, accessTokenOrAppId); + } + + #endregion 同步方法 + + #region 异步方法 + + public static async Task SendSubscribeAsync(TemplateMessageData templateMessageData, string templateId, + string toUser, + string pageUrl) + { + try + { + Senparc.Weixin.MP.Entities.AccessTokenResult accessTokenResult = await CommonHelper.GetTokenAsync( + Configs.GetConfigurationValue("SenparcWeixinSetting", "WxOpenAppId"), + Configs.GetConfigurationValue("SenparcWeixinSetting", "WxOpenAppSecret")); + string page = pageUrl; + WxJsonResult sU = await SendSubscribeAsync(accessTokenResult.access_token, + toUser, templateId, templateMessageData, + page); + } + catch (Exception ex) + { + Log4NetHelper.Error("SendSubscribeAsync" + ex); + } + } + + /// + /// 【异步方法】发送订阅消息 + /// + /// AccessToken或AppId(推荐使用AppId,需要先注册) + /// 接收者(用户)的 openid + /// 所需下发的订阅模板id + /// 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } } + /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + /// + /// + public static async Task SendSubscribeAsync(string accessTokenOrAppId, string toUser, + string templateId, TemplateMessageData data, string page = null, int timeOut = Config.TIME_OUT) + { + return await WxOpenApiHandlerWapper.TryCommonApiAsync(async accessToken => + { + string urlFormat = Config.ApiMpHost + "/cgi-bin/message/subscribe/send?access_token={0}"; + var submitData = new + { + touser = toUser, + template_id = templateId, + page, + data + }; + + return await CommonJsonSend.SendAsync(accessToken, urlFormat, submitData, timeOut: timeOut); + }, accessTokenOrAppId); + } + + #endregion 异步方法 + } +} \ No newline at end of file diff --git a/Znyc.Admin.WeChat.Core/Yuebon.WeChat.Core.csproj b/Znyc.Admin.WeChat.Core/Yuebon.WeChat.Core.csproj new file mode 100644 index 0000000..e7c49f0 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/Yuebon.WeChat.Core.csproj @@ -0,0 +1,46 @@ + + + + net5.0 + ZNYC.Admin.WeChat + 上海越邦网络科技有限公司 + Yuebon + YuebonNetCore 微信开放接口类库 + true + 上海越邦网络科技有限公司 版权所有 + YuebonNetCore 微信公众号、小程序、开放平台接口实现类库 + false + https://gitee.com/yuebon/YuebonNetCore + + + 1.1.1.9 + LICENSE + logo.png + https://gitee.com/yuebon/YuebonNetCore + + + + + + True + + + + + + + + + + + + + + + + + + + + + diff --git a/Znyc.Admin.WeChat.Core/Znyc.Admin.WeChat.Core.csproj b/Znyc.Admin.WeChat.Core/Znyc.Admin.WeChat.Core.csproj new file mode 100644 index 0000000..45fad25 --- /dev/null +++ b/Znyc.Admin.WeChat.Core/Znyc.Admin.WeChat.Core.csproj @@ -0,0 +1,37 @@ + + + + net6.0 + + + + + + + + false + + + + 1.0 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Znyc.Admin.WebApi/.config/dotnet-tools.json b/Znyc.Admin.WebApi/.config/dotnet-tools.json new file mode 100644 index 0000000..5112d4b --- /dev/null +++ b/Znyc.Admin.WebApi/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "3.1.8", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Attributes/QuartzAttribute.cs b/Znyc.Admin.WebApi/Attributes/QuartzAttribute.cs new file mode 100644 index 0000000..614d619 --- /dev/null +++ b/Znyc.Admin.WebApi/Attributes/QuartzAttribute.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Threading.Tasks; +using Znyc.Admin.WebApi.Auth; + +namespace Znyc.Admin.WebApi.Attributes +{ + /// + /// 定时任务启动密钥 + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] + public class QuartzAttribute : AuthorizeAttribute, IAuthorizationFilter, IAsyncAuthorizationFilter + { + private IApiHandler _apiHandler; + + /// + /// + /// + /// + /// + public Task OnAuthorizationAsync(AuthorizationFilterContext context) + { + OnAuthorization(context); + return Task.CompletedTask; + } + + /// + /// + /// + /// + public async void OnAuthorization(AuthorizationFilterContext context) + { + string apiUrl = context.HttpContext.Request.Path.Value; + _apiHandler = context.HttpContext.RequestServices.GetService(); + var entity = await _apiHandler.ValidateAsync(apiUrl); + //key/value 存入数据库去查询,不同的api对应不同的key/value + string authHeader = context.HttpContext.Request.Headers[entity.AuthKey]; + if (authHeader != null && authHeader.Equals(entity.AuthValue)) + { + return; + } + else + { + context.Result = new StatusCodeResult(StatusCodes.Status401Unauthorized); + } + } + } +} diff --git a/Znyc.Admin.WebApi/Auth/ApiHandler.cs b/Znyc.Admin.WebApi/Auth/ApiHandler.cs new file mode 100644 index 0000000..61e5001 --- /dev/null +++ b/Znyc.Admin.WebApi/Auth/ApiHandler.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Auth +{ + /// + /// 定时任务 + /// + public class ApiHandler : IApiHandler + { + private readonly IApiService _apiService; + + /// + /// + /// + /// + public ApiHandler(IApiService apiService) + { + _apiService = apiService; + } + + /// + /// + /// + /// + /// + public async Task ValidateAsync(string apiUrl) + { + var result = await _apiService.GetApiAsync(apiUrl); + return result; + } + } +} diff --git a/Znyc.Admin.WebApi/Auth/IApiHandler.cs b/Znyc.Admin.WebApi/Auth/IApiHandler.cs new file mode 100644 index 0000000..206cf14 --- /dev/null +++ b/Znyc.Admin.WebApi/Auth/IApiHandler.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.WebApi.Auth +{ + /// + /// 定时任务 + /// + public interface IApiHandler + { + /// + /// + /// + /// + /// + public Task ValidateAsync(string apiUrl); + } +} diff --git a/Znyc.Admin.WebApi/Config/HangFireQueuesConfig.cs b/Znyc.Admin.WebApi/Config/HangFireQueuesConfig.cs new file mode 100644 index 0000000..8ddc1c2 --- /dev/null +++ b/Znyc.Admin.WebApi/Config/HangFireQueuesConfig.cs @@ -0,0 +1,35 @@ +using System.ComponentModel; + +namespace Znyc.Admin.WebApi +{ + /// + /// Hangfire定时任务相关 + /// + public enum HangFireQueuesConfig + { + /// + /// 默认 + /// + [Description("默认")] + @default = 1, + + /// + /// 接口 + /// + [Description("接口")] + apis = 2, + + /// + /// 网站 + /// + [Description("网站")] + web = 3, + + /// + /// 循环时间 + /// + [Description("循环时间")] + recurring = 4, + } + +} diff --git a/Znyc.Admin.WebApi/Controllers/Area/LoginController.cs b/Znyc.Admin.WebApi/Controllers/Area/LoginController.cs new file mode 100644 index 0000000..0ff8978 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/LoginController.cs @@ -0,0 +1,500 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Common; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.Mvc.Filter; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Core.App; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Net; +using Znyc.Admin.Commons.Options; +using Znyc.Admin.Security.Application; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 用户登录接口控制器 + /// + [ApiController] + [ApiVersion("1.0")] + [Produces("application/json")] + [Route("api/[controller]")] + public class LoginController : ApiController + { + private readonly IAdminUserService _userService; + private readonly IAdminUserLogOnService _userLogOnService; + private readonly ISystemTypeService _systemTypeService; + private readonly IAPPService _appService; + private readonly IRoleService _roleService; + private readonly IRoleDataService _roleDataService; + private readonly IMenuService _menuService; + + /// + /// 构造函数注入服务 + /// + /// + /// + /// + /// + /// + /// + /// + public LoginController(IAdminUserService _service, IAdminUserLogOnService userLogOnService, + ISystemTypeService systemTypeService, IAPPService appService, + IRoleService roleService, IRoleDataService roleDataService, IMenuService menuService) + { + _userService = _service; + _userLogOnService = userLogOnService; + _systemTypeService = systemTypeService; + _appService = appService; + _roleService = roleService; + _roleDataService = roleDataService; + _menuService = menuService; + } + + /// + /// 用户登录,必须要有验证码 + /// + /// 用户名 + /// 密码 + /// 验证码 + /// 验证码key + /// AppId + /// 系统编码 + /// 返回用户User对象 + [HttpGet("GetCheckUser")] + [NoPermissionRequired] + public async Task GetCheckUser(string username, string password, string vcode, string vkey, + string appId, string systemCode) + { + CommonResult result = new CommonResult(); + RemoteIpParser remoteIpParser = new RemoteIpParser(); + string strIp = remoteIpParser.GetClientIp(HttpContext).MapToIPv4().ToString(); + CacheHelper cacheHelper = new CacheHelper(); + + if (string.IsNullOrEmpty(username)) + { + result.ErrMsg = "用户名不能为空!"; + } + else if (string.IsNullOrEmpty(password)) + { + result.ErrMsg = "密码不能为空!"; + } + + if (string.IsNullOrEmpty(systemCode)) + { + result.ErrMsg = ErrCode.err40006; + } + else + { + string strHost = Request.Host.ToString(); + APP app = _appService.GetAPP(appId); + if (app == null) + { + result.ErrCode = "40001"; + result.ErrMsg = ErrCode.err40001; + } + else + { + SystemType systemType = _systemTypeService.GetByCode(systemCode); + if (systemType == null) + { + result.ErrMsg = ErrCode.err40006; + } + else + { + Tuple userLogin = await _userService.Validate(username, password); + if (userLogin != null) + { + string ipAddressName = "未知"; //IpAddressUtil.GetCityByIp(); + if (userLogin.Item1 != null) + { + result.Success = true; + AdminUser user = userLogin.Item1; + JwtOption jwtModel = App.GetService(); + TokenProvider tokenProvider = new TokenProvider(jwtModel); + TokenResult tokenResult = tokenProvider.LoginToken(user, appId); + AdminCurrentUser currentSession = new AdminCurrentUser + { + UserId = user.Id, + Name = user.UserName, + AccessToken = tokenResult.AccessToken, + AppKey = appId, + CreateTime = DateTime.Now, + Role = _roleService.GetRoleEnCode(user.RoleId.ToString()), + ActiveSystemId = systemType.Id, + CurrentLoginIP = strIp, + IPAddressName = ipAddressName + }; + TimeSpan expiresSliding = DateTime.Now.AddMinutes(120) - DateTime.Now; + cacheHelper.Add("login_user_" + user.Id, currentSession, expiresSliding, + true); + + //var list = cacheHelper.Get("AllowAppId").ToJson() + // .ToList(); + //if (list.Count == 0) + //{ + // var appList = _appService.GetAllByIsNotDeleteAndEnabledMark(); + // cacheHelper.Add("AllowAppId", appList); + //} + + CurrentUser = currentSession; + result.ResData = currentSession; + result.ErrCode = ErrCode.successCode; + result.Success = true; + + //loginlogEntity.UserName = user.UserName; + //loginlogEntity.LoginTime = DateTime.Now; + //loginlogEntity.PlatformType = (int)PlatformTypeEnum.Management; + //loginlogEntity.IP = CurrentUser.CurrentLoginIP; + //loginlogEntity.OS = "PC"; + //loginlogEntity.Browser = ""; + //loginlogEntity.City = ""; + //loginlogEntity.Result = "登陆成功"; + //loginlogEntity.UserAgent = ""; + //loginlogEntity.Id = YitIdHelper.NextId(); + //_loginLogsService.Insert(loginlogEntity); + } + else + { + result.ErrCode = ErrCode.failCode; + result.ErrMsg = userLogin.Item2; + //loginlogEntity.UserName = ""; + ////user.UserName; + //loginlogEntity.LoginTime = DateTime.Now; + //loginlogEntity.PlatformType = (int)PlatformTypeEnum.Management; + //loginlogEntity.IP = strIp; //CurrentUser.CurrentLoginIP; + //loginlogEntity.OS = "PC"; + //loginlogEntity.Browser = ""; + //loginlogEntity.City = ""; + //loginlogEntity.Result = $"登陆失败|ErrMsg:{result.ErrMsg}"; + //loginlogEntity.UserAgent = ""; + //loginlogEntity.Id = YitIdHelper.NextId(); + //_loginLogsService.Insert(loginlogEntity); + } + } + } + } + } + + cacheHelper.Remove("LoginValidateCode"); + return ToJsonContent(result, true); + } + + /// + /// 获取登录用户权限信息 + /// + /// 返回用户User对象 + [HttpGet("GetUserInfo")] + [FunctionAuthorize("")] + public IActionResult GetUserInfo() + { + CommonResult result = new CommonResult(); + AdminUser user = _userService.Get(CurrentUser.UserId); + CacheHelper cacheHelper = new CacheHelper(); + SystemType systemType = _systemTypeService.Get(CurrentUser.ActiveSystemId); + AdminCurrentUser currentSession = new AdminCurrentUser + { + UserId = user.Id, + Account = user.Account, + Name = user.UserName, + AccessToken = CurrentUser.AccessToken, + AppKey = CurrentUser.AppKey, + CreateTime = DateTime.Now, + HeadIcon = user.HeadIcon, + Gender = user.Gender, + Role = _roleService.GetRoleEnCode(user.RoleId.ToString()), + MobilePhone = user.MobilePhone, + OrganizeId = user.OrganizeId, + DeptId = user.DepartmentId, + CurrentLoginIP = CurrentUser.CurrentLoginIP, + IPAddressName = CurrentUser.IPAddressName, + TenantId = 0, + UserTheme = "default" + }; + CurrentUser = currentSession; + + CurrentUser.ActiveSystemId = systemType.Id; + CurrentUser.ActiveSystem = systemType.FullName; + CurrentUser.ActiveSystemUrl = systemType.Url; + + List listFunction = new List(); + MenuApp menuApp = new MenuApp(); + if (Permission.IsAdmin(CurrentUser)) + { + CurrentUser.SubSystemList = + _systemTypeService.GetAllByIsNotDeleteAndEnabledMark().MapTo(); + //取得用户可使用的授权功能信息,并存储在缓存中 + listFunction = menuApp.GetFunctionsBySystem(CurrentUser.ActiveSystemId.ToString()); + CurrentUser.MenusRouter = menuApp.GetVueRouter(0, systemType.EnCode); + } + //else + //{ + // CurrentUser.SubSystemList = _systemTypeService.GetSubSystemList(user.RoleId.ToString()); + // //取得用户可使用的授权功能信息,并存储在缓存中 + // listFunction = menuApp.GetFunctionsByUser(user.Id, CurrentUser.ActiveSystemId.ToString()); + // CurrentUser.MenusRouter = menuApp.GetVueRouter(user.RoleId, systemType.EnCode); + //} + + AdminUserLogOn userLogOn = _userLogOnService.GetByUserId(CurrentUser.UserId); + //CurrentUser.UserTheme = userLogOn.Theme == null ? "default" : userLogOn.Theme; + TimeSpan expiresSliding = DateTime.Now.AddMinutes(120) - DateTime.Now; + cacheHelper.Add("User_Function_" + user.Id, listFunction, expiresSliding, true); + List listModules = new List(); + foreach (MenuOutputDto item in listFunction) + { + listModules.Add(item.EnCode); + } + + //CurrentUser.Modules = listModules; + cacheHelper.Add("login_user_" + user.Id, CurrentUser, expiresSliding, true); + //该用户的数据权限 + List roleDateList = _roleDataService.GetListDeptByRole(user.RoleId.ToString()); + cacheHelper.Add("User_RoleData_" + user.Id, roleDateList, expiresSliding, true); + result.ResData = CurrentUser; + result.ErrCode = ErrCode.successCode; + result.Success = true; + return ToJsonContent(result, true); + } + + /// + /// 用户登录,无验证码,主要用于app登录 + /// + /// 用户名 + /// 密码 + /// AppId + /// 系统编码 + /// 返回用户User对象 + [HttpGet("UserLogin")] + [NoPermissionRequired] + public async Task UserLogin(string username, string password, string appId, string systemCode) + { + CommonResult result = new CommonResult(); + RemoteIpParser remoteIpParser = new RemoteIpParser(); + string strIp = remoteIpParser.GetClientIp(HttpContext).MapToIPv4().ToString(); + CacheHelper cacheHelper = new CacheHelper(); + //LoginLogs loginlogEntity = new LoginLogs(); + + if (string.IsNullOrEmpty(username)) + { + result.ErrMsg = "用户名不能为空!"; + } + else if (string.IsNullOrEmpty(password)) + { + result.ErrMsg = "密码不能为空!"; + } + + if (string.IsNullOrEmpty(systemCode)) + { + result.ErrMsg = ErrCode.err40006; + } + else + { + string strHost = Request.Host.ToString(); + APP app = _appService.GetAPP(appId); + if (app == null) + { + result.ErrCode = "40001"; + result.ErrMsg = ErrCode.err40001; + } + else + { + SystemType systemType = _systemTypeService.GetByCode(systemCode); + if (systemType == null) + { + result.ErrMsg = ErrCode.err40006; + } + else + { + Tuple userLogin = await _userService.Validate(username, password); + if (userLogin != null) + { + string ipAddressName = IpAddressUtil.GetCityByIp(strIp); + if (userLogin.Item1 != null) + { + result.Success = true; + + AdminUser user = userLogin.Item1; + + JwtOption jwtModel = App.GetService(); + TokenProvider tokenProvider = new TokenProvider(jwtModel); + TokenResult tokenResult = tokenProvider.LoginToken(user, appId); + AdminCurrentUser currentSession = new AdminCurrentUser + { + UserId = user.Id, + Name = user.UserName, + AccessToken = tokenResult.AccessToken, + AppKey = appId, + CreateTime = DateTime.Now, + Role = _roleService.GetRoleEnCode(user.RoleId.ToString()), + ActiveSystemId = systemType.Id, + CurrentLoginIP = strIp, + IPAddressName = ipAddressName + }; + TimeSpan expiresSliding = DateTime.Now.AddMinutes(120) - DateTime.Now; + cacheHelper.Add("login_user_" + user.Id, currentSession, expiresSliding, + true); + CurrentUser = currentSession; + result.ResData = currentSession; + result.ErrCode = ErrCode.successCode; + result.Success = true; + + //loginlogEntity.UserName = user.UserName; + //loginlogEntity.LoginTime = DateTime.Now; + //loginlogEntity.IP = CurrentUser.CurrentLoginIP; + //loginlogEntity.OS = "PC"; + //loginlogEntity.Browser = ""; + //loginlogEntity.City = ""; + //loginlogEntity.Result = "登陆成功"; + //loginlogEntity.UserAgent = ""; + //_loginLogsService.Insert(loginlogEntity); + } + else + { + result.ErrCode = ErrCode.failCode; + result.ErrMsg = userLogin.Item2; + //loginlogEntity.UserName = ""; + ////user.UserName; + //loginlogEntity.LoginTime = DateTime.Now; + //loginlogEntity.IP = CurrentUser.CurrentLoginIP; + //loginlogEntity.OS = "PC"; + //loginlogEntity.Browser = ""; + //loginlogEntity.City = ""; + //loginlogEntity.Result = $"登陆失败|ErrMsg:{result.ErrMsg}"; + //loginlogEntity.UserAgent = ""; + //_loginLogsService.Insert(loginlogEntity); + } + } + } + } + } + + return ToJsonContent(result, true); + } + + /// + /// 退出登录 + /// + /// + [HttpGet("Logout")] + [FunctionAuthorize("")] + public IActionResult Logout() + { + CommonResult result = new CommonResult(); + CacheHelper cacheHelper = new CacheHelper(); + cacheHelper.Remove("login_user_" + CurrentUser.UserId); + cacheHelper.Remove("User_Function_" + CurrentUser.UserId); + AdminUserLogOn userLogOn = _userLogOnService.GetWhere("AdminUserId=" + CurrentUser.UserId); + userLogOn.UserOnLine = false; + _userLogOnService.Update(userLogOn, userLogOn.Id); + CurrentUser = null; + result.Success = true; + result.ErrCode = ErrCode.successCode; + result.ErrMsg = "成功退出"; + return ToJsonContent(result); + } + + /// + /// 子系统切换登录 + /// + /// 凭据 + /// 应用Id + /// 子系统编码 + /// 返回用户User对象 + [HttpGet("SysConnect")] + [AllowAnonymous] + [NoPermissionRequired] + public IActionResult SysConnect(string openmf, string appId, string systemCode) + { + CommonResult result = new CommonResult(); + RemoteIpParser remoteIpParser = new RemoteIpParser(); + string strIp = remoteIpParser.GetClientIp(HttpContext).MapToIPv4().ToString(); + if (string.IsNullOrEmpty(openmf)) + { + result.ErrMsg = "切换参数错误!"; + } + + string ipAddressName = IpAddressUtil.GetCityByIp(strIp); + if (string.IsNullOrEmpty(systemCode)) + { + result.ErrMsg = ErrCode.err40006; + } + else + { + string strHost = Request.Host.ToString(); + APP app = _appService.GetAPP(appId); + if (app == null) + { + result.ErrCode = "40001"; + result.ErrMsg = ErrCode.err40001; + } + else + { + SystemType systemType = _systemTypeService.GetByCode(systemCode); + if (systemType == null) + { + result.ErrMsg = ErrCode.err40006; + } + else + { + CacheHelper cacheHelper = new CacheHelper(); + object cacheOpenmf = cacheHelper.Get("openmf" + openmf); + cacheHelper.Remove("openmf" + openmf); + if (cacheOpenmf == null) + { + result.ErrCode = "40007"; + result.ErrMsg = ErrCode.err40007; + } + else + { + object a = cacheOpenmf.ToString(); + AdminUser user = _userService.Get(cacheOpenmf.ToLong()); + if (user != null) + { + result.Success = true; + JwtOption jwtModel = App.GetService(); + TokenProvider tokenProvider = new TokenProvider(jwtModel); + TokenResult tokenResult = tokenProvider.LoginToken(user, appId); + AdminCurrentUser currentSession = new AdminCurrentUser + { + UserId = user.Id, + Name = user.UserName, + AccessToken = tokenResult.AccessToken, + AppKey = appId, + CreateTime = DateTime.Now, + Role = _roleService.GetRoleEnCode(user.RoleId.ToString()), + ActiveSystemId = systemType.Id, + CurrentLoginIP = strIp, + IPAddressName = ipAddressName, + ActiveSystemUrl = systemType.Url + }; + TimeSpan expiresSliding = DateTime.Now.AddMinutes(120) - DateTime.Now; + cacheHelper.Add("login_user_" + user.Id, currentSession, expiresSliding, true); + CurrentUser = currentSession; + result.ResData = currentSession; + result.ErrCode = ErrCode.successCode; + result.Success = true; + } + else + { + result.ErrCode = ErrCode.failCode; + } + } + } + } + } + + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/MenuController.cs b/Znyc.Admin.WebApi/Controllers/Area/MenuController.cs new file mode 100644 index 0000000..9924535 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/MenuController.cs @@ -0,0 +1,328 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 功能菜单接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class MenuController : AreaApiController + { + /// + /// 构造函数 + /// + /// + public MenuController(IMenuService service) : base(service) + { + _service = service; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(Menu info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + if (info.SortCode == 0) + { + info.SortCode = 99; + } + + if (string.IsNullOrEmpty(info.ParentId.ToString())) + { + info.Layers = 1; + info.ParentId = 0; + } + else + { + info.Layers = _service.Get(info.ParentId).Layers + 1; + } + + if (info.MenuType == "F") + { + info.IsFrame = false; + info.Component = ""; + info.UrlAddress = ""; + } + } + + /// + /// 新增 + /// + /// + /// + [HttpPost("Insert")] + [FunctionAuthorize("Add")] + public override async Task InsertAsync(MenuInputDto info) + { + CommonResult result = new CommonResult(); + Menu menu = info.MapTo(); + long ln = 0; + if (info.IsBatch) + { + string strEnCode = info.EnCode; + Menu listInfo = new Menu(); + listInfo = menu; + listInfo.FullName = "列表"; + listInfo.EnCode = strEnCode + "/List"; + listInfo.Icon = "list"; + OnBeforeInsert(listInfo); + long listId = info.ParentId; + ln = _service.Insert(listInfo); + + Menu addInfo = new Menu(); + addInfo = menu; + addInfo.Id = 0; + addInfo.FullName = "新增"; + addInfo.EnCode = strEnCode + "/Add"; + addInfo.ParentId = listId; + addInfo.Icon = "add"; + addInfo.SortCode = 1; + OnBeforeInsert(addInfo); + ln = _service.Insert(addInfo); + + Menu viewInfo = new Menu(); + viewInfo = menu; + viewInfo.Id = 0; + viewInfo.FullName = "查看"; + viewInfo.EnCode = strEnCode + "/View"; + viewInfo.ParentId = listId; + viewInfo.Icon = "eye-open"; + viewInfo.SortCode = 1; + OnBeforeInsert(viewInfo); + ln = _service.Insert(viewInfo); + + Menu editnfo = new Menu(); + editnfo = menu; + editnfo.Id = 0; + editnfo.FullName = "修改"; + editnfo.EnCode = strEnCode + "/Edit"; + editnfo.ParentId = listId; + editnfo.Icon = "write"; + editnfo.SortCode = 2; + OnBeforeInsert(editnfo); + ln = _service.Insert(editnfo); + + Menu enableInfo = new Menu(); + enableInfo = menu; + enableInfo.Id = 0; + enableInfo.FullName = "禁用"; + enableInfo.EnCode = strEnCode + "/Enable"; + enableInfo.ParentId = listId; + enableInfo.Icon = "pause"; + enableInfo.SortCode = 3; + OnBeforeInsert(enableInfo); + ln = _service.Insert(enableInfo); + + Menu enableInfo1 = new Menu(); + enableInfo1 = menu; + enableInfo1.Id = 0; + enableInfo1.FullName = "启用"; + enableInfo1.EnCode = strEnCode + "/Enable"; + enableInfo1.ParentId = listId; + enableInfo1.Icon = "play"; + enableInfo1.SortCode = 4; + OnBeforeInsert(enableInfo1); + ln = _service.Insert(enableInfo1); + + Menu deleteSoftInfo = new Menu(); + deleteSoftInfo = menu; + deleteSoftInfo.Id = 0; + deleteSoftInfo.FullName = "软删除"; + deleteSoftInfo.EnCode = strEnCode + "/DeleteSoft"; + deleteSoftInfo.ParentId = listId; + deleteSoftInfo.Icon = "remove"; + deleteSoftInfo.SortCode = 5; + OnBeforeInsert(deleteSoftInfo); + ln = _service.Insert(deleteSoftInfo); + + Menu deleteInfo = new Menu(); + deleteInfo = menu; + deleteInfo.Id = 0; + deleteInfo.FullName = "删除"; + deleteInfo.EnCode = strEnCode + "/Delete"; + deleteInfo.ParentId = listId; + deleteInfo.Icon = "remove"; + deleteInfo.SortCode = 6; + OnBeforeInsert(deleteInfo); + ln = _service.Insert(deleteInfo); + } + else + { + OnBeforeInsert(menu); + ln = await _service.InsertAsync(menu); + } + + if (ln >= 0) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrCode = "43001"; + } + + return ToJsonContent(result); + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(Menu info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + + if (info.SortCode == 0) + { + info.SortCode = 99; + } + + if (string.IsNullOrEmpty(info.ParentId.ToString())) + { + info.Layers = 1; + info.ParentId = 0; + } + else + { + info.Layers = _service.Get(info.ParentId).Layers + 1; + } + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(Menu info) + { + info.IsDeleted = true; + } + + /// + /// 异步更新数据 + /// + /// + /// + [HttpPost("Update")] + [FunctionAuthorize("Edit")] + public override async Task UpdateAsync(MenuInputDto tinfo) + { + CommonResult result = new CommonResult(); + + Menu info = _service.Get(tinfo.Id); + info.FullName = tinfo.FullName; + info.EnCode = tinfo.EnCode; + info.SystemTypeId = tinfo.SystemTypeId; + info.ParentId = tinfo.ParentId; + info.Icon = tinfo.Icon; + + info.SortCode = tinfo.SortCode; + info.Description = tinfo.Description; + info.MenuType = tinfo.MenuType; + info.ActiveMenu = tinfo.ActiveMenu; + if (info.MenuType == "F") + { + info.IsFrame = false; + info.Component = ""; + info.UrlAddress = ""; + } + else + { + info.Component = tinfo.Component; + info.IsFrame = tinfo.IsFrame; + info.UrlAddress = tinfo.UrlAddress; + } + + info.IsShow = tinfo.IsShow; + + OnBeforeUpdate(info); + bool bl = await _service.UpdateAsync(info, tinfo.Id).ConfigureAwait(false); + if (bl) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 获取功能菜单适用于Vue 树形列表 + /// + /// 子系统Id + /// + [HttpGet("GetAllMenuTreeTable")] + [FunctionAuthorize("List")] + public async Task GetAllMenuTreeTable(string systemTypeId) + { + CommonResult result = new CommonResult(); + try + { + System.Collections.Generic.List list = await _service.GetAllMenuTreeTable(systemTypeId); + result.Success = true; + result.ErrCode = ErrCode.successCode; + result.ResData = list; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取菜单异常", ex); + result.ErrMsg = ErrCode.err40110; + result.ErrCode = "40110"; + } + + return ToJsonContent(result); + } + + ///// + ///// 异步批量物理删除 + ///// + ///// + //[HttpDelete("DeleteBatchAsync")] + //[FunctionAuthorize("Delete")] + //public override async Task DeleteBatchAsync(DeletesInputDto info) + //{ + // var result = new CommonResult(); + + // if (info.Ids.Length > 0) + // { + // result = await _service.DeleteBatchWhereAsync(info).ConfigureAwait(false); + // if (result.Success) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = ErrCode.err0; + // } + // else + // { + // result.ErrCode = "43003"; + // } + // } + + // return ToJsonContent(result); + //} + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/OrganizeController.cs b/Znyc.Admin.WebApi/Controllers/Area/OrganizeController.cs new file mode 100644 index 0000000..25d8560 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/OrganizeController.cs @@ -0,0 +1,277 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.ViewModel; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 组织机构接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class + OrganizeController : AreaApiController + { + /// + /// 构造函数 + /// + /// + public OrganizeController(IOrganizeService service) : base(service) + { + _service = service; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(Organize info) + { + info.Id = 0; + info.IsEnabled = true; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + if (info.SortCode == 0) + { + info.SortCode = 99; + } + + if (info.ParentId == 0) + { + info.Layers = 1; + info.ParentId = 0; + } + else + { + info.Layers = _service.Get(info.ParentId).Layers + 1; + } + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(Organize info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + if (string.IsNullOrEmpty(info.ParentId.ToString())) + { + info.Layers = 1; + info.ParentId = 0; + } + else + { + info.Layers = _service.Get(info.ParentId).Layers + 1; + } + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(Organize info) + { + info.IsDeleted = true; + } + + /// + /// 异步新增数据 + /// + /// + /// + [HttpPost("Insert")] + [FunctionAuthorize("Add")] + public override async Task InsertAsync(OrganizeInputDto tinfo) + { + CommonResult result = new CommonResult(); + Organize info = tinfo.MapTo(); + OnBeforeInsert(info); + info.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + int bl = await _service.InsertAsync(info).ConfigureAwait(false); + if (bl > 0) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 异步更新数据 + /// + /// + /// + [HttpPost("Update")] + [FunctionAuthorize("Edit")] + public override async Task UpdateAsync(OrganizeInputDto tinfo) + { + CommonResult result = new CommonResult(); + + Organize info = _service.Get(tinfo.Id); + info.ParentId = tinfo.ParentId; + info.FullName = tinfo.FullName; + info.EnCode = tinfo.EnCode; + info.ManagerName = tinfo.ManagerId; + info.SortCode = tinfo.SortCode; + info.Description = tinfo.Description; + OnBeforeUpdate(info); + bool bl = await _service.UpdateAsync(info, tinfo.Id).ConfigureAwait(false); + if (bl) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 获取组织机构适用于Vue 树形列表 + /// + /// + [HttpGet("GetAllOrganizeTreeTable")] + [FunctionAuthorize("List")] + public async Task GetAllOrganizeTreeTable() + { + CommonResult result = new CommonResult(); + try + { + var list = await _service.GetAllOrganizeTreeTable(); + result.Success = true; + result.ErrCode = ErrCode.successCode; + result.ResData = list; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取组织结构异常", ex); + result.ErrMsg = ErrCode.err40110; + result.ErrCode = "40110"; + } + + return ToJsonContent(result); + } + + /// + /// 获取组织机构适用于Vue Tree树形 + /// + /// + [HttpGet("GetAllOrganizeTree")] + [FunctionAuthorize("List")] + public async Task GetAllOrganizeTree() + { + CommonResult result = new CommonResult(); + try + { + System.Collections.Generic.List list = await _service.GetAllOrganizeTreeTable(); + result.Success = true; + result.ErrCode = ErrCode.successCode; + result.ResData = list; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取组织结构异常", ex); + result.ErrMsg = ErrCode.err40110; + result.ErrCode = "40110"; + } + + return ToJsonContent(result); + } + + /// + /// 异步批量禁用数据 + /// + /// + [HttpPost("SetEnabledMarktBatchAsync")] + [FunctionAuthorize("")] + public async Task SetEnabledMarktBatchAsync(UpdateEnableViewModel info) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + if (typeof(int) == typeof(string)) + { + @where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + } + else if (typeof(int) == typeof(int)) + { + @where = "id in (" + info.Ids.Join(",") + ")"; + } + + if (!string.IsNullOrEmpty(where)) + { + bool bl = false; + if (info.Flag == "1") + { + bl = true; + } + + bool blResult = await _service.SetEnabledMarkByWhereAsync(bl, where, CurrentUser.UserId); + if (blResult) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + } + + return ToJsonContent(result); + } + + ///// + ///// 异步批量物理删除 + ///// + ///// + //[HttpDelete("DeleteBatchAsync")] + //[FunctionAuthorize("Delete")] + //public override async Task DeleteBatchAsync(DeletesInputDto info) + //{ + // var result = new CommonResult(); + + // if (info.Ids.Length > 0) + // { + // result = await _service.DeleteBatchWhereAsync(info).ConfigureAwait(false); + // if (result.Success) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = ErrCode.err0; + // } + // else + // { + // result.ErrCode = "43003"; + // } + // } + + // return ToJsonContent(result); + //} + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/RoleAuthorizeController.cs b/Znyc.Admin.WebApi/Controllers/Area/RoleAuthorizeController.cs new file mode 100644 index 0000000..950fac7 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/RoleAuthorizeController.cs @@ -0,0 +1,243 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 角色权限接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class RoleAuthorizeController : AreaApiController + { + private readonly IMenuService menuService; + private readonly IRoleDataService roleDataService; + private readonly IOrganizeService organizeService; + + /// + /// + /// + /// + /// + /// + /// + public RoleAuthorizeController(IRoleAuthorizeService service, IMenuService _menuService, + IRoleDataService _roleDataService, IOrganizeService _organizeService) : base(service) + { + _service = service; + menuService = _menuService; + roleDataService = _roleDataService; + organizeService = _organizeService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(RoleAuthorize info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + if (info.SortCode == null) + { + info.SortCode = 99; + } + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(RoleAuthorize info) + { + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(RoleAuthorize info) + { + } + + /// + /// 角色分配权限树 + /// + /// + /// + /// + [HttpGet("GetRoleAuthorizeFunction")] + [FunctionAuthorize("List")] + public async Task GetRoleAuthorizeFunction(long roleId, string itemType) + { + CommonResult result = new CommonResult(); + // roleId = "'" + roleId + "'"; + List resultlist = new List(); + IEnumerable list = _service.GetListRoleAuthorizeByRoleId(roleId.ToString(), itemType); + foreach (RoleAuthorize info in list) + { + resultlist.Add(info.ItemId); + } + + result.ResData = resultlist; + result.ErrCode = ErrCode.successCode; + return ToJsonContent(result); + } + + /// + /// 保存角色权限 + /// + /// 功能权限 + /// + [HttpPost("SaveRoleAuthorize")] + [FunctionAuthorize("List")] + public async Task SaveRoleAuthorize(RoleAuthorizeDataInputDto roleinfo) + { + CommonResult result = new CommonResult(); + try + { + List inList = new List(); + foreach (int item in roleinfo.RoleFunctios) + { + Menu menu = menuService.Get(item); + if (menu != null) + { + RoleAuthorize info = new RoleAuthorize + { + ObjectId = roleinfo.RoleId, + ItemType = menu.MenuType == "C" || menu.MenuType == "M" ? 1 : 2, + ObjectType = 1, + ItemId = menu.Id + }; + OnBeforeInsert(info); + inList.Add(info); + } + } + + List roleDataList = new List(); + foreach (string item in roleinfo.RoleData) + { + RoleData info = new RoleData + { + RoleId = roleinfo.RoleId, + AuthorizeData = item, + DType = "dept" + }; + roleDataList.Add(info); + } + + foreach (int item in roleinfo.RoleSystem) + { + RoleAuthorize info = new RoleAuthorize + { + ObjectId = roleinfo.RoleId, + ItemType = 0, + ObjectType = 1, + ItemId = item + }; + OnBeforeInsert(info); + inList.Add(info); + } + + result.Success = await _service.SaveRoleAuthorize(roleinfo.RoleId, inList, roleDataList); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + } + } + catch (Exception ex) + { + result.ErrMsg = ex.Message; + } + + return ToJsonContent(result); + } + + private List SubFunction(List list, int roleId) + { + List inList = new List(); + foreach (ModuleFunctionOutputDto item in list) + { + RoleAuthorize info = new RoleAuthorize + { + ObjectId = roleId, + ItemType = 1, + ObjectType = 1, + ItemId = item.Id + }; + OnBeforeInsert(info); + inList.Add(info); + inList.Concat(SubFunction(item.Children, roleId)); + } + + return inList; + } + + /// + /// 获取功能菜单适用于Vue Tree树形 + /// + /// + [HttpGet("GetAllFunctionTree")] + [FunctionAuthorize("List")] + public async Task GetAllFunctionTree() + { + CommonResult result = new CommonResult(); + try + { + List list = await _service.GetAllFunctionTree(); + result.Success = true; + result.ErrCode = ErrCode.successCode; + result.ResData = list; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取菜单异常", ex); + result.ErrMsg = ErrCode.err40110; + result.ErrCode = "40110"; + } + + return ToJsonContent(result); + } + + /// + /// 获取功能菜单适用于Vue 树形列表 + /// + /// 子系统Id + /// + //[HttpGet("GetAllFunctionTreeTable")] + //[FunctionAuthorize("List")] + //public async Task GetAllFunctionTreeTable(string systemTypeId) + //{ + // CommonResult result = new CommonResult(); + // try + // { + // List list = await menuService.GetAllFunctionTreeTable(systemTypeId); + // result.Success = true; + // result.ErrCode = ErrCode.successCode; + // result.ResData = list; + // } + // catch (Exception ex) + // { + // Log4NetHelper.Error("获取菜单异常", ex); + // result.ErrMsg = ErrCode.err40110; + // result.ErrCode = "40110"; + // } + // return ToJsonContent(result); + //} + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/RoleController.cs b/Znyc.Admin.WebApi/Controllers/Area/RoleController.cs new file mode 100644 index 0000000..faab61d --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/RoleController.cs @@ -0,0 +1,203 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.ViewModel; +using Znyc.Admin.Commons.Dtos; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 角色接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class RoleController : AreaApiController + { + private readonly IOrganizeService organizeService; + + /// + /// 构造函数 + /// + /// + /// + public RoleController(IRoleService service, IOrganizeService _organizeService) : base(service) + { + _service = service; + organizeService = _organizeService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(Role info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + if (info.SortCode == 0) + { + info.SortCode = 99; + } + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(Role info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(Role info) + { + info.IsDeleted = true; + } + + /// + /// 异步新增数据 + /// + /// + /// + [HttpPost("Insert")] + [FunctionAuthorize("Add")] + public override async Task InsertAsync(RoleInputDto tinfo) + { + CommonResult result = new CommonResult(); + Role info = tinfo.MapTo(); + OnBeforeInsert(info); + info.Id = Yitter.IdGenerator.YitIdHelper.NextId(); + long bl = await _service.InsertReturnPrimaryKeyAsync(info).ConfigureAwait(false); + if (bl > 0) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 异步更新数据 + /// + /// + /// + [HttpPost("Update")] + [FunctionAuthorize("Edit")] + public override async Task UpdateAsync(RoleInputDto tinfo) + { + CommonResult result = new CommonResult(); + + Role info = _service.Get(tinfo.Id); + info.OrganizeId = tinfo.OrganizeId; + info.FullName = tinfo.FullName; + info.EnCode = tinfo.EnCode; + + info.SortCode = tinfo.SortCode; + info.Description = tinfo.Description; + info.Type = tinfo.Type; + + OnBeforeUpdate(info); + bool bl = await _service.UpdateAsync(info, tinfo.Id).ConfigureAwait(false); + if (bl) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 根据条件查询数据库,并返回对象集合(用于分页数据显示) + /// + /// + /// + [HttpPost("FindWithPagerAsync")] + [FunctionAuthorize("List")] + public virtual async Task>> FindWithPagerAsync( + SearchInputDto search) + { + CommonResult> result = new CommonResult> + { + ResData = await _service.FindWithPagerAsync(search), + ErrCode = ErrCode.successCode + }; + return result; + } + + /// + /// 异步批量禁用数据 + /// + /// + [HttpPost("SetEnabledMarktBatchAsync")] + [FunctionAuthorize("")] + public async Task SetEnabledMarktBatchAsync(UpdateEnableViewModel info) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + if (typeof(int) == typeof(string)) + { + @where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + } + else if (typeof(int) == typeof(int)) + { + @where = "id in (" + info.Ids.Join(",") + ")"; + } + + if (!string.IsNullOrEmpty(where)) + { + bool bl = false; + if (info.Flag == "1") + { + bl = true; + } + + bool blResult = await _service.SetEnabledMarkByWhereAsync(bl, where, CurrentUser.UserId); + if (blResult) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + } + + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/RoleDataController.cs b/Znyc.Admin.WebApi/Controllers/Area/RoleDataController.cs new file mode 100644 index 0000000..1bb2379 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/RoleDataController.cs @@ -0,0 +1,81 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 角色数据权限接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class + RoleDataController : AreaApiController + { + /// + /// 构造函数 + /// + /// + public RoleDataController(IRoleDataService service) : base(service) + { + _service = service; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(RoleData info) + { + info.Id = 0; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(RoleData info) + { + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(RoleData info) + { + } + + /// + /// 角色可以访问数据 + /// + /// 角色Id + /// + [HttpGet("GetAllRoleDataByRoleId")] + [FunctionAuthorize("List")] + public async Task GetAllRoleDataByRoleId(string roleId) + { + CommonResult result = new CommonResult(); + string where = string.Format("RoleId='{0}'", roleId); + List resultlist = new List(); + IEnumerable list = await _service.GetListWhereAsync(where); + foreach (RoleData info in list) + { + resultlist.Add(info.AuthorizeData); + } + + result.ResData = resultlist; + result.ErrCode = ErrCode.successCode; + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/SysSettingController.cs b/Znyc.Admin.WebApi/Controllers/Area/SysSettingController.cs new file mode 100644 index 0000000..4d9a768 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/SysSettingController.cs @@ -0,0 +1,295 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.Mvc.Filter; +using Znyc.Admin.Commons; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extend; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; +using Znyc.Admin.WebApi.Areas.Security.Entitys; + +namespace Znyc.Admin.WebApi.Areas.Security +{ + /// + /// 系统基本信息 + /// + [Route("api/Security/[controller]")] + [ApiController] + public class SysSettingController : ApiController + { + private readonly IWebHostEnvironment _hostingEnvironment; + private readonly IAdminUserService _adminUserService; + private readonly IMenuService _menuService; + private readonly IRoleService _roleService; + private readonly IAPPService _aPPService; + private readonly IUserService _userService; + private readonly IStatisticalService _statisticalService; + private readonly ICompanyService _companyService; + private readonly IVehicleService _vehicleService; + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public SysSettingController(IWebHostEnvironment hostingEnvironment, + IAdminUserService adminUserService, + IMenuService menuService, + IRoleService roleService, + IUserService userService, + IStatisticalService statisticalService, + IVehicleService vehicleService, + ICompanyService companyService, + IAPPService aPPService) + { + _hostingEnvironment = hostingEnvironment; + _adminUserService = adminUserService; + _menuService = menuService; + _roleService = roleService; + _aPPService = aPPService; + _userService = userService; + _statisticalService = statisticalService; + _companyService = companyService; + _vehicleService = vehicleService; + } + + /// + /// 获取系统信息 + /// + /// + [HttpGet("GetSysInfo")] + [FunctionAuthorize("GetSysInfo")] + public async Task GetSysInfo() + { + CommonResult result = new CommonResult(); + try + { + SysSetting sysSetting = XmlConverter.Deserialize("xmlconfig/sys.config"); + CacheHelper cacheHelper = new CacheHelper(); + cacheHelper.Add("SysSetting", sysSetting); + DashboardOutModel dashboardOutModel = new DashboardOutModel + { + CertificatedCompany = sysSetting.CompanyName, + WebUrl = sysSetting.WebUrl, + Title = sysSetting.SoftName, + MachineName = Environment.MachineName, + ProcessorCount = Environment.ProcessorCount, + SystemPageSize = Environment.SystemPageSize, + WorkingSet = Environment.WorkingSet, + TickCount = Environment.TickCount, + RunTimeLength = (Environment.TickCount / 1000).ToBrowseTime(), + FrameworkDescription = RuntimeInformation.FrameworkDescription, + OSName = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "Linux" : + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "OSX" : "Windows", + OSDescription = + RuntimeInformation.OSDescription + " " + RuntimeInformation.OSArchitecture, + OSArchitecture = RuntimeInformation.OSArchitecture.ToString(), + ProcessArchitecture = RuntimeInformation.ProcessArchitecture.ToString(), + + Directory = AppContext.BaseDirectory + }; + Version version = Environment.Version; + dashboardOutModel.SystemVersion = version.Major + "." + version.Minor + "." + version.Build; + dashboardOutModel.Version = AppVersionHelper.Version; + dashboardOutModel.Manufacturer = AppVersionHelper.Manufacturer; + dashboardOutModel.WebSite = AppVersionHelper.WebSite; + dashboardOutModel.UpdateUrl = AppVersionHelper.UpdateUrl; + dashboardOutModel.IPAdress = Request.HttpContext.Connection.LocalIpAddress.ToString(); + dashboardOutModel.Port = Request.HttpContext.Connection.LocalPort.ToString(); + dashboardOutModel.TotalUser = await _adminUserService.GetCountByWhereAsync("1=1"); + dashboardOutModel.TotalModule = await _menuService.GetCountByWhereAsync("1=1"); + dashboardOutModel.TotalRole = await _roleService.GetCountByWhereAsync("1=1"); + result.ResData = dashboardOutModel; + result.ErrCode = ErrCode.successCode; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取系统信息异常", ex); + result.ErrMsg = ErrCode.err60001; + result.ErrCode = "60001"; + } + + return ToJsonContent(result); + } + + /// + /// 首页统计数据 + /// + /// + [HttpGet("GetStatisticalDataInfo")] + [FunctionAuthorize("")] + public async Task GetStatisticalDataInfo() + { + CommonResult result = new CommonResult(); + try + { + var statistical = await _statisticalService.GetStatisticalAsync(); + StatisticalOutputDto statisticalData = new StatisticalOutputDto() + { + Time = DateTime.Now.ToString("yyyy-MM-dd"), + UserAddTotal = await _userService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"), + UserSumTotal = await _userService.GetCountByWhereAsync(" Status=1"), + CompanyAddTotal = await _companyService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"), + CompanySumTotal = await _companyService.GetCountByWhereAsync("Status = 1"), + VehicleAddTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"), + VehicleSumTotal = await _vehicleService.GetCountByWhereAsync("Status = 1"), + ExpireAddTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(ExpireTime) = dayofmonth(now()) and Status=1"), + ExpireSumTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(ExpireTime) < dayofmonth(now()) and Status=1") + }; + if (statistical == null) + { + statisticalData.UserAddTotalPercent = 0; + } + else + { + statisticalData.UserAddTotalPercent = statistical.UserAddTotalPercent; + + } + + result.ResData = statisticalData; + result.ErrCode = ErrCode.successCode; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取系统信息异常", ex); + result.ErrMsg = ErrCode.err60001; + result.ErrCode = "60001"; + } + + return ToJsonContent(result); + } + + /// + /// 获取系统基本信息不完整信息 + /// + /// + [HttpGet("GetInfo")] + [NoPermissionRequired] + public IActionResult GetInfo() + { + CommonResult result = new CommonResult(); + CacheHelper cacheHelper = new CacheHelper(); + SysSetting sysSetting = cacheHelper.Get("SysSetting").ToJson().ToObject(); + SysSettingOutputDto sysSettingOutputDto = new SysSettingOutputDto(); + if (sysSetting == null) + { + sysSetting = XmlConverter.Deserialize("xmlconfig/sys.config"); + } + + sysSetting.Email = ""; + sysSettingOutputDto = sysSetting.MapTo(); + if (sysSettingOutputDto != null) + { + sysSettingOutputDto.CopyRight = UIConstants.CopyRight; + result.ResData = sysSettingOutputDto; + result.Success = true; + result.ErrCode = ErrCode.successCode; + } + else + { + result.ErrMsg = ErrCode.err60001; + result.ErrCode = "60001"; + } + + System.Collections.Generic.IEnumerable appList = _aPPService.GetAllByIsNotDeleteAndEnabledMark(); + cacheHelper.Add("AllowAppId", appList); + return ToJsonContent(result); + } + + /// + /// 获取系统基本信息 + /// + /// + [HttpGet("GetAllInfo")] + [FunctionAuthorize("GetSysInfo")] + public IActionResult GetAllInfo() + { + CommonResult result = new CommonResult(); + CacheHelper cacheHelper = new CacheHelper(); + SysSetting sysSetting = cacheHelper.Get("SysSetting").ToJson().ToObject(); + SysSettingOutputDto sysSettingOutputDto = new SysSettingOutputDto(); + if (sysSetting == null) + { + sysSetting = XmlConverter.Deserialize("xmlconfig/sys.config"); + } + + //对关键信息解密 + if (!string.IsNullOrEmpty(sysSetting.Email)) + { + sysSetting.Email = DEncrypt.Decrypt(sysSetting.Email); + } + + sysSettingOutputDto = sysSetting.MapTo(); + if (sysSettingOutputDto != null) + { + sysSettingOutputDto.CopyRight = UIConstants.CopyRight; + result.ResData = sysSettingOutputDto; + result.Success = true; + result.ErrCode = ErrCode.successCode; + } + else + { + result.ErrMsg = ErrCode.err60001; + result.ErrCode = "60001"; + } + + return ToJsonContent(result); + } + + /// + /// 保存系统设置信息 + /// + /// + [HttpPost("Save")] + [FunctionAuthorize("Edit")] + public IActionResult Save(SysSetting info) + { + CommonResult result = new CommonResult(); + info.LocalPath = _hostingEnvironment.WebRootPath; + SysSetting sysSetting = XmlConverter.Deserialize("xmlconfig/sys.config"); + sysSetting = info; + //对关键信息加密 + string uploadPath = _hostingEnvironment.WebRootPath + "/" + sysSetting.Filepath; + if (!Directory.Exists(uploadPath)) + { + Directory.CreateDirectory(uploadPath); + } + + CacheHelper cacheHelper = new CacheHelper(); + if (cacheHelper.Exists("SysSetting")) + { + cacheHelper.Replace("SysSetting", sysSetting); + } + else + { + //写入缓存 + cacheHelper.Add("SysSetting", sysSetting); + } + + XmlConverter.Serialize(sysSetting, "xmlconfig/sys.config"); + result.ErrCode = ErrCode.successCode; + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/SystemTypeController.cs b/Znyc.Admin.WebApi/Controllers/Area/SystemTypeController.cs new file mode 100644 index 0000000..8eab725 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/SystemTypeController.cs @@ -0,0 +1,144 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 系统类型 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class + SystemTypeController : AreaApiController + { + /// + /// 构造函数 + /// + /// + public SystemTypeController(ISystemTypeService service) : base(service) + { + _service = service; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(SystemType info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(SystemType info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(SystemType info) + { + info.IsDeleted = true; + } + + /// + /// 异步更新数据 + /// + /// + /// + [HttpPost("Update")] + [FunctionAuthorize("Edit")] + public override async Task UpdateAsync(SystemTypeInputDto tinfo) + { + CommonResult result = new CommonResult(); + + SystemType info = _service.Get(tinfo.Id); + //info.FullName = tinfo.FullName; + //info.EnCode = tinfo.EnCode; + //info.Url = tinfo.Url; + //info.AllowEdit = tinfo.AllowEdit; + //info.AllowDelete = tinfo.AllowDelete; + //info.SortCode = tinfo.SortCode; + + //info.Description = tinfo.Description; + + OnBeforeUpdate(info); + bool bl = await _service.UpdateAsync(info, tinfo.Id).ConfigureAwait(true); + if (bl) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 系统切换时获取凭据 + /// 适用于不同子系统分别独立部署站点场景 + /// + /// 子系统编码 + /// + [HttpGet("ZnycConnecSys")] + [FunctionAuthorize("")] + public IActionResult ZnycConnecSys(string systype) + { + CommonResult result = new CommonResult(); + try + { + if (!string.IsNullOrEmpty(systype)) + { + SystemType systemType = _service.GetByCode(systype); + string openmf = MD5Util.GetMD5_32(DEncrypt.Encrypt(CurrentUser.UserId.ToString() + systemType.Id.ToString(), GuidUtils.NewGuidFormatN())).ToLower(); + CacheHelper cacheHelper = new CacheHelper(); + TimeSpan expiresSliding = DateTime.Now.AddSeconds(200) - DateTime.Now; + cacheHelper.Add("openmf" + openmf, CurrentUser.UserId, expiresSliding, false); + result.ErrCode = ErrCode.successCode; + result.ResData = systemType.Url + "?openmf=" + openmf; + } + else + { + result.ErrCode = ErrCode.failCode; + result.ErrMsg = "切换子系统参数错误"; + } + } + catch (Exception ex) + { + Log4NetHelper.Error("切换子系统异常", ex); + result.ErrMsg = ErrCode.err40110; + result.ErrCode = "40110"; + } + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/TokenController.cs b/Znyc.Admin.WebApi/Controllers/Area/TokenController.cs new file mode 100644 index 0000000..d1b37fa --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/TokenController.cs @@ -0,0 +1,189 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Options; +using Znyc.Admin.Security.IServices; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// Token令牌接口控制器 + /// + [Route("api/[controller]")] + [ApiController] + public class TokenController : ControllerBase + { + private readonly IAPPService _iAPPService; + private readonly IAdminUserService userService; + private readonly JwtOption _jwtModel; + + /// + /// 构造函数 + /// + /// + /// + /// + public TokenController(IAPPService iAPPService, IAdminUserService _userService, JwtOption jwtModel) + { + if (iAPPService == null) + { + throw new ArgumentNullException(nameof(iAPPService)); + } + + _iAPPService = iAPPService; + userService = _userService; + _jwtModel = jwtModel; + } + + /// + /// 根据应用信息获得token令牌 + /// + /// 获取access_token填写client_credential + /// 应用唯一凭证,应用AppId + /// 应用密钥AppSecret + /// + [HttpGet] + [AllowAnonymous] + public IActionResult Get(string grant_type, string appid, string secret) + { + CommonResult result = new CommonResult(); + if (!grant_type.Equals(GrantType.ClientCredentials)) + { + result.ErrCode = "40003"; + result.ErrMsg = ErrCode.err40003; + return ToJsonContent(result); + } + else if (string.IsNullOrEmpty(grant_type)) + { + result.ErrCode = "40003"; + result.ErrMsg = ErrCode.err40003; + return ToJsonContent(result); + } + + string strHost = Request.Host.ToString(); + var app = _iAPPService.GetAPP(appid, secret); + if (app == null) + { + result.ErrCode = "40001"; + result.ErrMsg = ErrCode.err40001; + } + else + { + TokenProvider tokenProvider = new TokenProvider(_jwtModel); + TokenResult tokenResult = tokenProvider.GenerateToken(grant_type, appid, secret); + result.ResData = tokenResult; + result.ErrCode = "0"; + return ToJsonContent(result); + } + + return ToJsonContent(result); + } + + /// + /// 验证token的合法性。 + /// + /// + /// + [HttpGet("CheckToken")] + [AllowAnonymous] + public IActionResult CheckToken(string token) + { + CommonResult result = new CommonResult(); + TokenProvider tokenProvider = new TokenProvider(_jwtModel); + result = tokenProvider.ValidateToken(token); + return ToJsonContent(result); + } + + /// + /// 刷新token。 + /// + /// + /// + [HttpGet("RefreshToken")] + [AllowAnonymous] + public async Task RefreshToken(string token) + { + CommonResult result = new CommonResult(); + TokenProvider tokenProvider = new TokenProvider(_jwtModel); + if (!string.IsNullOrEmpty(token)) + { + JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token); +#if DEBUG + Log4NetHelper.Debug(jwtToken.ToJson()); +#endif + if (jwtToken != null) + { + //根据应用获取token + if (jwtToken.Subject == GrantType.ClientCredentials) + { + TokenResult tresult = new TokenResult(); + List claimlist = jwtToken?.Payload.Claims as List; + string strHost = Request.Host.ToString(); + Security.Entitys.APP app = _iAPPService.GetAPP(claimlist[0].Value); + if (app == null) + { + result.ErrCode = "40001"; + result.ErrMsg = ErrCode.err40001; + } + else + { + TokenResult tokenResult = tokenProvider.GenerateToken(GrantType.ClientCredentials, app.AppId, + app.AppSecret); + result.ResData = tokenResult; + result.ErrCode = "0"; + result.Success = true; + } + } + + // 用户账号密码登录获取token类型 + if (jwtToken.Subject == GrantType.Password) + { + List claimlist = jwtToken?.Payload.Claims as List; + Security.Entitys.AdminUser user = await userService.GetByUserName(claimlist[2].Value); + TokenResult tokenResult = tokenProvider.LoginToken(user, claimlist[0].Value); + result.ResData = tokenResult; + result.ErrCode = "0"; + result.Success = true; + } + } + else + { + result.ErrMsg = ErrCode.err40004; + result.ErrCode = "40004"; + } + } + else + { + result.ErrMsg = ErrCode.err40004; + result.ErrCode = "40004"; + } + + return ToJsonContent(result); + } + + /// + /// 把object对象转换为ContentResult + /// + /// + /// + [HttpPost] + [Route("api/ToJsonContent")] + protected IActionResult ToJsonContent(object obj) + { + string result = JsonConvert.SerializeObject(obj, Formatting.Indented); + return Content(obj.ToJson()); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Area/UploadFileController.cs b/Znyc.Admin.WebApi/Controllers/Area/UploadFileController.cs new file mode 100644 index 0000000..ec9434e --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Area/UploadFileController.cs @@ -0,0 +1,73 @@ +using Microsoft.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 文件管理 + /// + [Route("api/Security/[controller]")] + [ApiController] + public class UploadFileController : AreaApiController + { + /// + /// + /// + /// + public UploadFileController(IUploadFileService service) : base(service) + { + _service = service; + } + + ///// + ///// 异步批量物理删除 + ///// + ///// 主键Id数组 + //[HttpDelete("DeleteBatchAsync")] + //[FunctionAuthorize("Delete")] + //public override async Task DeleteBatchAsync(DeletesInputDto info) + //{ + // var result = new CommonResult(); + // var where = string.Empty; + // where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + + // if (!string.IsNullOrEmpty(where)) + // { + // var jobsId = info.Ids; + // foreach (var item in jobsId) + // { + // if (string.IsNullOrEmpty(item.ToString())) continue; + // UploadFile uploadFile = new UploadFileApp().Get(item.ToString()); + // var cacheHelper = new CacheHelper(); + // var sysSetting = cacheHelper.Get("SysSetting").ToJson().ToObject(); + // if (uploadFile != null) + // { + // if (System.IO.File.Exists(sysSetting.LocalPath + "/" + uploadFile.FilePath)) + // System.IO.File.Delete(sysSetting.LocalPath + "/" + uploadFile.FilePath); + // if (!string.IsNullOrEmpty(uploadFile.Thumbnail)) + // if (System.IO.File.Exists(sysSetting.LocalPath + "/" + uploadFile.Thumbnail)) + // System.IO.File.Delete(sysSetting.LocalPath + "/" + uploadFile.Thumbnail); + // } + // } + + // var bl = await _service.DeleteBatchWhereAsync(where).ConfigureAwait(false); + // if (bl) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = ErrCode.err0; + // } + // else + // { + // result.ErrMsg = ErrCode.err43003; + // result.ErrCode = "43003"; + // } + // } + + // return ToJsonContent(result); + //} + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/APPController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/APPController.cs new file mode 100644 index 0000000..cddc4ff --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/APPController.cs @@ -0,0 +1,123 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 应用管理接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class APPController : AreaApiController + { + /// + /// 构造函数 + /// + /// + public APPController(IAPPService service) : base(service) + { + _service = service; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(APP info) + { + info.Id = 0; + info.AppSecret = MD5Util.GetMD5_32(GuidUtils.NewGuidFormatN()).ToUpper(); + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(APP info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(APP info) + { + info.IsDeleted = true; + } + + /// + /// 异步更新数据 + /// + /// + /// + [HttpPost("Update")] + [FunctionAuthorize("Edit")] + public override async Task UpdateAsync(APPInputDto tinfo) + { + CommonResult result = new CommonResult(); + + APP info = _service.Get(tinfo.Id); + info.AppId = tinfo.AppId; + OnBeforeUpdate(info); + bool bl = await _service.UpdateAsync(info, tinfo.Id).ConfigureAwait(true); + if (bl) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 重置AppSecret + /// + /// + [HttpGet("ResetAppSecret")] + [FunctionAuthorize("ResetAppSecret")] + public async Task ResetAppSecret(int id) + { + CommonResult result = new CommonResult(); + APP aPP = _service.Get(id); + aPP.AppSecret = MD5Util.GetMD5_32(GuidUtils.NewGuidFormatN()).ToUpper(); + bool bl = await _service.UpdateAsync(aPP, id); + if (bl) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = aPP.AppSecret; + result.Success = true; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/AdminUserController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/AdminUserController.cs new file mode 100644 index 0000000..5596c39 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/AdminUserController.cs @@ -0,0 +1,414 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Linq; +using System.Threading.Tasks; +using Yitter.IdGenerator; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.Mvc.Filter; +using Znyc.Admin.AspNetCore.ViewModel; +using Znyc.Admin.Commons.Encrypt; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Enums; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 系统用户接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + [AllowAnonymous] + [NoPermissionRequired] + public class AdminUserController : AreaApiController + { + private readonly IOrganizeService _organizeService; + private readonly IRoleService _roleService; + private readonly IAdminUserLogOnService _adminUserLogOnService; + + /// + /// + /// + /// + /// + /// + /// + public AdminUserController(IAdminUserService service, IOrganizeService organizeService, + IRoleService roleService, + IAdminUserLogOnService adminUserLogOnService + ) : base(service) + { + _service = service; + _organizeService = organizeService; + _roleService = roleService; + _adminUserLogOnService = adminUserLogOnService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(AdminUser info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.OrganizeId = _organizeService.GetRootOrganize(info.DepartmentId).Id; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(AdminUser info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + info.OrganizeId = _organizeService.GetRootOrganize(info.DepartmentId).Id; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(AdminUser info) + { + info.IsDeleted = true; + } + + /// + /// 异步新增数据 + /// + /// + /// + [HttpPost("Insert")] + [FunctionAuthorize("Add")] + public override async Task InsertAsync(AdminUserInputDto tinfo) + { + CommonResult result = new CommonResult(); + + if (!string.IsNullOrEmpty(tinfo.Account)) + { + string where = string.Format("Account='{0}' or MobilePhone='{0}'", tinfo.Account); + AdminUser Admin = _service.GetWhere(where); + if (Admin != null) + { + result.ErrMsg = "登录账号不能重复"; + return ToJsonContent(result); + } + } + else + { + result.ErrMsg = "登录账号不能为空"; + return ToJsonContent(result); + } + + AdminUser info = tinfo.MapTo(); + OnBeforeInsert(info); + info.Id = YitIdHelper.NextId(); + info.Status =(int) CommonStatus.ENABLE; + await _service.InsertAsync(info); + AdminUserLogOn adminLogOn = new AdminUserLogOn + { + AdminUserId = info.Id, + AdminUserSecretkey = MD5Util.GetMD5_16(GuidUtils.NewGuidFormatN()).ToLower() + }; + adminLogOn.AdminUserPassword = MD5Util + .GetMD5_32(DEncrypt.Encrypt(MD5Util.GetMD5_32("12345678").ToLower(), adminLogOn.AdminUserSecretkey) + .ToLower()).ToLower(); + adminLogOn.LogOnCount = 0; + adminLogOn.Language = ""; + adminLogOn.Theme = ""; + adminLogOn.Id = YitIdHelper.NextId(); + await _adminUserLogOnService.InsertAsync(adminLogOn); + result.Success = adminLogOn.AdminUserId > 0 ? true : false; + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43001; + result.ErrCode = "43001"; + } + + return ToJsonContent(result); + } + + /// + /// 异步更新数据 + /// + /// + /// + [HttpPost("Update")] + [FunctionAuthorize("Edit")] + public override async Task UpdateAsync(AdminUserInputDto tinfo) + { + CommonResult result = new CommonResult(); + if (string.IsNullOrEmpty(tinfo.Account)) + { + result.ErrMsg = "登录账号不能为空"; + return ToJsonContent(result); + } + + AdminUser info = _service.Get(tinfo.Id); + info.Account = tinfo.Account; + info.HeadIcon = tinfo.HeadIcon; + info.UserName = tinfo.UserName; + info.Gender = tinfo.Gender; + info.MobilePhone = tinfo.MobilePhone; + info.DepartmentId = tinfo.DepartmentId; + info.RoleId = tinfo.RoleId; + info.IsAdministrator = tinfo.IsAdministrator; + OnBeforeUpdate(info); + bool bl = await _service.UpdateAsync(info, tinfo.Id).ConfigureAwait(false); + if (bl) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 根据用户登录账号获取详细信息 + /// + /// + /// + [HttpGet("GetByUserName")] + [FunctionAuthorize("")] + public async Task GetByUserName(string userName) + { + CommonResult result = new CommonResult(); + try + { + AdminUser Admin = await _service.GetByUserName(userName); + result.ResData = Admin.MapTo(); + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + catch (Exception ex) + { + Log4NetHelper.Error("获取用户异常", ex); //错误记录 + result.ErrMsg = ex.Message; + } + + return ToJsonContent(result); + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchUserModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _service.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + + // + // 重置密码 + // + // + //[HttpPost("ResetPassword")] + //[FunctionAuthorize("ResetPassword")] + //public async Task ResetPassword(int UserId) + //{ + // CommonResult result = new CommonResult(); + // try + // { + // string where = string.Format("UserId='{0}'", UserId); + // AdminLogOn AdminLogOn = AdminLogOnService.GetWhere(where); + // Random random = new Random(); + // string strRandom = random.Next(100000, 999999).ToString(); //生成编号 + // AdminLogOn.AdminSecretkey = MD5Util.GetMD5_16(GuidUtils.NewGuidFormatN()).ToLower(); + // AdminLogOn.AdminPassword = MD5Util.GetMD5_32(DEncrypt.Encrypt(MD5Util.GetMD5_32(strRandom).ToLower(), AdminLogOn.AdminSecretkey).ToLower()).ToLower(); + // AdminLogOn.ChangePasswordDate = DateTime.Now; + // bool bl = await AdminLogOnService.UpdateAsync(AdminLogOn, AdminLogOn.Id); + // if (bl) + // { + // result.ErrCode = ErrCode.successCode; + // result.ErrMsg = strRandom; + // result.Success = true; + // } + // else + // { + // result.ErrMsg = ErrCode.err43002; + // result.ErrCode = "43002"; + // } + // } + // catch (Exception ex) + // { + // Log4NetHelper.Error("重置密码异常", ex); //错误记录 + // result.ErrMsg = ex.Message; + // } + + // return ToJsonContent(result); + //} + + /// + /// 修改密码 + /// + /// 原密码 + /// 新密码 + /// 重复新密码 + /// + [HttpPost("ModifyPassword")] + [FunctionAuthorize("ModifyPassword")] + public async Task ModifyPassword(string oldpassword, string password, string password2) + { + CommonResult result = new CommonResult(); + try + { + if (string.IsNullOrEmpty(oldpassword)) + { + result.ErrMsg = "原密码不能为空!"; + } + else if (string.IsNullOrEmpty(password)) + { + result.ErrMsg = "密码不能为空!"; + } + else if (string.IsNullOrEmpty(password2)) + { + result.ErrMsg = "重复输入密码不能为空!"; + } + else if (password == password2) + { + AdminUserLogOn AdminSinginEntity = _adminUserLogOnService.GetByUserId(CurrentUser.UserId); + string inputPassword = MD5Util.GetMD5_32(DEncrypt.Encrypt(MD5Util.GetMD5_32(oldpassword).ToLower(), + AdminSinginEntity.AdminUserSecretkey).ToLower()).ToLower(); + if (inputPassword != AdminSinginEntity.AdminUserPassword) + { + result.ErrMsg = "原密码错误!"; + } + else + { + string where = string.Format("AdminUserId='{0}'", CurrentUser.UserId); + AdminUserLogOn AdminLogOn = _adminUserLogOnService.GetWhere(where); + + AdminLogOn.AdminUserSecretkey = MD5Util.GetMD5_16(GuidUtils.NewGuidFormatN()).ToLower(); + AdminLogOn.AdminUserPassword = MD5Util + .GetMD5_32(DEncrypt.Encrypt(MD5Util.GetMD5_32(password).ToLower(), + AdminLogOn.AdminUserSecretkey).ToLower()).ToLower(); + AdminLogOn.ChangePasswordDate = DateTime.Now; + bool bl = await _adminUserLogOnService.UpdateAsync(AdminLogOn, AdminLogOn.Id); + if (bl) + { + result.ErrCode = ErrCode.successCode; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + } + } + else + { + result.ErrMsg = "两次输入的密码不一样"; + } + } + catch (Exception ex) + { + Log4NetHelper.Error("重置密码异常", ex); //错误记录 + result.ErrMsg = ex.Message; + } + + return ToJsonContent(result); + } + + /// + /// 异步批量禁用数据 + /// + /// + [HttpPost("SetEnabledMarktBatchAsync")] + [FunctionAuthorize("")] + public async Task SetEnabledMarktBatchAsync(UpdateEnableViewModel info) + { + CommonResult result = new CommonResult(); + string where = string.Empty; + if (typeof(int) == typeof(string)) + { + @where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')"; + } + else if (typeof(int) == typeof(int)) + { + @where = "id in (" + info.Ids.Join(",") + ")"; + } + + if (!string.IsNullOrEmpty(where)) + { + bool bl = false; + if (info.Flag == "1") + { + bl = true; + } + + bool blResult = await _service.SetEnabledMarkByWhereAsync(bl, where, CurrentUser.UserId); + if (blResult) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + } + + return ToJsonContent(result); + } + + /// + /// 保存用户自定义的软件主题 + /// + /// 主题配置信息 + /// + [HttpPost("SaveUserTheme")] + [FunctionAuthorize("SaveUserTheme")] + public async Task SaveUserTheme(UserThemeInputDto info) + { + CommonResult result = new CommonResult(); + try + { + result.Success = await _adminUserLogOnService.SaveUserTheme(info, CurrentUser.UserId); + result.ErrCode = ErrCode.successCode; + } + catch (Exception ex) + { + Log4NetHelper.Error("保存用户自定义的软件主题异常", ex);//错误记录 + result.ErrMsg = ex.Message; + } + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/AreaController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/AreaController.cs new file mode 100644 index 0000000..cef2161 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/AreaController.cs @@ -0,0 +1,65 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 地区接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class AreaController : AreaApiController + { + private readonly IAreaService _areaService; + + /// + /// 构造函数 + /// + /// + public AreaController(IAreaService _service) : base(_service) + { + _areaService = _service; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(Area info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + if (info.SortCode == 0) + { + info.SortCode = 99; + } + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(Area info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(Area info) + { + info.IsDeleted = true; + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/CompanyController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/CompanyController.cs new file mode 100644 index 0000000..b356b5c --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/CompanyController.cs @@ -0,0 +1,138 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 公司服务 + /// + [ApiController] + [Route("api/Dispatching/[controller]")] + public class CompanyController : AreaApiController + { + private readonly ICompanyService _companyServices; + + /// + /// 构造函数 + /// + public CompanyController( + ICompanyService service + ) : base(service) + { + _companyServices = service; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(Company info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(Company info) + { + info.CreatedUserId = CurrentUser.UserId; + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(Company info) + { + info.IsDeleted = true; + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchUserModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _companyServices.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + + /// + /// 审核公司状态 + /// + /// + /// + /// + [HttpPut("AuditAsync")] + public async Task AuditAsync(long id, int status) + { + CommonResult result = new CommonResult(); + result = await _companyServices.AuditAsync(id, status); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = result.ErrMsg; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + + /// + /// 修改公司状态 + /// + /// + /// + /// + [HttpPut("UpdateAsync")] + public async Task UpdateAsync(long id, int status) + { + CommonResult result = new CommonResult(); + result = await _companyServices.UpdateAsync(id, status); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + + + + + + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/FilesController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/FilesController.cs new file mode 100644 index 0000000..e93d9f6 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/FilesController.cs @@ -0,0 +1,302 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.IO; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Extend; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Security.Application; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 文件上传 + /// + [Route("api/[controller]")] + [ApiController] + public class FilesController : ApiController + { + private string _filePath; + private string _dbFilePath; //数据库中的文件路径 + private string _dbThumbnail; //数据库中的缩略图路径 + private string _belongApp; //所属应用 + private string _belongAppId; //所属应用ID + private string _fileName; //文件名称 + private readonly IWebHostEnvironment _hostingEnvironment; + + /// + /// + /// + /// + public FilesController(IWebHostEnvironment hostingEnvironment) + { + _hostingEnvironment = hostingEnvironment; + } + + /// + /// 单文件上传接口 + /// + /// + /// 服务器存储的文件信息 + [HttpPost("Upload")] + public IActionResult Upload([FromForm] IFormCollection formCollection) + { + CommonResult result = new CommonResult(); + + FormFileCollection filelist = (FormFileCollection)formCollection.Files; + string belongApp = formCollection["belongApp"].ToString(); + string belongAppId = formCollection["belongAppId"].ToString(); + _fileName = filelist[0].FileName; + try + { + result.ResData = Add(filelist[0], belongApp, belongAppId); + result.ErrCode = ErrCode.successCode; + result.Success = true; + } + catch (Exception ex) + { + result.ErrCode = "500"; + result.ErrMsg = ex.Message; + Log4NetHelper.Error("", ex); + //throw ex; + } + + return ToJsonContent(result); + } + + /// + /// 批量上传文件接口 + /// + /// + /// 服务器存储的文件信息 + [HttpPost("Uploads")] + public IActionResult Uploads([FromForm] IFormCollection formCollection) + { + CommonResult result = new CommonResult(); + FormFileCollection filelist = (FormFileCollection)formCollection.Files; + string belongApp = formCollection["belongApp"].ToString(); + string belongAppId = formCollection["belongAppId"].ToString(); + try + { + result.ResData = Adds(filelist, belongApp, belongAppId); + } + catch (Exception ex) + { + Log4NetHelper.Error("", ex); + result.ErrCode = "500"; + result.ErrMsg = ex.Message; + } + + return ToJsonContent(result); + } + + /// + /// 删除文件 + /// + /// + /// + [HttpGet("DeleteFile")] + public IActionResult DeleteFile(int id) + { + CommonResult result = new CommonResult(); + try + { + UploadFile uploadFile = new UploadFileApp().Get(id); + + CacheHelper cacheHelper = new CacheHelper(); + SysSetting sysSetting = cacheHelper.Get("SysSetting").ToJson().ToObject(); + string localpath = _hostingEnvironment.WebRootPath; + if (uploadFile != null) + { + string filepath = (localpath + "/" + uploadFile.FilePath).ToFilePath(); + if (System.IO.File.Exists(filepath)) + { + System.IO.File.Delete(filepath); + } + + string filepathThu = (localpath + "/" + uploadFile.Thumbnail).ToFilePath(); + if (System.IO.File.Exists(filepathThu)) + { + System.IO.File.Delete(filepathThu); + } + + result.ErrCode = ErrCode.successCode; + result.Success = true; + } + else + { + result.ErrCode = ErrCode.failCode; + result.Success = false; + } + } + catch (Exception ex) + { + Log4NetHelper.Error("", ex); + result.ErrCode = "500"; + result.ErrMsg = ex.Message; + } + + return ToJsonContent(result); + } + + /// + /// 批量上传文件 + /// + /// 文件 + /// 所属应用,如文章article + /// 所属应用ID,如文章id + /// + private List Adds(IFormFileCollection files, string belongApp, string belongAppId) + { + List result = new List(); + foreach (IFormFile file in files) + { + if (file != null) + { + result.Add(Add(file, belongApp, belongAppId)); + } + } + + return result; + } + + /// + /// 单个上传文件 + /// + /// + /// + /// + /// + private UploadFileResultOuputDto Add(IFormFile file, string belongApp, string belongAppId) + { + _belongApp = belongApp; + _belongAppId = belongAppId; + if (file != null && file.Length > 0 && file.Length < 10485760) + { + using (BinaryReader binaryReader = new BinaryReader(file.OpenReadStream())) + { + string fileName = string.Empty; + fileName = _fileName; + + byte[] data = binaryReader.ReadBytes((int)file.Length); + UploadFile(fileName, data); + ; + UploadFile filedb = new UploadFile + { + Id = 0, + FilePath = _dbFilePath, + Thumbnail = _dbThumbnail, + FileName = fileName, + FileSize = file.Length.ToInt(), + FileType = Path.GetExtension(fileName), + Extension = Path.GetExtension(fileName), + BelongApp = _belongApp, + BelongAppId = _belongAppId + }; + //new UploadFileApp().Insert(filedb); + UploadFileResultOuputDto uploadFileResultOuputDto = filedb.MapTo(); + uploadFileResultOuputDto.PhysicsFilePath = + (_hostingEnvironment.WebRootPath + "/" + _dbThumbnail).ToFilePath(); + ; + return uploadFileResultOuputDto; + } + } + else + { + Log4NetHelper.Info("文件过大"); + throw new Exception("文件过大"); + } + } + + /// + /// 实现文件上传到服务器保存,并生成缩略图 + /// + /// 文件名称 + /// 文件字节流 + private void UploadFile(string fileName, byte[] fileBuffers) + { + //判断文件是否为空 + if (string.IsNullOrEmpty(fileName)) + { + Log4NetHelper.Info("文件名不能为空"); + throw new Exception("文件名不能为空"); + } + + //判断文件是否为空 + if (fileBuffers.Length < 1) + { + Log4NetHelper.Info("文件不能为空"); + throw new Exception("文件不能为空"); + } + + CacheHelper cacheHelper = new CacheHelper(); + SysSetting sysSetting = cacheHelper.Get("SysSetting").ToJson().ToObject(); + string folder = DateTime.Now.ToString("yyyyMMdd"); + _filePath = _hostingEnvironment.WebRootPath; + string _tempfilepath = sysSetting.Filepath; + + if (!string.IsNullOrEmpty(_belongApp)) + { + _tempfilepath += "/" + _belongApp; + } + + if (!string.IsNullOrEmpty(_belongAppId)) + { + _tempfilepath += "/" + _belongAppId; + } + + if (sysSetting.Filesave == "1") + { + _tempfilepath = _tempfilepath + "/" + folder + "/"; + } + + if (sysSetting.Filesave == "2") + { + DateTime date = DateTime.Now; + _tempfilepath = _tempfilepath + "/" + date.Year + "/" + date.Month + "/" + date.Day + "/"; + } + + string uploadPath = _filePath + "/" + _tempfilepath; + if (sysSetting.Fileserver == "localhost") + { + if (!Directory.Exists(uploadPath)) + { + Directory.CreateDirectory(uploadPath); + } + } + + string ext = Path.GetExtension(fileName).ToLower(); + Guid newName = Guid.NewGuid(); + string newfileName = newName + ext; + + using (FileStream fs = new FileStream(uploadPath + newfileName, FileMode.Create)) + { + fs.Write(fileBuffers, 0, fileBuffers.Length); + fs.Close(); + //生成缩略图 + if (ext.Contains(".jpg") || ext.Contains(".jpeg") || ext.Contains(".png") || ext.Contains(".bmp") || + ext.Contains(".gif")) + { + string thumbnailName = newName + "_" + sysSetting.Thumbnailwidth + "x" + sysSetting.Thumbnailheight + + ext; + ImgHelper.MakeThumbnail(uploadPath + newfileName, uploadPath + thumbnailName, + sysSetting.Thumbnailwidth.ToInt(), sysSetting.Thumbnailheight.ToInt()); + _dbThumbnail = _tempfilepath + thumbnailName; + } + + _dbFilePath = _tempfilepath + newfileName; + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/FunctionController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/FunctionController.cs new file mode 100644 index 0000000..13572f9 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/FunctionController.cs @@ -0,0 +1,81 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Json; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 功能模块接口 + /// + [ApiController] + [Produces("application/json")] + [Route("api/[controller]")] + public class FunctionController : AreaApiController + { + /// + /// + /// + /// + public FunctionController(IMenuService service) : base(service) + { + _service = service; + } + + /// + /// 根据父级功能编码查询所有子集功能,主要用于页面操作按钮权限 + /// + /// 菜单功能编码 + /// + [HttpGet("GetListByParentEnCode")] + [FunctionAuthorize("")] + public IActionResult GetListByParentEnCode(string enCode) + { + CommonResult result = new CommonResult(); + try + { + if (CurrentUser != null) + { + CacheHelper cacheHelper = new CacheHelper(); + List functions = new List(); + functions = cacheHelper.Get("User_Function_" + CurrentUser.UserId).ToJson() + .ToObject>(); + MenuOutputDto functionOutputDto = functions.Find(s => s.EnCode == enCode); + List nowFunList = new List(); + if (functionOutputDto != null) + { + nowFunList = functions + .FindAll(s => s.ParentId == functionOutputDto.Id && s.IsShow && s.MenuType.Equals("F")) + .OrderBy(s => s.SortCode).ToList(); + } + + result.ErrCode = ErrCode.successCode; + result.ResData = nowFunList; + } + else + { + result.ErrCode = "40008"; + result.ErrMsg = ErrCode.err40008; + } + } + catch (Exception ex) + { + Log4NetHelper.Error("根据父级功能编码查询所有子集功能,主要用于页面操作按钮权限,代码生成异常", ex); + result.ErrCode = ErrCode.failCode; + result.ErrMsg = "获取模块功能异常"; + } + + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/LogExController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/LogExController.cs new file mode 100644 index 0000000..c470b27 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/LogExController.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 日志接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class LogExController : AreaApiController + { + private readonly IOrganizeService organizeService; + + /// + /// + /// + /// + /// + public LogExController(ILogExService service, IOrganizeService _organizeService) : base(service) + { + _service = service; + organizeService = _organizeService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(LogEx info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(LogEx info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(LogEx info) + { + info.IsDeleted = true; + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchExceptionsLogsModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _service.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/LogOpController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/LogOpController.cs new file mode 100644 index 0000000..1bf05a8 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/LogOpController.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 操作日志接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class LogOpController : AreaApiController + { + private readonly IOrganizeService organizeService; + + /// + /// + /// + /// + /// + public LogOpController(ILogOpService service, IOrganizeService _organizeService) : base(service) + { + _service = service; + organizeService = _organizeService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(LogOp info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(LogOp info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(LogOp info) + { + info.IsDeleted = true; + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchLogOpModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _service.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/LogVisController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/LogVisController.cs new file mode 100644 index 0000000..18c3ede --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/LogVisController.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 日志接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class LogVisController : AreaApiController + { + private readonly IOrganizeService organizeService; + + /// + /// + /// + /// + /// + public LogVisController(ILogVisService service, IOrganizeService _organizeService) : base(service) + { + _service = service; + organizeService = _organizeService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(LogVis info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(LogVis info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(LogVis info) + { + info.IsDeleted = true; + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchDbLogsModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _service.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/QuartzController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/QuartzController.cs new file mode 100644 index 0000000..c31e145 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/QuartzController.cs @@ -0,0 +1,63 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; +using Znyc.Admin.WebApi.Attributes; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 定时调度 + /// + [Quartz] + [Route("api/Security/[controller]")] + [AllowAnonymous] + public class QuartzController : AreaApiController + { + private readonly IStatisticalService _statisticalService; + + /// + /// 构造函数 + /// + /// + /// + public QuartzController(IApiService service, + IStatisticalService statisticalService) : base(service) + { + _service = service; + _statisticalService = statisticalService; + } + + /// + /// 添加统计数据 + /// + /// + [HttpGet("InsertAsync")] + [AllowAnonymous] + + //[FunctionAuthorize("Add")] + public async Task AddAsync() + { + CommonResult result = new CommonResult(); + result = await _statisticalService.InsertAsync(); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + } +} diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/StatisticalController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/StatisticalController.cs new file mode 100644 index 0000000..63dc1e5 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/StatisticalController.cs @@ -0,0 +1,138 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 数据字典接口 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class StatisticalController : AreaApiController + { + private readonly IStatisticalService _statisticalService; + private readonly IUserService _userService; + private readonly ICompanyService _companyService; + private readonly IVehicleService _vehicleService; + + /// + /// 构造函数 + /// + /// + /// + /// + /// + public StatisticalController(IStatisticalService statisticalService, + ICompanyService companyService, + IVehicleService vehicleService, + IUserService userService + ) : base(statisticalService) + { + _statisticalService = statisticalService; + _userService = userService; + _companyService = companyService; + _vehicleService = vehicleService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(Statistical info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(Statistical info) + { + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 异步新增数据 + /// + /// + [HttpPost("InsertAsync")] + [FunctionAuthorize("Add")] + public async Task InsertAsync() + { + CommonResult result = new CommonResult(); + var statistical = await _statisticalService.GetStatisticalAsync(); + var userAddTotal = await _userService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"); + Statistical info = new Statistical() + { + Id = Yitter.IdGenerator.YitIdHelper.NextId(), + Time = DateTime.Now.ToString("yyyy-MM-dd"), + UserAddTotal = userAddTotal, + UserSumTotal = await _userService.GetCountByWhereAsync(" Status=1"), + CompanyAddTotal = await _companyService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"), + CompanySumTotal = await _companyService.GetCountByWhereAsync("Status = 1"), + VehicleAddTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(CreatedTime) = dayofmonth(now())"), + VehicleSumTotal = await _vehicleService.GetCountByWhereAsync("Status = 1"), + ExpireAddTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(ExpireTime) = dayofmonth(now()) and Status=1"), + ExpireSumTotal = await _vehicleService.GetCountByWhereAsync("dayofmonth(ExpireTime) < dayofmonth(now()) and Status=1"), + ModifiedTime = DateTime.Now, + CreatedTime = DateTime.Now + }; + if (statistical == null) + { + info.UserAddTotalPercent = 0; + } + else + { + info.UserAddTotalPercent = StringHelper.GetPercent(userAddTotal, statistical.UserSumTotal); + } + + OnBeforeInsert(info); + long ln = await _service.InsertAsync(info).ConfigureAwait(false); + if (ln > 0) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43001; + result.ErrCode = "43001"; + } + return ToJsonContent(result); + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchUserModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _statisticalService.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/UserController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/UserController.cs new file mode 100644 index 0000000..9bbacbd --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/UserController.cs @@ -0,0 +1,112 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 用户 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class UserController : AreaApiController + { + private readonly IUserService _userServices; + + /// + /// 构造函数 + /// + public UserController( + IUserService userServices + ) : base(userServices) + { + _userServices = userServices; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(User info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(User info) + { + info.CreatedUserId = CurrentUser.UserId; + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(User info) + { + info.IsDeleted = true; + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + [AllowAnonymous] + public async Task FindWithPagerSearchAsync(SearchUserModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _userServices.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + + /// + /// 修改用户状态 + /// + /// + /// + /// + [HttpPut("UpdateStatusAsync")] + [FunctionAuthorize("")] + public async Task UpdateStatusAsync(long id, int status) + { + CommonResult result = new CommonResult(); + result = await _userServices.UpdateStatusAsync(id, status); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/VehicleChangeController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/VehicleChangeController.cs new file mode 100644 index 0000000..2e1d81f --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/VehicleChangeController.cs @@ -0,0 +1,112 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 车辆换装 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class VehicleChangeController : AreaApiController + { + private readonly IVehicleChangeService _vehicleChangeService; + + /// + /// 构造函数 + /// + public VehicleChangeController( + IVehicleChangeService vehicleChangeService + ) : base(vehicleChangeService) + { + _vehicleChangeService = vehicleChangeService; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(VehicleChange info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(VehicleChange info) + { + info.CreatedUserId = CurrentUser.UserId; + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(VehicleChange info) + { + info.IsDeleted = true; + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchVehicleChangeModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _vehicleChangeService.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + + /// + /// 新增车辆换装记录 + /// + /// + /// + [HttpPost("InsertAsync")] + [FunctionAuthorize("Add")] + public new async Task InsertAsync(VehicleChangeInPutDto input) + { + CommonResult result = new CommonResult(); + VehicleChange vehicleChange = input.MapTo(); + OnBeforeInsert(vehicleChange); + result = await _vehicleChangeService.InsertAsync(vehicleChange); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = result.ErrMsg; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Dispatching/VehicleController.cs b/Znyc.Admin.WebApi/Controllers/Dispatching/VehicleController.cs new file mode 100644 index 0000000..3444a92 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Dispatching/VehicleController.cs @@ -0,0 +1,216 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Znyc.Admin.AspNetCore.Controllers; +using Znyc.Admin.AspNetCore.Entitys; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.Commons.Entitys; +using Znyc.Admin.Commons.Mapping; +using Znyc.Admin.Commons.Pages; +using Znyc.Admin.Security.Dtos; +using Znyc.Admin.Security.Entitys; +using Znyc.Admin.Security.IServices; + +namespace Znyc.Admin.WebApi.Controllers +{ + /// + /// 车辆 + /// + [ApiController] + [Route("api/Security/[controller]")] + public class VehicleController : AreaApiController + { + private readonly IVehicleService _vehicleServices; + + /// + /// 构造函数 + /// + public VehicleController( + IVehicleService vehicleServices + ) : base(vehicleServices) + { + _vehicleServices = vehicleServices; + } + + /// + /// 新增前处理数据 + /// + /// + protected override void OnBeforeInsert(Vehicle info) + { + info.Id = 0; + info.CreatedTime = DateTime.Now; + info.CreatedUserId = CurrentUser.UserId; + info.IsDeleted = false; + } + + /// + /// 在更新数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeUpdate(Vehicle info) + { + info.CreatedUserId = CurrentUser.UserId; + info.ModifiedUserId = CurrentUser.UserId; + info.ModifiedTime = DateTime.Now; + } + + /// + /// 在软删除数据前对数据的修改操作 + /// + /// + /// + protected override void OnBeforeSoftDelete(Vehicle info) + { + info.IsDeleted = true; + } + + /// + /// 异步分页查询 + /// + /// + /// + [HttpPost("FindWithPagerSearchAsync")] + [FunctionAuthorize("List")] + public async Task FindWithPagerSearchAsync(SearchVehicleModel search) + { + CommonResult> result = new CommonResult> + { + ResData = await _vehicleServices.FindWithPagerSearchAsync(search), + ErrCode = ErrCode.successCode + }; + return ToJsonContent(result); + } + + /// + /// 异步新增数据 + /// + /// + /// + [HttpPost("InsertAsync")] + [FunctionAuthorize("Add")] + public new async Task InsertAsync(VehicleInPutDto input) + { + CommonResult result = new CommonResult(); + Vehicle vehicle = input.MapTo(); + OnBeforeInsert(vehicle); + result = await _vehicleServices.InsertAsync(vehicle); + + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = result.ErrMsg; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + + /// + /// 异步更新数据 + /// + /// + /// + [HttpPost("UpdateAsync")] + [FunctionAuthorize("Edit")] + public async Task UpdateAsync(VehicleUpdateInPutDto input) + { + CommonResult result = new CommonResult(); + Vehicle vehicle = input.MapTo(); + OnBeforeUpdate(vehicle); + vehicle.Id = input.Id; + result = await _vehicleServices.UpdateAsync(vehicle); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = result.ErrMsg; + result.ErrCode = "43002"; + } + + return ToJsonContent(result); + } + + /// + /// 修改车辆状态 + /// + /// + /// + /// + [HttpPut("UpdateStatusAsync")] + [FunctionAuthorize("")] + public async Task UpdateStatusAsync(long id, int status) + { + CommonResult result = new CommonResult(); + result = await _vehicleServices.UpdateStatusAsync(id, status); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + + /// + /// 修改车辆是否激活 + /// + /// + /// + /// + [HttpPut("UpdateIsActivateAsync")] + [FunctionAuthorize("")] + public async Task UpdateIsActivateAsync(long id, bool isActivate) + { + CommonResult result = new CommonResult(); + result = await _vehicleServices.UpdateIsActivateAsync(id, isActivate); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + + /// + /// 修改车辆是否开启GPS + /// + /// + /// + /// + [HttpPut("UpdateIsGpsAsync")] + [FunctionAuthorize("")] + public async Task UpdateIsGpsAsync(long id, bool isGps) + { + CommonResult result = new CommonResult(); + result = await _vehicleServices.UpdateIsGpsAsync(id, isGps); + if (result.Success) + { + result.ErrCode = ErrCode.successCode; + result.ErrMsg = ErrCode.err0; + } + else + { + result.ErrMsg = ErrCode.err43002; + result.ErrCode = "43002"; + } + return ToJsonContent(result); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Controllers/Wx/WeixinController.cs b/Znyc.Admin.WebApi/Controllers/Wx/WeixinController.cs new file mode 100644 index 0000000..b0e7798 --- /dev/null +++ b/Znyc.Admin.WebApi/Controllers/Wx/WeixinController.cs @@ -0,0 +1,133 @@ +using Microsoft.AspNetCore.Mvc; +using Senparc.Weixin.MP; +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Security.IServices; +using PostModel = Senparc.Weixin.MP.Entities.Request.PostModel; + + +namespace Znyc.Admin.WebApi.Controllers.Wx +{ + /// + /// 微信接口 + /// + public class WeixinController : ControllerBase + { + public static readonly string Token = "rzC0pRTuBznwd3"; + //Config.SenparcWeixinSetting.MpSetting.Token;//与微信公众账号后台的Token设置保持一致,区分大小写。 + public static readonly string EncodingAESKey = "VtEIJLTcbrkGT18EkevZzKIBYgqpURtxyH6w2iWR5eD"; + //Config.SenparcWeixinSetting.MpSetting.EncodingAESKey;//与微信公众账号后台的EncodingAESKey设置保持一致,区分大小写。 + public static readonly string AppId = "wx07c574aca93ae8d9"; + //Config.SenparcWeixinSetting.MpSetting.WeixinAppId;//与微信公众账号后台的AppId设置保持一致,区分大小写。 + private readonly IUserService _userService; + private readonly IWxUserRelationService _wxUserRelationService; + + + + public WeixinController(IUserService userService, IWxUserRelationService wxUserRelationService) + { + _userService = userService; + _wxUserRelationService = wxUserRelationService; + } + /// + /// 微信后台验证地址 + /// + [HttpGet] + [ActionName("Index")] + public ActionResult Get(PostModel postModel, string echostr) + { + if (CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token)) + { + return Content(echostr); //返回随机字符串则表示验证通过 + } + else + { + return Content("failed:" + postModel.Signature + "," + Senparc.Weixin.MP.CheckSignature.GetSignature(postModel.Timestamp, postModel.Nonce, Token) + "。" + + "如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。"); + } + } + + /// + /// 用户发送消息后,微信平台自动Post一个请求到这里,并等待响应XML。 + /// PS:此方法为简化方法,效果与OldPost一致。 + /// v0.8之后的版本可以结合Senparc.Weixin.MP.MvcExtension扩展包,使用WeixinResult,见MiniPost方法。 + /// + [HttpPost] + [ActionName("Index")] + public async Task Post(string signature, string timestamp, string nonce) + { + Log4NetHelper.Error("info post"); + try + { + StreamReader sr = new StreamReader(Request.Body, Encoding.UTF8); + XmlDocument doc = new XmlDocument(); + doc.Load(sr); + sr.Close(); + sr.Dispose(); + WxMessage wxMessage = new WxMessage(); + wxMessage.ToUserName = doc.SelectSingleNode("xml").SelectSingleNode("ToUserName").InnerText; + wxMessage.FromUserName = doc.SelectSingleNode("xml").SelectSingleNode("FromUserName").InnerText; + wxMessage.MsgType = doc.SelectSingleNode("xml").SelectSingleNode("MsgType").InnerText; + wxMessage.CreateTime = int.Parse(doc.SelectSingleNode("xml").SelectSingleNode("CreateTime").InnerText); + Log4NetHelper.Error("wxMessage.MsgType"+ wxMessage.MsgType); + if (wxMessage.MsgType == "event") + { + wxMessage.EventName = doc.SelectSingleNode("xml").SelectSingleNode("Event").InnerText; + if (!string.IsNullOrEmpty(wxMessage.EventName) && wxMessage.EventName == "subscribe") + { + + + + string content = "您好,欢迎关注云车派工服务号"; + + content = SendTextMessage(wxMessage, content); + await _wxUserRelationService.UpdateAsync(wxMessage.FromUserName); + return Content(content); + } + } + } + catch (Exception ex) + { + //记录日志 + return Content($"{ex.StackTrace} | {ex.Message}"); + } + return Content(""); + } + + + /// + /// Send + /// + /// + /// + /// + private string SendTextMessage(WxMessage wxmessage, string content) + { + string result = string.Format(@" + + + {2} + + + ", wxmessage.FromUserName, wxmessage.ToUserName, DateTime.Now.Ticks, content); + return result; + } + + public class WxMessage + { + public string ToUserName { get; set; } + public string FromUserName { get; set; } + public long CreateTime { get; set; } + + public string Content { get; set; } + public string MsgType { get; set; } + public string EventName { get; set; } + public string EventKey { get; set; } + } + + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Dockerfile b/Znyc.Admin.WebApi/Dockerfile new file mode 100644 index 0000000..3e5d36b --- /dev/null +++ b/Znyc.Admin.WebApi/Dockerfile @@ -0,0 +1,28 @@ +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +ENV TZ=Asia/Shanghai +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj", "Znyc.Admin.WebApi/"] +COPY ["Znyc.Admin.MongoDb/Znyc.Admin.MongoDb.Core.csproj", "Znyc.Admin.MongoDb/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Znyc.Admin.AspNetCore.csproj", "Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Znyc.Admin.Security.Core.csproj", "Znyc.Admin.NetCore/Znyc.Admin.Security.Core/"] +COPY ["Znyc.Admin.WeChat.Core/Znyc.Admin.WeChat.Core.csproj", "Znyc.Admin.WeChat.Core/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.Commons/Znyc.Admin.Commons.csproj", "Znyc.Admin.NetCore/Znyc.Admin.Commons/"] +RUN dotnet restore "Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj" +COPY . . +WORKDIR "/src/Znyc.Admin.WebApi" +RUN dotnet build "Znyc.Admin.WebApi.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Znyc.Admin.WebApi.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Znyc.Admin.WebApi.dll"] diff --git a/Znyc.Admin.WebApi/Program.cs b/Znyc.Admin.WebApi/Program.cs new file mode 100644 index 0000000..5f73325 --- /dev/null +++ b/Znyc.Admin.WebApi/Program.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using System; +using System.IO; +using Znyc.Admin.Commons.Const; +using Znyc.Admin.Commons.Core.App; + +namespace Znyc.Admin.WebApi +{ + /// + /// + /// + public class Program + { + /// + /// 启动程序 + /// + /// + public static void Main(string[] args) + { + Console.WriteLine("start..."); + CreateHostBuilder(args).Build().Run(); + } + + /// + /// + /// + /// + /// + public static IHostBuilder CreateHostBuilder(string[] args) + { + IConfigurationRoot config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable(SysConst.ASPNETCORE_ENVIRONMENT)}.json").Build(); + App.Configuration = config; + return Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup() + .UseUrls("http://*:80"); + }); + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Properties/PublishProfiles/FolderProfile.pubxml b/Znyc.Admin.WebApi/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..841a99c --- /dev/null +++ b/Znyc.Admin.WebApi/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,20 @@ + + + + + False + False + True + Release + Any CPU + FileSystem + bin\Release\net6.0\publish\ + FileSystem + + net6.0 + 64c6211f-c371-471f-a3b6-9f6258621ae4 + false + + \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Startup.cs b/Znyc.Admin.WebApi/Startup.cs new file mode 100644 index 0000000..a0790f5 --- /dev/null +++ b/Znyc.Admin.WebApi/Startup.cs @@ -0,0 +1,539 @@ +using AutoMapper; +using Hangfire; +using Hangfire.Dashboard.BasicAuthorization; +using Hangfire.Redis; +using log4net; +using log4net.Repository; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.AspNetCore.Mvc.Versioning; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Pursue.Extension.MongoDB; +using Senparc.CO2NET; +using Senparc.CO2NET.RegisterServices; +using Senparc.Weixin.RegisterServices; +using Swashbuckle.AspNetCore.Filters; +using System; +using System.IO; +using System.Linq; +using System.Runtime.Loader; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Unicode; +using Znyc.Admin.AspNetCore.Common; +using Znyc.Admin.AspNetCore.Mvc; +using Znyc.Admin.AspNetCore.Mvc.Filter; +using Znyc.Admin.Commons.Cache; +using Znyc.Admin.Commons.Core.App; +using Znyc.Admin.Commons.DbContextCore; +using Znyc.Admin.Commons.Extensions; +using Znyc.Admin.Commons.Helpers; +using Znyc.Admin.Commons.IDbContext; +using Znyc.Admin.Commons.Linq; +using Znyc.Admin.Commons.Log; +using Znyc.Admin.Commons.Module; +using Znyc.Admin.Commons.Options; +using Znyc.Admin.Hangfire; +using Znyc.Admin.MongoDb; +using Znyc.Admin.MongoDb.Core.IRepositorys; +using Znyc.Admin.MongoDb.Core.Repositorys; +using Znyc.Admin.WebApi.Auth; + +namespace Znyc.Admin.WebApi +{ + /// + /// + /// + public class Startup + { + /// + /// + /// + public static ILoggerRepository LoggerRepository { get; set; } + + private string targetPath = string.Empty; + private IMvcBuilder mvcBuilder; + + /// + /// + /// + public IConfiguration Configuration { get; } + + private IApiVersionDescriptionProvider apiVersionProvider; //api接口版本控制 + + /// + /// + /// + /// + public Startup(IConfiguration configuration) + { + Configuration = configuration; + //初始化log4net + LoggerRepository = LogManager.CreateRepository("NETCoreRepository"); + Log4NetHelper.SetConfig(LoggerRepository, "log4net.config"); + } + + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// + /// + /// + public void ConfigureServices(IServiceCollection services) + { + services.TryAddSingleton(); + services.AddHttpContextAccessor(); + //如果部署在linux系统上,需要加上下面的配置: + services.Configure(options => options.AllowSynchronousIO = true); + services.AddOptions(); + services.Configure(options => options.AllowSynchronousIO = true); + + #region Swagger Api文档 + + // Api多版本版本配置 + services.AddApiVersioning(o => + { + o.ReportApiVersions = true; //是否在请求头中返回受支持的版本信息。 + o.ApiVersionReader = + new HeaderApiVersionReader("api-version"); ////版本信息放到header ,不写在不配置路由的情况下,版本信息放到response url 中 + o.AssumeDefaultVersionWhenUnspecified = true; //请求没有指明版本的情况下是否使用默认的版本。 + o.DefaultApiVersion = new ApiVersion(1, 0); //默认的版本号。 + }).AddVersionedApiExplorer(option => + { + // 版本名的格式:v+版本号 + option.GroupNameFormat = "'v'V"; + option.AssumeDefaultVersionWhenUnspecified = true; + }); + //获取webapi版本信息,用于swagger多版本支持 + apiVersionProvider = services.BuildServiceProvider().GetRequiredService(); + services.AddSwaggerGen(options => + { + foreach (ApiVersionDescription description in apiVersionProvider.ApiVersionDescriptions) + { + options.SwaggerDoc(description.GroupName, + new OpenApiInfo() + { + Title = $"{Configuration.GetSection("SwaggerDoc:Title").Value}v{description.ApiVersion}", + Version = description.ApiVersion.ToString(), + Description = Configuration.GetSection("SwaggerDoc:Description").Value, + } + ); + } + + Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.xml").ToList().ForEach(file => + { + options.IncludeXmlComments(file, true); + }); + options.DocumentFilter(); // 在接口类、方法标记属性 [HiddenApi],可以阻止【Swagger文档】生成 + //给api添加token令牌证书 + options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"", + Name = "Authorization", //jwt默认的参数名称 + In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) + Type = SecuritySchemeType.ApiKey, + BearerFormat = "JWT", + Scheme = "Bearer" + }); + //添加安全请求 + options.AddSecurityRequirement( + new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + new string[] { } + } + } + ); + //开启加权锁 + options.OperationFilter(); + options.OperationFilter(); + options.OperationFilter(); + }); + + #endregion Swagger Api文档 + + #region 全局设置跨域访问 + + //允许所有跨域访问,测试用 + services.AddCors(options => options.AddPolicy("Cors", + policy => policy.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); + // 跨域设置 建议正式环境 + //services.AddCors(options => options.AddPolicy("ZnycCors", + // policy => policy.WithOrigins(Configuration.GetSection("AppSetting:AllowOrigins").Value.Split(',', StringSplitOptions.RemoveEmptyEntries)).AllowAnyHeader().AllowAnyMethod())); + + #endregion 全局设置跨域访问 + + #region MiniProfiler + + services.AddMiniProfiler(options => { options.RouteBasePath = "/profiler"; }).AddEntityFramework(); + + #endregion MiniProfiler + + #region 控制器 + + services.AddControllers().AddJsonOptions(options => + { + options.JsonSerializerOptions.WriteIndented = true; + options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + //设置时间格式 + options.JsonSerializerOptions.Converters.Add(new DateTimeJsonConverter()); + options.JsonSerializerOptions.Converters.Add(new DateTimeNullableConverter()); + //设置bool获取格式 + options.JsonSerializerOptions.Converters.Add(new BooleanJsonConverter()); + //设置Decimal获取格式 + options.JsonSerializerOptions.Converters.Add(new DecimalJsonConverter()); + //设置数字 + options.JsonSerializerOptions.Converters.Add(new IntJsonConverter()); + options.JsonSerializerOptions.PropertyNamingPolicy = new UpperFirstCaseNamingPolicy(); + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + + mvcBuilder = services.AddMvc(option => + { + //option.Filters.Add(); + option.Filters.Add(new ExceptionHandlingAttribute()); + // option.Filters.Add(); + }).SetCompatibilityVersion(CompatibilityVersion.Latest).AddRazorRuntimeCompilation(); + + services.AddMvcCore() + .AddAuthorization().AddApiExplorer(); + + #endregion 控制器 + + services.AddSignalR(); //使用 SignalR + InitIoC(services); + services.AddCors(options => options.AddPolicy("ZnycCors", + policy => policy.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); + + services.AddSenparcWeixinServices(Configuration); + services.TryAddSingleton(); + + #region Hangfire + services.AddHangfire(x => x.UseRedisStorage(Configuration.GetSection("CacheProvider:Redis_ConnectionString").Value)); + services.AddHangfireServer(options => + { + options.Queues = new[] { HangFireQueuesConfig.@default.ToString(), HangFireQueuesConfig.apis.ToString(), HangFireQueuesConfig.web.ToString(), HangFireQueuesConfig.recurring.ToString() }; + options.ServerTimeout = TimeSpan.FromMinutes(4); + options.SchedulePollingInterval = TimeSpan.FromSeconds(15);//秒级任务需要配置短点,一般任务可以配置默认时间,默认15秒 + options.ShutdownTimeout = TimeSpan.FromMinutes(30); //超时时间 + options.WorkerCount = Math.Max(Environment.ProcessorCount, 20); //工作线程数,当前允许的最大线程,默认20 + }); + #endregion + } + + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// + /// + /// + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IOptions senparcSetting) + { + if (app != null) + { + app.UseStaticHttpContextAccessor(); + IServiceProvider provider = app.ApplicationServices; + AutoMapperService.UsePack(provider); + //加载插件应用 + LoadMoudleApps(env); + + app.UseMiniProfiler(); + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/Home/Error"); + app.UseHsts(); + } + + app.UseSwagger(); + app.UseSwaggerUI(options => + { + foreach (ApiVersionDescription description in apiVersionProvider.ApiVersionDescriptions) + { + options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", + $"{Configuration.GetSection("SwaggerDoc:Title").Value + description.GroupName.ToUpperInvariant()}"); + options.RoutePrefix = string.Empty; //这里主要是不需要再输入swagger这个默认前缀 + } + }); + app.Use((context, next) => + { + context.Request.EnableBuffering(); + return next(); + }); + app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + //跨域 + app.UseMiddleware(); + app.UseCors("Cors"); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + endpoints.MapControllerRoute("default", "api/{controller=Home}/{action=Index}/{id?}"); + }); + app.UseStatusCodePages(); + + #region WxSdk 注册 + + IRegisterService register = RegisterService.Start(senparcSetting.Value) + .UseSenparcGlobal(); + register.UseSenparcGlobal(true); + + #endregion WxSdk 注册 + + //#region Hangfire + //var filter = new BasicAuthAuthorizationFilter( + //new BasicAuthAuthorizationFilterOptions + //{ + // SslRedirect = false, + // // Require secure connection for dashboard + // RequireSsl = false, + // // Case sensitive login checking + // LoginCaseSensitive = false, + // // Users + // Users = new[] + // { + // new BasicAuthAuthorizationUser + // { + // Login = Configuration.GetSection("Hangfire:Login").Value, + // PasswordClear = Configuration.GetSection("Hangfire:Password").Value + // } + // } + //}); + + //var options = new DashboardOptions + //{ + // AppPath = "/",//返回时跳转的地址 + // DisplayStorageConnectionString = false,//是否显示数据库连接信息 + // Authorization = new[] + // { + // filter + //}, + // IsReadOnlyFunc = Context => + // { + // return false;//是否只读面板 + // } + //}; + + //app.UseHangfireDashboard("/dc_admin_job", options); + //HangfireDispose.HangfireService(); + //#endregion + } + } + + /// + /// IoC初始化 + /// + /// + /// + private void InitIoC(IServiceCollection services) + { + #region 缓存 + + CacheProvider cacheProvider = new CacheProvider + { + IsUseRedis = Configuration.GetSection("CacheProvider:UseRedis").Value.ToBool(false), + ConnectionString = Configuration.GetSection("CacheProvider:Redis_ConnectionString").Value, + InstanceName = Configuration.GetSection("CacheProvider:Redis_InstanceName").Value + }; + + JsonSerializerOptions options = new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + AllowTrailingCommas = true + }; + //设置时间格式 + options.Converters.Add(new DateTimeJsonConverter()); + options.Converters.Add(new DateTimeNullableConverter()); + //设置bool获取格式 + options.Converters.Add(new BooleanJsonConverter()); + //设置数字 + options.Converters.Add(new IntJsonConverter()); + options.PropertyNamingPolicy = new UpperFirstCaseNamingPolicy(); + options.PropertyNameCaseInsensitive = true; //忽略大小写 + //判断是否使用Redis,如果不使用 Redis就默认使用 MemoryCache + if (cacheProvider.IsUseRedis) + { + //Use Redis + services.AddStackExchangeRedisCache(options => + { + options.Configuration = cacheProvider.ConnectionString; + options.InstanceName = cacheProvider.InstanceName; + }); + services.AddSingleton(typeof(ICacheService), new RedisCacheService(new RedisCacheOptions + { + Configuration = cacheProvider.ConnectionString, + InstanceName = cacheProvider.InstanceName + }, options, 6)); + services.Configure(option => + option.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)); //设置Redis缓存有效时间为5分钟。 + } + else + { + //Use MemoryCache + services.AddSingleton(factory => + { + MemoryCache cache = new MemoryCache(new MemoryCacheOptions()); + return cache; + }); + services.AddSingleton(); + services.Configure( + options => options.AbsoluteExpirationRelativeToNow = + TimeSpan.FromMinutes(5)); //设置MemoryCache缓存有效时间为5分钟 + } + + services.AddTransient(); + services.AddMemoryCache(); // 启用MemoryCache + + services.AddSingleton(cacheProvider); //注册缓存配置 + + #endregion 缓存 + + #region 身份认证授权 + + IConfigurationSection jwtConfig = Configuration.GetSection("Jwt"); + JwtOption jwtOption = new JwtOption + { + Issuer = jwtConfig["Issuer"], + Expiration = Convert.ToInt16(jwtConfig["Expiration"]), + Secret = jwtConfig["Secret"], + Audience = jwtConfig["Audience"], + refreshJwtTime = Convert.ToInt16(jwtConfig["refreshJwtTime"]) + }; + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + ; + }).AddJwtBearer(jwtBearerOptions => + { + jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = + new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(jwtOption.Secret)), //秘钥 + ValidateIssuer = true, + ValidIssuer = jwtOption.Issuer, + ValidateAudience = true, + ValidAudience = jwtOption.Audience, + ValidateLifetime = true, + ClockSkew = TimeSpan.FromMinutes(5) + }; + }); + services.AddSingleton(jwtOption); //注册配置 + + #endregion 身份认证授权 + + services.AddAutoScanInjection(); //自动化注入仓储和服务 + services.AddTransient(); //注入EF上下文 + + #region automapper + + System.Collections.Generic.List myAssembly = RuntimeHelper.GetAllZnycAssemblies().ToList(); + services.AddAutoMapper(myAssembly); + services.AddTransient(); + + #endregion automapper + + services + .AddMongoDBContext(options => + { + options.UseMongo(Configuration.GetSection("MongoConnection:ConnectionString").Value, Configuration.GetSection("MongoConnection:Database").Value); + }); + + services + .AddMongoDbService(); + + + services.AddTransient(); + App.Services = services; + } + + /// + /// 加载模块应用 + /// + /// + private void LoadMoudleApps(IWebHostEnvironment env) + { + // 定位到插件应用目录 Apps + Microsoft.Extensions.FileProviders.IFileInfo apps = env.ContentRootFileProvider.GetFileInfo("Apps"); + if (!Directory.Exists(apps.PhysicalPath)) + { + return; + } + + // 把 Apps 下的动态库拷贝一份来运行, + // 使 Apps 中的动态库不会在运行时被占用(以便重新编译) + string shadows = targetPath = PrepareShadowCopies(); + // 从 Shadow Copy 目录加载 Assembly 并注册到 Mvc 中 + LoadFromShadowCopies(shadows); + + string PrepareShadowCopies() + { + // 准备 Shadow Copy 的目标目录 + string target = Path.Combine(env.ContentRootPath, "app_data", "apps-cache"); + Directory.CreateDirectory(target); + + // 找到插件目录下 bin 目录中的 .dll,拷贝 + Directory.EnumerateDirectories(apps.PhysicalPath) + .Select(path => Path.Combine(path, "bin")) + .Where(Directory.Exists) + .SelectMany(bin => Directory.EnumerateFiles(bin, "*.dll")) + .ForEach(dll => File.Copy(dll, Path.Combine(target, Path.GetFileName(dll)), true)); + + return target; + } + + void LoadFromShadowCopies(string targetPath) + { + foreach (string dll in Directory.GetFiles(targetPath, "*.dll")) + { + try + { + //解决插件还引用其他主程序没有引用的第三方dll问题System.IO.FileNotFoundException + AssemblyLoadContext.Default.LoadFromAssemblyPath(dll); + } + catch (Exception ex) + { + //非.net程序集类型的dll关联load时会报错,这里忽略就可以 + Log4NetHelper.Error(ex.Message); + } + } + + // 从 Shadow Copy 目录加载 Assembly 并注册到 Mvc 中 + System.Collections.Generic.IEnumerable groups = Directory.EnumerateFiles(targetPath, "Znyc.Admin.*App.Api.dll") + .Select(AssemblyLoadContext.Default.LoadFromAssemblyPath); + + // 直接加载到为 ApplicationPart + groups.ForEach(mvcBuilder.AddApplicationPart); + } + } + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj b/Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj new file mode 100644 index 0000000..be078d0 --- /dev/null +++ b/Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj @@ -0,0 +1,61 @@ + + + + net6.0 + 4d454771-6ff7-43f2-a2b6-7c3bada83304 + Linux + + + + bin\Release\Znyc.WebApi.xml + bin\Release\ + + + + bin\Debug\Znyc.WebApi.xml + bin\Debug\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + + + + \ No newline at end of file diff --git a/Znyc.Admin.WebApi/appsettings.Development.json b/Znyc.Admin.WebApi/appsettings.Development.json new file mode 100644 index 0000000..2d5bca0 --- /dev/null +++ b/Znyc.Admin.WebApi/appsettings.Development.json @@ -0,0 +1,90 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + }, + "AllowedHosts": "*", + "Jwt": { + "Secret": "Y2F0Y2yhciUyMHdvbmclMFWfsaZlJTIwLm5ldA==", //密钥,目前暂时没有用 + "Issuer": "ZnycTeach", //颁发者 + "Audience": "api", + "Expiration": 120, //过期时长,分钟, + "refreshJwtTime": 240 //有效刷新时间,分钟 + }, + "DbConnections": { + "DefaultDb": { + "MasterDB": { + //测试环境调试配置,非必要请在本地进行开发调试 + //"ConnectionString": "Server=106.52.55.123; Port=3306; Database=znyc_dispatching; Uid=guest; Pwd=4Y2e2WtekfDYWfT8; Charset=utf8mb4", + "ConnectionString": "Server=42.194.147.251;Port=43306;Database=znyc_dispatching;Uid=guest;Pwd=4Y2e2WtekfDYWfT8;Charset=utf8mb4", + "DatabaseType": "MySql" //MySql数据库类型 + } + } + }, + "AppSetting": { + "SoftName": "Znyc Framework", + "CertificatedCompany": "Znyc", + "ConStringEncrypt": "false", + "DefaultDataBase": "DefaultDb", + "IsDBReadWriteSeparate": false, //开启数据库读写分离 + "QueryDBStrategy": "Random", //定义多个从数据库的访问策略 + "LoginProvider": "Cookie", + "AppId": "system", + "AppSecret": "87135AB0160F706D8B47F06BDABA6FC6", + "AllowOrigins": "http://localhost,http://localhost:8080,http://localhost:9529,http://localhost:44304;http://localhost:9528", + "SessionTimeOut": "30", //session过期时长,分钟 + "IsMultiTenant": false //开启多租户模式 + }, + "CacheProvider": { + "UseRedis": true, + // Redis数据库 + //测试环境调试配置,非必要请在本地进行开发调试 + //"Redis_ConnectionString": "106.52.55.123:6379,password=vtgA9HXFQQYA9g8Z" + "Redis_ConnectionString": "42.194.147.251:6379,password=vtgA9HXFQQYA9g8Z,defaultDatabase=6", + //"Redis_InstanceName": "", + "Cache_Memcached_Configuration": "" + }, + "SwaggerDoc": { + "ContactName": "Znyc", + "Description": "api接口采用token+签名验证,在使用swagger测试接口时须先获取Token;", + "Title": "Znyc Admin API 文档" + }, + "SenparcSetting": { + "IsDebug": true, + "DefaultCacheNamespace": "DefaultCache", + "SenparcUnionAgentKey": "#{SenparcUnionAgentKey}#" + }, + //微信小程序 + "SenparcWeixinSetting": { + "IsDebug": true, + "WxOpenAppId": "wxa883c42a8db02847", + "WxOpenAppSecret": "4b9bd0910aab6c7b5266b07d5c17dba6", + "WxOpenToken": "#{WxOpenToken}#", + "WxOpenEncodingAESKey": "#{WxOpenEncodingAESKey}#" + }, + //微信公众号 + "WxOpen": { + "WxOpenAppId": "wx71f2b227f8eaf00a", + "WxOpenAppSecret": "bf868056d4e58f4b2831ff74308120ac", + "WxOpenToken": "rzC0pRTuBznwd3", + "WxOpenEncodingAESKey": "Z9ifQKA8kvQjybOXuXl8I0r9cFHWJGwW2q5iE5e37AM" + }, + "MongoConnection": { + "ConnectionString": "mongodb://42.194.147.251:27018", + "Database": "ZNYCGPS", + "IsSSL": true + }, + "Hangfire": { + "Login": "znyc", + "Password": "znyc2021" + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/appsettings.Production.json b/Znyc.Admin.WebApi/appsettings.Production.json new file mode 100644 index 0000000..a329499 --- /dev/null +++ b/Znyc.Admin.WebApi/appsettings.Production.json @@ -0,0 +1,87 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + }, + "AllowedHosts": "*", + "Jwt": { + "Secret": "Y2F0Y2yhciUyMHdvbmclMFWfsaZlJTIwLm5ldA==", //密钥,目前暂时没有用 + "Issuer": "ZnycTeach", //颁发者 + "Audience": "api", + "Expiration": 120, //过期时长,分钟, + "refreshJwtTime": 240 //有效刷新时间,分钟 + }, + "DbConnections": { + "DefaultDb": { + "MasterDB": { + // mysql生产数据库 + "ConnectionString": "server=172.16.0.6;database=znyc_dispatching;user=znyc;CharSet=utf8mb4;password=UhcAoRR5A3hnt^%U;port=3306;Allow User Variables=True;sslMode=None;", //主库 + "DatabaseType": "MySql" //MySql数据库类型 + } + } + }, + "AppSetting": { + "SoftName": "Znyc Framework", + "CertificatedCompany": "Znyc", + "ConStringEncrypt": "false", + "DefaultDataBase": "DefaultDb", + "IsDBReadWriteSeparate": false, //开启数据库读写分离 + "QueryDBStrategy": "Random", //定义多个从数据库的访问策略 + "LoginProvider": "Cookie", + "AppId": "system", + "AppSecret": "87135AB0160F706D8B47F06BDABA6FC6", + "AllowOrigins": "http://localhost,http://localhost:8080,http://localhost:9529,http://localhost:44304;http://localhost:9528", + "SessionTimeOut": "30", //session过期时长,分钟 + "IsMultiTenant": false //开启多租户模式 + }, + "CacheProvider": { + "UseRedis": true, + // Redis生产数据库 + "Redis_ConnectionString": "172.16.0.17:6379,defaultdatabase=6", + //"Redis_InstanceName": "", + "Cache_Memcached_Configuration": "" + }, + "SwaggerDoc": { + "ContactName": "Znyc", + "Description": "api接口采用token+签名验证,在使用swagger测试接口时须先获取Token;", + "Title": "Znyc Admin API 文档" + }, + "SenparcSetting": { + "IsDebug": true, + "DefaultCacheNamespace": "DefaultCache", + "SenparcUnionAgentKey": "#{SenparcUnionAgentKey}#" + }, + //微信小程序 + "SenparcWeixinSetting": { + "IsDebug": true, + "WxOpenAppId": "wxa883c42a8db02847", + "WxOpenAppSecret": "4b9bd0910aab6c7b5266b07d5c17dba6", + "WxOpenToken": "#{WxOpenToken}#", + "WxOpenEncodingAESKey": "#{WxOpenEncodingAESKey}#" + }, + //微信公众号 + "WxOpen": { + "WxOpenAppId": "wx71f2b227f8eaf00a", + "WxOpenAppSecret": "bf868056d4e58f4b2831ff74308120ac", + "WxOpenToken": "rzC0pRTuBznwd3", + "WxOpenEncodingAESKey": "Z9ifQKA8kvQjybOXuXl8I0r9cFHWJGwW2q5iE5e37AM" + }, + "MongoConnection": { + "ConnectionString": "mongodb://172.16.0.16:27017", + "Database": "ZNYCGPS", + "IsSSL": true + }, + "Hangfire": { + "Login": "znyc", + "Password": "znyc2021" + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/appsettings.Staging.json b/Znyc.Admin.WebApi/appsettings.Staging.json new file mode 100644 index 0000000..fea4afd --- /dev/null +++ b/Znyc.Admin.WebApi/appsettings.Staging.json @@ -0,0 +1,87 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + }, + "AllowedHosts": "*", + "Jwt": { + "Secret": "Y2F0Y2yhciUyMHdvbmclMFWfsaZlJTIwLm5ldA==", //密钥,目前暂时没有用 + "Issuer": "ZnycTeach", //颁发者 + "Audience": "api", + "Expiration": 120, //过期时长,分钟, + "refreshJwtTime": 240 //有效刷新时间,分钟 + }, + "DbConnections": { + "DefaultDb": { + "MasterDB": { + // mysql数据库 + "ConnectionString": "Server=10.0.8.5;Port=43306;Database=znyc_dispatching;Uid=guest;Pwd=4Y2e2WtekfDYWfT8;Charset=utf8mb4;Allow User Variables=True;sslMode=None;", //主库 + "DatabaseType": "MySql" //MySql数据库类型 + } + } + }, + "AppSetting": { + "SoftName": "Znyc Framework", + "CertificatedCompany": "Znyc", + "ConStringEncrypt": "false", + "DefaultDataBase": "DefaultDb", + "IsDBReadWriteSeparate": false, //开启数据库读写分离 + "QueryDBStrategy": "Random", //定义多个从数据库的访问策略 + "LoginProvider": "Cookie", + "AppId": "system", + "AppSecret": "87135AB0160F706D8B47F06BDABA6FC6", + "AllowOrigins": "http://localhost,http://localhost:8080,http://localhost:9529,http://localhost:44304;http://localhost:9528", + "SessionTimeOut": "30", //session过期时长,分钟 + "IsMultiTenant": false //开启多租户模式 + }, + "CacheProvider": { + "UseRedis": true, + // Redis数据库 + "Redis_ConnectionString": "10.0.8.5:6379,password=vtgA9HXFQQYA9g8Z,defaultdatabase=0", + //"Redis_InstanceName": "", + "Cache_Memcached_Configuration": "" + }, + "SwaggerDoc": { + "ContactName": "Znyc", + "Description": "api接口采用token+签名验证,在使用swagger测试接口时须先获取Token;", + "Title": "Znyc Admin API 文档" + }, + "SenparcSetting": { + "IsDebug": true, + "DefaultCacheNamespace": "DefaultCache", + "SenparcUnionAgentKey": "#{SenparcUnionAgentKey}#" + }, + //微信小程序 + "SenparcWeixinSetting": { + "IsDebug": true, + "WxOpenAppId": "wxa883c42a8db02847", + "WxOpenAppSecret": "4b9bd0910aab6c7b5266b07d5c17dba6", + "WxOpenToken": "#{WxOpenToken}#", + "WxOpenEncodingAESKey": "#{WxOpenEncodingAESKey}#" + }, + //微信公众号 + "WxOpen": { + "WxOpenAppId": "wx71f2b227f8eaf00a", + "WxOpenAppSecret": "bf868056d4e58f4b2831ff74308120ac", + "WxOpenToken": "rzC0pRTuBznwd3", + "WxOpenEncodingAESKey": "Z9ifQKA8kvQjybOXuXl8I0r9cFHWJGwW2q5iE5e37AM" + }, + "MongoConnection": { + "ConnectionString": "mongodb://42.194.147.251:27018", + "Database": "ZNYCGPS", + "IsSSL": true + }, + "Hangfire": { + "Login": "znyc", + "Password": "znyc2021" + } +} \ No newline at end of file diff --git a/Znyc.Admin.WebApi/index.html b/Znyc.Admin.WebApi/index.html new file mode 100644 index 0000000..e07bb6e --- /dev/null +++ b/Znyc.Admin.WebApi/index.html @@ -0,0 +1,89 @@ + + + + + + + + %(DocumentTitle) + + + + + %(HeadContent) + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/Znyc.Admin.WebApi/log4net.config b/Znyc.Admin.WebApi/log4net.config new file mode 100644 index 0000000..30fea42 --- /dev/null +++ b/Znyc.Admin.WebApi/log4net.config @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Znyc.Admin.WebApi/logo.png b/Znyc.Admin.WebApi/logo.png new file mode 100644 index 0000000..210599c Binary files /dev/null and b/Znyc.Admin.WebApi/logo.png differ diff --git a/Znyc.Admin.WebApi/wwwroot/favicon.ico b/Znyc.Admin.WebApi/wwwroot/favicon.ico new file mode 100644 index 0000000..d97e6b5 Binary files /dev/null and b/Znyc.Admin.WebApi/wwwroot/favicon.ico differ diff --git a/Znyc.Admin.WebApi/xmlconfig/sys.config b/Znyc.Admin.WebApi/xmlconfig/sys.config new file mode 100644 index 0000000..5fd509f --- /dev/null +++ b/Znyc.Admin.WebApi/xmlconfig/sys.config @@ -0,0 +1,23 @@ + + + 云车派工后台管理平台 + + vue.znyunche.com + https://Znyc-public-1304677865.cos.ap-guangzhou.myqcloud.com/znyclog.png + 云车派工后台管理平台 +
+ + + + + 0 + + + localhost + E:\Znyc\项目\人才招聘\Code\recruitmentadmin.api\Znyc.Admin.WebApi\wwwroot + upload + 1 + gif,jpg,jpeg,png,bmp,rar,zip,doc,xls,txt,cer + 100 + 100 + \ No newline at end of file diff --git a/ZnycAdminNetCore.sln b/ZnycAdminNetCore.sln new file mode 100644 index 0000000..b8b9531 --- /dev/null +++ b/ZnycAdminNetCore.sln @@ -0,0 +1,66 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Znyc.Admin.Commons", "Znyc.Admin.NetCore\Znyc.Admin.Commons\Znyc.Admin.Commons.csproj", "{75C4B78A-34AD-44F7-AABE-87D757BC85CD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Znyc.Admin.Security.Core", "Znyc.Admin.NetCore\Znyc.Admin.Security.Core\Znyc.Admin.Security.Core.csproj", "{AB4694C8-A952-4D6C-BC91-D882F00EAC25}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Znyc.Admin.AspNetCore", "Znyc.Admin.NetCore\Znyc.Admin.AspNetCore\Znyc.Admin.AspNetCore.csproj", "{18932470-2130-43FE-83FD-C4F2B3A564FD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Znyc.Admin.WeChat.Core", "Znyc.Admin.WeChat.Core\Znyc.Admin.WeChat.Core.csproj", "{CCF54E71-A953-4874-87C5-75478242C00D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Znyc.Admin.WebApi", "Znyc.Admin.WebApi\Znyc.Admin.WebApi.csproj", "{64C6211F-C371-471F-A3B6-9F6258621AE4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{C9C1E969-626D-44F1-9363-2ABE2626DA3A}" + ProjectSection(SolutionItems) = preProject + docker\Dockerfile = docker\Dockerfile + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Znyc.Admin.MongoDb.Core", "Znyc.Admin.MongoDb\Znyc.Admin.MongoDb.Core.csproj", "{40F0F101-CA80-4A5D-8E98-1047585C3A43}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Znyc.Admin.Hangfire", "Znyc.Admin.Hangfire\Znyc.Admin.Hangfire.csproj", "{3E96FA7A-68A1-4533-9267-452F7C7F7ADA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {75C4B78A-34AD-44F7-AABE-87D757BC85CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75C4B78A-34AD-44F7-AABE-87D757BC85CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75C4B78A-34AD-44F7-AABE-87D757BC85CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75C4B78A-34AD-44F7-AABE-87D757BC85CD}.Release|Any CPU.Build.0 = Release|Any CPU + {AB4694C8-A952-4D6C-BC91-D882F00EAC25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB4694C8-A952-4D6C-BC91-D882F00EAC25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB4694C8-A952-4D6C-BC91-D882F00EAC25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB4694C8-A952-4D6C-BC91-D882F00EAC25}.Release|Any CPU.Build.0 = Release|Any CPU + {18932470-2130-43FE-83FD-C4F2B3A564FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {18932470-2130-43FE-83FD-C4F2B3A564FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {18932470-2130-43FE-83FD-C4F2B3A564FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {18932470-2130-43FE-83FD-C4F2B3A564FD}.Release|Any CPU.Build.0 = Release|Any CPU + {CCF54E71-A953-4874-87C5-75478242C00D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCF54E71-A953-4874-87C5-75478242C00D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCF54E71-A953-4874-87C5-75478242C00D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCF54E71-A953-4874-87C5-75478242C00D}.Release|Any CPU.Build.0 = Release|Any CPU + {64C6211F-C371-471F-A3B6-9F6258621AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64C6211F-C371-471F-A3B6-9F6258621AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64C6211F-C371-471F-A3B6-9F6258621AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64C6211F-C371-471F-A3B6-9F6258621AE4}.Release|Any CPU.Build.0 = Release|Any CPU + {40F0F101-CA80-4A5D-8E98-1047585C3A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40F0F101-CA80-4A5D-8E98-1047585C3A43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40F0F101-CA80-4A5D-8E98-1047585C3A43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40F0F101-CA80-4A5D-8E98-1047585C3A43}.Release|Any CPU.Build.0 = Release|Any CPU + {3E96FA7A-68A1-4533-9267-452F7C7F7ADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E96FA7A-68A1-4533-9267-452F7C7F7ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E96FA7A-68A1-4533-9267-452F7C7F7ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E96FA7A-68A1-4533-9267-452F7C7F7ADA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {34EF7E78-935D-4750-8AAF-26B4C5ED9807} + EndGlobalSection +EndGlobal diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..3e5d36b --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,28 @@ +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +ENV TZ=Asia/Shanghai +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj", "Znyc.Admin.WebApi/"] +COPY ["Znyc.Admin.MongoDb/Znyc.Admin.MongoDb.Core.csproj", "Znyc.Admin.MongoDb/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/Znyc.Admin.AspNetCore.csproj", "Znyc.Admin.NetCore/Znyc.Admin.AspNetCore/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.Security.Core/Znyc.Admin.Security.Core.csproj", "Znyc.Admin.NetCore/Znyc.Admin.Security.Core/"] +COPY ["Znyc.Admin.WeChat.Core/Znyc.Admin.WeChat.Core.csproj", "Znyc.Admin.WeChat.Core/"] +COPY ["Znyc.Admin.NetCore/Znyc.Admin.Commons/Znyc.Admin.Commons.csproj", "Znyc.Admin.NetCore/Znyc.Admin.Commons/"] +RUN dotnet restore "Znyc.Admin.WebApi/Znyc.Admin.WebApi.csproj" +COPY . . +WORKDIR "/src/Znyc.Admin.WebApi" +RUN dotnet build "Znyc.Admin.WebApi.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Znyc.Admin.WebApi.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Znyc.Admin.WebApi.dll"] diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..242384b Binary files /dev/null and b/logo.png differ