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