11 Commits
v2.4.0 ... main

Author SHA1 Message Date
041f3eeda1 chore: 🔨 框架代码同步 (#343)
Co-authored-by: tk <fiyne1a@dingtalk.com>
2025-08-02 17:33:13 +08:00
1650b8a127 feat: 框架代码同步 (#342)
Co-authored-by: tk <fiyne1a@dingtalk.com>
2025-07-29 10:11:54 +08:00
tk
e99cb2aff9 feat: 框架代码同步 2025-07-19 10:00:04 +08:00
tk
4f6d465602 refactor: ♻️ projectUsings
[skip ci]
2025-07-15 19:26:28 +08:00
tk
fe19289b79 feat: 钱包冻结解冻 2025-07-15 19:21:58 +08:00
tk
e4d71a516d 1 2025-07-10 15:05:00 +08:00
tk
c15abdc5bb 1 2025-07-10 15:05:00 +08:00
4a5a7b96fc fix: 🐛 build err (#337)
[skip ci]

Co-authored-by: tk <fiyne1a@dingtalk.com>
2025-07-09 11:19:46 +08:00
3f4f547338 fix: 🐛 编译错误 (#336)
[skip ci]

Co-authored-by: tk <fiyne1a@dingtalk.com>
2025-07-09 09:44:58 +08:00
d01ead8283 feat: 代码模板 (#335)
Co-authored-by: tk <fiyne1a@dingtalk.com>
2025-07-08 16:04:15 +08:00
dc3249428a Merge pull request #333 from nsnail/release
chore(release): 2.4.0
2025-07-02 19:32:05 +08:00
313 changed files with 7083 additions and 2560 deletions

View File

@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/aspnet:9.0.5 AS base FROM mcr.microsoft.com/dotnet/aspnet:9.0.7 AS base
WORKDIR /app WORKDIR /app
EXPOSE 8080 EXPOSE 8080
RUN apt update RUN apt update

View File

@ -13,7 +13,10 @@ USDT
中专 中专
中共党员 中共党员
为其中之一 为其中之一
交易
人工
人工审核 人工审核
代码模板导出
以什么开始 以什么开始
以什么结束 以什么结束
作业名称 作业名称
@ -52,9 +55,11 @@ USDT
小于 小于
小于等于 小于等于
小学 小学
已冻结
已发送 已发送
已婚 已婚
已校验 已校验
已解冻
已读 已读
并且 并且
归属角色 归属角色
@ -96,7 +101,8 @@ USDT
未读 未读
本人数据 本人数据
本科 本科
本部门和下级部门数据 本部门和下级部门数据
本部门和所有子部门数据
本部门数据 本部门数据
框架 框架
比较数据库结构 比较数据库结构
@ -116,7 +122,6 @@ USDT
登录名 登录名
登录日志导出 登录日志导出
硕士 硕士
示例导出
离异 离异
空闲 空闲
站内信导出 站内信导出
@ -125,6 +130,7 @@ USDT
等待支付 等待支付
管理员充值 管理员充值
管理员扣费 管理员扣费
管理员赠送
管理模块 管理模块
系统模块 系统模块
绑定手机号码 绑定手机号码
@ -144,6 +150,8 @@ USDT
请求日志导出 请求日志导出
调试 调试
身份证 身份证
转账支出
转账收入
运行 运行
追踪 追踪
追踪标识 追踪标识
@ -154,6 +162,7 @@ USDT
配置导出 配置导出
重设密码 重设密码
钱包交易导出 钱包交易导出
钱包冻结导出
链接 链接
错误 错误
随机排序 随机排序

View File

@ -2,6 +2,7 @@
6位数字 6位数字
8位以上数字字母组合 8位以上数字字母组合
XML注释文件不存在 XML注释文件不存在
不能设置自己为上级
中文姓名 中文姓名
事务已回滚 事务已回滚
事务已提交 事务已提交
@ -12,6 +13,7 @@ XML注释文件不存在
作业名称不能为空 作业名称不能为空
允许的文件大小 允许的文件大小
允许的文件格式 允许的文件格式
冻结状态不正确
区号电话号码分机号 区号电话号码分机号
参数格式不正确 参数格式不正确
唯一编码不能为空 唯一编码不能为空
@ -31,6 +33,7 @@ XML注释文件不存在
性别不正确 性别不正确
手机号码不正确 手机号码不正确
手机号码不能为空 手机号码不能为空
指定的上级为该账号的下级用户
接口编码不存在 接口编码不存在
支付宝账号 支付宝账号
支付方式不正确 支付方式不正确
@ -58,25 +61,22 @@ XML注释文件不存在
未指定部门 未指定部门
未获取到待执行任务 未获取到待执行任务
档案可见性不正确 档案可见性不正确
模块名称不能为空 此操作不被允许
模块类型不能为空
模块说明不能为空
此节点已下线 此节点已下线
民族不正确 民族不正确
消息主题不能为空 消息主题不能为空
消息内容不能为空 消息内容不能为空
父节点不存在 父节点不存在
用户不存在 用户不存在
用户名不符合要求
用户名不能为空 用户名不能为空
用户名不能是手机号码 用户名不能是手机号码
用户名或密码错误 用户名或密码错误
用户名长度4位以上
用户头像不能为空 用户头像不能为空
用户编号不存在 用户编号不存在
登录用户 登录用户
目标设备不能为空 目标设备不能为空
短信验证请求不能为空 短信验证请求不能为空
种子数据插入完成
站内信不存在 站内信不存在
站内信状态不正确 站内信状态不正确
站内信类型不正确 站内信类型不正确
@ -101,7 +101,6 @@ XML注释文件不存在
请求地址不能为空 请求地址不能为空
请求对象不能为空 请求对象不能为空
请求方法不正确 请求方法不正确
请稍后重试
请联系管理员激活账号 请联系管理员激活账号
读取用户令牌出错 读取用户令牌出错
账号不能为空 账号不能为空
@ -111,7 +110,7 @@ XML注释文件不存在
部门可见 部门可见
部门名称不能为空 部门名称不能为空
配置文件初始化完毕 配置文件初始化完毕
钱包余额不足 钱包可用余额不足
键值不能为空 键值不能为空
键名称不能为空 键名称不能为空
随机延时结束时间不正确 随机延时结束时间不正确

View File

@ -0,0 +1,16 @@
[
{
"Enabled": true,
"Gender": 1,
"Id": 694360665923594,
"Name": "老王",
"Sort": 100,
},
{
"Enabled": true,
"Gender": 2,
"Id": 694360665923595,
"Name": "媳妇儿",
"Sort": 100,
}
]

View File

@ -1,5 +1,5 @@
[ [
// ------------------------------ 主控面板 ------------------------------ // ------------------------------ 主控面板 /home ------------------------------
{ {
"Component": "home", "Component": "home",
"Icon": "el-icon-house", "Icon": "el-icon-house",
@ -8,9 +8,9 @@
"Path": "/home", "Path": "/home",
"Sort": 999, "Sort": 999,
"Title": "主控面板", "Title": "主控面板",
"Type": 1 "Type": 1,
}, },
// ------------------------------ 权限管理 ------------------------------ // ------------------------------ 权限管理 /power ------------------------------
{ {
"Icon": "el-icon-setting", "Icon": "el-icon-setting",
"Id": 373837917724677, "Id": 373837917724677,
@ -18,96 +18,96 @@
"Path": "/power", "Path": "/power",
"Sort": 100, "Sort": 100,
"Title": "权限管理", "Title": "权限管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/user", "Component": "sys/power/user",
"Icon": "el-icon-user", "Icon": "el-icon-user",
"Id": 373837957840901, "Id": 373837957840901,
"Name": "sys/user", "Name": "sys/power/user",
"ParentId": 373837917724677, "ParentId": 373837917724677,
"Path": "/power/user", "Path": "/power/user",
"Sort": 100, "Sort": 100,
"Title": "用户管理", "Title": "用户管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/role", "Component": "sys/power/role",
"Icon": "sc-icon-role", "Icon": "sc-icon-role",
"Id": 373838018527237, "Id": 373838018527237,
"Name": "sys/role", "Name": "sys/power/role",
"ParentId": 373837917724677, "ParentId": 373837917724677,
"Path": "/power/role", "Path": "/power/role",
"Sort": 99, "Sort": 99,
"Title": "角色管理", "Title": "角色管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/dept", "Component": "sys/power/dept",
"Icon": "sc-icon-dept", "Icon": "sc-icon-dept",
"Id": 373838045605893, "Id": 373838045605893,
"Name": "sys/dept", "Name": "sys/power/dept",
"ParentId": 373837917724677, "ParentId": 373837917724677,
"Path": "/power/dept", "Path": "/power/dept",
"Sort": 98, "Sort": 98,
"Title": "部门管理", "Title": "部门管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/menu", "Component": "sys/power/menu",
"Icon": "el-icon-fold", "Icon": "el-icon-fold",
"Id": 373838070898693, "Id": 373838070898693,
"Name": "sys/menu", "Name": "sys/power/menu",
"ParentId": 373837917724677, "ParentId": 373837917724677,
"Path": "/power/menu", "Path": "/power/menu",
"Sort": 97, "Sort": 97,
"Title": "菜单管理", "Title": "菜单管理",
"Type": 1 "Type": 1,
}, },
// ------------------------------ 财务管理 ------------------------------ // ------------------------------ 财务管理 /finance ------------------------------
{ {
"Icon": "el-icon-money", "Icon": "el-icon-money",
"Id": 690906994118665, "Id": 690906994118665,
"Name": "finance", "Name": "sys/finance",
"Path": "/finance", "Path": "/finance",
"Sort": 99, "Sort": 99,
"Title": "财务管理", "Title": "财务管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/wallet", "Component": "sys/finance/wallet",
"Icon": "el-icon-wallet", "Icon": "el-icon-wallet",
"Id": 690907673255942, "Id": 690907673255942,
"Name": "sys/wallet", "Name": "sys/finance/wallet",
"ParentId": 690906994118665, "ParentId": 690906994118665,
"Path": "/finance/wallet", "Path": "/finance/wallet",
"Sort": 100, "Sort": 100,
"Title": "钱包管理", "Title": "钱包管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/trade", "Component": "sys/finance/trade",
"Icon": "el-icon-calendar", "Icon": "el-icon-calendar",
"Id": 690907673255943, "Id": 690907673255943,
"Name": "sys/trade", "Name": "sys/finance/trade",
"ParentId": 690906994118665, "ParentId": 690906994118665,
"Path": "/finance/trade", "Path": "/finance/trade",
"Sort": 99, "Sort": 99,
"Title": "交易流水", "Title": "交易流水",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/order", "Component": "sys/finance/order",
"Icon": "el-icon-shopping-cart", "Icon": "el-icon-shopping-cart",
"Id": 690907673255944, "Id": 690907673255944,
"Name": "sys/order", "Name": "sys/finance/order",
"ParentId": 690906994118665, "ParentId": 690906994118665,
"Path": "/finance/order", "Path": "/finance/order",
"Sort": 98, "Sort": 98,
"Title": "充值订单", "Title": "自助充值",
"Type": 1 "Type": 1,
}, },
// ------------------------------ 营销管理 ------------------------------ // ------------------------------ 营销管理 /market ------------------------------
{ {
"Icon": "el-icon-share", "Icon": "el-icon-share",
"Id": 692575802241032, "Id": 692575802241032,
@ -115,67 +115,67 @@
"Path": "/market", "Path": "/market",
"Sort": 98, "Sort": 98,
"Title": "营销管理", "Title": "营销管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/invite", "Component": "sys/market/invite",
"Icon": "el-icon-connection", "Icon": "el-icon-connection",
"Id": 692575802245126, "Id": 692575802245126,
"Name": "sys/invite", "Name": "sys/market/invite",
"ParentId": 692575802241032, "ParentId": 692575802241032,
"Path": "/market/invite", "Path": "/market/invite",
"Sort": 100, "Sort": 100,
"Title": "邀请管理", "Title": "粉丝管理",
"Type": 1 "Type": 1,
}, },
// ------------------------------ 系统管理 ------------------------------ // ------------------------------ 系统管理 /system ------------------------------
{ {
"Icon": "sc-icon-app", "Icon": "sc-icon-app",
"Id": 485278637670422, "Id": 485278637670422,
"Name": "sys", "Name": "system",
"Path": "/sys", "Path": "/system",
"Sort": 98, "Sort": 98,
"Title": "系统管理", "Title": "系统管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/config", "Component": "sys/system/config",
"Icon": "el-icon-set-up", "Icon": "el-icon-set-up",
"Id": 380415005847557, "Id": 380415005847557,
"Name": "sys/config", "Name": "sys/system/config",
"ParentId": 485278637670422, "ParentId": 485278637670422,
"Path": "/system/config", "Path": "/system/config",
"Sort": 100, "Sort": 100,
"Title": "系统设置", "Title": "系统设置",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/job", "Component": "sys/system/job",
"Icon": "sc-icon-scheduled-job", "Icon": "sc-icon-scheduled-job",
"Id": 510067557638158, "Id": 510067557638158,
"Name": "sys/job", "Name": "sys/system/job",
"ParentId": 485278637670422, "ParentId": 485278637670422,
"Path": "/system/job", "Path": "/system/job",
"Sort": 99, "Sort": 99,
"Title": "计划作业", "Title": "计划作业",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/dic", "Component": "sys/system/dic",
"Icon": "sc-icon-dic", "Icon": "sc-icon-dic",
"Id": 375315654221829, "Id": 375315654221829,
"Name": "sys/dic", "Name": "sys/system/dic",
"ParentId": 485278637670422, "ParentId": 485278637670422,
"Path": "/system/dic", "Path": "/system/dic",
"Sort": 98, "Sort": 98,
"Title": "字典管理", "Title": "字典管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/msg", "Component": "sys/system/msg",
"Icon": "el-icon-message", "Icon": "el-icon-message",
"Id": 482779610341392, "Id": 482779610341392,
"Name": "sys/msg", "Name": "sys/system/msg",
"ParentId": 485278637670422, "ParentId": 485278637670422,
"Path": "/system/msg", "Path": "/system/msg",
"Sort": 97, "Sort": 97,
@ -183,28 +183,28 @@
"Type": 1, "Type": 1,
}, },
{ {
"Component": "sys/api", "Component": "sys/system/api",
"Icon": "sc-icon-api", "Icon": "sc-icon-api",
"Id": 397880678895621, "Id": 397880678895621,
"Name": "sys/api", "Name": "sys/system/api",
"ParentId": 485278637670422, "ParentId": 485278637670422,
"Path": "/system/api", "Path": "/system/api",
"Sort": 96, "Sort": 96,
"Title": "接口管理", "Title": "接口管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/cache", "Component": "sys/system/cache",
"Icon": "sc-icon-memory", "Icon": "sc-icon-memory",
"Id": 374911555702789, "Id": 374911555702789,
"Name": "sys/cache", "Name": "sys/system/cache",
"ParentId": 485278637670422, "ParentId": 485278637670422,
"Path": "/system/cache", "Path": "/system/cache",
"Sort": 95, "Sort": 95,
"Title": "缓存管理", "Title": "缓存管理",
"Type": 1 "Type": 1,
}, },
// ------------------------------ 档案管理 ------------------------------ // ------------------------------ 档案管理 /archive ------------------------------
{ {
"Icon": "sc-icon-archive", "Icon": "sc-icon-archive",
"Id": 616214756757512, "Id": 616214756757512,
@ -212,20 +212,20 @@
"Path": "/archive", "Path": "/archive",
"Sort": 97, "Sort": 97,
"Title": "档案管理", "Title": "档案管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/doc", "Component": "sys/archive/doc",
"Icon": "el-icon-document", "Icon": "el-icon-document",
"Id": 616214756757516, "Id": 616214756757516,
"Name": "archive/doc", "Name": "sys/archive/doc",
"ParentId": 616214756757512, "ParentId": 616214756757512,
"Path": "/archive/doc", "Path": "/archive/doc",
"Sort": 100, "Sort": 100,
"Title": "文档管理", "Title": "文档管理",
"Type": 1 "Type": 1,
}, },
// ------------------------------ 日志管理 ------------------------------ // ------------------------------ 日志管理 /log ------------------------------
{ {
"Icon": "el-icon-tickets", "Icon": "el-icon-tickets",
"Id": 374792687640581, "Id": 374792687640581,
@ -233,7 +233,7 @@
"Path": "/log", "Path": "/log",
"Sort": 96, "Sort": 96,
"Title": "日志管理", "Title": "日志管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "sys/log/operation", "Component": "sys/log/operation",
@ -257,7 +257,7 @@
"Title": "登录日志", "Title": "登录日志",
"Type": 1, "Type": 1,
}, },
// ------------------------------ 开发管理 ------------------------------ // ------------------------------ 开发管理 /dev ------------------------------
{ {
"Icon": "sc-icon-code", "Icon": "sc-icon-code",
"Id": 373838105399301, "Id": 373838105399301,
@ -265,18 +265,29 @@
"Path": "/dev", "Path": "/dev",
"Sort": 95, "Sort": 95,
"Title": "开发管理", "Title": "开发管理",
"Type": 1 "Type": 1,
}, },
{ {
"Component": "dev/code", "Component": "sys/dev/code",
"Icon": "sc-icon-code2", "Icon": "sc-icon-code2",
"Id": 373838147022853, "Id": 373838147022853,
"Name": "dev/code", "Name": "sys/dev/code",
"ParentId": 373838105399301, "ParentId": 373838105399301,
"Path": "/dev/code", "Path": "/dev/code",
"Sort": 100, "Sort": 100,
"Title": "代码生成", "Title": "代码生成",
"Type": 1 "Type": 1,
},
{
"Component": "sys/dev/template",
"Icon": "sc-icon-template",
"Id": 694076641718288,
"Name": "sys/dev/template",
"ParentId": 373838105399301,
"Path": "/dev/template",
"Sort": 99,
"Title": "页面模板",
"Type": 1,
}, },
{ {
"Id": 482777529417739, "Id": 482777529417739,
@ -284,7 +295,7 @@
"Icon": "el-icon-eleme-filled", "Icon": "el-icon-eleme-filled",
"Name": "dev/element", "Name": "dev/element",
"Path": "https://element-plus.org/zh-CN/component/overview.html", "Path": "https://element-plus.org/zh-CN/component/overview.html",
"Sort": 99, "Sort": 98,
"Title": "Element", "Title": "Element",
"Type": 3, "Type": 3,
}, },
@ -294,7 +305,7 @@
"Icon": "sc-icon-free-sql", "Icon": "sc-icon-free-sql",
"Name": "dev/freesql", "Name": "dev/freesql",
"Path": "https://freesql.net/guide", "Path": "https://freesql.net/guide",
"Sort": 99, "Sort": 97,
"Title": "FreeSql", "Title": "FreeSql",
"Type": 3, "Type": 3,
} }

View File

@ -106,5 +106,17 @@
{ {
"ApiId": "api/sys/user.invite/query", "ApiId": "api/sys/user.invite/query",
"RoleId": 371729946431493, "RoleId": 371729946431493,
} },
{
"ApiId": "api/sys/wallet.frozen/get",
"RoleId": 371729946431493,
},
{
"ApiId": "api/sys/wallet.frozen/paged.query",
"RoleId": 371729946431493,
},
{
"ApiId": "api/sys/wallet.frozen/count.by",
"RoleId": 371729946431493,
},
] ]

View File

@ -19,11 +19,11 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.13.1"> <PackageReference Include="Roslynator.Analyzers" Version="4.14.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.12.0.118525"> <PackageReference Include="SonarAnalyzer.CSharp" Version="10.15.0.120848">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

View File

@ -1,7 +1,7 @@
{ {
"version": "2.4.0", "version": "2.4.0",
"devDependencies": { "devDependencies": {
"cz-git": "^1.11.2", "cz-git": "^1.12.0",
"commitizen": "^4.3.1", "commitizen": "^4.3.1",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"standard-version": "^9.5.0" "standard-version": "^9.5.0"
@ -11,4 +11,4 @@
"path": "node_modules/cz-git" "path": "node_modules/cz-git"
} }
} }
} }

View File

@ -0,0 +1,24 @@
using NetAdmin.Domain;
using NetAdmin.Domain.Dto.Dependency;
namespace NetAdmin.Application.Extensions;
/// <summary>
/// FreeSql Select 扩展方法
/// </summary>
public static class ISelectExtensions
{
/// <summary>
/// 附加其他过滤条件
/// </summary>
public static ISelect<T> AppendOtherFilters<T, TQuery>(this ISelect<T> me, QueryReq<TQuery> req)
where TQuery : DataAbstraction, new()
{
if (req.IgnoreOwner) {
me = me.DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_SELF, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT
, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILDREN, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_SON);
}
return me;
}
}

View File

@ -69,4 +69,9 @@ public interface ICrudModule<in TCreateReq, TCreateRsp, in TEditReq, TQueryReq,
/// 查询实体 /// 查询实体
/// </summary> /// </summary>
Task<IEnumerable<TQueryRsp>> QueryAsync(QueryReq<TQueryReq> req); Task<IEnumerable<TQueryRsp>> QueryAsync(QueryReq<TQueryReq> req);
/// <summary>
/// 实体求和
/// </summary>
Task<decimal> SumAsync(QueryReq<TQueryReq> req);
} }

View File

@ -1,13 +0,0 @@
using NetAdmin.Domain.Dto.Dependency;
using NetAdmin.Domain.Dto.Tpl.Example;
namespace NetAdmin.Application.Modules.Tpl;
/// <summary>
/// 示例模块
/// </summary>
public interface IExampleModule : ICrudModule<CreateExampleReq, QueryExampleRsp // 创建类型
, EditExampleReq // 编辑类型
, QueryExampleReq, QueryExampleRsp // 查询类型
, DelReq // 删除类型
>;

View File

@ -62,6 +62,23 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false); return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
} }
/// <summary>
/// 唯一索引冲突处理
/// </summary>
protected static async Task OnUniqueIndexConflictAsync(Func<Task> actionTry, Func<Task> actionCatch = null)
{
try {
await actionTry().ConfigureAwait(false);
}
catch (Exception ex) when (ex.Message.Contains(Chars.FLG_DB_EXCEPTION_PRIMARY_KEY_CONFLICT) ||
ex.Message.Contains(Chars.FLG_DB_EXCEPTION_UNIQUE_CONSTRAINT_CONFLICT) ||
ex.Message.Contains(Chars.FLG_DB_EXCEPTION_IDX)) {
if (actionCatch != null) {
await actionCatch().ConfigureAwait(false);
}
}
}
/// <summary> /// <summary>
/// 更新实体 /// 更新实体
/// </summary> /// </summary>
@ -85,7 +102,8 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
whereExp ??= a => a.Id.Equals(newValue.Id); whereExp ??= a => a.Id.Equals(newValue.Id);
var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql); var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql);
if (disableGlobalDataFilter) { if (disableGlobalDataFilter) {
update = update.DisableGlobalFilter(nameof(Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA)); update = update.DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_SELF, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT
, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILDREN, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_SON);
} }
return update.ExecuteEffectsAsync(); return update.ExecuteEffectsAsync();
@ -106,8 +124,8 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
TEntity newValue // TEntity newValue //
, List<string> includeFields = null // , List<string> includeFields = null //
, List<string> excludeFields = null // , List<string> excludeFields = null //
, Expression<Func<TEntity, bool>> whereExp = null // , Expression<Func<TEntity, bool>> whereExp = null //
, string whereSql = null // , string whereSql = null //
, bool ignoreVersion = false) , bool ignoreVersion = false)
{ {
// 默认匹配主键 // 默认匹配主键

View File

@ -42,12 +42,7 @@ public abstract class ServiceBase : IScoped, IService
/// <summary> /// <summary>
/// 获取服务 /// 获取服务
/// </summary> /// </summary>
#pragma warning disable RCS1036 protected static T S<T>()
#pragma warning restore RCS1036
// ReSharper disable once MemberCanBeMadeStatic.Global
#pragma warning disable CA1822, S2325
protected T S<T>()
#pragma warning restore S2325, CA1822 #pragma warning restore S2325, CA1822
where T : class where T : class
{ {

View File

@ -1,8 +0,0 @@
using NetAdmin.Application.Modules.Tpl;
namespace NetAdmin.Application.Services.Tpl.Dependency;
/// <summary>
/// 示例服务
/// </summary>
public interface IExampleService : IService, IExampleModule;

View File

@ -1,133 +0,0 @@
using NetAdmin.Application.Repositories;
using NetAdmin.Application.Services.Tpl.Dependency;
using NetAdmin.Domain.DbMaps.Tpl;
using NetAdmin.Domain.Dto.Dependency;
using NetAdmin.Domain.Dto.Tpl.Example;
using NetAdmin.Domain.Extensions;
namespace NetAdmin.Application.Services.Tpl;
/// <inheritdoc cref="IExampleService" />
public sealed class ExampleService(BasicRepository<Tpl_Example, long> rpo) //
: RepositoryService<Tpl_Example, long, IExampleService>(rpo), IExampleService
{
/// <inheritdoc />
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
{
req.ThrowIfInvalid();
var ret = 0;
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var item in req.Items) {
ret += await DeleteAsync(item).ConfigureAwait(false);
}
return ret;
}
/// <inheritdoc />
public Task<long> CountAsync(QueryReq<QueryExampleReq> req)
{
req.ThrowIfInvalid();
return QueryInternal(req).WithNoLockNoWait().CountAsync();
}
/// <inheritdoc />
public async Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryExampleReq> req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(req with { Order = Orders.None })
.WithNoLockNoWait()
.GroupBy(req.GetToListExp<Tpl_Example>())
.ToDictionaryAsync(a => a.Count())
.ConfigureAwait(false);
return ret.Select(x => new KeyValuePair<IImmutableDictionary<string, string>, int>(
req.RequiredFields.ToImmutableDictionary(y => y, y => typeof(Tpl_Example).GetProperty(y)!.GetValue(x.Key)?.ToString())
, x.Value))
.Where(x => x.Key.Any(y => !y.Value.NullOrEmpty()))
.OrderByDescending(x => x.Value);
}
/// <inheritdoc />
public async Task<QueryExampleRsp> CreateAsync(CreateExampleReq req)
{
req.ThrowIfInvalid();
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
return ret.Adapt<QueryExampleRsp>();
}
/// <inheritdoc />
public Task<int> DeleteAsync(DelReq req)
{
req.ThrowIfInvalid();
return Rpo.DeleteAsync(a => a.Id == req.Id);
}
/// <inheritdoc />
public async Task<QueryExampleRsp> EditAsync(EditExampleReq req)
{
req.ThrowIfInvalid();
#if DBTYPE_SQLSERVER
return (await UpdateReturnListAsync(req).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryExampleRsp>();
#else
return await UpdateAsync(req).ConfigureAwait(false) > 0 ? await GetAsync(new QueryExampleReq { Id = req.Id }).ConfigureAwait(false) : null;
#endif
}
/// <inheritdoc />
public Task<IActionResult> ExportAsync(QueryReq<QueryExampleReq> req)
{
req.ThrowIfInvalid();
return ExportAsync<QueryExampleReq, QueryExampleRsp>(QueryInternal, req, Ln.);
}
/// <inheritdoc />
public async Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryExampleReq> { Filter = req, Order = Orders.None }).ToOneAsync().ConfigureAwait(false);
return ret.Adapt<QueryExampleRsp>();
}
/// <inheritdoc />
public async Task<PagedQueryRsp<QueryExampleRsp>> PagedQueryAsync(PagedQueryReq<QueryExampleReq> req)
{
req.ThrowIfInvalid();
var list = await QueryInternal(req)
.Page(req.Page, req.PageSize)
.WithNoLockNoWait()
.Count(out var total)
.ToListAsync(req)
.ConfigureAwait(false);
return new PagedQueryRsp<QueryExampleRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryExampleRsp>>());
}
/// <inheritdoc />
public async Task<IEnumerable<QueryExampleRsp>> QueryAsync(QueryReq<QueryExampleReq> req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(req).WithNoLockNoWait().Take(req.Count).ToListAsync(req).ConfigureAwait(false);
return ret.Adapt<IEnumerable<QueryExampleRsp>>();
}
private ISelect<Tpl_Example> QueryInternal(QueryReq<QueryExampleReq> req)
{
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
switch (req.Order) {
case Orders.None:
return ret;
case Orders.Random:
return ret.OrderByRandom();
}
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
ret = ret.OrderByDescending(a => a.Id);
}
return ret;
}
}

View File

@ -1,9 +0,0 @@
using NetAdmin.Application.Modules.Tpl;
using NetAdmin.Application.Services.Tpl.Dependency;
namespace NetAdmin.Cache.Tpl.Dependency;
/// <summary>
/// 示例缓存
/// </summary>
public interface IExampleCache : ICache<IDistributedCache, IExampleService>, IExampleModule;

View File

@ -1,71 +0,0 @@
using NetAdmin.Application.Services.Tpl.Dependency;
using NetAdmin.Cache.Tpl.Dependency;
using NetAdmin.Domain.Dto.Dependency;
using NetAdmin.Domain.Dto.Tpl.Example;
namespace NetAdmin.Cache.Tpl;
/// <inheritdoc cref="IExampleCache" />
public sealed class ExampleCache(IDistributedCache cache, IExampleService service)
: DistributedCache<IExampleService>(cache, service), IScoped, IExampleCache
{
/// <inheritdoc />
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
{
return Service.BulkDeleteAsync(req);
}
/// <inheritdoc />
public Task<long> CountAsync(QueryReq<QueryExampleReq> req)
{
return Service.CountAsync(req);
}
/// <inheritdoc />
public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryExampleReq> req)
{
return Service.CountByAsync(req);
}
/// <inheritdoc />
public Task<QueryExampleRsp> CreateAsync(CreateExampleReq req)
{
return Service.CreateAsync(req);
}
/// <inheritdoc />
public Task<int> DeleteAsync(DelReq req)
{
return Service.DeleteAsync(req);
}
/// <inheritdoc />
public Task<QueryExampleRsp> EditAsync(EditExampleReq req)
{
return Service.EditAsync(req);
}
/// <inheritdoc />
public Task<IActionResult> ExportAsync(QueryReq<QueryExampleReq> req)
{
return Service.ExportAsync(req);
}
/// <inheritdoc />
public Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
{
return Service.GetAsync(req);
}
/// <inheritdoc />
public Task<PagedQueryRsp<QueryExampleRsp>> PagedQueryAsync(PagedQueryReq<QueryExampleReq> req)
{
return Service.PagedQueryAsync(req);
}
/// <inheritdoc />
public Task<IEnumerable<QueryExampleRsp>> QueryAsync(QueryReq<QueryExampleReq> req)
{
return Service.QueryAsync(req);
}
}

View File

@ -19,7 +19,7 @@ public sealed class UserNameAttribute : RegexAttribute
public override bool IsValid(object value) public override bool IsValid(object value)
{ {
if (!base.IsValid(value)) { if (!base.IsValid(value)) {
ErrorMessageResourceName = nameof(Ln.4); ErrorMessageResourceName = nameof(Ln.);
return false; return false;
} }

View File

@ -3,14 +3,23 @@ namespace NetAdmin.Domain;
/// <summary> /// <summary>
/// 数据基类 /// 数据基类
/// </summary> /// </summary>
public abstract record DataAbstraction public abstract record DataAbstraction : IValidatableObject
{ {
/// <summary>
/// 是否已验证
/// </summary>
protected bool HasValidated { get; set; }
/// <summary> /// <summary>
/// 如果数据校验失败,抛出异常 /// 如果数据校验失败,抛出异常
/// </summary> /// </summary>
/// <exception cref="NetAdminValidateException">NetAdminValidateException</exception> /// <exception cref="NetAdminValidateException">NetAdminValidateException</exception>
public void ThrowIfInvalid() public void ThrowIfInvalid()
{ {
if (HasValidated) {
return;
}
var validationResult = this.TryValidate(); var validationResult = this.TryValidate();
if (!validationResult.IsValid) { if (!validationResult.IsValid) {
throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( // throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( //
@ -45,4 +54,19 @@ public abstract record DataAbstraction
property.SetValue(this, s); property.SetValue(this, s);
} }
} }
/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
HasValidated = true;
return ValidateInternal(validationContext);
}
/// <summary>
/// 内部验证
/// </summary>
protected virtual IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
{
yield return ValidationResult.Success;
}
} }

View File

@ -8,5 +8,5 @@ public interface IFieldSummary
/// <summary> /// <summary>
/// 备注 /// 备注
/// </summary> /// </summary>
string Summary { get; init; } string Summary { get; set; }
} }

View File

@ -79,5 +79,5 @@ public record Sys_Api : ImmutableEntity<string>, IFieldSummary
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
} }

View File

@ -0,0 +1,89 @@
namespace NetAdmin.Domain.DbMaps.Sys;
/// <summary>
/// 代码模板表
/// </summary>
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_CodeTemplate))]
public record Sys_CodeTemplate : VersionEntity, IFieldSort, IFieldSummary, IFieldEnabled, IFieldOwner
{
/// <summary>
/// 是否启用
/// </summary>
/// <example>true</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual bool Enabled { get; init; }
/// <summary>
/// 性别
/// </summary>
/// <example>Male</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual Genders? Gender { get; init; }
/// <summary>
/// 唯一编码
/// </summary>
/// <example>123456</example>
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
[CsvIgnore]
[JsonIgnore]
[Snowflake]
public override long Id { get; init; }
/// <summary>
/// 名称
/// </summary>
/// <example>老王</example>
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
[CsvIgnore]
[JsonIgnore]
public virtual string Name { get; init; }
/// <summary>
/// 归属用户
/// </summary>
[CsvIgnore]
[JsonIgnore]
[Navigate(nameof(OwnerId))]
public Sys_User Owner { get; init; }
/// <summary>
/// 归属部门编号
/// </summary>
/// <example>370942943322181</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long? OwnerDeptId { get; init; }
/// <summary>
/// 归属用户编号
/// </summary>
/// <example>370942943322181</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long? OwnerId { get; init; }
/// <summary>
/// 排序值,越大越前
/// </summary>
/// <example>100</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long Sort { get; init; }
/// <summary>
/// 备注
/// </summary>
/// <example>备注文字</example>
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore]
[JsonIgnore]
public virtual string Summary { get; set; }
}

View File

@ -68,5 +68,5 @@ public record Sys_Dept : VersionEntity, IFieldEnabled, IFieldSummary, IFieldSort
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
} }

View File

@ -45,7 +45,7 @@ public record Sys_DicContent : VersionEntity, IFieldEnabled, IFieldSummary
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
/// <summary> /// <summary>
/// 键值 /// 键值

View File

@ -134,7 +134,7 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
/// <summary> /// <summary>
/// 执行用户 /// 执行用户

View File

@ -104,7 +104,7 @@ public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
/// <summary> /// <summary>
/// 此角色下的用户集合 /// 此角色下的用户集合

View File

@ -62,7 +62,7 @@ public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
/// <summary> /// <summary>
/// 消息主题 /// 消息主题

View File

@ -121,7 +121,7 @@ public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
/// <summary> /// <summary>
/// 授权验证Token全局唯一可以随时重置强制下线 /// 授权验证Token全局唯一可以随时重置强制下线

View File

@ -46,6 +46,14 @@ public record Sys_UserInvite : VersionEntity, IFieldOwner
[JsonIgnore] [JsonIgnore]
public virtual long? OwnerId { get; init; } public virtual long? OwnerId { get; init; }
/// <summary>
/// 允许自助充值
/// </summary>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual bool SelfRechargeAllowed { get; init; }
/// <summary> /// <summary>
/// 用户 /// 用户
/// </summary> /// </summary>

View File

@ -46,14 +46,6 @@ public record Sys_UserWallet : LiteVersionEntity, IFieldOwner
[JsonIgnore] [JsonIgnore]
public virtual long? OwnerId { get; init; } public virtual long? OwnerId { get; init; }
/// <summary>
/// 总余额
/// </summary>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long TotalBalance { get; init; }
/// <summary> /// <summary>
/// 总支出 /// 总支出
/// </summary> /// </summary>

View File

@ -0,0 +1,99 @@
using NetAdmin.Domain.Enums.Sys;
namespace NetAdmin.Domain.DbMaps.Sys;
/// <summary>
/// 钱包冻结表
/// </summary>
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_WalletFrozen))]
public record Sys_WalletFrozen : LiteVersionEntity, IFieldOwner, IFieldSummary
{
/// <summary>
/// 冻结金额
/// </summary>
/// <example>100</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long Amount { get; init; }
/// <summary>
/// 冻结前数值
/// </summary>
/// <example>100</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long FrozenBalanceBefore { get; init; }
/// <summary>
/// 冻结编号
/// </summary>
/// <example>123456</example>
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
[CsvIgnore]
[JsonIgnore]
[Snowflake]
public override long Id { get; init; }
/// <summary>
/// 归属用户
/// </summary>
[CsvIgnore]
[JsonIgnore]
[Navigate(nameof(OwnerId))]
public Sys_User Owner { get; init; }
/// <summary>
/// 归属部门编号
/// </summary>
/// <example>370942943322181</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long? OwnerDeptId { get; init; }
/// <summary>
/// 归属用户编号
/// </summary>
/// <example>370942943322181</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual long? OwnerId { get; init; }
/// <summary>
/// 冻结原因
/// </summary>
/// <example>Trade</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual WalletFrozenReasons Reason { get; init; }
/// <summary>
/// 冻结状态
/// </summary>
/// <example>Frozen</example>
[Column]
[CsvIgnore]
[JsonIgnore]
public virtual WalletFrozenStatues Status { get; init; }
/// <summary>
/// 备注
/// </summary>
/// <example>备注文字</example>
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore]
[JsonIgnore]
public virtual string Summary { get; set; }
/// <summary>
/// 钱包
/// </summary>
[CsvIgnore]
[JsonIgnore]
[Navigate(nameof(OwnerId))]
public Sys_UserWallet Wallet { get; init; }
}

View File

@ -12,7 +12,7 @@ public record Sys_WalletTrade : ImmutableEntity, IFieldOwner, IFieldSummary
[Column] [Column]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual long Amount { get; init; } public virtual long Amount { get; set; }
/// <summary> /// <summary>
/// 交易前余额 /// 交易前余额
@ -60,7 +60,7 @@ public record Sys_WalletTrade : ImmutableEntity, IFieldOwner, IFieldSummary
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public virtual string Summary { get; init; } public virtual string Summary { get; set; }
/// <summary> /// <summary>
/// 交易方向 /// 交易方向

View File

@ -1,7 +0,0 @@
namespace NetAdmin.Domain.DbMaps.Tpl;
/// <summary>
/// 示例表
/// </summary>
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Tpl_Example))]
public record Tpl_Example : VersionEntity;

View File

@ -0,0 +1,22 @@
namespace NetAdmin.Domain.Dto.Dependency;
/// <summary>
/// 工作批请求
/// </summary>
public record JobReq : DataAbstraction
{
/// <summary>
/// 处理数量
/// </summary>
public int? Count { get; init; }
/// <summary>
/// n秒以前
/// </summary>
public int? SecondsAgo { get; init; }
/// <summary>
/// 直到n秒前
/// </summary>
public int? UntilSecondsAgo { get; init; }
}

View File

@ -22,6 +22,12 @@ public record QueryReq<T> : DataAbstraction
/// </summary> /// </summary>
public T Filter { get; init; } public T Filter { get; init; }
/// <summary>
/// 忽略归属
/// </summary>
[JsonIgnore]
public bool IgnoreOwner { get; init; }
/// <summary> /// <summary>
/// 查询关键字 /// 查询关键字
/// </summary> /// </summary>
@ -42,6 +48,23 @@ public record QueryReq<T> : DataAbstraction
/// </summary> /// </summary>
public string[] RequiredFields { get; init; } public string[] RequiredFields { get; init; }
/// <summary>
/// 求和表达式
/// </summary>
public Expression<Func<TEntity, long>> GetSumExp<TEntity>()
{
if (RequiredFields.NullOrEmpty()) {
return null;
}
var field = RequiredFields[0];
var leftParameter = Expression.Parameter(typeof(TEntity), "a");
var prop = typeof(TEntity).GetRecursiveProperty(field);
return prop == null || prop.GetCustomAttribute<DangerFieldAttribute>() != null
? null
: Expression.Lambda<Func<TEntity, long>>(CreatePropertyExpression(leftParameter, field), leftParameter);
}
/// <summary> /// <summary>
/// 列表表达式 /// 列表表达式
/// </summary> /// </summary>
@ -52,21 +75,30 @@ public record QueryReq<T> : DataAbstraction
} }
var expParameter = Expression.Parameter(typeof(TEntity), "a"); var expParameter = Expression.Parameter(typeof(TEntity), "a");
var bindings = new List<MemberBinding>(); var bindings = new List<(PropertyInfo, MemberInitExpression)>();
// ReSharper disable once LoopCanBeConvertedToQuery // ReSharper disable once LoopCanBeConvertedToQuery
foreach (var field in RequiredFields) { foreach (var field in RequiredFields) {
var prop = typeof(TEntity).GetProperty(field); var prop = typeof(TEntity).GetRecursiveProperty(field);
if (prop == null || prop.GetCustomAttribute<DangerFieldAttribute>() != null) { if (prop == null || prop.GetCustomAttribute<DangerFieldAttribute>() != null) {
continue; continue;
} }
var propExp = Expression.Property(expParameter, prop); var parentPath = field[..field.LastIndexOf('.').Is(-1, field.Length)];
var binding = Expression.Bind(prop, propExp); var parentProperty = typeof(TEntity).GetRecursiveProperty(parentPath);
bindings.Add(binding); var propExp = Expression.Property(Expression.Parameter(prop.DeclaringType!, parentPath), prop);
bindings.Add((parentProperty, Expression.MemberInit(Expression.New(prop.DeclaringType), Expression.Bind(prop, propExp))));
} }
var expBody = Expression.MemberInit(Expression.New(typeof(TEntity)), bindings); var expBody = Expression.MemberInit( //
Expression.New(typeof(TEntity))
, bindings.SelectMany(x => x.Item1.PropertyType == x.Item2.Type ? [Expression.Bind(x.Item1, x.Item2)] : x.Item2.Bindings.ToArray()));
return Expression.Lambda<Func<TEntity, TEntity>>(expBody, expParameter); return Expression.Lambda<Func<TEntity, TEntity>>(expBody, expParameter);
} }
private static Expression CreatePropertyExpression(ParameterExpression param, string propertyPath)
{
return propertyPath.Split('.').Aggregate<string, Expression>(param, Expression.PropertyOrField);
}
} }

View File

@ -31,5 +31,5 @@ public sealed record ExportApiRsp : QueryApiRsp
[CsvIndex(3)] [CsvIndex(3)]
[CsvIgnore(false)] [CsvIgnore(false)]
[CsvName(nameof(Ln.接口描述))] [CsvName(nameof(Ln.接口描述))]
public override string Summary { get; init; } public override string Summary { get; set; }
} }

View File

@ -33,5 +33,5 @@ public record QueryApiRsp : Sys_Api
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
} }

View File

@ -0,0 +1,30 @@
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
/// <summary>
/// 请求:创建代码模板
/// </summary>
public record CreateCodeTemplateReq : Sys_CodeTemplate
{
/// <inheritdoc cref="IFieldEnabled.Enabled" />
public override bool Enabled { get; init; } = true;
/// <inheritdoc cref="Sys_CodeTemplate.Gender" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override Genders? Gender { get; init; }
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; }
/// <inheritdoc cref="Sys_CodeTemplate.Name" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Name { get; init; }
/// <inheritdoc cref="IFieldSort.Sort" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Sort { get; init; }
/// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; set; }
}

View File

@ -0,0 +1,11 @@
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
/// <summary>
/// 请求:编辑代码模板
/// </summary>
public sealed record EditCodeTemplateReq : CreateCodeTemplateReq
{
/// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; }
}

View File

@ -0,0 +1,11 @@
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
/// <summary>
/// 请求:查询代码模板
/// </summary>
public sealed record QueryCodeTemplateReq : Sys_CodeTemplate
{
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; }
}

View File

@ -0,0 +1,72 @@
using NetAdmin.Domain.Dto.Sys.User;
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
/// <summary>
/// 响应:查询代码模板
/// </summary>
public record QueryCodeTemplateRsp : Sys_CodeTemplate
{
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override DateTime CreatedTime { get; init; }
/// <inheritdoc cref="IFieldCreatedUser.CreatedUserId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? CreatedUserId { get; init; }
/// <inheritdoc cref="IFieldCreatedUser.CreatedUserName" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string CreatedUserName { get; init; }
/// <inheritdoc cref="IFieldEnabled.Enabled" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override bool Enabled { get; init; }
/// <inheritdoc cref="Sys_CodeTemplate.Gender" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override Genders? Gender { get; init; }
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; }
/// <inheritdoc cref="IFieldModifiedTime.ModifiedTime" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override DateTime? ModifiedTime { get; init; }
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? ModifiedUserId { get; init; }
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserName" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string ModifiedUserName { get; init; }
/// <inheritdoc cref="Sys_CodeTemplate.Name" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Name { get; init; }
/// <inheritdoc cref="Sys_CodeTemplate.Owner" />
public new virtual QueryUserRsp Owner { get; init; }
/// <inheritdoc cref="IFieldOwner.OwnerDeptId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? OwnerDeptId { get; init; }
/// <inheritdoc cref="IFieldOwner.OwnerId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? OwnerId { get; init; }
/// <inheritdoc cref="IFieldSort.Sort" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Sort { get; init; }
/// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; set; }
/// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; }
}

View File

@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.DepositOrder;
/// <summary> /// <summary>
/// 请求:创建充值订单 /// 请求:创建充值订单
/// </summary> /// </summary>
public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject public record CreateDepositOrderReq : Sys_DepositOrder
{ {
/// <inheritdoc cref="Sys_DepositOrder.ActualPayAmount" /> /// <inheritdoc cref="Sys_DepositOrder.ActualPayAmount" />
public override long ActualPayAmount { get; init; } public override long ActualPayAmount { get; init; }
@ -13,7 +13,7 @@ public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject
/// <inheritdoc cref="Sys_DepositOrder.DepositPoint" /> /// <inheritdoc cref="Sys_DepositOrder.DepositPoint" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
[Range(100, long.MaxValue)] [Range(100, int.MaxValue)]
public override long DepositPoint { get; init; } public override long DepositPoint { get; init; }
/// <inheritdoc cref="Sys_DepositOrder.PaymentMode" /> /// <inheritdoc cref="Sys_DepositOrder.PaymentMode" />
@ -25,7 +25,7 @@ public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject
public override int ToPointRate { get; init; } public override int ToPointRate { get; init; }
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
{ {
if (PaymentMode != PaymentModes.USDT) { if (PaymentMode != PaymentModes.USDT) {
yield return new ValidationResult(Ln., [nameof(PaymentMode)]); yield return new ValidationResult(Ln., [nameof(PaymentMode)]);

View File

@ -1,12 +0,0 @@
namespace NetAdmin.Domain.Dto.Sys.DepositOrder;
/// <summary>
/// 请求:到账确认
/// </summary>
public record ReceivedConfirmationReq : DataAbstraction
{
/// <summary>
/// 读取前n条记录
/// </summary>
public int ReadRecordCount { get; init; }
}

View File

@ -5,9 +5,8 @@ namespace NetAdmin.Domain.Dto.Sys.Dept;
/// </summary> /// </summary>
public record CreateDeptReq : Sys_Dept public record CreateDeptReq : Sys_Dept
{ {
/// <inheritdoc cref="IFieldEnabled.Enabled" /> /// <inheritdoc />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] public override bool Enabled { get; init; } = true;
public override bool Enabled { get; init; }
/// <inheritdoc cref="Sys_Dept.Name" /> /// <inheritdoc cref="Sys_Dept.Name" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
@ -24,5 +23,5 @@ public record CreateDeptReq : Sys_Dept
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
} }

View File

@ -43,5 +43,5 @@ public sealed record ExportDeptRsp : QueryDeptRsp
[CsvIndex(3)] [CsvIndex(3)]
[CsvIgnore(false)] [CsvIgnore(false)]
[CsvName(nameof(Ln.备注))] [CsvName(nameof(Ln.备注))]
public override string Summary { get; init; } public override string Summary { get; set; }
} }

View File

@ -34,7 +34,7 @@ public record QueryDeptRsp : Sys_Dept
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="IFieldVersion.Version" /> /// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]

View File

@ -0,0 +1,47 @@
namespace NetAdmin.Domain.Dto.Sys.Dev;
/// <summary>
/// 信息:字段项信息
/// </summary>
public sealed record FieldItemInfo : DataAbstraction
{
/// <summary>
/// 数据库字段类型
/// </summary>
public string DbType { get; init; }
/// <summary>
/// 代码模板
/// </summary>
public string Example { get; init; }
/// <summary>
/// 可空
/// </summary>
public bool IsNullable { get; init; }
/// <summary>
/// 是否主键
/// </summary>
public bool IsPrimary { get; set; }
/// <summary>
/// 值类型
/// </summary>
public bool IsStruct { get; init; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; init; }
/// <summary>
/// 备注
/// </summary>
public string Summary { get; set; }
/// <summary>
/// 类型
/// </summary>
public string Type { get; init; }
}

View File

@ -6,20 +6,32 @@ namespace NetAdmin.Domain.Dto.Sys.Dev;
public sealed record GenerateCsCodeReq : DataAbstraction public sealed record GenerateCsCodeReq : DataAbstraction
{ {
/// <summary> /// <summary>
/// 模块名称 /// 基类
/// </summary> /// </summary>
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.模块名称不能为空))] public string BaseClass { get; init; }
public string ModuleName { get; init; }
/// <summary> /// <summary>
/// 模块说明 /// 实体名称
/// </summary> /// </summary>
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.模块说明不能为空))] public string EntityName { get; init; }
public string ModuleRemark { get; init; }
/// <summary> /// <summary>
/// 模块类型 /// 字段列表
/// </summary> /// </summary>
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.模块类型不能为空))] public IReadOnlyCollection<FieldItemInfo> FieldList { get; init; }
public string Type { get; init; }
/// <summary>
/// 接口列表
/// </summary>
public string[] Interfaces { get; init; }
/// <summary>
/// 项目
/// </summary>
public string Project { get; init; }
/// <summary>
/// 描述
/// </summary>
public string Summary { get; set; }
} }

View File

@ -0,0 +1,13 @@
namespace NetAdmin.Domain.Dto.Sys.Dev;
/// <summary>
/// 请求:获取所有数据类型
/// </summary>
public sealed record GetDotnetDataTypesReq : DataAbstraction
{
/// <summary>
/// 开始匹配
/// </summary>
[Required]
public string StartWith { get; init; }
}

View File

@ -21,7 +21,7 @@ public record CreateDicContentReq : Sys_DicContent
/// <inheritdoc cref="Sys_DicContent.Summary" /> /// <inheritdoc cref="Sys_DicContent.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_DicContent.Value" /> /// <inheritdoc cref="Sys_DicContent.Value" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

View File

@ -27,7 +27,7 @@ public sealed record ExportDicContentRsp : QueryDicContentRsp
[CsvIndex(4)] [CsvIndex(4)]
[CsvIgnore(false)] [CsvIgnore(false)]
[CsvName(nameof(Ln.备注))] [CsvName(nameof(Ln.备注))]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc /> /// <inheritdoc />
[CsvIndex(1)] [CsvIndex(1)]

View File

@ -23,7 +23,7 @@ public record QueryDicContentRsp : Sys_DicContent
/// <inheritdoc cref="Sys_DicContent.Summary" /> /// <inheritdoc cref="Sys_DicContent.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_DicContent.Value" /> /// <inheritdoc cref="Sys_DicContent.Value" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

View File

@ -58,7 +58,7 @@ public record CreateJobReq : Sys_Job
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_Job.UserId" /> /// <inheritdoc cref="Sys_Job.UserId" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]

View File

@ -112,7 +112,7 @@ public record QueryJobRsp : Sys_Job
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_Job.User" /> /// <inheritdoc cref="Sys_Job.User" />
public new virtual QueryUserRsp User { get; init; } public new virtual QueryUserRsp User { get; init; }

View File

@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Sys.Role;
/// <summary> /// <summary>
/// 请求:创建角色 /// 请求:创建角色
/// </summary> /// </summary>
public record CreateRoleReq : Sys_Role, IValidatableObject public record CreateRoleReq : Sys_Role
{ {
/// <summary> /// <summary>
/// 角色-接口映射 /// 角色-接口映射
@ -55,10 +55,10 @@ public record CreateRoleReq : Sys_Role, IValidatableObject
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
{ {
if (validationContext.MemberName != null) { if (validationContext.MemberName != null) {
DashboardLayout = JsonSerializer.Serialize(JsonDocument.Parse(DashboardLayout)); DashboardLayout = JsonSerializer.Serialize(JsonDocument.Parse(DashboardLayout));

View File

@ -63,7 +63,7 @@ public record QueryRoleRsp : Sys_Role
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="IFieldVersion.Version" /> /// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]

View File

@ -46,7 +46,7 @@ public sealed record ExportSiteMsgRsp : QuerySiteMsgRsp
[CsvIndex(4)] [CsvIndex(4)]
[CsvIgnore(false)] [CsvIgnore(false)]
[CsvName(nameof(Ln.消息摘要))] [CsvName(nameof(Ln.消息摘要))]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc /> /// <inheritdoc />
[CsvIndex(3)] [CsvIndex(3)]

View File

@ -53,7 +53,7 @@ public record QuerySiteMsgRsp : Sys_SiteMsg
/// <inheritdoc cref="Sys_SiteMsg.Summary" /> /// <inheritdoc cref="Sys_SiteMsg.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_SiteMsg.Title" /> /// <inheritdoc cref="Sys_SiteMsg.Title" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

View File

@ -44,7 +44,7 @@ public abstract record CreateEditUserReq : Sys_User
/// <inheritdoc cref="Sys_User.Summary" /> /// <inheritdoc cref="Sys_User.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_User.UserName" /> /// <inheritdoc cref="Sys_User.UserName" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

View File

@ -6,7 +6,7 @@ namespace NetAdmin.Domain.Dto.Sys.User;
/// <summary> /// <summary>
/// 请求:创建用户 /// 请求:创建用户
/// </summary> /// </summary>
public sealed record CreateUserReq : CreateEditUserReq public record CreateUserReq : CreateEditUserReq
{ {
/// <inheritdoc /> /// <inheritdoc />
public override bool Enabled { get; init; } = true; public override bool Enabled { get; init; } = true;

View File

@ -1,5 +1,6 @@
using NetAdmin.Domain.Dto.Sys.Dept; using NetAdmin.Domain.Dto.Sys.Dept;
using NetAdmin.Domain.Dto.Sys.Role; using NetAdmin.Domain.Dto.Sys.Role;
using NetAdmin.Domain.Dto.Sys.UserInvite;
namespace NetAdmin.Domain.Dto.Sys.User; namespace NetAdmin.Domain.Dto.Sys.User;
@ -27,6 +28,11 @@ public record QueryUserRsp : Sys_User
/// <inheritdoc cref="Sys_User.Dept" /> /// <inheritdoc cref="Sys_User.Dept" />
public new virtual QueryDeptRsp Dept { get; init; } public new virtual QueryDeptRsp Dept { get; init; }
/// <summary>
/// 本部门以及子部门编号
/// </summary>
public IReadOnlyCollection<long?> DeptIds { get; init; }
/// <inheritdoc cref="Sys_User.Email" /> /// <inheritdoc cref="Sys_User.Email" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Email { get; init; } public override string Email { get; init; }
@ -39,6 +45,9 @@ public record QueryUserRsp : Sys_User
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; } public override long Id { get; init; }
/// <inheritdoc cref="Sys_User.Invite" />
public new virtual QueryUserInviteRsp Invite { get; init; }
/// <inheritdoc cref="Sys_User.InviteCode" /> /// <inheritdoc cref="Sys_User.InviteCode" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string InviteCode { get; init; } public override string InviteCode { get; init; }
@ -56,7 +65,7 @@ public record QueryUserRsp : Sys_User
/// <inheritdoc cref="Sys_User.Summary" /> /// <inheritdoc cref="Sys_User.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_User.UserName" /> /// <inheritdoc cref="Sys_User.UserName" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

View File

@ -0,0 +1,8 @@
using NetAdmin.Domain.Dto.Sys.User;
namespace NetAdmin.Domain.Dto.Sys.UserInvite;
/// <summary>
/// 请求:创建粉丝账号
/// </summary>
public record CreateFansAccountReq : CreateUserReq;

View File

@ -8,4 +8,7 @@ public record CreateUserInviteReq : Sys_UserInvite
/// <inheritdoc cref="Sys_UserInvite.CommissionRatio" /> /// <inheritdoc cref="Sys_UserInvite.CommissionRatio" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override int CommissionRatio { get; init; } public override int CommissionRatio { get; init; }
/// <inheritdoc />
public override bool SelfRechargeAllowed { get; init; } = true;
} }

View File

@ -8,4 +8,9 @@ public sealed record QueryUserInviteReq : Sys_UserInvite
/// <inheritdoc cref="EntityBase{T}.Id" /> /// <inheritdoc cref="EntityBase{T}.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; } public override long Id { get; init; }
/// <summary>
/// 是否平面查询
/// </summary>
public bool IsPlainQuery { get; init; }
} }

View File

@ -54,6 +54,10 @@ public record QueryUserInviteRsp : Sys_UserInvite
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? OwnerId { get; init; } public override long? OwnerId { get; init; }
/// <inheritdoc cref="Sys_UserInvite.SelfRechargeAllowed" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override bool SelfRechargeAllowed { get; init; }
/// <inheritdoc cref="Sys_UserInvite.User" /> /// <inheritdoc cref="Sys_UserInvite.User" />
[CsvIgnore] [CsvIgnore]
public new virtual QueryUserRsp User { get; init; } public new virtual QueryUserRsp User { get; init; }

View File

@ -0,0 +1,15 @@
namespace NetAdmin.Domain.Dto.Sys.UserInvite;
/// <summary>
/// 请求:修改粉丝角色
/// </summary>
public record SetFansRoleReq : Sys_UserInvite
{
/// <inheritdoc />
public override long Id { get; init; }
/// <summary>
/// 角色编号
/// </summary>
public long RoleId { get; init; }
}

View File

@ -0,0 +1,30 @@
namespace NetAdmin.Domain.Dto.Sys.UserInvite;
/// <summary>
/// 请求:设置上级
/// </summary>
public record SetInviterReq : Sys_UserInvite
{
/// <inheritdoc cref="EntityBase{T}.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; }
/// <inheritdoc />
[Required]
[Range(1, long.MaxValue)]
public override long? OwnerId { get; init; }
/// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; }
/// <inheritdoc />
protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
{
if (OwnerId == Id) {
yield return new ValidationResult(Ln., [nameof(OwnerId)]);
}
yield return ValidationResult.Success;
}
}

View File

@ -1,16 +1,18 @@
using NetAdmin.Domain.DbMaps.Tpl; namespace NetAdmin.Domain.Dto.Sys.UserInvite;
namespace NetAdmin.Domain.Dto.Tpl.Example;
/// <summary> /// <summary>
/// 响应:查询示例 /// 请求:设置允许自助充值
/// </summary> /// </summary>
public sealed record QueryExampleRsp : Tpl_Example public record SetSelfRechargeAllowedReq : Sys_UserInvite
{ {
/// <inheritdoc cref="EntityBase{T}.Id" /> /// <inheritdoc cref="EntityBase{T}.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; } public override long Id { get; init; }
/// <inheritdoc cref="Sys_UserInvite.SelfRechargeAllowed" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override bool SelfRechargeAllowed { get; init; }
/// <inheritdoc cref="IFieldVersion.Version" /> /// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; } public override long Version { get; init; }

View File

@ -38,10 +38,6 @@ public record QueryUserWalletRsp : Sys_UserWallet
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? OwnerId { get; init; } public override long? OwnerId { get; init; }
/// <inheritdoc cref="Sys_UserWallet.TotalBalance" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long TotalBalance { get; init; }
/// <inheritdoc cref="Sys_UserWallet.TotalExpenditure" /> /// <inheritdoc cref="Sys_UserWallet.TotalExpenditure" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long TotalExpenditure { get; init; } public override long TotalExpenditure { get; init; }

View File

@ -6,7 +6,7 @@ namespace NetAdmin.Domain.Dto.Sys.VerifyCode;
/// <summary> /// <summary>
/// 请求:发送验证码 /// 请求:发送验证码
/// </summary> /// </summary>
public sealed record SendVerifyCodeReq : Sys_VerifyCode, IValidatableObject public sealed record SendVerifyCodeReq : Sys_VerifyCode
{ {
/// <inheritdoc cref="Sys_VerifyCode.DestDevice" /> /// <inheritdoc cref="Sys_VerifyCode.DestDevice" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
@ -35,7 +35,7 @@ public sealed record SendVerifyCodeReq : Sys_VerifyCode, IValidatableObject
public VerifyCaptchaReq VerifyCaptchaReq { get; init; } public VerifyCaptchaReq VerifyCaptchaReq { get; init; }
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
{ {
ValidationResult validationResult; ValidationResult validationResult;
switch (DeviceType) { switch (DeviceType) {

View File

@ -0,0 +1,33 @@
using NetAdmin.Domain.Enums.Sys;
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
/// <summary>
/// 请求:创建钱包冻结
/// </summary>
public record CreateWalletFrozenReq : Sys_WalletFrozen
{
/// <inheritdoc cref="Sys_WalletFrozen.Amount" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Amount { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.OwnerId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? OwnerId { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.Reason" />
[EnumDataType(typeof(WalletFrozenReasons))]
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override WalletFrozenReasons Reason { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.Status" />
public override WalletFrozenStatues Status { get; init; } = WalletFrozenStatues.Frozen;
/// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; set; }
/// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; }
}

View File

@ -1,11 +1,11 @@
namespace NetAdmin.Domain.Dto.Tpl.Example; namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
/// <summary> /// <summary>
/// 请求:编辑示例 /// 请求:编辑钱包冻结
/// </summary> /// </summary>
public record EditExampleReq : CreateExampleReq public sealed record EditWalletFrozenReq : CreateWalletFrozenReq
{ {
/// <inheritdoc cref="EntityBase{T}.Id" /> /// <inheritdoc cref="Sys_WalletFrozen.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; } public override long Id { get; init; }

View File

@ -1,11 +1,9 @@
using NetAdmin.Domain.DbMaps.Tpl; namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
namespace NetAdmin.Domain.Dto.Tpl.Example;
/// <summary> /// <summary>
/// 请求:查询示例 /// 请求:查询钱包冻结
/// </summary> /// </summary>
public sealed record QueryExampleReq : Tpl_Example public sealed record QueryWalletFrozenReq : Sys_WalletFrozen
{ {
/// <inheritdoc cref="EntityBase{T}.Id" /> /// <inheritdoc cref="EntityBase{T}.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]

View File

@ -0,0 +1,57 @@
using NetAdmin.Domain.Dto.Sys.User;
using NetAdmin.Domain.Enums.Sys;
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
/// <summary>
/// 响应:查询钱包冻结
/// </summary>
public record QueryWalletFrozenRsp : Sys_WalletFrozen
{
/// <inheritdoc cref="Sys_WalletFrozen.Amount" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Amount { get; init; }
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override DateTime CreatedTime { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.FrozenBalanceBefore" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long FrozenBalanceBefore { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; }
/// <inheritdoc cref="IFieldModifiedTime.ModifiedTime" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override DateTime? ModifiedTime { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.Owner" />
public new virtual QueryUserRsp Owner { get; init; }
/// <inheritdoc cref="IFieldOwner.OwnerDeptId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? OwnerDeptId { get; init; }
/// <inheritdoc cref="IFieldOwner.OwnerId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? OwnerId { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.Reason" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override WalletFrozenReasons Reason { get; init; }
/// <inheritdoc cref="Sys_WalletFrozen.Status" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override WalletFrozenStatues Status { get; init; }
/// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; set; }
/// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; }
}

View File

@ -0,0 +1,11 @@
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
/// <summary>
/// 请求:将状态设置为解冻
/// </summary>
public record SetStatusToThawedReq : Sys_WalletFrozen
{
/// <inheritdoc cref="Sys_WalletFrozen.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Id { get; init; }
}

View File

@ -3,13 +3,11 @@ namespace NetAdmin.Domain.Dto.Sys.WalletTrade;
/// <summary> /// <summary>
/// 请求:创建钱包交易 /// 请求:创建钱包交易
/// </summary> /// </summary>
public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject public record CreateWalletTradeReq : Sys_WalletTrade
{ {
private readonly TradeTypes _tradeType;
/// <inheritdoc cref="Sys_WalletTrade.Amount" /> /// <inheritdoc cref="Sys_WalletTrade.Amount" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Amount { get; init; } public override long Amount { get; set; }
/// <inheritdoc cref="Sys_WalletTrade.BusinessOrderNumber" /> /// <inheritdoc cref="Sys_WalletTrade.BusinessOrderNumber" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
@ -24,7 +22,7 @@ public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_WalletTrade.TradeDirection" /> /// <inheritdoc cref="Sys_WalletTrade.TradeDirection" />
public override TradeDirections TradeDirection { get; init; } public override TradeDirections TradeDirection { get; init; }
@ -33,20 +31,23 @@ public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
[EnumDataType(typeof(TradeTypes))] [EnumDataType(typeof(TradeTypes))]
public override TradeTypes TradeType { public override TradeTypes TradeType {
get => _tradeType; get;
init { init {
_tradeType = value; field = value;
TradeDirection = value.Attr<TradeAttribute>().Direction; TradeDirection = value.Attr<TradeAttribute>().Direction;
} }
} }
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
{ {
var tradeDirection = TradeType.Attr<TradeAttribute>().Direction; var tradeDirection = TradeType.Attr<TradeAttribute>().Direction;
if (Amount == 0 || (tradeDirection == TradeDirections.Income && Amount < 0) || (tradeDirection == TradeDirections.Expense && Amount > 0)) { if (Amount == 0) {
yield return new ValidationResult(Ln., [nameof(Amount)]); yield return new ValidationResult(Ln., [nameof(Amount)]);
} }
else if ((tradeDirection == TradeDirections.Income && Amount < 0) || (tradeDirection == TradeDirections.Expense && Amount > 0)) {
Amount = -Amount;
}
yield return ValidationResult.Success; yield return ValidationResult.Success;
} }

View File

@ -9,7 +9,7 @@ public record QueryWalletTradeRsp : Sys_WalletTrade
{ {
/// <inheritdoc cref="Sys_WalletTrade.Amount" /> /// <inheritdoc cref="Sys_WalletTrade.Amount" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Amount { get; init; } public override long Amount { get; set; }
/// <inheritdoc cref="Sys_WalletTrade.BalanceBefore" /> /// <inheritdoc cref="Sys_WalletTrade.BalanceBefore" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
@ -49,7 +49,7 @@ public record QueryWalletTradeRsp : Sys_WalletTrade
/// <inheritdoc cref="IFieldSummary.Summary" /> /// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; init; } public override string Summary { get; set; }
/// <inheritdoc cref="Sys_WalletTrade.TradeDirection" /> /// <inheritdoc cref="Sys_WalletTrade.TradeDirection" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]

View File

@ -0,0 +1,28 @@
namespace NetAdmin.Domain.Dto.Sys.WalletTrade;
/// <summary>
/// 请求:转账
/// </summary>
public record TransferReq : Sys_WalletTrade
{
/// <inheritdoc cref="Sys_WalletTrade.Amount" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Amount { get; set; }
/// <inheritdoc cref="IFieldOwner.OwnerId" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Required]
[UserId]
[Range(1, long.MaxValue)]
public override long? OwnerId { get; init; }
/// <inheritdoc cref="IFieldSummary.Summary" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string Summary { get; set; }
/// <inheritdoc />
protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
{
yield return Amount <= 0 ? new ValidationResult(Ln., [nameof(Amount)]) : ValidationResult.Success;
}
}

View File

@ -1,8 +0,0 @@
using NetAdmin.Domain.DbMaps.Tpl;
namespace NetAdmin.Domain.Dto.Tpl.Example;
/// <summary>
/// 请求:创建示例
/// </summary>
public record CreateExampleReq : Tpl_Example;

View File

@ -15,10 +15,10 @@ public enum DataScopes
, ,
/// <summary> /// <summary>
/// 本部门和下级部门数据 /// 本部门和所有子部门数据
/// </summary> /// </summary>
[ResourceDescription<Ln>(nameof(Ln.本部门和下级部门数据))] [ResourceDescription<Ln>(nameof(Ln.本部门和所有子部门数据))]
DeptWithChild = 2 DeptWithChildren = 2
, ,
@ -43,4 +43,12 @@ public enum DataScopes
/// </summary> /// </summary>
[ResourceDescription<Ln>(nameof(Ln.指定部门数据))] [ResourceDescription<Ln>(nameof(Ln.指定部门数据))]
SpecificDept = 5 SpecificDept = 5
,
/// <summary>
/// 本部门和下一级部门数据
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.本部门和下一级部门数据))]
DeptWithSon = 6
} }

View File

@ -0,0 +1,22 @@
namespace NetAdmin.Domain.Enums.Sys;
/// <summary>
/// 钱包冻结原因
/// </summary>
[Export]
public enum WalletFrozenReasons
{
/// <summary>
/// 交易
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.交易))]
Trade = 1
,
/// <summary>
/// 人工
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.人工))]
Manual = 2
}

View File

@ -0,0 +1,22 @@
namespace NetAdmin.Domain.Enums.Sys;
/// <summary>
/// 钱包冻结状态
/// </summary>
[Export]
public enum WalletFrozenStatues
{
/// <summary>
/// 已冻结
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.已冻结))]
Frozen = 1
,
/// <summary>
/// 已解冻
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.已解冻))]
Thawed = 2
}

View File

@ -0,0 +1,13 @@
using NetAdmin.Domain.Dto.Sys.User;
namespace NetAdmin.Domain.Events.Sys;
/// <summary>
/// 用户注册事件
/// </summary>
public sealed record UserRegisteredEvent : EventData<UserInfoRsp>
{
/// <inheritdoc />
public UserRegisteredEvent(UserInfoRsp payLoad) //
: base(payLoad) { }
}

View File

@ -4,7 +4,7 @@
<ProjectReference Include="../NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/> <ProjectReference Include="../NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CronExpressionDescriptor" Version="2.41.0"/> <PackageReference Include="CronExpressionDescriptor" Version="2.44.0"/>
<PackageReference Include="Cronos" Version="0.11.0"/> <PackageReference Include="Cronos" Version="0.11.0"/>
<PackageReference Include="NetAdmin.CsvHelper" Version="1.0.0"/> <PackageReference Include="NetAdmin.CsvHelper" Version="1.0.0"/>
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/> <PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/>

View File

@ -1,102 +0,0 @@
using NetAdmin.Application.Modules.Tpl;
using NetAdmin.Application.Services.Tpl.Dependency;
using NetAdmin.Cache.Tpl.Dependency;
using NetAdmin.Domain.Dto.Dependency;
using NetAdmin.Domain.Dto.Tpl.Example;
using NetAdmin.Host.Attributes;
namespace NetAdmin.Host.Controllers.Tpl;
/// <summary>
/// 示例服务
/// </summary>
[ApiDescriptionSettings(nameof(Tpl), Module = nameof(Tpl))]
[Produces(Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_JSON)]
public sealed class ExampleController(IExampleCache cache) : ControllerBase<IExampleCache, IExampleService>(cache), IExampleModule
{
/// <summary>
/// 批量删除示例
/// </summary>
[Transaction]
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
{
return Cache.BulkDeleteAsync(req);
}
/// <summary>
/// 示例计数
/// </summary>
public Task<long> CountAsync(QueryReq<QueryExampleReq> req)
{
return Cache.CountAsync(req);
}
/// <summary>
/// 示例分组计数
/// </summary>
public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryExampleReq> req)
{
return Cache.CountByAsync(req);
}
/// <summary>
/// 创建示例
/// </summary>
[Transaction]
public Task<QueryExampleRsp> CreateAsync(CreateExampleReq req)
{
return Cache.CreateAsync(req);
}
/// <summary>
/// 删除示例
/// </summary>
[Transaction]
public Task<int> DeleteAsync(DelReq req)
{
return Cache.DeleteAsync(req);
}
/// <summary>
/// 编辑示例
/// </summary>
[Transaction]
public Task<QueryExampleRsp> EditAsync(EditExampleReq req)
{
return Cache.EditAsync(req);
}
/// <summary>
/// 导出示例
/// </summary>
[NonAction]
public Task<IActionResult> ExportAsync(QueryReq<QueryExampleReq> req)
{
return Cache.ExportAsync(req);
}
/// <summary>
/// 获取单个示例
/// </summary>
public Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
{
return Cache.GetAsync(req);
}
/// <summary>
/// 分页查询示例
/// </summary>
public Task<PagedQueryRsp<QueryExampleRsp>> PagedQueryAsync(PagedQueryReq<QueryExampleReq> req)
{
return Cache.PagedQueryAsync(req);
}
/// <summary>
/// 查询示例
/// </summary>
[NonAction]
public Task<IEnumerable<QueryExampleRsp>> QueryAsync(QueryReq<QueryExampleReq> req)
{
return Cache.QueryAsync(req);
}
}

View File

@ -45,8 +45,7 @@ public abstract class ApiResultHandler<T>
/// <summary> /// <summary>
/// HTTP状态码处理 /// HTTP状态码处理
/// </summary> /// </summary>
#pragma warning disable ASA001, VSTHRD200 public Task OnResponseStatusCodesAsync( //
public Task OnResponseStatusCodes( //
HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings = null) HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings = null)
{ {
// 设置响应状态码 // 设置响应状态码
@ -54,8 +53,6 @@ public abstract class ApiResultHandler<T>
return Task.CompletedTask; return Task.CompletedTask;
} }
#pragma warning restore ASA001, VSTHRD200
/// <summary> /// <summary>
/// 请求成功 /// 请求成功
/// </summary> /// </summary>

View File

@ -5,7 +5,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NetAdmin.ApiSkin" Condition="'$(Configuration)' == 'Debug'" Version="1.0.1"/> <PackageReference Include="NetAdmin.ApiSkin" Condition="'$(Configuration)' == 'Debug'" Version="1.0.1"/>
<PackageReference Include="NetAdmin.Spectre.Console.Cli" Version="1.0.1"/> <PackageReference Include="NetAdmin.Spectre.Console.Cli" Version="1.0.3"/>
<PackageReference Include="prometheus-net.AspNetCore" Condition="'$(Configuration)' != 'Debug'" Version="8.2.1"/> <PackageReference Include="prometheus-net.AspNetCore" Condition="'$(Configuration)' != 'Debug'" Version="8.2.1"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -46,8 +46,11 @@ public static class Chars
public const string FLG_DB_FIELD_TYPE_VARCHAR_7 = "varchar(7)"; public const string FLG_DB_FIELD_TYPE_VARCHAR_7 = "varchar(7)";
public const string FLG_DB_INDEX_PREFIX = "idx_{tablename}_"; public const string FLG_DB_INDEX_PREFIX = "idx_{tablename}_";
public const string FLG_DB_TABLE_NAME_PREFIX = ""; public const string FLG_DB_TABLE_NAME_PREFIX = "";
public const string FLG_FREE_SQL_GLOBAL_FILTER_DATA = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DATA); public const string FLG_DIC_CATALOG_NEW_USER_ROLE_CONFIG = "new-user-role-config";
public const string FLG_FREE_SQL_GLOBAL_FILTER_DELETE = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DELETE); public const string FLG_FREE_SQL_GLOBAL_FILTER_DELETE = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DELETE);
public const string FLG_FREE_SQL_GLOBAL_FILTER_DEPT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DEPT);
public const string FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILDREN = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILDREN);
public const string FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_SON = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_SON);
public const string FLG_FREE_SQL_GLOBAL_FILTER_MEMBER = nameof(FLG_FREE_SQL_GLOBAL_FILTER_MEMBER); public const string FLG_FREE_SQL_GLOBAL_FILTER_MEMBER = nameof(FLG_FREE_SQL_GLOBAL_FILTER_MEMBER);
public const string FLG_FREE_SQL_GLOBAL_FILTER_SELF = nameof(FLG_FREE_SQL_GLOBAL_FILTER_SELF); public const string FLG_FREE_SQL_GLOBAL_FILTER_SELF = nameof(FLG_FREE_SQL_GLOBAL_FILTER_SELF);
public const string FLG_FREE_SQL_GLOBAL_FILTER_TENANT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_TENANT); public const string FLG_FREE_SQL_GLOBAL_FILTER_TENANT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_TENANT);
@ -108,7 +111,7 @@ public static class Chars
public const string RGX_TELEPHONE = """^((\d{3,4}\-)|)\d{7,8}(|([-\u8f6c]{1}\d{1,5}))$"""; public const string RGX_TELEPHONE = """^((\d{3,4}\-)|)\d{7,8}(|([-\u8f6c]{1}\d{1,5}))$""";
public const string RGX_UP_AND_LOWER_NUMBER = """^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$"""; public const string RGX_UP_AND_LOWER_NUMBER = """^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$""";
public const string RGX_URL = """^(https?|ftp):\/\/[^\s/$.?#].[^\s]*\.[^\s]{2,}$"""; public const string RGX_URL = """^(https?|ftp):\/\/[^\s/$.?#].[^\s]*\.[^\s]{2,}$""";
public const string RGX_USERNAME = "^[a-zA-Z0-9_]{4,16}$"; public const string RGX_USERNAME = """^[\u4e00-\u9fa5a-zA-Z0-9_-]{2,16}$""";
public const string RGX_VERIFY_CODE = """^\d{4}$"""; public const string RGX_VERIFY_CODE = """^\d{4}$""";
public const string RGXL_CHINESE_NAME public const string RGXL_CHINESE_NAME

View File

@ -0,0 +1,33 @@
namespace NetAdmin.Infrastructure.Enums;
/// <summary>
/// 管理员交易类型
/// </summary>
[Export]
public enum AdminTradeTypes
{
/// <summary>
/// 管理员赠送
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.管理员赠送))]
[Trade(Direction = TradeDirections.Income)]
AdminGift = 1
,
/// <summary>
/// 管理员扣费
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.管理员扣费))]
[Trade(Direction = TradeDirections.Expense)]
AdminDeduct = 2
,
/// <summary>
/// 管理员充值
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.管理员充值))]
[Trade(Direction = TradeDirections.Income)]
AdminDeposit = 6
}

View File

@ -7,11 +7,11 @@ namespace NetAdmin.Infrastructure.Enums;
public enum TradeTypes public enum TradeTypes
{ {
/// <summary> /// <summary>
/// 管理员充值 /// 管理员赠送
/// </summary> /// </summary>
[ResourceDescription<Ln>(nameof(Ln.管理员充值))] [ResourceDescription<Ln>(nameof(Ln.管理员赠送))]
[Trade(Direction = TradeDirections.Income)] [Trade(Direction = TradeDirections.Income)]
AdminDeposit = 1 AdminGift = 1
, ,
@ -30,4 +30,29 @@ public enum TradeTypes
[ResourceDescription<Ln>(nameof(Ln.自助充值))] [ResourceDescription<Ln>(nameof(Ln.自助充值))]
[Trade(Direction = TradeDirections.Income)] [Trade(Direction = TradeDirections.Income)]
SelfDeposit = 3 SelfDeposit = 3
,
/// <summary>
/// 转账支出
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.转账支出))]
[Trade(Direction = TradeDirections.Expense)]
TransferExpense = 4
,
/// <summary>
/// 转账收入
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.转账收入))]
[Trade(Direction = TradeDirections.Income)]
TransferIncome = 5,
/// <summary>
/// 管理员充值
/// </summary>
[ResourceDescription<Ln>(nameof(Ln.管理员充值))]
[Trade(Direction = TradeDirections.Income)]
AdminDeposit = 6
} }

View File

@ -0,0 +1,32 @@
namespace NetAdmin.Infrastructure.Enums;
/// <summary>
/// 类型扩展方法
/// </summary>
public static class TypeExtensions
{
/// <summary>
/// 递归获取类型的属性
/// </summary>
/// <param name="type">要查找的类型</param>
/// <param name="propertyPath">属性路径,如"a.b.c"</param>
/// <returns>找到的属性信息如果路径中任何属性不存在则返回null</returns>
public static PropertyInfo GetRecursiveProperty(this Type type, string propertyPath)
{
var properties = propertyPath.Split('.');
PropertyInfo propertyInfo = null;
var currentType = type;
foreach (var propertyName in properties) {
propertyInfo = currentType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (propertyInfo == null) {
return null;
}
currentType = propertyInfo.PropertyType;
}
return propertyInfo;
}
}

View File

@ -24,9 +24,7 @@ public static class StringExtensions
/// <summary> /// <summary>
/// 去掉尾部字符串“Async” /// 去掉尾部字符串“Async”
/// </summary> /// </summary>
#pragma warning disable RCS1047, ASA002, VSTHRD200 public static string TrimAsyncSuffix(this string me)
public static string TrimSuffixAsync(this string me)
#pragma warning restore VSTHRD200, ASA002, RCS1047
{ {
return me.TrimSuffix("Async"); return me.TrimSuffix("Async");
} }
@ -34,7 +32,7 @@ public static class StringExtensions
/// <summary> /// <summary>
/// 去掉尾部字符串“Options” /// 去掉尾部字符串“Options”
/// </summary> /// </summary>
public static string TrimSuffixOptions(this string me) public static string TrimOptionsSuffix(this string me)
{ {
return me.TrimSuffix("Options"); return me.TrimSuffix("Options");
} }

View File

@ -3,13 +3,13 @@
<Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/> <Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/>
<Import Project="$(SolutionDir)/build/prebuild.targets"/> <Import Project="$(SolutionDir)/build/prebuild.targets"/>
<ItemGroup> <ItemGroup>
<PackageReference Include="NetAdmin.FreeSql.DbContext" Version="1.1.7" Label="refs"/> <PackageReference Include="NetAdmin.FreeSql.DbContext" Version="1.1.8" Label="refs"/>
<PackageReference Include="NetAdmin.FreeSql.Provider.Sqlite" Version="1.1.7" Label="refs"/> <PackageReference Include="NetAdmin.FreeSql.Provider.Sqlite" Version="1.1.8" Label="refs"/>
<PackageReference Include="Gurion" Version="1.2.15" Label="refs"/> <PackageReference Include="Gurion" Version="1.2.17" Label="refs"/>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.6"/> <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.7"/>
<PackageReference Include="Minio" Version="6.0.5"/> <PackageReference Include="Minio" Version="6.0.5"/>
<PackageReference Include="NSExt" Version="2.3.7"/> <PackageReference Include="NSExt" Version="2.3.8"/>
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.6"/> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!--<ProjectReference Include="$(SolutionDir)/refs/NetAdmin.FreeSql/src/FreeSql.DbContext/FreeSql.DbContext.csproj" Label="refs"/>--> <!--<ProjectReference Include="$(SolutionDir)/refs/NetAdmin.FreeSql/src/FreeSql.DbContext/FreeSql.DbContext.csproj" Label="refs"/>-->

View File

@ -5,7 +5,7 @@ namespace NetAdmin.Infrastructure.Utils;
/// </summary> /// </summary>
public static class PhoneNumberHelper public static class PhoneNumberHelper
{ {
private static readonly IEnumerable<(string CallingCode, CountryCodes CountryCode)> _countryList; private static readonly ImmutableList<(string CallingCode, CountryCodes CountryCode)> _countryList;
#pragma warning disable S3963 #pragma warning disable S3963
static PhoneNumberHelper() static PhoneNumberHelper()
@ -21,14 +21,20 @@ public static class PhoneNumberHelper
.OrderBy(x => x.Item1) .OrderBy(x => x.Item1)
.ThenByDescending(x => x.x.Attr<CountryInfoAttribute>().IsPreferred) .ThenByDescending(x => x.x.Attr<CountryInfoAttribute>().IsPreferred)
.DistinctBy(x => x.Item1) .DistinctBy(x => x.Item1)
.OrderByDescending(x => x.Item1.Length); .OrderByDescending(x => x.Item1.Length)
.ToImmutableList();
} }
/// <summary> /// <summary>
/// 电话号码转国家代码 /// 电话号码转国家代码
/// </summary> /// </summary>
public static CountryCodes PhoneNumberToCountryCode(string phoneNumber) public static CountryCodes? PhoneNumberToCountryCode(string phoneNumber)
{ {
return _countryList.First(x => phoneNumber.Replace("+", string.Empty).Trim().StartsWith(x.CallingCode, StringComparison.Ordinal)).CountryCode; phoneNumber = phoneNumber.Trim();
if (phoneNumber.StartsWith('+')) {
phoneNumber = phoneNumber[1..];
}
return _countryList.FirstOrDefault(x => phoneNumber.StartsWith(x.CallingCode, StringComparison.Ordinal)).CountryCode;
} }
} }

View File

@ -17,7 +17,7 @@ public sealed class XmlCommentReader : ISingleton
public XmlCommentReader(IOptions<SpecificationDocumentSettingsOptions> specificationDocumentSettings) public XmlCommentReader(IOptions<SpecificationDocumentSettingsOptions> specificationDocumentSettings)
{ {
var xmlComments = specificationDocumentSettings.Value.XmlComments // var xmlComments = specificationDocumentSettings.Value.XmlComments //
?? App.GetConfig<SpecificationDocumentSettingsOptions>(nameof(SpecificationDocumentSettingsOptions).TrimSuffixOptions()) ?? App.GetConfig<SpecificationDocumentSettingsOptions>(nameof(SpecificationDocumentSettingsOptions).TrimOptionsSuffix())
.XmlComments; .XmlComments;
foreach (var commentFile in xmlComments) { foreach (var commentFile in xmlComments) {
var xmlDoc = new XmlDocument(); var xmlDoc = new XmlDocument();

View File

@ -0,0 +1,12 @@
using NetAdmin.Domain.Dto.Sys.CodeTemplate;
namespace NetAdmin.SysComponent.Application.Modules.Sys;
/// <summary>
/// 代码模板模块
/// </summary>
public interface ICodeTemplateModule : ICrudModule<CreateCodeTemplateReq, QueryCodeTemplateRsp // 创建类型
, EditCodeTemplateReq // 编辑类型
, QueryCodeTemplateReq, QueryCodeTemplateRsp // 查询类型
, DelReq // 删除类型
>;

View File

@ -24,5 +24,5 @@ public interface IDepositOrderModule : ICrudModule<CreateDepositOrderReq, QueryD
/// <summary> /// <summary>
/// 到账确认 /// 到账确认
/// </summary> /// </summary>
Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req); Task<int> ReceivedConfirmationAsync(JobReq req);
} }

View File

@ -21,4 +21,24 @@ public interface IDevModule
/// 生成接口代码 /// 生成接口代码
/// </summary> /// </summary>
Task GenerateJsCodeAsync(); Task GenerateJsCodeAsync();
/// <summary>
/// 获取实体项目列表
/// </summary>
Task<IEnumerable<Tuple<string, string>>> GetDomainProjectsAsync();
/// <summary>
/// 获取所有数据类型
/// </summary>
IEnumerable<string> GetDotnetDataTypes(GetDotnetDataTypesReq req);
/// <summary>
/// 获取实体基类列表
/// </summary>
IEnumerable<Tuple<string, string>> GetEntityBaseClasses();
/// <summary>
/// 获取字段接口列表
/// </summary>
IEnumerable<Tuple<string, string>> GetFieldInterfaces();
} }

View File

@ -1,3 +1,5 @@
using NetAdmin.Domain.Dto.Sys.Dic.Content;
using NetAdmin.Domain.Dto.Sys.User;
using NetAdmin.Domain.Dto.Sys.UserInvite; using NetAdmin.Domain.Dto.Sys.UserInvite;
namespace NetAdmin.SysComponent.Application.Modules.Sys; namespace NetAdmin.SysComponent.Application.Modules.Sys;
@ -11,8 +13,38 @@ public interface IUserInviteModule : ICrudModule<CreateUserInviteReq, QueryUserI
, DelReq // 删除类型 , DelReq // 删除类型
> >
{ {
/// <summary>
/// 创建粉丝账号
/// </summary>
Task<QueryUserRsp> CreateFansAccountAsync(CreateFansAccountReq req);
/// <summary>
/// 获取自己是否允许自助充值
/// </summary>
Task<bool> GetSelfRechargeAllowedAsync();
/// <summary>
/// 查询可分配的角色
/// </summary>
Task<IEnumerable<QueryDicContentRsp>> QueryRolesAllowApplyAsync();
/// <summary> /// <summary>
/// 设置返佣比率 /// 设置返佣比率
/// </summary> /// </summary>
Task<int> SetCommissionRatioAsync(SetCommissionRatioReq req); Task<int> SetCommissionRatioAsync(SetCommissionRatioReq req);
/// <summary>
/// 修改粉丝角色
/// </summary>
Task<int> SetFansRoleAsync(SetFansRoleReq req);
/// <summary>
/// 设置上级
/// </summary>
Task<int> SetInviterAsync(SetInviterReq req);
/// <summary>
/// 设置允许自助充值
/// </summary>
Task<int> SetSelfRechargeAllowedAsync(SetSelfRechargeAllowedReq req);
} }

View File

@ -6,7 +6,7 @@ namespace NetAdmin.SysComponent.Application.Modules.Sys;
/// 用户钱包模块 /// 用户钱包模块
/// </summary> /// </summary>
public interface IUserWalletModule : ICrudModule<CreateUserWalletReq, QueryUserWalletRsp // 创建类型 public interface IUserWalletModule : ICrudModule<CreateUserWalletReq, QueryUserWalletRsp // 创建类型
, EditUserWalletReq // 编辑类型 , EditUserWalletReq // 编辑类型
, QueryUserWalletReq, QueryUserWalletRsp // 查询类型 , QueryUserWalletReq, QueryUserWalletRsp // 查询类型
, DelReq // 删除类型 , DelReq // 删除类型
>; >;

Some files were not shown because too many files have changed in this diff Show More