From 26f6856151e89dc02ab43c1389a8bc04a10aa695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E5=BB=BA=E7=A5=A5?= <958464639@qq.com> Date: Sun, 14 Jul 2024 21:38:58 +0800 Subject: [PATCH] =?UTF-8?q?714=E6=9C=AC=E5=91=A8=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...DD\345\206\215\346\200\273\347\273\223.md" | 26 +++++ ...67\350\247\222\350\211\262\350\241\250.md" | 99 +++++++++++++++++++ ...56\347\232\204\347\273\237\344\270\200.md" | 28 ++++++ ...06\347\240\201\345\212\240\347\233\220.md" | 36 +++++++ ...dv\347\273\204\344\273\266\345\272\223.md" | 79 +++++++++++++++ 5 files changed, 268 insertions(+) create mode 100644 "\345\215\242\345\273\272\347\245\245/20240708-DDD\345\206\215\346\200\273\347\273\223.md" create mode 100644 "\345\215\242\345\273\272\347\245\245/20240709-\347\224\250\346\210\267\350\247\222\350\211\262\350\241\250.md" create mode 100644 "\345\215\242\345\273\272\347\245\245/20240710-\350\277\224\345\233\236\346\225\260\346\215\256\347\232\204\347\273\237\344\270\200.md" create mode 100644 "\345\215\242\345\273\272\347\245\245/20240711-\345\257\206\347\240\201\345\212\240\347\233\220.md" create mode 100644 "\345\215\242\345\273\272\347\245\245/20240712-\345\211\215\347\253\257Antdv\347\273\204\344\273\266\345\272\223.md" diff --git "a/\345\215\242\345\273\272\347\245\245/20240708-DDD\345\206\215\346\200\273\347\273\223.md" "b/\345\215\242\345\273\272\347\245\245/20240708-DDD\345\206\215\346\200\273\347\273\223.md" new file mode 100644 index 0000000..ed0f68b --- /dev/null +++ "b/\345\215\242\345\273\272\347\245\245/20240708-DDD\345\206\215\346\200\273\347\273\223.md" @@ -0,0 +1,26 @@ +## 关于 DDD 领域驱动设计思想的探讨与思考 + +- 域 +- 子域 +- 聚合 +- 聚合根 +- 领域模型 +- 值对象 +- 领域模型 一些不涉及其他实体的业务操作,放在领域模型 +- 通用仓储接口(底层 贴近数据) +- 领域模型仓储接口 - +- 领域服务接口 +- 应用服务接口 +- API 服务接口(高层 贴近用户) 接收参数 最多做一些数据验证工作 +- 领域事件 +- 头脑风暴 +- 事件风暴 + +### 领域模型:一些不涉及其他对象(不是指其他类型,是指对象的实例)的业务操作,放在领域模型 + +- Admin2024.Domain + 1. 通用仓储接口(底层 贴近数据)--其实现放在基础设施层,单独的一层 ORM 工具层 + 2. 领域模型仓储接口--独有的一些业务,可以写成领域模型的接口,其实现放在 Domain + 3. 领域服务接口--涉及到多个领域实体的业务和操作,放在领域服务,持久化也放在领域服务 +- Admin2024.Application +- Admin2024.Application.Contracts 4. 应用服务接口--应用服务其实就是对领域模型和领域服务进行编排的一个层,比较薄 5. API 服务接口(高层,因为贴近因为)--接收参数,最多做一些数据验证工作 diff --git "a/\345\215\242\345\273\272\347\245\245/20240709-\347\224\250\346\210\267\350\247\222\350\211\262\350\241\250.md" "b/\345\215\242\345\273\272\347\245\245/20240709-\347\224\250\346\210\267\350\247\222\350\211\262\350\241\250.md" new file mode 100644 index 0000000..2abff13 --- /dev/null +++ "b/\345\215\242\345\273\272\347\245\245/20240709-\347\224\250\346\210\267\350\247\222\350\211\262\350\241\250.md" @@ -0,0 +1,99 @@ +#### 分配角色给用户 + +```csharp +using Admin2024.Domain.Entity.System; +using Admin2024.Domain.Interface; + +namespace Admin2024.Domain.DomainService; + +public class AppUserDomainService : IAppUserDomainService +{ + private readonly IRepository _appUserRepository; + private readonly IRepository _appRoleRepository; + private readonly IRepository _appUserRoleRepository; + + public AppUserDomainService(IRepository appUserRepository, + IRepository appUserRoleRepository, IRepository appRoleRepository) + { + _appUserRepository = appUserRepository; + _appRoleRepository = appRoleRepository; + _appUserRoleRepository = appUserRoleRepository; + } + + // 给用户分配角色 + public async Task AssigmRole(Guid appUserId, Guid appRoleId) + { + // 1.需要对id对应的实例存在不存在做验证 + // 2.如果都存在,需要对id对应的领域对象做进一步验证,如状态验证和业务验证 + var user = await _appUserRepository.GetByIdAsync(appUserId); + var role = await _appRoleRepository.GetByIdAsync(appRoleId); + // id对应的用户和角色都存在的情况下 + if (user != null && role != null) + { + // 业务要求:用户没有被删除,也没有被禁用 + // 业务要求:角色没有被删除,也没有被禁用 + if (user.IsDeleted != true && user.IsActived == true + && role.IsDeleted != true && role.IsActived == true) + { + var userRole = new AppUserRole { AppUserId = appUserId, AppRoleId = appRoleId }; + var res = await _appUserRoleRepository.CreateAsync(userRole); + return res; + } + + return null; + } + + return null; + + } + + public async Task Create(string username, string password, string confirmPassword) + { + // 先用用户名去查找数据库有无相当用户名的记录,如果找到,说明用户名重复了 + var user = _appUserRepository.Table.FirstOrDefault(x => x.Username == username); + + if (user == null && password == confirmPassword) + { + var appUser = await _appUserRepository.CreateAsync(new AppUser + { + Username = username, + Password = password, + Salt = "盐" + }); + return appUser; + } + return null; + } + + public void HasPemission(AppPermission appPermission) + { + throw new NotImplementedException(); + } + + public string? Login(string username, string password) + { + var user = _appUserRepository.Table.FirstOrDefault(x => x.Username == username); + + if (user != null && user.Password == password) + { + return "我是token"; + } + + return null; + } + + // 修改密码,修改密码的大部分操作在领域类型中完成的,如,md5加密,或者base64加密 + // 领域服务中,仅仅只是完成持久化 + public async void ModifyPassword(Guid id, string password) + { + var user = await _appUserRepository.GetByIdAsync(id); + if (user != null) + { + // 真正修改密码,其实是在领域模型中完成 + user.ModifyPassword(password); + await _appUserRepository.UpdateAsync(id, user); + } + + } +} +``` diff --git "a/\345\215\242\345\273\272\347\245\245/20240710-\350\277\224\345\233\236\346\225\260\346\215\256\347\232\204\347\273\237\344\270\200.md" "b/\345\215\242\345\273\272\347\245\245/20240710-\350\277\224\345\233\236\346\225\260\346\215\256\347\232\204\347\273\237\344\270\200.md" new file mode 100644 index 0000000..b1cc314 --- /dev/null +++ "b/\345\215\242\345\273\272\347\245\245/20240710-\350\277\224\345\233\236\346\225\260\346\215\256\347\232\204\347\273\237\344\270\200.md" @@ -0,0 +1,28 @@ +## 返回的数据 + +```csharp +namespace Demo.Domain.ApiRes; + +public class ApiResponse +{ + public bool IsSuccess { get; protected set; } + public T Data { get; protected set; } + public string Message { get; protected set; } + public ApiResponse(bool isSuccess, T data, string message) + { + IsSuccess = isSuccess; + Data = data; + Message = message; + } + public static ApiResponse Success(T data) + { + return new ApiResponse(true, data, "成功"); + } + public static ApiResponse Error(string message) + { +#pragma warning disable CS8604 // 引用类型参数可能为 null。 + return new ApiResponse(false, default, message); +#pragma warning restore CS8604 // 引用类型参数可能为 null。 + } +} +``` diff --git "a/\345\215\242\345\273\272\347\245\245/20240711-\345\257\206\347\240\201\345\212\240\347\233\220.md" "b/\345\215\242\345\273\272\347\245\245/20240711-\345\257\206\347\240\201\345\212\240\347\233\220.md" new file mode 100644 index 0000000..564fca6 --- /dev/null +++ "b/\345\215\242\345\273\272\347\245\245/20240711-\345\257\206\347\240\201\345\212\240\347\233\220.md" @@ -0,0 +1,36 @@ +## 密码加盐 + +- 密码加盐,是指在密码加密时,在密码的基础上,再添加一些随机的字符串,叫做盐,这样,即使数据库被破解,黑客也拿不到真正的密码,只能拿去加盐后的密码,然后通过彩虹表或者字典攻击,才能破解出真正的密码。 + +```csharp +using System.Security.Cryptography; +using System.Text; + +namespace Demo.Domain.SaltPwd; + +public class SaltMd5 +{ + public static string GetPasswordSalt() + { + var salt = new byte[128 / 8]; + using (var saltnum = RandomNumberGenerator.Create()) + { + saltnum.GetBytes(salt); + } + return Convert.ToBase64String(salt); + } + public static string GenEncodingPassword(string password + , string salt) + { + MD5 md5 = MD5.Create(); + byte[] bs = Encoding.UTF8.GetBytes(password + salt); + byte[] hs = md5.ComputeHash(bs); + StringBuilder strb = new StringBuilder(); + foreach (byte item in hs) + { + strb.Append(item.ToString("x2")); + } + return strb.ToString(); + } +} +``` diff --git "a/\345\215\242\345\273\272\347\245\245/20240712-\345\211\215\347\253\257Antdv\347\273\204\344\273\266\345\272\223.md" "b/\345\215\242\345\273\272\347\245\245/20240712-\345\211\215\347\253\257Antdv\347\273\204\344\273\266\345\272\223.md" new file mode 100644 index 0000000..aed6802 --- /dev/null +++ "b/\345\215\242\345\273\272\347\245\245/20240712-\345\211\215\347\253\257Antdv\347\273\204\344\273\266\345\272\223.md" @@ -0,0 +1,79 @@ +### 前端 Antdv 组件库 + +## 一、引入 ant-design-vue + +### 1.新建项目 + +### 2.使用组件 + +#### 1. 安装 + +```js +yarn add ant-design-vue +``` + +#### 2. 注册 + +1. 全局完整注册 + +```js +import { createApp } from "vue"; +import App from "./App"; +// 以下完整引入antdv +import Antd from "ant-design-vue"; +import "ant-design-vue/dist/reset.css"; + +let app = createApp(App); + +app.use(Antd).mount("#app"); +// 样式文件需要单独引入 +``` + +2. 全局部分注册 + +```js +import { createApp } from "vue"; +import { Button, message } from "ant-design-vue"; +import App from "./App"; + +let app = createApp(App); + +/* 会自动注册 Button 下的子组件, 例如 Button.Group */ +app.use(Button).mount("#app"); + +app.config.globalProperties.$message = message; +``` + +3. 局部组件 + 需要分别注册组件子组件,如 Button、ButtonGroup,并且注册后仅在当前组件中有效 + +```js + // 选项式写法 + + + // 组合式写法 + + + +``` + +## 二、按需加载 + +> ant-design-vue 默认支持基于 ES modules 的 tree shaking,直接引入 import { Button } from 'ant-design-vue'; 就会有按需加载的效果 -- Gitee