mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2025-11-09 19:04:44 +08:00
Merge branch 'main' of https://gitee.com/dotnetchina/OpenAuth.Net
This commit is contained in:
@@ -175,7 +175,7 @@ namespace Infrastructure
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filterjson))
|
||||
{
|
||||
var filterGroup = JsonHelper.Instance.Deserialize<FilterGroup>(filterjson);
|
||||
var filterGroup = JsonHelper.Instance.Deserialize<QueryObject>(filterjson);
|
||||
query = GenerateFilter(query, parametername, filterGroup);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace Infrastructure
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filterjson))
|
||||
{
|
||||
var filterGroup = JsonHelper.Instance.Deserialize<FilterGroup>(filterjson);
|
||||
var filterGroup = JsonHelper.Instance.Deserialize<QueryObject>(filterjson);
|
||||
query = GenerateFilter(query, parametername, filterGroup);
|
||||
}
|
||||
|
||||
@@ -199,13 +199,13 @@ namespace Infrastructure
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="parametername"></param>
|
||||
/// <param name="filterGroup"></param>
|
||||
/// <param name="queryObject"></param>
|
||||
/// <returns></returns>
|
||||
public static IQueryable<T> GenerateFilter<T>(this IQueryable<T> query, string parametername,
|
||||
FilterGroup filterGroup)
|
||||
QueryObject queryObject)
|
||||
{
|
||||
var param = CreateLambdaParam<T>(parametername);
|
||||
Expression result = ConvertGroup<T>(filterGroup, param);
|
||||
Expression result = ConvertGroup<T>(queryObject, param);
|
||||
query = query.Where(param.GenerateTypeLambda<T>(result));
|
||||
return query;
|
||||
}
|
||||
@@ -215,14 +215,14 @@ namespace Infrastructure
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="parametername"></param>
|
||||
/// <param name="filterGroup"></param>
|
||||
/// <param name="queryObject"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static ISugarQueryable<T> GenerateFilter<T>(this ISugarQueryable<T> query, string parametername,
|
||||
FilterGroup filterGroup)
|
||||
QueryObject queryObject)
|
||||
{
|
||||
var param = CreateLambdaParam<T>(parametername);
|
||||
Expression result = ConvertGroup<T>(filterGroup, param);
|
||||
Expression result = ConvertGroup<T>(queryObject, param);
|
||||
query = query.Where(param.GenerateTypeLambda<T>(result));
|
||||
return query;
|
||||
}
|
||||
@@ -230,62 +230,62 @@ namespace Infrastructure
|
||||
/// <summary>
|
||||
/// 转换filtergroup为表达式
|
||||
/// </summary>
|
||||
/// <param name="filterGroup"></param>
|
||||
/// <param name="queryObject"></param>
|
||||
/// <param name="param"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Expression ConvertGroup<T>(FilterGroup filterGroup, ParameterExpression param)
|
||||
public static Expression ConvertGroup<T>(QueryObject queryObject, ParameterExpression param)
|
||||
{
|
||||
if (filterGroup == null) return null;
|
||||
if (queryObject == null) return null;
|
||||
|
||||
if (filterGroup.Filters.Length == 1 &&(filterGroup.Children == null || !filterGroup.Children.Any())) //只有一个条件
|
||||
if (queryObject.Filters.Length == 1 &&(queryObject.Children == null || !queryObject.Children.Any())) //只有一个条件
|
||||
{
|
||||
return param.GenerateBody<T>(filterGroup.Filters[0]);
|
||||
return param.GenerateBody<T>(queryObject.Filters[0]);
|
||||
}
|
||||
|
||||
Expression result = ConvertFilters<T>(filterGroup.Filters, param, filterGroup.Operation);
|
||||
Expression gresult = ConvertGroup<T>(filterGroup.Children, param, filterGroup.Operation);
|
||||
Expression result = ConvertFilters<T>(queryObject.Filters, param, queryObject.Operation);
|
||||
Expression gresult = ConvertGroup<T>(queryObject.Children, param, queryObject.Operation);
|
||||
if (gresult == null) return result;
|
||||
if (result == null) return gresult;
|
||||
|
||||
if (filterGroup.Operation == "and")
|
||||
if (queryObject.Operation == "and")
|
||||
{
|
||||
return result.AndAlso(gresult);
|
||||
}
|
||||
else //or
|
||||
{
|
||||
return result.Or(gresult);
|
||||
return Expression.OrElse( result, gresult);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换FilterGroup[]为表达式,不管FilterGroup里面的Filters
|
||||
/// </summary>
|
||||
/// <param name="groups"></param>
|
||||
/// <param name="queryObjs"></param>
|
||||
/// <param name="param"></param>
|
||||
/// <param name="operation"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
private static Expression ConvertGroup<T>(FilterGroup[] groups, ParameterExpression param, string operation)
|
||||
private static Expression ConvertGroup<T>(QueryObject[] queryObjs, ParameterExpression param, string operation)
|
||||
{
|
||||
if (groups == null || !groups.Any()) return null;
|
||||
if (queryObjs == null || !queryObjs.Any()) return null;
|
||||
|
||||
Expression result = ConvertGroup<T>(groups[0], param);
|
||||
Expression result = ConvertGroup<T>(queryObjs[0], param);
|
||||
|
||||
if (groups.Length == 1) return result;
|
||||
if (queryObjs.Length == 1) return result;
|
||||
|
||||
if (operation == "and")
|
||||
{
|
||||
foreach (var filter in groups.Skip(1))
|
||||
foreach (var filter in queryObjs.Skip(1))
|
||||
{
|
||||
result = result.AndAlso(ConvertGroup<T>(filter, param));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var filter in groups.Skip(1))
|
||||
foreach (var filter in queryObjs.Skip(1))
|
||||
{
|
||||
result = result.Or(ConvertGroup<T>(filter, param));
|
||||
result = Expression.OrElse(result, ConvertGroup<T>(filter, param));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ namespace Infrastructure
|
||||
{
|
||||
foreach (var filter in filters.Skip(1))
|
||||
{
|
||||
result = result.Or(param.GenerateBody<T>(filter));
|
||||
result = Expression.OrElse(result, param.GenerateBody<T>(filter));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,64 @@
|
||||
namespace Infrastructure
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 查询表达式中的最小单元,如:
|
||||
/// new Filter {Key = "name", Value = "yubaolee", Contrast = "=="},
|
||||
/// new Filter {Key = "name", Value = "yubaolee", Contrast = "contains"},
|
||||
/// new Filter {Key = "age", Value = "10,20,30", Contrast = "in"},
|
||||
/// new Filter {Key = "10,20,30", Value = "40", Contrast = "intersect"}
|
||||
/// </summary>
|
||||
public class Filter
|
||||
{
|
||||
/// <summary>
|
||||
/// 过滤条件的关键字。
|
||||
/// </summary>
|
||||
public string Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通常为值,如:yubaolee、10、10,20,30等。
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通常为运算符,如:==、contains、in、intersect等。
|
||||
/// </summary>
|
||||
public string Contrast { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对于特殊值的说明
|
||||
/// </summary>
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
public class FilterGroup
|
||||
/// <summary>
|
||||
/// 查询对象类,用于封装查询条件。
|
||||
/// </summary>
|
||||
public class QueryObject
|
||||
{
|
||||
/// <summary>
|
||||
/// or /and
|
||||
/// 操作类型,定义了查询条件之间的逻辑关系,如OR、AND。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该属性决定了如何组合多个过滤条件,以构建复杂的查询逻辑。
|
||||
/// </remarks>
|
||||
public string Operation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过滤器数组,包含一组过滤条件。
|
||||
/// </summary>
|
||||
public Filter[] Filters { get; set; }
|
||||
public FilterGroup[] Children { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子查询对象数组,支持嵌套查询。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 通过嵌套查询对象,可以构建复杂的查询逻辑,处理更复杂的数据关系。
|
||||
/// </remarks>
|
||||
public QueryObject[] Children { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
51
Infrastructure/QueryObjExtension.cs
Normal file
51
Infrastructure/QueryObjExtension.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// 查询对象FilterGroup扩展,将对象转换为sql查询
|
||||
/// </summary>
|
||||
public static class QueryObjExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据过滤器组构建查询。
|
||||
/// </summary>
|
||||
public static string BuildQuery(this QueryObject query)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BuildQuery(query, sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归构建查询字符串。
|
||||
/// </summary>
|
||||
private static void BuildQuery(QueryObject query, StringBuilder sb)
|
||||
{
|
||||
// 构建当前过滤器组的过滤条件
|
||||
if (query.Filters != null && query.Filters.Length > 0)
|
||||
{
|
||||
string filters = string.Join($" {query.Operation} ", query.Filters.Select(f => $"{f.Key} {f.Contrast} '{f.Value}'"));
|
||||
sb.Append($"({filters})");
|
||||
}
|
||||
|
||||
// 构建当前过滤器组的子过滤器组
|
||||
if (query.Children != null && query.Children.Length > 0)
|
||||
{
|
||||
// 如果当前字符串不为空,则添加操作符连接子过滤器组
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
sb.Append($" {query.Operation} ");
|
||||
}
|
||||
// 使用递归方式构建子过滤器组的查询字符串,并连接到当前字符串
|
||||
string children = string.Join($" {query.Operation} ", query.Children.Select(child =>
|
||||
{
|
||||
StringBuilder childSb = new StringBuilder();
|
||||
BuildQuery(child, childSb);
|
||||
return childSb.ToString();
|
||||
}));
|
||||
sb.Append($"({children})");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Infrastructure.Test
|
||||
[Test]
|
||||
public void Convert()
|
||||
{
|
||||
FilterGroup sub = new FilterGroup
|
||||
QueryObject sub = new QueryObject
|
||||
{
|
||||
Operation = "or"
|
||||
};
|
||||
@@ -19,22 +19,22 @@ namespace Infrastructure.Test
|
||||
new Filter {Key = "c3", Value = "10,20,30", Contrast = "in"}
|
||||
};
|
||||
|
||||
FilterGroup filterGroup = new FilterGroup
|
||||
QueryObject queryObject = new QueryObject
|
||||
{
|
||||
Operation = "and"
|
||||
};
|
||||
filterGroup.Filters = new[]
|
||||
queryObject.Filters = new[]
|
||||
{
|
||||
new Filter {Key = "c1", Value = "name", Contrast = "contains"},
|
||||
new Filter {Key = "10,20,30", Value = "40", Contrast = "intersect"}
|
||||
};
|
||||
|
||||
filterGroup.Children = new[]
|
||||
queryObject.Children = new[]
|
||||
{
|
||||
sub
|
||||
};
|
||||
|
||||
var expression = DynamicLinq.ConvertGroup<TestOjb>(filterGroup,
|
||||
var expression = DynamicLinq.ConvertGroup<TestOjb>(queryObject,
|
||||
Expression.Parameter(typeof(TestOjb), "c"));
|
||||
|
||||
Console.WriteLine(expression.ToString());
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace OpenAuth.App
|
||||
string.Join(',',orgs));
|
||||
}
|
||||
return UnitWork.Find<T>(null).GenerateFilter(parametername,
|
||||
JsonHelper.Instance.Deserialize<FilterGroup>(rule.PrivilegeRules));
|
||||
JsonHelper.Instance.Deserialize<QueryObject>(rule.PrivilegeRules));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace OpenAuth.App
|
||||
string.Join(',',orgs));
|
||||
}
|
||||
return SugarClient.Queryable<T>().GenerateFilter(parametername,
|
||||
JsonHelper.Instance.Deserialize<FilterGroup>(rule.PrivilegeRules));
|
||||
JsonHelper.Instance.Deserialize<QueryObject>(rule.PrivilegeRules));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -26,6 +26,7 @@ using System.Linq.Expressions;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure.Const;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@@ -136,8 +137,16 @@ namespace OpenAuth.App
|
||||
{
|
||||
var t = Type.GetType("OpenAuth.App." + flowInstance.DbName + "App");
|
||||
ICustomerForm icf = (ICustomerForm) _serviceProvider.GetService(t);
|
||||
try
|
||||
{
|
||||
icf.Add(flowInstance.Id, flowInstance.FrmData);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception("流程表单数据解析失败,请检查表单是否填写完整");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//如果工作流配置的表单配置有对应的数据库
|
||||
if (!string.IsNullOrEmpty(form.DbName))
|
||||
@@ -616,7 +625,10 @@ namespace OpenAuth.App
|
||||
//当审批流程时,能进到这里,表明当前登录用户已经有审批当前节点的权限,完全可以直接用登录用户的直接上级
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
var parentId = _userManagerApp.GetParent(user.Id);
|
||||
|
||||
if (StringExtension.IsNullOrEmpty(parentId))
|
||||
{
|
||||
throw new Exception("无法找到当前用户的直属上级");
|
||||
}
|
||||
makerList = GenericHelpers.ArrayToString(new[]{parentId}, makerList);
|
||||
}
|
||||
else if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_CHAIRMAN)
|
||||
@@ -825,7 +837,7 @@ namespace OpenAuth.App
|
||||
// 加入搜索自定义标题
|
||||
if (!string.IsNullOrEmpty(request.key))
|
||||
{
|
||||
waitExp = waitExp.And(t => t.CustomName.Contains(request.key));
|
||||
waitExp = PredicateBuilder.And(waitExp, t => t.CustomName.Contains(request.key));
|
||||
}
|
||||
|
||||
result.count = await UnitWork.Find(waitExp).CountAsync();
|
||||
@@ -859,7 +871,7 @@ namespace OpenAuth.App
|
||||
// 加入搜索自定义标题
|
||||
if (!string.IsNullOrEmpty(request.key))
|
||||
{
|
||||
myFlowExp = myFlowExp.And(t => t.CustomName.Contains(request.key));
|
||||
myFlowExp = PredicateBuilder.And(myFlowExp, t => t.CustomName.Contains(request.key));
|
||||
}
|
||||
|
||||
result.count = await UnitWork.Find(myFlowExp).CountAsync();
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace OpenAuth.App.Test
|
||||
var services = new ServiceCollection();
|
||||
|
||||
var cachemock = new Mock<ICacheContext>();
|
||||
cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession { Account = "Systems" });
|
||||
cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession { Account = "admin" });
|
||||
services.AddScoped(x => cachemock.Object);
|
||||
|
||||
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
|
||||
@@ -37,7 +37,7 @@ namespace OpenAuth.App.Test
|
||||
{
|
||||
var app = _autofacServiceProvider.GetService<ResourceApp>();
|
||||
var result = app.Load(new QueryResourcesReq());
|
||||
Console.WriteLine(JsonHelper.Instance.Serialize(result));
|
||||
Console.WriteLine(JsonHelper.Instance.Serialize(result.Result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -46,7 +46,7 @@ namespace OpenAuth.App.Test
|
||||
var auth = _autofacServiceProvider.GetService<IAuth>();
|
||||
var app = _autofacServiceProvider.GetService<DataPrivilegeRuleApp>();
|
||||
//该测试解析为:针对资源列表,【管理员】可以看到所有,角色为【神】或【测试】的只能看到自己创建的
|
||||
var filterGroup = new FilterGroup
|
||||
var filterGroup = new QueryObject
|
||||
{
|
||||
Operation = "or"
|
||||
};
|
||||
@@ -61,7 +61,7 @@ namespace OpenAuth.App.Test
|
||||
};
|
||||
filterGroup.Children = new[]
|
||||
{
|
||||
new FilterGroup //登录用户角色包含【测试】或包含【神】的,只能看到自己的
|
||||
new QueryObject //登录用户角色包含【测试】或包含【神】的,只能看到自己的
|
||||
{
|
||||
Operation = "and",
|
||||
Filters = new Filter[]
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "//hm.baidu.com/hm.js?0558502420ce5fee054b31425e77ffa6";
|
||||
hm.src = "//hm.baidu.com/hm.js?93a7b9a145222f9b7109d643a0c58f8d";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -44,7 +44,7 @@ layui.config({
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "//hm.baidu.com/hm.js?0558502420ce5fee054b31425e77ffa6";
|
||||
hm.src = "https://hm.baidu.com/hm.js?93a7b9a145222f9b7109d643a0c58f8d";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace OpenAuth.Repository.Domain
|
||||
/// 前端界面是否缓存
|
||||
/// </summary>
|
||||
/// [Description("前端界面是否缓存")]
|
||||
public bool KeepAlive { get; set; }
|
||||
public bool? KeepAlive { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace OpenAuth.Repository.Test
|
||||
[Test]
|
||||
public void TestDynamic()
|
||||
{
|
||||
FilterGroup sub = new FilterGroup
|
||||
QueryObject sub = new QueryObject
|
||||
{
|
||||
Operation = "or"
|
||||
};
|
||||
@@ -69,24 +69,24 @@ namespace OpenAuth.Repository.Test
|
||||
new Filter {Key = "Sex", Value = "10", Contrast = "=="}
|
||||
};
|
||||
|
||||
FilterGroup filterGroup = new FilterGroup
|
||||
QueryObject queryObject = new QueryObject
|
||||
{
|
||||
Operation = "and"
|
||||
};
|
||||
filterGroup.Filters = new[]
|
||||
queryObject.Filters = new[]
|
||||
{
|
||||
new Filter {Key = "Account", Value = "name", Contrast = "=="},
|
||||
new Filter {Key = "Password", Value = "10", Contrast = "=="}
|
||||
};
|
||||
|
||||
filterGroup.Children = new[]
|
||||
queryObject.Children = new[]
|
||||
{
|
||||
sub
|
||||
};
|
||||
|
||||
var dbcontext = _autofacServiceProvider.GetService<OpenAuthDBContext>();
|
||||
|
||||
var query = dbcontext.Users.GenerateFilter("c",JsonHelper.Instance.Serialize(filterGroup));
|
||||
var query = dbcontext.Users.GenerateFilter("c",JsonHelper.Instance.Serialize(queryObject));
|
||||
Console.WriteLine(query.Expression.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace OpenAuth.Repository.Test
|
||||
[Test]
|
||||
public void TestDynamic()
|
||||
{
|
||||
FilterGroup sub = new FilterGroup
|
||||
QueryObject sub = new QueryObject
|
||||
{
|
||||
Operation = "or"
|
||||
};
|
||||
@@ -83,24 +83,24 @@ namespace OpenAuth.Repository.Test
|
||||
new Filter {Key = "Sex", Value = "10", Contrast = "=="}
|
||||
};
|
||||
|
||||
FilterGroup filterGroup = new FilterGroup
|
||||
QueryObject queryObject = new QueryObject
|
||||
{
|
||||
Operation = "and"
|
||||
};
|
||||
filterGroup.Filters = new[]
|
||||
queryObject.Filters = new[]
|
||||
{
|
||||
new Filter {Key = "Account", Value = "name", Contrast = "=="},
|
||||
new Filter {Key = "Password", Value = "10", Contrast = "=="}
|
||||
};
|
||||
|
||||
filterGroup.Children = new[]
|
||||
queryObject.Children = new[]
|
||||
{
|
||||
sub
|
||||
};
|
||||
|
||||
var sugarClient = _autofacServiceProvider.GetService<ISqlSugarClient>();
|
||||
|
||||
var query = sugarClient.Queryable<User>().GenerateFilter("c",filterGroup);
|
||||
var query = sugarClient.Queryable<User>().GenerateFilter("c",queryObject);
|
||||
Console.WriteLine(query.ToSqlString());
|
||||
}
|
||||
}
|
||||
|
||||
31
README.md
31
README.md
@@ -1,18 +1,5 @@
|
||||
🔥.Net权限管理及快速开发框架、最好用的权限工作流系统。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:角色授权、代码生成、智能打印、表单设计、工作流、定时任务等。架构易扩展,是中小企业的首选。
|
||||
|
||||
## ❤❤❤郑重声明❤❤❤
|
||||
|
||||
主分支main运行环境默认为.Net SDK 6.0,如果你使用vs2019作为开发工具,请注意查看:[VS2019打开6.0及以后版本](http://doc.openauth.net.cn/core/faq.html#vs2019%E6%89%93%E5%BC%806-0%E5%8F%8A%E4%BB%A5%E5%90%8E%E7%89%88%E6%9C%AC)
|
||||
|
||||
需要.Net SDK 4.0/4.5开发环境的同学请查看本项目4.0分支,已停止维护
|
||||
|
||||
使用.Net Core 2.1--3.1的请看:
|
||||
|
||||
**GitHub** https://github.com/yubaolee/OpenAuth.Core
|
||||
|
||||
**码云** https://gitee.com/yubaolee/OpenAuth.Core
|
||||
|
||||
|
||||

|
||||
|
||||
**logo图标含义** OpenAuth中OA字母的结合体;整体像鱼,授人以渔;你非说像咸鱼,那也是积极向上的咸鱼;中心是个笑脸,微笑面对生活(✿◡‿◡)。
|
||||
@@ -21,7 +8,6 @@
|
||||
|
||||
**官方文档** http://doc.openauth.net.cn
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||
@@ -41,6 +27,23 @@
|
||||

|
||||

|
||||
|
||||
## ❤❤❤郑重声明❤❤❤
|
||||
|
||||
主分支main运行环境默认为.Net SDK 6.0,支持.NET未来版本,需要.Net SDK 4.0/4.5开发环境的同学请查看本项目4.0分支,已停止维护
|
||||
|
||||
使用.Net Core 2.1-3.1的请进:https://gitee.com/yubaolee/OpenAuth.Core ,已停止维护
|
||||
|
||||
## OpenAuth.Net系列视频火热更新中
|
||||
|
||||
[OpenAuth.Net视频合集--系统结构及代码下载](https://www.bilibili.com/video/BV1Z1421q7xU/)
|
||||
|
||||
[OpenAuth.Net视频合集--基于RBAC体系的权限管理介绍](https://www.bilibili.com/video/BV1M9KeejENf/)
|
||||
|
||||
[OpenAuth.Net视频合集--企业版代码启动](https://www.bilibili.com/video/BV1KSuQebEek/)
|
||||
|
||||
[OpenAuth.Net视频合集--使用企业版代码生成器](https://www.bilibili.com/video/BV1JCuyeaEFp/)
|
||||
|
||||
[OpenAuth.Net视频合集--表单设计](https://www.bilibili.com/video/BV1dagEeFEVA/)
|
||||
|
||||
|
||||
## 关于OpenAuth.Net企业版/高级版的说明:
|
||||
|
||||
@@ -39,11 +39,18 @@ CodeSmith Generator Studio 8.0或以上
|
||||
|
||||
如下图,使用CodeSmith文件夹中的模板,右击【ApiGenerate.cst】--【Execute】,选择需要生成的表(本文以Stock为例)及相关的上下文命名空间,点击【Generate】
|
||||
|
||||

|
||||

|
||||
|
||||
注意,有两个配置项:
|
||||
|
||||
* WholeDb: 如果选中,则按数据库中所有表生成实体及逻辑;否则,按选择的表生成
|
||||
|
||||
* HeaderModel:会生成主、从表结构,类似 WmsInboundOrderTbl / WmsInboundOrderDtbl
|
||||
|
||||
|
||||
生成成功后,在CodeSmith/Csharp文件夹下面会有Stock实体相关文档,如下图:
|
||||
|
||||

|
||||

|
||||
|
||||
把CSharp\OpenAuth.App覆盖到自己项目对应目录
|
||||
|
||||
@@ -51,7 +58,6 @@ CodeSmith Generator Studio 8.0或以上
|
||||
|
||||
**把CSharp\OpenAuth.Repository\OpenAuthDBContext.cs中的内容添加到自己项目的文件中,千万不要直接覆盖文件!!!**
|
||||
|
||||
**其他文件夹的内容为WebAPI项目使用,可以不管。**
|
||||
|
||||
## 添加界面
|
||||
|
||||
@@ -69,7 +75,15 @@ userJs直接覆盖到OpenAuth.Mvc/wwwroot中
|
||||
|
||||
## 添加模块
|
||||
|
||||
编写完上面代码后,运行系统,使用System账号登录系统,在【模块管理】中,添加`仓储管理`模块,并为它添加菜单,这里我只添加一个菜单【btnAdd】,如下图:
|
||||
编写完上面代码后,运行系统,使用System账号登录系统,在【模块管理】中,添加`仓储管理`模块,
|
||||
|
||||

|
||||
|
||||
::: warning 注意
|
||||
因为生成的Controller名称类似XXXsController,所以模块的Url地址应该是XXXs/Index
|
||||
:::
|
||||
|
||||
并为它添加菜单,这里我只添加一个菜单【btnAdd】,如下图:
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -10,9 +10,13 @@ OpenAuth.Pro是一套全新的前端界面,基于vue-element-admin,采用VUE
|
||||
|
||||
## OpenAuth.Net系列教学视频
|
||||
|
||||
[OpenAuth.Net教学合集--系统结构及代码下载](https://www.bilibili.com/video/BV1Z1421q7xU/)
|
||||
[OpenAuth.Net视频合集--系统结构及代码下载](https://www.bilibili.com/video/BV1Z1421q7xU/)
|
||||
|
||||
[OpenAuth.Net教学合集--企业版代码启动](https://www.bilibili.com/video/BV1KSuQebEek/)
|
||||
[OpenAuth.Net视频合集--企业版代码启动](https://www.bilibili.com/video/BV1KSuQebEek/)
|
||||
|
||||
[OpenAuth.Net视频合集--使用企业版代码生成器](https://www.bilibili.com/video/BV1JCuyeaEFp/)
|
||||
|
||||
[OpenAuth.Net视频合集--权限管理介绍](https://www.bilibili.com/video/BV1M9KeejENf/)
|
||||
|
||||
|
||||
## 工具准备
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 企业版代码生成器
|
||||
|
||||
本章节视频讲解请参考:[OpenAuth.Net视频合集--使用企业版代码生成器](https://www.bilibili.com/video/BV1JCuyeaEFp/)
|
||||
|
||||
## 术语解释
|
||||
|
||||
在添加新功能之前,需要先了解OpenAuth.Net生成代码时的两个概念:动态头部和固定头部
|
||||
@@ -49,17 +51,21 @@ initCfg() {
|
||||
-- mysql示例
|
||||
create table stock
|
||||
(
|
||||
createtime datetime not null comment '操作时间',
|
||||
status int not null comment '出库/入库',
|
||||
price decimal(10, 1) not null comment '产品单价',
|
||||
number int not null comment '产品数量',
|
||||
name text not null comment '产品名称',
|
||||
orgid varchar(50) null comment '组织ID',
|
||||
user varchar(50) not null comment '操作人',
|
||||
viewable varchar(50) not null comment '可见范围',
|
||||
id varchar(50) not null comment '数据ID'
|
||||
primary key
|
||||
Id varchar(50) not null comment '数据ID'
|
||||
primary key,
|
||||
Name text not null comment '产品名称',
|
||||
Number int not null comment '产品数量',
|
||||
Price decimal(10, 1) not null comment '产品单价',
|
||||
Status int not null comment '出库/入库',
|
||||
Viewable varchar(50) not null comment '可见范围',
|
||||
User varchar(50) not null comment '操作人',
|
||||
Time datetime not null comment '操作时间',
|
||||
OrgId varchar(50) null comment '组织ID'
|
||||
)
|
||||
comment '出入库信息表' charset = utf8
|
||||
row_format = COMPACT;
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user