mirror of
https://gitee.com/ccnetcore/Yi
synced 2026-03-03 00:00:58 +08:00
Compare commits
127 Commits
abp-dev
...
watermelon
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eabbd55789 | ||
|
|
801e30c1dc | ||
|
|
7049175827 | ||
|
|
f27a5a135b | ||
|
|
82ad9e249a | ||
|
|
fcff711a04 | ||
|
|
0c78b8d868 | ||
|
|
b6b54164a8 | ||
|
|
983daddebc | ||
|
|
605db9340c | ||
|
|
36ea04bd70 | ||
|
|
6f691e45d8 | ||
|
|
2c6558874d | ||
|
|
d60b432f0c | ||
|
|
adb9849650 | ||
|
|
48abbbf83e | ||
|
|
9e5361338c | ||
|
|
c5ecd71c6e | ||
|
|
b09bbba21b | ||
|
|
2db543573c | ||
|
|
cadd4df5d0 | ||
|
|
427de4b42f | ||
|
|
79cb82ea24 | ||
|
|
1b472c4ad7 | ||
|
|
21ab4950c8 | ||
|
|
1b2977d591 | ||
|
|
c54cf0bca2 | ||
|
|
935c990fe4 | ||
|
|
44f94f8398 | ||
|
|
8380cb1084 | ||
|
|
83fc4f46b2 | ||
|
|
9a97134a37 | ||
|
|
912010ed70 | ||
|
|
09b0bd8b09 | ||
|
|
c0dece8936 | ||
|
|
571b610417 | ||
|
|
658339047c | ||
|
|
13120712b1 | ||
|
|
10e1fad7f3 | ||
|
|
d7629763ef | ||
|
|
94ee0fb058 | ||
|
|
d4e8ce9c89 | ||
|
|
707e241f25 | ||
|
|
58fa94e8b8 | ||
|
|
72d307503e | ||
|
|
d9fd9163e4 | ||
|
|
21807c3a66 | ||
|
|
f499d2d8a9 | ||
|
|
0f9958bb26 | ||
|
|
8e66a9880c | ||
|
|
38e112fb06 | ||
|
|
bb0e48cd41 | ||
|
|
fd0edd93ea | ||
|
|
6359696bde | ||
|
|
1fee392989 | ||
|
|
dfdced9644 | ||
|
|
e50c1c374a | ||
|
|
dbcd051aae | ||
|
|
96571bb999 | ||
|
|
0620f6b6e3 | ||
|
|
ae163167b6 | ||
|
|
ba0bb32b5f | ||
|
|
b15e789b0b | ||
|
|
8c7afa2e7a | ||
|
|
87e30b9edf | ||
|
|
887ebe6f2f | ||
|
|
099581dddc | ||
|
|
3e84890765 | ||
|
|
d2fb0791d9 | ||
|
|
a2f22007cf | ||
|
|
d4dd531ac4 | ||
|
|
8374c81860 | ||
|
|
579f60e789 | ||
|
|
40b5f33c4e | ||
|
|
978a7fab4c | ||
|
|
f7790c46d2 | ||
|
|
9fc5b521e5 | ||
|
|
775e31c5e9 | ||
|
|
3339e30014 | ||
|
|
4ed44a2a8f | ||
|
|
6134e76030 | ||
|
|
e1ea210fe9 | ||
|
|
d9022a0383 | ||
|
|
0b0c1405ea | ||
|
|
e393e1f525 | ||
|
|
ad78cb1bcd | ||
|
|
e886614641 | ||
|
|
bc83362b35 | ||
|
|
b648f09f16 | ||
|
|
eb8d1626ea | ||
|
|
db94cd32d5 | ||
|
|
71fd5a13fc | ||
|
|
67c7ef37e6 | ||
|
|
2e22f4ea67 | ||
|
|
8be36f088b | ||
|
|
b985c2c784 | ||
|
|
e39d381f08 | ||
|
|
7694c7f97b | ||
|
|
eadb5eb216 | ||
|
|
cf5c46b2ce | ||
|
|
6e9dd669ba | ||
|
|
60ef93b510 | ||
|
|
e3aada0fff | ||
|
|
bbe1a44788 | ||
|
|
bfe0f346c8 | ||
|
|
8f10146d39 | ||
|
|
5f402488d4 | ||
|
|
07c48479af | ||
|
|
4bc2cebd60 | ||
|
|
dc242420f8 | ||
|
|
0656e3f536 | ||
|
|
cfffcda068 | ||
|
|
187885fdb9 | ||
|
|
f67b60dd82 | ||
|
|
92a2421a9b | ||
|
|
556d32729a | ||
|
|
4a3bd18bac | ||
|
|
de8f23bf2f | ||
|
|
3691a74d7e | ||
|
|
2aba4eccee | ||
|
|
3e6d02eccc | ||
|
|
2cf244058b | ||
|
|
971f137a21 | ||
|
|
b1a245c2a2 | ||
|
|
0c1ad1f4e5 | ||
|
|
e2a675054c | ||
|
|
0ad49e9b9d |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -20,7 +20,7 @@ x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[L]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
@@ -267,9 +267,10 @@ 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
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/logs/
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/yi-abp-dev.db
|
||||
|
||||
|
||||
213
README-en.md
Normal file
213
README-en.md
Normal file
@@ -0,0 +1,213 @@
|
||||
<h1 align="center"><img align="left" height="150px" src="https://ccnetcore.com/prod-api/wwwroot/logo.png"> Yi-Framework</h1>
|
||||
<h4 align="center">A .NET 8 Web open-source Asp.NetCore framework focused on user experience.</h4>
|
||||
<h5 align="center">Supports Native/Abp.vNext/Furion/Ruoyi/Pure</h5>
|
||||
<h2 align="center">A comprehensive solution that ultimately becomes a wheel</h2>
|
||||
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
|
||||
English | [简体中文](README.md)
|
||||
****
|
||||
## 🍍 Introduction:
|
||||
YiFramework is a DDD (Domain-Driven Design) backend open-source framework based on .Net8, Abp.vNext, and SqlSugar.
|
||||
|
||||
Who says ABP is complex? Who says DDD is difficult?`Breaking conventions, simplifying complexity.`,Newcomer-friendly and one of the best approaches for project extensions.
|
||||
|
||||
Modular design allows for the independent inclusion or exclusion of components based on business needs. It is an all-encompassing framework where you may gain unique insights.
|
||||
|
||||
A Comprehensive Solution, Ultimately Just Another Wheel.
|
||||
|
||||
(Frequent updates, feel free to watch for continuous updates.)
|
||||
|
||||
— This is not just a program; it is also a work of art, focused on artistic development!
|
||||
|
||||
> Core Features: Simple and easy to use, the framework is not referenced in a packaged form, but is provided directly with the project alongside the source code. It offers maximum freedom and complies with the MIT license, allowing for unrestricted modifications (please indicate the source).
|
||||
|
||||
**Branch Directory:**
|
||||
|
||||
- Branch **Abp**: Based on the Abp.vNext branch, DDD (Domain-Driven Design) simplifies the essence of development, providing support for multiple frontends from one backend.
|
||||
|
||||
- Yi.Abp.Net8:Backend
|
||||
- Yi.Bbs.Vue3:Bbs Community - Frontend
|
||||
- Yi.Doc.Md: Open Source Documentation Tutorial
|
||||
- Yi.Pure.Vue3:Pure TS Backend Frontend
|
||||
- Yi.RuoYi.Vue3:RuoYi JS Backend Frontend
|
||||
|
||||
****
|
||||
|
||||
## 🍊 Official website and demo link:
|
||||
|
||||
Let's get straight to the point and provide the link.
|
||||
|
||||
YiCommunity official website URL.(Bbs):[ccnetcore.com](https://ccnetcore.com) (Now live, welcome to join!)
|
||||
|
||||
Rbac:https://ccnetcore.com:1000 (userName cc\password 123456)
|
||||
|
||||
Pure:https://ccnetcore.com:1001 (userNamecc\password 123456)
|
||||
|
||||
## 🍏 Support:
|
||||
|
||||
- [x] Fully supports monolithic application architecture
|
||||
- [x] Fully supports distributed application architecture
|
||||
- [x] Fully supports microservices architecture
|
||||
|
||||
****
|
||||
## 🍇 Explosive Detail Yi Framework Tutorial Navigation:
|
||||
|
||||
1. [Framework Quick Start Guide](https://ccnetcore.com/article/aaa00329-7f35-d3fe-d258-3a0f8380b742)(Completed)
|
||||
2. [Framework Functionality Module Tutorials](https://ccnetcore.com/article/8c464ab3-8ba5-2761-a4b0-3a0f83a9f312)(Completed)
|
||||
3. [Practical Development Exercises](https://ccnetcore.com/article/e89c9593-f337-ada7-d108-3a0f83ae48e6)(Completed)
|
||||
4. [Chengzi Ops CI/CD Tutorial](https://ccnetcore.com/article/6b80ed42-50cd-db15-c073-3a0fa8f7fd77)(Completed)
|
||||
5. [Version Update Log](https://ccnetcore.com/article/e9e69a38-ce1e-06f5-7944-3a0fdc942ef3)(Completed)
|
||||
|
||||
****
|
||||
## 🍓 Its philosophy:
|
||||
Who says ABP is complicated? Who says DDD is difficult? Break the norm, simplify complexity, and serve as one of the best ways for newcomers and project second development.
|
||||
|
||||
> For every hundred people, there are a hundred different interpretations of DDD. The YiFramework may not strict adherence to DDD principles, but it is built on the shoulders of giants, distilled from numerous projects to craft a best practice.
|
||||
|
||||
Effortlessly achieve rapid development; typically, simplicity and elegance are hard to reconcile. The YiFramework does not solely pursue extreme decoupling but considers user experience and ease of use.
|
||||
|
||||
A user-oriented rapid development backend framework.
|
||||
|
||||
> Once you truly get hands-on, you'll understand this: extreme simplicity is also a form of elegance.
|
||||
****
|
||||
|
||||
## 🍍 Features
|
||||
- A user-oriented backend framework that is easy to use, suitable for small, medium, and enterprise-level projects.
|
||||
- The project comes with the source code directly embedded, without packaging, making it ideal for secondary development and modification.
|
||||
- Includes a large number of reusable modules for common scenarios.
|
||||
- Elegantly supports distributed and microservices architectures.
|
||||
- And more…
|
||||
|
||||
## 🥭 Core Technologies
|
||||
#### Backend
|
||||
C# Asp.NetCore 8.0
|
||||
- [x] Dynamic API: Abp.vNext
|
||||
- [x] Authentication and Authorization: Jwt
|
||||
- [x] Logging: Serilog
|
||||
- [x] Modularization: Abp.vNext
|
||||
- [x] Dependency Injection: Autofac
|
||||
- [x] Object Mapping: Mapster
|
||||
- [x] ORM: SqlsugarCore
|
||||
- [x] Multi-tenancy: Abp.vNext
|
||||
- [x] Background Tasks: Quartz.Net
|
||||
- [x] Local Caching: Abp.vNext
|
||||
- [x] Distributed Caching: Abp.vNext
|
||||
- [x] Event Bus: Abp.vNext
|
||||
|
||||
#### Frontend
|
||||
js Vue3
|
||||
- [x] Asynchronous Requests: axios
|
||||
- [x] Charts: echarts
|
||||
- [x] UI: element-plus
|
||||
- [x] State Management: pinia
|
||||
- [x] Routing: vue-router
|
||||
- [x] Bundling: vite
|
||||
|
||||
#### DevOps
|
||||
- [x] Deployment: nginx
|
||||
- [x] CICD: gitlab+Jenkins
|
||||
- [x] Docker: harbor
|
||||
|
||||
#### 🍉 Demo:
|
||||
<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/201.png"/></td>
|
||||
<td><img src="readme/202.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/203.png"/></td>
|
||||
<td><img src="readme/204.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/205.png"/></td>
|
||||
<td><img src="readme/206.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>
|
||||
|
||||
## 🌶 Thank you:
|
||||
|
||||
[橙子]https://ccnetcore.com
|
||||
|
||||
[XWen]https://gitee.com/on-wensil
|
||||
|
||||
[朝夕教育]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
|
||||
|
||||
[Furion百小僧]https://furion.baiqian.ltd/
|
||||
|
||||
****
|
||||
## 🌽 Contact Us:
|
||||
|
||||
Author's QQ:`454313500`
|
||||
|
||||
QQ group chat:官方一群(Full)、官方二群(Full)、官方三群:`786308927`(Full)、官方四群:`498310311`(Full)、官方五群:`981136525`(New)
|
||||
|
||||
WeChat Group Chat:官方微信一群(Full)、官方微信二群
|
||||
|
||||
WeChat Community: Add the author's WeChat chengzilaoge520 (橙子老哥520),Note: Join the group.
|
||||
|
||||
Contact the author, everyone here is a consultant.
|
||||
|
||||
Official website message area:[ccnetcore.com](https://ccnetcore.com)
|
||||
|
||||
****
|
||||
## 🍄 FQA:
|
||||
|
||||
Visit the official website to view the message board.
|
||||
|
||||
[the message board](https://ccnetcore.com/discuss/1641030787056930818)
|
||||
81
README.md
81
README.md
@@ -1,6 +1,6 @@
|
||||
<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>
|
||||
<h5 align="center">支持Abp.vNext 版本原生版本、Furion版本,前端接入Ruoyi/Pure Vue</h5>
|
||||
<h2 align="center">集大成者,终究轮子</h2>
|
||||
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
[English](README-en.md) | 简体中文
|
||||
****
|
||||
## :tw-1f34e: 简介:
|
||||
## 🍍 简介:
|
||||
YiFramework是一个基于.Net8+Abp.vNext+SqlSugar的DDD领域驱动设计后端开源框架
|
||||
|
||||
谁说Abp复杂?谁说DDD难?`打破常规,化繁为简`,新人入门,项目二开,最佳方式之一
|
||||
@@ -31,44 +31,45 @@ Yi框架-一套与SqlSugar一样爽的.Net8开源框架。
|
||||
|
||||
> 核心特点:简单好用,框架不以打包形式引用,而是直接以项目附带源码给出,自由度拉满,遵循Mit协议,允许随意修改(请注明来源即可)
|
||||
|
||||
**分支:**
|
||||
**分支目录:**
|
||||
|
||||
- (推荐) **Abp**: 基于Abp.vNext分支,DDD领域驱动设计,回归开发本质,极度简单,用起来贼爽
|
||||
- 分支**Abp**: 基于Abp.vNext分支,DDD领域驱动设计,回归开发本质,极度简单,一个后台支持以下多个前端
|
||||
|
||||
- **Furion**: 基于Furion分支
|
||||
- Yi.Abp.Net8:后端
|
||||
- Yi.Bbs.Vue3:Bbs社区 前端
|
||||
- Yi.Doc.Md: 开源文档教程
|
||||
- Yi.Pure.Vue3:Pure ts后台前端
|
||||
- Yi.RuoYi.Vue3:RuoYi js后台前端
|
||||
|
||||
****
|
||||
|
||||
## :tw-1f350: 官网及演示地址:
|
||||
## 🍊 官网及演示地址:
|
||||
|
||||
废话少说直接上地址
|
||||
|
||||
Yi社区官网网址:[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
Yi社区官网网址(Bbs社区正式):[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
|
||||
Rbac后台管理系统:已上线,暂不提供演示地址,可本地部署访问
|
||||
Rbac后台演示地址:https://ccnetcore.com:1000 (用户cc、密码123456)
|
||||
|
||||
App移动端系统:已上线,暂不提供演示地址,可本地部署访问
|
||||
Pure后台演示地址:https://ccnetcore.com:1001 (用户cc、密码123456)
|
||||
|
||||
Rbac演示地址:https://ccnetcore.com:1000 (用户cc、密码123456)
|
||||
|
||||
|
||||
## :tw-1f351: 支持:
|
||||
## 🍏 支持:
|
||||
|
||||
- [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)
|
||||
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)(已完成)
|
||||
|
||||
****
|
||||
## :tw-1f353: 它的理念:
|
||||
## 🍓 它的理念:
|
||||
谁说Abp复杂?谁说DDD难?打破常规,化繁为简,新人入门,项目二开,最佳方式之一
|
||||
|
||||
> 一百个人,就有一百种DDD,Yi框架不一定是极度严格的DDD,而是站在巨人的肩膀上,经过极多项目的提炼,摸索出一种最佳实践
|
||||
@@ -78,17 +79,17 @@ Rbac演示地址:https://ccnetcore.com:1000 (用户cc、密码123456)
|
||||
|
||||
> 一个面向用户的快速开发后端框架
|
||||
|
||||
在真正的使用这,你会明白这一点,极致的简单,也是优雅的一种体现。
|
||||
在真正的使用过,你会明白这一点,极致的简单,也是优雅的一种体现。
|
||||
****
|
||||
|
||||
## :tw-1f354: 特点
|
||||
## 🍍 特点
|
||||
- 面向用户的后端框架,使用简单,适合小型、中型、企业级项目
|
||||
- 项目直接内置源码,不打包,非常适合进行二开改造
|
||||
- 内置包含大量通用场景模块
|
||||
- 优雅支持分布式及微服务架构
|
||||
- 等等
|
||||
|
||||
## :tw-1f340: 基础设施简介
|
||||
## 🍍 基础设施简介
|
||||
|
||||
以下全部功能可直接使用:
|
||||
|
||||
@@ -96,14 +97,14 @@ Rbac演示地址:https://ccnetcore.com:1000 (用户cc、密码123456)
|
||||
|
||||
- [SqlSugar官网](https://www.donet5.com/home/doc)
|
||||
|
||||
## :tw-1f341: 内置模块简介
|
||||
- Rbac权限管理系统(已上线)
|
||||
## 🍅 内置模块简介
|
||||
- Rbac权限管理系统(已上线)(支持pure、ruoyi前端)
|
||||
- Bbs论坛社区系统(已上线)
|
||||
|
||||
> 重复的东西,无需再写一遍,这也是优雅的体现之一
|
||||
|
||||
****
|
||||
## :tw-1f31e: 核心技术
|
||||
## 🥭 核心技术
|
||||
#### 后端
|
||||
C# Asp.NetCore 8.0
|
||||
- [x] 动态Api:Abp.vNext
|
||||
@@ -120,7 +121,7 @@ C# Asp.NetCore 8.0
|
||||
- [x] 事件总线:Abp.vNext
|
||||
|
||||
#### 前端
|
||||
js Vue3.2
|
||||
js Vue3
|
||||
- [x] 异步请求:axios
|
||||
- [x] 图表:echarts
|
||||
- [x] ui:element-plus
|
||||
@@ -135,9 +136,9 @@ js Vue3.2
|
||||
|
||||
|
||||
****
|
||||
## :tw-1f366: 业务支持模块:
|
||||
## 🍌 业务支持模块:
|
||||
|
||||
#### :tw-1f42f: RABC权限管理系统(持续更新)
|
||||
#### 🍒 RABC权限管理系统(持续更新)
|
||||
(采用ruoyi前端)
|
||||
- 用户管理
|
||||
- 角色管理
|
||||
@@ -152,9 +153,8 @@ js Vue3.2
|
||||
- 定时任务
|
||||
- 缓存列表
|
||||
- 服务监控
|
||||
- WebFirst代码生成工具
|
||||
|
||||
#### :tw-1f431: BBS社区论坛系统(持续更新)
|
||||
#### 🍐 BBS社区论坛系统(持续更新)
|
||||
(采用vue3前端)
|
||||
- 文章功能
|
||||
- 板块功能
|
||||
@@ -163,7 +163,7 @@ js Vue3.2
|
||||
- 授权中心
|
||||
- 权限管理
|
||||
|
||||
#### :star: 演示截图:
|
||||
#### 🍉 演示截图:
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="readme/101.png"/></td>
|
||||
@@ -174,7 +174,22 @@ js Vue3.2
|
||||
<td><img src="readme/104.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="readme/201.png"/></td>
|
||||
<td><img src="readme/202.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/203.png"/></td>
|
||||
<td><img src="readme/204.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/205.png"/></td>
|
||||
<td><img src="readme/206.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@@ -207,7 +222,7 @@ js Vue3.2
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## :tw-1f44f: 感谢:
|
||||
## 🌶 感谢:
|
||||
|
||||
[橙子]https://ccnetcore.com
|
||||
|
||||
@@ -228,12 +243,14 @@ js Vue3.2
|
||||
[Furion百小僧]https://furion.baiqian.ltd/
|
||||
|
||||
****
|
||||
## :tw-1f438: 联系我们:
|
||||
## 🌽 联系我们:
|
||||
|
||||
作者QQ:`454313500`,2029年之前作者24小时在线,时刻保持活跃更新。
|
||||
|
||||
QQ交流群:官方一群(已满)、官方二群(已满)、官方三群:`786308927`(已满)、官方四群:`498310311`(基本已满)、官方五群:`981136525`(新群)
|
||||
|
||||
微信交流群:官方微信一群(已满)、官方微信二群
|
||||
|
||||
微信交流群:加作者微信 chengzilaoge520 (橙子老哥520),备注拉群
|
||||
|
||||
联系作者,这里人人都是顾问
|
||||
@@ -241,7 +258,7 @@ QQ交流群:官方一群(已满)、官方二群(已满)、官方三群
|
||||
官方网址留言区:[ccnetcore.com](https://ccnetcore.com)
|
||||
|
||||
****
|
||||
## :tw-1f41e: FQA:
|
||||
## 🍄 FQA:
|
||||
|
||||
前往官网查看留言区
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
usings.props = usings.props
|
||||
version.props = version.props
|
||||
publish.bat = publish.bat
|
||||
publish_Demo.bat = publish_Demo.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}"
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult;
|
||||
|
||||
/// <summary>
|
||||
/// 异常元数据
|
||||
/// </summary>
|
||||
public sealed class ExceptionMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public int StatusCode { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误码
|
||||
/// </summary>
|
||||
public object ErrorCode { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误码(没被复写过的 ErrorCode )
|
||||
/// </summary>
|
||||
public object OriginErrorCode { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误对象(信息)
|
||||
/// </summary>
|
||||
public object Errors { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外数据
|
||||
/// </summary>
|
||||
public object Data { get; internal set; }
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.Core.Extensions;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult.Fiters;
|
||||
|
||||
/// <summary>
|
||||
/// 友好异常拦截器
|
||||
/// </summary>
|
||||
public sealed class FriendlyExceptionFilter : IAsyncExceptionFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 异常拦截
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public async Task OnExceptionAsync(ExceptionContext context)
|
||||
{
|
||||
|
||||
// 排除 WebSocket 请求处理
|
||||
if (context.HttpContext.IsWebSocketRequest()) return;
|
||||
|
||||
// 如果异常在其他地方被标记了处理,那么这里不再处理
|
||||
if (context.ExceptionHandled) return;
|
||||
|
||||
// 解析异常信息
|
||||
var exceptionMetadata = GetExceptionMetadata(context);
|
||||
|
||||
IUnifyResultProvider unifyResult = context.GetRequiredService<IUnifyResultProvider>();
|
||||
// 执行规范化异常处理
|
||||
context.Result = unifyResult.OnException(context, exceptionMetadata);
|
||||
|
||||
// 创建日志记录器
|
||||
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<FriendlyExceptionFilter>>();
|
||||
|
||||
// 记录拦截日常
|
||||
logger.LogError(context.Exception, context.Exception.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取异常元数据
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static ExceptionMetadata GetExceptionMetadata(ActionContext context)
|
||||
{
|
||||
object errorCode = default;
|
||||
object originErrorCode = default;
|
||||
object errors = default;
|
||||
object data = default;
|
||||
var statusCode = StatusCodes.Status500InternalServerError;
|
||||
var isValidationException = false; // 判断是否是验证异常
|
||||
var isFriendlyException = false;
|
||||
|
||||
// 判断是否是 ExceptionContext 或者 ActionExecutedContext
|
||||
var exception = context is ExceptionContext exContext
|
||||
? exContext.Exception
|
||||
: (
|
||||
context is ActionExecutedContext edContext
|
||||
? edContext.Exception
|
||||
: default
|
||||
);
|
||||
|
||||
// 判断是否是友好异常
|
||||
if (exception is UserFriendlyException friendlyException)
|
||||
{
|
||||
int statusCode2 = 500;
|
||||
int.TryParse(friendlyException.Code, out statusCode2);
|
||||
isFriendlyException = true;
|
||||
errorCode = friendlyException.Code;
|
||||
originErrorCode = friendlyException.Code;
|
||||
statusCode = statusCode2==0?403:statusCode2;
|
||||
isValidationException = false;
|
||||
errors = friendlyException.Message;
|
||||
data = friendlyException.Data;
|
||||
}
|
||||
|
||||
return new ExceptionMetadata
|
||||
{
|
||||
StatusCode = statusCode,
|
||||
ErrorCode = errorCode,
|
||||
OriginErrorCode = originErrorCode,
|
||||
Errors = errors,
|
||||
Data = data
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.Core.Extensions;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult.Fiters;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化结构(请求成功)过滤器
|
||||
/// </summary>
|
||||
public class SucceededUnifyResultFilter : IAsyncActionFilter, IOrderedFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 过滤器排序
|
||||
/// </summary>
|
||||
private const int FilterOrder = 8888;
|
||||
|
||||
/// <summary>
|
||||
/// 排序属性
|
||||
/// </summary>
|
||||
public int Order => FilterOrder;
|
||||
|
||||
/// <summary>
|
||||
/// 处理规范化结果
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <returns></returns>
|
||||
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
// 执行 Action 并获取结果
|
||||
var actionExecutedContext = await next();
|
||||
|
||||
// 排除 WebSocket 请求处理
|
||||
if (actionExecutedContext.HttpContext.IsWebSocketRequest()) return;
|
||||
|
||||
// 处理已经含有状态码结果的 Result
|
||||
if (actionExecutedContext.Result is IStatusCodeActionResult statusCodeResult &&
|
||||
statusCodeResult.StatusCode != null)
|
||||
{
|
||||
// 小于 200 或者 大于 299 都不是成功值,直接跳过
|
||||
if (statusCodeResult.StatusCode.Value < 200 || statusCodeResult.StatusCode.Value > 299)
|
||||
{
|
||||
// 处理规范化结果
|
||||
if (!CheckStatusCodeNonUnify(context.HttpContext, out var unifyRes))
|
||||
{
|
||||
var httpContext = context.HttpContext;
|
||||
var statusCode = statusCodeResult.StatusCode.Value;
|
||||
|
||||
// 解决刷新 Token 时间和 Token 时间相近问题
|
||||
if (statusCodeResult.StatusCode.Value == StatusCodes.Status401Unauthorized
|
||||
&& httpContext.Response.Headers.ContainsKey("access-token")
|
||||
&& httpContext.Response.Headers.ContainsKey("x-access-token"))
|
||||
{
|
||||
httpContext.Response.StatusCode = statusCode = StatusCodes.Status403Forbidden;
|
||||
}
|
||||
|
||||
// 如果 Response 已经完成输出,则禁止写入
|
||||
if (httpContext.Response.HasStarted) return;
|
||||
await unifyRes.OnResponseStatusCodes(httpContext, statusCode,
|
||||
httpContext.RequestServices.GetService<IOptions<UnifyResultSettingsOptions>>()?.Value);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果出现异常,则不会进入该过滤器
|
||||
if (actionExecutedContext.Exception != null) return;
|
||||
|
||||
// 获取控制器信息
|
||||
var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
|
||||
|
||||
// 判断是否支持 MVC 规范化处理,检测配置而已
|
||||
// if (!UnifyContext.CheckSupportMvcController(context.HttpContext, actionDescriptor, out _)) return;
|
||||
|
||||
// 判断是否跳过规范化处理,检测NonUnifyAttribute而已
|
||||
if (CheckSucceededNonUnify(actionDescriptor.MethodInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
IUnifyResultProvider unifyResult = context.GetRequiredService<IUnifyResultProvider>();
|
||||
|
||||
// 处理 BadRequestObjectResult 类型规范化处理
|
||||
if (actionExecutedContext.Result is BadRequestObjectResult badRequestObjectResult)
|
||||
{
|
||||
// 解析验证消息
|
||||
var validationMetadata = GetValidationMetadata(badRequestObjectResult.Value);
|
||||
|
||||
var result = unifyResult.OnValidateFailed(context, validationMetadata);
|
||||
if (result != null) actionExecutedContext.Result = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
IActionResult result = default;
|
||||
|
||||
// 检查是否是有效的结果(可进行规范化的结果)
|
||||
if (CheckVaildResult(actionExecutedContext.Result, out var data))
|
||||
{
|
||||
result = unifyResult.OnSucceeded(actionExecutedContext, data);
|
||||
}
|
||||
|
||||
// 如果是不能规范化的结果类型,则跳过
|
||||
if (result == null) return;
|
||||
|
||||
actionExecutedContext.Result = result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证错误信息
|
||||
/// </summary>
|
||||
/// <param name="errors"></param>
|
||||
/// <returns></returns>
|
||||
private static ValidationMetadata GetValidationMetadata(object errors)
|
||||
{
|
||||
ModelStateDictionary _modelState = null;
|
||||
object validationResults = null;
|
||||
(string message, string firstErrorMessage, string firstErrorProperty) = (default, default, default);
|
||||
|
||||
// 判断是否是集合类型
|
||||
if (errors is IEnumerable && errors is not string)
|
||||
{
|
||||
// 如果是模型验证字典类型
|
||||
if (errors is ModelStateDictionary modelState)
|
||||
{
|
||||
_modelState = modelState;
|
||||
// 将验证错误信息转换成字典并序列化成 Json
|
||||
validationResults = modelState.Where(u => modelState[u.Key].ValidationState == ModelValidationState.Invalid)
|
||||
.ToDictionary(u => u.Key, u => modelState[u.Key].Errors.Select(c => c.ErrorMessage).ToArray());
|
||||
}
|
||||
// 如果是 ValidationProblemDetails 特殊类型
|
||||
else if (errors is ValidationProblemDetails validation)
|
||||
{
|
||||
validationResults = validation.Errors
|
||||
.ToDictionary(u => u.Key, u => u.Value.ToArray());
|
||||
}
|
||||
// 如果是字典类型
|
||||
else if (errors is Dictionary<string, string[]> dicResults)
|
||||
{
|
||||
validationResults = dicResults;
|
||||
}
|
||||
|
||||
message = JsonSerializer.Serialize(validationResults, new JsonSerializerOptions
|
||||
{
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
WriteIndented = true
|
||||
});
|
||||
firstErrorMessage = (validationResults as Dictionary<string, string[]>).First().Value[0];
|
||||
firstErrorProperty = (validationResults as Dictionary<string, string[]>).First().Key;
|
||||
}
|
||||
// 其他类型
|
||||
else
|
||||
{
|
||||
validationResults = firstErrorMessage = message = errors?.ToString();
|
||||
}
|
||||
|
||||
return new ValidationMetadata
|
||||
{
|
||||
ValidationResult = validationResults,
|
||||
Message = message,
|
||||
ModelState = _modelState,
|
||||
FirstErrorProperty = firstErrorProperty,
|
||||
FirstErrorMessage = firstErrorMessage
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否是有效的结果(可进行规范化的结果)
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
private bool CheckVaildResult(IActionResult result, out object data)
|
||||
{
|
||||
data = default;
|
||||
|
||||
// 排除以下结果,跳过规范化处理
|
||||
var isDataResult = result switch
|
||||
{
|
||||
ViewResult => false,
|
||||
PartialViewResult => false,
|
||||
FileResult => false,
|
||||
ChallengeResult => false,
|
||||
SignInResult => false,
|
||||
SignOutResult => false,
|
||||
RedirectToPageResult => false,
|
||||
RedirectToRouteResult => false,
|
||||
RedirectResult => false,
|
||||
RedirectToActionResult => false,
|
||||
LocalRedirectResult => false,
|
||||
ForbidResult => false,
|
||||
ViewComponentResult => false,
|
||||
PageResult => false,
|
||||
NotFoundResult => false,
|
||||
NotFoundObjectResult => false,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
// 目前支持返回值 ActionResult
|
||||
if (isDataResult) data = result switch
|
||||
{
|
||||
// 处理内容结果
|
||||
ContentResult content => content.Content,
|
||||
// 处理对象结果
|
||||
ObjectResult obj => obj.Value,
|
||||
// 处理 JSON 对象
|
||||
JsonResult json => json.Value,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
return isDataResult;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查短路状态码(>=400)是否进行规范化处理
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="unifyResult"></param>
|
||||
/// <returns>返回 true 跳过处理,否则进行规范化处理</returns>
|
||||
internal static bool CheckStatusCodeNonUnify(HttpContext context, out IUnifyResultProvider unifyResult)
|
||||
{
|
||||
// 获取终点路由特性
|
||||
var endpointFeature = context.Features.Get<IEndpointFeature>();
|
||||
if (endpointFeature == null) return (unifyResult = null) == null;
|
||||
|
||||
// 判断是否跳过规范化处理
|
||||
var isSkip = context.GetEndpoint()?.Metadata?.GetMetadata<NonUnifyAttribute>()!= null
|
||||
|| endpointFeature?.Endpoint?.Metadata?.GetMetadata<NonUnifyAttribute>() != null
|
||||
|| context.Request.Headers["accept"].ToString().Contains("odata.metadata=", StringComparison.OrdinalIgnoreCase)
|
||||
|| context.Request.Headers["accept"].ToString().Contains("odata.streaming=", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (isSkip == true) unifyResult = null;
|
||||
else
|
||||
{
|
||||
unifyResult = context.RequestServices.GetRequiredService<IUnifyResultProvider>();
|
||||
}
|
||||
|
||||
return unifyResult == null || isSkip;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查请求成功是否进行规范化处理
|
||||
/// </summary>
|
||||
/// <param name="method"></param>
|
||||
/// <param name="isWebRequest"></param>
|
||||
/// <returns>返回 true 跳过处理,否则进行规范化处理</returns>
|
||||
private bool CheckSucceededNonUnify(MethodInfo method, bool isWebRequest = true)
|
||||
{
|
||||
// 判断是否跳过规范化处理
|
||||
var isSkip = method.CustomAttributes.Any(x => typeof(NonUnifyAttribute).IsAssignableFrom(x.AttributeType) || typeof(ProducesResponseTypeAttribute).IsAssignableFrom(x.AttributeType) || typeof(IApiResponseMetadataProvider).IsAssignableFrom(x.AttributeType))
|
||||
|| method.ReflectedType.IsDefined(typeof(NonUnifyAttribute), true)
|
||||
|| method.DeclaringType.Assembly.GetName().Name.StartsWith("Microsoft.AspNetCore.OData");
|
||||
|
||||
if (!isWebRequest)
|
||||
{
|
||||
return isSkip;
|
||||
}
|
||||
return isSkip;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化结果提供器
|
||||
/// </summary>
|
||||
public interface IUnifyResultProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 异常返回值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="metadata"></param>
|
||||
/// <returns></returns>
|
||||
IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata);
|
||||
|
||||
/// <summary>
|
||||
/// 成功返回值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
IActionResult OnSucceeded(ActionExecutedContext context, object data);
|
||||
|
||||
/// <summary>
|
||||
/// 验证失败返回值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="metadata"></param>
|
||||
/// <returns></returns>
|
||||
IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata);
|
||||
|
||||
/// <summary>
|
||||
/// 拦截返回状态码
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="statusCode"></param>
|
||||
/// <param name="unifyResultSettings"></param>
|
||||
/// <returns></returns>
|
||||
Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings = default);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult;
|
||||
|
||||
/// <summary>
|
||||
/// 禁止规范化处理
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
|
||||
public sealed class NonUnifyAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult.Providers;
|
||||
|
||||
/// <summary>
|
||||
/// RESTful 风格返回值
|
||||
/// </summary>
|
||||
[Dependency(TryRegister = true)]
|
||||
[ExposeServices(typeof(IUnifyResultProvider))]
|
||||
public class RESTfulResultProvider : IUnifyResultProvider,ITransientDependency
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置响应状态码
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="statusCode"></param>
|
||||
/// <param name="unifyResultSettings"></param>
|
||||
public static void SetResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)
|
||||
{
|
||||
if (unifyResultSettings == null) return;
|
||||
|
||||
// 篡改响应状态码
|
||||
if (unifyResultSettings.AdaptStatusCodes != null && unifyResultSettings.AdaptStatusCodes.Length > 0)
|
||||
{
|
||||
var adaptStatusCode = unifyResultSettings.AdaptStatusCodes.FirstOrDefault(u => u[0] == statusCode);
|
||||
if (adaptStatusCode != null && adaptStatusCode.Length > 0 && adaptStatusCode[0] > 0)
|
||||
{
|
||||
context.Response.StatusCode = adaptStatusCode[1];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果为 null,则所有请求错误的状态码设置为 200
|
||||
if (unifyResultSettings.Return200StatusCodes == null) context.Response.StatusCode = 200;
|
||||
// 否则只有里面的才设置为 200
|
||||
else if (unifyResultSettings.Return200StatusCodes.Contains(statusCode)) context.Response.StatusCode = 200;
|
||||
else { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异常返回值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="metadata"></param>
|
||||
/// <returns></returns>
|
||||
public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)
|
||||
{
|
||||
return new JsonResult(RESTfulResult(metadata.StatusCode, data: metadata.Data, errors: metadata.Errors));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 成功返回值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public IActionResult OnSucceeded(ActionExecutedContext context, object data)
|
||||
{
|
||||
return new JsonResult(RESTfulResult(StatusCodes.Status200OK, true, data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证失败/业务异常返回值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="metadata"></param>
|
||||
/// <returns></returns>
|
||||
public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)
|
||||
{
|
||||
return new JsonResult(RESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, data: metadata.Data, errors: metadata.ValidationResult));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 特定状态码返回值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="statusCode"></param>
|
||||
/// <param name="unifyResultSettings"></param>
|
||||
/// <returns></returns>
|
||||
public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)
|
||||
{
|
||||
// 设置响应状态码
|
||||
SetResponseStatusCodes(context, statusCode, unifyResultSettings);
|
||||
|
||||
switch (statusCode)
|
||||
{
|
||||
// 处理 401 状态码
|
||||
case StatusCodes.Status401Unauthorized:
|
||||
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "401 Unauthorized"));
|
||||
break;
|
||||
// 处理 403 状态码
|
||||
case StatusCodes.Status403Forbidden:
|
||||
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 Forbidden"));
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回 RESTful 风格结果集
|
||||
/// </summary>
|
||||
/// <param name="statusCode"></param>
|
||||
/// <param name="succeeded"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="errors"></param>
|
||||
/// <returns></returns>
|
||||
public static RESTfulResult<object> RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)
|
||||
{
|
||||
return new RESTfulResult<object>
|
||||
{
|
||||
StatusCode = statusCode,
|
||||
Succeeded = succeeded,
|
||||
Data = data,
|
||||
Errors = errors,
|
||||
Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult;
|
||||
|
||||
/// <summary>
|
||||
/// RESTful 风格结果集
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class RESTfulResult<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public int? StatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
public T Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行成功
|
||||
/// </summary>
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public object Errors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附加数据
|
||||
/// </summary>
|
||||
public object Extras { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间戳
|
||||
/// </summary>
|
||||
public long Timestamp { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
|
||||
using Yi.Framework.AspNetCore.UnifyResult.Fiters;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化接口
|
||||
/// 由于太多人反应,想兼容一套类似furion的返回情况,200状态码包一层更符合国内习惯,既然如此,不如直接搬过来
|
||||
/// </summary>
|
||||
public static class UnifyResultExtensions
|
||||
{
|
||||
public static IServiceCollection AddFurionUnifyResultApi(this IServiceCollection services)
|
||||
{
|
||||
//成功规范接口
|
||||
services.AddTransient<SucceededUnifyResultFilter>();
|
||||
//异常规范接口
|
||||
services.AddTransient<FriendlyExceptionFilter>();
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.Filters.AddService<SucceededUnifyResultFilter>(99);
|
||||
options.Filters.AddService<FriendlyExceptionFilter>(100);
|
||||
options.Filters.RemoveAll(x => (x as ServiceFilterAttribute)?.ServiceType == typeof(AbpExceptionFilter));
|
||||
});
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化配置选项
|
||||
/// </summary>
|
||||
public sealed class UnifyResultSettingsOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置返回 200 状态码列表
|
||||
/// <para>默认:401,403,如果设置为 null,则标识所有状态码都返回 200 </para>
|
||||
/// </summary>
|
||||
public int[] Return200StatusCodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 适配(篡改)Http 状态码(只支持短路状态码,比如 401,403,500 等)
|
||||
/// </summary>
|
||||
public int[][] AdaptStatusCodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否支持 MVC 控制台规范化处理
|
||||
/// </summary>
|
||||
public bool? SupportMvcController { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选项后期配置
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="configuration"></param>
|
||||
public void PostConfigure(UnifyResultSettingsOptions options, IConfiguration configuration)
|
||||
{
|
||||
options.Return200StatusCodes ??= new[] { 401, 403 };
|
||||
options.SupportMvcController ??= false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// MIT 许可证
|
||||
//
|
||||
// 版权 © 2020-present 百小僧, 百签科技(广东)有限公司 和所有贡献者
|
||||
//
|
||||
// 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,
|
||||
// 包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,
|
||||
// 以及再授权被配发了本软件的人如上的权利,须在下列条件下:
|
||||
//
|
||||
// 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
|
||||
//
|
||||
// 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。
|
||||
// 在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,
|
||||
// 还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.UnifyResult;
|
||||
|
||||
/// <summary>
|
||||
/// 验证信息元数据
|
||||
/// </summary>
|
||||
public sealed class ValidationMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证结果
|
||||
/// </summary>
|
||||
/// <remarks>返回字典或字符串类型</remarks>
|
||||
public object ValidationResult { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异常消息
|
||||
/// </summary>
|
||||
public string Message { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证状态
|
||||
/// </summary>
|
||||
public ModelStateDictionary ModelState { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误码
|
||||
/// </summary>
|
||||
public object ErrorCode { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误码(没被复写过的 ErrorCode )
|
||||
/// </summary>
|
||||
public object OriginErrorCode { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public int? StatusCode { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 首个错误属性
|
||||
/// </summary>
|
||||
public string FirstErrorProperty { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 首个错误消息
|
||||
/// </summary>
|
||||
public string FirstErrorMessage { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外数据
|
||||
/// </summary>
|
||||
public object Data { get; internal set; }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Text;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
@@ -74,9 +74,12 @@ namespace Yi.Framework.Core.Extensions
|
||||
result = "127.0.0.1";
|
||||
|
||||
result = result.Replace("::ffff:", "127.0.0.1");
|
||||
|
||||
//如果有端口号,删除端口号
|
||||
result = Regex.Replace(result, @":\d{1,5}$", "");
|
||||
//Ip规则校验
|
||||
var regResult = Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
|
||||
var regResult =
|
||||
Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$")
|
||||
|| Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?):\d{1,5}$");
|
||||
|
||||
result = regResult ? result : "127.0.0.1";
|
||||
return result;
|
||||
@@ -96,5 +99,15 @@ namespace Yi.Framework.Core.Extensions
|
||||
{
|
||||
return context.User.Claims.Where(x => x.Type == permissionsName).Select(x => x.Value).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否是 WebSocket 请求
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsWebSocketRequest(this HttpContext context)
|
||||
{
|
||||
return context.WebSockets.IsWebSocketRequest || context.Request.Path == "/ws";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,12 +78,25 @@ namespace Yi.Framework.Core.Helper
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CPU使用情况
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static CPUMetrics GetCPUMetrics()
|
||||
{
|
||||
CPUMetrics cpuMetrics = new CPUMetrics();
|
||||
var cpudetail = GetCPUDetails();
|
||||
cpuMetrics.CoreTotal = cpudetail.Cores;
|
||||
cpuMetrics.LogicalProcessors =cpudetail.LogicalProcessors;
|
||||
cpuMetrics.CPURate = Math.Ceiling(ParseToDouble(GetCPURate()));
|
||||
cpuMetrics.FreeRate = 1 - cpuMetrics.CPURate;
|
||||
return cpuMetrics;
|
||||
}
|
||||
/// <summary>
|
||||
/// 内存使用情况
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static MemoryMetrics GetComputerInfo()
|
||||
public static MemoryMetrics GetMemoryMetrics()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -94,7 +107,7 @@ namespace Yi.Framework.Core.Helper
|
||||
memoryMetrics.UsedRam = Math.Round(memoryMetrics.Used / 1024, 2) + "GB";
|
||||
memoryMetrics.TotalRAM = Math.Round(memoryMetrics.Total / 1024, 2) + "GB";
|
||||
memoryMetrics.RAMRate = Math.Ceiling(100 * memoryMetrics.Used / memoryMetrics.Total).ToString() + "%";
|
||||
memoryMetrics.CPURate = Math.Ceiling(ParseToDouble(GetCPURate())) + "%";
|
||||
|
||||
return memoryMetrics;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -105,7 +118,7 @@ namespace Yi.Framework.Core.Helper
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取内存大小
|
||||
/// 获取磁盘信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<DiskInfo> GetDiskInfos()
|
||||
@@ -174,7 +187,7 @@ namespace Yi.Framework.Core.Helper
|
||||
var isUnix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
|
||||
return isUnix;
|
||||
}
|
||||
|
||||
|
||||
public static string GetCPURate()
|
||||
{
|
||||
string cpuRate;
|
||||
@@ -221,8 +234,69 @@ namespace Yi.Framework.Core.Helper
|
||||
}
|
||||
return runTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static CPUInfo GetCPUDetails()
|
||||
{
|
||||
int logicalProcessors = 0;
|
||||
int cores = 0;
|
||||
|
||||
if (IsUnix())
|
||||
{
|
||||
string logicalOutput = ShellHelper.Bash("lscpu | grep '^CPU(s):' | awk '{print $2}'");
|
||||
logicalProcessors = int.Parse(logicalOutput.Trim());
|
||||
|
||||
string coresOutput = ShellHelper.Bash("lscpu | grep 'Core(s) per socket:' | awk '{print $4}'");
|
||||
string socketsOutput = ShellHelper.Bash("lscpu | grep 'Socket(s):' | awk '{print $2}'");
|
||||
cores = int.Parse(coresOutput.Trim()) * int.Parse(socketsOutput.Trim());
|
||||
}
|
||||
else
|
||||
{
|
||||
string output = ShellHelper.Cmd("wmic", "cpu get NumberOfCores,NumberOfLogicalProcessors /format:csv");
|
||||
var lines = output.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (lines.Length > 1)
|
||||
{
|
||||
var values = lines[1].Split(',');
|
||||
|
||||
cores = int.Parse(values[1].Trim());
|
||||
logicalProcessors =int.Parse(values[2].Trim());
|
||||
}
|
||||
}
|
||||
|
||||
return new CPUInfo
|
||||
{
|
||||
LogicalProcessors = logicalProcessors,
|
||||
Cores = cores
|
||||
};
|
||||
}
|
||||
}
|
||||
public class CPUInfo
|
||||
{
|
||||
public int LogicalProcessors { get; set; }
|
||||
public int Cores { get; set; }
|
||||
}
|
||||
public class CPUMetrics
|
||||
{
|
||||
/// <summary>
|
||||
/// 内核数
|
||||
/// </summary>
|
||||
public int CoreTotal { get; set; }
|
||||
/// <summary>
|
||||
/// 逻辑处理器数
|
||||
/// </summary>
|
||||
public int LogicalProcessors { get; set; }
|
||||
/// <summary>
|
||||
/// CPU使用率%
|
||||
/// </summary>
|
||||
public double CPURate { get; set; }
|
||||
/// <summary>
|
||||
/// CPU空闲率%
|
||||
/// </summary>
|
||||
public double FreeRate { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内存信息
|
||||
/// </summary>
|
||||
@@ -236,10 +310,7 @@ namespace Yi.Framework.Core.Helper
|
||||
public double Free { get; set; }
|
||||
|
||||
public string UsedRam { get; set; }
|
||||
/// <summary>
|
||||
/// CPU使用率%
|
||||
/// </summary>
|
||||
public string CPURate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总内存 GB
|
||||
/// </summary>
|
||||
@@ -306,20 +377,25 @@ namespace Yi.Framework.Core.Helper
|
||||
/// <returns></returns>
|
||||
public MemoryMetrics GetUnixMetrics()
|
||||
{
|
||||
string output = ShellHelper.Bash("free -m | awk '{print $2,$3,$4,$5,$6}'");
|
||||
string output = ShellHelper.Bash(@"
|
||||
# 从 /proc/meminfo 文件中提取总内存
|
||||
total_mem=$(cat /proc/meminfo | grep -i ""MemTotal"" | awk '{print $2}')
|
||||
# 从 /proc/meminfo 文件中提取剩余内存
|
||||
free_mem=$(cat /proc/meminfo | grep -i ""MemFree"" | awk '{print $2}')
|
||||
# 显示提取的信息
|
||||
echo $total_mem $used_mem $free_mem
|
||||
");
|
||||
var metrics = new MemoryMetrics();
|
||||
var lines = output.Split('\n', (char)StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (lines.Length <= 0) return metrics;
|
||||
|
||||
if (lines != null && lines.Length > 0)
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
var memory = lines[1].Split(' ', (char)StringSplitOptions.RemoveEmptyEntries);
|
||||
if (memory.Length >= 3)
|
||||
var memory = output.Split(' ', (char)StringSplitOptions.RemoveEmptyEntries);
|
||||
if (memory.Length >= 2)
|
||||
{
|
||||
metrics.Total = double.Parse(memory[0]);
|
||||
metrics.Used = double.Parse(memory[1]);
|
||||
metrics.Free = double.Parse(memory[2]);//m
|
||||
metrics.Total = Math.Round(double.Parse(memory[0]) / 1024, 0);
|
||||
|
||||
metrics.Free = Math.Round(double.Parse(memory[1])/ 1024, 0);//m
|
||||
metrics.Used = metrics.Total - metrics.Free;
|
||||
}
|
||||
}
|
||||
return metrics;
|
||||
|
||||
@@ -13,5 +13,39 @@ namespace Yi.Framework.Ddd.Application.Contracts
|
||||
/// 查询结束时间条件
|
||||
/// </summary>
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序列名,字段名对应前端
|
||||
/// </summary>
|
||||
public string? OrderByColumn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否顺序,字段名对应前端
|
||||
/// </summary>
|
||||
public string? IsAsc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否顺序
|
||||
/// </summary>
|
||||
public bool CanAsc => IsAsc?.ToLower() == "ascending" ? true : false;
|
||||
|
||||
private string _sorting;
|
||||
|
||||
//排序引用
|
||||
public new string? Sorting
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!OrderByColumn.IsNullOrWhiteSpace())
|
||||
{
|
||||
return $"{OrderByColumn} {(CanAsc ? "ASC" : "DESC")}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return _sorting;
|
||||
}
|
||||
}
|
||||
set => _sorting = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,11 @@ 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>
|
||||
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)
|
||||
{
|
||||
@@ -49,16 +51,53 @@ namespace Yi.Framework.Ddd.Application
|
||||
}
|
||||
|
||||
|
||||
public abstract class YiCrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
|
||||
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>
|
||||
where TEntity : class, IEntity<TKey>
|
||||
where TGetOutputDto : IEntityDto<TKey>
|
||||
where TGetListOutputDto : IEntityDto<TKey>
|
||||
{
|
||||
protected YiCrudAppService(IRepository<TEntity, TKey> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<TGetOutputDto> UpdateAsync(TKey id, TUpdateInput input)
|
||||
{
|
||||
await CheckUpdatePolicyAsync();
|
||||
|
||||
var entity = await GetEntityByIdAsync(id);
|
||||
await CheckUpdateInputDtoAsync(entity,input);
|
||||
|
||||
await MapToEntityAsync(input, entity);
|
||||
await Repository.UpdateAsync(entity, autoSave: true);
|
||||
|
||||
return await MapToGetOutputDtoAsync(entity);
|
||||
}
|
||||
|
||||
protected virtual Task CheckUpdateInputDtoAsync(TEntity entity,TUpdateInput input)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task<TGetOutputDto> CreateAsync(TCreateInput input)
|
||||
{
|
||||
await CheckCreatePolicyAsync();
|
||||
await CheckCreateInputDtoAsync(input);
|
||||
var entity = await MapToEntityAsync(input);
|
||||
|
||||
TryToSetTenantId(entity);
|
||||
|
||||
await Repository.InsertAsync(entity, autoSave: true);
|
||||
|
||||
return await MapToGetOutputDtoAsync(entity);
|
||||
}
|
||||
|
||||
protected virtual Task CheckCreateInputDtoAsync(TCreateInput input)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 多查
|
||||
/// </summary>
|
||||
@@ -70,12 +109,14 @@ namespace Yi.Framework.Ddd.Application
|
||||
//区分多查还是批量查
|
||||
if (input is IPagedResultRequest pagedInput)
|
||||
{
|
||||
entites = await Repository.GetPagedListAsync(pagedInput.SkipCount, pagedInput.MaxResultCount, string.Empty);
|
||||
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);
|
||||
@@ -146,4 +187,4 @@ namespace Yi.Framework.Ddd.Application
|
||||
//await Repository.InsertManyAsync(entities);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,10 @@ namespace Yi.Framework.SqlSugarCore.Abstractions
|
||||
/// </summary>
|
||||
public bool EnabledDbSeed { get; set; } = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 开启驼峰转下划线
|
||||
/// </summary>
|
||||
public bool EnableUnderLine { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 开启codefirst
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nito.AsyncEx;
|
||||
using SqlSugar;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Linq;
|
||||
@@ -13,9 +17,9 @@ namespace Yi.Framework.SqlSugarCore.Repositories
|
||||
{
|
||||
public class SqlSugarRepository<TEntity> : ISqlSugarRepository<TEntity>, IRepository<TEntity> where TEntity : class, IEntity, new()
|
||||
{
|
||||
public ISqlSugarClient _Db => GetDbContextAsync().Result;
|
||||
public ISqlSugarClient _Db => AsyncContext.Run(async () => await GetDbContextAsync());
|
||||
|
||||
public ISugarQueryable<TEntity> _DbQueryable => GetDbContextAsync().Result.Queryable<TEntity>();
|
||||
public ISugarQueryable<TEntity> _DbQueryable => _Db.Queryable<TEntity>();
|
||||
|
||||
private ISugarDbContextProvider<ISqlSugarDbContext> _sugarDbContextProvider;
|
||||
public IAsyncQueryableExecuter AsyncExecuter { get; }
|
||||
@@ -33,9 +37,7 @@ namespace Yi.Framework.SqlSugarCore.Repositories
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ISqlSugarClient> GetDbContextAsync()
|
||||
{
|
||||
|
||||
var db = (await _sugarDbContextProvider.GetDbContextAsync()).SqlSugarClient;
|
||||
//await Console.Out.WriteLineAsync("获取的id:" + db.ContextID);
|
||||
return db;
|
||||
}
|
||||
|
||||
@@ -243,7 +245,7 @@ namespace Yi.Framework.SqlSugarCore.Repositories
|
||||
{
|
||||
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
|
||||
{
|
||||
return await (await GetDbSimpleClientAsync()).AsUpdateable().SetColumns(nameof(ISoftDelete), true).Where(whereExpression).ExecuteCommandAsync() > 0;
|
||||
return await (await GetDbSimpleClientAsync()).AsUpdateable().SetColumns(nameof(ISoftDelete.IsDeleted), true).Where(whereExpression).ExecuteCommandAsync() > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -372,6 +374,20 @@ namespace Yi.Framework.SqlSugarCore.Repositories
|
||||
|
||||
public virtual async Task<bool> UpdateAsync(TEntity updateObj)
|
||||
{
|
||||
if (typeof(TEntity).IsAssignableTo<IHasConcurrencyStamp>())//带版本号乐观锁更新
|
||||
{
|
||||
try
|
||||
{
|
||||
int num = await (await GetDbSimpleClientAsync())
|
||||
.Context.Updateable(updateObj).ExecuteCommandWithOptLockAsync(true);
|
||||
return num>0;
|
||||
}
|
||||
catch (VersionExceptions ex)
|
||||
{
|
||||
|
||||
throw new AbpDbConcurrencyException($"{ex.Message}[更新失败:ConcurrencyStamp不是最新版本],entityInfo:{updateObj}", ex);
|
||||
}
|
||||
}
|
||||
return await (await GetDbSimpleClientAsync()).UpdateAsync(updateObj);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,12 @@ namespace Yi.Framework.SqlSugarCore
|
||||
//设置codefirst非空值判断
|
||||
ConfigureExternalServices = new ConfigureExternalServices
|
||||
{
|
||||
// 处理表
|
||||
EntityNameService = (type, entity) =>
|
||||
{
|
||||
if (dbConnOptions.EnableUnderLine && !entity.DbTableName.Contains('_'))
|
||||
entity.DbTableName = UtilMethods.ToUnderLine(entity.DbTableName);// 驼峰转下划线
|
||||
},
|
||||
EntityService = (c, p) =>
|
||||
{
|
||||
if (new NullabilityInfoContext()
|
||||
@@ -72,6 +78,9 @@ namespace Yi.Framework.SqlSugarCore
|
||||
p.IsNullable = true;
|
||||
}
|
||||
|
||||
if (dbConnOptions.EnableUnderLine && !p.IsIgnore && !p.DbColumnName.Contains('_'))
|
||||
p.DbColumnName = UtilMethods.ToUnderLine(p.DbColumnName);// 驼峰转下划线
|
||||
|
||||
EntityService(c, p);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
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;
|
||||
@@ -17,6 +14,7 @@ using Volo.Abp.Guids;
|
||||
using Volo.Abp.MultiTenancy;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
using Check = Volo.Abp.Check;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
@@ -26,22 +24,23 @@ namespace Yi.Framework.SqlSugarCore
|
||||
/// SqlSugar 客户端
|
||||
/// </summary>
|
||||
public ISqlSugarClient SqlSugarClient { get; private set; }
|
||||
public ICurrentUser CurrentUser => LazyServiceProvider.GetRequiredService<ICurrentUser>();
|
||||
|
||||
protected ICurrentUser CurrentUser => LazyServiceProvider.GetRequiredService<ICurrentUser>();
|
||||
private IAbpLazyServiceProvider LazyServiceProvider { get; }
|
||||
|
||||
private IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetRequiredService<IGuidGenerator>();
|
||||
protected ILoggerFactory Logger => LazyServiceProvider.LazyGetRequiredService<ILoggerFactory>();
|
||||
private ILoggerFactory Logger => LazyServiceProvider.LazyGetRequiredService<ILoggerFactory>();
|
||||
private ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService<ICurrentTenant>();
|
||||
public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>();
|
||||
protected 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);
|
||||
private 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;
|
||||
|
||||
private ISerializeService SerializeService=> LazyServiceProvider.LazyGetRequiredService<ISerializeService>();
|
||||
|
||||
public void SetSqlSugarClient(ISqlSugarClient sqlSugarClient)
|
||||
{
|
||||
SqlSugarClient = sqlSugarClient;
|
||||
@@ -50,7 +49,6 @@ namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
LazyServiceProvider = lazyServiceProvider;
|
||||
var connectionCreator = LazyServiceProvider.LazyGetRequiredService<ISqlSugarDbConnectionCreator>();
|
||||
_dbConnectionCreator = connectionCreator;
|
||||
connectionCreator.OnSqlSugarClientConfig = OnSqlSugarClientConfig;
|
||||
connectionCreator.EntityService = EntityService;
|
||||
connectionCreator.DataExecuting = DataExecuting;
|
||||
@@ -62,7 +60,10 @@ namespace Yi.Framework.SqlSugarCore
|
||||
options.ConnectionString = GetCurrentConnectionString();
|
||||
options.DbType = GetCurrentDbType();
|
||||
}));
|
||||
//统一使用aop处理
|
||||
connectionCreator.SetDbAop(SqlSugarClient);
|
||||
//替换默认序列化器
|
||||
SqlSugarClient.CurrentConnectionConfig.ConfigureExternalServices.SerializeService = SerializeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -71,23 +72,12 @@ namespace Yi.Framework.SqlSugarCore
|
||||
/// <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();
|
||||
var connectionString = connectionStringResolver.ResolveAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
|
||||
//没有检测到使用多租户功能,默认使用默认库即可
|
||||
if (string.IsNullOrWhiteSpace(connectionString))
|
||||
{
|
||||
Volo.Abp.Check.NotNull(Options.Url, "租户默认库Defalut未找到");
|
||||
connectionString = defautlUrl;
|
||||
Check.NotNull(Options.Url, "dbUrl未配置");
|
||||
}
|
||||
return connectionString!;
|
||||
}
|
||||
@@ -102,7 +92,7 @@ namespace Yi.Framework.SqlSugarCore
|
||||
return dbTypeFromTenantName.Value;
|
||||
}
|
||||
}
|
||||
Volo.Abp.Check.NotNull(Options.DbType, "默认DbType未配置!");
|
||||
Check.NotNull(Options.DbType, "默认DbType未配置!");
|
||||
return Options.DbType!.Value;
|
||||
}
|
||||
|
||||
@@ -150,9 +140,9 @@ namespace Yi.Framework.SqlSugarCore
|
||||
}
|
||||
if (IsMultiTenantFilterEnabled)
|
||||
{
|
||||
//表达式不能放方法
|
||||
Guid? tenantId = CurrentTenant?.Id;
|
||||
sqlSugarClient.QueryFilter.AddTableFilter<IMultiTenant>(u => u.TenantId == tenantId);
|
||||
//表达式里只能有具体值,不能运算
|
||||
var expressionCurrentTenant = CurrentTenant.Id ?? null;
|
||||
sqlSugarClient.QueryFilter.AddTableFilter<IMultiTenant>(u => u.TenantId == expressionCurrentTenant);
|
||||
}
|
||||
CustomDataFilter(sqlSugarClient);
|
||||
}
|
||||
@@ -205,23 +195,22 @@ namespace Yi.Framework.SqlSugarCore
|
||||
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
|
||||
{
|
||||
//为空或者为默认最小值
|
||||
if (oldValue is null || DateTime.MinValue.Equals(oldValue))
|
||||
if (DateTime.MinValue.Equals(oldValue))
|
||||
{
|
||||
entityInfo.SetValue(DateTime.Now);
|
||||
}
|
||||
}
|
||||
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
|
||||
{
|
||||
if (CurrentUser.Id != null)
|
||||
if (CurrentUser.Id is not null)
|
||||
{
|
||||
entityInfo.SetValue(CurrentUser.Id);
|
||||
}
|
||||
}
|
||||
|
||||
//插入时,需要租户id,先预留
|
||||
|
||||
if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
|
||||
{
|
||||
if (CurrentTenant is not null)
|
||||
if (CurrentTenant.Id is not null)
|
||||
{
|
||||
entityInfo.SetValue(CurrentTenant.Id);
|
||||
}
|
||||
@@ -315,9 +304,11 @@ namespace Yi.Framework.SqlSugarCore
|
||||
/// <param name="column"></param>
|
||||
protected virtual void EntityService(PropertyInfo property, EntityColumnInfo column)
|
||||
{
|
||||
if (property.Name == "ConcurrencyStamp")
|
||||
if (property.Name == nameof(IHasConcurrencyStamp.ConcurrencyStamp)) //带版本号并发更新
|
||||
{
|
||||
column.IsIgnore = true;
|
||||
// column.IsOnlyIgnoreInsert = true;
|
||||
// column.IsOnlyIgnoreUpdate = true;
|
||||
column.IsEnableUpdateVersionValidation = true;
|
||||
}
|
||||
if (property.PropertyType == typeof(ExtraPropertyDictionary))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore;
|
||||
|
||||
public class NonPublicPropertiesResolver : DefaultContractResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// 重写获取属性,存在get set方法就可以写入
|
||||
/// </summary>
|
||||
/// <param name="member"></param>
|
||||
/// <param name="memberSerialization"></param>
|
||||
/// <returns></returns>
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
|
||||
{
|
||||
var prop = base.CreateProperty(member, memberSerialization);
|
||||
if (member is PropertyInfo pi)
|
||||
{
|
||||
prop.Readable = (pi.GetMethod != null);
|
||||
prop.Writable = (pi.SetMethod != null);
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
|
||||
public class SqlSugarNonPublicSerializer : ISerializeService
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认的序列化服务
|
||||
/// </summary>
|
||||
private readonly ISerializeService _serializeService = DefaultServices.Serialize;
|
||||
|
||||
public string SerializeObject(object value)
|
||||
{
|
||||
//保留原有实现
|
||||
return _serializeService.SerializeObject(value);
|
||||
}
|
||||
|
||||
public string SugarSerializeObject(object value)
|
||||
{ //保留原有实现
|
||||
return _serializeService.SugarSerializeObject(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写对象反序列化支持NoPublic访问器
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T DeserializeObject<T>(string value)
|
||||
{
|
||||
if (typeof(T).FullName.StartsWith("System.Text.Json."))
|
||||
{
|
||||
// 动态创建一个 JsonSerializer 实例
|
||||
Type serializerType =typeof(T).Assembly.GetType("System.Text.Json.JsonSerializer");
|
||||
|
||||
var methods = serializerType
|
||||
.GetMethods().Where(it=>it.Name== "Deserialize")
|
||||
.Where(it=>it.GetParameters().Any(z=>z.ParameterType==typeof(string))).First();
|
||||
|
||||
// 调用 SerializeObject 方法序列化对象
|
||||
T json = (T)methods.MakeGenericMethod(typeof(T))
|
||||
.Invoke(null, new object[] { value, null });
|
||||
return json;
|
||||
}
|
||||
var jSetting = new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver =new NonPublicPropertiesResolver() //替换默认解析器使能支持protect
|
||||
};
|
||||
return JsonConvert.DeserializeObject<T>(value, jSetting);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
||||
|
||||
public ISqlSugarDbContext GetDbContext()
|
||||
{
|
||||
|
||||
return _sqlsugarDbContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
||||
|
||||
//获取当前连接字符串,未多租户时,默认为空
|
||||
var connectionString = await ResolveConnectionStringAsync(connectionStringName);
|
||||
var dbContextKey = $"{this.GetType().FullName}_{connectionString}";
|
||||
var dbContextKey = $"{this.GetType().Name}_{connectionString}";
|
||||
|
||||
|
||||
var unitOfWork = UnitOfWorkManager.Current;
|
||||
|
||||
@@ -25,7 +25,8 @@ namespace Yi.Framework.SqlSugarCore
|
||||
{
|
||||
var service = context.Services;
|
||||
var configuration = service.GetConfiguration();
|
||||
Configure<DbConnOptions>(configuration.GetSection("DbConnOptions"));
|
||||
var section = configuration.GetSection("DbConnOptions");
|
||||
Configure<DbConnOptions>(section);
|
||||
|
||||
service.TryAddScoped<ISqlSugarDbContext, SqlSugarDbContext>();
|
||||
|
||||
@@ -39,7 +40,12 @@ namespace Yi.Framework.SqlSugarCore
|
||||
service.AddTransient(typeof(ISqlSugarRepository<,>), typeof(SqlSugarRepository<,>));
|
||||
|
||||
service.AddTransient(typeof(ISugarDbContextProvider<>), typeof(UnitOfWorkSqlsugarDbContextProvider<>));
|
||||
//替换Sqlsugar默认序列化器,用来解决.Select()不支持嵌套对象/匿名对象的非公有访问器 值无法绑定,如Id属性
|
||||
context.Services.AddSingleton<ISerializeService, SqlSugarNonPublicSerializer>();
|
||||
|
||||
var dbConfig = section.Get<DbConnOptions>();
|
||||
//将默认db传递给abp连接字符串模块
|
||||
Configure<AbpDbConnectionOptions>(x => { x.ConnectionStrings.Default = dbConfig.Url; });
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -50,8 +56,8 @@ namespace Yi.Framework.SqlSugarCore
|
||||
//进行CodeFirst
|
||||
var service = context.ServiceProvider;
|
||||
var options = service.GetRequiredService<IOptions<DbConnOptions>>().Value;
|
||||
|
||||
var _logger= service.GetRequiredService<ILogger<YiFrameworkSqlSugarCoreModule>>();
|
||||
|
||||
var logger = service.GetRequiredService<ILogger<YiFrameworkSqlSugarCoreModule>>();
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -65,13 +71,14 @@ namespace Yi.Framework.SqlSugarCore
|
||||
sb.AppendLine("===============================");
|
||||
|
||||
|
||||
_logger.LogInformation(sb.ToString());
|
||||
logger.LogInformation(sb.ToString());
|
||||
//Todo:准备支持多租户种子数据及CodeFirst
|
||||
|
||||
if (options.EnabledCodeFirst)
|
||||
{
|
||||
CodeFirst(service);
|
||||
}
|
||||
|
||||
if (options.EnabledDbSeed)
|
||||
{
|
||||
await DataSeedAsync(service);
|
||||
@@ -80,7 +87,6 @@ namespace Yi.Framework.SqlSugarCore
|
||||
|
||||
private void CodeFirst(IServiceProvider service)
|
||||
{
|
||||
|
||||
var moduleContainer = service.GetRequiredService<IModuleContainer>();
|
||||
var db = service.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient;
|
||||
|
||||
@@ -95,11 +101,11 @@ namespace Yi.Framework.SqlSugarCore
|
||||
.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)
|
||||
@@ -108,4 +114,4 @@ namespace Yi.Framework.SqlSugarCore
|
||||
await dataSeeder.SeedAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,11 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
public class DiscussGetListOutputDto : EntityDto<Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否禁止评论创建功能
|
||||
/// 是否禁止评论创建功能
|
||||
/// </summary>
|
||||
public bool IsDisableCreateComment { get; set; }
|
||||
/// <summary>
|
||||
/// 是否已点赞,默认未登录不点赞
|
||||
/// 是否已点赞,默认未登录不点赞
|
||||
/// </summary>
|
||||
public bool IsAgree { get; set; } = false;
|
||||
public string Title { get; set; }
|
||||
@@ -23,26 +23,26 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
public int AgreeNum { get; set; }
|
||||
public int SeeNum { get; set; }
|
||||
|
||||
//批量查询,不给内容,性能考虑
|
||||
//批量查询,不给内容,性能考虑
|
||||
//public string Content { get; set; }
|
||||
public string? Color { get; set; }
|
||||
|
||||
public Guid PlateId { get; set; }
|
||||
|
||||
//是否置顶,默认false
|
||||
//是否置顶,默认false
|
||||
public bool IsTop { get; set; }
|
||||
|
||||
public DiscussPermissionTypeEnum PermissionType { get; set; }
|
||||
//是否禁止,默认false
|
||||
//是否禁止,默认false
|
||||
public bool IsBan { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 封面
|
||||
/// 封面
|
||||
/// </summary>
|
||||
public string? Cover { get; set; }
|
||||
|
||||
//私有需要判断code权限
|
||||
//私有需要判断code权限
|
||||
public string? PrivateCode { get; set; }
|
||||
public DateTime CreationTime { get; set; }
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
Title = DiscussConst.Privacy;
|
||||
Introduction = "";
|
||||
Cover = null;
|
||||
//被禁止
|
||||
//被禁止
|
||||
IsBan = true;
|
||||
}
|
||||
}
|
||||
@@ -73,14 +73,14 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
case DiscussPermissionTypeEnum.Public:
|
||||
break;
|
||||
case DiscussPermissionTypeEnum.Oneself:
|
||||
//当前主题是仅自己可见,同时不是当前登录用户
|
||||
//当前主题是仅自己可见,同时不是当前登录用户
|
||||
if (dto.User.Id != userId)
|
||||
{
|
||||
dto.SetBan();
|
||||
}
|
||||
break;
|
||||
case DiscussPermissionTypeEnum.User:
|
||||
//当前主题为部分可见,同时不是当前登录用户 也 不在可见用户列表中
|
||||
//当前主题为部分可见,同时不是当前登录用户 也 不在可见用户列表中
|
||||
if (dto.User.Id != userId && !dto.PermissionUserIds.Contains(userId))
|
||||
{
|
||||
dto.SetBan();
|
||||
|
||||
@@ -17,9 +17,11 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
public class BbsForumAnalyseService : ApplicationService, IApplicationService
|
||||
{
|
||||
private ForumManager _forumManager;
|
||||
public BbsForumAnalyseService(ForumManager forumManager)
|
||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||
public BbsForumAnalyseService(ForumManager forumManager, ISqlSugarRepository<AgreeEntity> agreeRepository)
|
||||
{
|
||||
_forumManager = forumManager;
|
||||
_agreeRepository = agreeRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -38,7 +40,7 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
// IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
@@ -52,6 +54,26 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
|
||||
}, true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount);
|
||||
var discussId = output.Select(x => x.Id);
|
||||
//点赞字典,key为主题id,y为用户ids
|
||||
var agreeDic =
|
||||
(await _agreeRepository._DbQueryable.Where(x => discussId.Contains(x.DiscussId)).ToListAsync())
|
||||
.GroupBy(x => x.DiscussId)
|
||||
.ToDictionary(x => x.Key, y => y.Select(y => y.CreatorId).ToList());
|
||||
|
||||
//等级、是否点赞赋值
|
||||
output?.ForEach(x =>
|
||||
{
|
||||
if (CurrentUser.Id is not null)
|
||||
{
|
||||
//默认fasle
|
||||
if (agreeDic.TryGetValue(x.Id,out var userIds))
|
||||
{
|
||||
x.IsAgree = userIds.Contains(CurrentUser.Id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,19 +29,27 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// <summary>
|
||||
/// Discuss应用服务实现,用于参数校验、领域服务业务组合、日志记录、事务处理、账户信息
|
||||
/// </summary>
|
||||
public class DiscussService : YiCrudAppService<DiscussAggregateRoot, DiscussGetOutputDto, DiscussGetListOutputDto, Guid, DiscussGetListInputVo, DiscussCreateInputVo, DiscussUpdateInputVo>,
|
||||
IDiscussService
|
||||
public class DiscussService : YiCrudAppService<DiscussAggregateRoot, DiscussGetOutputDto, DiscussGetListOutputDto,
|
||||
Guid, DiscussGetListInputVo, DiscussCreateInputVo, DiscussUpdateInputVo>,
|
||||
IDiscussService
|
||||
{
|
||||
private ISqlSugarRepository<DiscussTopEntity> _discussTopEntityRepository;
|
||||
private ISqlSugarRepository<DiscussTopEntity> _discussTopRepository;
|
||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||
private BbsUserManager _bbsUserManager;
|
||||
public DiscussService(BbsUserManager bbsUserManager, ForumManager forumManager, ISqlSugarRepository<DiscussTopEntity> discussTopEntityRepository, ISqlSugarRepository<PlateAggregateRoot> plateEntityRepository, ILocalEventBus localEventBus) : base(forumManager._discussRepository)
|
||||
|
||||
public DiscussService(BbsUserManager bbsUserManager, ForumManager forumManager,
|
||||
ISqlSugarRepository<DiscussTopEntity> discussTopRepository,
|
||||
ISqlSugarRepository<PlateAggregateRoot> plateEntityRepository, ILocalEventBus localEventBus,
|
||||
ISqlSugarRepository<AgreeEntity> agreeRepository) : base(forumManager._discussRepository)
|
||||
{
|
||||
_forumManager = forumManager;
|
||||
_plateEntityRepository = plateEntityRepository;
|
||||
_localEventBus = localEventBus;
|
||||
_discussTopEntityRepository = discussTopEntityRepository;
|
||||
_bbsUserManager=bbsUserManager;
|
||||
_agreeRepository = agreeRepository;
|
||||
_discussTopRepository = discussTopRepository;
|
||||
_bbsUserManager = bbsUserManager;
|
||||
}
|
||||
|
||||
private readonly ILocalEventBus _localEventBus;
|
||||
private ForumManager _forumManager { get; set; }
|
||||
|
||||
@@ -49,8 +57,6 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
private ISqlSugarRepository<PlateAggregateRoot> _plateEntityRepository { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 单查
|
||||
/// </summary>
|
||||
@@ -58,42 +64,43 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// <returns></returns>
|
||||
public async override Task<DiscussGetOutputDto> GetAsync(Guid id)
|
||||
{
|
||||
|
||||
//查询主题发布 浏览主题 事件,浏览数+1
|
||||
var item = await _forumManager._discussRepository._DbQueryable.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
var item = await _forumManager._discussRepository._DbQueryable
|
||||
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||
.LeftJoin<PlateAggregateRoot>((discuss, user, info, plate) => plate.Id == discuss.PlateId)
|
||||
.Select((discuss, user, info, plate) => new DiscussGetOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Id = user.Id,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money=info.Money,
|
||||
Experience=info.Experience
|
||||
},
|
||||
Plate = new Contracts.Dtos.Plate.PlateGetOutputDto()
|
||||
{
|
||||
Name = plate.Name,
|
||||
Id = plate.Id,
|
||||
Code = plate.Code,
|
||||
Introduction = plate.Introduction,
|
||||
Logo = plate.Logo
|
||||
|
||||
}
|
||||
}, true)
|
||||
.SingleAsync(discuss => discuss.Id == id);
|
||||
.Select((discuss, user, info, plate) => new DiscussGetOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null,
|
||||
x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Id = user.Id,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money = info.Money,
|
||||
Experience = info.Experience
|
||||
},
|
||||
Plate = new Contracts.Dtos.Plate.PlateGetOutputDto()
|
||||
{
|
||||
Name = plate.Name,
|
||||
Id = plate.Id,
|
||||
Code = plate.Code,
|
||||
Introduction = plate.Introduction,
|
||||
Logo = plate.Logo
|
||||
}
|
||||
}, true)
|
||||
.SingleAsync(discuss => discuss.Id == id);
|
||||
|
||||
if (item is not null)
|
||||
{
|
||||
await VerifyDiscussPermissionAsync(item.Id);
|
||||
await _localEventBus.PublishAsync(new SeeDiscussEventArgs { DiscussId = item.Id, OldSeeNum = item.SeeNum });
|
||||
await _localEventBus.PublishAsync(new SeeDiscussEventArgs
|
||||
{ DiscussId = item.Id, OldSeeNum = item.SeeNum });
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -105,49 +112,65 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<PagedResultDto<DiscussGetListOutputDto>> GetListAsync([FromQuery] DiscussGetListInputVo input)
|
||||
public override async Task<PagedResultDto<DiscussGetListOutputDto>> GetListAsync(
|
||||
[FromQuery] DiscussGetListInputVo input)
|
||||
{
|
||||
//需要关联创建者用户
|
||||
RefAsync<int> total = 0;
|
||||
var items = await _forumManager._discussRepository._DbQueryable
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title))
|
||||
.WhereIF(input.PlateId is not null, x => x.PlateId == input.PlateId)
|
||||
.WhereIF(input.IsTop is not null, x => x.IsTop == input.IsTop)
|
||||
.WhereIF(input.UserId is not null,x=>x.CreatorId==input.UserId)
|
||||
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
.WhereIF(input.UserName is not null, (discuss, user)=>user.UserName==input.UserName!)
|
||||
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||
|
||||
.OrderByDescending(discuss => discuss.OrderNum)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.New, discuss => discuss.CreationTime, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Host, discuss => discuss.SeeNum, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Suggest, discuss => discuss.AgreeNum, OrderByType.Desc)
|
||||
|
||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
Id = user.Id,
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money = info.Money,
|
||||
Experience = info.Experience
|
||||
}
|
||||
|
||||
}, true)
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title))
|
||||
.WhereIF(input.PlateId is not null, x => x.PlateId == input.PlateId)
|
||||
.WhereIF(input.IsTop is not null, x => x.IsTop == input.IsTop)
|
||||
.WhereIF(input.UserId is not null, x => x.CreatorId == input.UserId)
|
||||
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
.WhereIF(input.UserName is not null, (discuss, user) => user.UserName == input.UserName!)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||
.OrderByDescending(discuss => discuss.OrderNum)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.New, discuss => discuss.CreationTime, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Host, discuss => discuss.SeeNum, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Suggest, discuss => discuss.AgreeNum, OrderByType.Desc)
|
||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
// 优化查询,不使用子查询
|
||||
// IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
Id = user.Id,
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money = info.Money,
|
||||
Experience = info.Experience
|
||||
}
|
||||
}, true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
var discussId = items.Select(x => x.Id);
|
||||
|
||||
//点赞字典,key为主题id,y为用户ids
|
||||
var agreeDic =
|
||||
(await _agreeRepository._DbQueryable.Where(x => discussId.Contains(x.DiscussId)).ToListAsync())
|
||||
.GroupBy(x => x.DiscussId)
|
||||
.ToDictionary(x => x.Key, y => y.Select(y => y.CreatorId).ToList());
|
||||
|
||||
//查询完主题之后,要过滤一下私有的主题信息
|
||||
items.ApplyPermissionTypeFilter(CurrentUser.Id ?? Guid.Empty);
|
||||
|
||||
items?.ForEach(x => x.User.LevelName = _bbsUserManager._levelCacheDic[x.User.Level].Name);
|
||||
//等级、是否点赞赋值
|
||||
items?.ForEach(x =>
|
||||
{
|
||||
x.User.LevelName = _bbsUserManager._levelCacheDic[x.User.Level].Name;
|
||||
if (CurrentUser.Id is not null)
|
||||
{
|
||||
//默认fasle
|
||||
if (agreeDic.TryGetValue(x.Id,out var userIds))
|
||||
{
|
||||
x.IsAgree = userIds.Contains(CurrentUser.Id);
|
||||
}
|
||||
}
|
||||
});
|
||||
return new PagedResultDto<DiscussGetListOutputDto>(total, items);
|
||||
}
|
||||
|
||||
@@ -157,14 +180,16 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// <returns></returns>
|
||||
public async Task<List<DiscussGetListOutputDto>> GetListTopAsync()
|
||||
{
|
||||
var output = await _discussTopEntityRepository._DbQueryable.LeftJoin<DiscussAggregateRoot>((top, discuss) => top.DiscussId == discuss.Id)
|
||||
var output = await _discussTopRepository._DbQueryable
|
||||
.LeftJoin<DiscussAggregateRoot>((top, discuss) => top.DiscussId == discuss.Id)
|
||||
.LeftJoin<UserAggregateRoot>((top, discuss, user) => discuss.CreatorId == user.Id)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((top, discuss, user, info) => user.Id == info.UserId)
|
||||
.OrderByDescending(top => top.OrderNum)
|
||||
.Select((top, discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null,
|
||||
x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto
|
||||
{
|
||||
Id = user.Id,
|
||||
@@ -206,6 +231,11 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
throw new UserFriendlyException(PlateConst.No_Exist);
|
||||
}
|
||||
|
||||
if (await _forumManager._discussRepository.IsAnyAsync(x => x.Title == input.Title))
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.Repeat);
|
||||
}
|
||||
|
||||
//如果开启了禁用创建主题
|
||||
if (plate.IsDisableCreateDiscuss == true)
|
||||
{
|
||||
@@ -233,6 +263,7 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.No_Exist);
|
||||
}
|
||||
|
||||
if (discuss.PermissionType == DiscussPermissionTypeEnum.Oneself)
|
||||
{
|
||||
if (discuss.CreatorId != CurrentUser.Id)
|
||||
@@ -240,13 +271,15 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
throw new UserFriendlyException(DiscussConst.Privacy);
|
||||
}
|
||||
}
|
||||
|
||||
if (discuss.PermissionType == DiscussPermissionTypeEnum.User)
|
||||
{
|
||||
if (discuss.CreatorId != CurrentUser.Id && !discuss.PermissionUserIds.Contains(CurrentUser.Id ?? Guid.Empty))
|
||||
if (discuss.CreatorId != CurrentUser.Id &&
|
||||
!discuss.PermissionUserIds.Contains(CurrentUser.Id ?? Guid.Empty))
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.Privacy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace Yi.Framework.Bbs.Domain.Shared.Consts
|
||||
/// </summary>
|
||||
public class DiscussConst
|
||||
{
|
||||
public const string Repeat = "创建主题重复";
|
||||
public const string No_Exist = "传入的主题id不存在";
|
||||
|
||||
public const string Privacy = "【私密】您无该主题权限,可联系作者申请开放";
|
||||
|
||||
@@ -5,24 +5,25 @@ public enum AssignmentRequirementTypeEnum
|
||||
/// <summary>
|
||||
/// 主题
|
||||
/// </summary>
|
||||
Discuss=2,
|
||||
|
||||
Discuss = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 评论
|
||||
/// </summary>
|
||||
Comment=4,
|
||||
|
||||
Comment = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 点赞
|
||||
/// </summary>
|
||||
Agree=8,
|
||||
|
||||
/// <summary>
|
||||
/// 更新个人中心
|
||||
/// </summary>
|
||||
UpdateProfile=16
|
||||
|
||||
|
||||
Agree = 8,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 更新昵称
|
||||
/// </summary>
|
||||
UpdateNick = 16,
|
||||
|
||||
/// <summary>
|
||||
/// 更新头像
|
||||
/// </summary>
|
||||
UpdateIcon = 32,
|
||||
}
|
||||
@@ -9,6 +9,7 @@ namespace Yi.Framework.Bbs.Domain.Entities.Forum
|
||||
[SugarTable("Discuss")]
|
||||
[SugarIndex($"index_{nameof(Title)}", nameof(Title), OrderByType.Asc)]
|
||||
[SugarIndex($"index_{nameof(PlateId)}", nameof(PlateId), OrderByType.Asc)]
|
||||
[SugarIndex($"index_{nameof(CreatorId)}", nameof(CreatorId), OrderByType.Asc)]
|
||||
[SugarIndex($"index_{nameof(CreationTime)}", nameof(CreationTime), OrderByType.Desc)]
|
||||
public class DiscussAggregateRoot : AggregateRoot<Guid>, ISoftDelete, IAuditedObject
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
|
||||
|
||||
//查询主题的信息
|
||||
var discussAndAgreeDto = await _agreeRepository._DbQueryable
|
||||
.Where(agree=>agree.Id==agreeEntity.Id)
|
||||
.LeftJoin<DiscussAggregateRoot>((agree, discuss) => agree.DiscussId == discuss.Id)
|
||||
.Select((agree, discuss) =>
|
||||
new
|
||||
|
||||
@@ -33,21 +33,27 @@ public class AssignmentEventHandler : ILocalEventHandler<AssignmentEventArgs>, I
|
||||
case AssignmentRequirementTypeEnum.Discuss:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.Discuss, currentAssignmentList);
|
||||
break;
|
||||
|
||||
|
||||
//发表评论
|
||||
case AssignmentRequirementTypeEnum.Comment:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.Comment, currentAssignmentList);
|
||||
break;
|
||||
|
||||
|
||||
//点赞
|
||||
case AssignmentRequirementTypeEnum.Agree:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.Agree, currentAssignmentList);
|
||||
break;
|
||||
|
||||
//更新个人信息
|
||||
case AssignmentRequirementTypeEnum.UpdateProfile:
|
||||
//这里还需判断是否更新了
|
||||
|
||||
//更新昵称
|
||||
case AssignmentRequirementTypeEnum.UpdateNick:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.UpdateNick, currentAssignmentList);
|
||||
break;
|
||||
|
||||
//更新头像
|
||||
case AssignmentRequirementTypeEnum.UpdateIcon:
|
||||
SetCurrentStepNumber(AssignmentRequirementTypeEnum.UpdateIcon, currentAssignmentList);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
@@ -72,7 +78,7 @@ public class AssignmentEventHandler : ILocalEventHandler<AssignmentEventArgs>, I
|
||||
x.CurrentStepNumber < x.TotalStepNumber)
|
||||
{
|
||||
x.CurrentStepNumber += 1;
|
||||
if (x.CurrentStepNumber==x.TotalStepNumber)
|
||||
if (x.CurrentStepNumber == x.TotalStepNumber)
|
||||
{
|
||||
x.AssignmentState = AssignmentStateEnum.Completed;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,70 @@
|
||||
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.Bbs.Domain.Entities.Assignment;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Managers.AssignmentProviders;
|
||||
|
||||
/// <summary>
|
||||
/// 新手任务提供者
|
||||
/// </summary>
|
||||
public class NoviceProvider : IAssignmentProvider
|
||||
[ExposeServices(typeof(IAssignmentProvider))]
|
||||
public class NoviceProvider : IAssignmentProvider
|
||||
{
|
||||
public async Task<List<AssignmentDefineAggregateRoot>> GetCanReceiveListAsync(AssignmentContext context)
|
||||
{
|
||||
List<AssignmentDefineAggregateRoot> output = new List<AssignmentDefineAggregateRoot>();
|
||||
//新手任务是要有前置依赖关系的,链表类型依赖
|
||||
throw new NotImplementedException();
|
||||
|
||||
//先获取到对应任务定义列表,新手任务
|
||||
var assignmentDefines = context.AllAssignmentDefine.Where(x => x.AssignmentType == AssignmentTypeEnum.Novice)
|
||||
.ToList();
|
||||
var assignmentDefineIds = assignmentDefines.Select(x => x.Id).ToList();
|
||||
|
||||
//根路径
|
||||
var rootAssignmentDefine = assignmentDefines.Where(x => x.PreAssignmentId == null).OrderBy(x=>x.OrderNum).FirstOrDefault();
|
||||
//代表没有定义新手任务
|
||||
if (rootAssignmentDefine is null)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
//1:查询该用户有正在进行的新手任务,如果有跳过
|
||||
if (context.CurrentUserAssignments
|
||||
.Where(x => assignmentDefineIds.Contains(x.AssignmentDefineId))
|
||||
.Any(x => x.AssignmentState == AssignmentStateEnum.Progress))
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
//2: 查询该用户是否有完成的新手任务,如果没有,直接返回根节点,如果有,则根据链表选择最后的节点
|
||||
var assignmentFilterIds = context.CurrentUserAssignments
|
||||
.Where(x => assignmentDefineIds.Contains(x.AssignmentDefineId))
|
||||
.Where(x =>
|
||||
//已经完成的
|
||||
x.AssignmentState == AssignmentStateEnum.End||
|
||||
x.AssignmentState==AssignmentStateEnum.Completed
|
||||
)
|
||||
.Select(x => x.AssignmentDefineId)
|
||||
.ToList();
|
||||
|
||||
if (assignmentFilterIds.Count == 0)
|
||||
{
|
||||
output.Add(rootAssignmentDefine);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
//该用户接受的最后一个新手任务
|
||||
var lastAssignment = assignmentDefines.Where(x => assignmentFilterIds.Contains(x.Id))
|
||||
.OrderByDescending(x => x.OrderNum).First();
|
||||
|
||||
//包含比该用户还要大的任务
|
||||
if (assignmentDefines.Any(x => x.OrderNum > lastAssignment.OrderNum))
|
||||
{
|
||||
output.Add(assignmentDefines.FirstOrDefault(x => x.OrderNum == lastAssignment.OrderNum + 1));
|
||||
return output;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,12 @@
|
||||
/// <summary>
|
||||
/// 账号
|
||||
/// </summary>
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一标识码
|
||||
@@ -29,5 +29,11 @@
|
||||
/// 验证码
|
||||
/// </summary>
|
||||
public string? Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 昵称
|
||||
/// </summary>
|
||||
public string? Nick{ get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
|
||||
|
||||
public class RetrievePasswordDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一标识码
|
||||
/// </summary>
|
||||
public string? Uuid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 电话
|
||||
/// </summary>
|
||||
public long Phone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证码
|
||||
/// </summary>
|
||||
public string? Code { get; set; }
|
||||
}
|
||||
@@ -3,5 +3,6 @@
|
||||
public class UpdateIconDto
|
||||
{
|
||||
public string? Icon { get; set; }
|
||||
public Guid? UserId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,17 @@ using Yi.Framework.Ddd.Application.Contracts;
|
||||
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置查询参数
|
||||
/// 配置查询参数
|
||||
/// </summary>
|
||||
public class ConfigGetListInputVo : PagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置名称
|
||||
/// 配置名称
|
||||
/// </summary>
|
||||
public string? ConfigName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 配置键
|
||||
/// 配置键
|
||||
/// </summary>
|
||||
public string? ConfigKey { get; set; }
|
||||
|
||||
|
||||
@@ -5,14 +5,11 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Dept
|
||||
/// </summary>
|
||||
public class DeptCreateInputVo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime CreationTime { get; set; } = DateTime.Now;
|
||||
public Guid? CreatorId { get; set; }
|
||||
public bool State { get; set; }
|
||||
public string DeptName { get; set; } = string.Empty;
|
||||
public string DeptCode { get; set; } = string.Empty;
|
||||
public string DeptName { get; set; }
|
||||
public string DeptCode { get; set; }
|
||||
public string? Leader { get; set; }
|
||||
public Guid ParentId { get; set; }
|
||||
public Guid? ParentId { get; set; }=Guid.Empty;
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,11 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Dept
|
||||
{
|
||||
public class DeptUpdateInputVo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime CreationTime { get; set; } = DateTime.Now;
|
||||
public Guid? CreatorId { get; set; }
|
||||
public bool State { get; set; }
|
||||
public string DeptName { get; set; } = string.Empty;
|
||||
public string DeptCode { get; set; } = string.Empty;
|
||||
public string? Leader { get; set; }
|
||||
public Guid ParentId { get; set; }
|
||||
public Guid? ParentId { get; set; }=Guid.Empty;
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Menu
|
||||
/// </summary>
|
||||
public class MenuCreateInputVo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid? Id { get; set; }
|
||||
public DateTime CreationTime { get; set; } = DateTime.Now;
|
||||
public Guid? CreatorId { get; set; }
|
||||
public bool State { get; set; }
|
||||
@@ -24,5 +24,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Menu
|
||||
public string? Component { get; set; }
|
||||
public string? Query { get; set; }
|
||||
public int OrderNum { get; set; }
|
||||
public MenuSourceEnum MenuSource { get; set; } = MenuSourceEnum.Ruoyi;
|
||||
public string? RouterName { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Menu
|
||||
{
|
||||
@@ -7,6 +8,6 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Menu
|
||||
|
||||
public bool? State { get; set; }
|
||||
public string? MenuName { get; set; }
|
||||
|
||||
public MenuSourceEnum MenuSource { get; set; } = MenuSourceEnum.Ruoyi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Menu
|
||||
public string? Component { get; set; }
|
||||
public string? Query { get; set; }
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
//public List<MenuEntity>? Children { get; set; }
|
||||
public string? RouterName { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,9 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Post
|
||||
/// </summary>
|
||||
public class PostCreateInputVo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime CreationTime { get; set; } = DateTime.Now;
|
||||
public long? CreatorId { get; set; }
|
||||
public bool? State { get; set; }
|
||||
public string PostCode { get; set; } = string.Empty;
|
||||
public string PostName { get; set; } = string.Empty;
|
||||
public string PostCode { get; set; }
|
||||
public string PostName { get; set; }
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,9 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Post
|
||||
{
|
||||
public class PostUpdateInputVo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime CreationTime { get; set; } = DateTime.Now;
|
||||
public Guid? CreatorId { get; set; }
|
||||
public bool? State { get; set; }
|
||||
public string PostCode { get; set; } = string.Empty;
|
||||
public string PostName { get; set; } = string.Empty;
|
||||
public string PostCode { get; set; }
|
||||
public string PostName { get; set; }
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.Ddd.Application.Contracts\Yi.Framework.Ddd.Application.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\bbs\Yi.Framework.Bbs.Domain.Shared\Yi.Framework.Bbs.Domain.Shared.csproj" />
|
||||
<ProjectReference Include="..\Yi.Framework.Rbac.Domain.Shared\Yi.Framework.Rbac.Domain.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using Lazy.Captcha.Core;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SqlSugar;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Authorization;
|
||||
using Volo.Abp.Caching;
|
||||
using Volo.Abp.EventBus.Local;
|
||||
using Volo.Abp.Guids;
|
||||
using Volo.Abp.Uow;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
@@ -21,14 +27,16 @@ using Yi.Framework.Rbac.Domain.Repositories;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Caches;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Etos;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Options;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
|
||||
public class AccountService : ApplicationService, IAccountService
|
||||
{
|
||||
protected ILocalEventBus LocalEventBus => LazyServiceProvider.LazyGetRequiredService<ILocalEventBus>();
|
||||
private IDistributedCache<CaptchaPhoneCacheItem, CaptchaPhoneCacheKey> _phoneCache;
|
||||
private readonly ICaptcha _captcha;
|
||||
private readonly IGuidGenerator _guidGenerator;
|
||||
@@ -36,6 +44,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
private readonly IAliyunManger _aliyunManger;
|
||||
private IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> _userCache;
|
||||
private UserManager _userManager;
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public AccountService(IUserRepository userRepository,
|
||||
ICurrentUser currentUser,
|
||||
IAccountManager accountManager,
|
||||
@@ -46,7 +56,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
IGuidGenerator guidGenerator,
|
||||
IOptions<RbacOptions> options,
|
||||
IAliyunManger aliyunManger,
|
||||
UserManager userManager)
|
||||
UserManager userManager, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_currentUser = currentUser;
|
||||
@@ -59,6 +69,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
_aliyunManger = aliyunManger;
|
||||
_userCache = userCache;
|
||||
_userManager = userManager;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +77,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
private ICurrentUser _currentUser;
|
||||
private IAccountManager _accountManager;
|
||||
private ISqlSugarRepository<MenuAggregateRoot> _menuRepository;
|
||||
|
||||
/// <summary>
|
||||
/// 校验图片登录验证码,无需和账号绑定
|
||||
/// </summary>
|
||||
@@ -83,7 +95,6 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 登录
|
||||
/// </summary>
|
||||
@@ -104,10 +115,21 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
//校验
|
||||
await _accountManager.LoginValidationAsync(input.UserName, input.Password, x => user = x);
|
||||
|
||||
var userInfo = new UserRoleMenuDto();
|
||||
//获取token
|
||||
var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id);
|
||||
var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id, (info) => userInfo = info);
|
||||
var refreshToken = _accountManager.CreateRefreshToken(user.Id);
|
||||
|
||||
//这里抛出一个登录的事件,也可以在全部流程走完,在应用层组装
|
||||
if (_httpContextAccessor.HttpContext is not null)
|
||||
{
|
||||
var loginEntity = new LoginLogAggregateRoot().GetInfoByHttpContext(_httpContextAccessor.HttpContext);
|
||||
var loginEto = loginEntity.Adapt<LoginEventArgs>();
|
||||
loginEto.UserName = userInfo.User.UserName;
|
||||
loginEto.UserId = userInfo.User.Id;
|
||||
await LocalEventBus.PublishAsync(loginEto);
|
||||
}
|
||||
|
||||
return new { Token = accessToken, RefreshToken = refreshToken };
|
||||
}
|
||||
|
||||
@@ -130,7 +152,6 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// 生成验证码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<CaptchaImageDto> GetCaptchaImageAsync()
|
||||
{
|
||||
@@ -143,37 +164,62 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// 验证电话号码
|
||||
/// </summary>
|
||||
/// <param name="str_handset"></param>
|
||||
private async Task ValidationPhone(string str_handset)
|
||||
private async Task ValidationPhone(string phone)
|
||||
{
|
||||
var res = Regex.IsMatch(str_handset, @"^\d{11}$");
|
||||
var res = Regex.IsMatch(phone, @"^\d{11}$");
|
||||
if (res == false)
|
||||
{
|
||||
throw new UserFriendlyException("手机号码格式错误!请检查");
|
||||
}
|
||||
if (await _userRepository.IsAnyAsync(x => x.Phone.ToString() == str_handset))
|
||||
{
|
||||
throw new UserFriendlyException("该手机号已被注册!");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 注册 手机验证码
|
||||
/// 手机验证码-注册
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("account/captcha-phone")]
|
||||
[AllowAnonymous]
|
||||
public async Task<object> PostCaptchaPhoneForRegisterAsync(PhoneCaptchaImageDto input)
|
||||
{
|
||||
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.Register, input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手机验证码-找回密码
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("account/captcha-phone/repassword")]
|
||||
public async Task<object> PostCaptchaPhoneForRetrievePasswordAsync(PhoneCaptchaImageDto input)
|
||||
{
|
||||
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.RetrievePassword, input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手机验证码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
public async Task<object> PostCaptchaPhone(PhoneCaptchaImageDto input)
|
||||
private async Task<object> PostCaptchaPhoneAsync(ValidationPhoneTypeEnum validationPhoneType,
|
||||
PhoneCaptchaImageDto input)
|
||||
{
|
||||
await ValidationPhone(input.Phone);
|
||||
var value = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(input.Phone));
|
||||
|
||||
//注册的手机号验证,是不能已经注册过的
|
||||
if (validationPhoneType == ValidationPhoneTypeEnum.Register&& await _userRepository.IsAnyAsync(x => x.Phone.ToString() == input.Phone))
|
||||
{
|
||||
throw new UserFriendlyException("该手机号已被注册!");
|
||||
}
|
||||
|
||||
var value = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(validationPhoneType, input.Phone));
|
||||
|
||||
//防止暴刷
|
||||
if (value is not null)
|
||||
{
|
||||
throw new UserFriendlyException($"{input.Phone}已发送过验证码,10分钟后可重试");
|
||||
}
|
||||
|
||||
//生成一个4位数的验证码
|
||||
//发送短信,同时生成uuid
|
||||
////key: 电话号码 value:验证码+uuid
|
||||
@@ -181,7 +227,9 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
var uuid = Guid.NewGuid();
|
||||
await _aliyunManger.SendSmsAsync(input.Phone, code);
|
||||
|
||||
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(input.Phone), new CaptchaPhoneCacheItem(code), new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
|
||||
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(validationPhoneType, input.Phone),
|
||||
new CaptchaPhoneCacheItem(code),
|
||||
new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
|
||||
return new
|
||||
{
|
||||
Uuid = uuid
|
||||
@@ -191,18 +239,43 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// <summary>
|
||||
/// 校验电话验证码,需要与电话号码绑定
|
||||
/// </summary>
|
||||
private async Task ValidationPhoneCaptchaAsync(RegisterDto input)
|
||||
private async Task ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum validationPhoneType, long phone,
|
||||
string code)
|
||||
{
|
||||
var item = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
|
||||
if (item is not null && item.Code.Equals($"{input.Code}"))
|
||||
var item = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(validationPhoneType, phone.ToString()));
|
||||
if (item is not null && item.Code.Equals($"{code}"))
|
||||
{
|
||||
//成功,需要清空
|
||||
await _phoneCache.RemoveAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
|
||||
await _phoneCache.RemoveAsync(new CaptchaPhoneCacheKey(validationPhoneType, code.ToString()));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UserFriendlyException("验证码错误");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 找回密码
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
[AllowAnonymous]
|
||||
[UnitOfWork]
|
||||
public async Task<string> PostRetrievePasswordAsync(RetrievePasswordDto input)
|
||||
{
|
||||
//校验验证码,根据电话号码获取 value,比对验证码已经uuid
|
||||
await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.RetrievePassword, input.Phone, input.Code);
|
||||
|
||||
var entity = await _userRepository.GetFirstAsync(x => x.Phone == input.Phone);
|
||||
if (entity is null)
|
||||
{
|
||||
throw new UserFriendlyException("该手机号码未注册");
|
||||
}
|
||||
|
||||
await _accountManager.RestPasswordAsync(entity.Id, input.Password);
|
||||
|
||||
return entity.UserName;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 注册,需要验证码通过
|
||||
/// </summary>
|
||||
@@ -216,23 +289,24 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
throw new UserFriendlyException("该系统暂未开放注册功能");
|
||||
}
|
||||
|
||||
if (_rbacOptions.EnableCaptcha)
|
||||
{
|
||||
//校验验证码,根据电话号码获取 value,比对验证码已经uuid
|
||||
await ValidationPhoneCaptchaAsync(input);
|
||||
await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.Register, input.Phone, input.Code);
|
||||
}
|
||||
|
||||
//注册领域逻辑
|
||||
await _accountManager.RegisterAsync(input.UserName, input.Password, input.Phone);
|
||||
await _accountManager.RegisterAsync(input.UserName, input.Password, input.Phone, input.Nick);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 查询已登录的账户信息,已缓存
|
||||
/// 查询已登录的账户信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Route("account")]
|
||||
[Authorize]
|
||||
|
||||
public async Task<UserRoleMenuDto> GetAsync()
|
||||
{
|
||||
//通过鉴权jwt获取到用户的id
|
||||
@@ -241,6 +315,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
throw new UserFriendlyException("用户未登录");
|
||||
}
|
||||
|
||||
//此处优先从缓存中获取
|
||||
var output = await _userManager.GetInfoAsync(userId.Value);
|
||||
return output;
|
||||
@@ -249,18 +324,19 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前登录用户的前端路由
|
||||
/// 支持ruoyi/pure
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
[Route("account/Vue3Router")]
|
||||
public async Task<List<Vue3RouterDto>> GetVue3Router()
|
||||
[Route("account/Vue3Router/{routerType?}")]
|
||||
public async Task<object> GetVue3Router([FromRoute] string? routerType)
|
||||
{
|
||||
var userId = _currentUser.Id;
|
||||
if (_currentUser.Id is null)
|
||||
{
|
||||
throw new AbpAuthorizationException("用户未登录");
|
||||
|
||||
}
|
||||
|
||||
var data = await _userManager.GetInfoAsync(userId!.Value);
|
||||
var menus = data.Menus.ToList();
|
||||
|
||||
@@ -269,9 +345,22 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
menus = ObjectMapper.Map<List<MenuAggregateRoot>, List<MenuDto>>(await _menuRepository.GetListAsync());
|
||||
}
|
||||
//将后端菜单转换成前端路由,组件级别需要过滤
|
||||
List<Vue3RouterDto> routers = ObjectMapper.Map<List<MenuDto>, List<MenuAggregateRoot>>(menus).Vue3RouterBuild();
|
||||
return routers;
|
||||
|
||||
object output = null;
|
||||
if (routerType is null || routerType == "ruoyi")
|
||||
{
|
||||
//将后端菜单转换成前端路由,组件级别需要过滤
|
||||
output =
|
||||
ObjectMapper.Map<List<MenuDto>, List<MenuAggregateRoot>>(menus).Vue3RuoYiRouterBuild();
|
||||
}
|
||||
else if (routerType == "pure")
|
||||
{
|
||||
//将后端菜单转换成前端路由,组件级别需要过滤
|
||||
output =
|
||||
ObjectMapper.Map<List<MenuDto>, List<MenuAggregateRoot>>(menus).Vue3PureRouterBuild();
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -287,6 +376,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
return false;
|
||||
// throw new UserFriendlyException("用户已退出");
|
||||
}
|
||||
|
||||
await _userCache.RemoveAsync(new UserInfoCacheKey(userId.Value));
|
||||
//Jwt去中心化登出,只需用记录日志即可
|
||||
return true;
|
||||
@@ -303,11 +393,14 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
throw new UserFriendlyException("无效更新!输入的数据,新密码不能与老密码相同");
|
||||
}
|
||||
|
||||
if (_currentUser.Id is null)
|
||||
{
|
||||
throw new UserFriendlyException("用户未登录");
|
||||
}
|
||||
await _accountManager.UpdatePasswordAsync(_currentUser.Id ?? Guid.Empty, input.NewPassword, input.OldPassword);
|
||||
|
||||
await _accountManager.UpdatePasswordAsync(_currentUser.Id ?? Guid.Empty, input.NewPassword,
|
||||
input.OldPassword);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -324,6 +417,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
throw new UserFriendlyException("重置密码不能为空!");
|
||||
}
|
||||
|
||||
await _accountManager.RestPasswordAsync(userId, input.Password);
|
||||
return true;
|
||||
}
|
||||
@@ -335,11 +429,22 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// <returns></returns>
|
||||
public async Task<bool> UpdateIconAsync(UpdateIconDto input)
|
||||
{
|
||||
var entity = await _userRepository.GetByIdAsync(_currentUser.Id);
|
||||
Guid userId=input.UserId == null?_currentUser.GetId():input.UserId.Value;
|
||||
|
||||
var entity = await _userRepository.GetByIdAsync(userId);
|
||||
|
||||
if (entity.Icon == input.Icon)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
entity.Icon = input.Icon;
|
||||
await _userRepository.UpdateAsync(entity);
|
||||
|
||||
//发布更新头像任务事件
|
||||
await this.LocalEventBus.PublishAsync(
|
||||
new AssignmentEventArgs(AssignmentRequirementTypeEnum.UpdateIcon, userId), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.Config;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Services
|
||||
@@ -12,10 +13,12 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// <summary>
|
||||
/// Config服务实现
|
||||
/// </summary>
|
||||
public class ConfigService : YiCrudAppService<ConfigAggregateRoot, ConfigGetOutputDto, ConfigGetListOutputDto, Guid, ConfigGetListInputVo, ConfigCreateInputVo, ConfigUpdateInputVo>,
|
||||
IConfigService
|
||||
public class ConfigService : YiCrudAppService<ConfigAggregateRoot, ConfigGetOutputDto, ConfigGetListOutputDto, Guid,
|
||||
ConfigGetListInputVo, ConfigCreateInputVo, ConfigUpdateInputVo>,
|
||||
IConfigService
|
||||
{
|
||||
private ISqlSugarRepository<ConfigAggregateRoot, Guid> _repository;
|
||||
|
||||
public ConfigService(ISqlSugarRepository<ConfigAggregateRoot, Guid> repository) : base(repository)
|
||||
{
|
||||
_repository = repository;
|
||||
@@ -30,11 +33,33 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.ConfigKey), x => x.ConfigKey.Contains(input.ConfigKey!))
|
||||
.WhereIF(!string.IsNullOrEmpty(input.ConfigName), x => x.ConfigName!.Contains(input.ConfigName!))
|
||||
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.ConfigKey),
|
||||
x => x.ConfigKey.Contains(input.ConfigKey!))
|
||||
.WhereIF(!string.IsNullOrEmpty(input.ConfigName), x => x.ConfigName!.Contains(input.ConfigName!))
|
||||
.WhereIF(input.StartTime is not null && input.EndTime is not null,
|
||||
x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<ConfigGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
protected override async Task CheckCreateInputDtoAsync(ConfigCreateInputVo input)
|
||||
{
|
||||
var isExist =
|
||||
await _repository.IsAnyAsync(x => x.ConfigKey == input.ConfigKey);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(ConfigConst.Exist);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task CheckUpdateInputDtoAsync(ConfigAggregateRoot entity, ConfigUpdateInputVo input)
|
||||
{
|
||||
var isExist = await _repository._DbQueryable.Where(x => x.Id != entity.Id)
|
||||
.AnyAsync(x => x.ConfigKey == input.ConfigKey);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(ConfigConst.Exist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.Dictionary;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
|
||||
@@ -14,26 +15,30 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// <summary>
|
||||
/// Dictionary服务实现
|
||||
/// </summary>
|
||||
public class DictionaryService : YiCrudAppService<DictionaryEntity, DictionaryGetOutputDto, DictionaryGetListOutputDto, Guid, DictionaryGetListInputVo, DictionaryCreateInputVo, DictionaryUpdateInputVo>,
|
||||
IDictionaryService
|
||||
public class DictionaryService : YiCrudAppService<DictionaryEntity, DictionaryGetOutputDto,
|
||||
DictionaryGetListOutputDto, Guid, DictionaryGetListInputVo, DictionaryCreateInputVo,
|
||||
DictionaryUpdateInputVo>,
|
||||
IDictionaryService
|
||||
{
|
||||
private ISqlSugarRepository<DictionaryEntity, Guid> _repository;
|
||||
|
||||
public DictionaryService(ISqlSugarRepository<DictionaryEntity, Guid> repository) : base(repository)
|
||||
{
|
||||
_repository= repository;
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询
|
||||
/// </summary>
|
||||
|
||||
public override async Task<PagedResultDto<DictionaryGetListOutputDto>> GetListAsync(DictionaryGetListInputVo input)
|
||||
public override async Task<PagedResultDto<DictionaryGetListOutputDto>> GetListAsync(
|
||||
DictionaryGetListInputVo input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
var entities = await _repository._DbQueryable.WhereIF(input.DictType is not null, x => x.DictType == input.DictType)
|
||||
.WhereIF(input.DictLabel is not null, x => x.DictLabel!.Contains(input.DictLabel!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
var entities = await _repository._DbQueryable
|
||||
.WhereIF(input.DictType is not null, x => x.DictType == input.DictType)
|
||||
.WhereIF(input.DictLabel is not null, x => x.DictLabel!.Contains(input.DictLabel!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<DictionaryGetListOutputDto>
|
||||
{
|
||||
TotalCount = total,
|
||||
@@ -55,4 +60,4 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.DictionaryType;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Services
|
||||
@@ -22,7 +23,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async override Task<PagedResultDto<DictionaryTypeGetListOutputDto>> GetListAsync(DictionaryTypeGetListInputVo input)
|
||||
public override async Task<PagedResultDto<DictionaryTypeGetListOutputDto>> GetListAsync(DictionaryTypeGetListInputVo input)
|
||||
{
|
||||
|
||||
RefAsync<int> total = 0;
|
||||
@@ -38,5 +39,25 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
Items = await MapToGetListOutputDtosAsync(entities)
|
||||
};
|
||||
}
|
||||
|
||||
protected override async Task CheckCreateInputDtoAsync(DictionaryTypeCreateInputVo input)
|
||||
{
|
||||
var isExist =
|
||||
await _repository.IsAnyAsync(x => x.DictType == input.DictType);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(DictionaryConst.Exist);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task CheckUpdateInputDtoAsync(DictionaryTypeAggregateRoot entity, DictionaryTypeUpdateInputVo input)
|
||||
{
|
||||
var isExist = await _repository._DbQueryable.Where(x => x.Id != entity.Id)
|
||||
.AnyAsync(x => x.DictType == input.DictType);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(DictionaryConst.Exist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new UserFriendlyException("文件不存在",code:"404");
|
||||
return new NotFoundResult();
|
||||
// throw new UserFriendlyException("文件不存在",code:"404");
|
||||
}
|
||||
|
||||
|
||||
@@ -66,12 +67,6 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
// path = $"wwwroot/{FileTypeEnum.Thumbnail}/{file.Id}{Path.GetExtension(file.FileName)}";
|
||||
//}
|
||||
//路径为: 文件路径/文件id+文件扩展名
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new UserFriendlyException("本地文件不存在", "404");
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Yi.Framework.Rbac.Application.Services.Monitor
|
||||
[HttpGet("monitor-server/info")]
|
||||
public object GetInfo()
|
||||
{
|
||||
int cpuNum = Environment.ProcessorCount;
|
||||
|
||||
string computerName = Environment.MachineName;
|
||||
string osName = RuntimeInformation.OSDescription;
|
||||
string osArch = RuntimeInformation.OSArchitecture.ToString();
|
||||
@@ -35,9 +35,10 @@ namespace Yi.Framework.Rbac.Application.Services.Monitor
|
||||
string programRunTime = DateTimeHelper.FormatTime(long.Parse((DateTime.Now - programStartTime).TotalMilliseconds.ToString().Split('.')[0]));
|
||||
var data = new
|
||||
{
|
||||
cpu = ComputerHelper.GetComputerInfo(),
|
||||
memory = ComputerHelper.GetMemoryMetrics(),
|
||||
cpu = ComputerHelper.GetCPUMetrics(),
|
||||
disk = ComputerHelper.GetDiskInfos(),
|
||||
sys = new { cpuNum, computerName, osName, osArch, serverIP, runTime = sysRunTime },
|
||||
sys = new {computerName, osName, osArch, serverIP, runTime = sysRunTime },
|
||||
app = new
|
||||
{
|
||||
name = _hostEnvironment.EnvironmentName,
|
||||
|
||||
@@ -41,8 +41,6 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
return new PagedResultDto<NoticeGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 发送在线消息
|
||||
/// </summary>
|
||||
|
||||
@@ -20,10 +20,12 @@ namespace Yi.Framework.Rbac.Application.Services.RecordLog
|
||||
public override async Task<PagedResultDto<LoginLogGetListOutputDto>> GetListAsync(LoginLogGetListInputVo input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
|
||||
if (input.Sorting.IsNullOrWhiteSpace())
|
||||
input.Sorting = $"{nameof(LoginLogAggregateRoot.CreationTime)} Desc";
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.LoginIp), x => x.LoginIp.Contains(input.LoginIp!))
|
||||
.WhereIF(!string.IsNullOrEmpty(input.LoginUser), x => x.LoginUser!.Contains(input.LoginUser!))
|
||||
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||
.OrderBy(input.Sorting)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<LoginLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
@@ -24,9 +24,12 @@ namespace Yi.Framework.Rbac.Application.Services.RecordLog
|
||||
public override async Task<PagedResultDto<OperationLogGetListOutputDto>> GetListAsync(OperationLogGetListInputVo input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
if (input.Sorting.IsNullOrWhiteSpace())
|
||||
input.Sorting = $"{nameof(OperationLogEntity.CreationTime)} Desc";
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.OperUser), x => x.OperUser.Contains(input.OperUser!))
|
||||
.WhereIF(input.OperType is not null, x => x.OperType == input.OperType)
|
||||
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||
.OrderBy(input.Sorting)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<OperationLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.Dept;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Repositories;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Services.System
|
||||
{
|
||||
/// <summary>
|
||||
/// Dept服务实现
|
||||
/// </summary>
|
||||
public class DeptService : YiCrudAppService<DeptAggregateRoot, DeptGetOutputDto, DeptGetListOutputDto, Guid, DeptGetListInputVo, DeptCreateInputVo, DeptUpdateInputVo>, IDeptService
|
||||
public class DeptService : YiCrudAppService<DeptAggregateRoot, DeptGetOutputDto, DeptGetListOutputDto, Guid,
|
||||
DeptGetListInputVo, DeptCreateInputVo, DeptUpdateInputVo>, IDeptService
|
||||
{
|
||||
private IDeptRepository _deptRepository;
|
||||
public DeptService(IDeptRepository deptRepository) : base(deptRepository)
|
||||
{ _deptRepository = deptRepository; }
|
||||
private IDeptRepository _repository;
|
||||
|
||||
public DeptService(IDeptRepository repository) : base(repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
[RemoteService(false)]
|
||||
public async Task<List<Guid>> GetChildListAsync(Guid deptId)
|
||||
{
|
||||
return await _deptRepository.GetChildListAsync(deptId);
|
||||
return await _repository.GetChildListAsync(deptId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -32,7 +35,7 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
//[Route("{roleId}")]
|
||||
public async Task<List<DeptGetListOutputDto>> GetRoleIdAsync(Guid roleId)
|
||||
{
|
||||
var entities = await _deptRepository.GetListRoleIdAsync(roleId);
|
||||
var entities = await _repository.GetListRoleIdAsync(roleId);
|
||||
return await MapToGetListOutputDtosAsync(entities);
|
||||
}
|
||||
|
||||
@@ -44,16 +47,36 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
public override async Task<PagedResultDto<DeptGetListOutputDto>> GetListAsync(DeptGetListInputVo input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
var entities = await _deptRepository._DbQueryable
|
||||
.WhereIF(!string.IsNullOrEmpty(input.DeptName), u => u.DeptName.Contains(input.DeptName!))
|
||||
.WhereIF(input.State is not null, u => u.State == input.State)
|
||||
.OrderBy(u => u.OrderNum, OrderByType.Asc)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
var entities = await _repository._DbQueryable
|
||||
.WhereIF(!string.IsNullOrEmpty(input.DeptName), u => u.DeptName.Contains(input.DeptName!))
|
||||
.WhereIF(input.State is not null, u => u.State == input.State)
|
||||
.OrderBy(u => u.OrderNum, OrderByType.Asc)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<DeptGetListOutputDto>
|
||||
{
|
||||
Items = await MapToGetListOutputDtosAsync(entities),
|
||||
TotalCount = total
|
||||
};
|
||||
}
|
||||
|
||||
protected override async Task CheckCreateInputDtoAsync(DeptCreateInputVo input)
|
||||
{
|
||||
var isExist =
|
||||
await _repository.IsAnyAsync(x => x.DeptCode == input.DeptCode);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(DeptConst.Exist);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task CheckUpdateInputDtoAsync(DeptAggregateRoot entity, DeptUpdateInputVo input)
|
||||
{
|
||||
var isExist = await _repository._DbQueryable.Where(x => x.Id != entity.Id)
|
||||
.AnyAsync(x => x.DeptCode == input.DeptCode);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(DeptConst.Exist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.Menu;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Services.System
|
||||
@@ -23,14 +23,12 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
|
||||
public override async Task<PagedResultDto<MenuGetListOutputDto>> GetListAsync(MenuGetListInputVo input)
|
||||
{
|
||||
|
||||
RefAsync<int> total = 0;
|
||||
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.MenuName), x => x.MenuName.Contains(input.MenuName!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.Where(x=>x.MenuSource==input.MenuSource)
|
||||
.OrderByDescending(x => x.OrderNum)
|
||||
.ToListAsync();
|
||||
//.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<MenuGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.Post;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Services.System
|
||||
@@ -12,10 +12,12 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// <summary>
|
||||
/// Post服务实现
|
||||
/// </summary>
|
||||
public class PostService : YiCrudAppService<PostAggregateRoot, PostGetOutputDto, PostGetListOutputDto, Guid, PostGetListInputVo, PostCreateInputVo, PostUpdateInputVo>,
|
||||
IPostService
|
||||
public class PostService : YiCrudAppService<PostAggregateRoot, PostGetOutputDto, PostGetListOutputDto, Guid,
|
||||
PostGetListInputVo, PostCreateInputVo, PostUpdateInputVo>,
|
||||
IPostService
|
||||
{
|
||||
private readonly ISqlSugarRepository<PostAggregateRoot, Guid> _repository;
|
||||
|
||||
public PostService(ISqlSugarRepository<PostAggregateRoot, Guid> repository) : base(repository)
|
||||
{
|
||||
_repository = repository;
|
||||
@@ -25,10 +27,31 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.PostName), x => x.PostName.Contains(input.PostName!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.PostName),
|
||||
x => x.PostName.Contains(input.PostName!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<PostGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
protected override async Task CheckCreateInputDtoAsync(PostCreateInputVo input)
|
||||
{
|
||||
var isExist =
|
||||
await _repository.IsAnyAsync(x => x.PostCode == input.PostCode);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(PostConst.Exist);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task CheckUpdateInputDtoAsync(PostAggregateRoot entity, PostUpdateInputVo input)
|
||||
{
|
||||
var isExist = await _repository._DbQueryable.Where(x => x.Id != entity.Id)
|
||||
.AnyAsync(x => x.PostCode == input.PostCode);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(RoleConst.Exist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ using Yi.Framework.Rbac.Application.Contracts.Dtos.User;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Managers;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
@@ -19,13 +20,16 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// <summary>
|
||||
/// Role服务实现
|
||||
/// </summary>
|
||||
public class RoleService : YiCrudAppService<RoleAggregateRoot, RoleGetOutputDto, RoleGetListOutputDto, Guid, RoleGetListInputVo, RoleCreateInputVo, RoleUpdateInputVo>,
|
||||
IRoleService
|
||||
public class RoleService : YiCrudAppService<RoleAggregateRoot, RoleGetOutputDto, RoleGetListOutputDto, Guid,
|
||||
RoleGetListInputVo, RoleCreateInputVo, RoleUpdateInputVo>,
|
||||
IRoleService
|
||||
{
|
||||
public RoleService(RoleManager roleManager, ISqlSugarRepository<RoleDeptEntity> roleDeptRepository, ISqlSugarRepository<UserRoleEntity> userRoleRepository, ISqlSugarRepository<RoleAggregateRoot, Guid> repository) : base(repository)
|
||||
public RoleService(RoleManager roleManager, ISqlSugarRepository<RoleDeptEntity> roleDeptRepository,
|
||||
ISqlSugarRepository<UserRoleEntity> userRoleRepository,
|
||||
ISqlSugarRepository<RoleAggregateRoot, Guid> repository) : base(repository)
|
||||
{
|
||||
(_roleManager, _roleDeptRepository, _userRoleRepository, _repository) =
|
||||
(roleManager, roleDeptRepository, userRoleRepository, repository);
|
||||
(roleManager, roleDeptRepository, userRoleRepository, repository);
|
||||
}
|
||||
|
||||
private ISqlSugarRepository<RoleAggregateRoot, Guid> _repository;
|
||||
@@ -41,23 +45,25 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
if (input.DataScope == DataScopeEnum.CUSTOM)
|
||||
{
|
||||
await _roleDeptRepository.DeleteAsync(x => x.RoleId == input.RoleId);
|
||||
var insertEntities = input.DeptIds.Select(x => new RoleDeptEntity { DeptId = x, RoleId = input.RoleId }).ToList();
|
||||
var insertEntities = input.DeptIds.Select(x => new RoleDeptEntity { DeptId = x, RoleId = input.RoleId })
|
||||
.ToList();
|
||||
await _roleDeptRepository.InsertRangeAsync(insertEntities);
|
||||
}
|
||||
|
||||
var entity = new RoleAggregateRoot() { DataScope = input.DataScope };
|
||||
EntityHelper.TrySetId(entity, () => input.RoleId);
|
||||
await _repository._Db.Updateable(entity).UpdateColumns(x => x.DataScope).ExecuteCommandAsync();
|
||||
|
||||
}
|
||||
|
||||
public override async Task<PagedResultDto<RoleGetListOutputDto>> GetListAsync(RoleGetListInputVo input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.RoleCode), x => x.RoleCode.Contains(input.RoleCode!))
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.RoleCode),
|
||||
x => x.RoleCode.Contains(input.RoleCode!))
|
||||
.WhereIF(!string.IsNullOrEmpty(input.RoleName), x => x.RoleName.Contains(input.RoleName!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<RoleGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
@@ -68,15 +74,16 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// <returns></returns>
|
||||
public override async Task<RoleGetOutputDto> CreateAsync(RoleCreateInputVo input)
|
||||
{
|
||||
RoleGetOutputDto outputDto;
|
||||
//using (var uow = _unitOfWorkManager.CreateContext())
|
||||
//{
|
||||
var isExist =
|
||||
await _repository.IsAnyAsync(x => x.RoleCode == input.RoleCode || x.RoleName == input.RoleName);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(RoleConst.Exist);
|
||||
}
|
||||
|
||||
var entity = await MapToEntityAsync(input);
|
||||
await _repository.InsertAsync(entity);
|
||||
outputDto = await MapToGetOutputDtoAsync(entity);
|
||||
await _roleManager.GiveRoleSetMenuAsync(new List<Guid> { entity.Id }, input.MenuIds);
|
||||
// uow.Commit();
|
||||
//}
|
||||
var outputDto = await MapToGetOutputDtoAsync(entity);
|
||||
|
||||
return outputDto;
|
||||
}
|
||||
@@ -89,18 +96,20 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// <returns></returns>
|
||||
public override async Task<RoleGetOutputDto> UpdateAsync(Guid id, RoleUpdateInputVo input)
|
||||
{
|
||||
var dto = new RoleGetOutputDto();
|
||||
//using (var uow = _unitOfWorkManager.CreateContext())
|
||||
//{
|
||||
var entity = await _repository.GetByIdAsync(id);
|
||||
|
||||
var isExist = await _repository._DbQueryable.Where(x => x.Id != entity.Id).AnyAsync(x => x.RoleCode == input.RoleCode || x.RoleName == input.RoleName);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(RoleConst.Exist);
|
||||
}
|
||||
|
||||
await MapToEntityAsync(input, entity);
|
||||
await _repository.UpdateAsync(entity);
|
||||
|
||||
await _roleManager.GiveRoleSetMenuAsync(new List<Guid> { id }, input.MenuIds);
|
||||
|
||||
dto = await MapToGetOutputDtoAsync(entity);
|
||||
// uow.Commit();
|
||||
//}
|
||||
var dto = await MapToGetOutputDtoAsync(entity);
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -134,7 +143,8 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// <param name="isAllocated">是否在该角色下</param>
|
||||
/// <returns></returns>
|
||||
[Route("role/auth-user/{roleId}/{isAllocated}")]
|
||||
public async Task<PagedResultDto<UserGetListOutputDto>> GetAuthUserByRoleIdAsync([FromRoute] Guid roleId, [FromRoute] bool isAllocated, [FromQuery] RoleAuthUserGetListInput input)
|
||||
public async Task<PagedResultDto<UserGetListOutputDto>> GetAuthUserByRoleIdAsync([FromRoute] Guid roleId,
|
||||
[FromRoute] bool isAllocated, [FromQuery] RoleAuthUserGetListInput input)
|
||||
{
|
||||
PagedResultDto<UserGetListOutputDto> output;
|
||||
//角色下已授权用户
|
||||
@@ -147,30 +157,34 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
{
|
||||
output = await GetNotAllocatedAuthUserByRoleIdAsync(roleId, input);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private async Task<PagedResultDto<UserGetListOutputDto>> GetAllocatedAuthUserByRoleIdAsync(Guid roleId, RoleAuthUserGetListInput input)
|
||||
private async Task<PagedResultDto<UserGetListOutputDto>> GetAllocatedAuthUserByRoleIdAsync(Guid roleId,
|
||||
RoleAuthUserGetListInput input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
var output = await _userRoleRepository._DbQueryable
|
||||
.LeftJoin<UserAggregateRoot>((ur, u) => ur.UserId == u.Id && ur.RoleId == roleId)
|
||||
.Where((ur, u) => ur.RoleId == roleId)
|
||||
.WhereIF(!string.IsNullOrEmpty(input.UserName), (ur, u) => u.UserName.Contains(input.UserName))
|
||||
.WhereIF(input.Phone is not null, (ur, u) => u.Phone.ToString().Contains(input.Phone.ToString()))
|
||||
.Select((ur, u) => new UserGetListOutputDto { Id = u.Id }, true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
.LeftJoin<UserAggregateRoot>((ur, u) => ur.UserId == u.Id && ur.RoleId == roleId)
|
||||
.Where((ur, u) => ur.RoleId == roleId)
|
||||
.WhereIF(!string.IsNullOrEmpty(input.UserName), (ur, u) => u.UserName.Contains(input.UserName))
|
||||
.WhereIF(input.Phone is not null, (ur, u) => u.Phone.ToString().Contains(input.Phone.ToString()))
|
||||
.Select((ur, u) => new UserGetListOutputDto { Id = u.Id }, true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<UserGetListOutputDto>(total, output);
|
||||
}
|
||||
|
||||
private async Task<PagedResultDto<UserGetListOutputDto>> GetNotAllocatedAuthUserByRoleIdAsync(Guid roleId, RoleAuthUserGetListInput input)
|
||||
private async Task<PagedResultDto<UserGetListOutputDto>> GetNotAllocatedAuthUserByRoleIdAsync(Guid roleId,
|
||||
RoleAuthUserGetListInput input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
var entities = await _userRoleRepository._Db.Queryable<UserAggregateRoot>()
|
||||
.Where(u => SqlFunc.Subqueryable<UserRoleEntity>().Where(x => x.RoleId == roleId).Where(x => x.UserId == u.Id).NotAny())
|
||||
.WhereIF(!string.IsNullOrEmpty(input.UserName), u => u.UserName.Contains(input.UserName))
|
||||
.WhereIF(input.Phone is not null, u => u.Phone.ToString().Contains(input.Phone.ToString()))
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
.Where(u => SqlFunc.Subqueryable<UserRoleEntity>().Where(x => x.RoleId == roleId)
|
||||
.Where(x => x.UserId == u.Id).NotAny())
|
||||
.WhereIF(!string.IsNullOrEmpty(input.UserName), u => u.UserName.Contains(input.UserName))
|
||||
.WhereIF(input.Phone is not null, u => u.Phone.ToString().Contains(input.Phone.ToString()))
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
var output = entities.Adapt<List<UserGetListOutputDto>>();
|
||||
return new PagedResultDto<UserGetListOutputDto>(total, output);
|
||||
}
|
||||
@@ -181,9 +195,10 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task CreateAuthUserAsync(RoleAuthUserCreateOrDeleteInput input)
|
||||
public async Task CreateAuthUserAsync([FromBody] RoleAuthUserCreateOrDeleteInput input)
|
||||
{
|
||||
var userRoleEntities = input.UserIds.Select(u => new UserRoleEntity { RoleId = input.RoleId, UserId = u }).ToList();
|
||||
var userRoleEntities = input.UserIds.Select(u => new UserRoleEntity { RoleId = input.RoleId, UserId = u })
|
||||
.ToList();
|
||||
await _userRoleRepository.InsertRangeAsync(userRoleEntities);
|
||||
}
|
||||
|
||||
@@ -193,11 +208,12 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteAuthUserAsync(RoleAuthUserCreateOrDeleteInput input)
|
||||
public async Task DeleteAuthUserAsync([FromBody] RoleAuthUserCreateOrDeleteInput input)
|
||||
{
|
||||
await _userRoleRepository._Db.Deleteable<UserRoleEntity>().Where(x => x.RoleId == input.RoleId)
|
||||
.Where(x => input.UserIds.Contains(x.UserId))
|
||||
.ExecuteCommandAsync(); ;
|
||||
.ExecuteCommandAsync();
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Caching;
|
||||
using Volo.Abp.EventBus.Local;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.User;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
@@ -24,13 +26,20 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// <summary>
|
||||
/// User服务实现
|
||||
/// </summary>
|
||||
public class UserService : YiCrudAppService<UserAggregateRoot, UserGetOutputDto, UserGetListOutputDto, Guid, UserGetListInputVo, UserCreateInputVo, UserUpdateInputVo>, IUserService
|
||||
public class UserService : YiCrudAppService<UserAggregateRoot, UserGetOutputDto, UserGetListOutputDto, Guid,
|
||||
UserGetListInputVo, UserCreateInputVo, UserUpdateInputVo>, IUserService
|
||||
//IUserService
|
||||
{
|
||||
public UserService(ISqlSugarRepository<UserAggregateRoot, Guid> repository, UserManager userManager, IUserRepository userRepository, ICurrentUser currentUser, IDeptService deptService, ILocalEventBus localEventBus, IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> userCache) : base(repository)
|
||||
protected ILocalEventBus LocalEventBus => LazyServiceProvider.LazyGetRequiredService<ILocalEventBus>();
|
||||
|
||||
public UserService(ISqlSugarRepository<UserAggregateRoot, Guid> repository, UserManager userManager,
|
||||
IUserRepository userRepository, ICurrentUser currentUser, IDeptService deptService,
|
||||
ILocalEventBus localEventBus,
|
||||
IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> userCache) : base(repository)
|
||||
=>
|
||||
(_userManager, _userRepository, _currentUser, _deptService, _repository, _localEventBus) =
|
||||
(userManager, userRepository, currentUser, deptService, repository, localEventBus);
|
||||
(_userManager, _userRepository, _currentUser, _deptService, _repository, _localEventBus) =
|
||||
(userManager, userRepository, currentUser, deptService, repository, localEventBus);
|
||||
|
||||
private UserManager _userManager { get; set; }
|
||||
private ISqlSugarRepository<UserAggregateRoot, Guid> _repository;
|
||||
private IUserRepository _userRepository { get; set; }
|
||||
@@ -39,6 +48,7 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
private ICurrentUser _currentUser { get; set; }
|
||||
|
||||
private ILocalEventBus _localEventBus;
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户
|
||||
/// </summary>
|
||||
@@ -56,22 +66,21 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
|
||||
|
||||
List<Guid> ids = input.Ids?.Split(",").Select(x => Guid.Parse(x)).ToList();
|
||||
var outPut = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.UserName), x => x.UserName.Contains(input.UserName!))
|
||||
.WhereIF(input.Phone is not null, x => x.Phone.ToString()!.Contains(input.Phone.ToString()!))
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name!.Contains(input.Name!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||
var outPut = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.UserName),
|
||||
x => x.UserName.Contains(input.UserName!))
|
||||
.WhereIF(input.Phone is not null, x => x.Phone.ToString()!.Contains(input.Phone.ToString()!))
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name!.Contains(input.Name!))
|
||||
.WhereIF(input.State is not null, x => x.State == input.State)
|
||||
.WhereIF(input.StartTime is not null && input.EndTime is not null,
|
||||
x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||
|
||||
//这个为过滤当前部门,加入数据权限后,将由数据权限控制
|
||||
.WhereIF(input.DeptId is not null, x => deptIds.Contains(x.DeptId ?? Guid.Empty))
|
||||
|
||||
.WhereIF(ids is not null, x => ids.Contains(x.Id))
|
||||
|
||||
|
||||
.LeftJoin<DeptAggregateRoot>((user, dept) => user.DeptId == dept.Id)
|
||||
.OrderByDescending(user => user.CreationTime)
|
||||
.Select((user, dept) => new UserGetListOutputDto(), true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
//这个为过滤当前部门,加入数据权限后,将由数据权限控制
|
||||
.WhereIF(input.DeptId is not null, x => deptIds.Contains(x.DeptId ?? Guid.Empty))
|
||||
.WhereIF(ids is not null, x => ids.Contains(x.Id))
|
||||
.LeftJoin<DeptAggregateRoot>((user, dept) => user.DeptId == dept.Id)
|
||||
.OrderByDescending(user => user.CreationTime)
|
||||
.Select((user, dept) => new UserGetListOutputDto(), true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
|
||||
var result = new PagedResultDto<UserGetListOutputDto>();
|
||||
result.Items = outPut;
|
||||
@@ -96,7 +105,6 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
[Permission("system:user:add")]
|
||||
public async override Task<UserGetOutputDto> CreateAsync(UserCreateInputVo input)
|
||||
{
|
||||
|
||||
var entitiy = await MapToEntityAsync(input);
|
||||
|
||||
await _userManager.CreateAsync(entitiy);
|
||||
@@ -119,10 +127,12 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[Permission("system:user:list")]
|
||||
public override async Task<UserGetOutputDto> GetAsync(Guid id)
|
||||
{
|
||||
//使用导航树形查询
|
||||
var entity = await _repository._DbQueryable.Includes(u => u.Roles).Includes(u => u.Posts).Includes(u => u.Dept).InSingleAsync(id);
|
||||
var entity = await _repository._DbQueryable.Includes(u => u.Roles).Includes(u => u.Posts)
|
||||
.Includes(u => u.Dept).InSingleAsync(id);
|
||||
|
||||
return await MapToGetOutputDtoAsync(entity);
|
||||
}
|
||||
@@ -141,17 +151,20 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
{
|
||||
throw new UserFriendlyException(UserConst.Name_Not_Allowed);
|
||||
}
|
||||
|
||||
if (await _repository.IsAnyAsync(u => input.UserName!.Equals(u.UserName) && !id.Equals(u.Id)))
|
||||
{
|
||||
throw new UserFriendlyException("用户已经存在,更新失败");
|
||||
throw new UserFriendlyException(UserConst.Exist);
|
||||
}
|
||||
|
||||
var entity = await _repository.GetByIdAsync(id);
|
||||
//更新密码,特殊处理
|
||||
if (input.Password is not null)
|
||||
if (!string.IsNullOrWhiteSpace(input.Password))
|
||||
{
|
||||
entity.EncryPassword.Password = input.Password;
|
||||
entity.BuildPassword();
|
||||
}
|
||||
|
||||
await MapToEntityAsync(input, entity);
|
||||
|
||||
var res1 = await _repository.UpdateAsync(entity);
|
||||
@@ -173,6 +186,14 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
|
||||
await _repository.UpdateAsync(entity);
|
||||
var dto = await MapToGetOutputDtoAsync(entity);
|
||||
//发布更新昵称任务事件
|
||||
if (input.Nick != entity.Icon)
|
||||
{
|
||||
await this.LocalEventBus.PublishAsync(
|
||||
new AssignmentEventArgs(AssignmentRequirementTypeEnum.UpdateNick, _currentUser.GetId(), input.Nick),
|
||||
false);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -192,15 +213,16 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
{
|
||||
throw new ApplicationException("用户未存在");
|
||||
}
|
||||
|
||||
entity.State = state;
|
||||
await _repository.UpdateAsync(entity);
|
||||
return await MapToGetOutputDtoAsync(entity);
|
||||
}
|
||||
|
||||
[OperLog("删除用户", OperEnum.Delete)]
|
||||
[Permission("system:user:delete")]
|
||||
public override async Task DeleteAsync(Guid id)
|
||||
{
|
||||
|
||||
await base.DeleteAsync(id);
|
||||
}
|
||||
|
||||
@@ -216,4 +238,4 @@ namespace Yi.Framework.Rbac.Application.Services.System
|
||||
return base.PostImportExcelAsync(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Uow;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Options;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试文档控制器
|
||||
/// </summary>
|
||||
public class TestServcie : ApplicationService
|
||||
{
|
||||
private IRepository<StudentEntity> _repository;
|
||||
private IUnitOfWorkManager _unitOfWork;
|
||||
private ISqlSugarRepository<StudentEntity> _sqlsugarRepository;
|
||||
|
||||
public IOptions<JwtOptions> options { get; set; }
|
||||
public TestServcie(IRepository<StudentEntity> repository, IUnitOfWorkManager unitOfWork, ISqlSugarRepository<StudentEntity> sqlsugarRepository, IRepository<StudentEntity, Guid> repository2)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_repository = repository;
|
||||
_sqlsugarRepository = sqlsugarRepository;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 你好,多线程
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<string> GetTaskTest()
|
||||
{
|
||||
var tasks = Enumerable.Range(0, 2).Select(x =>
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
using (var uow = _unitOfWork.Begin(true))
|
||||
{
|
||||
// await _repository.GetListAsync();
|
||||
await _sqlsugarRepository._DbQueryable.ToListAsync();
|
||||
await uow.CompleteAsync();
|
||||
}
|
||||
});
|
||||
}).ToList();
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
return "你哈";
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public async Task<List<StudentEntity>> GetTest()
|
||||
{
|
||||
//using (var uow = _unitOfWork.Begin(true))
|
||||
//{
|
||||
var data = await _repository.GetListAsync();
|
||||
var data2 = await _repository.GetListAsync();
|
||||
//await uow.CompleteAsync();
|
||||
return data;
|
||||
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//[UnitOfWork]
|
||||
public async Task<StudentEntity> PostTest()
|
||||
{
|
||||
//using (var uow = _unitOfWork.Begin())
|
||||
//{
|
||||
var stu = new StudentEntity() { Name = $"{DateTime.Now.ToString()}你好" };
|
||||
|
||||
var data = await _repository.InsertAsync(stu);
|
||||
//await uow.CompleteAsync();
|
||||
return data;
|
||||
//}
|
||||
}
|
||||
|
||||
public async Task<StudentEntity> PostError()
|
||||
{
|
||||
throw new ApplicationException();
|
||||
}
|
||||
|
||||
public async Task<StudentEntity> PostUserError()
|
||||
{
|
||||
throw new UserFriendlyException("直接爆炸");
|
||||
}
|
||||
|
||||
public string Login()
|
||||
{
|
||||
var data = options.Value;
|
||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(data.SecurityKey));
|
||||
|
||||
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||
var claims = new List<Claim>()
|
||||
{
|
||||
new Claim("name","admin")
|
||||
};
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: data.Issuer,
|
||||
audience: data.Audience,
|
||||
claims: claims,
|
||||
expires: DateTime.Now.AddSeconds(60 * 60 * 2),
|
||||
notBefore: DateTime.Now,
|
||||
signingCredentials: creds);
|
||||
string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
|
||||
|
||||
return returnToken;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Rbac.Domain.Shared.Caches
|
||||
{
|
||||
@@ -14,13 +15,15 @@ namespace Yi.Framework.Rbac.Domain.Shared.Caches
|
||||
|
||||
public class CaptchaPhoneCacheKey
|
||||
{
|
||||
public CaptchaPhoneCacheKey(string phone) { Phone = phone; }
|
||||
|
||||
public CaptchaPhoneCacheKey(ValidationPhoneTypeEnum validationPhoneType,string phone) { Phone = phone;
|
||||
ValidationPhoneType = validationPhoneType;
|
||||
}
|
||||
public ValidationPhoneTypeEnum ValidationPhoneType { get; set; }
|
||||
public string Phone { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Phone:{Phone}";
|
||||
return $"Phone:{ValidationPhoneType.ToString()}:{Phone}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
|
||||
public class ConfigConst
|
||||
{
|
||||
public const string Exist = "该配置已经存在";
|
||||
}
|
||||
@@ -12,5 +12,6 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
|
||||
|
||||
public class DeptConst
|
||||
{
|
||||
public const string Exist = "该部门已经存在";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
|
||||
public class DictionaryConst
|
||||
{
|
||||
public const string Exist = "该字典已经存在";
|
||||
}
|
||||
@@ -12,5 +12,6 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
|
||||
|
||||
public class MenuConst
|
||||
{
|
||||
public const string Exist = "该菜单已经存在";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,6 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
|
||||
|
||||
public class PostConst
|
||||
{
|
||||
public const string Exist = "该岗位已经存在";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,6 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
|
||||
|
||||
public class RoleConst
|
||||
{
|
||||
public const string Exist = "该角色已经存在";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
|
||||
public const string Login_User_No_Exist = "登录失败!用户名不存在!";
|
||||
public const string Login_Passworld_Error = "密码为空,添加失败!";
|
||||
public const string Create_Passworld_Error = "密码格式错误,长度需大于等于6位";
|
||||
public const string User_Exist = "用户已经存在,创建失败!";
|
||||
public const string Exist = "用户已经存在,创建失败!";
|
||||
public const string State_Is_State = "该用户已被禁用,请联系管理员进行恢复";
|
||||
public const string No_Permission = "登录禁用!该用户分配无任何权限,无意义登录!";
|
||||
public const string No_Role = "登录禁用!该用户分配无任何角色,无意义登录!";
|
||||
|
||||
@@ -195,6 +195,11 @@ namespace Yi.Framework.Rbac.Domain.Shared.Dtos
|
||||
public class MenuDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
/// <summary>
|
||||
/// 菜单来源
|
||||
/// </summary>
|
||||
public MenuSourceEnum MenuSource { get; set; }
|
||||
public string? RouterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 逻辑删除
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||
|
||||
public class Vue3PureRouterDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid ParentId { get; set; }
|
||||
public string Path { get; set; }
|
||||
public string Name { get; set; }
|
||||
public MetaPureRouterDto Meta { get; set; } = new MetaPureRouterDto();
|
||||
|
||||
public string? component { get; set; }
|
||||
public List<Vue3PureRouterDto>? Children { get; set; }
|
||||
}
|
||||
|
||||
public class MetaPureRouterDto
|
||||
{
|
||||
public string Icon { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
public List<string>? Roles { get; set; }
|
||||
|
||||
public List<string>? Auths { get; set; }
|
||||
|
||||
public string? FrameSrc { get; set; }
|
||||
|
||||
public string? FrameLoading { get; set; }
|
||||
|
||||
public bool? KeepAlive { get; set; }
|
||||
|
||||
public bool? showLink { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||
|
||||
public enum MenuSourceEnum
|
||||
{
|
||||
Ruoyi=0,
|
||||
Pure=1
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||
|
||||
public enum ValidationPhoneTypeEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册
|
||||
/// </summary>
|
||||
Register,
|
||||
/// <summary>
|
||||
/// 忘记密码
|
||||
/// </summary>
|
||||
RetrievePassword
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using IPTools.Core;
|
||||
using IPTools.Core;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using SqlSugar;
|
||||
using UAParser;
|
||||
@@ -75,7 +75,14 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
location = IpTool.Search(ipAddr);
|
||||
try
|
||||
{
|
||||
location = IpTool.Search(ipAddr);
|
||||
}
|
||||
catch
|
||||
{
|
||||
location = new IpInfo() { Province = ipAddr, City = "未知地区" };
|
||||
}
|
||||
}
|
||||
ClientInfo clientInfo = GetClientInfo(context);
|
||||
LoginLogAggregateRoot entity = new()
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using SqlSugar;
|
||||
using System.Web;
|
||||
using NUglify.Helpers;
|
||||
using SqlSugar;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
@@ -15,10 +17,22 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
[SugarTable("Menu")]
|
||||
public partial class MenuAggregateRoot : AggregateRoot<Guid>, ISoftDelete, IAuditedObject, IOrderNum, IState
|
||||
{
|
||||
public MenuAggregateRoot() { }
|
||||
public MenuAggregateRoot()
|
||||
{
|
||||
}
|
||||
|
||||
public MenuAggregateRoot(Guid id)
|
||||
{
|
||||
Id = id;
|
||||
ParentId = Guid.Empty;
|
||||
}
|
||||
|
||||
public MenuAggregateRoot(Guid id, Guid parentId)
|
||||
{
|
||||
Id = id;
|
||||
ParentId = parentId;
|
||||
}
|
||||
|
||||
public MenuAggregateRoot(Guid id) { Id = id; ParentId = Guid.Empty; }
|
||||
public MenuAggregateRoot(Guid id, Guid parentId) { Id = id; ParentId = parentId; }
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
@@ -63,17 +77,25 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
/// <summary>
|
||||
/// 菜单名
|
||||
/// </summary>
|
||||
public string MenuName { get; set; } = string.Empty;
|
||||
public string MenuName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由名称
|
||||
/// </summary>
|
||||
public string? RouterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "MenuType")]
|
||||
public MenuTypeEnum MenuType { get; set; } = MenuTypeEnum.Menu;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "PermissionCode")]
|
||||
public string? PermissionCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
///</summary>
|
||||
@@ -85,21 +107,25 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "MenuIcon")]
|
||||
public string? MenuIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单组件路由
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "Router")]
|
||||
public string? Router { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为外部链接
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "IsLink")]
|
||||
public bool IsLink { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否缓存
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "IsCache")]
|
||||
public bool IsCache { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示
|
||||
///</summary>
|
||||
@@ -111,20 +137,25 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "Remark")]
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 组件路径
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "Component")]
|
||||
public string? Component { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单来源
|
||||
/// </summary>
|
||||
public MenuSourceEnum MenuSource { get; set; } = MenuSourceEnum.Ruoyi;
|
||||
|
||||
/// <summary>
|
||||
/// 路由参数
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "Query")]
|
||||
public string? Query { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public List<MenuAggregateRoot>? Children { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)] public List<MenuAggregateRoot>? Children { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -137,13 +168,16 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
/// </summary>
|
||||
/// <param name="menus"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Vue3RouterDto> Vue3RouterBuild(this List<MenuAggregateRoot> menus)
|
||||
public static List<Vue3RouterDto> Vue3RuoYiRouterBuild(this List<MenuAggregateRoot> menus)
|
||||
{
|
||||
menus = menus.Where(m => m.MenuType != MenuTypeEnum.Component).ToList();
|
||||
menus = menus
|
||||
.Where(m => m.State == true)
|
||||
.Where(m => m.MenuType != MenuTypeEnum.Component)
|
||||
.Where(m => m.MenuSource == MenuSourceEnum.Ruoyi)
|
||||
.ToList();
|
||||
List<Vue3RouterDto> routers = new();
|
||||
foreach (var m in menus)
|
||||
{
|
||||
|
||||
var r = new Vue3RouterDto();
|
||||
r.OrderNum = m.OrderNum;
|
||||
var routerName = m.Router?.Split("/").LastOrDefault();
|
||||
@@ -171,6 +205,7 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
r.Component = "ParentView";
|
||||
}
|
||||
}
|
||||
|
||||
if (m.MenuType == MenuTypeEnum.Menu)
|
||||
{
|
||||
r.Redirect = "noRedirect";
|
||||
@@ -178,6 +213,7 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
r.Component = m.Component!;
|
||||
r.AlwaysShow = false;
|
||||
}
|
||||
|
||||
r.Meta = new Meta
|
||||
{
|
||||
Title = m.MenuName!,
|
||||
@@ -192,8 +228,62 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
|
||||
routers.Add(r);
|
||||
}
|
||||
return TreeHelper.SetTree(routers);
|
||||
|
||||
return TreeHelper.SetTree(routers);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 构建vue3 pure路由
|
||||
/// </summary>
|
||||
/// <param name="menus"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Vue3PureRouterDto> Vue3PureRouterBuild(this List<MenuAggregateRoot> menus)
|
||||
{
|
||||
//pure的菜单为树形
|
||||
var allRouters = menus
|
||||
.Where(m => m.State == true)
|
||||
.Where(m => m.MenuType != MenuTypeEnum.Component)
|
||||
.Where(m => m.MenuSource == MenuSourceEnum.Pure)
|
||||
.Select(m => new Vue3PureRouterDto
|
||||
{
|
||||
Path =m.Router.StartsWith("/")?m.Router:"/"+m.Router,
|
||||
Name =m.IsLink==true?"Link": m.RouterName,
|
||||
component = m.Component,
|
||||
Meta = new MetaPureRouterDto()
|
||||
{
|
||||
showLink = m.IsShow,
|
||||
FrameSrc = m.IsLink == true ? m.Router : null,
|
||||
Auths = new List<string>() { m.PermissionCode },
|
||||
Icon = m.MenuIcon,
|
||||
Title = m.MenuName,
|
||||
|
||||
},
|
||||
Children =null,
|
||||
Id = m.Id,
|
||||
ParentId = m.ParentId
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
var routerDic = allRouters.GroupBy(x => x.ParentId).ToDictionary(x => x.Key,y=>y.ToList());
|
||||
//根路由
|
||||
if (!routerDic.TryGetValue(Guid.Empty, out var rootRouters))
|
||||
{
|
||||
return new List<Vue3PureRouterDto>();
|
||||
}
|
||||
Stack<Vue3PureRouterDto> stack = new Stack<Vue3PureRouterDto>(rootRouters);
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var currentRouter = stack.Pop();
|
||||
if (routerDic.TryGetValue(currentRouter.Id, out var items))
|
||||
{
|
||||
currentRouter.Children = items;
|
||||
items?.ForEach(x => stack.Push(x));
|
||||
}
|
||||
}
|
||||
|
||||
return rootRouters;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using Volo.Abp.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.Rbac.Domain.Entities
|
||||
{
|
||||
public class StudentEntity : Entity<Guid>
|
||||
{
|
||||
|
||||
[SqlSugar.SugarColumn(IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,12 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
||||
{
|
||||
|
||||
}
|
||||
public UserAggregateRoot(string userName, string password, long phone, string nick = "萌新")
|
||||
public UserAggregateRoot(string userName, string password, long phone, string? nick = null)
|
||||
{
|
||||
UserName = userName;
|
||||
EncryPassword.Password = password;
|
||||
Phone = phone;
|
||||
Nick = nick+"-"+userName;
|
||||
Nick =string.IsNullOrWhiteSpace(nick)?"萌新-"+userName:nick.Trim();
|
||||
BuildPassword();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Domain.Entities.Events;
|
||||
using Volo.Abp.EventBus;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.Rbac.Domain.EventHandlers
|
||||
{
|
||||
public class StudentEventHandler : ILocalEventHandler<EntityCreatedEventData<StudentEntity>>, ITransientDependency
|
||||
{
|
||||
public Task HandleEventAsync(EntityCreatedEventData<StudentEntity> eventData)
|
||||
{
|
||||
Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(eventData.Entity));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,11 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
private readonly ILocalEventBus _localEventBus;
|
||||
private readonly JwtOptions _jwtOptions;
|
||||
private readonly RbacOptions _options;
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
private UserManager _userManager;
|
||||
private ISqlSugarRepository<RoleAggregateRoot> _roleRepository;
|
||||
private RefreshJwtOptions _refreshJwtOptions;
|
||||
|
||||
public AccountManager(IUserRepository repository
|
||||
, IHttpContextAccessor httpContextAccessor
|
||||
, IOptions<JwtOptions> jwtOptions
|
||||
, ILocalEventBus localEventBus
|
||||
, UserManager userManager
|
||||
@@ -49,7 +47,6 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
, IOptions<RbacOptions> options)
|
||||
{
|
||||
_repository = repository;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_jwtOptions = jwtOptions.Value;
|
||||
_localEventBus = localEventBus;
|
||||
_userManager = userManager;
|
||||
@@ -62,9 +59,10 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
/// 根据用户id获取token
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="getUserInfo"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="UserFriendlyException"></exception>
|
||||
public async Task<string> GetTokenByUserIdAsync(Guid userId)
|
||||
public async Task<string> GetTokenByUserIdAsync(Guid userId,Action<UserRoleMenuDto>? getUserInfo=null)
|
||||
{
|
||||
//获取用户信息
|
||||
var userInfo = await _userManager.GetInfoAsync(userId);
|
||||
@@ -79,23 +77,18 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
{
|
||||
throw new UserFriendlyException(UserConst.No_Role);
|
||||
}
|
||||
if (userInfo.PermissionCodes.Count() == 0)
|
||||
if (!userInfo.PermissionCodes.Any())
|
||||
{
|
||||
throw new UserFriendlyException(UserConst.No_Permission);
|
||||
}
|
||||
//这里抛出一个登录的事件,也可以在全部流程走完,在应用层组装
|
||||
if (_httpContextAccessor.HttpContext is not null)
|
||||
|
||||
if (getUserInfo is not null)
|
||||
{
|
||||
var loginEntity = new LoginLogAggregateRoot().GetInfoByHttpContext(_httpContextAccessor.HttpContext);
|
||||
var loginEto = loginEntity.Adapt<LoginEventArgs>();
|
||||
loginEto.UserName = userInfo.User.UserName;
|
||||
loginEto.UserId = userInfo.User.Id;
|
||||
await _localEventBus.PublishAsync(loginEto);
|
||||
getUserInfo(userInfo);
|
||||
}
|
||||
|
||||
var accessToken = CreateToken(this.UserInfoToClaim(userInfo));
|
||||
//将用户信息添加到缓存中,需要考虑的是更改了用户、角色、菜单等整个体系都需要将缓存进行刷新,看具体业务进行选择
|
||||
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@@ -187,6 +180,8 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 令牌转换
|
||||
@@ -257,7 +252,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置密码
|
||||
/// 重置密码,也可以是找回密码
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="password"></param>
|
||||
@@ -265,7 +260,6 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
public async Task<bool> RestPasswordAsync(Guid userId, string password)
|
||||
{
|
||||
var user = await _repository.GetByIdAsync(userId);
|
||||
// EntityHelper.TrySetId(user, () => GuidGenerator.Create(), true);
|
||||
user.EncryPassword.Password = password;
|
||||
user.BuildPassword();
|
||||
return await _repository.UpdateAsync(user);
|
||||
@@ -278,12 +272,11 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
/// <param name="password"></param>
|
||||
/// <param name="phone"></param>
|
||||
/// <returns></returns>
|
||||
public async Task RegisterAsync(string userName, string password, long phone)
|
||||
public async Task RegisterAsync(string userName, string password, long phone,string? nick)
|
||||
{
|
||||
var user = new UserAggregateRoot(userName, password, phone);
|
||||
var user = new UserAggregateRoot(userName, password, phone,nick);
|
||||
await _userManager.CreateAsync(user);
|
||||
await _userManager.SetDefautRoleAsync(user.Id);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,15 +5,16 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||
|
||||
namespace Yi.Framework.Rbac.Domain.Managers
|
||||
{
|
||||
public interface IAccountManager : IDomainService
|
||||
{
|
||||
string CreateRefreshToken(Guid userId);
|
||||
Task<string> GetTokenByUserIdAsync(Guid userId);
|
||||
Task LoginValidationAsync(string userName, string password, Action<UserAggregateRoot> userAction = null);
|
||||
Task RegisterAsync(string userName, string password, long phone);
|
||||
Task<string> GetTokenByUserIdAsync(Guid userId,Action<UserRoleMenuDto>? getUserInfo=null);
|
||||
Task LoginValidationAsync(string userName, string password, Action<UserAggregateRoot>? userAction = null);
|
||||
Task RegisterAsync(string userName, string password, long phone,string? nick);
|
||||
Task<bool> RestPasswordAsync(Guid userId, string password);
|
||||
Task UpdatePasswordAsync(Guid userId, string newPassword, string oldPassword);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
var isExist = await _repository.IsAnyAsync(x => x.UserName == userEntity.UserName);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException(UserConst.User_Exist);
|
||||
throw new UserFriendlyException(UserConst.Exist);
|
||||
}
|
||||
|
||||
var entity = await _repository.InsertReturnEntityAsync(userEntity);
|
||||
@@ -162,14 +162,23 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户信息,已缓存
|
||||
/// 查询用户信息,取消缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<UserRoleMenuDto> GetInfoAsync(Guid userId)
|
||||
{
|
||||
|
||||
var output = await GetInfoByCacheAsync(userId);
|
||||
return output;
|
||||
var user = await _userRepository.GetUserAllInfoAsync(userId);
|
||||
var data = EntityMapToDto(user);
|
||||
//系统用户数据被重置,老前端访问重新授权
|
||||
if (data is null)
|
||||
{
|
||||
throw new AbpAuthorizationException();
|
||||
}
|
||||
//data.Menus.Clear();
|
||||
// output = data;
|
||||
return data;
|
||||
// var output = await GetInfoByCacheAsync(userId);
|
||||
// return output;
|
||||
}
|
||||
private async Task<UserRoleMenuDto> GetInfoByCacheAsync(Guid userId)
|
||||
{
|
||||
@@ -222,10 +231,11 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
|
||||
var userRoleMenu = new UserRoleMenuDto();
|
||||
//首先获取到该用户全部信息,导航到角色、菜单,(菜单需要去重,完全交给Set来处理即可)
|
||||
//if (user is null)
|
||||
//{
|
||||
// throw new UserFriendlyException($"数据错误,用户id:{nameof(userId)} 不存在,请重新登录");
|
||||
//}
|
||||
if (user is null)
|
||||
{
|
||||
//为了解决token前端缓存,后端数据库重新dbseed
|
||||
throw new UserFriendlyException($"数据错误,查询用户不存在,请重新登录");
|
||||
}
|
||||
user.EncryPassword.Password = string.Empty;
|
||||
user.EncryPassword.Salt = string.Empty;
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using IPTools.Core;
|
||||
using IPTools.Core;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Users;
|
||||
@@ -25,9 +26,9 @@ namespace Yi.Framework.Rbac.Domain.Operlog
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
||||
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
var resultContext = await next.Invoke();
|
||||
var resultContext = await next();
|
||||
//执行后
|
||||
|
||||
//判断标签是在方法上
|
||||
@@ -47,10 +48,18 @@ namespace Yi.Framework.Rbac.Domain.Operlog
|
||||
//获取Ip
|
||||
string ip = resultContext.HttpContext.GetClientIp();
|
||||
|
||||
//根据ip获取地址
|
||||
//根据ip获取地址
|
||||
string location = "";
|
||||
try
|
||||
{
|
||||
var ipTool = IpTool.Search(ip);
|
||||
location = ipTool.Province + " " + ipTool.City;
|
||||
}
|
||||
catch
|
||||
{
|
||||
location = "搜索地址失败,可能是内网地址:" + ip;
|
||||
}
|
||||
|
||||
var ipTool = IpTool.Search(ip);
|
||||
string location = ipTool.Province + " " + ipTool.City;
|
||||
|
||||
//日志服务插入一条操作记录即可
|
||||
|
||||
@@ -84,7 +93,8 @@ namespace Yi.Framework.Rbac.Domain.Operlog
|
||||
if (operLogAttribute.IsSaveRequestData)
|
||||
{
|
||||
//不建议保存,吃性能
|
||||
//logEntity.RequestParam = context.HttpContext.GetRequestValue(logEntity.RequestMethod);
|
||||
//保存请求参数
|
||||
logEntity.RequestParam = JsonConvert.SerializeObject(context.ActionArguments);
|
||||
}
|
||||
|
||||
await _repository.InsertAsync(logEntity);
|
||||
|
||||
@@ -51,12 +51,12 @@ namespace Yi.Framework.Rbac.Domain.Operlog
|
||||
/// <summary>
|
||||
/// 请求参数
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "RequestParam")]
|
||||
[SugarColumn(ColumnName = "RequestParam",ColumnDataType = StaticConfig.CodeFirst_BigString)]
|
||||
public string? RequestParam { get; set; }
|
||||
/// <summary>
|
||||
/// 请求结果
|
||||
///</summary>
|
||||
[SugarColumn(ColumnName = "RequestResult", Length = 9999)]
|
||||
[SugarColumn(ColumnName = "RequestResult",ColumnDataType = StaticConfig.CodeFirst_BigString)]
|
||||
public string? RequestResult { get; set; }
|
||||
|
||||
public DateTime CreationTime { get; set; }
|
||||
|
||||
@@ -0,0 +1,519 @@
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Guids;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
||||
{
|
||||
public class MenuPureDataSeed : IDataSeedContributor, ITransientDependency
|
||||
{
|
||||
private ISqlSugarRepository<MenuAggregateRoot> _repository;
|
||||
private IGuidGenerator _guidGenerator;
|
||||
public MenuPureDataSeed(ISqlSugarRepository<MenuAggregateRoot> repository, IGuidGenerator guidGenerator)
|
||||
{
|
||||
_repository = repository;
|
||||
_guidGenerator = guidGenerator;
|
||||
}
|
||||
|
||||
public async Task SeedAsync(DataSeedContext context)
|
||||
{
|
||||
if (!await _repository.IsAnyAsync(x => x.MenuName == "系统管理"&&x.MenuSource==MenuSourceEnum.Pure))
|
||||
{
|
||||
await _repository.InsertManyAsync(GetSeedData());
|
||||
}
|
||||
}
|
||||
public List<MenuAggregateRoot> GetSeedData()
|
||||
{
|
||||
List<MenuAggregateRoot> entities = new List<MenuAggregateRoot>();
|
||||
//系统管理
|
||||
MenuAggregateRoot system = new MenuAggregateRoot(_guidGenerator.Create(), Guid.Empty)
|
||||
{
|
||||
MenuName = "系统管理",
|
||||
MenuType = MenuTypeEnum.Catalogue,
|
||||
Router = "/system",
|
||||
MenuIcon = "ri:settings-3-line",
|
||||
OrderNum = 100
|
||||
};
|
||||
entities.Add(system);
|
||||
|
||||
//系统监控
|
||||
MenuAggregateRoot monitoring = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
MenuName = "系统监控",
|
||||
MenuType = MenuTypeEnum.Catalogue,
|
||||
Router = "/monitor",
|
||||
MenuIcon = "ep:monitor",
|
||||
OrderNum = 99,
|
||||
};
|
||||
entities.Add(monitoring);
|
||||
|
||||
|
||||
//在线用户
|
||||
MenuAggregateRoot online = new MenuAggregateRoot(_guidGenerator.Create(), monitoring.Id)
|
||||
{
|
||||
MenuName = "在线用户",
|
||||
PermissionCode = "monitor:online:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/monitor/online-user",
|
||||
MenuIcon = "ri:user-voice-line",
|
||||
OrderNum = 100,
|
||||
RouterName = "OnlineUser",
|
||||
Component = "monitor/online/index"
|
||||
};
|
||||
entities.Add(online);
|
||||
|
||||
|
||||
//Yi框架
|
||||
MenuAggregateRoot guide = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
MenuName = "Yi框架",
|
||||
MenuType = MenuTypeEnum.Catalogue,
|
||||
Router = "https://ccnetcore.com",
|
||||
IsLink = true,
|
||||
MenuIcon = "ri:at-line",
|
||||
OrderNum = 90,
|
||||
Component = null
|
||||
};
|
||||
entities.Add(guide);
|
||||
|
||||
//用户管理
|
||||
MenuAggregateRoot user = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
MenuName = "用户管理",
|
||||
PermissionCode = "system:user:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/system/user/index",
|
||||
MenuIcon = "ri:admin-line",
|
||||
OrderNum = 100,
|
||||
ParentId = system.Id,
|
||||
RouterName = "SystemUser"
|
||||
};
|
||||
entities.Add(user);
|
||||
|
||||
MenuAggregateRoot userQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "用户查询",
|
||||
PermissionCode = "system:user:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = user.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(userQuery);
|
||||
|
||||
MenuAggregateRoot userAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "用户新增",
|
||||
PermissionCode = "system:user:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = user.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(userAdd);
|
||||
|
||||
MenuAggregateRoot userEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "用户修改",
|
||||
PermissionCode = "system:user:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = user.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(userEdit);
|
||||
|
||||
MenuAggregateRoot userRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "用户删除",
|
||||
PermissionCode = "system:user:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = user.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(userRemove);
|
||||
|
||||
|
||||
MenuAggregateRoot userResetPwd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "重置密码",
|
||||
PermissionCode = "system:user:resetPwd",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = user.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(userResetPwd);
|
||||
|
||||
|
||||
//角色管理
|
||||
MenuAggregateRoot role = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "角色管理",
|
||||
PermissionCode = "system:role:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/system/role/index",
|
||||
MenuIcon = "ri:admin-fill",
|
||||
OrderNum = 99,
|
||||
ParentId = system.Id,
|
||||
RouterName = "SystemRole"
|
||||
};
|
||||
entities.Add(role);
|
||||
|
||||
MenuAggregateRoot roleQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "角色查询",
|
||||
PermissionCode = "system:role:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = role.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(roleQuery);
|
||||
|
||||
MenuAggregateRoot roleAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "角色新增",
|
||||
PermissionCode = "system:role:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = role.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(roleAdd);
|
||||
|
||||
MenuAggregateRoot roleEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "角色修改",
|
||||
PermissionCode = "system:role:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = role.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(roleEdit);
|
||||
|
||||
MenuAggregateRoot roleRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "角色删除",
|
||||
PermissionCode = "system:role:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = role.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(roleRemove);
|
||||
|
||||
|
||||
//菜单管理
|
||||
MenuAggregateRoot menu = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "菜单管理",
|
||||
PermissionCode = "system:menu:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/system/menu/index",
|
||||
MenuIcon = "ep:menu",
|
||||
OrderNum = 98,
|
||||
ParentId = system.Id,
|
||||
RouterName = "SystemMenu"
|
||||
};
|
||||
entities.Add(menu);
|
||||
|
||||
MenuAggregateRoot menuQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "菜单查询",
|
||||
PermissionCode = "system:menu:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = menu.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(menuQuery);
|
||||
|
||||
MenuAggregateRoot menuAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "菜单新增",
|
||||
PermissionCode = "system:menu:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = menu.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(menuAdd);
|
||||
|
||||
MenuAggregateRoot menuEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "菜单修改",
|
||||
PermissionCode = "system:menu:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = menu.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(menuEdit);
|
||||
|
||||
MenuAggregateRoot menuRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "菜单删除",
|
||||
PermissionCode = "system:menu:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = menu.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(menuRemove);
|
||||
|
||||
//部门管理
|
||||
MenuAggregateRoot dept = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "部门管理",
|
||||
PermissionCode = "system:dept:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/system/dept/index",
|
||||
MenuIcon = "ri:git-branch-line",
|
||||
OrderNum = 97,
|
||||
ParentId = system.Id,
|
||||
RouterName = "SystemDept"
|
||||
};
|
||||
entities.Add(dept);
|
||||
|
||||
MenuAggregateRoot deptQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "部门查询",
|
||||
PermissionCode = "system:dept:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = dept.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(deptQuery);
|
||||
|
||||
MenuAggregateRoot deptAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "部门新增",
|
||||
PermissionCode = "system:dept:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = dept.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(deptAdd);
|
||||
|
||||
MenuAggregateRoot deptEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "部门修改",
|
||||
PermissionCode = "system:dept:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = dept.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(deptEdit);
|
||||
|
||||
MenuAggregateRoot deptRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "部门删除",
|
||||
PermissionCode = "system:dept:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = dept.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(deptRemove);
|
||||
|
||||
|
||||
|
||||
//岗位管理
|
||||
MenuAggregateRoot post = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "岗位管理",
|
||||
PermissionCode = "system:post:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/system/post/index",
|
||||
MenuIcon = "ant-design:deployment-unit-outlined",
|
||||
OrderNum = 96,
|
||||
ParentId = system.Id,
|
||||
RouterName = "SystemPost"
|
||||
};
|
||||
entities.Add(post);
|
||||
|
||||
MenuAggregateRoot postQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "岗位查询",
|
||||
PermissionCode = "system:post:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = post.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(postQuery);
|
||||
|
||||
MenuAggregateRoot postAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "岗位新增",
|
||||
PermissionCode = "system:post:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = post.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(postAdd);
|
||||
|
||||
MenuAggregateRoot postEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "岗位修改",
|
||||
PermissionCode = "system:post:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = post.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(postEdit);
|
||||
|
||||
MenuAggregateRoot postRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "岗位删除",
|
||||
PermissionCode = "system:post:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = post.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(postRemove);
|
||||
|
||||
|
||||
//操作日志
|
||||
MenuAggregateRoot operationLog = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "操作日志",
|
||||
PermissionCode = "monitor:operlog:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/monitor/operation-logs",
|
||||
MenuIcon = "ri:history-fill",
|
||||
OrderNum = 100,
|
||||
ParentId = monitoring.Id,
|
||||
RouterName = "OperationLog",
|
||||
Component = "monitor/logs/operation/index"
|
||||
};
|
||||
entities.Add(operationLog);
|
||||
|
||||
MenuAggregateRoot operationLogQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "操作查询",
|
||||
PermissionCode = "monitor:operlog:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = operationLog.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(operationLogQuery);
|
||||
|
||||
MenuAggregateRoot operationLogRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "操作删除",
|
||||
PermissionCode = "monitor:operlog:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = operationLog.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(operationLogRemove);
|
||||
|
||||
|
||||
//登录日志
|
||||
MenuAggregateRoot loginLog = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "登录日志",
|
||||
PermissionCode = "monitor:logininfor:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "/monitor/login-logs",
|
||||
IsShow = true,
|
||||
IsLink = false,
|
||||
IsCache = true,
|
||||
Component = "monitor/logs/login/index",
|
||||
MenuIcon = "ri:window-line",
|
||||
OrderNum = 100,
|
||||
ParentId = monitoring.Id,
|
||||
RouterName = "LoginLog",
|
||||
};
|
||||
entities.Add(loginLog);
|
||||
|
||||
MenuAggregateRoot loginLogQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "登录查询",
|
||||
PermissionCode = "monitor:logininfor:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = loginLog.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(loginLogQuery);
|
||||
|
||||
MenuAggregateRoot loginLogRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "登录删除",
|
||||
PermissionCode = "monitor:logininfor:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = loginLog.Id,
|
||||
IsDeleted = false,
|
||||
|
||||
};
|
||||
entities.Add(loginLogRemove);
|
||||
|
||||
//默认值
|
||||
entities.ForEach(m =>
|
||||
{
|
||||
m.IsDeleted = false;
|
||||
m.State = true;
|
||||
m.MenuSource = MenuSourceEnum.Pure;
|
||||
m.IsShow = true;
|
||||
});
|
||||
|
||||
var p = entities.GroupBy(x => x.Id);
|
||||
foreach (var k in p)
|
||||
{
|
||||
if (k.ToList().Count > 1)
|
||||
{
|
||||
Console.WriteLine("菜单id重复");
|
||||
}
|
||||
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,11 @@ using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
||||
{
|
||||
public class MenuDataSeed : IDataSeedContributor, ITransientDependency
|
||||
public class MenuRuoYiDataSeed : IDataSeedContributor, ITransientDependency
|
||||
{
|
||||
private ISqlSugarRepository<MenuAggregateRoot> _repository;
|
||||
private IGuidGenerator _guidGenerator;
|
||||
public MenuDataSeed(ISqlSugarRepository<MenuAggregateRoot> repository, IGuidGenerator guidGenerator)
|
||||
public MenuRuoYiDataSeed(ISqlSugarRepository<MenuAggregateRoot> repository, IGuidGenerator guidGenerator)
|
||||
{
|
||||
_repository = repository;
|
||||
_guidGenerator = guidGenerator;
|
||||
@@ -19,7 +19,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
||||
|
||||
public async Task SeedAsync(DataSeedContext context)
|
||||
{
|
||||
if (!await _repository.IsAnyAsync(x => x.MenuName == "系统管理"))
|
||||
if (!await _repository.IsAnyAsync(x => x.MenuName == "系统管理"&&x.MenuSource==MenuSourceEnum.Ruoyi))
|
||||
{
|
||||
await _repository.InsertManyAsync(GetSeedData());
|
||||
}
|
||||
@@ -54,7 +54,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
||||
IsLink = false,
|
||||
MenuIcon = "build",
|
||||
OrderNum = 91,
|
||||
IsDeleted = false
|
||||
IsDeleted = false,
|
||||
};
|
||||
entities.Add(code);
|
||||
|
||||
@@ -229,332 +229,332 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
||||
entities.Add(swagger);
|
||||
|
||||
|
||||
//ERP
|
||||
MenuAggregateRoot erp = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
MenuName = "ERP(待更新)",
|
||||
MenuType = MenuTypeEnum.Catalogue,
|
||||
Router = "/erp",
|
||||
IsShow = true,
|
||||
IsLink = false,
|
||||
MenuIcon = "international",
|
||||
OrderNum = 96,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(erp);
|
||||
|
||||
|
||||
|
||||
//供应商定义
|
||||
MenuAggregateRoot supplier = new MenuAggregateRoot(_guidGenerator.Create(), erp.Id)
|
||||
{
|
||||
MenuName = "供应商定义",
|
||||
PermissionCode = "erp:supplier:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "supplier",
|
||||
IsShow = true,
|
||||
IsLink = false,
|
||||
IsCache = true,
|
||||
Component = "erp/supplier/index",
|
||||
MenuIcon = "education",
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(supplier);
|
||||
|
||||
MenuAggregateRoot supplierQuery = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
{
|
||||
MenuName = "供应商查询",
|
||||
PermissionCode = "erp:supplier:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(supplierQuery);
|
||||
|
||||
MenuAggregateRoot supplierAdd = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
{
|
||||
MenuName = "供应商新增",
|
||||
PermissionCode = "erp:supplier:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(supplierAdd);
|
||||
|
||||
MenuAggregateRoot supplierEdit = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
{
|
||||
MenuName = "供应商修改",
|
||||
PermissionCode = "erp:supplier:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(supplierEdit);
|
||||
|
||||
MenuAggregateRoot supplierRemove = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
{
|
||||
MenuName = "供应商删除",
|
||||
PermissionCode = "erp:supplier:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(supplierRemove);
|
||||
|
||||
|
||||
//仓库定义
|
||||
MenuAggregateRoot warehouse = new MenuAggregateRoot(_guidGenerator.Create(), erp.Id)
|
||||
{
|
||||
MenuName = "仓库定义",
|
||||
PermissionCode = "erp:warehouse:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "warehouse",
|
||||
IsShow = true,
|
||||
IsLink = false,
|
||||
IsCache = true,
|
||||
Component = "erp/warehouse/index",
|
||||
MenuIcon = "education",
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(warehouse);
|
||||
|
||||
MenuAggregateRoot warehouseQuery = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
{
|
||||
MenuName = "仓库查询",
|
||||
PermissionCode = "erp:warehouse:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = warehouse.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(warehouseQuery);
|
||||
|
||||
MenuAggregateRoot warehouseAdd = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
{
|
||||
MenuName = "仓库新增",
|
||||
PermissionCode = "erp:warehouse:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(warehouseAdd);
|
||||
|
||||
MenuAggregateRoot warehouseEdit = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
{
|
||||
MenuName = "仓库修改",
|
||||
PermissionCode = "erp:warehouse:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(warehouseEdit);
|
||||
|
||||
MenuAggregateRoot warehouseRemove = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
{
|
||||
MenuName = "仓库删除",
|
||||
PermissionCode = "erp:warehouse:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(warehouseRemove);
|
||||
|
||||
|
||||
//单位定义
|
||||
MenuAggregateRoot unit = new MenuAggregateRoot(_guidGenerator.Create(), erp.Id)
|
||||
{
|
||||
MenuName = "单位定义",
|
||||
PermissionCode = "erp:unit:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "unit",
|
||||
IsShow = true,
|
||||
IsLink = false,
|
||||
IsCache = true,
|
||||
Component = "erp/unit/index",
|
||||
MenuIcon = "education",
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(unit);
|
||||
|
||||
MenuAggregateRoot unitQuery = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
{
|
||||
MenuName = "单位查询",
|
||||
PermissionCode = "erp:unit:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(unitQuery);
|
||||
|
||||
MenuAggregateRoot unitAdd = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
{
|
||||
MenuName = "单位新增",
|
||||
PermissionCode = "erp:unit:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(unitAdd);
|
||||
|
||||
MenuAggregateRoot unitEdit = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
{
|
||||
MenuName = "单位修改",
|
||||
PermissionCode = "erp:unit:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(unitEdit);
|
||||
|
||||
MenuAggregateRoot unitRemove = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
{
|
||||
MenuName = "单位删除",
|
||||
PermissionCode = "erp:unit:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(unitRemove);
|
||||
|
||||
|
||||
//物料定义
|
||||
MenuAggregateRoot material = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "物料定义",
|
||||
PermissionCode = "erp:material:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "material",
|
||||
IsShow = true,
|
||||
IsLink = false,
|
||||
IsCache = true,
|
||||
Component = "erp/material/index",
|
||||
MenuIcon = "education",
|
||||
OrderNum = 100,
|
||||
ParentId = erp.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(material);
|
||||
|
||||
MenuAggregateRoot materialQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "物料查询",
|
||||
PermissionCode = "erp:material:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = material.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(materialQuery);
|
||||
|
||||
MenuAggregateRoot materialAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "物料新增",
|
||||
PermissionCode = "erp:material:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = material.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(materialAdd);
|
||||
|
||||
MenuAggregateRoot materialEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "物料修改",
|
||||
PermissionCode = "erp:material:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = material.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(materialEdit);
|
||||
|
||||
MenuAggregateRoot materialRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "物料删除",
|
||||
PermissionCode = "erp:material:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = material.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(materialRemove);
|
||||
|
||||
|
||||
//采购订单
|
||||
MenuAggregateRoot purchase = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "采购订单",
|
||||
PermissionCode = "erp:purchase:list",
|
||||
MenuType = MenuTypeEnum.Menu,
|
||||
Router = "purchase",
|
||||
IsShow = true,
|
||||
IsLink = false,
|
||||
IsCache = true,
|
||||
Component = "erp/purchase/index",
|
||||
MenuIcon = "education",
|
||||
OrderNum = 100,
|
||||
ParentId = erp.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(purchase);
|
||||
|
||||
MenuAggregateRoot purchaseQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "采购订单查询",
|
||||
PermissionCode = "erp:purchase:query",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = purchase.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(purchaseQuery);
|
||||
|
||||
MenuAggregateRoot purchaseAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "采购订单新增",
|
||||
PermissionCode = "erp:purchase:add",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = purchase.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(purchaseAdd);
|
||||
|
||||
MenuAggregateRoot purchaseEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "采购订单修改",
|
||||
PermissionCode = "erp:purchase:edit",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = purchase.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(purchaseEdit);
|
||||
|
||||
MenuAggregateRoot purchaseRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
{
|
||||
|
||||
MenuName = "采购订单删除",
|
||||
PermissionCode = "erp:purchase:remove",
|
||||
MenuType = MenuTypeEnum.Component,
|
||||
OrderNum = 100,
|
||||
ParentId = purchase.Id,
|
||||
IsDeleted = false
|
||||
};
|
||||
entities.Add(purchaseRemove);
|
||||
// //ERP
|
||||
// MenuAggregateRoot erp = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
// MenuName = "ERP(待更新)",
|
||||
// MenuType = MenuTypeEnum.Catalogue,
|
||||
// Router = "/erp",
|
||||
// IsShow = true,
|
||||
// IsLink = false,
|
||||
// MenuIcon = "international",
|
||||
// OrderNum = 96,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(erp);
|
||||
//
|
||||
//
|
||||
//
|
||||
// //供应商定义
|
||||
// MenuAggregateRoot supplier = new MenuAggregateRoot(_guidGenerator.Create(), erp.Id)
|
||||
// {
|
||||
// MenuName = "供应商定义",
|
||||
// PermissionCode = "erp:supplier:list",
|
||||
// MenuType = MenuTypeEnum.Menu,
|
||||
// Router = "supplier",
|
||||
// IsShow = true,
|
||||
// IsLink = false,
|
||||
// IsCache = true,
|
||||
// Component = "erp/supplier/index",
|
||||
// MenuIcon = "education",
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(supplier);
|
||||
//
|
||||
// MenuAggregateRoot supplierQuery = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
// {
|
||||
// MenuName = "供应商查询",
|
||||
// PermissionCode = "erp:supplier:query",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(supplierQuery);
|
||||
//
|
||||
// MenuAggregateRoot supplierAdd = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
// {
|
||||
// MenuName = "供应商新增",
|
||||
// PermissionCode = "erp:supplier:add",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
//
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(supplierAdd);
|
||||
//
|
||||
// MenuAggregateRoot supplierEdit = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
// {
|
||||
// MenuName = "供应商修改",
|
||||
// PermissionCode = "erp:supplier:edit",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(supplierEdit);
|
||||
//
|
||||
// MenuAggregateRoot supplierRemove = new MenuAggregateRoot(_guidGenerator.Create(), supplier.Id)
|
||||
// {
|
||||
// MenuName = "供应商删除",
|
||||
// PermissionCode = "erp:supplier:remove",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(supplierRemove);
|
||||
//
|
||||
//
|
||||
// //仓库定义
|
||||
// MenuAggregateRoot warehouse = new MenuAggregateRoot(_guidGenerator.Create(), erp.Id)
|
||||
// {
|
||||
// MenuName = "仓库定义",
|
||||
// PermissionCode = "erp:warehouse:list",
|
||||
// MenuType = MenuTypeEnum.Menu,
|
||||
// Router = "warehouse",
|
||||
// IsShow = true,
|
||||
// IsLink = false,
|
||||
// IsCache = true,
|
||||
// Component = "erp/warehouse/index",
|
||||
// MenuIcon = "education",
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(warehouse);
|
||||
//
|
||||
// MenuAggregateRoot warehouseQuery = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
// {
|
||||
// MenuName = "仓库查询",
|
||||
// PermissionCode = "erp:warehouse:query",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = warehouse.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(warehouseQuery);
|
||||
//
|
||||
// MenuAggregateRoot warehouseAdd = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
// {
|
||||
// MenuName = "仓库新增",
|
||||
// PermissionCode = "erp:warehouse:add",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(warehouseAdd);
|
||||
//
|
||||
// MenuAggregateRoot warehouseEdit = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
// {
|
||||
// MenuName = "仓库修改",
|
||||
// PermissionCode = "erp:warehouse:edit",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(warehouseEdit);
|
||||
//
|
||||
// MenuAggregateRoot warehouseRemove = new MenuAggregateRoot(_guidGenerator.Create(), warehouse.Id)
|
||||
// {
|
||||
// MenuName = "仓库删除",
|
||||
// PermissionCode = "erp:warehouse:remove",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(warehouseRemove);
|
||||
//
|
||||
//
|
||||
// //单位定义
|
||||
// MenuAggregateRoot unit = new MenuAggregateRoot(_guidGenerator.Create(), erp.Id)
|
||||
// {
|
||||
// MenuName = "单位定义",
|
||||
// PermissionCode = "erp:unit:list",
|
||||
// MenuType = MenuTypeEnum.Menu,
|
||||
// Router = "unit",
|
||||
// IsShow = true,
|
||||
// IsLink = false,
|
||||
// IsCache = true,
|
||||
// Component = "erp/unit/index",
|
||||
// MenuIcon = "education",
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(unit);
|
||||
//
|
||||
// MenuAggregateRoot unitQuery = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
// {
|
||||
// MenuName = "单位查询",
|
||||
// PermissionCode = "erp:unit:query",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(unitQuery);
|
||||
//
|
||||
// MenuAggregateRoot unitAdd = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
// {
|
||||
// MenuName = "单位新增",
|
||||
// PermissionCode = "erp:unit:add",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(unitAdd);
|
||||
//
|
||||
// MenuAggregateRoot unitEdit = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
// {
|
||||
// MenuName = "单位修改",
|
||||
// PermissionCode = "erp:unit:edit",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(unitEdit);
|
||||
//
|
||||
// MenuAggregateRoot unitRemove = new MenuAggregateRoot(_guidGenerator.Create(), unit.Id)
|
||||
// {
|
||||
// MenuName = "单位删除",
|
||||
// PermissionCode = "erp:unit:remove",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(unitRemove);
|
||||
//
|
||||
//
|
||||
// //物料定义
|
||||
// MenuAggregateRoot material = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "物料定义",
|
||||
// PermissionCode = "erp:material:list",
|
||||
// MenuType = MenuTypeEnum.Menu,
|
||||
// Router = "material",
|
||||
// IsShow = true,
|
||||
// IsLink = false,
|
||||
// IsCache = true,
|
||||
// Component = "erp/material/index",
|
||||
// MenuIcon = "education",
|
||||
// OrderNum = 100,
|
||||
// ParentId = erp.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(material);
|
||||
//
|
||||
// MenuAggregateRoot materialQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "物料查询",
|
||||
// PermissionCode = "erp:material:query",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = material.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(materialQuery);
|
||||
//
|
||||
// MenuAggregateRoot materialAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "物料新增",
|
||||
// PermissionCode = "erp:material:add",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = material.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(materialAdd);
|
||||
//
|
||||
// MenuAggregateRoot materialEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "物料修改",
|
||||
// PermissionCode = "erp:material:edit",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = material.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(materialEdit);
|
||||
//
|
||||
// MenuAggregateRoot materialRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "物料删除",
|
||||
// PermissionCode = "erp:material:remove",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = material.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(materialRemove);
|
||||
//
|
||||
//
|
||||
// //采购订单
|
||||
// MenuAggregateRoot purchase = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "采购订单",
|
||||
// PermissionCode = "erp:purchase:list",
|
||||
// MenuType = MenuTypeEnum.Menu,
|
||||
// Router = "purchase",
|
||||
// IsShow = true,
|
||||
// IsLink = false,
|
||||
// IsCache = true,
|
||||
// Component = "erp/purchase/index",
|
||||
// MenuIcon = "education",
|
||||
// OrderNum = 100,
|
||||
// ParentId = erp.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(purchase);
|
||||
//
|
||||
// MenuAggregateRoot purchaseQuery = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "采购订单查询",
|
||||
// PermissionCode = "erp:purchase:query",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = purchase.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(purchaseQuery);
|
||||
//
|
||||
// MenuAggregateRoot purchaseAdd = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "采购订单新增",
|
||||
// PermissionCode = "erp:purchase:add",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = purchase.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(purchaseAdd);
|
||||
//
|
||||
// MenuAggregateRoot purchaseEdit = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "采购订单修改",
|
||||
// PermissionCode = "erp:purchase:edit",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = purchase.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(purchaseEdit);
|
||||
//
|
||||
// MenuAggregateRoot purchaseRemove = new MenuAggregateRoot(_guidGenerator.Create())
|
||||
// {
|
||||
//
|
||||
// MenuName = "采购订单删除",
|
||||
// PermissionCode = "erp:purchase:remove",
|
||||
// MenuType = MenuTypeEnum.Component,
|
||||
// OrderNum = 100,
|
||||
// ParentId = purchase.Id,
|
||||
// IsDeleted = false
|
||||
// };
|
||||
// entities.Add(purchaseRemove);
|
||||
|
||||
|
||||
|
||||
@@ -564,7 +564,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
||||
|
||||
MenuName = "Yi框架",
|
||||
MenuType = MenuTypeEnum.Catalogue,
|
||||
Router = "https://gitee.com/ccnetcore/yi",
|
||||
Router = "https://ccnetcore.com",
|
||||
IsShow = true,
|
||||
IsLink = true,
|
||||
MenuIcon = "guide",
|
||||
@@ -1317,6 +1317,8 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
||||
{
|
||||
m.IsDeleted = false;
|
||||
m.State = true;
|
||||
m.MenuSource = MenuSourceEnum.Ruoyi;
|
||||
m.IsShow = true;
|
||||
});
|
||||
|
||||
var p = entities.GroupBy(x => x.Id);
|
||||
24
Yi.Abp.Net8/publish_Demo.bat
Normal file
24
Yi.Abp.Net8/publish_Demo.bat
Normal file
@@ -0,0 +1,24 @@
|
||||
@echo on
|
||||
|
||||
set SERVER_USER=root
|
||||
set SERVER_IP=ccnetcore.com
|
||||
set FILE_PATH=publish_demo_02.zip
|
||||
set REMOTE_PATH=/home/yi/build/publish_demo_02.zip
|
||||
set REMOTE_COMMAND="cd /home/yi/demo-net8&&pwd&&unzip -o /home/yi/build/publish_demo_02.zip -d ./&&./start.sh"
|
||||
set sevenzip_Path="D:\Program Files\7-Zip\7z.exe"
|
||||
|
||||
echo start
|
||||
echo 1-build-start
|
||||
:: dotnet publish
|
||||
echo 1-build-end
|
||||
echo 2-zip-start
|
||||
|
||||
%sevenzip_Path% a ./publish_demo_02.zip ./src/Yi.Abp.Web/bin/Release/net8.0/linux-x64/publish/*
|
||||
:: tar -cvf publish_demo_02.zip -C "dist" "*"
|
||||
echo 2-zip-end
|
||||
echo 3-publish-start
|
||||
scp %FILE_PATH% %SERVER_USER%@%SERVER_IP%:%REMOTE_PATH%
|
||||
ssh %SERVER_USER%@%SERVER_IP% %REMOTE_COMMAND%
|
||||
echo 3-publish-end
|
||||
echo end
|
||||
pause
|
||||
@@ -13,22 +13,24 @@
|
||||
},
|
||||
|
||||
//数据库类型列表
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle" ],
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle", "PostgreSQL" ],
|
||||
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-abp-dev.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
//]
|
||||
},
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-abp-dev.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true,
|
||||
"EnableUnderLine": false // 启用驼峰转下划线
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
// "HOST=[xxxx];PORT=5432;DATABASE=[xxxx];USERID=[xxxx];PASSWORD=[xxxx]" //PostgreSQL
|
||||
//]
|
||||
},
|
||||
|
||||
//鉴权
|
||||
"JwtOptions": {
|
||||
|
||||
Binary file not shown.
@@ -39,6 +39,17 @@ namespace Yi.Abp.Application.Services
|
||||
return name ?? "HelloWord";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异常处理
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("error")]
|
||||
public string GetError()
|
||||
{
|
||||
throw new UserFriendlyException("业务异常");
|
||||
throw new Exception("系统异常");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SqlSugar
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Text;
|
||||
using System.Threading.RateLimiting;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Newtonsoft.Json.Converters;
|
||||
@@ -11,6 +13,7 @@ using Volo.Abp.AspNetCore.ExceptionHandling;
|
||||
using Volo.Abp.AspNetCore.MultiTenancy;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
|
||||
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
|
||||
using Volo.Abp.AspNetCore.Serilog;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Autofac;
|
||||
@@ -25,6 +28,7 @@ using Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
|
||||
using Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
|
||||
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder;
|
||||
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
|
||||
using Yi.Framework.AspNetCore.UnifyResult;
|
||||
using Yi.Framework.Bbs.Application;
|
||||
using Yi.Framework.Bbs.Application.Extensions;
|
||||
using Yi.Framework.ChatHub.Application;
|
||||
@@ -68,6 +72,10 @@ namespace Yi.Abp.Web
|
||||
optios.AlwaysLogSelectors.Add(x => Task.FromResult(true));
|
||||
});
|
||||
|
||||
//采用furion格式的规范化api,默认不开启,使用abp优雅的方式
|
||||
//你没看错。。。
|
||||
//service.AddFurionUnifyResultApi();
|
||||
|
||||
//配置错误处理显示详情
|
||||
Configure<AbpExceptionHandlingOptions>(options => { options.SendExceptionsDetailsToClients = true; });
|
||||
|
||||
@@ -299,6 +307,8 @@ namespace Yi.Abp.Web
|
||||
app.UseDefaultFiles();
|
||||
app.UseDirectoryBrowser("/api/app/wwwroot");
|
||||
|
||||
|
||||
// app.Properties.Add("_AbpExceptionHandlingMiddleware_Added",false);
|
||||
//工作单元
|
||||
app.UseUnitOfWork();
|
||||
|
||||
|
||||
@@ -17,24 +17,26 @@
|
||||
},
|
||||
|
||||
//数据库类型列表
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle" ],
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle", "PostgreSQL" ],
|
||||
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-abp-dev.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true,
|
||||
//SAAS多租户
|
||||
"EnabledSaasMultiTenancy": false
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
//]
|
||||
},
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-abp-dev.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true,
|
||||
"EnableUnderLine": false, // 启用驼峰转下划线
|
||||
//SAAS多租户
|
||||
"EnabledSaasMultiTenancy": true
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
// "HOST=[xxxx];PORT=5432;DATABASE=[xxxx];USERID=[xxxx];PASSWORD=[xxxx]" //PostgreSQL
|
||||
//]
|
||||
},
|
||||
|
||||
//redis使用freeesql参数在“FreeSqlOptions的ConnectionStringBuilder中”
|
||||
"Redis": {
|
||||
|
||||
@@ -13,22 +13,24 @@
|
||||
},
|
||||
|
||||
//数据库类型列表
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle" ],
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle", "PostgreSQL" ],
|
||||
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-abp-dev.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
//]
|
||||
},
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-abp-dev.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true,
|
||||
"EnableUnderLine": false // 启用驼峰转下划线
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
// "HOST=[xxxx];PORT=5432;DATABASE=[xxxx];USERID=[xxxx];PASSWORD=[xxxx]" //PostgreSQL
|
||||
//]
|
||||
},
|
||||
|
||||
//鉴权
|
||||
"JwtOptions": {
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Yi.Framework.Rbac.Test.System
|
||||
}
|
||||
catch (UserFriendlyException ex)
|
||||
{
|
||||
ex.Message.ShouldBe(UserConst.User_Exist);
|
||||
ex.Message.ShouldBe(UserConst.Exist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,22 +13,24 @@
|
||||
},
|
||||
|
||||
//数据库类型列表
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle" ],
|
||||
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle", "PostgreSQL" ],
|
||||
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-rbac-test.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
//]
|
||||
},
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-rbac-test.db",
|
||||
"DbType": "Sqlite",
|
||||
"EnabledReadWrite": false,
|
||||
"EnabledCodeFirst": true,
|
||||
"EnabledSqlLog": true,
|
||||
"EnabledDbSeed": true,
|
||||
"EnableUnderLine": false // 启用驼峰转下划线
|
||||
//读写分离地址
|
||||
//"ReadUrl": [
|
||||
// "DataSource=[xxxx]", //Sqlite
|
||||
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
|
||||
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
|
||||
// "HOST=[xxxx];PORT=5432;DATABASE=[xxxx];USERID=[xxxx];PASSWORD=[xxxx]" //PostgreSQL
|
||||
//]
|
||||
},
|
||||
|
||||
//鉴权
|
||||
"JwtOptions": {
|
||||
|
||||
@@ -8,20 +8,18 @@ namespace Yi.Abp.Tool.Domain
|
||||
public class NugetCrawlerManager : ITransientDependency
|
||||
{
|
||||
private const string NugetVersionUrl = "https://www.nuget.org/packages/Yi.Abp.Tool#versions-body-tab";
|
||||
|
||||
public NugetCrawlerManager(IDistributedCache<NugetResult> cache)
|
||||
{
|
||||
//缓存设置1分钟获取一次结果
|
||||
this.NugetResult = cache.GetOrAdd("NugetResult", () =>
|
||||
{
|
||||
return InitData();
|
||||
}, () =>
|
||||
{
|
||||
var options = new DistributedCacheEntryOptions();
|
||||
options.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(1);
|
||||
return options;
|
||||
})!;
|
||||
|
||||
this.NugetResult = cache.GetOrAdd("NugetResult", () => { return InitData(); }, () =>
|
||||
{
|
||||
var options = new DistributedCacheEntryOptions();
|
||||
options.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(1);
|
||||
return options;
|
||||
})!;
|
||||
}
|
||||
|
||||
private HtmlDocument HtmlDoc { get; set; }
|
||||
private NugetResult NugetResult { get; set; } = new NugetResult();
|
||||
|
||||
@@ -56,11 +54,12 @@ namespace Yi.Abp.Tool.Domain
|
||||
|
||||
foreach (var tr in trDoc)
|
||||
{
|
||||
var version = tr.ChildNodes.Where(x => x.Name == "td").First().ChildNodes.Where(x => x.Name == "a").First().GetAttributes("title").First().Value;
|
||||
var version = tr.ChildNodes.Where(x => x.Name == "td").First().ChildNodes.Where(x => x.Name == "a")
|
||||
.First().GetAttributes("title").First().Value;
|
||||
|
||||
versions.Add(version);
|
||||
|
||||
}
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
@@ -70,8 +69,17 @@ namespace Yi.Abp.Tool.Domain
|
||||
/// <returns></returns>
|
||||
private long GetDownloadNumber()
|
||||
{
|
||||
var spanDoc = HtmlDoc.DocumentNode.SelectNodes("//*[@id=\"skippedToContent\"]/section/div/aside/div[1]/div[2]/div[1]/span[2]");
|
||||
var spanDoc =
|
||||
HtmlDoc.DocumentNode.SelectNodes(
|
||||
"//*[@id=\"skippedToContent\"]/section/div/aside/div[1]/div[2]/div[1]/span[2]");
|
||||
var downLoadNumber = spanDoc.First().InnerText;
|
||||
if (downLoadNumber.Contains("K"))
|
||||
{
|
||||
downLoadNumber = downLoadNumber.TrimEnd('K');
|
||||
return (long)Math.Round(decimal.Parse(downLoadNumber) * 1000);
|
||||
}
|
||||
|
||||
|
||||
return long.Parse(downLoadNumber);
|
||||
}
|
||||
}
|
||||
@@ -82,4 +90,4 @@ namespace Yi.Abp.Tool.Domain
|
||||
public long DownloadNumber { get; set; }
|
||||
public List<string> Versions { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,7 @@ VITE_APP_URL="http://localhost:19001/api/app"
|
||||
|
||||
# ws/开发环境
|
||||
VITE_APP_BASE_WS = '/dev-ws'
|
||||
VITE_APP_BASE_URL_WS="http://localhost:19001/hub"
|
||||
VITE_APP_BASE_URL_WS="http://localhost:19001/hub"
|
||||
|
||||
# 是否开启ICP备案模式
|
||||
VITE_APP_ICP = false
|
||||
@@ -6,4 +6,7 @@ VITE_APP_URL="http://ccnetcore.com:19001/api/app"
|
||||
|
||||
# ws
|
||||
VITE_APP_BASE_WS = '/prod-ws'
|
||||
VITE_APP_BASE_URL_WS="http://ccnetcore.com:19001/hub"
|
||||
VITE_APP_BASE_URL_WS="http://ccnetcore.com:19001/hub"
|
||||
|
||||
# 是否开启ICP备案模式
|
||||
VITE_APP_ICP = false
|
||||
@@ -4,20 +4,22 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>意社区</title>
|
||||
<link rel="stylesheet" href="/src/assets/loading.css" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5453339688995325"
|
||||
crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Loading">
|
||||
<div class="loader JS_on">
|
||||
<span class="binary"></span>
|
||||
<span class="binary"></span>
|
||||
<span class="getting-there">意社区很大,你要等一下...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<title>.Net意社区</title>
|
||||
<!-- 为了,icp备案-->
|
||||
<!-- <title>个人成果展示</title>-->
|
||||
<link rel="stylesheet" href="/src/assets/loading.css" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5453339688995325"
|
||||
crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Loading">
|
||||
<div class="loader JS_on">
|
||||
<span class="binary"></span>
|
||||
<span class="binary"></span>
|
||||
<span class="getting-there">意社区很大,你要等一下...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -18,6 +18,24 @@ export function login(username, password, code, uuid) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//找回密码
|
||||
export function retrievePassword(password, phone, code, uuid) {
|
||||
const data = {
|
||||
password,
|
||||
phone,
|
||||
code,
|
||||
uuid,
|
||||
};
|
||||
return request({
|
||||
url: "/account/retrieve-password",
|
||||
headers: {
|
||||
isToken: false,
|
||||
},
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
// 注册方法
|
||||
export function register(userName, password, phone, code, uuid) {
|
||||
const data = {
|
||||
@@ -76,3 +94,15 @@ export function getCodePhone(phone) {
|
||||
data: { phone },
|
||||
});
|
||||
}
|
||||
// 获取短信验证码-为了重置密码
|
||||
export function getCodePhoneForRetrievePassword(phone) {
|
||||
return request({
|
||||
url: "/account/captcha-phone/repassword",
|
||||
headers: {
|
||||
isToken: false,
|
||||
},
|
||||
method: "post",
|
||||
timeout: 20000,
|
||||
data: { phone },
|
||||
});
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user