mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2025-11-10 03:14:45 +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))
|
if (!string.IsNullOrEmpty(filterjson))
|
||||||
{
|
{
|
||||||
var filterGroup = JsonHelper.Instance.Deserialize<FilterGroup>(filterjson);
|
var filterGroup = JsonHelper.Instance.Deserialize<QueryObject>(filterjson);
|
||||||
query = GenerateFilter(query, parametername, filterGroup);
|
query = GenerateFilter(query, parametername, filterGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ namespace Infrastructure
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(filterjson))
|
if (!string.IsNullOrEmpty(filterjson))
|
||||||
{
|
{
|
||||||
var filterGroup = JsonHelper.Instance.Deserialize<FilterGroup>(filterjson);
|
var filterGroup = JsonHelper.Instance.Deserialize<QueryObject>(filterjson);
|
||||||
query = GenerateFilter(query, parametername, filterGroup);
|
query = GenerateFilter(query, parametername, filterGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,13 +199,13 @@ namespace Infrastructure
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="query"></param>
|
/// <param name="query"></param>
|
||||||
/// <param name="parametername"></param>
|
/// <param name="parametername"></param>
|
||||||
/// <param name="filterGroup"></param>
|
/// <param name="queryObject"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IQueryable<T> GenerateFilter<T>(this IQueryable<T> query, string parametername,
|
public static IQueryable<T> GenerateFilter<T>(this IQueryable<T> query, string parametername,
|
||||||
FilterGroup filterGroup)
|
QueryObject queryObject)
|
||||||
{
|
{
|
||||||
var param = CreateLambdaParam<T>(parametername);
|
var param = CreateLambdaParam<T>(parametername);
|
||||||
Expression result = ConvertGroup<T>(filterGroup, param);
|
Expression result = ConvertGroup<T>(queryObject, param);
|
||||||
query = query.Where(param.GenerateTypeLambda<T>(result));
|
query = query.Where(param.GenerateTypeLambda<T>(result));
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
@@ -215,14 +215,14 @@ namespace Infrastructure
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query"></param>
|
/// <param name="query"></param>
|
||||||
/// <param name="parametername"></param>
|
/// <param name="parametername"></param>
|
||||||
/// <param name="filterGroup"></param>
|
/// <param name="queryObject"></param>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ISugarQueryable<T> GenerateFilter<T>(this ISugarQueryable<T> query, string parametername,
|
public static ISugarQueryable<T> GenerateFilter<T>(this ISugarQueryable<T> query, string parametername,
|
||||||
FilterGroup filterGroup)
|
QueryObject queryObject)
|
||||||
{
|
{
|
||||||
var param = CreateLambdaParam<T>(parametername);
|
var param = CreateLambdaParam<T>(parametername);
|
||||||
Expression result = ConvertGroup<T>(filterGroup, param);
|
Expression result = ConvertGroup<T>(queryObject, param);
|
||||||
query = query.Where(param.GenerateTypeLambda<T>(result));
|
query = query.Where(param.GenerateTypeLambda<T>(result));
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
@@ -230,62 +230,62 @@ namespace Infrastructure
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换filtergroup为表达式
|
/// 转换filtergroup为表达式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filterGroup"></param>
|
/// <param name="queryObject"></param>
|
||||||
/// <param name="param"></param>
|
/// <param name="param"></param>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <returns></returns>
|
/// <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 result = ConvertFilters<T>(queryObject.Filters, param, queryObject.Operation);
|
||||||
Expression gresult = ConvertGroup<T>(filterGroup.Children, param, filterGroup.Operation);
|
Expression gresult = ConvertGroup<T>(queryObject.Children, param, queryObject.Operation);
|
||||||
if (gresult == null) return result;
|
if (gresult == null) return result;
|
||||||
if (result == null) return gresult;
|
if (result == null) return gresult;
|
||||||
|
|
||||||
if (filterGroup.Operation == "and")
|
if (queryObject.Operation == "and")
|
||||||
{
|
{
|
||||||
return result.AndAlso(gresult);
|
return result.AndAlso(gresult);
|
||||||
}
|
}
|
||||||
else //or
|
else //or
|
||||||
{
|
{
|
||||||
return result.Or(gresult);
|
return Expression.OrElse( result, gresult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换FilterGroup[]为表达式,不管FilterGroup里面的Filters
|
/// 转换FilterGroup[]为表达式,不管FilterGroup里面的Filters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="groups"></param>
|
/// <param name="queryObjs"></param>
|
||||||
/// <param name="param"></param>
|
/// <param name="param"></param>
|
||||||
/// <param name="operation"></param>
|
/// <param name="operation"></param>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <returns></returns>
|
/// <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")
|
if (operation == "and")
|
||||||
{
|
{
|
||||||
foreach (var filter in groups.Skip(1))
|
foreach (var filter in queryObjs.Skip(1))
|
||||||
{
|
{
|
||||||
result = result.AndAlso(ConvertGroup<T>(filter, param));
|
result = result.AndAlso(ConvertGroup<T>(filter, param));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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))
|
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
|
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
|
public class Filter
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 过滤条件的关键字。
|
||||||
|
/// </summary>
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通常为值,如:yubaolee、10、10,20,30等。
|
||||||
|
/// </summary>
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通常为运算符,如:==、contains、in、intersect等。
|
||||||
|
/// </summary>
|
||||||
public string Contrast { get; set; }
|
public string Contrast { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对于特殊值的说明
|
||||||
|
/// </summary>
|
||||||
public string Text { get; set; }
|
public string Text { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FilterGroup
|
/// <summary>
|
||||||
|
/// 查询对象类,用于封装查询条件。
|
||||||
|
/// </summary>
|
||||||
|
public class QueryObject
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// or /and
|
/// 操作类型,定义了查询条件之间的逻辑关系,如OR、AND。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 该属性决定了如何组合多个过滤条件,以构建复杂的查询逻辑。
|
||||||
|
/// </remarks>
|
||||||
public string Operation { get; set; }
|
public string Operation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 过滤器数组,包含一组过滤条件。
|
||||||
|
/// </summary>
|
||||||
public Filter[] Filters { get; set; }
|
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]
|
[Test]
|
||||||
public void Convert()
|
public void Convert()
|
||||||
{
|
{
|
||||||
FilterGroup sub = new FilterGroup
|
QueryObject sub = new QueryObject
|
||||||
{
|
{
|
||||||
Operation = "or"
|
Operation = "or"
|
||||||
};
|
};
|
||||||
@@ -19,22 +19,22 @@ namespace Infrastructure.Test
|
|||||||
new Filter {Key = "c3", Value = "10,20,30", Contrast = "in"}
|
new Filter {Key = "c3", Value = "10,20,30", Contrast = "in"}
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterGroup filterGroup = new FilterGroup
|
QueryObject queryObject = new QueryObject
|
||||||
{
|
{
|
||||||
Operation = "and"
|
Operation = "and"
|
||||||
};
|
};
|
||||||
filterGroup.Filters = new[]
|
queryObject.Filters = new[]
|
||||||
{
|
{
|
||||||
new Filter {Key = "c1", Value = "name", Contrast = "contains"},
|
new Filter {Key = "c1", Value = "name", Contrast = "contains"},
|
||||||
new Filter {Key = "10,20,30", Value = "40", Contrast = "intersect"}
|
new Filter {Key = "10,20,30", Value = "40", Contrast = "intersect"}
|
||||||
};
|
};
|
||||||
|
|
||||||
filterGroup.Children = new[]
|
queryObject.Children = new[]
|
||||||
{
|
{
|
||||||
sub
|
sub
|
||||||
};
|
};
|
||||||
|
|
||||||
var expression = DynamicLinq.ConvertGroup<TestOjb>(filterGroup,
|
var expression = DynamicLinq.ConvertGroup<TestOjb>(queryObject,
|
||||||
Expression.Parameter(typeof(TestOjb), "c"));
|
Expression.Parameter(typeof(TestOjb), "c"));
|
||||||
|
|
||||||
Console.WriteLine(expression.ToString());
|
Console.WriteLine(expression.ToString());
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace OpenAuth.App
|
|||||||
string.Join(',',orgs));
|
string.Join(',',orgs));
|
||||||
}
|
}
|
||||||
return UnitWork.Find<T>(null).GenerateFilter(parametername,
|
return UnitWork.Find<T>(null).GenerateFilter(parametername,
|
||||||
JsonHelper.Instance.Deserialize<FilterGroup>(rule.PrivilegeRules));
|
JsonHelper.Instance.Deserialize<QueryObject>(rule.PrivilegeRules));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace OpenAuth.App
|
|||||||
string.Join(',',orgs));
|
string.Join(',',orgs));
|
||||||
}
|
}
|
||||||
return SugarClient.Queryable<T>().GenerateFilter(parametername,
|
return SugarClient.Queryable<T>().GenerateFilter(parametername,
|
||||||
JsonHelper.Instance.Deserialize<FilterGroup>(rule.PrivilegeRules));
|
JsonHelper.Instance.Deserialize<QueryObject>(rule.PrivilegeRules));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ using System.Linq.Expressions;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Infrastructure.Const;
|
using Infrastructure.Const;
|
||||||
|
using Infrastructure.Extensions;
|
||||||
using Infrastructure.Helpers;
|
using Infrastructure.Helpers;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
@@ -136,8 +137,16 @@ namespace OpenAuth.App
|
|||||||
{
|
{
|
||||||
var t = Type.GetType("OpenAuth.App." + flowInstance.DbName + "App");
|
var t = Type.GetType("OpenAuth.App." + flowInstance.DbName + "App");
|
||||||
ICustomerForm icf = (ICustomerForm) _serviceProvider.GetService(t);
|
ICustomerForm icf = (ICustomerForm) _serviceProvider.GetService(t);
|
||||||
|
try
|
||||||
|
{
|
||||||
icf.Add(flowInstance.Id, flowInstance.FrmData);
|
icf.Add(flowInstance.Id, flowInstance.FrmData);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("流程表单数据解析失败,请检查表单是否填写完整");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//如果工作流配置的表单配置有对应的数据库
|
//如果工作流配置的表单配置有对应的数据库
|
||||||
if (!string.IsNullOrEmpty(form.DbName))
|
if (!string.IsNullOrEmpty(form.DbName))
|
||||||
@@ -616,7 +625,10 @@ namespace OpenAuth.App
|
|||||||
//当审批流程时,能进到这里,表明当前登录用户已经有审批当前节点的权限,完全可以直接用登录用户的直接上级
|
//当审批流程时,能进到这里,表明当前登录用户已经有审批当前节点的权限,完全可以直接用登录用户的直接上级
|
||||||
var user = _auth.GetCurrentUser().User;
|
var user = _auth.GetCurrentUser().User;
|
||||||
var parentId = _userManagerApp.GetParent(user.Id);
|
var parentId = _userManagerApp.GetParent(user.Id);
|
||||||
|
if (StringExtension.IsNullOrEmpty(parentId))
|
||||||
|
{
|
||||||
|
throw new Exception("无法找到当前用户的直属上级");
|
||||||
|
}
|
||||||
makerList = GenericHelpers.ArrayToString(new[]{parentId}, makerList);
|
makerList = GenericHelpers.ArrayToString(new[]{parentId}, makerList);
|
||||||
}
|
}
|
||||||
else if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_CHAIRMAN)
|
else if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_CHAIRMAN)
|
||||||
@@ -825,7 +837,7 @@ namespace OpenAuth.App
|
|||||||
// 加入搜索自定义标题
|
// 加入搜索自定义标题
|
||||||
if (!string.IsNullOrEmpty(request.key))
|
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();
|
result.count = await UnitWork.Find(waitExp).CountAsync();
|
||||||
@@ -859,7 +871,7 @@ namespace OpenAuth.App
|
|||||||
// 加入搜索自定义标题
|
// 加入搜索自定义标题
|
||||||
if (!string.IsNullOrEmpty(request.key))
|
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();
|
result.count = await UnitWork.Find(myFlowExp).CountAsync();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace OpenAuth.App.Test
|
|||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
|
|
||||||
var cachemock = new Mock<ICacheContext>();
|
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);
|
services.AddScoped(x => cachemock.Object);
|
||||||
|
|
||||||
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
|
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
|
||||||
@@ -37,7 +37,7 @@ namespace OpenAuth.App.Test
|
|||||||
{
|
{
|
||||||
var app = _autofacServiceProvider.GetService<ResourceApp>();
|
var app = _autofacServiceProvider.GetService<ResourceApp>();
|
||||||
var result = app.Load(new QueryResourcesReq());
|
var result = app.Load(new QueryResourcesReq());
|
||||||
Console.WriteLine(JsonHelper.Instance.Serialize(result));
|
Console.WriteLine(JsonHelper.Instance.Serialize(result.Result));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -46,7 +46,7 @@ namespace OpenAuth.App.Test
|
|||||||
var auth = _autofacServiceProvider.GetService<IAuth>();
|
var auth = _autofacServiceProvider.GetService<IAuth>();
|
||||||
var app = _autofacServiceProvider.GetService<DataPrivilegeRuleApp>();
|
var app = _autofacServiceProvider.GetService<DataPrivilegeRuleApp>();
|
||||||
//该测试解析为:针对资源列表,【管理员】可以看到所有,角色为【神】或【测试】的只能看到自己创建的
|
//该测试解析为:针对资源列表,【管理员】可以看到所有,角色为【神】或【测试】的只能看到自己创建的
|
||||||
var filterGroup = new FilterGroup
|
var filterGroup = new QueryObject
|
||||||
{
|
{
|
||||||
Operation = "or"
|
Operation = "or"
|
||||||
};
|
};
|
||||||
@@ -61,7 +61,7 @@ namespace OpenAuth.App.Test
|
|||||||
};
|
};
|
||||||
filterGroup.Children = new[]
|
filterGroup.Children = new[]
|
||||||
{
|
{
|
||||||
new FilterGroup //登录用户角色包含【测试】或包含【神】的,只能看到自己的
|
new QueryObject //登录用户角色包含【测试】或包含【神】的,只能看到自己的
|
||||||
{
|
{
|
||||||
Operation = "and",
|
Operation = "and",
|
||||||
Filters = new Filter[]
|
Filters = new Filter[]
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
var _hmt = _hmt || [];
|
var _hmt = _hmt || [];
|
||||||
(function () {
|
(function () {
|
||||||
var hm = document.createElement("script");
|
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];
|
var s = document.getElementsByTagName("script")[0];
|
||||||
s.parentNode.insertBefore(hm, s);
|
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 || [];
|
var _hmt = _hmt || [];
|
||||||
(function () {
|
(function () {
|
||||||
var hm = document.createElement("script");
|
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];
|
var s = document.getElementsByTagName("script")[0];
|
||||||
s.parentNode.insertBefore(hm, s);
|
s.parentNode.insertBefore(hm, s);
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ namespace OpenAuth.Repository.Domain
|
|||||||
/// 前端界面是否缓存
|
/// 前端界面是否缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// [Description("前端界面是否缓存")]
|
/// [Description("前端界面是否缓存")]
|
||||||
public bool KeepAlive { get; set; }
|
public bool? KeepAlive { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ namespace OpenAuth.Repository.Test
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestDynamic()
|
public void TestDynamic()
|
||||||
{
|
{
|
||||||
FilterGroup sub = new FilterGroup
|
QueryObject sub = new QueryObject
|
||||||
{
|
{
|
||||||
Operation = "or"
|
Operation = "or"
|
||||||
};
|
};
|
||||||
@@ -69,24 +69,24 @@ namespace OpenAuth.Repository.Test
|
|||||||
new Filter {Key = "Sex", Value = "10", Contrast = "=="}
|
new Filter {Key = "Sex", Value = "10", Contrast = "=="}
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterGroup filterGroup = new FilterGroup
|
QueryObject queryObject = new QueryObject
|
||||||
{
|
{
|
||||||
Operation = "and"
|
Operation = "and"
|
||||||
};
|
};
|
||||||
filterGroup.Filters = new[]
|
queryObject.Filters = new[]
|
||||||
{
|
{
|
||||||
new Filter {Key = "Account", Value = "name", Contrast = "=="},
|
new Filter {Key = "Account", Value = "name", Contrast = "=="},
|
||||||
new Filter {Key = "Password", Value = "10", Contrast = "=="}
|
new Filter {Key = "Password", Value = "10", Contrast = "=="}
|
||||||
};
|
};
|
||||||
|
|
||||||
filterGroup.Children = new[]
|
queryObject.Children = new[]
|
||||||
{
|
{
|
||||||
sub
|
sub
|
||||||
};
|
};
|
||||||
|
|
||||||
var dbcontext = _autofacServiceProvider.GetService<OpenAuthDBContext>();
|
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());
|
Console.WriteLine(query.Expression.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace OpenAuth.Repository.Test
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestDynamic()
|
public void TestDynamic()
|
||||||
{
|
{
|
||||||
FilterGroup sub = new FilterGroup
|
QueryObject sub = new QueryObject
|
||||||
{
|
{
|
||||||
Operation = "or"
|
Operation = "or"
|
||||||
};
|
};
|
||||||
@@ -83,24 +83,24 @@ namespace OpenAuth.Repository.Test
|
|||||||
new Filter {Key = "Sex", Value = "10", Contrast = "=="}
|
new Filter {Key = "Sex", Value = "10", Contrast = "=="}
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterGroup filterGroup = new FilterGroup
|
QueryObject queryObject = new QueryObject
|
||||||
{
|
{
|
||||||
Operation = "and"
|
Operation = "and"
|
||||||
};
|
};
|
||||||
filterGroup.Filters = new[]
|
queryObject.Filters = new[]
|
||||||
{
|
{
|
||||||
new Filter {Key = "Account", Value = "name", Contrast = "=="},
|
new Filter {Key = "Account", Value = "name", Contrast = "=="},
|
||||||
new Filter {Key = "Password", Value = "10", Contrast = "=="}
|
new Filter {Key = "Password", Value = "10", Contrast = "=="}
|
||||||
};
|
};
|
||||||
|
|
||||||
filterGroup.Children = new[]
|
queryObject.Children = new[]
|
||||||
{
|
{
|
||||||
sub
|
sub
|
||||||
};
|
};
|
||||||
|
|
||||||
var sugarClient = _autofacServiceProvider.GetService<ISqlSugarClient>();
|
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());
|
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等)。核心模块包括:角色授权、代码生成、智能打印、表单设计、工作流、定时任务等。架构易扩展,是中小企业的首选。
|
🔥.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字母的结合体;整体像鱼,授人以渔;你非说像咸鱼,那也是积极向上的咸鱼;中心是个笑脸,微笑面对生活(✿◡‿◡)。
|
**logo图标含义** OpenAuth中OA字母的结合体;整体像鱼,授人以渔;你非说像咸鱼,那也是积极向上的咸鱼;中心是个笑脸,微笑面对生活(✿◡‿◡)。
|
||||||
@@ -21,7 +8,6 @@
|
|||||||
|
|
||||||
**官方文档** http://doc.openauth.net.cn
|
**官方文档** 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企业版/高级版的说明:
|
## 关于OpenAuth.Net企业版/高级版的说明:
|
||||||
|
|||||||
@@ -39,11 +39,18 @@ CodeSmith Generator Studio 8.0或以上
|
|||||||
|
|
||||||
如下图,使用CodeSmith文件夹中的模板,右击【ApiGenerate.cst】--【Execute】,选择需要生成的表(本文以Stock为例)及相关的上下文命名空间,点击【Generate】
|
如下图,使用CodeSmith文件夹中的模板,右击【ApiGenerate.cst】--【Execute】,选择需要生成的表(本文以Stock为例)及相关的上下文命名空间,点击【Generate】
|
||||||
|
|
||||||

|

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

|

|
||||||
|
|
||||||
把CSharp\OpenAuth.App覆盖到自己项目对应目录
|
把CSharp\OpenAuth.App覆盖到自己项目对应目录
|
||||||
|
|
||||||
@@ -51,7 +58,6 @@ CodeSmith Generator Studio 8.0或以上
|
|||||||
|
|
||||||
**把CSharp\OpenAuth.Repository\OpenAuthDBContext.cs中的内容添加到自己项目的文件中,千万不要直接覆盖文件!!!**
|
**把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系列教学视频
|
||||||
|
|
||||||
[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生成代码时的两个概念:动态头部和固定头部
|
在添加新功能之前,需要先了解OpenAuth.Net生成代码时的两个概念:动态头部和固定头部
|
||||||
@@ -49,17 +51,21 @@ initCfg() {
|
|||||||
-- mysql示例
|
-- mysql示例
|
||||||
create table stock
|
create table stock
|
||||||
(
|
(
|
||||||
createtime datetime not null comment '操作时间',
|
Id varchar(50) not null comment '数据ID'
|
||||||
status int not null comment '出库/入库',
|
primary key,
|
||||||
price decimal(10, 1) not null comment '产品单价',
|
Name text not null comment '产品名称',
|
||||||
number int not null comment '产品数量',
|
Number int not null comment '产品数量',
|
||||||
name text not null comment '产品名称',
|
Price decimal(10, 1) not null comment '产品单价',
|
||||||
orgid varchar(50) null comment '组织ID',
|
Status int not null comment '出库/入库',
|
||||||
user varchar(50) not null comment '操作人',
|
Viewable varchar(50) not null comment '可见范围',
|
||||||
viewable varchar(50) not null comment '可见范围',
|
User varchar(50) not null comment '操作人',
|
||||||
id varchar(50) not null comment '数据ID'
|
Time datetime not null comment '操作时间',
|
||||||
primary key
|
OrgId varchar(50) null comment '组织ID'
|
||||||
)
|
)
|
||||||
|
comment '出入库信息表' charset = utf8
|
||||||
|
row_format = COMPACT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user