mirror of
https://gitee.com/ccnetcore/Yi
synced 2026-04-24 18:36:39 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de0c040cb3 | ||
|
|
23276bb0fd | ||
|
|
46c53e09a3 | ||
|
|
209eb019d3 | ||
|
|
10a608c0af |
133
.gitignore
vendored
133
.gitignore
vendored
@@ -1,7 +1,14 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
dist/
|
||||
|
||||
appsettings.Production.json
|
||||
appsettings.Development.json
|
||||
wwwroot
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
@@ -17,16 +24,21 @@
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
@@ -40,18 +52,28 @@ TestResult.xml
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
@@ -61,6 +83,7 @@ artifacts/
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
@@ -89,6 +112,9 @@ ipch/
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
@@ -109,6 +135,14 @@ _TeamCity*
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
@@ -140,7 +174,7 @@ publish/
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# Note: 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
|
||||
@@ -153,12 +187,12 @@ PublishScripts/
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
!**/[Pp]ackages/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
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
@@ -175,12 +209,13 @@ AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
@@ -188,11 +223,15 @@ ClientBin/
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
@@ -207,15 +246,20 @@ _UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- Backup*.rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
@@ -225,6 +269,7 @@ FakesAssemblies/
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
@@ -232,6 +277,9 @@ FakesAssemblies/
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
@@ -251,25 +299,48 @@ paket-files/
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# BookStore
|
||||
src/Acme.BookStore.Web/Logs/*
|
||||
src/Acme.BookStore.Web.Host/Logs/*
|
||||
src/Acme.BookStore.AuthServer/Logs/*
|
||||
src/Acme.BookStore.HttpApi.Host/Logs/*
|
||||
src/Acme.BookStore.HttpApi.HostWithIds/Logs/*
|
||||
src/Acme.BookStore.DbMigrator/Logs/*
|
||||
src/Acme.BookStore.Blazor.Server/Logs/*
|
||||
src/Acme.BookStore.Blazor.Server.Tiered/Logs/*
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Use abp install-libs to restore.
|
||||
**/wwwroot/libs/*
|
||||
dist
|
||||
.vscode
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.Development.json
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.Production.json
|
||||
Logs
|
||||
logs
|
||||
/Yi.Abp.Net8/test/Yi.Abp.Test/appsettings.Development.json
|
||||
/Yi.Abp.Net8/test/Yi.Abp.Test/appsettings.Production.json
|
||||
database_backup
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.Staging.json
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
appsettings.Development.json
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 橙子
|
||||
Copyright (c) 2022 jacktang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
287
README.md
287
README.md
@@ -1,31 +1,28 @@
|
||||
<h1 align="center"><img align="left" height="150px" src="https://ccnetcore.com/prod-api/wwwroot/logo.png"> Yi框架</h1>
|
||||
<h4 align="center">一套以用户体验出发的.Net8 Web开源框架</h4>
|
||||
<h5 align="center">支持Abp.vNext 版本原生版本、Furion版本,前端后台接入Ruoyi Vue3.0</h5>
|
||||
<h1 align="center"><img align="left" height="150px" src="https://user-images.githubusercontent.com/68722157/138828506-f58b7c57-5e10-4178-8f7d-5d5e12050113.png"> Yi框架</h1>
|
||||
<h4 align="center">一套以用户体验出发的.Net6 Web开源框架</h4>
|
||||
<h5 align="center">支持原生版本、Furion版本、Abp版本,前端后台接入Ruoyi Vue3.0</h5>
|
||||
<h2 align="center">集大成者,终究轮子</h2>
|
||||
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
|
||||
[English](README-en.md) | 简体中文
|
||||
|
||||

|
||||
|
||||
****
|
||||
## :tw-1f34e: 简介:
|
||||
YiFramework是一个基于.Net8+Abp.vNext+SqlSugar的DDD领域驱动设计后端开源框架
|
||||
|
||||
谁说Abp复杂?谁说DDD难?`打破常规,化繁为简`,新人入门,项目二开,最佳方式之一
|
||||
|
||||
### 简介:
|
||||
**中文:意框架**(和他的名字一样“简易”,同时接入Java的Ruoyi Vue3.0前端)
|
||||
|
||||
模块化,可根据业务自行引用或抛弃,集大成者,大而全乎,也许你能从中学习到一些独特见解
|
||||
模块分化较多,可根据业务自行引用或抛弃,集大成者,大而全乎,也许你能从中学习到一些独特见解
|
||||
|
||||
**英文:YiFramework**
|
||||
|
||||
Yi框架-一套与SqlSugar一样爽的.Net8开源框架。
|
||||
Yi框架-一套与SqlSugar一样爽的.Net6开源框架。
|
||||
与Sqlsugar理念一致,以用户体验出发。
|
||||
适合.Net8学习、Sqlsugar学习 、项目二次开发。
|
||||
适合.Net6学习、Sqlsugar学习 、项目二次开发。
|
||||
集大成者,终究轮子
|
||||
|
||||
(更新频繁,可watching持续关注。)
|
||||
Yi框架最新版本标签:`v3.0.0`,具体版本可以查看标签迭代
|
||||
|
||||
(项目与Sqlsugar同步更新,但这作者老杰哥代码天天爆肝到凌晨两点,我们也尽量会跟上他的脚步。更新频繁,所以可watching持续关注。)
|
||||
|
||||
————这不仅仅是一个程序,更是一个艺术品,面向艺术的开发!
|
||||
|
||||
@@ -33,91 +30,152 @@ Yi框架-一套与SqlSugar一样爽的.Net8开源框架。
|
||||
|
||||
**分支:**
|
||||
|
||||
- (推荐) **Abp**: 基于Abp.vNext分支,DDD领域驱动设计,回归开发本质,极度简单,用起来贼爽
|
||||
(本项目由EFCore版本历经4年不断迭代至Sqlsugar版本,现EFcore版本已弃用,目前sqlsugar已带业务功能)
|
||||
|
||||
- **Furion**: 基于Furion分支
|
||||
- (推荐) **Furion**: 基于Furion分支,回归开发本质,极度简单,用起来贼爽
|
||||
|
||||
- ~~**Framework**~~: 框架分支,所有东西都在这里
|
||||
|
||||
- ~~**SqlSugar**:.Net6 DDD领域驱动设计 简单分层微服务架构~~
|
||||
|
||||
- ~~**SqlSugar-Dev**:为sqlsugar分支的实时开发版本~~
|
||||
|
||||
- ~~**abp**:基于abp.vnext项目~~
|
||||
|
||||
****
|
||||
|
||||
## :tw-1f350: 官网及演示地址:
|
||||
**目录:**
|
||||
|
||||
废话少说直接上地址
|
||||
Yi后端框架分为3个部分:
|
||||
|
||||
Yi社区官网网址:[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
- Infrastructure(基础设施,框架底层+sqlsugar+furion)
|
||||
- Module(应用模块,可选项,例如缓存模块、微信模块、文件模块、日志模块等)
|
||||
- Application(业务模块,用于开发)
|
||||
|
||||
Rbac后台管理系统:已上线,暂不提供演示地址,可本地部署访问
|
||||
另外,光说不练假把式,我们不仅仅提供一个空白的框架,还同时提供3个基于yi框架的业务模块,没有听错,目前为1个后端,支持3个前端。各个模块关系解耦,可单独使用其中的任意业务模块
|
||||
|
||||
App移动端系统:已上线,暂不提供演示地址,可本地部署访问
|
||||
- Yi.RuoYi.Vue3:Ruoyi后台管理系统Rbac Vue3前端(推荐)
|
||||
|
||||
Rbac演示地址:https://ccnetcore.com:1000 (用户cc、密码123456)
|
||||
- Yi.Furion.Net6:.NET6后端(推荐)
|
||||
|
||||
- Yi.App.Vue3:移动端App Vue3前端
|
||||
|
||||
- Yi.BBS.Vue3:Web网页端BBS论坛 Vue3+Ts前端
|
||||
|
||||
后续我们持续更新各大应用模块及业务模块:shop商场、erp进销存、mes工厂系统等
|
||||
|
||||
业务支持并扩展至各个领域,用于具体项目的二次开发极大复用后端代码及前端代码,以通用的部分+不通的部分快速二开
|
||||
|
||||
|
||||
## :tw-1f351: 支持:
|
||||
### 演示地址:
|
||||
|
||||
废话少说直接上地址,**请不要**更改里面的数据
|
||||
|
||||
官网网址:[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
|
||||
Bbs社区系统:[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
|
||||
Rbac后台管理系统:[yi.ccnetcore.com](http://yi.ccnetcore.com) (已上线)~~管理员账号:cc 、 123456~~
|
||||
|
||||
App移动端系统:[xxx](xxx)正在部署
|
||||
|
||||
网关地址:~~[gate.ccnetcore.com/swagger](http://gate.ccnetcore.com/swagger)~~(目前使用单体架构部署,无需网关)
|
||||
|
||||
### 支持:
|
||||
|
||||
- [x] 完全支持单体应用架构
|
||||
- [x] 完全支持分布式应用架构
|
||||
- [x] 完全支持微服务架构
|
||||
|
||||
****
|
||||
## :tw-1f352: 详细到爆炸的Yi框架教程导航:
|
||||
### 详细到爆炸的Yi框架教程导航:
|
||||
|
||||
1. [框架快速开始教程](https://ccnetcore.com/article/aaa00329-7f35-d3fe-d258-3a0f8380b742)(已完成)
|
||||
2. [框架功能模块教程](https://ccnetcore.com/article/8c464ab3-8ba5-2761-a4b0-3a0f83a9f312)(已完成)
|
||||
3. [实战演练开发教程](https://ccnetcore.com/article/e89c9593-f337-ada7-d108-3a0f83ae48e6)
|
||||
4. [橙子运维CICD教程](https://ccnetcore.com/article/6b80ed42-50cd-db15-c073-3a0fa8f7fd77)(已完成)
|
||||
5. [版本更新日志](https://ccnetcore.com/article/e9e69a38-ce1e-06f5-7944-3a0fdc942ef3)(已完成)
|
||||
1. [框架快速开始](https://ccnetcore.com/article/1641733850189139969)(已完成)
|
||||
2. [框架模块教程](https://ccnetcore.com/article/1641733991574933505)(已完成)
|
||||
3. [应用模块教程](https://ccnetcore.com/article/1641734073091231745)
|
||||
4. [Yi.RBAC后台系统](https://ccnetcore.com/article/1641734171128893441)
|
||||
5. [Yi.BBS社区系统](https://ccnetcore.com/article/1641734308475572225)
|
||||
|
||||
****
|
||||
## :tw-1f353: 它的理念:
|
||||
谁说Abp复杂?谁说DDD难?打破常规,化繁为简,新人入门,项目二开,最佳方式之一
|
||||
|
||||
> 一百个人,就有一百种DDD,Yi框架不一定是极度严格的DDD,而是站在巨人的肩膀上,经过极多项目的提炼,摸索出一种最佳实践
|
||||
|
||||
|
||||
### 它的理念:
|
||||
优雅的进行快速开发,通常,简单程度与优雅程度不可兼得,Yi框架并不一昧的追求极致的解耦,会站在用户使用角度上,在使用难易度进行考虑衡量
|
||||
|
||||
例如:我们大部分功能紧密贴合Sqlsugar,虽然缺少其他orm的替换性,但在使用程度上降低的使用难度
|
||||
|
||||
> 一个面向用户的快速开发后端框架
|
||||
|
||||
在真正的使用这,你会明白这一点,极致的简单,也是优雅的一种体现。
|
||||
****
|
||||
|
||||
## :tw-1f354: 特点
|
||||
- 面向用户的后端框架,使用简单,适合小型、中型、企业级项目
|
||||
- 项目直接内置源码,不打包,非常适合进行二开改造
|
||||
### 特点:
|
||||
- 面向用户的后端框架,使用简单,适合小型、企业级项目
|
||||
- 项目内置源码,不打包
|
||||
- 开箱即用
|
||||
- 支持模块化
|
||||
- 支持动态Api
|
||||
- 支持属性注入
|
||||
- 内置包含大量通用场景模块
|
||||
- 优雅支持分布式及微服务架构
|
||||
- 等等
|
||||
|
||||
## :tw-1f340: 基础设施简介
|
||||
### 基础设施简介
|
||||
- Jwt鉴权
|
||||
- 接口级别授权
|
||||
- 对象映射
|
||||
- O/RM
|
||||
- 数据过滤
|
||||
- 多租户
|
||||
- 逻辑删除
|
||||
- 审计日志
|
||||
- 种子数据
|
||||
- 工作单元
|
||||
- 模块化
|
||||
- 动态Api
|
||||
- 属性注入
|
||||
- 自动依赖注入
|
||||
- 当前用户
|
||||
- 仓储
|
||||
- Crud
|
||||
|
||||
以下全部功能可直接使用:
|
||||
|
||||
- [Abp.vNext官网](https://docs.abp.io/zh-Hans/abp/latest/)
|
||||
### 内置模块简介
|
||||
- 后台任务
|
||||
- 本地缓存
|
||||
- 分布式缓存
|
||||
- 事件总线
|
||||
- 字典管理
|
||||
- 文件管理
|
||||
- 图片操作
|
||||
- Excel操作
|
||||
- 操作日志管理
|
||||
- Sms短信
|
||||
- 微信支付
|
||||
- WebFirst代码生成
|
||||
|
||||
- [SqlSugar官网](https://www.donet5.com/home/doc)
|
||||
|
||||
## :tw-1f341: 内置模块简介
|
||||
- Rbac权限管理系统(已上线)
|
||||
- Bbs论坛社区系统(已上线)
|
||||
### 业务项目
|
||||
- RABC后台管理系统
|
||||
- BBS社区系统
|
||||
- APP移动端系统
|
||||
|
||||
> 重复的东西,无需再写一遍,这也是优雅的体现之一
|
||||
|
||||
****
|
||||
## :tw-1f31e: 核心技术
|
||||
### 核心技术
|
||||
#### 后端
|
||||
C# Asp.NetCore 8.0
|
||||
- [x] 动态Api:Abp.vNext
|
||||
C# Asp.NetCore 6.0
|
||||
- [x] 动态Api:Cike.AutoApi
|
||||
- [x] 鉴权授权:Jwt
|
||||
- [x] 日志:Serilog
|
||||
- [x] 模块化:Abp.vNext
|
||||
- [x] 日志:Nlog
|
||||
- [x] 模块化:StartupModules
|
||||
- [x] 依赖注入:Autofac
|
||||
- [x] 对象映射:Mapster
|
||||
- [x] ORM: SqlsugarCore
|
||||
- [x] 多租户:Abp.vNext
|
||||
- [x] ORM:SqlsugarCore
|
||||
- [x] 多租户:Abp
|
||||
- [x] 后台任务:Quartz.Net
|
||||
- [x] 本地缓存:Abp.vNext
|
||||
- [x] 分布式缓存:Abp.vNext
|
||||
- [x] 事件总线:Abp.vNext
|
||||
- [x] 本地缓存:MemortCache
|
||||
- [x] 分布式缓存:CSRedisCore
|
||||
- [x] 事件总线:Cike.EventBus
|
||||
- [x] 图像操作:SixLabors.ImageSharp
|
||||
- [x] Excle操作:ExcelToObject.Npoi
|
||||
|
||||
#### 前端
|
||||
js Vue3.2
|
||||
@@ -133,11 +191,10 @@ js Vue3.2
|
||||
- [x] CICD:gitlab+Jenkins
|
||||
- [x] Docker:harbor
|
||||
|
||||
|
||||
****
|
||||
## :tw-1f366: 业务支持模块:
|
||||
### 业务支持模块:
|
||||
|
||||
#### :tw-1f42f: RABC权限管理系统(持续更新)
|
||||
RABC权限管理系统(正在更新)
|
||||
(采用ruoyi前端)
|
||||
- 用户管理
|
||||
- 角色管理
|
||||
@@ -154,94 +211,78 @@ js Vue3.2
|
||||
- 服务监控
|
||||
- WebFirst代码生成工具
|
||||
|
||||
#### :tw-1f431: BBS社区论坛系统(持续更新)
|
||||
(采用vue3前端)
|
||||
- 文章功能
|
||||
- 板块功能
|
||||
- 主题功能
|
||||
- 个人中心
|
||||
- 授权中心
|
||||
- 权限管理
|
||||
**演示截图:**
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
#### :star: 演示截图:
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="readme/101.png"/></td>
|
||||
<td><img src="readme/102.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/103.png"/></td>
|
||||
<td><img src="readme/104.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="readme/1.png"/></td>
|
||||
<td><img src="readme/2.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/3.png"/></td>
|
||||
<td><img src="readme/4.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/3.png"/></td>
|
||||
<td><img src="readme/4.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/5.png"/></td>
|
||||
<td><img src="readme/6.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/7.png"/></td>
|
||||
<td><img src="readme/8.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/9.png"/></td>
|
||||
<td><img src="readme/10.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/11.png"/></td>
|
||||
<td><img src="readme/12.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
BBS论坛系统(持续迭代)
|
||||
- 文章管理
|
||||
- 评论管理
|
||||
- 主题管理
|
||||
- 板块管理
|
||||
- 点赞管理
|
||||
- 等等
|
||||
|
||||
## :tw-1f44f: 感谢:
|
||||
APP移动端系统(持续迭代)
|
||||
- 动态查询
|
||||
- 我的资料
|
||||
|
||||
ERP进销存系统(持续迭代)
|
||||
- 供货商管理
|
||||
- 等等
|
||||
|
||||
SHOP电商系统(持续迭代)
|
||||
- SPU管理
|
||||
- SKU管理
|
||||
- 商品规格
|
||||
- 商品分类
|
||||
- 等等
|
||||
|
||||
|
||||
****
|
||||
### 感谢:
|
||||
|
||||
**大力支持**: Eleven神、Sqlsugar上海杰哥、Gerry、哲学的老张
|
||||
|
||||
[橙子]https://ccnetcore.com
|
||||
|
||||
[XWen]https://gitee.com/on-wensil
|
||||
[lzw]https://github.com/yeslode
|
||||
|
||||
[朝夕教育]https://www.zhaoxiedu.net
|
||||
|
||||
[Sqlsugar老杰哥]https://www.donet5.com/Home/Doc
|
||||
|
||||
[车神]微信公众号搜索Dotnet技术进阶
|
||||
|
||||
[RuYiAdmin如意老兄]https://gitee.com/pang-mingjun/RuYiAdmin
|
||||
|
||||
[ZrAdminNetCore字母老哥]https://gitee.com/izory/ZrAdminNetCore
|
||||
|
||||
[Admin.NET]https://gitee.com/zuohuaijun/Admin.NET
|
||||
[Admin.NET周哥]https://gitee.com/zuohuaijun/Admin.NET
|
||||
|
||||
[Furion百小僧]https://furion.baiqian.ltd/
|
||||
|
||||
****
|
||||
## :tw-1f438: 联系我们:
|
||||
### 联系我们:
|
||||
|
||||
作者QQ:`454313500`,2029年之前作者24小时在线,时刻保持活跃更新。
|
||||
|
||||
QQ交流群:官方一群(已满)、官方二群(已满)、官方三群:`786308927`(已满)、官方四群:`498310311`(基本已满)、官方五群:`981136525`(新群)
|
||||
|
||||
微信交流群:加作者微信 chengzilaoge520 (橙子老哥520),备注拉群
|
||||
QQ交流群:官方一群(已满)、官方二群(已满)、官方三群:`786308927`(基本已满)、官方四群:`498310311`(新群)
|
||||
|
||||
联系作者,这里人人都是顾问
|
||||
|
||||
官方网址留言区:[ccnetcore.com](https://ccnetcore.com)
|
||||
|
||||
****
|
||||
## :tw-1f41e: FQA:
|
||||
### FQA:
|
||||
|
||||
前往官网查看留言区
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
**/.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
|
||||
!**/.gitignore
|
||||
!.git/HEAD
|
||||
!.git/config
|
||||
!.git/packed-refs
|
||||
!.git/refs/heads/**
|
||||
@@ -1,509 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.7.34202.233
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Web", "src\Yi.Abp.Web\Yi.Abp.Web.csproj", "{15913E44-DA92-44B9-9AC5-E9457EA34BF5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.SqlSugarCore", "framework\Yi.Framework.SqlSugarCore\Yi.Framework.SqlSugarCore.csproj", "{DC431ECC-C75D-4B01-8B79-4861948179BB}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B782C78B-6C17-49E6-A237-3383BA720766}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0D10EEF2-FBAE-4C72-B816-A52823FC299B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "framework", "framework", "{77B949E9-530E-45A5-9657-20F7D5C6875C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "module", "module", "{2317227D-7796-4E7B-BEDB-7CD1CAE7B853}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.SqlSugarCore", "src\Yi.Abp.SqlSugarCore\Yi.Abp.SqlSugarCore.csproj", "{9A7BBA40-28D6-4900-9E1D-D627A516EE72}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Application", "src\Yi.Abp.Application\Yi.Abp.Application.csproj", "{746DBBD6-23E8-4D5D-9D23-E2902BE338BD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Application.Contracts", "src\Yi.Abp.Application.Contracts\Yi.Abp.Application.Contracts.csproj", "{51EEBF59-3D37-4681-981D-56F8D8F8968D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Domain", "src\Yi.Abp.Domain\Yi.Abp.Domain.csproj", "{7B15C198-538A-44ED-A6AA-3A0FEAA1D2BD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Domain.Shared", "src\Yi.Abp.Domain.Shared\Yi.Abp.Domain.Shared.csproj", "{F4D5A496-BFBE-470B-A05B-CB5823B47E72}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6A5375C6-1D55-4E93-9B19-736F1C68CBC3}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
common.props = common.props
|
||||
end.sh = end.sh
|
||||
logo.png = logo.png
|
||||
start.sh = start.sh
|
||||
tool.bat = tool.bat
|
||||
usings.props = usings.props
|
||||
version.props = version.props
|
||||
publish.bat = publish.bat
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.SqlSugarCore.Abstractions", "framework\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj", "{FD6D6860-3753-4747-8A26-977E4A3001F9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Core", "framework\Yi.Framework.Core\Yi.Framework.Core.csproj", "{ECE874D4-F882-4EF4-84A6-A842D9B8FBC5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Mapster", "framework\Yi.Framework.Mapster\Yi.Framework.Mapster.csproj", "{1995A019-C8AE-467E-B427-ED57D6CBF44F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AspNetCore", "framework\Yi.Framework.AspNetCore\Yi.Framework.AspNetCore.csproj", "{F5011C0D-209B-4A98-BBE3-68157503EEF8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Ddd.Application.Contracts", "framework\Yi.Framework.Ddd.Application.Contracts\Yi.Framework.Ddd.Application.Contracts.csproj", "{0A8296A3-C11F-4F13-8E49-6BC8188D4804}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Ddd.Application", "framework\Yi.Framework.Ddd.Application\Yi.Framework.Ddd.Application.csproj", "{F0141C17-0EBD-4261-98D5-1C5B7BC1DFEE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rbac", "rbac", "{9CC7A457-1236-40BA-B47B-E7B710A3F061}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.Application.Contracts", "module\rbac\Yi.Framework.Rbac.Application.Contracts\Yi.Framework.Rbac.Application.Contracts.csproj", "{1C360956-8CD8-407E-B87F-D0BD57068EB9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.Application", "module\rbac\Yi.Framework.Rbac.Application\Yi.Framework.Rbac.Application.csproj", "{4F02B08D-5FE2-460D-BCA5-DA565151AE30}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.Domain", "module\rbac\Yi.Framework.Rbac.Domain\Yi.Framework.Rbac.Domain.csproj", "{C04D3F71-1557-46D0-B810-97B1FBB6AB73}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.Domain.Shared", "module\rbac\Yi.Framework.Rbac.Domain.Shared\Yi.Framework.Rbac.Domain.Shared.csproj", "{A2BB899D-4F9A-4184-81BD-94B938E2AB03}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.SqlSugarCore", "module\rbac\Yi.Framework.Rbac.SqlSugarCore\Yi.Framework.Rbac.SqlSugarCore.csproj", "{4503A2F9-139D-4CBC-AF11-689C34F0D77B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bbs", "bbs", "{E902A945-4F41-4E96-A0DA-9F66CDA22261}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Domain.Shared", "module\bbs\Yi.Framework.Bbs.Domain.Shared\Yi.Framework.Bbs.Domain.Shared.csproj", "{EB9349E2-256D-41EB-A345-21635A1361B3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Domain", "module\bbs\Yi.Framework.Bbs.Domain\Yi.Framework.Bbs.Domain.csproj", "{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Application.Contracts", "module\bbs\Yi.Framework.Bbs.Application.Contracts\Yi.Framework.Bbs.Application.Contracts.csproj", "{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Application", "module\bbs\Yi.Framework.Bbs.Application\Yi.Framework.Bbs.Application.csproj", "{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.SqlSugarCore", "module\bbs\Yi.Framework.Bbs.SqlSugarCore\Yi.Framework.Bbs.SqlSugarCore.csproj", "{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "audit-logging", "audit-logging", "{73CCF2C4-B9FD-44AB-8D4B-0A421805B094}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AuditLogging.SqlSugarCore", "module\audit-logging\Yi.Framework.AuditLogging.SqlSugarCore\Yi.Framework.AuditLogging.SqlSugarCore.csproj", "{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AspNetCore.Authentication.OAuth", "framework\Yi.Framework.AspNetCore.Authentication.OAuth\Yi.Framework.AspNetCore.Authentication.OAuth.csproj", "{791AC2FA-50D3-4408-8D68-31DA72F608BE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{01300F0F-686E-47B3-821D-12424177867B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Web", "sample\Acme.BookStore.Web\Acme.BookStore.Web.csproj", "{576DBC97-4E5D-4444-B65C-F41649A5F8E0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain.Shared", "sample\Acme.BookStore.Domain.Shared\Acme.BookStore.Domain.Shared.csproj", "{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain", "sample\Acme.BookStore.Domain\Acme.BookStore.Domain.csproj", "{B615847F-8568-41D1-8B7E-63D61AE69F3D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application.Contracts", "sample\Acme.BookStore.Application.Contracts\Acme.BookStore.Application.Contracts.csproj", "{20827DB5-5CDE-491A-82E8-3CAB82618C1E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application", "sample\Acme.BookStore.Application\Acme.BookStore.Application.csproj", "{320273B6-7AE3-42DA-9675-D9AD4928A289}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.SqlSugarCore", "sample\Acme.BookStore.SqlSugarCore\Acme.BookStore.SqlSugarCore.csproj", "{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Test", "test\Yi.Abp.Test\Yi.Abp.Test.csproj", "{68627BC2-F049-4C69-AD17-81DF9478E8CE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenant-management", "tenant-management", "{499A8C71-7892-42D0-A77E-48756E1EFF16}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.TenantManagement.SqlSugarCore", "module\tenant-management\Yi.Framework.TenantManagement.SqlSugarCore\Yi.Framework.TenantManagement.SqlSugarCore.csproj", "{FA5BBAA1-08DC-472F-BB2C-5314E59D1556}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.TenantManagement.Domain", "module\tenant-management\Yi.Framework.TenantManagement.Domain\Yi.Framework.TenantManagement.Domain.csproj", "{54D8E2BC-591C-4344-A58E-874D49C00B41}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AuditLogging.Domain", "module\audit-logging\Yi.Framework.AuditLogging.Domain\Yi.Framework.AuditLogging.Domain.csproj", "{EFD13211-17B5-400A-B99A-9F6F4E520C1E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AuditLogging.Domain.Shared", "module\audit-logging\Yi.Framework.AuditLogging.Domain.Shared\Yi.Framework.AuditLogging.Domain.Shared.csproj", "{9C8C3C53-3DCE-4516-867E-228858E61B26}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.TenantManagement.Application", "module\tenant-management\Yi.Framework.TenantManagement.Application\Yi.Framework.TenantManagement.Application.csproj", "{17816837-E53B-486B-B796-53C601FE6CD9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.TenantManagement.Application.Contracts", "module\tenant-management\Yi.Framework.TenantManagement.Application.Contracts\Yi.Framework.TenantManagement.Application.Contracts.csproj", "{FA735055-CBDD-4EFD-B84B-85810DA1425E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code-gen", "code-gen", "{4FFE7212-21F2-476D-B628-3C65E6C5075E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application", "module\code-gen\Yi.Framework.CodeGen.Application\Yi.Framework.CodeGen.Application.csproj", "{97EC40D7-DBFA-467A-98CB-221AF27B14F2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application.Contracts", "module\code-gen\Yi.Framework.CodeGen.Application.Contracts\Yi.Framework.CodeGen.Application.Contracts.csproj", "{882BC563-2F75-4B95-AC96-F4BF23F5E69D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain", "module\code-gen\Yi.Framework.CodeGen.Domain\Yi.Framework.CodeGen.Domain.csproj", "{85CB8517-2B80-42D8-B954-081079AC9BA0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain.Shared", "module\code-gen\Yi.Framework.CodeGen.Domain.Shared\Yi.Framework.CodeGen.Domain.Shared.csproj", "{EEFF0F05-2709-4151-A8CE-667935CEAE0B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching.FreeRedis", "framework\Yi.Framework.Caching.FreeRedis\Yi.Framework.Caching.FreeRedis.csproj", "{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.SqlSugarCore", "module\code-gen\Yi.Framework.CodeGen.SqlSugarCore\Yi.Framework.CodeGen.SqlSugarCore.csproj", "{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{8B27846A-043D-4F2F-8140-5CEC9D1863B5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.HttpApi.Client", "client\Yi.Abp.HttpApi.Client\Yi.Abp.HttpApi.Client.csproj", "{6B554DCC-3A81-4624-9141-4E39365ADA35}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Client.Console", "client\Yi.Abp.Client.Console\Yi.Abp.Client.Console.csproj", "{2D23B44A-DFA3-4C36-8516-4F5AE442403C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Client.WebApi", "client\Yi.Abp.Client.WebApi\Yi.Abp.Client.WebApi.csproj", "{00E49781-C6A0-491C-86A1-46F685C90915}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "setting-management", "setting-management", "{8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.SettingManagement.Domain", "module\setting-management\Yi.Framework.SettingManagement.Domain\Yi.Framework.SettingManagement.Domain.csproj", "{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.SettingManagement.SqlSugarCore", "module\setting-management\Yi.Framework.SettingManagement.SqlSugarCore\Yi.Framework.SettingManagement.SqlSugarCore.csproj", "{495C4643-39D4-46E7-BDC8-237589627BE4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "chat-hub", "chat-hub", "{D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Application.Contracts", "module\chat-hub\Yi.Framework.ChatHub.Application.Contracts\Yi.Framework.ChatHub.Application.Contracts.csproj", "{65D4D033-5504-44B9-B152-0172ACD64CE6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Domain.Shared", "module\chat-hub\Yi.Framework.ChatHub.Domain.Shared\Yi.Framework.ChatHub.Domain.Shared.csproj", "{DEEC0B15-190C-4464-B469-C45C6563C592}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.SqlSugarCore", "module\chat-hub\Yi.Framework.ChatHub.SqlSugarCore\Yi.Framework.ChatHub.SqlSugarCore.csproj", "{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Domain", "module\chat-hub\Yi.Framework.ChatHub.Domain\Yi.Framework.ChatHub.Domain.csproj", "{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Application", "module\chat-hub\Yi.Framework.ChatHub.Application\Yi.Framework.ChatHub.Application.csproj", "{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.Test", "test\Yi.Framework.Rbac.Test\Yi.Framework.Rbac.Test.csproj", "{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tool", "tool", "{084CBEEC-5D37-4716-B9C7-D80D6960DFF4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool", "tool\Yi.Abp.Tool\Yi.Abp.Tool.csproj", "{4FEBBDD9-E4F4-4BAF-8599-E2D57C08A74F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.Web", "tool\Yi.Abp.Tool.Web\Yi.Abp.Tool.Web.csproj", "{2CE51D4C-1EF9-462B-BA14-7EA01A7E4AF1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.Application", "tool\Yi.Abp.Tool.Application\Yi.Abp.Tool.Application.csproj", "{776590BA-B900-4C8B-986A-5B721FA4B306}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.Application.Contracts", "tool\Yi.Abp.Tool.Application.Contracts\Yi.Abp.Tool.Application.Contracts.csproj", "{3A3AF1ED-FC7F-48CF-8ACE-9D50426B4675}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.Domain", "tool\Yi.Abp.Tool.Domain\Yi.Abp.Tool.Domain.csproj", "{68F73B7B-0F8A-41C1-8092-6D6FFAED32F8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.Domain.Shared", "tool\Yi.Abp.Tool.Domain.Shared\Yi.Abp.Tool.Domain.Shared.csproj", "{4AE84CDE-2A47-4D68-8E93-86193F72E4E8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.HttpApi.Client", "tool\Yi.Abp.Tool.HttpApi.Client\Yi.Abp.Tool.HttpApi.Client.csproj", "{C8F97775-D903-4365-A4FF-3DA97E318CD2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.SettingManagement.Application", "module\setting-management\Yi.Framework.SettingManagement.Application\Yi.Framework.SettingManagement.Application.csproj", "{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{15913E44-DA92-44B9-9AC5-E9457EA34BF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{15913E44-DA92-44B9-9AC5-E9457EA34BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{15913E44-DA92-44B9-9AC5-E9457EA34BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{15913E44-DA92-44B9-9AC5-E9457EA34BF5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DC431ECC-C75D-4B01-8B79-4861948179BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DC431ECC-C75D-4B01-8B79-4861948179BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DC431ECC-C75D-4B01-8B79-4861948179BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DC431ECC-C75D-4B01-8B79-4861948179BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9A7BBA40-28D6-4900-9E1D-D627A516EE72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9A7BBA40-28D6-4900-9E1D-D627A516EE72}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A7BBA40-28D6-4900-9E1D-D627A516EE72}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A7BBA40-28D6-4900-9E1D-D627A516EE72}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{746DBBD6-23E8-4D5D-9D23-E2902BE338BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{746DBBD6-23E8-4D5D-9D23-E2902BE338BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{746DBBD6-23E8-4D5D-9D23-E2902BE338BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{746DBBD6-23E8-4D5D-9D23-E2902BE338BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{51EEBF59-3D37-4681-981D-56F8D8F8968D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{51EEBF59-3D37-4681-981D-56F8D8F8968D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{51EEBF59-3D37-4681-981D-56F8D8F8968D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{51EEBF59-3D37-4681-981D-56F8D8F8968D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7B15C198-538A-44ED-A6AA-3A0FEAA1D2BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7B15C198-538A-44ED-A6AA-3A0FEAA1D2BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7B15C198-538A-44ED-A6AA-3A0FEAA1D2BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7B15C198-538A-44ED-A6AA-3A0FEAA1D2BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F4D5A496-BFBE-470B-A05B-CB5823B47E72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F4D5A496-BFBE-470B-A05B-CB5823B47E72}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F4D5A496-BFBE-470B-A05B-CB5823B47E72}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F4D5A496-BFBE-470B-A05B-CB5823B47E72}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD6D6860-3753-4747-8A26-977E4A3001F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD6D6860-3753-4747-8A26-977E4A3001F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD6D6860-3753-4747-8A26-977E4A3001F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD6D6860-3753-4747-8A26-977E4A3001F9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ECE874D4-F882-4EF4-84A6-A842D9B8FBC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ECE874D4-F882-4EF4-84A6-A842D9B8FBC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ECE874D4-F882-4EF4-84A6-A842D9B8FBC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ECE874D4-F882-4EF4-84A6-A842D9B8FBC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1995A019-C8AE-467E-B427-ED57D6CBF44F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1995A019-C8AE-467E-B427-ED57D6CBF44F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1995A019-C8AE-467E-B427-ED57D6CBF44F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1995A019-C8AE-467E-B427-ED57D6CBF44F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F5011C0D-209B-4A98-BBE3-68157503EEF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F5011C0D-209B-4A98-BBE3-68157503EEF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F5011C0D-209B-4A98-BBE3-68157503EEF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F5011C0D-209B-4A98-BBE3-68157503EEF8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0A8296A3-C11F-4F13-8E49-6BC8188D4804}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0A8296A3-C11F-4F13-8E49-6BC8188D4804}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A8296A3-C11F-4F13-8E49-6BC8188D4804}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A8296A3-C11F-4F13-8E49-6BC8188D4804}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F0141C17-0EBD-4261-98D5-1C5B7BC1DFEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F0141C17-0EBD-4261-98D5-1C5B7BC1DFEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F0141C17-0EBD-4261-98D5-1C5B7BC1DFEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F0141C17-0EBD-4261-98D5-1C5B7BC1DFEE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1C360956-8CD8-407E-B87F-D0BD57068EB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1C360956-8CD8-407E-B87F-D0BD57068EB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1C360956-8CD8-407E-B87F-D0BD57068EB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1C360956-8CD8-407E-B87F-D0BD57068EB9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4F02B08D-5FE2-460D-BCA5-DA565151AE30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4F02B08D-5FE2-460D-BCA5-DA565151AE30}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4F02B08D-5FE2-460D-BCA5-DA565151AE30}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4F02B08D-5FE2-460D-BCA5-DA565151AE30}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C04D3F71-1557-46D0-B810-97B1FBB6AB73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C04D3F71-1557-46D0-B810-97B1FBB6AB73}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C04D3F71-1557-46D0-B810-97B1FBB6AB73}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C04D3F71-1557-46D0-B810-97B1FBB6AB73}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A2BB899D-4F9A-4184-81BD-94B938E2AB03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A2BB899D-4F9A-4184-81BD-94B938E2AB03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A2BB899D-4F9A-4184-81BD-94B938E2AB03}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A2BB899D-4F9A-4184-81BD-94B938E2AB03}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{791AC2FA-50D3-4408-8D68-31DA72F608BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{791AC2FA-50D3-4408-8D68-31DA72F608BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{791AC2FA-50D3-4408-8D68-31DA72F608BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{791AC2FA-50D3-4408-8D68-31DA72F608BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{68627BC2-F049-4C69-AD17-81DF9478E8CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68627BC2-F049-4C69-AD17-81DF9478E8CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68627BC2-F049-4C69-AD17-81DF9478E8CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{68627BC2-F049-4C69-AD17-81DF9478E8CE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FA5BBAA1-08DC-472F-BB2C-5314E59D1556}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FA5BBAA1-08DC-472F-BB2C-5314E59D1556}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FA5BBAA1-08DC-472F-BB2C-5314E59D1556}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FA5BBAA1-08DC-472F-BB2C-5314E59D1556}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{54D8E2BC-591C-4344-A58E-874D49C00B41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{54D8E2BC-591C-4344-A58E-874D49C00B41}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{54D8E2BC-591C-4344-A58E-874D49C00B41}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{54D8E2BC-591C-4344-A58E-874D49C00B41}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EFD13211-17B5-400A-B99A-9F6F4E520C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EFD13211-17B5-400A-B99A-9F6F4E520C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EFD13211-17B5-400A-B99A-9F6F4E520C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EFD13211-17B5-400A-B99A-9F6F4E520C1E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9C8C3C53-3DCE-4516-867E-228858E61B26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9C8C3C53-3DCE-4516-867E-228858E61B26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9C8C3C53-3DCE-4516-867E-228858E61B26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9C8C3C53-3DCE-4516-867E-228858E61B26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{17816837-E53B-486B-B796-53C601FE6CD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{17816837-E53B-486B-B796-53C601FE6CD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{17816837-E53B-486B-B796-53C601FE6CD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{17816837-E53B-486B-B796-53C601FE6CD9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2D23B44A-DFA3-4C36-8516-4F5AE442403C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D23B44A-DFA3-4C36-8516-4F5AE442403C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D23B44A-DFA3-4C36-8516-4F5AE442403C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D23B44A-DFA3-4C36-8516-4F5AE442403C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{00E49781-C6A0-491C-86A1-46F685C90915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{00E49781-C6A0-491C-86A1-46F685C90915}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{00E49781-C6A0-491C-86A1-46F685C90915}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{00E49781-C6A0-491C-86A1-46F685C90915}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4FEBBDD9-E4F4-4BAF-8599-E2D57C08A74F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4FEBBDD9-E4F4-4BAF-8599-E2D57C08A74F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4FEBBDD9-E4F4-4BAF-8599-E2D57C08A74F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4FEBBDD9-E4F4-4BAF-8599-E2D57C08A74F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2CE51D4C-1EF9-462B-BA14-7EA01A7E4AF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2CE51D4C-1EF9-462B-BA14-7EA01A7E4AF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2CE51D4C-1EF9-462B-BA14-7EA01A7E4AF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2CE51D4C-1EF9-462B-BA14-7EA01A7E4AF1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{776590BA-B900-4C8B-986A-5B721FA4B306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{776590BA-B900-4C8B-986A-5B721FA4B306}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{776590BA-B900-4C8B-986A-5B721FA4B306}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{776590BA-B900-4C8B-986A-5B721FA4B306}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3A3AF1ED-FC7F-48CF-8ACE-9D50426B4675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3A3AF1ED-FC7F-48CF-8ACE-9D50426B4675}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3A3AF1ED-FC7F-48CF-8ACE-9D50426B4675}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3A3AF1ED-FC7F-48CF-8ACE-9D50426B4675}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{68F73B7B-0F8A-41C1-8092-6D6FFAED32F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68F73B7B-0F8A-41C1-8092-6D6FFAED32F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68F73B7B-0F8A-41C1-8092-6D6FFAED32F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{68F73B7B-0F8A-41C1-8092-6D6FFAED32F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4AE84CDE-2A47-4D68-8E93-86193F72E4E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4AE84CDE-2A47-4D68-8E93-86193F72E4E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4AE84CDE-2A47-4D68-8E93-86193F72E4E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4AE84CDE-2A47-4D68-8E93-86193F72E4E8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C8F97775-D903-4365-A4FF-3DA97E318CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C8F97775-D903-4365-A4FF-3DA97E318CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C8F97775-D903-4365-A4FF-3DA97E318CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C8F97775-D903-4365-A4FF-3DA97E318CD2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{15913E44-DA92-44B9-9AC5-E9457EA34BF5} = {B782C78B-6C17-49E6-A237-3383BA720766}
|
||||
{DC431ECC-C75D-4B01-8B79-4861948179BB} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{9A7BBA40-28D6-4900-9E1D-D627A516EE72} = {B782C78B-6C17-49E6-A237-3383BA720766}
|
||||
{746DBBD6-23E8-4D5D-9D23-E2902BE338BD} = {B782C78B-6C17-49E6-A237-3383BA720766}
|
||||
{51EEBF59-3D37-4681-981D-56F8D8F8968D} = {B782C78B-6C17-49E6-A237-3383BA720766}
|
||||
{7B15C198-538A-44ED-A6AA-3A0FEAA1D2BD} = {B782C78B-6C17-49E6-A237-3383BA720766}
|
||||
{F4D5A496-BFBE-470B-A05B-CB5823B47E72} = {B782C78B-6C17-49E6-A237-3383BA720766}
|
||||
{FD6D6860-3753-4747-8A26-977E4A3001F9} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{ECE874D4-F882-4EF4-84A6-A842D9B8FBC5} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{1995A019-C8AE-467E-B427-ED57D6CBF44F} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{F5011C0D-209B-4A98-BBE3-68157503EEF8} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{0A8296A3-C11F-4F13-8E49-6BC8188D4804} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{F0141C17-0EBD-4261-98D5-1C5B7BC1DFEE} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{9CC7A457-1236-40BA-B47B-E7B710A3F061} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{1C360956-8CD8-407E-B87F-D0BD57068EB9} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{4F02B08D-5FE2-460D-BCA5-DA565151AE30} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{C04D3F71-1557-46D0-B810-97B1FBB6AB73} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{A2BB899D-4F9A-4184-81BD-94B938E2AB03} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{E902A945-4F41-4E96-A0DA-9F66CDA22261} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{73CCF2C4-B9FD-44AB-8D4B-0A421805B094} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3} = {73CCF2C4-B9FD-44AB-8D4B-0A421805B094}
|
||||
{791AC2FA-50D3-4408-8D68-31DA72F608BE} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{576DBC97-4E5D-4444-B65C-F41649A5F8E0} = {01300F0F-686E-47B3-821D-12424177867B}
|
||||
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D} = {01300F0F-686E-47B3-821D-12424177867B}
|
||||
{B615847F-8568-41D1-8B7E-63D61AE69F3D} = {01300F0F-686E-47B3-821D-12424177867B}
|
||||
{20827DB5-5CDE-491A-82E8-3CAB82618C1E} = {01300F0F-686E-47B3-821D-12424177867B}
|
||||
{320273B6-7AE3-42DA-9675-D9AD4928A289} = {01300F0F-686E-47B3-821D-12424177867B}
|
||||
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7} = {01300F0F-686E-47B3-821D-12424177867B}
|
||||
{68627BC2-F049-4C69-AD17-81DF9478E8CE} = {0D10EEF2-FBAE-4C72-B816-A52823FC299B}
|
||||
{499A8C71-7892-42D0-A77E-48756E1EFF16} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{FA5BBAA1-08DC-472F-BB2C-5314E59D1556} = {499A8C71-7892-42D0-A77E-48756E1EFF16}
|
||||
{54D8E2BC-591C-4344-A58E-874D49C00B41} = {499A8C71-7892-42D0-A77E-48756E1EFF16}
|
||||
{EFD13211-17B5-400A-B99A-9F6F4E520C1E} = {73CCF2C4-B9FD-44AB-8D4B-0A421805B094}
|
||||
{9C8C3C53-3DCE-4516-867E-228858E61B26} = {73CCF2C4-B9FD-44AB-8D4B-0A421805B094}
|
||||
{17816837-E53B-486B-B796-53C601FE6CD9} = {499A8C71-7892-42D0-A77E-48756E1EFF16}
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E} = {499A8C71-7892-42D0-A77E-48756E1EFF16}
|
||||
{4FFE7212-21F2-476D-B628-3C65E6C5075E} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5}
|
||||
{2D23B44A-DFA3-4C36-8516-4F5AE442403C} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5}
|
||||
{00E49781-C6A0-491C-86A1-46F685C90915} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5}
|
||||
{8C68059E-F3B1-4D28-A1C9-A5830F53E5D3} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}
|
||||
{D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07} = {0D10EEF2-FBAE-4C72-B816-A52823FC299B}
|
||||
{4FEBBDD9-E4F4-4BAF-8599-E2D57C08A74F} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{2CE51D4C-1EF9-462B-BA14-7EA01A7E4AF1} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{776590BA-B900-4C8B-986A-5B721FA4B306} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{3A3AF1ED-FC7F-48CF-8ACE-9D50426B4675} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{68F73B7B-0F8A-41C1-8092-6D6FFAED32F8} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{4AE84CDE-2A47-4D68-8E93-86193F72E4E8} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{C8F97775-D903-4365-A4FF-3DA97E318CD2} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {23D6FBC9-C970-4641-BC1E-2AEA59F51C18}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,33 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Yi.Abp.Client.Console;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
|
||||
try
|
||||
{
|
||||
IHost host = Host.CreateDefaultBuilder()
|
||||
.ConfigureServices(async (host, service) =>
|
||||
{
|
||||
await service.AddApplicationAsync<YiAbpClientConsoleModule>();
|
||||
})
|
||||
.UseAutofac()
|
||||
.Build();
|
||||
|
||||
//控制台直接调用
|
||||
var account = host.Services.GetRequiredService<IAccountService>();
|
||||
|
||||
//获取验证码
|
||||
var data1 = await account.GetCaptchaImageAsync();
|
||||
|
||||
//登录
|
||||
var data2 = await account.PostLoginAsync(new Yi.Framework.Rbac.Application.Contracts.Dtos.Account.LoginInputVo { UserName = "cc", Password = "123456", Code = string.Empty, Uuid = string.Empty });
|
||||
|
||||
|
||||
host.Run();
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Volo.Abp.Autofac" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Abp.HttpApi.Client\Yi.Abp.HttpApi.Client.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Abp.HttpApi.Client;
|
||||
|
||||
namespace Yi.Abp.Client.Console
|
||||
{
|
||||
[DependsOn(typeof(YiAbpHttpApiClientModule))]
|
||||
public class YiAbpClientConsoleModule:AbpModule
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
|
||||
namespace Yi.Abp.Client.WebApi.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class AccountController : ControllerBase
|
||||
{
|
||||
|
||||
|
||||
private readonly ILogger<AccountController> _logger;
|
||||
private IAccountService _accountService;
|
||||
public AccountController(ILogger<AccountController> logger, IAccountService accountService)
|
||||
{
|
||||
_logger = logger;
|
||||
_accountService = accountService;
|
||||
}
|
||||
|
||||
[HttpPost("my-login")]
|
||||
public async Task<IActionResult> Login(LoginInputVo input)
|
||||
{
|
||||
await _accountService.PostLoginAsync(input);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("my-captcha-image")]
|
||||
public async Task<IActionResult> CaptchaImageAsync()
|
||||
{
|
||||
var output = await _accountService.GetCaptchaImageAsync();
|
||||
return Ok(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using Autofac.Core;
|
||||
using Yi.Abp.Client.WebApi;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Host.UseAutofac();
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
await builder.Services.AddApplicationAsync<YiAbpClientWebApiModule>();
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:35597",
|
||||
"sslPort": 44322
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5002",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7108;http://localhost:5002",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Import Project="..\..\common.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Abp.HttpApi.Client\Yi.Abp.HttpApi.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,6 +0,0 @@
|
||||
@Yi.Abp.Client.WebApi_HostAddress = http://localhost:5002
|
||||
|
||||
GET {{Yi.Abp.Client.WebApi_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
@@ -1,10 +0,0 @@
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Abp.HttpApi.Client;
|
||||
|
||||
namespace Yi.Abp.Client.WebApi
|
||||
{
|
||||
[DependsOn(typeof(YiAbpHttpApiClientModule))]
|
||||
public class YiAbpClientWebApiModule:AbpModule
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Volo.Abp.Http.Client" Version="$(AbpVersion)" />
|
||||
<PackageReference Include="Volo.Abp.Autofac" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Yi.Abp.Application.Contracts\Yi.Abp.Application.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,32 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Volo.Abp.Autofac;
|
||||
using Volo.Abp.Http.Client;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.Rbac.Application.Contracts;
|
||||
|
||||
namespace Yi.Abp.HttpApi.Client
|
||||
{
|
||||
[DependsOn(typeof(AbpHttpClientModule),
|
||||
typeof(AbpAutofacModule),
|
||||
|
||||
|
||||
typeof(YiFrameworkRbacApplicationContractsModule))]
|
||||
public class YiAbpHttpApiClientModule : AbpModule
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
//创建动态客户端代理
|
||||
context.Services.AddHttpClientProxies(
|
||||
typeof(YiFrameworkRbacApplicationContractsModule).Assembly
|
||||
|
||||
);
|
||||
Configure<AbpRemoteServiceOptions>(options =>
|
||||
{
|
||||
options.RemoteServices.Default =
|
||||
new RemoteServiceConfiguration("http://localhost:19001");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<Project>
|
||||
<Import Project="usings.props" />
|
||||
<Import Project="version.props" />
|
||||
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Version>1.0.0</Version>
|
||||
<NoWarn>$(NoWarn);CS1591;CS8618;CS1998;CS8604;CS8620;CS8600;CS8602</NoWarn>
|
||||
<AbpProjectType>app</AbpProjectType>
|
||||
|
||||
<PublishDocumentationFiles>true</PublishDocumentationFiles>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="NoWarnOnRazorViewImportedTypeConflicts" BeforeTargets="RazorCoreCompile">
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);0436</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
kill -9 $(lsof -t -i:19001)
|
||||
echo "Yi-进程已关闭"
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
public class AuthenticationConstants
|
||||
{
|
||||
public const string OpenId = "urn:openid";
|
||||
public const string AccessToken = "urn:access_token";
|
||||
public const string Name = "urn:name";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
public class AuthenticationOAuthOptions:OAuthOptions
|
||||
{
|
||||
|
||||
public string RedirectUri { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
public class AuthticationErrCodeModel
|
||||
{
|
||||
public string error { get; set; }
|
||||
|
||||
public string error_description { get; set; }
|
||||
|
||||
public static void VerifyErrResponse(string content)
|
||||
{
|
||||
|
||||
var model = Newtonsoft.Json.JsonConvert.DeserializeObject<AuthticationErrCodeModel>(content);
|
||||
if (model.error != null)
|
||||
{
|
||||
|
||||
throw new Exception($"第三方授权返回错误,错误码:【{model.error}】,错误详情:【{model.error_description}】");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
|
||||
|
||||
/// <summary>
|
||||
/// Contains constants specific to the <see cref="GiteeAuthenticationHandler"/>.
|
||||
/// </summary>
|
||||
public static class GiteeAuthenticationConstants
|
||||
{
|
||||
public static class Claims
|
||||
{
|
||||
public const string Url = "urn:gitee:url";
|
||||
public const string AvatarUrl = "urn:gitee:avatarUrl";
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
|
||||
|
||||
/// <summary>
|
||||
/// Default values used by the Gitee authentication middleware.
|
||||
/// </summary>
|
||||
public static class GiteeAuthenticationDefaults
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value for <see cref="AuthenticationScheme.Name"/>.
|
||||
/// </summary>
|
||||
public const string AuthenticationScheme = "Gitee";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="AuthenticationScheme.DisplayName"/>.
|
||||
/// </summary>
|
||||
public static readonly string DisplayName = "Gitee";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="AuthenticationSchemeOptions.ClaimsIssuer"/>.
|
||||
/// </summary>
|
||||
public static readonly string Issuer = "Gitee";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="RemoteAuthenticationOptions.CallbackPath"/>.
|
||||
/// </summary>
|
||||
public static readonly string CallbackPath = "/signin-gitee";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="OAuthOptions.AuthorizationEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string AuthorizationEndpoint = "https://gitee.com/oauth/authorize";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="OAuthOptions.TokenEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string TokenEndpoint = "https://gitee.com/oauth/token";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="OAuthOptions.UserInformationEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string UserInformationEndpoint = "https://gitee.com/api/v5/user";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="GiteeAuthenticationOptions.UserEmailsEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string UserEmailsEndpoint = "https://gitee.com/api/v5/emails";
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods to add Gitee authentication capabilities to an HTTP application pipeline.
|
||||
/// </summary>
|
||||
public static class GiteeAuthenticationExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds <see cref="GiteeAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables Gitee authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddGitee([NotNull] this AuthenticationBuilder builder)
|
||||
{
|
||||
return builder.AddGitee(GiteeAuthenticationDefaults.AuthenticationScheme, options => { });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="GiteeAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables Gitee authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <param name="configuration">The delegate used to configure the OpenID 2.0 options.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddGitee(
|
||||
[NotNull] this AuthenticationBuilder builder,
|
||||
[NotNull] Action<GiteeAuthenticationOptions> configuration)
|
||||
{
|
||||
return builder.AddGitee(GiteeAuthenticationDefaults.AuthenticationScheme, configuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="GiteeAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables Gitee authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <param name="scheme">The authentication scheme associated with this instance.</param>
|
||||
/// <param name="configuration">The delegate used to configure the Gitee options.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddGitee(
|
||||
[NotNull] this AuthenticationBuilder builder,
|
||||
[NotNull] string scheme,
|
||||
[NotNull] Action<GiteeAuthenticationOptions> configuration)
|
||||
{
|
||||
return builder.AddGitee(scheme, GiteeAuthenticationDefaults.DisplayName, configuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="GiteeAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables Gitee authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <param name="scheme">The authentication scheme associated with this instance.</param>
|
||||
/// <param name="caption">The optional display name associated with this instance.</param>
|
||||
/// <param name="configuration">The delegate used to configure the Gitee options.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddGitee(
|
||||
[NotNull] this AuthenticationBuilder builder,
|
||||
[NotNull] string scheme,
|
||||
[CanBeNull] string caption,
|
||||
[NotNull] Action<GiteeAuthenticationOptions> configuration)
|
||||
{
|
||||
return builder.AddScheme<GiteeAuthenticationOptions, GiteeAuthenticationHandler>(scheme, caption, configuration);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using static Yi.Framework.AspNetCore.Authentication.OAuth.Gitee.GiteeAuthenticationConstants;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.Gitee
|
||||
{
|
||||
public class GiteeAuthenticationHandler : OauthAuthenticationHandler<GiteeAuthenticationOptions>
|
||||
{
|
||||
public GiteeAuthenticationHandler(IOptionsMonitor<GiteeAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, IHttpClientFactory httpClientFactory) : base(options, logger, encoder, httpClientFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override string AuthenticationSchemeNmae => GiteeAuthenticationDefaults.AuthenticationScheme;
|
||||
|
||||
protected override async Task<List<Claim>> GetAuthTicketAsync(string code)
|
||||
{
|
||||
//获取 accessToken
|
||||
var tokenQueryKv = new List<KeyValuePair<string, string?>>()
|
||||
{
|
||||
new KeyValuePair<string, string?>("grant_type","authorization_code"),
|
||||
new KeyValuePair<string, string?>("client_id",Options.ClientId),
|
||||
new KeyValuePair<string, string?>("client_secret",Options.ClientSecret),
|
||||
new KeyValuePair<string, string?>("redirect_uri",Options.RedirectUri),
|
||||
new KeyValuePair<string, string?>("code",code)
|
||||
};
|
||||
var tokenModel = await SendHttpRequestAsync<GiteeAuthticationcationTokenResponse>(GiteeAuthenticationDefaults.TokenEndpoint, tokenQueryKv,HttpMethod.Post);
|
||||
|
||||
//获取 userInfo
|
||||
var userInfoQueryKv = new List<KeyValuePair<string, string?>>()
|
||||
{
|
||||
new KeyValuePair<string, string?>("access_token",tokenModel.access_token),
|
||||
};
|
||||
var userInfoMdoel = await SendHttpRequestAsync<GiteeAuthticationcationUserInfoResponse>(GiteeAuthenticationDefaults.UserInformationEndpoint, userInfoQueryKv);
|
||||
|
||||
List<Claim> claims = new List<Claim>()
|
||||
{
|
||||
new Claim(Claims.AvatarUrl, userInfoMdoel.avatar_url),
|
||||
new Claim(Claims.Url, userInfoMdoel.url),
|
||||
|
||||
new Claim(AuthenticationConstants.OpenId,userInfoMdoel.id.ToString()),
|
||||
new Claim(AuthenticationConstants.Name, userInfoMdoel.name),
|
||||
new Claim(AuthenticationConstants.AccessToken, tokenModel.access_token)
|
||||
};
|
||||
return claims;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using static Yi.Framework.AspNetCore.Authentication.OAuth.Gitee.GiteeAuthenticationConstants;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a set of options used by <see cref="GiteeAuthenticationHandler"/>.
|
||||
/// </summary>
|
||||
public class GiteeAuthenticationOptions : AuthenticationOAuthOptions
|
||||
{
|
||||
public GiteeAuthenticationOptions()
|
||||
{
|
||||
ClaimsIssuer = GiteeAuthenticationDefaults.Issuer;
|
||||
|
||||
CallbackPath = GiteeAuthenticationDefaults.CallbackPath;
|
||||
|
||||
AuthorizationEndpoint = GiteeAuthenticationDefaults.AuthorizationEndpoint;
|
||||
TokenEndpoint = GiteeAuthenticationDefaults.TokenEndpoint;
|
||||
UserInformationEndpoint = GiteeAuthenticationDefaults.UserInformationEndpoint;
|
||||
UserEmailsEndpoint = GiteeAuthenticationDefaults.UserEmailsEndpoint;
|
||||
|
||||
Scope.Add("user_info");
|
||||
Scope.Add("emails");
|
||||
|
||||
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
|
||||
ClaimActions.MapJsonKey(ClaimTypes.Name, "login");
|
||||
ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
|
||||
ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
|
||||
ClaimActions.MapJsonKey(Claims.Url, "url");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the address of the endpoint exposing
|
||||
/// the email addresses associated with the logged in user.
|
||||
/// </summary>
|
||||
public string UserEmailsEndpoint { get; set; }
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.Gitee
|
||||
{
|
||||
public class GiteeAuthticationcationTokenResponse
|
||||
{
|
||||
public string access_token { get; set; }
|
||||
public string token_type { get; set; }
|
||||
public int expires_in { get; set; }
|
||||
public string refresh_token { get; set; }
|
||||
public string scope { get; set; }
|
||||
public long created_at { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class GiteeAuthticationcationOpenIdResponse
|
||||
{
|
||||
public string client_id { get; set; }
|
||||
|
||||
public string openid { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class GiteeAuthticationcationUserInfoResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// 也可以等于openId
|
||||
/// </summary>
|
||||
public int id { get; set; }
|
||||
public string login { get; set; }
|
||||
public string name { get; set; }
|
||||
public string avatar_url { get; set; }
|
||||
public string url { get; set; }
|
||||
public string html_url { get; set; }
|
||||
public string remark { get; set; }
|
||||
public string followers_url { get; set; }
|
||||
public string following_url { get; set; }
|
||||
public string gists_url { get; set; }
|
||||
public string starred_url { get; set; }
|
||||
public string subscriptions_url { get; set; }
|
||||
public string organizations_url { get; set; }
|
||||
public string repos_url { get; set; }
|
||||
public string events_url { get; set; }
|
||||
public string received_events_url { get; set; }
|
||||
public string type { get; set; }
|
||||
public string blog { get; set; }
|
||||
public string weibo { get; set; }
|
||||
public string bio { get; set; }
|
||||
public int public_repos { get; set; }
|
||||
public int public_gists { get; set; }
|
||||
public int followers { get; set; }
|
||||
public int following { get; set; }
|
||||
public int stared { get; set; }
|
||||
public int watched { get; set; }
|
||||
public DateTime created_at { get; set; }
|
||||
public DateTime updated_at { get; set; }
|
||||
public string email { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
public abstract class OauthAuthenticationHandler<TOptions> : AuthenticationHandler<TOptions> where TOptions : AuthenticationSchemeOptions, new()
|
||||
{
|
||||
public abstract string AuthenticationSchemeNmae { get; }
|
||||
private AuthenticationScheme _scheme;
|
||||
|
||||
public OauthAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, IHttpClientFactory httpClientFactory) : base(options, logger, encoder)
|
||||
{
|
||||
HttpClientFactory = httpClientFactory;
|
||||
HttpClient = HttpClientFactory.CreateClient();
|
||||
}
|
||||
|
||||
|
||||
protected IHttpClientFactory HttpClientFactory { get; }
|
||||
|
||||
protected HttpClient HttpClient { get; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 生成认证票据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private AuthenticationTicket TicketConver(List<Claim> claims)
|
||||
{
|
||||
var claimsIdentity = new ClaimsIdentity(claims.ToArray(), AuthenticationSchemeNmae);
|
||||
var principal = new ClaimsPrincipal(claimsIdentity);
|
||||
return new AuthenticationTicket(principal, AuthenticationSchemeNmae);
|
||||
}
|
||||
|
||||
protected async Task<HttpModel> SendHttpRequestAsync<HttpModel>(string url, IEnumerable<KeyValuePair<string, string?>> query, HttpMethod? httpMethod = null)
|
||||
{
|
||||
httpMethod = httpMethod ?? HttpMethod.Get;
|
||||
|
||||
var queryUrl = QueryHelpers.AddQueryString(url, query);
|
||||
HttpResponseMessage response = null;
|
||||
if (httpMethod == HttpMethod.Get)
|
||||
{
|
||||
response = await HttpClient.GetAsync(queryUrl);
|
||||
}
|
||||
else if (httpMethod == HttpMethod.Post)
|
||||
{
|
||||
response = await HttpClient.PostAsync(queryUrl, null);
|
||||
}
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new Exception($"授权服务器请求错误,请求地址:{queryUrl},错误信息:{content}");
|
||||
}
|
||||
VerifyErrResponse(content);
|
||||
var model = Newtonsoft.Json.JsonConvert.DeserializeObject<HttpModel>(content);
|
||||
return model!;
|
||||
}
|
||||
|
||||
protected virtual void VerifyErrResponse(string content)
|
||||
{
|
||||
AuthticationErrCodeModel.VerifyErrResponse(content);
|
||||
}
|
||||
|
||||
protected abstract Task<List<Claim>> GetAuthTicketAsync(string code);
|
||||
|
||||
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
if (!Context.Request.Query.ContainsKey("code"))
|
||||
{
|
||||
return AuthenticateResult.Fail("回调未包含code参数");
|
||||
}
|
||||
var code = Context.Request.Query["code"].ToString();
|
||||
|
||||
List<Claim> authTicket = null;
|
||||
try
|
||||
{
|
||||
authTicket = await GetAuthTicketAsync(code);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return AuthenticateResult.Fail(ex.Message ?? "未知错误");
|
||||
}
|
||||
//成功
|
||||
var result = AuthenticateResult.Success(TicketConver(authTicket));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
|
||||
|
||||
/// <summary>
|
||||
/// Contains constants specific to the <see cref="QQAuthenticationHandler"/>.
|
||||
/// </summary>
|
||||
public static class QQAuthenticationConstants
|
||||
{
|
||||
public static class Claims
|
||||
{
|
||||
public const string AvatarFullUrl = "urn:qq:avatar_full";
|
||||
public const string AvatarUrl = "urn:qq:avatar";
|
||||
public const string PictureFullUrl = "urn:qq:picture_full";
|
||||
public const string PictureMediumUrl = "urn:qq:picture_medium";
|
||||
public const string PictureUrl = "urn:qq:picture";
|
||||
public const string UnionId = "urn:qq:unionid";
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
|
||||
|
||||
/// <summary>
|
||||
/// Default values for QQ authentication.
|
||||
/// </summary>
|
||||
public static class QQAuthenticationDefaults
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value for <see cref="AuthenticationScheme.Name"/>.
|
||||
/// </summary>
|
||||
public const string AuthenticationScheme = "QQ";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="AuthenticationScheme.DisplayName"/>.
|
||||
/// </summary>
|
||||
public static readonly string DisplayName = "QQ";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="AuthenticationSchemeOptions.ClaimsIssuer"/>.
|
||||
/// </summary>
|
||||
public static readonly string Issuer = "QQ";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="RemoteAuthenticationOptions.CallbackPath"/>.
|
||||
/// </summary>
|
||||
public static readonly string CallbackPath = "/signin-qq";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="OAuthOptions.AuthorizationEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string AuthorizationEndpoint = "https://graph.qq.com/oauth2.0/authorize";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="OAuthOptions.TokenEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string TokenEndpoint = "https://graph.qq.com/oauth2.0/token";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="QQAuthenticationOptions.UserIdentificationEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string UserIdentificationEndpoint = "https://graph.qq.com/oauth2.0/me";
|
||||
|
||||
/// <summary>
|
||||
/// Default value for <see cref="OAuthOptions.UserInformationEndpoint"/>.
|
||||
/// </summary>
|
||||
public static readonly string UserInformationEndpoint = "https://graph.qq.com/user/get_user_info";
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods to add QQ authentication capabilities to an HTTP application pipeline.
|
||||
/// </summary>
|
||||
public static class QQAuthenticationExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds <see cref="QQAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables QQ authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddQQ([NotNull] this AuthenticationBuilder builder)
|
||||
{
|
||||
return builder.AddQQ(QQAuthenticationDefaults.AuthenticationScheme, options => { });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="QQAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables QQ authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <param name="configuration">The delegate used to configure the OpenID 2.0 options.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddQQ(
|
||||
[NotNull] this AuthenticationBuilder builder,
|
||||
[NotNull] Action<QQAuthenticationOptions> configuration)
|
||||
{
|
||||
return builder.AddQQ(QQAuthenticationDefaults.AuthenticationScheme, configuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="QQAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables QQ authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <param name="scheme">The authentication scheme associated with this instance.</param>
|
||||
/// <param name="configuration">The delegate used to configure the QQ options.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddQQ(
|
||||
[NotNull] this AuthenticationBuilder builder,
|
||||
[NotNull] string scheme,
|
||||
[NotNull] Action<QQAuthenticationOptions> configuration)
|
||||
{
|
||||
return builder.AddQQ(scheme, QQAuthenticationDefaults.DisplayName, configuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="QQAuthenticationHandler"/> to the specified
|
||||
/// <see cref="AuthenticationBuilder"/>, which enables QQ authentication capabilities.
|
||||
/// </summary>
|
||||
/// <param name="builder">The authentication builder.</param>
|
||||
/// <param name="scheme">The authentication scheme associated with this instance.</param>
|
||||
/// <param name="caption">The optional display name associated with this instance.</param>
|
||||
/// <param name="configuration">The delegate used to configure the QQ options.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
public static AuthenticationBuilder AddQQ(
|
||||
[NotNull] this AuthenticationBuilder builder,
|
||||
[NotNull] string scheme,
|
||||
[CanBeNull] string caption,
|
||||
[NotNull] Action<QQAuthenticationOptions> configuration)
|
||||
{
|
||||
return builder.AddScheme<QQAuthenticationOptions, QQAuthenticationHandler>(scheme, caption, configuration);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using static Yi.Framework.AspNetCore.Authentication.OAuth.QQ.QQAuthenticationConstants;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.QQ
|
||||
{
|
||||
public class QQAuthenticationHandler : OauthAuthenticationHandler<QQAuthenticationOptions>
|
||||
{
|
||||
public QQAuthenticationHandler(IOptionsMonitor<QQAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, IHttpClientFactory httpClientFactory) : base(options, logger, encoder, httpClientFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override string AuthenticationSchemeNmae => QQAuthenticationDefaults.AuthenticationScheme;
|
||||
|
||||
protected override async Task<List<Claim>> GetAuthTicketAsync(string code)
|
||||
{
|
||||
|
||||
//获取 accessToken
|
||||
var tokenQueryKv = new List<KeyValuePair<string, string?>>()
|
||||
{
|
||||
new KeyValuePair<string, string?>("grant_type","authorization_code"),
|
||||
new KeyValuePair<string, string?>("client_id",Options.ClientId),
|
||||
new KeyValuePair<string, string?>("client_secret",Options.ClientSecret),
|
||||
new KeyValuePair<string, string?>("redirect_uri",Options.RedirectUri),
|
||||
new KeyValuePair<string, string?>("fmt","json"),
|
||||
new KeyValuePair<string, string?>("need_openid","1"),
|
||||
new KeyValuePair<string, string?>("code",code)
|
||||
};
|
||||
var tokenModel = await SendHttpRequestAsync<QQAuthticationcationTokenResponse>(QQAuthenticationDefaults.TokenEndpoint, tokenQueryKv);
|
||||
|
||||
|
||||
|
||||
//获取 userInfo
|
||||
var userInfoQueryKv = new List<KeyValuePair<string, string?>>()
|
||||
{
|
||||
new KeyValuePair<string, string?>("access_token",tokenModel.access_token),
|
||||
new KeyValuePair<string, string?>("oauth_consumer_key",Options.ClientId),
|
||||
new KeyValuePair<string, string?>("openid",tokenModel.openid),
|
||||
};
|
||||
|
||||
var userInfoMdoel = await SendHttpRequestAsync<QQAuthticationcationUserInfoResponse>(QQAuthenticationDefaults.UserInformationEndpoint, userInfoQueryKv);
|
||||
|
||||
|
||||
List<Claim> claims = new List<Claim>()
|
||||
{
|
||||
|
||||
new Claim(Claims.AvatarFullUrl, userInfoMdoel.figureurl_qq_2),
|
||||
new Claim(Claims.AvatarUrl, userInfoMdoel.figureurl_qq_1),
|
||||
new Claim(Claims.PictureFullUrl, userInfoMdoel.figureurl_2),
|
||||
new Claim(Claims.PictureMediumUrl, userInfoMdoel.figureurl_qq_1),
|
||||
new Claim(Claims.PictureUrl, userInfoMdoel.figureurl),
|
||||
|
||||
new Claim(AuthenticationConstants.OpenId, tokenModel.openid),
|
||||
new Claim(AuthenticationConstants.Name, userInfoMdoel.nickname),
|
||||
new Claim(AuthenticationConstants.AccessToken, tokenModel.access_token),
|
||||
|
||||
};
|
||||
return claims;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
|
||||
* for more information concerning the license and the contributors participating to this project.
|
||||
*/
|
||||
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using static Yi.Framework.AspNetCore.Authentication.OAuth.QQ.QQAuthenticationConstants;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a set of options used by <see cref="QQAuthenticationHandler"/>.
|
||||
/// </summary>
|
||||
public class QQAuthenticationOptions : AuthenticationOAuthOptions
|
||||
{
|
||||
public QQAuthenticationOptions()
|
||||
{
|
||||
ClaimsIssuer = QQAuthenticationDefaults.Issuer;
|
||||
CallbackPath = QQAuthenticationDefaults.CallbackPath;
|
||||
|
||||
AuthorizationEndpoint = QQAuthenticationDefaults.AuthorizationEndpoint;
|
||||
TokenEndpoint = QQAuthenticationDefaults.TokenEndpoint;
|
||||
UserIdentificationEndpoint = QQAuthenticationDefaults.UserIdentificationEndpoint;
|
||||
UserInformationEndpoint = QQAuthenticationDefaults.UserInformationEndpoint;
|
||||
|
||||
Scope.Add("get_user_info");
|
||||
|
||||
ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
|
||||
ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender");
|
||||
ClaimActions.MapJsonKey(Claims.PictureUrl, "figureurl");
|
||||
ClaimActions.MapJsonKey(Claims.PictureMediumUrl, "figureurl_1");
|
||||
ClaimActions.MapJsonKey(Claims.PictureFullUrl, "figureurl_2");
|
||||
ClaimActions.MapJsonKey(Claims.AvatarUrl, "figureurl_qq_1");
|
||||
ClaimActions.MapJsonKey(Claims.AvatarFullUrl, "figureurl_qq_2");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the union Id (the primary key of an owner for different apps of the QQ platform) should be put into the user claims.
|
||||
/// </summary>
|
||||
public bool ApplyForUnionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the URL of the user identification endpoint (a.k.a. the "OpenID endpoint").
|
||||
/// </summary>
|
||||
public string UserIdentificationEndpoint { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth.QQ
|
||||
{
|
||||
public class QQAuthticationcationTokenResponse
|
||||
{
|
||||
public string access_token { get; set; }
|
||||
|
||||
public string expires_in { get; set; }
|
||||
|
||||
public string refresh_token { get; set; }
|
||||
|
||||
public string openid { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class QQAuthticationcationOpenIdResponse
|
||||
{
|
||||
public string client_id { get; set; }
|
||||
|
||||
public string openid { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class QQAuthticationcationUserInfoResponse
|
||||
{
|
||||
// 返回码
|
||||
public int ret { get; set; }
|
||||
|
||||
// 如果ret<0,会有相应的错误信息提示
|
||||
// 返回数据全部用UTF-8编码
|
||||
public string msg { get; set; }
|
||||
|
||||
// 判断是否有数据丢失
|
||||
// 0或者不返回:没有数据丢失,可以缓存
|
||||
// 1:有部分数据丢失或错误,不要缓存
|
||||
public int is_lost { get; set; }
|
||||
|
||||
// 用户在QQ空间的昵称
|
||||
public string nickname { get; set; }
|
||||
|
||||
// 大小为30x30像素的QQ空间头像URL
|
||||
public string figureurl { get; set; }
|
||||
|
||||
// 大小为50x50像素的QQ空间头像URL
|
||||
public string figureurl_1 { get; set; }
|
||||
|
||||
// 大小为100x100像素的QQ空间头像URL
|
||||
public string figureurl_2 { get; set; }
|
||||
|
||||
// 大小为40x40像素的QQ头像URL
|
||||
public string figureurl_qq_1 { get; set; }
|
||||
|
||||
// 大小为100x100像素的QQ头像URL
|
||||
// 需要注意,不是所有的用户都拥有QQ的100x100的头像,但40x40像素则是一定会有
|
||||
public string figureurl_qq_2 { get; set; }
|
||||
|
||||
// 性别。如果获取不到则默认返回"男"
|
||||
public string gender { get; set; }
|
||||
|
||||
// 性别类型。默认返回2
|
||||
public int gender_type { get; set; }
|
||||
|
||||
// 省
|
||||
public string province { get; set; }
|
||||
|
||||
// 市
|
||||
public string city { get; set; }
|
||||
|
||||
// 年
|
||||
public int year { get; set; }
|
||||
|
||||
// 星座
|
||||
public string constellation { get; set; }
|
||||
|
||||
// 标识用户是否为黄钻用户
|
||||
public int is_yellow_vip { get; set; }
|
||||
|
||||
// 黄钻等级
|
||||
public int yellow_vip_level { get; set; }
|
||||
|
||||
// 是否为年费黄钻用户
|
||||
public int is_yellow_year_vip { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.AspNetCore\Yi.Framework.AspNetCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,20 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.Core;
|
||||
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// 本模块轮子来自 AspNet.Security.OAuth.QQ;
|
||||
/// </summary>
|
||||
[DependsOn(typeof(YiFrameworkAspNetCoreModule))]
|
||||
public class YiFrameworkAspNetCoreAuthenticationOAuthModule:AbpModule
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
var service = context.Services;
|
||||
service.AddHttpClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Middlewares;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder
|
||||
{
|
||||
public static class ApiInfoBuilderExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseYiApiHandlinge([NotNull] this IApplicationBuilder app)
|
||||
{
|
||||
app.UseMiddleware<ApiInfoMiddleware>();
|
||||
return app;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder
|
||||
{
|
||||
public static class SwaggerBuilderExtensons
|
||||
{
|
||||
public static IApplicationBuilder UseYiSwagger(this IApplicationBuilder app, params SwaggerModel[] swaggerModels)
|
||||
{
|
||||
var mvcOptions = app.ApplicationServices.GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>().Value;
|
||||
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
foreach (var setting in mvcOptions.ConventionalControllers.ConventionalControllerSettings)
|
||||
{
|
||||
c.SwaggerEndpoint($"/swagger/{setting.RemoteServiceName}/swagger.json", setting.RemoteServiceName);
|
||||
}
|
||||
if (mvcOptions.ConventionalControllers.ConventionalControllerSettings.Count==0&&swaggerModels.Length == 0)
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Yi.Framework");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var k in swaggerModels)
|
||||
{
|
||||
c.SwaggerEndpoint(k.Url, k.Name);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
return app;
|
||||
}
|
||||
|
||||
}
|
||||
public class SwaggerModel
|
||||
{
|
||||
public SwaggerModel(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Url = "/swagger/v1/swagger.json";
|
||||
}
|
||||
public SwaggerModel(string url, string name)
|
||||
{
|
||||
this.Url = url;
|
||||
this.Name = name;
|
||||
}
|
||||
public string Url { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Json;
|
||||
using Yi.Framework.Core.Extensions;
|
||||
using static System.Net.WebRequestMethods;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Microsoft.AspNetCore.Middlewares
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
public class ApiInfoMiddleware : IMiddleware, ITransientDependency
|
||||
{
|
||||
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
context.Response.OnStarting([DebuggerStepThrough] () =>
|
||||
{
|
||||
if (context.Response.StatusCode == StatusCodes.Status200OK
|
||||
&& context.Response.Headers["Content-Type"].ToString() == "application/vnd.ms-excel")
|
||||
{
|
||||
context.FileAttachmentHandle($"{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}.xlsx");
|
||||
}
|
||||
if (context.Response.StatusCode == StatusCodes.Status200OK &&
|
||||
context.Response.Headers["Content-Type"].ToString() == "application/x-zip-compressed")
|
||||
{
|
||||
context.FileAttachmentHandle($"{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}.zip");
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
await next(context);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class SwaggerAddExtensions
|
||||
{
|
||||
public static IServiceCollection AddYiSwaggerGen<Program>(this IServiceCollection services, Action<SwaggerGenOptions>? action=null)
|
||||
{
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
var mvcOptions = serviceProvider.GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>();
|
||||
|
||||
var mvcSettings = mvcOptions.Value.ConventionalControllers.ConventionalControllerSettings.DistinctBy(x => x.RemoteServiceName);
|
||||
|
||||
|
||||
services.AddAbpSwaggerGen(
|
||||
options =>
|
||||
{
|
||||
if (action is not null)
|
||||
{
|
||||
action.Invoke(options);
|
||||
}
|
||||
|
||||
// 配置分组,还需要去重,支持重写,如果外部传入后,将以外部为准
|
||||
foreach (var setting in mvcSettings.OrderBy(x => x.RemoteServiceName))
|
||||
{
|
||||
if (!options.SwaggerGeneratorOptions.SwaggerDocs.ContainsKey(setting.RemoteServiceName))
|
||||
{
|
||||
options.SwaggerDoc(setting.RemoteServiceName, new OpenApiInfo { Title = setting.RemoteServiceName, Version = "v1" });
|
||||
}
|
||||
}
|
||||
|
||||
// 根据分组名称过滤 API 文档
|
||||
options.DocInclusionPredicate((docName, apiDesc) =>
|
||||
{
|
||||
if (apiDesc.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
|
||||
{
|
||||
var settingOrNull = mvcSettings.Where(x => x.Assembly == controllerActionDescriptor.ControllerTypeInfo.Assembly).FirstOrDefault();
|
||||
if (settingOrNull is not null)
|
||||
{
|
||||
return docName == settingOrNull.RemoteServiceName;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
options.CustomSchemaIds(type => type.FullName);
|
||||
var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
|
||||
if (basePath is not null)
|
||||
{
|
||||
foreach (var item in Directory.GetFiles(basePath, "*.xml"))
|
||||
{
|
||||
options.IncludeXmlComments(item, true);
|
||||
}
|
||||
}
|
||||
|
||||
options.AddSecurityDefinition("JwtBearer", new OpenApiSecurityScheme()
|
||||
{
|
||||
Description = "直接输入Token即可",
|
||||
Name = "Authorization",
|
||||
In = ParameterLocation.Header,
|
||||
Type = SecuritySchemeType.Http,
|
||||
Scheme = "bearer"
|
||||
});
|
||||
var scheme = new OpenApiSecurityScheme()
|
||||
{
|
||||
Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "JwtBearer" }
|
||||
};
|
||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
|
||||
{
|
||||
[scheme] = new string[0]
|
||||
});
|
||||
|
||||
options.OperationFilter<AddRequiredHeaderParameter>();
|
||||
options.SchemaFilter<EnumSchemaFilter>();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Swagger文档枚举字段显示枚举属性和枚举值,以及枚举描述
|
||||
/// </summary>
|
||||
public class EnumSchemaFilter : ISchemaFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现接口
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <param name="context"></param>
|
||||
|
||||
public void Apply(OpenApiSchema model, SchemaFilterContext context)
|
||||
{
|
||||
if (context.Type.IsEnum)
|
||||
{
|
||||
model.Enum.Clear();
|
||||
model.Type = "string";
|
||||
model.Format = null;
|
||||
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Enum.GetNames(context.Type)
|
||||
.ToList()
|
||||
.ForEach(name =>
|
||||
{
|
||||
Enum e = (Enum)Enum.Parse(context.Type, name);
|
||||
var descrptionOrNull = GetEnumDescription(e);
|
||||
model.Enum.Add(new OpenApiString(name));
|
||||
stringBuilder.Append($"【枚举:{name}{(descrptionOrNull is null ? string.Empty : $"({descrptionOrNull})")}={Convert.ToInt64(Enum.Parse(context.Type, name))}】<br />");
|
||||
});
|
||||
model.Description= stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetEnumDescription(Enum value)
|
||||
{
|
||||
var fieldInfo = value.GetType().GetField(value.ToString());
|
||||
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
return attributes.Length > 0 ? attributes[0].Description : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class AddRequiredHeaderParameter : IOperationFilter
|
||||
{
|
||||
public static string HeaderKey { get; set; } = "__tenant";
|
||||
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||
{
|
||||
if (operation.Parameters == null)
|
||||
operation.Parameters = new List<OpenApiParameter>();
|
||||
operation.Parameters.Add(new OpenApiParameter
|
||||
{
|
||||
Name = HeaderKey,
|
||||
In = ParameterLocation.Header,
|
||||
Required = false,
|
||||
AllowEmptyValue = true,
|
||||
Description="租户id或者租户名称(可空为默认租户)"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.AspNetCore.Mvc.Conventions;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Reflection;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Mvc
|
||||
{
|
||||
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
|
||||
[ExposeServices(typeof(IConventionalRouteBuilder))]
|
||||
public class YiConventionalRouteBuilder : ConventionalRouteBuilder
|
||||
{
|
||||
public YiConventionalRouteBuilder(IOptions<AbpConventionalControllerOptions> options) : base(options)
|
||||
{
|
||||
}
|
||||
public override string Build(
|
||||
string rootPath,
|
||||
string controllerName,
|
||||
ActionModel action,
|
||||
string httpMethod,
|
||||
[CanBeNull] ConventionalControllerSetting configuration)
|
||||
{
|
||||
|
||||
var apiRoutePrefix = GetApiRoutePrefix(action, configuration);
|
||||
var controllerNameInUrl =
|
||||
NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration);
|
||||
|
||||
var url = $"{rootPath}/{NormalizeControllerNameCase(controllerNameInUrl, configuration)}";
|
||||
|
||||
//Add {id} path if needed
|
||||
var idParameterModel = action.Parameters.FirstOrDefault(p => p.ParameterName == "id");
|
||||
if (idParameterModel != null)
|
||||
{
|
||||
if (TypeHelper.IsPrimitiveExtended(idParameterModel.ParameterType, includeEnums: true))
|
||||
{
|
||||
url += "/{id}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var properties = idParameterModel
|
||||
.ParameterType
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
url += "/{" + NormalizeIdPropertyNameCase(property, configuration) + "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add action name if needed
|
||||
var actionNameInUrl = NormalizeUrlActionName(rootPath, controllerName, action, httpMethod, configuration);
|
||||
if (!actionNameInUrl.IsNullOrEmpty())
|
||||
{
|
||||
url += $"/{NormalizeActionNameCase(actionNameInUrl, configuration)}";
|
||||
|
||||
//Add secondary Id
|
||||
var secondaryIds = action.Parameters
|
||||
.Where(p => p.ParameterName.EndsWith("Id", StringComparison.Ordinal)).ToList();
|
||||
if (secondaryIds.Count == 1)
|
||||
{
|
||||
url += $"/{{{NormalizeSecondaryIdNameCase(secondaryIds[0], configuration)}}}";
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.AspNetCore;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.AspNetCore.Mvc.Conventions;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Reflection;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Mvc
|
||||
{
|
||||
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
|
||||
[ExposeServices(typeof(IAbpServiceConvention))]
|
||||
public class YiServiceConvention : AbpServiceConvention
|
||||
{
|
||||
public YiServiceConvention(IOptions<AbpAspNetCoreMvcOptions> options, IConventionalRouteBuilder conventionalRouteBuilder) : base(options, conventionalRouteBuilder)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ConfigureSelector(string rootPath, string controllerName, ActionModel action, ConventionalControllerSetting? configuration)
|
||||
{
|
||||
RemoveEmptySelectors(action.Selectors);
|
||||
|
||||
var remoteServiceAtt = ReflectionHelper.GetSingleAttributeOrDefault<RemoteServiceAttribute>(action.ActionMethod);
|
||||
if (remoteServiceAtt != null && !remoteServiceAtt.IsEnabledFor(action.ActionMethod))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!action.Selectors.Any())
|
||||
{
|
||||
AddAbpServiceSelector(rootPath, controllerName, action, configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
NormalizeSelectorRoutes(rootPath, controllerName, action, configuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void AddAbpServiceSelector(string rootPath, string controllerName, ActionModel action, ConventionalControllerSetting? configuration)
|
||||
{
|
||||
base.AddAbpServiceSelector(rootPath, controllerName, action, configuration);
|
||||
}
|
||||
|
||||
protected override void NormalizeSelectorRoutes(string rootPath, string controllerName, ActionModel action, ConventionalControllerSetting? configuration)
|
||||
{
|
||||
foreach (var selector in action.Selectors)
|
||||
{
|
||||
var httpMethod = selector.ActionConstraints
|
||||
.OfType<HttpMethodActionConstraint>()
|
||||
.FirstOrDefault()?
|
||||
.HttpMethods?
|
||||
.FirstOrDefault();
|
||||
|
||||
if (httpMethod == null)
|
||||
{
|
||||
httpMethod = SelectHttpMethod(action, configuration);
|
||||
}
|
||||
|
||||
if (selector.AttributeRouteModel == null)
|
||||
{
|
||||
selector.AttributeRouteModel = CreateAbpServiceAttributeRouteModel(rootPath, controllerName, action, httpMethod, configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var template = selector.AttributeRouteModel.Template;
|
||||
if (!template.StartsWith("/"))
|
||||
{
|
||||
var route = $"{rootPath}/{template}";
|
||||
selector.AttributeRouteModel.Template = route;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!selector.ActionConstraints.OfType<HttpMethodActionConstraint>().Any())
|
||||
{
|
||||
selector.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { httpMethod }));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
namespace Yi.Framework.AspNetCore
|
||||
{
|
||||
[Serializable]
|
||||
public class RemoteServiceSuccessInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RemoteServiceSuccessInfo"/>.
|
||||
/// </summary>
|
||||
public RemoteServiceSuccessInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RemoteServiceSuccessInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="code">Error code</param>
|
||||
/// <param name="details">Error details</param>
|
||||
/// <param name="message">Error message</param>
|
||||
/// <param name="data">Error data</param>
|
||||
public RemoteServiceSuccessInfo(string message, string? details = null, string? code = null, object? data = null)
|
||||
{
|
||||
Message = message;
|
||||
Details = details;
|
||||
Code = code;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// code.
|
||||
/// </summary>
|
||||
public string? Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// message.
|
||||
/// </summary>
|
||||
public string? Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// details.
|
||||
/// </summary>
|
||||
public string? Details { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// data.
|
||||
/// </summary>
|
||||
public object? Data { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Cors\**" />
|
||||
<EmbeddedResource Remove="Cors\**" />
|
||||
<None Remove="Cors\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Volo.Abp.Json" Version="$(AbpVersion)" />
|
||||
<PackageReference Include="Volo.Abp.Swashbuckle" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.Core\Yi.Framework.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.AspNetCore.Mvc;
|
||||
using Yi.Framework.Core;
|
||||
|
||||
namespace Yi.Framework.AspNetCore
|
||||
{
|
||||
[DependsOn(typeof(YiFrameworkCoreModule)
|
||||
)]
|
||||
public class YiFrameworkAspNetCoreModule : AbpModule
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FreeRedis;
|
||||
|
||||
namespace Yi.Framework.Caching.FreeRedis
|
||||
{
|
||||
/// <summary>
|
||||
/// 便于转到定义
|
||||
/// </summary>
|
||||
public class FreeSqlOptions: ConnectionStringBuilder
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FreeRedis" Version="1.2.14" />
|
||||
<PackageReference Include="FreeRedis.DistributedCache" Version="1.2.5" />
|
||||
<PackageReference Include="Volo.Abp.Caching" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.Caching;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.MultiTenancy;
|
||||
|
||||
namespace Yi.Framework.Caching.FreeRedis
|
||||
{
|
||||
[Dependency(ReplaceServices =true)]
|
||||
public class YiDistributedCacheKeyNormalizer : IDistributedCacheKeyNormalizer, ITransientDependency
|
||||
{
|
||||
protected ICurrentTenant CurrentTenant { get; }
|
||||
|
||||
protected AbpDistributedCacheOptions DistributedCacheOptions { get; }
|
||||
|
||||
public YiDistributedCacheKeyNormalizer(
|
||||
ICurrentTenant currentTenant,
|
||||
IOptions<AbpDistributedCacheOptions> distributedCacheOptions)
|
||||
{
|
||||
CurrentTenant = currentTenant;
|
||||
DistributedCacheOptions = distributedCacheOptions.Value;
|
||||
}
|
||||
|
||||
public virtual string NormalizeKey(DistributedCacheKeyNormalizeArgs args)
|
||||
{
|
||||
var normalizedKey = $"{DistributedCacheOptions.KeyPrefix}{args.Key}";
|
||||
|
||||
//if (!args.IgnoreMultiTenancy && CurrentTenant.Id.HasValue)
|
||||
//{
|
||||
// normalizedKey = $"t:{CurrentTenant.Id.Value},{normalizedKey}";
|
||||
//}
|
||||
|
||||
return normalizedKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using FreeRedis;
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Volo.Abp.Caching;
|
||||
|
||||
namespace Yi.Framework.Caching.FreeRedis
|
||||
{
|
||||
/// <summary>
|
||||
/// 此模块得益于FreeRedis作者支持IDistributedCache,使用湿滑
|
||||
/// </summary>
|
||||
[DependsOn(typeof(AbpCachingModule))]
|
||||
public class YiFrameworkCachingFreeRedisModule : AbpModule
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
|
||||
var configuration = context.Services.GetConfiguration();
|
||||
|
||||
var redisEnabled = configuration["Redis:IsEnabled"];
|
||||
if (redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled))
|
||||
{
|
||||
var redisConfiguration = configuration["Redis:Configuration"];
|
||||
RedisClient redisClient = new RedisClient(redisConfiguration);
|
||||
|
||||
context.Services.AddSingleton<IRedisClient>(redisClient);
|
||||
context.Services.Replace(ServiceDescriptor.Singleton<IDistributedCache>(new
|
||||
DistributedCache(redisClient)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Modularity;
|
||||
|
||||
namespace Yi.Framework.Core.Modularity;
|
||||
|
||||
[Dependency(ReplaceServices =true)]
|
||||
public class YiModuleManager : ModuleManager, IModuleManager, ISingletonDependency
|
||||
{
|
||||
private readonly IModuleContainer _moduleContainer;
|
||||
private readonly IEnumerable<IModuleLifecycleContributor> _lifecycleContributors;
|
||||
private readonly ILogger<YiModuleManager> _logger;
|
||||
|
||||
public YiModuleManager(IModuleContainer moduleContainer, ILogger<YiModuleManager> logger, IOptions<AbpModuleLifecycleOptions> options, IServiceProvider serviceProvider) : base(moduleContainer, logger, options, serviceProvider)
|
||||
{
|
||||
_moduleContainer = moduleContainer;
|
||||
_logger = logger;
|
||||
_lifecycleContributors = options.Value.Contributors.Select(serviceProvider.GetRequiredService).Cast<IModuleLifecycleContributor>().ToArray();
|
||||
}
|
||||
|
||||
public override async Task InitializeModulesAsync(ApplicationInitializationContext context)
|
||||
{
|
||||
|
||||
_logger.LogDebug("==========模块Initialize初始化统计-跳过0ms模块==========");
|
||||
var total = 0;
|
||||
var watch =new Stopwatch();
|
||||
long totalTime = 0;
|
||||
foreach (var contributor in _lifecycleContributors)
|
||||
{
|
||||
foreach (var module in _moduleContainer.Modules)
|
||||
{
|
||||
try
|
||||
{
|
||||
watch.Restart();
|
||||
await contributor.InitializeAsync(context, module.Instance);
|
||||
watch.Stop();
|
||||
totalTime += watch.ElapsedMilliseconds;
|
||||
total++;
|
||||
if (watch.ElapsedMilliseconds > 1)
|
||||
{
|
||||
_logger.LogDebug($"耗时-{watch.ElapsedMilliseconds}ms,已加载模块-{module.Assembly.GetName().Name}");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation($"==========【{total}】个模块初始化执行完毕,总耗时【{totalTime}ms】==========");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Volo.Abp.Core" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,9 +0,0 @@
|
||||
using Volo.Abp.Modularity;
|
||||
|
||||
namespace Yi.Framework.Core
|
||||
{
|
||||
public class YiFrameworkCoreModule:AbpModule
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Services;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application.Contracts
|
||||
{
|
||||
public interface IDeletesAppService<in TKey> : IDeleteAppService< TKey> , IApplicationService, IRemoteService
|
||||
{
|
||||
Task DeleteAsync(IEnumerable<TKey> ids);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application.Contracts
|
||||
{
|
||||
public interface IPageTimeResultRequestDto : IPagedAndSortedResultRequest
|
||||
{
|
||||
DateTime? StartTime { get; set; }
|
||||
DateTime? EndTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application.Contracts
|
||||
{
|
||||
public interface IPagedAllResultRequestDto : IPageTimeResultRequestDto, IPagedAndSortedResultRequest
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Application.Services;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application.Contracts
|
||||
{
|
||||
public interface IYiCrudAppService<TEntityDto, in TKey> : ICrudAppService<TEntityDto, TKey>
|
||||
{
|
||||
}
|
||||
|
||||
public interface IYiCrudAppService<TEntityDto, in TKey, in TGetListInput> : ICrudAppService<TEntityDto, TKey, TGetListInput>
|
||||
{
|
||||
}
|
||||
|
||||
public interface IYiCrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput> : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput>
|
||||
{
|
||||
}
|
||||
|
||||
public interface IYiCrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput, in TUpdateInput> : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
{
|
||||
}
|
||||
|
||||
public interface IYiCrudAppService<TGetOutputDto, TGetListOutputDto, in TKey, in TGetListInput, in TCreateInput, in TUpdateInput> : ICrudAppService<TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>, IDeletesAppService<TKey>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application.Contracts
|
||||
{
|
||||
public class PagedAllResultRequestDto : PagedAndSortedResultRequestDto, IPagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 查询开始时间条件
|
||||
/// </summary>
|
||||
public DateTime? StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询结束时间条件
|
||||
/// </summary>
|
||||
public DateTime? EndTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.Core\Yi.Framework.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,10 +0,0 @@
|
||||
using Volo.Abp.Application;
|
||||
using Volo.Abp.Modularity;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application.Contracts
|
||||
{
|
||||
[DependsOn(typeof(AbpDddApplicationContractsModule))]
|
||||
public class YiFrameworkDddApplicationContractsModule : AbpModule
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MiniExcel" Version="1.31.3" />
|
||||
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.Ddd.Application.Contracts\Yi.Framework.Ddd.Application.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,119 +0,0 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Caching;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.MultiTenancy;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application
|
||||
{
|
||||
public abstract class YiCacheCrudAppService<TEntity, TEntityDto, TKey> : YiCrudAppService<TEntity, TEntityDto, TKey, PagedAndSortedResultRequestDto>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCacheCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class YiCacheCrudAppService<TEntity, TEntityDto, TKey, TGetListInput>
|
||||
: YiCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TEntityDto>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCacheCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract class YiCacheCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TCreateInput>
|
||||
: YiCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TCreateInput, TCreateInput>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCacheCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class YiCacheCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
: YiCrudAppService<TEntity, TEntityDto, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCacheCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract class YiCacheCrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
: YiCrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TGetOutputDto : IEntityDto<TKey>
|
||||
where TGetListOutputDto : IEntityDto<TKey>
|
||||
{
|
||||
protected IDistributedCache<TEntity> Cache => LazyServiceProvider.LazyGetRequiredService<IDistributedCache<TEntity>>();
|
||||
|
||||
protected string GetCacheKey(TKey id) => typeof(TEntity).Name + ":" + CurrentTenant.Id ?? Guid.Empty + ":" + id.ToString();
|
||||
protected YiCacheCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<TGetOutputDto> UpdateAsync(TKey id, TUpdateInput input)
|
||||
{
|
||||
var output = await base.UpdateAsync(id, input);
|
||||
await Cache.RemoveAsync(GetCacheKey(id));
|
||||
return output;
|
||||
}
|
||||
|
||||
public override async Task<PagedResultDto<TGetListOutputDto>> GetListAsync(TGetListInput input)
|
||||
{
|
||||
//两种方式:
|
||||
//1:全表缓存,使用缓存直接查询
|
||||
//2:非全部缓存,查询到的数据直接添加到缓存
|
||||
|
||||
//判断是否该实体为全表缓存
|
||||
throw new NotImplementedException();
|
||||
|
||||
//IDistributedCache 有局限性,条件查询无法进行缓存了
|
||||
//if (true)
|
||||
//{
|
||||
// return await GetListByCacheAsync(input);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// return await GetListByDbAsync(input);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
protected virtual async Task<PagedResultDto<TGetListOutputDto>> GetListByDbAsync(TGetListInput input)
|
||||
{
|
||||
//如果不是全表缓存,可以走这个啦
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
protected virtual async Task<PagedResultDto<TGetListOutputDto>> GetListByCacheAsync(TGetListInput input)
|
||||
{
|
||||
//如果是全表缓存,可以走这个啦
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
protected override async Task<TEntity> GetEntityByIdAsync(TKey id)
|
||||
{
|
||||
var output = await Cache.GetOrAddAsync(GetCacheKey(id), async () => await base.GetEntityByIdAsync(id));
|
||||
return output!;
|
||||
}
|
||||
|
||||
public override async Task DeleteAsync(IEnumerable<TKey> id)
|
||||
{
|
||||
await base.DeleteAsync(id);
|
||||
foreach (var itemId in id)
|
||||
{
|
||||
await Cache.RemoveAsync(GetCacheKey(itemId));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MiniExcelLibs;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application
|
||||
{
|
||||
public abstract class YiCrudAppService<TEntity, TEntityDto, TKey> : YiCrudAppService<TEntity, TEntityDto, TKey, PagedAndSortedResultRequestDto>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class YiCrudAppService<TEntity, TEntityDto, TKey, TGetListInput>
|
||||
: YiCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TEntityDto>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract class YiCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TCreateInput>
|
||||
: YiCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TCreateInput, TCreateInput>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class YiCrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
: YiCrudAppService<TEntity, TEntityDto, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TEntityDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract class YiCrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
: CrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TGetOutputDto : IEntityDto<TKey>
|
||||
where TGetListOutputDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 多查
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<PagedResultDto<TGetListOutputDto>> GetListAsync(TGetListInput input)
|
||||
{
|
||||
List<TEntity>? entites = null;
|
||||
//区分多查还是批量查
|
||||
if (input is IPagedResultRequest pagedInput)
|
||||
{
|
||||
entites = await Repository.GetPagedListAsync(pagedInput.SkipCount, pagedInput.MaxResultCount, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
entites = await Repository.GetListAsync();
|
||||
}
|
||||
var total = await Repository.GetCountAsync();
|
||||
var output = await MapToGetListOutputDtosAsync(entites);
|
||||
return new PagedResultDto<TGetListOutputDto>(total, output);
|
||||
//throw new NotImplementedException($"【{typeof(TEntity)}】实体的CrudAppService,查询为具体业务,通用查询几乎无实际场景,请重写实现!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 多删
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[RemoteService(isEnabled: true)]
|
||||
public virtual async Task DeleteAsync(IEnumerable<TKey> id)
|
||||
{
|
||||
await Repository.DeleteManyAsync(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 偷梁换柱
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[RemoteService(isEnabled: false)]
|
||||
public override Task DeleteAsync(TKey id)
|
||||
{
|
||||
return base.DeleteAsync(id);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 导出excel
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IActionResult> GetExportExcelAsync(TGetListInput input)
|
||||
{
|
||||
if (input is IPagedResultRequest paged)
|
||||
{
|
||||
paged.SkipCount = 0;
|
||||
paged.MaxResultCount = LimitedResultRequestDto.MaxMaxResultCount;
|
||||
}
|
||||
|
||||
var output = await this.GetListAsync(input);
|
||||
var dirPath = $"/wwwroot/temp";
|
||||
|
||||
var fileName = $"{typeof(TEntity).Name}_{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}_{Guid.NewGuid()}";
|
||||
var filePath = $"{dirPath}/{fileName}.xlsx";
|
||||
if (!Directory.Exists(dirPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirPath);
|
||||
}
|
||||
|
||||
MiniExcel.SaveAs(filePath, output.Items);
|
||||
return new PhysicalFileResult(filePath, "application/vnd.ms-excel");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入excle
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task PostImportExcelAsync(List<TCreateInput> input)
|
||||
{
|
||||
var entities = input.Select(x => MapToEntity(x)).ToList();
|
||||
//安全起见,该接口需要自己实现
|
||||
throw new NotImplementedException();
|
||||
//await Repository.DeleteManyAsync(entities.Select(x => x.Id));
|
||||
//await Repository.InsertManyAsync(entities);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application
|
||||
{
|
||||
[DependsOn(typeof(AbpDddApplicationModule),
|
||||
typeof(YiFrameworkDddApplicationContractsModule))]
|
||||
public class YiFrameworkDddApplicationModule : AbpModule
|
||||
{
|
||||
public override void OnApplicationInitialization(ApplicationInitializationContext context)
|
||||
{
|
||||
//分页限制
|
||||
LimitedResultRequestDto.DefaultMaxResultCount = 10;
|
||||
LimitedResultRequestDto.MaxMaxResultCount = 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Mapster;
|
||||
using Volo.Abp.ObjectMapping;
|
||||
|
||||
namespace Yi.Framework.Mapster
|
||||
{
|
||||
public class MapsterAutoObjectMappingProvider : IAutoObjectMappingProvider
|
||||
{
|
||||
public TDestination Map<TSource, TDestination>(object source)
|
||||
{
|
||||
var sss = typeof(TDestination).Name;
|
||||
return source.Adapt<TDestination>();
|
||||
}
|
||||
|
||||
public TDestination Map<TSource, TDestination>(TSource source, TDestination destination)
|
||||
{
|
||||
return source.Adapt<TSource, TDestination>(destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.ObjectMapping;
|
||||
|
||||
namespace Yi.Framework.Mapster
|
||||
{
|
||||
public class MapsterObjectMapper : IObjectMapper
|
||||
{
|
||||
public IAutoObjectMappingProvider AutoObjectMappingProvider => throw new NotImplementedException();
|
||||
|
||||
public TDestination Map<TSource, TDestination>(TSource source)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TDestination Map<TSource, TDestination>(TSource source, TDestination destination)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||
<PackageReference Include="Volo.Abp.ObjectMapping" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.Core\Yi.Framework.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,21 +0,0 @@
|
||||
using MapsterMapper;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Volo.Abp.Modularity;
|
||||
using Volo.Abp.ObjectMapping;
|
||||
using Yi.Framework.Core;
|
||||
|
||||
namespace Yi.Framework.Mapster
|
||||
{
|
||||
[DependsOn(typeof(YiFrameworkCoreModule),
|
||||
|
||||
typeof(AbpObjectMappingModule)
|
||||
)]
|
||||
public class YiFrameworkMapsterModule : AbpModule
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
context.Services.AddTransient<IAutoObjectMappingProvider, MapsterAutoObjectMappingProvider>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class DefaultTenantTableAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
{
|
||||
public interface ISqlSugarDbConnectionCreator
|
||||
{
|
||||
DbConnOptions Options { get; }
|
||||
Action<ISqlSugarClient> OnSqlSugarClientConfig { get; set; }
|
||||
Action<object, DataAfterModel> DataExecuted { get; set; }
|
||||
Action<object, DataFilterModel> DataExecuting { get; set; }
|
||||
Action<string, SugarParameter[]> OnLogExecuting { get; set; }
|
||||
Action<string, SugarParameter[]> OnLogExecuted { get; set; }
|
||||
Action<PropertyInfo, EntityColumnInfo> EntityService { get; set; }
|
||||
|
||||
ConnectionConfig Build(Action<ConnectionConfig>? action = null);
|
||||
void SetDbAop(ISqlSugarClient currentDb);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
{
|
||||
public interface ISqlSugarDbContext
|
||||
{
|
||||
// IAbpLazyServiceProvider LazyServiceProvider { get; set; }
|
||||
ISqlSugarClient SqlSugarClient { get; }
|
||||
DbConnOptions Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库备份
|
||||
/// </summary>
|
||||
void BackupDataBase();
|
||||
void SetSqlSugarClient(ISqlSugarClient sqlSugarClient);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using System.Linq.Expressions;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
{
|
||||
|
||||
public interface ISqlSugarRepository<TEntity>:IRepository<TEntity> where TEntity : class, IEntity,new ()
|
||||
{
|
||||
ISqlSugarClient _Db { get; }
|
||||
ISugarQueryable<TEntity> _DbQueryable { get; }
|
||||
|
||||
Task<ISqlSugarClient> GetDbContextAsync();
|
||||
Task<IDeleteable<TEntity>> AsDeleteable();
|
||||
Task<IInsertable<TEntity>> AsInsertable(List<TEntity> insertObjs);
|
||||
Task<IInsertable<TEntity>> AsInsertable(TEntity insertObj);
|
||||
Task<IInsertable<TEntity>> AsInsertable(TEntity[] insertObjs);
|
||||
Task<ISugarQueryable<TEntity>> AsQueryable();
|
||||
Task<ISqlSugarClient> AsSugarClient();
|
||||
Task<ITenant> AsTenant();
|
||||
Task<IUpdateable<TEntity>> AsUpdateable(List<TEntity> updateObjs);
|
||||
Task<IUpdateable<TEntity>> AsUpdateable(TEntity updateObj);
|
||||
Task<IUpdateable<TEntity>> AsUpdateable();
|
||||
Task<IUpdateable<TEntity>> AsUpdateable(TEntity[] updateObjs);
|
||||
|
||||
#region 单查
|
||||
//单查
|
||||
Task<TEntity> GetByIdAsync(dynamic id);
|
||||
Task<TEntity> GetSingleAsync(Expression<Func<TEntity, bool>> whereExpression);
|
||||
Task<TEntity> GetFirstAsync(Expression<Func<TEntity, bool>> whereExpression);
|
||||
Task<bool> IsAnyAsync(Expression<Func<TEntity, bool>> whereExpression);
|
||||
Task<int> CountAsync(Expression<Func<TEntity, bool>> whereExpression);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 多查
|
||||
//多查
|
||||
Task<List<TEntity>> GetListAsync();
|
||||
Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> whereExpression);
|
||||
#endregion
|
||||
|
||||
|
||||
#region 分页查
|
||||
//分页查
|
||||
Task<List<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> whereExpression, int pageNum, int pageSize);
|
||||
Task<List<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> whereExpression, int pageNum, int pageSize, Expression<Func<TEntity, object>>? orderByExpression = null, OrderByType orderByType = OrderByType.Asc);
|
||||
#endregion
|
||||
|
||||
#region 插入
|
||||
//插入
|
||||
Task<bool> InsertAsync(TEntity insertObj);
|
||||
Task<bool> InsertOrUpdateAsync(TEntity data);
|
||||
Task<bool> InsertOrUpdateAsync(List<TEntity> datas);
|
||||
Task<int> InsertReturnIdentityAsync(TEntity insertObj);
|
||||
Task<long> InsertReturnBigIdentityAsync(TEntity insertObj);
|
||||
Task<long> InsertReturnSnowflakeIdAsync(TEntity insertObj);
|
||||
Task<TEntity> InsertReturnEntityAsync(TEntity insertObj);
|
||||
Task<bool> InsertRangeAsync(List<TEntity> insertObjs);
|
||||
#endregion
|
||||
|
||||
|
||||
#region 更新
|
||||
//更新
|
||||
Task<bool> UpdateAsync(TEntity updateObj);
|
||||
Task<bool> UpdateRangeAsync(List<TEntity> updateObjs);
|
||||
Task<bool> UpdateAsync(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> whereExpression);
|
||||
#endregion
|
||||
|
||||
#region 删除
|
||||
//删除
|
||||
Task<bool> DeleteAsync(TEntity deleteObj);
|
||||
Task<bool> DeleteAsync(List<TEntity> deleteObjs);
|
||||
Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression);
|
||||
Task<bool> DeleteByIdAsync(dynamic id);
|
||||
Task<bool> DeleteByIdsAsync(dynamic[] ids);
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
||||
public interface ISqlSugarRepository<TEntity, TKey> : ISqlSugarRepository<TEntity>,IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>, new()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
{
|
||||
public interface ISugarDbContextProvider<TDbContext>
|
||||
where TDbContext : ISqlSugarDbContext
|
||||
{
|
||||
|
||||
Task<TDbContext> GetDbContextAsync();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class IgnoreCodeFirstAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="$(SqlSugarVersion)" />
|
||||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.Core\Yi.Framework.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,11 +0,0 @@
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.Core;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
{
|
||||
[DependsOn(typeof(YiFrameworkCoreModule))]
|
||||
public class YiFrameworkSqlSugarCoreAbstractionsModule : AbpModule
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
public class AsyncLocalDbContextAccessor
|
||||
{
|
||||
public static AsyncLocalDbContextAccessor Instance { get; } = new();
|
||||
public ISqlSugarDbContext? Current
|
||||
{
|
||||
get => _currentScope.Value;
|
||||
set => _currentScope.Value = value;
|
||||
}
|
||||
public AsyncLocalDbContextAccessor()
|
||||
{
|
||||
_currentScope = new AsyncLocal<ISqlSugarDbContext?>();
|
||||
}
|
||||
private readonly AsyncLocal<ISqlSugarDbContext> _currentScope;
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Linq;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Repositories
|
||||
{
|
||||
public class SqlSugarObjectRepository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
|
||||
{
|
||||
public ISqlSugarClient _Db => GetDbContextAsync().Result;
|
||||
private ISugarDbContextProvider<ISqlSugarDbContext> _sugarDbContextProvider;
|
||||
/// <summary>
|
||||
/// 获取DB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ISqlSugarClient> GetDbContextAsync()
|
||||
{
|
||||
|
||||
var db = (await _sugarDbContextProvider.GetDbContextAsync()).SqlSugarClient;
|
||||
//await Console.Out.WriteLineAsync("获取的id:" + db.ContextID);
|
||||
return db;
|
||||
}
|
||||
|
||||
public IAsyncQueryableExecuter AsyncExecuter => throw new NotImplementedException();
|
||||
|
||||
public bool? IsChangeTrackingEnabled => throw new NotImplementedException();
|
||||
|
||||
public Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteDirectAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity?> FindAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<long> GetCountAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> GetPagedListAsync(int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> GetQueryableAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await (await GetDbContextAsync()).InsertableByObject(entity).ExecuteCommandAsync();
|
||||
return entity;
|
||||
}
|
||||
|
||||
public Task InsertManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> WithDetails()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> WithDetails(params Expression<Func<TEntity, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> WithDetailsAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> WithDetailsAsync(params Expression<Func<TEntity, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class SqlSugarObjectRepository<TEntity, TKey> : SqlSugarObjectRepository<TEntity>, IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>
|
||||
{
|
||||
public Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteManyAsync(IEnumerable<TKey> ids, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity?> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,419 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using SqlSugar;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Linq;
|
||||
using Yi.Framework.Core.Helper;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Repositories
|
||||
{
|
||||
public class SqlSugarRepository<TEntity> : ISqlSugarRepository<TEntity>, IRepository<TEntity> where TEntity : class, IEntity, new()
|
||||
{
|
||||
public ISqlSugarClient _Db => GetDbContextAsync().Result;
|
||||
|
||||
public ISugarQueryable<TEntity> _DbQueryable => GetDbContextAsync().Result.Queryable<TEntity>();
|
||||
|
||||
private ISugarDbContextProvider<ISqlSugarDbContext> _sugarDbContextProvider;
|
||||
public IAsyncQueryableExecuter AsyncExecuter { get; }
|
||||
|
||||
public bool? IsChangeTrackingEnabled => false;
|
||||
|
||||
public SqlSugarRepository(ISugarDbContextProvider<ISqlSugarDbContext> sugarDbContextProvider)
|
||||
{
|
||||
_sugarDbContextProvider = sugarDbContextProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取DB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ISqlSugarClient> GetDbContextAsync()
|
||||
{
|
||||
|
||||
var db = (await _sugarDbContextProvider.GetDbContextAsync()).SqlSugarClient;
|
||||
//await Console.Out.WriteLineAsync("获取的id:" + db.ContextID);
|
||||
return db;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取简单Db
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<SimpleClient<TEntity>> GetDbSimpleClientAsync()
|
||||
{
|
||||
var db = await GetDbContextAsync();
|
||||
return new SimpleClient<TEntity>(db);
|
||||
}
|
||||
|
||||
#region Abp模块
|
||||
|
||||
public virtual async Task<TEntity?> FindAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetFirstAsync(predicate);
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetFirstAsync(predicate);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await this.DeleteAsync(predicate);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteDirectAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await this.DeleteAsync(predicate);
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> WithDetails()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> WithDetails(params Expression<Func<TEntity, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> WithDetailsAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> WithDetailsAsync(params Expression<Func<TEntity, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> GetQueryableAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public virtual async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetListAsync(predicate);
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await InsertReturnEntityAsync(entity);
|
||||
}
|
||||
|
||||
public virtual async Task InsertManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await InsertRangeAsync(entities.ToList());
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await UpdateAsync(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public virtual async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await UpdateRangeAsync(entities.ToList());
|
||||
}
|
||||
|
||||
public virtual async Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await DeleteAsync(entity);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await DeleteAsync(entities.ToList());
|
||||
}
|
||||
|
||||
public virtual async Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetListAsync();
|
||||
}
|
||||
|
||||
public virtual async Task<long> GetCountAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await this.CountAsync(_=>true);
|
||||
}
|
||||
|
||||
public virtual async Task<List<TEntity>> GetPagedListAsync(int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetPageListAsync(_ => true, skipCount, maxResultCount);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region 内置DB快捷操作
|
||||
public virtual async Task<IDeleteable<TEntity>> AsDeleteable()
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsDeleteable();
|
||||
}
|
||||
|
||||
public virtual async Task<IInsertable<TEntity>> AsInsertable(List<TEntity> insertObjs)
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsInsertable(insertObjs);
|
||||
}
|
||||
|
||||
public virtual async Task<IInsertable<TEntity>> AsInsertable(TEntity insertObj)
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsInsertable(insertObj);
|
||||
}
|
||||
|
||||
public virtual async Task<IInsertable<TEntity>> AsInsertable(TEntity[] insertObjs)
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsInsertable(insertObjs);
|
||||
}
|
||||
|
||||
public virtual async Task<ISugarQueryable<TEntity>> AsQueryable()
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsQueryable();
|
||||
}
|
||||
|
||||
public virtual async Task<ISqlSugarClient> AsSugarClient()
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsSugarClient();
|
||||
}
|
||||
|
||||
public virtual async Task<ITenant> AsTenant()
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsTenant();
|
||||
}
|
||||
|
||||
public virtual async Task<IUpdateable<TEntity>> AsUpdateable(List<TEntity> updateObjs)
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsUpdateable(updateObjs);
|
||||
}
|
||||
|
||||
public virtual async Task<IUpdateable<TEntity>> AsUpdateable(TEntity updateObj)
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsUpdateable(updateObj);
|
||||
}
|
||||
|
||||
public virtual async Task<IUpdateable<TEntity>> AsUpdateable()
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsUpdateable();
|
||||
}
|
||||
|
||||
public virtual async Task<IUpdateable<TEntity>> AsUpdateable(TEntity[] updateObjs)
|
||||
{
|
||||
return (await GetDbSimpleClientAsync()).AsUpdateable(updateObjs);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SimpleClient模块
|
||||
public virtual async Task<int> CountAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).CountAsync(whereExpression);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> DeleteAsync(TEntity deleteObj)
|
||||
{
|
||||
if (deleteObj is ISoftDelete)
|
||||
{
|
||||
ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, deleteObj);
|
||||
return await (await GetDbSimpleClientAsync()).UpdateAsync(deleteObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).DeleteAsync(deleteObj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public virtual async Task<bool> DeleteAsync(List<TEntity> deleteObjs)
|
||||
{
|
||||
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
|
||||
{
|
||||
deleteObjs.ForEach(e => ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, e));
|
||||
return await (await GetDbSimpleClientAsync()).UpdateRangeAsync(deleteObjs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).DeleteAsync(deleteObjs);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).AsUpdateable().SetColumns(nameof(ISoftDelete), true).Where(whereExpression).ExecuteCommandAsync() > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).DeleteAsync(whereExpression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public virtual async Task<bool> DeleteByIdAsync(dynamic id)
|
||||
{
|
||||
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
|
||||
{
|
||||
var entity = await GetByIdAsync(id);
|
||||
//反射赋值
|
||||
ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, entity);
|
||||
return await UpdateAsync(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).DeleteByIdAsync(id);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async Task<bool> DeleteByIdsAsync(dynamic[] ids)
|
||||
{
|
||||
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
|
||||
{
|
||||
var simpleClient = (await GetDbSimpleClientAsync());
|
||||
var entities = await simpleClient.AsQueryable().In(ids).ToListAsync();
|
||||
if (entities.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//反射赋值
|
||||
entities.ForEach(e => ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, e));
|
||||
return await UpdateRangeAsync(entities);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).DeleteByIdAsync(ids);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity> GetByIdAsync(dynamic id)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).GetByIdAsync(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual async Task<TEntity> GetFirstAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).GetFirstAsync(whereExpression);
|
||||
}
|
||||
|
||||
public virtual async Task<List<TEntity>> GetListAsync()
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).GetListAsync();
|
||||
}
|
||||
|
||||
public virtual async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).GetListAsync(whereExpression);
|
||||
}
|
||||
|
||||
public virtual async Task<List<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> whereExpression, int pageNum, int pageSize)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).GetPageListAsync(whereExpression, new PageModel() { PageIndex = pageNum, PageSize = pageSize });
|
||||
}
|
||||
|
||||
public virtual async Task<List<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> whereExpression, int pageNum, int pageSize, Expression<Func<TEntity, object>>? orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).GetPageListAsync(whereExpression, new PageModel { PageIndex = pageNum, PageSize = pageSize }, orderByExpression, orderByType);
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity> GetSingleAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).GetSingleAsync(whereExpression);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> InsertAsync(TEntity insertObj)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertAsync(insertObj);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> InsertOrUpdateAsync(TEntity data)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertOrUpdateAsync(data);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> InsertOrUpdateAsync(List<TEntity> datas)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertOrUpdateAsync(datas);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> InsertRangeAsync(List<TEntity> insertObjs)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertRangeAsync(insertObjs);
|
||||
}
|
||||
|
||||
public virtual async Task<long> InsertReturnBigIdentityAsync(TEntity insertObj)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertReturnBigIdentityAsync(insertObj);
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity> InsertReturnEntityAsync(TEntity insertObj)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertReturnEntityAsync(insertObj);
|
||||
}
|
||||
|
||||
public virtual async Task<int> InsertReturnIdentityAsync(TEntity insertObj)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertReturnIdentityAsync(insertObj);
|
||||
}
|
||||
|
||||
public virtual async Task<long> InsertReturnSnowflakeIdAsync(TEntity insertObj)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).InsertReturnSnowflakeIdAsync(insertObj);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> IsAnyAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).IsAnyAsync(whereExpression);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> UpdateAsync(TEntity updateObj)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).UpdateAsync(updateObj);
|
||||
}
|
||||
|
||||
public virtual async Task<bool> UpdateAsync(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).UpdateAsync(columns, whereExpression);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual async Task<bool> UpdateRangeAsync(List<TEntity> updateObjs)
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).UpdateRangeAsync(updateObjs);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class SqlSugarRepository<TEntity, TKey> : SqlSugarRepository<TEntity>, ISqlSugarRepository<TEntity, TKey>, IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>, new()
|
||||
{
|
||||
public SqlSugarRepository(ISugarDbContextProvider<ISqlSugarDbContext> sugarDbContextProvider) : base(sugarDbContextProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await DeleteByIdAsync(id);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteManyAsync(IEnumerable<TKey> ids, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await DeleteByIdsAsync(ids.Select(x => (object)x).ToArray());
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity?> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetByIdAsync(id);
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetByIdAsync(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
|
||||
public class SqlSugarDbConnectionCreator: ISqlSugarDbConnectionCreator,ITransientDependency
|
||||
{
|
||||
public SqlSugarDbConnectionCreator(IOptions<DbConnOptions> options)
|
||||
{
|
||||
Options = options.Value;
|
||||
}
|
||||
public DbConnOptions Options { get; }
|
||||
|
||||
public void SetDbAop(ISqlSugarClient currentDb)
|
||||
{
|
||||
currentDb.Aop.OnLogExecuting = this.OnLogExecuting;
|
||||
currentDb.Aop.OnLogExecuted = this.OnLogExecuted;
|
||||
currentDb.Aop.DataExecuting = this.DataExecuting;
|
||||
currentDb.Aop.DataExecuted = this.DataExecuted;
|
||||
OnSqlSugarClientConfig(currentDb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ConnectionConfig Build(Action<ConnectionConfig>? action=null)
|
||||
{
|
||||
var dbConnOptions = Options;
|
||||
#region 组装options
|
||||
if (dbConnOptions.DbType is null)
|
||||
{
|
||||
throw new ArgumentException("DbType配置为空");
|
||||
}
|
||||
var slavaConFig = new List<SlaveConnectionConfig>();
|
||||
if (dbConnOptions.EnabledReadWrite)
|
||||
{
|
||||
if (dbConnOptions.ReadUrl is null)
|
||||
{
|
||||
throw new ArgumentException("读写分离为空");
|
||||
}
|
||||
|
||||
var readCon = dbConnOptions.ReadUrl;
|
||||
|
||||
readCon.ForEach(s =>
|
||||
{
|
||||
//如果是动态saas分库,这里的连接串都不能写死,需要动态添加,这里只配置共享库的连接
|
||||
slavaConFig.Add(new SlaveConnectionConfig() { ConnectionString = s });
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 组装连接config
|
||||
var connectionConfig = new ConnectionConfig()
|
||||
{
|
||||
ConfigId= ConnectionStrings.DefaultConnectionStringName,
|
||||
DbType = dbConnOptions.DbType ?? DbType.Sqlite,
|
||||
ConnectionString = dbConnOptions.Url,
|
||||
IsAutoCloseConnection = true,
|
||||
SlaveConnectionConfigs = slavaConFig,
|
||||
//设置codefirst非空值判断
|
||||
ConfigureExternalServices = new ConfigureExternalServices
|
||||
{
|
||||
EntityService = (c, p) =>
|
||||
{
|
||||
if (new NullabilityInfoContext()
|
||||
.Create(c).WriteState is NullabilityState.Nullable)
|
||||
{
|
||||
p.IsNullable = true;
|
||||
}
|
||||
|
||||
EntityService(c, p);
|
||||
}
|
||||
},
|
||||
//这里多租户有个坑,无效的
|
||||
AopEvents = new AopEvents
|
||||
{
|
||||
DataExecuted = DataExecuted,
|
||||
DataExecuting = DataExecuting,
|
||||
OnLogExecuted = OnLogExecuted,
|
||||
OnLogExecuting = OnLogExecuting
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (action is not null)
|
||||
{
|
||||
action.Invoke(connectionConfig);
|
||||
}
|
||||
#endregion
|
||||
return connectionConfig;
|
||||
}
|
||||
[DisablePropertyInjection]
|
||||
public Action<ISqlSugarClient> OnSqlSugarClientConfig { get; set; }
|
||||
|
||||
[DisablePropertyInjection]
|
||||
public Action<object, DataAfterModel> DataExecuted { get; set; }
|
||||
|
||||
[DisablePropertyInjection]
|
||||
public Action<object, DataFilterModel> DataExecuting { get; set; }
|
||||
|
||||
[DisablePropertyInjection]
|
||||
public Action<string, SugarParameter[]> OnLogExecuting { get; set; }
|
||||
|
||||
[DisablePropertyInjection]
|
||||
public Action<string, SugarParameter[]> OnLogExecuted { get; set; }
|
||||
|
||||
[DisablePropertyInjection]
|
||||
public Action<PropertyInfo, EntityColumnInfo> EntityService { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SqlSugar;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Entities.Events;
|
||||
using Volo.Abp.Guids;
|
||||
using Volo.Abp.MultiTenancy;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
public class SqlSugarDbContext : ISqlSugarDbContext
|
||||
{
|
||||
/// <summary>
|
||||
/// SqlSugar 客户端
|
||||
/// </summary>
|
||||
public ISqlSugarClient SqlSugarClient { get; private set; }
|
||||
public ICurrentUser CurrentUser => LazyServiceProvider.GetRequiredService<ICurrentUser>();
|
||||
private IAbpLazyServiceProvider LazyServiceProvider { get; }
|
||||
|
||||
private IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetRequiredService<IGuidGenerator>();
|
||||
protected ILoggerFactory Logger => LazyServiceProvider.LazyGetRequiredService<ILoggerFactory>();
|
||||
private ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService<ICurrentTenant>();
|
||||
public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>();
|
||||
protected virtual bool IsMultiTenantFilterEnabled => DataFilter?.IsEnabled<IMultiTenant>() ?? false;
|
||||
|
||||
protected virtual bool IsSoftDeleteFilterEnabled => DataFilter?.IsEnabled<ISoftDelete>() ?? false;
|
||||
|
||||
public IEntityChangeEventHelper EntityChangeEventHelper => LazyServiceProvider.LazyGetService<IEntityChangeEventHelper>(NullEntityChangeEventHelper.Instance);
|
||||
public DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService<IOptions<DbConnOptions>>().Value;
|
||||
public AbpDbConnectionOptions ConnectionOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDbConnectionOptions>>().Value;
|
||||
private ISqlSugarDbConnectionCreator _dbConnectionCreator;
|
||||
|
||||
public void SetSqlSugarClient(ISqlSugarClient sqlSugarClient)
|
||||
{
|
||||
SqlSugarClient = sqlSugarClient;
|
||||
}
|
||||
public SqlSugarDbContext(IAbpLazyServiceProvider lazyServiceProvider)
|
||||
{
|
||||
LazyServiceProvider = lazyServiceProvider;
|
||||
var connectionCreator = LazyServiceProvider.LazyGetRequiredService<ISqlSugarDbConnectionCreator>();
|
||||
_dbConnectionCreator = connectionCreator;
|
||||
connectionCreator.OnSqlSugarClientConfig = OnSqlSugarClientConfig;
|
||||
connectionCreator.EntityService = EntityService;
|
||||
connectionCreator.DataExecuting = DataExecuting;
|
||||
connectionCreator.DataExecuted = DataExecuted;
|
||||
connectionCreator.OnLogExecuting = OnLogExecuting;
|
||||
connectionCreator.OnLogExecuted = OnLogExecuted;
|
||||
SqlSugarClient = new SqlSugarClient(connectionCreator.Build(action: options =>
|
||||
{
|
||||
options.ConnectionString = GetCurrentConnectionString();
|
||||
options.DbType = GetCurrentDbType();
|
||||
}));
|
||||
connectionCreator.SetDbAop(SqlSugarClient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// db切换多库支持
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual string GetCurrentConnectionString()
|
||||
{
|
||||
var defautlUrl = Options.Url ?? ConnectionOptions.GetConnectionStringOrNull(ConnectionStrings.DefaultConnectionStringName);
|
||||
//如果未开启多租户,返回db url 或者 默认连接字符串
|
||||
if (!Options.EnabledSaasMultiTenancy)
|
||||
{
|
||||
return defautlUrl;
|
||||
}
|
||||
|
||||
//开启了多租户
|
||||
var connectionStringResolver = LazyServiceProvider.LazyGetRequiredService<IConnectionStringResolver>();
|
||||
var connectionString = connectionStringResolver.ResolveAsync().GetAwaiter().GetResult();
|
||||
|
||||
|
||||
//没有检测到使用多租户功能,默认使用默认库即可
|
||||
if (string.IsNullOrWhiteSpace(connectionString))
|
||||
{
|
||||
Volo.Abp.Check.NotNull(Options.Url, "租户默认库Defalut未找到");
|
||||
connectionString = defautlUrl;
|
||||
}
|
||||
return connectionString!;
|
||||
}
|
||||
|
||||
protected virtual DbType GetCurrentDbType()
|
||||
{
|
||||
if (CurrentTenant.Name is not null)
|
||||
{
|
||||
var dbTypeFromTenantName = GetDbTypeFromTenantName(CurrentTenant.Name);
|
||||
if (dbTypeFromTenantName is not null)
|
||||
{
|
||||
return dbTypeFromTenantName.Value;
|
||||
}
|
||||
}
|
||||
Volo.Abp.Check.NotNull(Options.DbType, "默认DbType未配置!");
|
||||
return Options.DbType!.Value;
|
||||
}
|
||||
|
||||
//根据租户name进行匹配db类型: Test_Sqlite,[来自AI]
|
||||
private DbType? GetDbTypeFromTenantName(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 查找下划线的位置
|
||||
int underscoreIndex = name.LastIndexOf('_');
|
||||
|
||||
if (underscoreIndex == -1 || underscoreIndex == name.Length - 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 提取 枚举 部分
|
||||
string enumString = name.Substring(underscoreIndex + 1);
|
||||
|
||||
// 尝试将 尾缀 转换为枚举
|
||||
if (Enum.TryParse<DbType>(enumString, out DbType result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// 条件不满足时返回 null
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 上下文对象扩展
|
||||
/// </summary>
|
||||
/// <param name="sqlSugarClient"></param>
|
||||
protected virtual void OnSqlSugarClientConfig(ISqlSugarClient sqlSugarClient)
|
||||
{
|
||||
//需自定义扩展
|
||||
if (IsSoftDeleteFilterEnabled)
|
||||
{
|
||||
sqlSugarClient.QueryFilter.AddTableFilter<ISoftDelete>(u => u.IsDeleted == false);
|
||||
}
|
||||
if (IsMultiTenantFilterEnabled)
|
||||
{
|
||||
//表达式不能放方法
|
||||
Guid? tenantId = CurrentTenant?.Id;
|
||||
sqlSugarClient.QueryFilter.AddTableFilter<IMultiTenant>(u => u.TenantId == tenantId);
|
||||
}
|
||||
CustomDataFilter(sqlSugarClient);
|
||||
}
|
||||
protected virtual void CustomDataFilter(ISqlSugarClient sqlSugarClient)
|
||||
{
|
||||
|
||||
}
|
||||
protected virtual void DataExecuted(object oldValue, DataAfterModel entityInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
/// <param name="oldValue"></param>
|
||||
/// <param name="entityInfo"></param>
|
||||
protected virtual void DataExecuting(object oldValue, DataFilterModel entityInfo)
|
||||
{
|
||||
//审计日志
|
||||
switch (entityInfo.OperationType)
|
||||
{
|
||||
case DataFilterType.UpdateByObject:
|
||||
|
||||
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModificationTime)))
|
||||
{
|
||||
if (!DateTime.MinValue.Equals(oldValue))
|
||||
{
|
||||
entityInfo.SetValue(DateTime.Now);
|
||||
}
|
||||
}
|
||||
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId)))
|
||||
{
|
||||
if (CurrentUser.Id != null)
|
||||
{
|
||||
entityInfo.SetValue(CurrentUser.Id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DataFilterType.InsertByObject:
|
||||
if (entityInfo.PropertyName.Equals(nameof(IEntity<Guid>.Id)))
|
||||
{
|
||||
//主键为空或者为默认最小值
|
||||
if (Guid.Empty.Equals(oldValue))
|
||||
{
|
||||
entityInfo.SetValue(GuidGenerator.Create());
|
||||
}
|
||||
}
|
||||
|
||||
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
|
||||
{
|
||||
//为空或者为默认最小值
|
||||
if (oldValue is null || DateTime.MinValue.Equals(oldValue))
|
||||
{
|
||||
entityInfo.SetValue(DateTime.Now);
|
||||
}
|
||||
}
|
||||
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
|
||||
{
|
||||
if (CurrentUser.Id != null)
|
||||
{
|
||||
entityInfo.SetValue(CurrentUser.Id);
|
||||
}
|
||||
}
|
||||
|
||||
//插入时,需要租户id,先预留
|
||||
if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
|
||||
{
|
||||
if (CurrentTenant is not null)
|
||||
{
|
||||
entityInfo.SetValue(CurrentTenant.Id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//领域事件
|
||||
switch (entityInfo.OperationType)
|
||||
{
|
||||
case DataFilterType.InsertByObject:
|
||||
if (entityInfo.PropertyName == nameof(IEntity<object>.Id))
|
||||
{
|
||||
EntityChangeEventHelper.PublishEntityCreatedEvent(entityInfo.EntityValue);
|
||||
}
|
||||
break;
|
||||
case DataFilterType.UpdateByObject:
|
||||
if (entityInfo.PropertyName == nameof(IEntity<object>.Id))
|
||||
{
|
||||
//软删除,发布的是删除事件
|
||||
if (entityInfo.EntityValue is ISoftDelete softDelete)
|
||||
{
|
||||
if (softDelete.IsDeleted == true)
|
||||
{
|
||||
EntityChangeEventHelper.PublishEntityDeletedEvent(entityInfo.EntityValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityChangeEventHelper.PublishEntityUpdatedEvent(entityInfo.EntityValue);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case DataFilterType.DeleteByObject:
|
||||
if (entityInfo.PropertyName == nameof(IEntity<object>.Id))
|
||||
{
|
||||
//这里sqlsugar有个特殊,删除会返回批量的结果
|
||||
if (entityInfo.EntityValue is IEnumerable entityValues)
|
||||
{
|
||||
foreach (var entityValue in entityValues)
|
||||
{
|
||||
|
||||
EntityChangeEventHelper.PublishEntityDeletedEvent(entityValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志
|
||||
/// </summary>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="pars"></param>
|
||||
protected virtual void OnLogExecuting(string sql, SugarParameter[] pars)
|
||||
{
|
||||
if (Options.EnabledSqlLog)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("==========Yi-SQL执行:==========");
|
||||
sb.AppendLine(UtilMethods.GetSqlString(DbType.SqlServer, sql, pars));
|
||||
sb.AppendLine("===============================");
|
||||
Logger.CreateLogger<SqlSugarDbContext>().LogDebug(sb.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志
|
||||
/// </summary>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="pars"></param>
|
||||
protected virtual void OnLogExecuted(string sql, SugarParameter[] pars)
|
||||
{
|
||||
if (Options.EnabledSqlLog)
|
||||
{
|
||||
var sqllog = $"=========Yi-SQL耗时{SqlSugarClient.Ado.SqlExecutionTime.TotalMilliseconds}毫秒=====";
|
||||
Logger.CreateLogger<SqlSugarDbContext>().LogDebug(sqllog.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实体配置
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <param name="column"></param>
|
||||
protected virtual void EntityService(PropertyInfo property, EntityColumnInfo column)
|
||||
{
|
||||
if (property.Name == "ConcurrencyStamp")
|
||||
{
|
||||
column.IsIgnore = true;
|
||||
}
|
||||
if (property.PropertyType == typeof(ExtraPropertyDictionary))
|
||||
{
|
||||
column.IsIgnore = true;
|
||||
}
|
||||
if (property.Name == nameof(Entity<object>.Id))
|
||||
{
|
||||
column.IsPrimarykey = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void BackupDataBase()
|
||||
{
|
||||
string directoryName = "database_backup";
|
||||
string fileName = DateTime.Now.ToString($"yyyyMMdd_HHmmss") + $"_{SqlSugarClient.Ado.Connection.Database}";
|
||||
if (!Directory.Exists(directoryName))
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
switch (Options.DbType)
|
||||
{
|
||||
case DbType.MySql:
|
||||
//MySql
|
||||
SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database, $"{Path.Combine(directoryName, fileName)}.sql");//mysql 只支持.net core
|
||||
break;
|
||||
|
||||
|
||||
case DbType.Sqlite:
|
||||
//Sqlite
|
||||
SqlSugarClient.DbMaintenance.BackupDataBase(null, $"{fileName}.db"); //sqlite 只支持.net core
|
||||
break;
|
||||
|
||||
|
||||
case DbType.SqlServer:
|
||||
//SqlServer
|
||||
SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database, $"{Path.Combine(directoryName, fileName)}.bak"/*服务器路径*/);//第一个参数库名
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
throw new NotImplementedException("其他数据库备份未实现");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Data.Common;
|
||||
using Volo.Abp;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore;
|
||||
|
||||
public class SqlSugarDbContextCreationContext
|
||||
{
|
||||
public static SqlSugarDbContextCreationContext Current => _current.Value;
|
||||
private static readonly AsyncLocal<SqlSugarDbContextCreationContext> _current = new AsyncLocal<SqlSugarDbContextCreationContext>();
|
||||
public string ConnectionStringName { get; }
|
||||
|
||||
public string ConnectionString { get; }
|
||||
|
||||
public DbConnection ExistingConnection { get; internal set; }
|
||||
|
||||
public SqlSugarDbContextCreationContext(string connectionStringName, string connectionString)
|
||||
{
|
||||
ConnectionStringName = connectionStringName;
|
||||
ConnectionString = connectionString;
|
||||
}
|
||||
|
||||
public static IDisposable Use(SqlSugarDbContextCreationContext context)
|
||||
{
|
||||
var previousValue = Current;
|
||||
_current.Value = context;
|
||||
return new DisposeAction(() => _current.Value = previousValue);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
public static class SqlsugarCoreExtensions
|
||||
{
|
||||
public static IServiceCollection AddYiDbContext<DbContext>(this IServiceCollection service, ServiceLifetime serviceLifetime = ServiceLifetime.Transient) where DbContext : class, ISqlSugarDbContext
|
||||
{
|
||||
service.Replace(new ServiceDescriptor(typeof(ISqlSugarDbContext), typeof(DbContext), serviceLifetime));
|
||||
return service;
|
||||
}
|
||||
public static IServiceCollection TryAddYiDbContext<DbContext>(this IServiceCollection service, ServiceLifetime serviceLifetime = ServiceLifetime.Transient) where DbContext : class, ISqlSugarDbContext
|
||||
{
|
||||
service.TryAdd(new ServiceDescriptor(typeof(ISqlSugarDbContext), typeof(DbContext), serviceLifetime));
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
public static IServiceCollection AddYiDbContext<DbContext>(this IServiceCollection service, Action<DbConnOptions> options) where DbContext : class, ISqlSugarDbContext
|
||||
{
|
||||
|
||||
service.Configure<DbConnOptions>(ops =>
|
||||
{
|
||||
options.Invoke(ops);
|
||||
});
|
||||
service.AddYiDbContext<DbContext>();
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Uow;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Uow
|
||||
{
|
||||
public class SqlSugarDatabaseApi : IDatabaseApi
|
||||
{
|
||||
public ISqlSugarDbContext DbContext { get; }
|
||||
|
||||
public SqlSugarDatabaseApi(ISqlSugarDbContext dbContext)
|
||||
{
|
||||
DbContext = dbContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using Volo.Abp.Uow;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Uow
|
||||
{
|
||||
public class SqlSugarTransactionApi : ITransactionApi, ISupportsRollback
|
||||
{
|
||||
private ISqlSugarDbContext _sqlsugarDbContext;
|
||||
|
||||
public SqlSugarTransactionApi(ISqlSugarDbContext sqlsugarDbContext)
|
||||
{
|
||||
_sqlsugarDbContext = sqlsugarDbContext;
|
||||
}
|
||||
|
||||
public ISqlSugarDbContext GetDbContext()
|
||||
{
|
||||
|
||||
return _sqlsugarDbContext;
|
||||
}
|
||||
|
||||
public async Task CommitAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _sqlsugarDbContext.SqlSugarClient.Ado.CommitTranAsync();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_sqlsugarDbContext.SqlSugarClient.Ado.Dispose();
|
||||
}
|
||||
|
||||
public async Task RollbackAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _sqlsugarDbContext.SqlSugarClient.Ado.RollbackTranAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.MultiTenancy;
|
||||
using Volo.Abp.Threading;
|
||||
using Volo.Abp.Uow;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Uow
|
||||
{
|
||||
public class UnitOfWorkSqlsugarDbContextProvider<TDbContext> : ISugarDbContextProvider<TDbContext> where TDbContext : ISqlSugarDbContext
|
||||
{
|
||||
private readonly ISqlSugarDbConnectionCreator _dbConnectionCreator;
|
||||
|
||||
public ILogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>> Logger { get; set; }
|
||||
public IServiceProvider ServiceProvider { get; set; }
|
||||
|
||||
private static AsyncLocalDbContextAccessor ContextInstance => AsyncLocalDbContextAccessor.Instance;
|
||||
protected readonly IUnitOfWorkManager UnitOfWorkManager;
|
||||
protected readonly IConnectionStringResolver ConnectionStringResolver;
|
||||
protected readonly ICancellationTokenProvider CancellationTokenProvider;
|
||||
protected readonly ICurrentTenant CurrentTenant;
|
||||
|
||||
public UnitOfWorkSqlsugarDbContextProvider(
|
||||
IUnitOfWorkManager unitOfWorkManager,
|
||||
IConnectionStringResolver connectionStringResolver,
|
||||
ICancellationTokenProvider cancellationTokenProvider,
|
||||
ICurrentTenant currentTenant,
|
||||
ISqlSugarDbConnectionCreator dbConnectionCreator
|
||||
)
|
||||
{
|
||||
UnitOfWorkManager = unitOfWorkManager;
|
||||
ConnectionStringResolver = connectionStringResolver;
|
||||
CancellationTokenProvider = cancellationTokenProvider;
|
||||
CurrentTenant = currentTenant;
|
||||
Logger = NullLogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>>.Instance;
|
||||
_dbConnectionCreator = dbConnectionCreator;
|
||||
}
|
||||
|
||||
//private static object _databaseApiLock = new object();
|
||||
public virtual async Task<TDbContext> GetDbContextAsync()
|
||||
{
|
||||
|
||||
var connectionStringName = ConnectionStrings.DefaultConnectionStringName;
|
||||
|
||||
//获取当前连接字符串,未多租户时,默认为空
|
||||
var connectionString = await ResolveConnectionStringAsync(connectionStringName);
|
||||
var dbContextKey = $"{this.GetType().FullName}_{connectionString}";
|
||||
|
||||
|
||||
var unitOfWork = UnitOfWorkManager.Current;
|
||||
if (unitOfWork == null /*|| unitOfWork.Options.IsTransactional == false*/)
|
||||
{
|
||||
var dbContext = (TDbContext)ServiceProvider.GetRequiredService<ISqlSugarDbContext>();
|
||||
//提高体验,取消工作单元强制性
|
||||
//throw new AbpException("A DbContext can only be created inside a unit of work!");
|
||||
//如果不启用工作单元,创建一个新的db,不开启事务即可
|
||||
return dbContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//尝试当前工作单元获取db
|
||||
var databaseApi = unitOfWork.FindDatabaseApi(dbContextKey);
|
||||
|
||||
//当前没有db创建一个新的db
|
||||
if (databaseApi == null)
|
||||
{
|
||||
//db根据连接字符串来创建
|
||||
databaseApi = new SqlSugarDatabaseApi(
|
||||
await CreateDbContextAsync(unitOfWork, connectionStringName, connectionString)
|
||||
);
|
||||
|
||||
//await Console.Out.WriteLineAsync(">>>----------------实例化了db"+ ((SqlSugarDatabaseApi)databaseApi).DbContext.SqlSugarClient.ContextID.ToString());
|
||||
//创建的db加入到当前工作单元中
|
||||
unitOfWork.AddDatabaseApi(dbContextKey, databaseApi);
|
||||
|
||||
}
|
||||
return (TDbContext)((SqlSugarDatabaseApi)databaseApi).DbContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected virtual async Task<TDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork, string connectionStringName, string connectionString)
|
||||
{
|
||||
var creationContext = new SqlSugarDbContextCreationContext(connectionStringName, connectionString);
|
||||
//将连接key进行传值
|
||||
using (SqlSugarDbContextCreationContext.Use(creationContext))
|
||||
{
|
||||
var dbContext = await CreateDbContextAsync(unitOfWork);
|
||||
return dbContext;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task<TDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork)
|
||||
{
|
||||
return unitOfWork.Options.IsTransactional
|
||||
? await CreateDbContextWithTransactionAsync(unitOfWork)
|
||||
: unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
|
||||
}
|
||||
protected virtual async Task<TDbContext> CreateDbContextWithTransactionAsync(IUnitOfWork unitOfWork)
|
||||
{
|
||||
//事务key
|
||||
var transactionApiKey = $"SqlsugarCore_{SqlSugarDbContextCreationContext.Current.ConnectionString}";
|
||||
|
||||
//尝试查找事务
|
||||
var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as SqlSugarTransactionApi;
|
||||
|
||||
//该db还没有进行开启事务
|
||||
if (activeTransaction == null)
|
||||
{
|
||||
//获取到db添加事务即可
|
||||
var dbContext = unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
|
||||
var transaction = new SqlSugarTransactionApi(
|
||||
dbContext
|
||||
);
|
||||
unitOfWork.AddTransactionApi(transactionApiKey, transaction);
|
||||
|
||||
await dbContext.SqlSugarClient.Ado.BeginTranAsync();
|
||||
return dbContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (TDbContext)activeTransaction.GetDbContext();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected virtual async Task<string> ResolveConnectionStringAsync(string connectionStringName)
|
||||
{
|
||||
if (typeof(TDbContext).IsDefined(typeof(IgnoreMultiTenancyAttribute), false))
|
||||
{
|
||||
using (CurrentTenant.Change(null))
|
||||
{
|
||||
return await ConnectionStringResolver.ResolveAsync(connectionStringName);
|
||||
}
|
||||
}
|
||||
|
||||
return await ConnectionStringResolver.ResolveAsync(connectionStringName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MySqlBackup.NET.MySqlConnector" Version="2.3.8" />
|
||||
<PackageReference Include="SqlSugarCore" Version="$(SqlSugarVersion)" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,111 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SqlSugar;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.Domain;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
using Yi.Framework.SqlSugarCore.Repositories;
|
||||
using Yi.Framework.SqlSugarCore.Uow;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
[DependsOn(typeof(AbpDddDomainModule))]
|
||||
public class YiFrameworkSqlSugarCoreModule : AbpModule
|
||||
{
|
||||
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
|
||||
{
|
||||
var service = context.Services;
|
||||
var configuration = service.GetConfiguration();
|
||||
Configure<DbConnOptions>(configuration.GetSection("DbConnOptions"));
|
||||
|
||||
service.TryAddScoped<ISqlSugarDbContext, SqlSugarDbContext>();
|
||||
|
||||
//不开放sqlsugarClient
|
||||
//service.AddTransient<ISqlSugarClient>(x => x.GetRequiredService<ISqlsugarDbContext>().SqlSugarClient);
|
||||
|
||||
|
||||
service.AddTransient(typeof(IRepository<>), typeof(SqlSugarRepository<>));
|
||||
service.AddTransient(typeof(IRepository<,>), typeof(SqlSugarRepository<,>));
|
||||
service.AddTransient(typeof(ISqlSugarRepository<>), typeof(SqlSugarRepository<>));
|
||||
service.AddTransient(typeof(ISqlSugarRepository<,>), typeof(SqlSugarRepository<,>));
|
||||
|
||||
service.AddTransient(typeof(ISugarDbContextProvider<>), typeof(UnitOfWorkSqlsugarDbContextProvider<>));
|
||||
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
public override async Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
|
||||
{
|
||||
//进行CodeFirst
|
||||
var service = context.ServiceProvider;
|
||||
var options = service.GetRequiredService<IOptions<DbConnOptions>>().Value;
|
||||
|
||||
var _logger= service.GetRequiredService<ILogger<YiFrameworkSqlSugarCoreModule>>();
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("==========Yi-SQL配置:==========");
|
||||
sb.AppendLine($"数据库连接字符串:{options.Url}");
|
||||
sb.AppendLine($"数据库类型:{options.DbType.ToString()}");
|
||||
sb.AppendLine($"是否开启种子数据:{options.EnabledDbSeed}");
|
||||
sb.AppendLine($"是否开启CodeFirst:{options.EnabledCodeFirst}");
|
||||
sb.AppendLine($"是否开启Saas多租户:{options.EnabledSaasMultiTenancy}");
|
||||
sb.AppendLine("===============================");
|
||||
|
||||
|
||||
_logger.LogInformation(sb.ToString());
|
||||
//Todo:准备支持多租户种子数据及CodeFirst
|
||||
|
||||
if (options.EnabledCodeFirst)
|
||||
{
|
||||
CodeFirst(service);
|
||||
}
|
||||
if (options.EnabledDbSeed)
|
||||
{
|
||||
await DataSeedAsync(service);
|
||||
}
|
||||
}
|
||||
|
||||
private void CodeFirst(IServiceProvider service)
|
||||
{
|
||||
|
||||
var moduleContainer = service.GetRequiredService<IModuleContainer>();
|
||||
var db = service.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient;
|
||||
|
||||
//尝试创建数据库
|
||||
db.DbMaintenance.CreateDatabase();
|
||||
|
||||
List<Type> types = new List<Type>();
|
||||
foreach (var module in moduleContainer.Modules)
|
||||
{
|
||||
types.AddRange(module.Assembly.GetTypes()
|
||||
.Where(x => x.GetCustomAttribute<IgnoreCodeFirstAttribute>() == null)
|
||||
.Where(x => x.GetCustomAttribute<SugarTable>() != null)
|
||||
.Where(x => x.GetCustomAttribute<SplitTableAttribute>() is null));
|
||||
}
|
||||
if (types.Count > 0)
|
||||
{
|
||||
db.CopyNew().CodeFirst.InitTables(types.ToArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async Task DataSeedAsync(IServiceProvider service)
|
||||
{
|
||||
var dataSeeder = service.GetRequiredService<IDataSeeder>();
|
||||
await dataSeeder.SeedAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.9 KiB |
@@ -1,19 +0,0 @@
|
||||
namespace Yi.Framework.AuditLogging.Domain.Shared.Consts;
|
||||
|
||||
public class AuditLogActionConsts
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value: 256
|
||||
/// </summary>
|
||||
public static int MaxServiceNameLength { get; set; } = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 128
|
||||
/// </summary>
|
||||
public static int MaxMethodNameLength { get; set; } = 128;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 2000
|
||||
/// </summary>
|
||||
public static int MaxParametersLength { get; set; } = 2000;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
namespace Yi.Framework.AuditLogging.Domain.Shared.Consts;
|
||||
|
||||
public static class AuditLogConsts
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value: 96
|
||||
/// </summary>
|
||||
public static int MaxApplicationNameLength { get; set; } = 96;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 64
|
||||
/// </summary>
|
||||
public static int MaxClientIpAddressLength { get; set; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 128
|
||||
/// </summary>
|
||||
public static int MaxClientNameLength { get; set; } = 128;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 64
|
||||
/// </summary>
|
||||
public static int MaxClientIdLength { get; set; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 64
|
||||
/// </summary>
|
||||
public static int MaxCorrelationIdLength { get; set; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 512
|
||||
/// </summary>
|
||||
public static int MaxBrowserInfoLength { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 256
|
||||
/// </summary>
|
||||
public static int MaxCommentsLength { get; set; } = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 256
|
||||
/// </summary>
|
||||
public static int MaxUrlLength { get; set; } = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 16
|
||||
/// </summary>
|
||||
public static int MaxHttpMethodLength { get; set; } = 16;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 256
|
||||
/// </summary>
|
||||
public static int MaxUserNameLength { get; set; } = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 64
|
||||
/// </summary>
|
||||
public static int MaxTenantNameLength { get; set; } = 64;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace Yi.Framework.AuditLogging.Domain.Shared.Consts;
|
||||
|
||||
public class EntityChangeConsts
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value: 128
|
||||
/// </summary>
|
||||
public static int MaxEntityTypeFullNameLength { get; set; } = 128;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 128
|
||||
/// </summary>
|
||||
public static int MaxEntityIdLength { get; set; } = 128;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace Yi.Framework.AuditLogging.Domain.Shared.Consts;
|
||||
|
||||
public class EntityPropertyChangeConsts
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value: 512
|
||||
/// </summary>
|
||||
public static int MaxNewValueLength { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 512
|
||||
/// </summary>
|
||||
public static int MaxOriginalValueLength { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 128
|
||||
/// </summary>
|
||||
public static int MaxPropertyNameLength { get; set; } = 128;
|
||||
|
||||
/// <summary>
|
||||
/// Default value: 64
|
||||
/// </summary>
|
||||
public static int MaxPropertyTypeFullNameLength { get; set; } = 64;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\common.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="$(AbpVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,11 +0,0 @@
|
||||
using Volo.Abp.Domain;
|
||||
using Volo.Abp.Modularity;
|
||||
|
||||
namespace Yi.Framework.AuditLogging.Domain.Shared
|
||||
{
|
||||
[DependsOn(typeof(AbpDddDomainSharedModule))]
|
||||
public class YiFrameworkAuditLoggingDomainSharedModule:AbpModule
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.AspNetCore.ExceptionHandling;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Guids;
|
||||
using Volo.Abp.Http;
|
||||
using Volo.Abp.Json;
|
||||
using Yi.Framework.AuditLogging.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.AuditLogging.Domain;
|
||||
|
||||
public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, ITransientDependency
|
||||
{
|
||||
protected IGuidGenerator GuidGenerator { get; }
|
||||
protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; }
|
||||
protected IJsonSerializer JsonSerializer { get; }
|
||||
protected AbpExceptionHandlingOptions ExceptionHandlingOptions { get; }
|
||||
|
||||
public AuditLogInfoToAuditLogConverter(IGuidGenerator guidGenerator, IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, IJsonSerializer jsonSerializer, IOptions<AbpExceptionHandlingOptions> exceptionHandlingOptions)
|
||||
{
|
||||
GuidGenerator = guidGenerator;
|
||||
ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter;
|
||||
JsonSerializer = jsonSerializer;
|
||||
ExceptionHandlingOptions = exceptionHandlingOptions.Value;
|
||||
}
|
||||
|
||||
public virtual Task<AuditLogAggregateRoot> ConvertAsync(AuditLogInfo auditLogInfo)
|
||||
{
|
||||
var auditLogId = GuidGenerator.Create();
|
||||
|
||||
var extraProperties = new ExtraPropertyDictionary();
|
||||
if (auditLogInfo.ExtraProperties != null)
|
||||
{
|
||||
foreach (var pair in auditLogInfo.ExtraProperties)
|
||||
{
|
||||
extraProperties.Add(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
var entityChanges = auditLogInfo
|
||||
.EntityChanges?
|
||||
.Select(entityChangeInfo => new EntityChangeEntity(GuidGenerator, auditLogId, entityChangeInfo, tenantId: auditLogInfo.TenantId))
|
||||
.ToList()
|
||||
?? new List<EntityChangeEntity>();
|
||||
|
||||
var actions = auditLogInfo
|
||||
.Actions?
|
||||
.Select(auditLogActionInfo => new AuditLogActionEntity(GuidGenerator.Create(), auditLogId, auditLogActionInfo, tenantId: auditLogInfo.TenantId))
|
||||
.ToList()
|
||||
?? new List<AuditLogActionEntity>();
|
||||
|
||||
var remoteServiceErrorInfos = auditLogInfo.Exceptions?.Select(exception => ExceptionToErrorInfoConverter.Convert(exception, options =>
|
||||
{
|
||||
options.SendExceptionsDetailsToClients = ExceptionHandlingOptions.SendExceptionsDetailsToClients;
|
||||
options.SendStackTraceToClients = ExceptionHandlingOptions.SendStackTraceToClients;
|
||||
}))
|
||||
?? new List<RemoteServiceErrorInfo>();
|
||||
|
||||
var exceptions = remoteServiceErrorInfos.Any()
|
||||
? JsonSerializer.Serialize(remoteServiceErrorInfos, indented: true)
|
||||
: null;
|
||||
|
||||
var comments = auditLogInfo
|
||||
.Comments?
|
||||
.JoinAsString(Environment.NewLine);
|
||||
|
||||
var auditLog = new AuditLogAggregateRoot(
|
||||
auditLogId,
|
||||
auditLogInfo.ApplicationName,
|
||||
auditLogInfo.TenantId,
|
||||
auditLogInfo.TenantName,
|
||||
auditLogInfo.UserId,
|
||||
auditLogInfo.UserName,
|
||||
auditLogInfo.ExecutionTime,
|
||||
auditLogInfo.ExecutionDuration,
|
||||
auditLogInfo.ClientIpAddress,
|
||||
auditLogInfo.ClientName,
|
||||
auditLogInfo.ClientId,
|
||||
auditLogInfo.CorrelationId,
|
||||
auditLogInfo.BrowserInfo,
|
||||
auditLogInfo.HttpMethod,
|
||||
auditLogInfo.Url,
|
||||
auditLogInfo.HttpStatusCode,
|
||||
auditLogInfo.ImpersonatorUserId,
|
||||
auditLogInfo.ImpersonatorUserName,
|
||||
auditLogInfo.ImpersonatorTenantId,
|
||||
auditLogInfo.ImpersonatorTenantName,
|
||||
extraProperties,
|
||||
entityChanges,
|
||||
actions,
|
||||
exceptions,
|
||||
comments
|
||||
);
|
||||
|
||||
return Task.FromResult(auditLog);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Uow;
|
||||
using Yi.Framework.AuditLogging.Domain.Repositories;
|
||||
using Yi.Framework.Core.Helper;
|
||||
|
||||
namespace Yi.Framework.AuditLogging.Domain;
|
||||
|
||||
public class AuditingStore : IAuditingStore, ITransientDependency
|
||||
{
|
||||
public ILogger<AuditingStore> Logger { get; set; }
|
||||
protected IAuditLogRepository AuditLogRepository { get; }
|
||||
protected IUnitOfWorkManager UnitOfWorkManager { get; }
|
||||
protected AbpAuditingOptions Options { get; }
|
||||
protected IAuditLogInfoToAuditLogConverter Converter { get; }
|
||||
public AuditingStore(
|
||||
IAuditLogRepository auditLogRepository,
|
||||
IUnitOfWorkManager unitOfWorkManager,
|
||||
IOptions<AbpAuditingOptions> options,
|
||||
IAuditLogInfoToAuditLogConverter converter)
|
||||
{
|
||||
AuditLogRepository = auditLogRepository;
|
||||
UnitOfWorkManager = unitOfWorkManager;
|
||||
Converter = converter;
|
||||
Options = options.Value;
|
||||
|
||||
Logger = NullLogger<AuditingStore>.Instance;
|
||||
}
|
||||
|
||||
public virtual async Task SaveAsync(AuditLogInfo auditInfo)
|
||||
{
|
||||
if (!Options.HideErrors)
|
||||
{
|
||||
await SaveLogAsync(auditInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await SaveLogAsync(auditInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning("Could not save the audit log object: " + Environment.NewLine + auditInfo.ToString());
|
||||
Logger.LogException(ex, LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task SaveLogAsync(AuditLogInfo auditInfo)
|
||||
{
|
||||
Logger.LogDebug("Yi-请求追踪:" + JsonHelper.ObjToStr(auditInfo, "yyyy-MM-dd HH:mm:ss"));
|
||||
using (var uow = UnitOfWorkManager.Begin(true))
|
||||
{
|
||||
await AuditLogRepository.InsertAsync(await Converter.ConvertAsync(auditInfo));
|
||||
await uow.CompleteAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.MultiTenancy;
|
||||
using Yi.Framework.AuditLogging.Domain.Shared.Consts;
|
||||
|
||||
namespace Yi.Framework.AuditLogging.Domain.Entities;
|
||||
|
||||
[DisableAuditing]
|
||||
[SugarTable("YiAuditLogAction")]
|
||||
[SugarIndex($"index_{nameof(AuditLogId)}", nameof(AuditLogId), OrderByType.Asc)]
|
||||
[SugarIndex($"index_{nameof(TenantId)}_{nameof(ExecutionTime)}", nameof(TenantId), OrderByType.Asc, nameof(ServiceName), OrderByType.Asc, nameof(MethodName), OrderByType.Asc, nameof(ExecutionTime), OrderByType.Asc)]
|
||||
public class AuditLogActionEntity : Entity<Guid>, IMultiTenant
|
||||
{
|
||||
public virtual Guid? TenantId { get; protected set; }
|
||||
|
||||
public virtual Guid AuditLogId { get; protected set; }
|
||||
|
||||
public virtual string? ServiceName { get; protected set; }
|
||||
|
||||
public virtual string? MethodName { get; protected set; }
|
||||
|
||||
public virtual string? Parameters { get; protected set; }
|
||||
|
||||
public virtual DateTime? ExecutionTime { get; protected set; }
|
||||
|
||||
public virtual int? ExecutionDuration { get; protected set; }
|
||||
|
||||
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
public AuditLogActionEntity()
|
||||
{
|
||||
}
|
||||
|
||||
public AuditLogActionEntity(Guid id, Guid auditLogId, AuditLogActionInfo actionInfo, Guid? tenantId = null)
|
||||
{
|
||||
|
||||
Id = id;
|
||||
TenantId = tenantId;
|
||||
AuditLogId = auditLogId;
|
||||
ExecutionTime = actionInfo.ExecutionTime;
|
||||
ExecutionDuration = actionInfo.ExecutionDuration;
|
||||
|
||||
ServiceName = actionInfo.ServiceName.TruncateFromBeginning(AuditLogActionConsts.MaxServiceNameLength);
|
||||
MethodName = actionInfo.MethodName.TruncateFromBeginning(AuditLogActionConsts.MaxMethodNameLength);
|
||||
Parameters = actionInfo.Parameters.Length > AuditLogActionConsts.MaxParametersLength ? "" : actionInfo.Parameters;
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.MultiTenancy;
|
||||
using Yi.Framework.AuditLogging.Domain.Shared.Consts;
|
||||
|
||||
namespace Yi.Framework.AuditLogging.Domain.Entities
|
||||
{
|
||||
[DisableAuditing]
|
||||
[SugarTable("YiAuditLog")]
|
||||
[SugarIndex($"index_{nameof(ExecutionTime)}", nameof(TenantId), OrderByType.Asc,nameof(ExecutionTime), OrderByType.Asc)]
|
||||
[SugarIndex($"index_{nameof(ExecutionTime)}_{nameof(UserId)}",nameof(TenantId), OrderByType.Asc, nameof(UserId), OrderByType.Asc, nameof(ExecutionTime), OrderByType.Asc)]
|
||||
public class AuditLogAggregateRoot: AggregateRoot<Guid>, IMultiTenant
|
||||
{
|
||||
public AuditLogAggregateRoot()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AuditLogAggregateRoot(
|
||||
Guid id,
|
||||
string applicationName,
|
||||
Guid? tenantId,
|
||||
string tenantName,
|
||||
Guid? userId,
|
||||
string userName,
|
||||
DateTime executionTime,
|
||||
int executionDuration,
|
||||
string clientIpAddress,
|
||||
string clientName,
|
||||
string clientId,
|
||||
string correlationId,
|
||||
string browserInfo,
|
||||
string httpMethod,
|
||||
string url,
|
||||
int? httpStatusCode,
|
||||
Guid? impersonatorUserId,
|
||||
string impersonatorUserName,
|
||||
Guid? impersonatorTenantId,
|
||||
string impersonatorTenantName,
|
||||
ExtraPropertyDictionary extraPropertyDictionary,
|
||||
List<EntityChangeEntity> entityChanges,
|
||||
List<AuditLogActionEntity> actions,
|
||||
string exceptions,
|
||||
string comments)
|
||||
: base(id)
|
||||
{
|
||||
ApplicationName = applicationName.Truncate(AuditLogConsts.MaxApplicationNameLength);
|
||||
TenantId = tenantId;
|
||||
TenantName = tenantName.Truncate(AuditLogConsts.MaxTenantNameLength);
|
||||
UserId = userId;
|
||||
UserName = userName.Truncate(AuditLogConsts.MaxUserNameLength);
|
||||
ExecutionTime = executionTime;
|
||||
ExecutionDuration = executionDuration;
|
||||
ClientIpAddress = clientIpAddress.Truncate(AuditLogConsts.MaxClientIpAddressLength);
|
||||
ClientName = clientName.Truncate(AuditLogConsts.MaxClientNameLength);
|
||||
ClientId = clientId.Truncate(AuditLogConsts.MaxClientIdLength);
|
||||
CorrelationId = correlationId.Truncate(AuditLogConsts.MaxCorrelationIdLength);
|
||||
BrowserInfo = browserInfo.Truncate(AuditLogConsts.MaxBrowserInfoLength);
|
||||
HttpMethod = httpMethod.Truncate(AuditLogConsts.MaxHttpMethodLength);
|
||||
Url = url.Truncate(AuditLogConsts.MaxUrlLength);
|
||||
HttpStatusCode = httpStatusCode;
|
||||
ImpersonatorUserId = impersonatorUserId;
|
||||
ImpersonatorUserName = impersonatorUserName.Truncate(AuditLogConsts.MaxUserNameLength);
|
||||
ImpersonatorTenantId = impersonatorTenantId;
|
||||
ImpersonatorTenantName = impersonatorTenantName.Truncate(AuditLogConsts.MaxTenantNameLength);
|
||||
ExtraProperties = extraPropertyDictionary;
|
||||
EntityChanges = entityChanges;
|
||||
Actions = actions;
|
||||
Exceptions = exceptions;
|
||||
Comments = comments.Truncate(AuditLogConsts.MaxCommentsLength);
|
||||
}
|
||||
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
|
||||
public virtual string? ApplicationName { get; set; }
|
||||
|
||||
public virtual Guid? UserId { get; protected set; }
|
||||
|
||||
public virtual string? UserName { get; protected set; }
|
||||
|
||||
public virtual string? TenantName { get; protected set; }
|
||||
|
||||
public virtual Guid? ImpersonatorUserId { get; protected set; }
|
||||
|
||||
public virtual string? ImpersonatorUserName { get; protected set; }
|
||||
|
||||
public virtual Guid? ImpersonatorTenantId { get; protected set; }
|
||||
|
||||
public virtual string? ImpersonatorTenantName { get; protected set; }
|
||||
|
||||
public virtual DateTime? ExecutionTime { get; protected set; }
|
||||
|
||||
public virtual int? ExecutionDuration { get; protected set; }
|
||||
|
||||
public virtual string? ClientIpAddress { get; protected set; }
|
||||
|
||||
public virtual string? ClientName { get; protected set; }
|
||||
|
||||
public virtual string? ClientId { get; set; }
|
||||
|
||||
public virtual string? CorrelationId { get; set; }
|
||||
|
||||
public virtual string? BrowserInfo { get; protected set; }
|
||||
|
||||
public virtual string? HttpMethod { get; protected set; }
|
||||
|
||||
public virtual string? Url { get; protected set; }
|
||||
|
||||
public virtual string? Exceptions { get; protected set; }
|
||||
|
||||
public virtual string? Comments { get; protected set; }
|
||||
|
||||
public virtual int? HttpStatusCode { get; set; }
|
||||
|
||||
public virtual Guid? TenantId { get; protected set; }
|
||||
|
||||
//导航属性
|
||||
[Navigate(NavigateType.OneToMany, nameof(EntityChangeEntity.AuditLogId))]
|
||||
public virtual List<EntityChangeEntity> EntityChanges { get; protected set; }
|
||||
|
||||
//导航属性
|
||||
[Navigate(NavigateType.OneToMany, nameof(AuditLogActionEntity.AuditLogId))]
|
||||
public virtual List<AuditLogActionEntity> Actions { get; protected set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public override ExtraPropertyDictionary ExtraProperties { get; protected set; }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user