64 Commits
7.5 ... 7.7

Author SHA1 Message Date
wintel
3747773685 docs: 完善自定义查询文档 2025-05-07 20:58:02 +08:00
wintel
7c0107f78e docs: 增加表格组件文档 2025-05-07 20:34:10 +08:00
wintel
ce01dca5c3 docs: 增加列设置文档 2025-05-07 20:30:31 +08:00
wintel
f7bd7e22b4 docs: 增加vue3自定义查询组件文档 2025-05-07 19:26:07 +08:00
yubaolee
985f898d88 fix: 入库单调整为sqlsugar后主从表关联处理 2025-05-07 17:35:27 +08:00
yubaolee
e8b85fc05a feat: 入库订单调整为sqlsugar,并支持自定义查询 2025-05-07 16:15:42 +08:00
wintel
a978fa7e22 Merge commit '576ff6e98a0d443519620c7b1d1ff9d01bfc86c6' into main 2025-05-06 22:27:43 +08:00
wintel
576ff6e98a feat: 增加高级查询 2025-05-06 21:15:47 +08:00
wintel
032f5551dc Merge branch 'main' of https://gitee.com/dotnetchina/OpenAuth.Net into main 2025-04-29 19:08:01 +08:00
yubaolee
a28458347a feat: 增加低代码平台脚本 2025-04-29 17:15:43 +08:00
yubaolee
3def1e6bfc chore: 增加cursor mcp Servers支持 2025-04-29 15:51:04 +08:00
wintel
a42b2dcb7c docs: update doc 2025-04-26 16:19:44 +08:00
wintel
89fe623a72 docs: 增加右下角导航;
调整identity显示级别
2025-04-26 15:04:49 +08:00
wintel
107e297e01 docs: update doc 2025-04-26 11:57:13 +08:00
wintel
8c129d6746 docs: 更新文档 2025-04-25 00:05:19 +08:00
wintel
688caa324b docs: update startflow.md 2025-04-24 23:40:36 +08:00
wintel
a6fdf4e6ce docs: 更新打印文档 2025-04-24 23:24:14 +08:00
wintel
b583b2adbf docs: 删除docs 2025-04-24 23:21:31 +08:00
wintel
17e426c785 docs: update doc 2025-04-24 23:16:06 +08:00
yubaolee
85497a544a docs: update router 2025-04-24 15:06:59 +08:00
yubaolee
aa7056bfb3 docs: update devnew 2025-04-24 15:02:55 +08:00
yubaolee
9653778c77 docs: update deploy 2025-04-24 14:29:56 +08:00
yubaolee
59a099b607 docs: add start 2025-04-24 10:40:15 +08:00
yubaolee
bf9be59a84 docs: 修复文档链接 2025-04-24 10:34:58 +08:00
wintel
c7ff40615b fix: svg 2025-04-24 02:01:33 +08:00
wintel
61240b6f16 docs: update home 2025-04-24 01:51:51 +08:00
wintel
1750ff4c9e docs: 优化首页 2025-04-24 01:30:19 +08:00
wintel
700bf8dea4 docs: add iconify icon 2025-04-24 01:15:54 +08:00
wintel
dd02328033 docs: 修复图片 2025-04-24 00:36:50 +08:00
wintel
8ae512022e docs: 修复图片 2025-04-24 00:30:36 +08:00
wintel
4a3d51b13d docs: fix image 2025-04-24 00:11:40 +08:00
wintel
1926a3a09b docs: add logo 2025-04-24 00:05:33 +08:00
wintel
ca8b2a82c4 docs: 更新文档标题 2025-04-24 00:03:31 +08:00
wintel
1525a25aba docs: 增加vue3、vue2文档 2025-04-23 23:58:54 +08:00
wintel
2b0979dc88 Merge branch 'main' of https://gitee.com/dotnetchina/OpenAuth.Net into main 2025-04-23 23:38:07 +08:00
wintel
918b6a53d4 docs: 全新文档 2025-04-23 23:37:58 +08:00
yubaolee
1e2cfcb208 fix: 紧急修复待办列表数据异常 2025-04-21 10:56:53 +08:00
wintel
05922c77f3 docs: update doc 2025-04-20 20:59:44 +08:00
wintel
346d0e9d5d chore: 完善注释 2025-04-19 23:09:27 +08:00
wintel
df83cde075 docs: update devnew.md 2025-04-19 23:07:57 +08:00
wintel
390ab89dff docs: update flowinstance.md 2025-04-19 22:47:19 +08:00
wintel
757d86a765 fix #IC2GBH 流程审批页面显示不出数据 2025-04-19 22:44:15 +08:00
wintel
8d6e1e5a65 docs: 完善文档 2025-04-19 18:21:03 +08:00
wintel
3895a16942 docs: update startflow.md 2025-04-19 13:00:59 +08:00
wintel
8027c7b5bb docs: 完善工作流文档 2025-04-19 11:40:59 +08:00
wintel
263ff70f26 fix: 修复顺序审批时,节点审批人为全部加签的异常 2025-04-19 00:31:19 +08:00
yubaolee
d5249d8cb3 fix: 修复会签节点审批 2025-04-18 17:33:36 +08:00
wintel
3eb94d7f21 feat: 分离会签和网关功能 2025-04-17 23:37:50 +08:00
wintel
1b0a9193d1 refactor: 将会签->网关 2025-04-17 21:47:28 +08:00
yubaolee
b5bb518bd2 refactor: 修改approvetype类型 2025-04-17 17:20:23 +08:00
yubaolee
8359e21fdd refactor: 调整历史记录的fromnodetype/tonodetype 2025-04-17 15:10:03 +08:00
yubaolee
831053aaf1 refactor: 流程模板end round 切换为end
统一判断流程结束
          流程节点类型统一用字符串表示
2025-04-17 14:44:57 +08:00
yubaolee
d32ef5b78d refactor: 去掉流程实例的ActivityType,重构节点类型相关代码 2025-04-17 13:55:26 +08:00
wintel
ac72a26313 refactor: 优化代码结构 2025-04-17 00:05:49 +08:00
wintel
daf7273537 docs: update flowinstancestatus.md 2025-04-16 22:47:30 +08:00
wintel
9117e88e3e Merge branch 'main' of https://gitee.com/dotnetchina/OpenAuth.Net into main 2025-04-16 00:04:10 +08:00
wintel
964ccb0d0b docs: 更新代码生成器文档 2025-04-16 00:04:04 +08:00
yubaolee
612f60f1b6 docs: update doc 2025-04-15 13:36:47 +08:00
yubaolee
39f5b9790c docs: update doc 2025-04-15 12:29:42 +08:00
yubaolee
3693a9dc44 fix: 修复点击选中行 2025-04-14 15:58:09 +08:00
wintel
77445b7197 docs: update README.md 2025-04-13 11:45:06 +08:00
李玉宝
24d383cdb0 update README.md.
Signed-off-by: 李玉宝 <yubaolee@163.com>
2025-04-13 03:43:22 +00:00
wintel
9255a91669 chore: 优化底部样式 2025-04-13 11:30:46 +08:00
wintel
33a5293ee1 refactor: 删除treetable css 2025-04-13 10:46:05 +08:00
182 changed files with 3710 additions and 1537 deletions

29
.cursor/mcp.json Normal file
View File

@@ -0,0 +1,29 @@
{
"mcpServers": {
"PostgreSQL": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://postgres:AwxBRx1_5kljfy@172.30.144.46/openauthpro"
],
"env": {}
},
"mysql": {
"type": "stdio",
"command": "uvx",
"args": [
"--from",
"mysql-mcp-server",
"mysql_mcp_server"
],
"env": {
"MYSQL_HOST": "localhost",
"MYSQL_PORT": "3306",
"MYSQL_USER": "root",
"MYSQL_PASSWORD": "000000",
"MYSQL_DATABASE": "openauthpro"
}
}
}
}

View File

@@ -14,7 +14,7 @@ Description="连接的数据库" %>
<%@ Import Namespace="Util" %>
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
}
<blockquote class="layui-elem-quote news_search toolList" id="menus">
</blockquote>

View File

@@ -5,47 +5,247 @@
/// </summary>
public static class Define
{
public static string USERROLE = "UserRole"; //用户角色关联KEY
public const string ROLERESOURCE = "RoleResource"; //角色资源关联KEY
public const string USERORG = "UserOrg"; //用户机构关联KEY
public const string ROLEELEMENT = "RoleElement"; //角色菜单关联KEY
public const string ROLEMODULE = "RoleModule"; //角色模块关联KEY
public const string ROLEDATAPROPERTY = "RoleDataProperty"; //角色数据字段权限
public const string MODULEPRINTERPLAN = "ModulePrinterPlan"; //模块配置打印方案
public const string MODULE_FLOWSCHEME = "ModuleFlowScheme"; //模块挂载流程模板
//Relevance关联KEY
/// <summary>
/// 用户角色关联KEY
/// </summary>
public static string USERROLE = "UserRole";
/// <summary>
/// 角色资源关联KEY
/// </summary>
public const string ROLERESOURCE = "RoleResource";
/// <summary>
/// 用户机构关联KEY
/// </summary>
public const string USERORG = "UserOrg";
/// <summary>
/// 角色菜单关联KEY
/// </summary>
public const string ROLEELEMENT = "RoleElement";
/// <summary>
/// 角色模块关联KEY
/// </summary>
public const string ROLEMODULE = "RoleModule";
/// <summary>
/// 角色数据字段权限
/// </summary>
public const string ROLEDATAPROPERTY = "RoleDataProperty";
/// <summary>
/// 模块配置打印方案
/// </summary>
public const string MODULEPRINTERPLAN = "ModulePrinterPlan";
/// <summary>
/// 模块挂载流程模板
/// </summary>
public const string MODULE_FLOWSCHEME = "ModuleFlowScheme";
public const string DBTYPE_SQLSERVER = "SqlServer"; //sql server
public const string DBTYPE_MYSQL = "MySql"; //mysql
public const string DBTYPE_PostgreSQL = "PostgreSQL"; //PostgreSQL
public const string DBTYPE_ORACLE = "Oracle"; //oracle
//数据库类型
/// <summary>
/// 数据库类型SQL Server
/// </summary>
public const string DBTYPE_SQLSERVER = "SqlServer";
/// <summary>
/// 数据库类型MySQL
/// </summary>
public const string DBTYPE_MYSQL = "MySql";
/// <summary>
/// 数据库类型PostgreSQL
/// </summary>
public const string DBTYPE_PostgreSQL = "PostgreSQL";
/// <summary>
/// 数据库类型Oracle
/// </summary>
public const string DBTYPE_ORACLE = "Oracle";
public const int INVALID_TOKEN = 50014; //token无效
/// <summary>
/// Token无效错误码50014
/// </summary>
public const int INVALID_TOKEN = 50014;
/// <summary>
/// Token名称用于HTTP请求头
/// </summary>
public const string TOKEN_NAME = "X-Token";
/// <summary>
/// 租户ID标识
/// </summary>
public const string TENANT_ID = "tenantId";
/// <summary>
/// 系统用户名
/// </summary>
public const string SYSTEM_USERNAME = "System";
/// <summary>
/// 系统用户默认密码
/// </summary>
public const string SYSTEM_USERPWD = "123456";
public const string DATAPRIVILEGE_LOGINUSER = "{loginUser}"; //数据权限配置中当前登录用户的key
public const string DATAPRIVILEGE_LOGINROLE = "{loginRole}"; //数据权限配置中,当前登录用户角色的key
public const string DATAPRIVILEGE_LOGINORG = "{loginOrg}"; //数据权限配置中当前登录用户部门的key
/// <summary>
/// 数据权限配置中当前登录用户的key
/// </summary>
public const string DATAPRIVILEGE_LOGINUSER = "{loginUser}";
/// <summary>
/// 数据权限配置中当前登录用户角色的key
/// </summary>
public const string DATAPRIVILEGE_LOGINROLE = "{loginRole}";
/// <summary>
/// 数据权限配置中当前登录用户部门的key
/// </summary>
public const string DATAPRIVILEGE_LOGINORG = "{loginOrg}";
/// <summary>
/// 任务调度映射键
/// </summary>
public const string JOBMAPKEY = "OpenJob";
/// <summary>
/// 默认表单实例ID字段名
/// </summary>
public const string DEFAULT_FORM_INSTANCE_ID_NAME = "InstanceId";
//流程实例知会用户
//表单类型
/// <summary>
/// 表单类型:动态表单(0)
/// </summary>
public const int FORM_TYPE_DYNAMIC = 0;
/// <summary>
/// 表单类型:自定义表单(1)
/// </summary>
public const int FORM_TYPE_DEVELOP = 1;
/// <summary>
/// 表单类型vForm拖拽表单(2)
/// </summary>
public const int FORM_TYPE_DRAG = 2;
/// <summary>
/// 表单类型URL表单(3)
/// </summary>
public const int FORM_TYPE_URL = 3;
//节点类型
/// <summary>
/// 节点类型:开始节点
/// </summary>
public const string NODE_TYPE_START = "start";
/// <summary>
/// 节点类型:结束节点
/// </summary>
public const string NODE_TYPE_END = "end";
/// <summary>
/// 节点类型:任务节点
/// </summary>
public const string NODE_TYPE_TASK = "node";
/// <summary>
/// 节点类型:网关开始
/// </summary>
public const string NODE_TYPE_FORK = "fork";
/// <summary>
/// 节点类型:网关结束
/// </summary>
public const string NODE_TYPE_JOIN = "join";
/// <summary>
/// 节点类型:多实例、会签节点
/// </summary>
public const string NODE_TYPE_MULTI_INSTANCE = "multiInstance";
/// <summary>
/// 流程实例知会用户
/// </summary>
public const string INSTANCE_NOTICE_USER = "INSTANCE_NOTICE_USER";
//流程实例知会角色
/// <summary>
/// 流程实例知会角色
/// </summary>
public const string INSTANCE_NOTICE_ROLE = "INSTANCE_NOTICE_ROLE";
//表单类型
public const int FORM_TYPE_DYNAMIC = 0; //动态表单
public const int FORM_TYPE_DEVELOP = 1; //自定义表单
public const int FORM_TYPE_DRAG = 2; //vForm拖拽表单
public const int FORM_TYPE_URL = 3; //URL表单
//流程节点执行权限类型
/// <summary>
/// 流程节点执行权限类型:所有用户
/// </summary>
public const string ALL_USER = "ALL_USER";
/// <summary>
/// 流程节点执行权限类型:指定角色
/// </summary>
public const string SPECIAL_ROLE = "SPECIAL_ROLE";
/// <summary>
/// 流程节点执行权限类型:指定用户
/// </summary>
public const string SPECIAL_USER = "SPECIAL_USER";
/// <summary>
/// 流程节点执行权限类型指定SQL
/// </summary>
public const string SPECIAL_SQL = "SPECIAL_SQL";
/// <summary>
/// 连续多级直属上级
/// <para>不同于钉钉的各上级部门负责人审批OpenAuth以用户的各级直属上级审批模式</para>
/// </summary>
public const string RUNTIME_MANY_PARENTS = "RUNTIME_MANY_PARENTS";
/// <summary>
/// 部门负责人
/// </summary>
public const string RUNTIME_CHAIRMAN = "RUNTIME_CHAIRMAN";
/// <summary>
/// 上一节点执行人的直属上级
/// </summary>
public const string RUNTIME_PARENT = "RUNTIME_PARENT";
/// <summary>
/// 流程节点执行权限类型:运行时指定角色
/// </summary>
public const string RUNTIME_SPECIAL_ROLE = "RUNTIME_SPECIAL_ROLE";
/// <summary>
/// 流程节点执行权限类型:运行时指定用户
/// </summary>
public const string RUNTIME_SPECIAL_USER = "RUNTIME_SPECIAL_USER";
//加签类型
/// <summary>
/// 加签类型:顺序审批
/// </summary>
public const string APPROVE_TYPE_SEQUENTIAL = "sequential";
/// <summary>
/// 加签类型:并行且审批(所有人必须同意)
/// </summary>
public const string APPROVE_TYPE_ALL = "all";
/// <summary>
/// 加签类型:并行或审批(一人同意即可)
/// </summary>
public const string APPROVE_TYPE_ONE = "one";
/// <summary>
/// API资源标识
/// </summary>
public const string API = "API_RESOURCE";
}
}

View File

@@ -15,6 +15,11 @@
public string key { get; set; }
/// <summary>
/// 自定义sql条件
/// </summary>
public string sqlWhere { get; set; }
public PageReq()
{
page = 1;

View File

@@ -569,6 +569,9 @@ namespace OpenAuth.App
{
return "DateTime.Now";
}
else if (type == "bool"){
return "false";
}
return Activator.CreateInstance(t).ToString();
}

View File

@@ -32,6 +32,10 @@ namespace OpenAuth.App
{
objs = objs.Where(u => u.Name.Contains(request.key));
}
if (!string.IsNullOrEmpty(request.sqlWhere))
{
objs = objs.Where(request.sqlWhere);
}
result.data = objs.OrderBy(u => u.Name)
.Skip((request.page - 1) * request.limit)

View File

@@ -5,11 +5,6 @@
/// </summary>
public class FlowNode
{
public const string START = "start round mix";
public const string END = "end round";
public const string NODE = "node";
public const string FORK = "fork"; //会签开始节点
public const string JOIN = "join"; //会签结束节点
public string id { get; set; }
@@ -32,27 +27,7 @@
public class Setinfo
{
public const string ALL_USER = "ALL_USER"; //所有用户
public const string SPECIAL_ROLE = "SPECIAL_ROLE"; //指定角色
public const string SPECIAL_USER = "SPECIAL_USER"; //指定用户
public const string SPECIAL_SQL = "SPECIAL_SQL"; //指定SQL
/// <summary>
/// 连续多级直属上级
/// <para>不同于钉钉的各上级部门负责人审批OpenAuth以用户的各级直属上级审批模式</para>
/// </summary>
public const string RUNTIME_MANY_PARENTS = "RUNTIME_MANY_PARENTS";
/// <summary>
/// 部门负责人
/// </summary>
public const string RUNTIME_CHAIRMAN = "RUNTIME_CHAIRMAN";
/// <summary>
/// 上一节点执行人的直属上级
/// </summary>
public const string RUNTIME_PARENT = "RUNTIME_PARENT";
public const string RUNTIME_SPECIAL_ROLE = "RUNTIME_SPECIAL_ROLE"; //运行时指定角色
public const string RUNTIME_SPECIAL_USER = "RUNTIME_SPECIAL_USER"; //运行时指定用户
/// <summary>
/// 节点执行权限类型
/// </summary>
@@ -78,18 +53,18 @@
public string Description { get; set; }
public string TagedTime { get; set; }
//节点会签方式,
//网关审批通过的方式,
//all/空:默认为全部通过
//one :至少有一个通过
public string NodeConfluenceType { get; set; }
/// <summary>
/// 会签通过的个数
/// 网关通过的个数
/// </summary>
public int? ConfluenceOk { get; set; }
/// <summary>
/// 会签拒绝的个数
/// 网关拒绝的个数
/// </summary>
public int? ConfluenceNo { get; set; }

View File

@@ -33,23 +33,21 @@ namespace OpenAuth.App.Flow
InitNodes(schemeContentJson);
currentNodeId = instance.ActivityId == "" ? startNodeId : instance.ActivityId;
currentNodeType = GetNodeType(currentNodeId);
FrmData = instance.FrmData;
title = schemeContentJson.title;
initNum = schemeContentJson.initNum ?? 0;
previousId = instance.PreviousId;
flowInstanceId = instance.Id;
//会签开始节点和流程结束节点没有下一步
if (currentNodeType == 0 || currentNodeType == 4)
//网关开始节点和流程结束节点没有下一步
if (GetCurrentNodeType() == Define.NODE_TYPE_FORK
|| GetCurrentNodeType() == Define.NODE_TYPE_END)
{
nextNodeId = "-1";
nextNodeType = -1;
}
else
{
nextNodeId = GetNextNodeId(); //下一个节点
nextNodeType = GetNodeType(nextNodeId);
}
}
@@ -71,7 +69,7 @@ namespace OpenAuth.App.Flow
Nodes.Add(node.id, node);
}
if (node.type == FlowNode.START)
if (node.type == Define.NODE_TYPE_START)
{
this.startNodeId = node.id;
}
@@ -120,9 +118,9 @@ namespace OpenAuth.App.Flow
{
throw new Exception("无法寻找到下一个节点");
}
//URL表单暂时不支持URL表单
if(flowInstance.FrmType == Define.FORM_TYPE_URL) return lines[0].to;
if (flowInstance.FrmType == Define.FORM_TYPE_URL) return lines[0].to;
if (FrmData == "" || FrmData == "{}") return lines[0].to;
@@ -144,6 +142,14 @@ namespace OpenAuth.App.Flow
#region
/// <summary>
/// 判断流程是否完成
/// </summary>
public bool IsFinish()
{
return GetNextNodeType() == Define.NODE_TYPE_END;
}
//获取下一个节点
public FlowNode GetNextNode(string nodeId = null)
{
@@ -151,64 +157,54 @@ namespace OpenAuth.App.Flow
}
/// <summary>
/// 获取实例接下来运行的状态
/// 获取实例接下来运行的节点类型
/// </summary>
/// <returns>-1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束</returns>
public int GetNextNodeType()
public string GetNextNodeType()
{
if (nextNodeId != "-1")
{
return GetNodeType(nextNodeId);
}
return -1;
return Define.NODE_TYPE_END;
}
/// <summary>
/// 获取节点类型 0会签开始,1会签结束,2一般节点,开始节点,4流程运行结束
/// 获取节点类型
/// </summary>
/// <param name="nodeId"></param>
/// <returns></returns>
public int GetNodeType(string nodeId)
public string GetNodeType(string nodeId)
{
switch (Nodes[nodeId].type)
{
//会签开始节点
case FlowNode.FORK:
return 0;
//会签结束节点
case FlowNode.JOIN:
return 1;
//结束节点
case FlowNode.END:
return 4;
//开始节点
case FlowNode.START:
return 3;
default:
return 2;
}
return Nodes[nodeId].type;
}
/// <summary>
/// 节点会签审核
/// 获取当前节点类型
/// </summary>
/// <param name="nodeId">会签时currentNodeId是会签开始节点。这个表示当前正在处理的节点</param>
/// <returns></returns>
public string GetCurrentNodeType()
{
return GetNodeType(currentNodeId);
}
/// <summary>
/// 审批网关开始节点
/// </summary>
/// <param name="nodeId">currentNodeId是网关开始节点。这个表示当前正在处理的节点</param>
/// <param name="tag"></param>
/// <returns>-1不通过,1等待,其它通过</returns>
public string NodeConfluence(HttpClient httpClient, Tag tag)
public string VerifyGatewayStart(HttpClient httpClient, Tag tag)
{
var user = AutofacContainerModule.GetService<IAuth>().GetCurrentUser().User;
//会签时的【当前节点】一直是会签开始节点
//TODO: 标记会签节点的状态,这个地方感觉怪怪的
//审批网关时的【当前节点】一直是网关开始节点
//TODO: 标记网关节点的状态,这个地方感觉怪怪的
MakeTagNode(currentNodeId, tag);
string canCheckId = ""; //寻找当前登录用户可审核的节点Id
foreach (string fromForkStartNodeId in FromNodeLines[currentNodeId]
.Select(u => u.to))
{
var fromForkStartNode = Nodes[fromForkStartNodeId]; //与会前开始节点直接连接的节点
var fromForkStartNode = Nodes[fromForkStartNodeId]; //与网关开始节点直接连接的节点
canCheckId = GetOneForkLineCanCheckNodeId(fromForkStartNode, tag);
if (!string.IsNullOrEmpty(canCheckId)) break;
}
@@ -225,18 +221,18 @@ namespace OpenAuth.App.Flow
MakeTagNode(canCheckId, tag); //标记审核节点状态
var forkNode = Nodes[currentNodeId]; //会签开始节点
var forkNode = Nodes[currentNodeId]; //网关开始节点
FlowNode nextNode = GetNextNode(canCheckId); //获取当前处理的下一个节点
int forkNumber = FromNodeLines[currentNodeId].Count; //直接与会签节点连接的点,即会签分支数目
string res = string.Empty; //记录会签的结果,默认正在会签
int forkNumber = FromNodeLines[currentNodeId].Count; //直接与网关节点连接的点,即网关分支数目
string gatewayResult = string.Empty; //记录网关审批的的结果,为空表示仍然在网关内部处理
if (forkNode.setInfo.NodeConfluenceType == "one") //有一个步骤通过即可
{
if (tag.Taged == (int)TagState.Ok)
{
if (nextNode.type == FlowNode.JOIN) //下一个节点是会签结束,则该线路结束
if (nextNode.type == Define.NODE_TYPE_JOIN) //下一个节点是网关结束,则该线路结束
{
res = GetNextNodeId(nextNode.id);
gatewayResult = GetNextNodeId(nextNode.id);
}
}
else if (tag.Taged == (int)TagState.No)
@@ -247,13 +243,13 @@ namespace OpenAuth.App.Flow
}
else if (forkNode.setInfo.ConfluenceNo == (forkNumber - 1))
{
res = TagState.No.ToString("D");
gatewayResult = TagState.No.ToString("D");
}
else
{
bool isFirst = true; //是不是从会签开始到现在第一个
bool isFirst = true; //是不是从网关开始到现在第一个
var preNode = GetPreNode(canCheckId);
while (preNode.id != forkNode.id) //反向一直到会签开始节点
while (preNode.id != forkNode.id) //反向一直到网关开始节点
{
if (preNode.setInfo != null && preNode.setInfo.Taged == (int)TagState.No)
{
@@ -269,23 +265,23 @@ namespace OpenAuth.App.Flow
}
}
}
else //默认所有步骤通过
else //所有步骤通过
{
if (tag.Taged == (int)TagState.No) //只要有一个不同意,那么流程就结束
{
res = TagState.No.ToString("D");
gatewayResult = TagState.No.ToString("D");
}
else if (tag.Taged == (int)TagState.Ok)
{
if (nextNode.type == FlowNode.JOIN) //这种模式下只有坚持到【会签结束】节点之前才有意义,是否需要判定这条线所有的节点都通过,不然直接执行这个节点??
if (nextNode.type == Define.NODE_TYPE_JOIN) //这种模式下只有坚持到【网关结束】节点之前才有意义,是否需要判定这条线所有的节点都通过,不然直接执行这个节点??
{
if (forkNode.setInfo.ConfluenceOk == null)
{
forkNode.setInfo.ConfluenceOk = 1;
}
else if (forkNode.setInfo.ConfluenceOk == (forkNumber - 1)) //会签成功
else if (forkNode.setInfo.ConfluenceOk == (forkNumber - 1)) //网关成功
{
res = GetNextNodeId(nextNode.id);
gatewayResult = GetNextNodeId(nextNode.id);
}
else
{
@@ -295,30 +291,28 @@ namespace OpenAuth.App.Flow
}
}
if (res == TagState.No.ToString("D"))
if (gatewayResult == TagState.No.ToString("D"))
{
tag.Taged = (int)TagState.No;
MakeTagNode(nextNode.id, tag);
}
else if (!string.IsNullOrEmpty(res)) //会签结束,标记合流节点
else if (!string.IsNullOrEmpty(gatewayResult)) //网关结束,标记合流节点
{
tag.Taged = (int)TagState.Ok;
MakeTagNode(nextNode.id, tag);
nextNodeId = res;
nextNodeType = GetNodeType(res);
nextNodeId = gatewayResult;
}
else
{
nextNodeId = nextNode.id;
nextNodeType = GetNodeType(nextNode.id);
}
if (!string.IsNullOrEmpty(res)) //会签结束节点配置了回调,则发起通知
if (!string.IsNullOrEmpty(gatewayResult)) //网关结束节点配置了回调,则发起通知
{
NotifyThirdParty(httpClient, nextNode, tag);
}
return res;
return gatewayResult;
}
//获取上一个节点
@@ -378,7 +372,6 @@ namespace OpenAuth.App.Flow
{
flowInstance.PreviousId = flowInstance.ActivityId;
flowInstance.ActivityId = rejectNode;
flowInstance.ActivityType = GetNodeType(rejectNode);
flowInstance.ActivityName = Nodes[rejectNode].name;
flowInstance.MakerList =
GetNodeMarkers(Nodes[rejectNode], flowInstance.CreateUserId);
@@ -386,7 +379,7 @@ namespace OpenAuth.App.Flow
}
flowInstance.SchemeContent = JsonHelper.Instance.Serialize(ToSchemeObj());
var sugarClient = AutofacContainerModule.GetService<ISqlSugarClient>();
sugarClient.Updateable(flowInstance).ExecuteCommand();
@@ -405,11 +398,10 @@ namespace OpenAuth.App.Flow
{
item.Value.setInfo = null;
}
flowInstance.IsFinish = FlowInstanceStatus.Draft;
flowInstance.PreviousId = flowInstance.ActivityId;
flowInstance.ActivityId = startNodeId;
flowInstance.ActivityType = GetNodeType(startNodeId);
flowInstance.ActivityName = Nodes[startNodeId].name;
flowInstance.MakerList = GetNodeMarkers(Nodes[startNodeId], flowInstance.CreateUserId);
@@ -417,9 +409,9 @@ namespace OpenAuth.App.Flow
var sugarClient = AutofacContainerModule.GetService<ISqlSugarClient>();
sugarClient.Updateable(flowInstance).ExecuteCommand();
SaveOperationHis($"【撤回】备注:{request.Description}");
sugarClient.Ado.CommitTran();
}
@@ -501,11 +493,11 @@ namespace OpenAuth.App.Flow
CreateUserName = user.Name,
FromNodeId = currentNodeId,
FromNodeName = currentNode.name,
FromNodeType = currentNodeType,
FromNodeType = GetCurrentNodeType(),
ToNodeId = nextNodeId,
ToNodeName = nextNode?.name,
ToNodeType = nextNodeType,
IsFinish = nextNodeType == 4 ? FlowInstanceStatus.Finished : FlowInstanceStatus.Running,
ToNodeType = GetNextNodeType(),
IsFinish = IsFinish() ? FlowInstanceStatus.Finished : FlowInstanceStatus.Running,
TransitionSate = 0
};
@@ -533,7 +525,7 @@ namespace OpenAuth.App.Flow
result = tag.Taged, //1通过;2不通过3驳回
description = tag.Description,
execTime = tag.TagedTime,
isFinish = node.type == FlowNode.END
isFinish = node.type == Define.NODE_TYPE_END
};
var url = node.setInfo.ThirdPartyUrl;
@@ -561,14 +553,14 @@ namespace OpenAuth.App.Flow
/// </summary>
public void UndoVerification()
{
// 已结束的流程不能撤销
if (flowInstance.IsFinish == FlowInstanceStatus.Finished
// 已结束的流程不能撤销
if (flowInstance.IsFinish == FlowInstanceStatus.Finished
|| flowInstance.IsFinish == FlowInstanceStatus.Rejected)
{
throw new Exception("流程已结束,不能撤销");
}
if(Nodes[previousId].type == FlowNode.START)
if (Nodes[previousId].type == Define.NODE_TYPE_START)
{
throw new Exception("没有任何审批,不能撤销!你可以删除或召回这个流程");
}
@@ -576,12 +568,11 @@ namespace OpenAuth.App.Flow
// 恢复到上一个节点
currentNodeId = flowInstance.PreviousId;
flowInstance.ActivityId = currentNodeId;
flowInstance.ActivityType = GetNodeType(currentNodeId);
flowInstance.ActivityName = Nodes[currentNodeId].name;
//向前查找ActivityId的前一个结点即连线指向ActivityId的节点
flowInstance.PreviousId = GetPreNode().id;
flowInstance.MakerList = GetNodeMarkers(Nodes[currentNodeId]);
// 清除当前节点的审批状态
currentNode.setInfo.Taged = null;
currentNode.setInfo.UserId = "";
@@ -624,11 +615,15 @@ namespace OpenAuth.App.Flow
throw new Exception("无法寻找到下一个节点");
}
if (nextNodeType == 0) //如果是会签节点
if (GetNextNodeType() == Define.NODE_TYPE_FORK) //如果是网关节点
{
makerList = GetForkNodeMakers(nextNodeId);
}
else if (nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_ROLE)
else if (GetNextNodeType() == Define.NODE_TYPE_MULTI_INSTANCE) //如果是多实例、会签节点
{
makerList = GetMultiInstanceNodeMakers(nextNodeId);
}
else if (nextNode.setInfo.NodeDesignate == Define.RUNTIME_SPECIAL_ROLE)
{
//如果是运行时指定角色
if (nextNode.setInfo.NodeDesignate != request.NodeDesignateType)
@@ -640,7 +635,7 @@ namespace OpenAuth.App.Flow
var users = revelanceApp.Get(Define.USERROLE, false, request.NodeDesignates);
makerList = GenericHelpers.ArrayToString(users, makerList);
}
else if (nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_USER)
else if (nextNode.setInfo.NodeDesignate == Define.RUNTIME_SPECIAL_USER)
{
//如果是运行时指定用户
if (nextNode.setInfo.NodeDesignate != request.NodeDesignateType)
@@ -650,7 +645,7 @@ namespace OpenAuth.App.Flow
makerList = GenericHelpers.ArrayToString(request.NodeDesignates, makerList);
}
else if (nextNode.setInfo.NodeDesignate == Setinfo.SPECIAL_SQL)
else if (nextNode.setInfo.NodeDesignate == Define.SPECIAL_SQL)
{
//如果是指定SQL
if (nextNode.setInfo.NodeDesignate != request.NodeDesignateType)
@@ -663,8 +658,8 @@ namespace OpenAuth.App.Flow
var result = sugarClient.Ado.SqlQuery<string>(sql);
makerList = GenericHelpers.ArrayToString(result, makerList);
}
else if (nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_PARENT
|| nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_MANY_PARENTS)
else if (nextNode.setInfo.NodeDesignate == Define.RUNTIME_PARENT
|| nextNode.setInfo.NodeDesignate == Define.RUNTIME_MANY_PARENTS)
{
//如果是上一节点执行人的直属上级或连续多级直属上级
if (nextNode.setInfo.NodeDesignate != request.NodeDesignateType)
@@ -684,7 +679,7 @@ namespace OpenAuth.App.Flow
makerList = GenericHelpers.ArrayToString(new[] { parentId }, makerList);
}
else if (nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_CHAIRMAN)
else if (nextNode.setInfo.NodeDesignate == Define.RUNTIME_CHAIRMAN)
{
//如果是发起人的部门负责人
if (nextNode.setInfo.NodeDesignate != request.NodeDesignateType)
@@ -708,36 +703,105 @@ namespace OpenAuth.App.Flow
return makerList;
}
/// <summary>
/// 计算多实例、会签节点的执行人
/// </summary>
/// <param name="nodeId"></param>
/// <returns></returns>
private string GetMultiInstanceNodeMakers(string nodeId)
{
if (GetNodeType(nodeId) != Define.NODE_TYPE_MULTI_INSTANCE)
{
throw new Exception("当前节点不是会签节点,请联系管理员");
}
var node = Nodes[nodeId];
string[] makerList = Array.Empty<string>(); // 执行人列表
var sugarClient = AutofacContainerModule.GetService<ISqlSugarClient>();
if (node.setInfo.NodeDesignate == Define.SPECIAL_USER) //指定用户
{
makerList = node.setInfo.NodeDesignateData.datas;
}
else if (node.setInfo.NodeDesignate == Define.SPECIAL_ROLE) //指定角色
{
var revelanceApp = AutofacContainerModule.GetService<RevelanceManagerApp>();
makerList = revelanceApp.Get(Define.USERROLE, false, node.setInfo.NodeDesignateData.datas).ToArray();
}
else if (node.setInfo.NodeDesignate == Define.SPECIAL_SQL) //指定SQL
{
//如果是指定SQL则需要执行SQL并返回结果
var sql = ReplaceSql(node.setInfo.NodeDesignateData.datas[0]);
makerList = sugarClient.Ado.SqlQuery<string>(sql).ToArray();
}
else
{
throw new Exception("会签节点,不支持该类型,请重新设计流程模板");
}
//将所有的会签人员写入到FlowApprover后续审批的时候按加签的逻辑处理
var users = sugarClient.Queryable<SysUser>()
.Where(u => makerList.Contains(u.Id))
.ToList()
.OrderBy(u => Array.IndexOf(makerList, u.Id))
.ToList();
int order = 1;
foreach (var user in users)
{
var flowApprover = new FlowApprover
{
InstanceId = flowInstanceId,
ActivityId = nodeId,
ApproverId = user.Id,
ApproverName = user.Name,
OrderNo = order++,
ApproveType = node.setInfo.NodeConfluenceType,
ReturnToSignNode = false,
Reason = "",
CreateDate = DateTime.Now
};
sugarClient.Insertable(flowApprover).ExecuteCommand();
}
//如果是顺序执行,取第一个人
if (node.setInfo.NodeConfluenceType == Define.APPROVE_TYPE_SEQUENTIAL)
{
return makerList[0];
}
//否则并行且/并行或都是返回所有加签人
return GenericHelpers.ArrayToString(makerList, "");
}
/// <summary>
/// 计算节点执行人
/// 这里专门处理由前端选择相关的节点执行人
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public string GetNodeMarkers(FlowNode node, string flowinstanceCreateUserId = "")
{
string makerList = "";
if (node.type == FlowNode.START && (!string.IsNullOrEmpty(flowinstanceCreateUserId))) //如果是开始节点,通常情况下是驳回到开始了
if (node.type == Define.NODE_TYPE_START && (!string.IsNullOrEmpty(flowinstanceCreateUserId))) //如果是开始节点,通常情况下是驳回到开始了
{
makerList = flowinstanceCreateUserId;
}
else if (node.setInfo != null)
{
if (string.IsNullOrEmpty(node.setInfo.NodeDesignate) ||
node.setInfo.NodeDesignate == Setinfo.ALL_USER) //所有成员
node.setInfo.NodeDesignate == Define.ALL_USER) //所有成员
{
makerList = "1";
}
else if (node.setInfo.NodeDesignate == Setinfo.SPECIAL_USER) //指定成员
else if (node.setInfo.NodeDesignate == Define.SPECIAL_USER) //指定成员
{
makerList = GenericHelpers.ArrayToString(node.setInfo.NodeDesignateData.datas, makerList);
}
else if (node.setInfo.NodeDesignate == Setinfo.SPECIAL_ROLE) //指定角色
else if (node.setInfo.NodeDesignate == Define.SPECIAL_ROLE) //指定角色
{
var revelanceApp = AutofacContainerModule.GetService<RevelanceManagerApp>();
var users = revelanceApp.Get(Define.USERROLE, false, node.setInfo.NodeDesignateData.datas);
makerList = GenericHelpers.ArrayToString(users, makerList);
}
else if (node.setInfo.NodeDesignate == Setinfo.SPECIAL_SQL) //指定SQL
else if (node.setInfo.NodeDesignate == Define.SPECIAL_SQL) //指定SQL
{
//如果是指定SQL则需要执行SQL并返回结果
var sql = ReplaceSql(node.setInfo.NodeDesignateData.datas[0]);
@@ -745,8 +809,8 @@ namespace OpenAuth.App.Flow
var result = sugarClient.Ado.SqlQuery<string>(sql);
makerList = GenericHelpers.ArrayToString(result, makerList);
}
else if (node.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_ROLE
|| node.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_USER)
else if (node.setInfo.NodeDesignate == Define.RUNTIME_SPECIAL_ROLE
|| node.setInfo.NodeDesignate == Define.RUNTIME_SPECIAL_USER)
{
//如果是运行时选定的用户,则暂不处理。由上个节点审批时选定
}
@@ -768,7 +832,8 @@ namespace OpenAuth.App.Flow
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
private string ReplaceSql(string sql){
private string ReplaceSql(string sql)
{
var loginUser = AutofacContainerModule.GetService<IAuth>().GetCurrentUser();
var res = sql.Replace(Define.DATAPRIVILEGE_LOGINUSER, $"'{loginUser.User.Id}'");
res = res.Replace(Define.DATAPRIVILEGE_LOGINROLE, string.Join(',', loginUser.Roles.Select(u => $"'{u.Id}'")));
@@ -777,7 +842,7 @@ namespace OpenAuth.App.Flow
}
/// <summary>
/// 会签时,获取一条会签分支上面是否有用户可审核的节点
/// 网关时,获取一条网关分支上面是否有用户可审核的节点
/// </summary>
/// <param name="fromForkStartNode"></param>
/// <param name="tag"></param>
@@ -786,7 +851,7 @@ namespace OpenAuth.App.Flow
{
string canCheckId = "";
var node = fromForkStartNode;
do //沿一条分支线路执行,直到遇到会签结束节点
do //沿一条分支线路执行,直到遇到网关结束节点
{
var makerList = GetNodeMarkers(node);
@@ -798,22 +863,22 @@ namespace OpenAuth.App.Flow
}
node = GetNextNode(node.id);
} while (node.type != FlowNode.JOIN);
} while (node.type != Define.NODE_TYPE_JOIN);
return canCheckId;
}
/// <summary>
/// 获取会签开始节点的所有可执行者
/// 获取网关开始节点的所有可执行者
/// </summary>
/// <param name="forkNodeId">会签开始节点</param>
/// <param name="forkNodeId">网关开始节点</param>
/// <returns></returns>
public string GetForkNodeMakers(string forkNodeId)
{
string makerList = "";
foreach (string fromForkStartNodeId in FromNodeLines[forkNodeId].Select(u => u.to))
{
var fromForkStartNode = Nodes[fromForkStartNodeId]; //与会签开始节点直接连接的节点
var fromForkStartNode = Nodes[fromForkStartNodeId]; //与网关开始节点直接连接的节点
if (makerList != "")
{
makerList += ",";
@@ -826,9 +891,9 @@ namespace OpenAuth.App.Flow
}
/// <summary>
/// 获取会签一条线上的审核者,该审核者应该是已审核过的节点的下一个人
/// 获取网关一条线上的审核者,该审核者应该是已审核过的节点的下一个人
/// </summary>
/// <param name="fromForkStartNode">与会签开始节点直接连接的节点</param>
/// <param name="fromForkStartNode">与网关开始节点直接连接的节点</param>
private string GetOneForkLineMakers(FlowNode fromForkStartNode)
{
string markers = "";
@@ -837,7 +902,7 @@ namespace OpenAuth.App.Flow
{
if (node.setInfo != null && node.setInfo.Taged != null)
{
if (node.type != FlowNode.FORK && node.setInfo.Taged != (int)TagState.Ok) //如果节点是不同意或驳回,则不用再找了
if (node.type != Define.NODE_TYPE_FORK && node.setInfo.Taged != (int)TagState.Ok) //如果节点是不同意或驳回,则不用再找了
{
break;
}
@@ -854,7 +919,7 @@ namespace OpenAuth.App.Flow
if (marker == "1")
{
throw new Exception($"节点{node.name}是会签节点,不能用所有人,请检查!");
throw new Exception($"节点{node.name}是网关节点,不能用所有人,请检查!");
}
if (markers != "")
@@ -864,7 +929,7 @@ namespace OpenAuth.App.Flow
markers += marker;
break;
} while (node.type != FlowNode.JOIN);
} while (node.type != Define.NODE_TYPE_JOIN);
return markers;
}
@@ -888,7 +953,7 @@ namespace OpenAuth.App.Flow
/// 上一个节点
/// </summary>
private string previousId { get; set; }
/// <summary>
/// 实例节点集合
/// </summary>
@@ -909,11 +974,6 @@ namespace OpenAuth.App.Flow
/// </summary>
private Dictionary<string, List<FlowLine>> ToNodeLines { get; set; }
/// <summary>
/// 当前节点类型 0会签开始,1会签结束,2一般节点,开始节点,4流程运行结束
/// </summary>
private int currentNodeType { get; set; }
/// <summary>
/// 表单数据
/// </summary>
@@ -939,12 +999,6 @@ namespace OpenAuth.App.Flow
/// </summary>
public string nextNodeId { get; set; }
/// <summary>
/// 下一个节点类型 -1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束
/// </summary>
/// <value>The type of the next node.</value>
public int nextNodeType { get; set; }
/// <summary>
/// 下一个节点对象
/// </summary>

View File

@@ -112,7 +112,7 @@ namespace OpenAuth.App
}
//如果是顺序执行,取第一个人
if (query.First().ApproveType == 0)
if (query.First().ApproveType == Define.APPROVE_TYPE_SEQUENTIAL)
{
var result = query.OrderBy(u => u.OrderNo).First();
return new[] { result };
@@ -138,7 +138,7 @@ namespace OpenAuth.App
VerifyDate = DateTime.Now
}, u => u.Id == verifyApproverReq.Id);
if (approve.ApproveType == 2)
if (approve.ApproveType == Define.APPROVE_TYPE_ONE)
{
//如果是并行或,只需要一个审批通过即可
return Repository.IsAny(u => u.InstanceId == approve.InstanceId

View File

@@ -28,9 +28,9 @@ namespace OpenAuth.App.Request
/// <summary>
///类型(0顺序1并行且,2并行或)
///类型(sequential顺序all并行且,one并行或)
/// </summary>
public int ApproveType { get; set; }
public string ApproveType { get; set; }
/// <summary>
///父节点ID应对多次加签

View File

@@ -2,7 +2,7 @@
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2024-12-13 16:55:17
* @Description: 工作流实例表操作
* @LastEditTime: 2025-04-10 00:02:15
* @LastEditTime: 2025-04-21 10:54:45
* Copyright (c) 2024 by yubaolee | ahfu~ , All Rights Reserved.
*/
@@ -112,7 +112,6 @@ namespace OpenAuth.App
#region
flowInstance.ActivityId = wfruntime.nextNodeId;
flowInstance.ActivityType = wfruntime.GetNextNodeType();
flowInstance.ActivityName = wfruntime.nextNode.name;
flowInstance.PreviousId = wfruntime.currentNodeId;
flowInstance.CreateUserId = user.User.Id;
@@ -121,8 +120,8 @@ namespace OpenAuth.App
addFlowInstanceReq.CreateUserName = user.User.Account;
flowInstance.MakerList =
wfruntime.GetNextNodeType() != 4 ? wfruntime.GetNextMakers(addFlowInstanceReq) : "";
flowInstance.IsFinish = wfruntime.GetNextNodeType() == 4
(!wfruntime.IsFinish()) ? wfruntime.GetNextMakers(addFlowInstanceReq) : "";
flowInstance.IsFinish = wfruntime.IsFinish()
? FlowInstanceStatus.Finished
: FlowInstanceStatus.Running;
@@ -329,9 +328,9 @@ namespace OpenAuth.App
FlowRuntime wfruntime = new FlowRuntime(flowInstance);
if (flowInstance.ActivityType == 0) //当前节点是会签节点
if (wfruntime.GetCurrentNodeType() == Define.NODE_TYPE_FORK) //当前节点是网关开始节点
{
CounterSign(wfruntime, tag, flowInstance);
VerifyGatewayStart(wfruntime, tag, flowInstance);
}
else
{
@@ -389,33 +388,32 @@ namespace OpenAuth.App
}
/// <summary>
/// 会签
/// 网关
/// </summary>
private void CounterSign(FlowRuntime wfruntime, Tag tag, FlowInstance flowInstance)
private void VerifyGatewayStart(FlowRuntime wfruntime, Tag tag, FlowInstance flowInstance)
{
string res = wfruntime.NodeConfluence(_httpClientFactory.CreateClient(), tag);
string res = wfruntime.VerifyGatewayStart(_httpClientFactory.CreateClient(), tag);
if (res == TagState.No.ToString("D"))
{
flowInstance.IsFinish = FlowInstanceStatus.Disagree;
}
else if (!string.IsNullOrEmpty(res)) //会签结束,当前活动节点变为会签结束节点的下一个节点
else if (!string.IsNullOrEmpty(res)) //网关结束,当前活动节点变为网关结束节点的下一个节点
{
flowInstance.PreviousId = flowInstance.ActivityId;
flowInstance.ActivityId = wfruntime.nextNodeId;
flowInstance.ActivityType = wfruntime.nextNodeType;
flowInstance.ActivityName = wfruntime.nextNode.name;
flowInstance.IsFinish = wfruntime.nextNodeType == 4
flowInstance.IsFinish = wfruntime.IsFinish()
? FlowInstanceStatus.Finished
: FlowInstanceStatus.Running;
flowInstance.MakerList =
wfruntime.nextNodeType == 4 ? "" : wfruntime.GetNextMakers();
wfruntime.IsFinish() ? "" : wfruntime.GetNextMakers();
wfruntime.SaveTransitionHis();
}
else
{
//会签过程中,需要更新用户
//网关过程中,需要更新用户
flowInstance.MakerList = wfruntime.GetForkNodeMakers(wfruntime.currentNodeId);
wfruntime.SaveTransitionHis();
}
@@ -462,6 +460,11 @@ namespace OpenAuth.App
if (!isfinish) //如果没有完成,不能到下一步
{
canNext = false;
flowInstance.MakerList = GenericHelpers.ArrayToString(_flowApproverApp.GetApproverIds(new QueryApproverReq()
{
FlowInstanceId = flowInstance.Id,
ActivityId = flowInstance.ActivityId
}), "");
}
else if (approverInfo.ReturnToSignNode == null || !approverInfo.ReturnToSignNode.Value)
{
@@ -477,7 +480,7 @@ namespace OpenAuth.App
}
}
if (wfruntime.currentNode.setInfo.NodeDesignate == Setinfo.RUNTIME_MANY_PARENTS)
if (wfruntime.currentNode.setInfo.NodeDesignate == Define.RUNTIME_MANY_PARENTS)
{
List<string> roles;
if (user.Id != tag.UserId)
@@ -503,10 +506,9 @@ namespace OpenAuth.App
{
flowInstance.PreviousId = flowInstance.ActivityId;
flowInstance.ActivityId = wfruntime.nextNodeId;
flowInstance.ActivityType = wfruntime.nextNodeType;
flowInstance.ActivityName = wfruntime.nextNode.name;
flowInstance.MakerList = wfruntime.nextNodeType == 4 ? "" : wfruntime.GetNextMakers(request);
flowInstance.IsFinish = wfruntime.nextNodeType == 4
flowInstance.MakerList = wfruntime.IsFinish() ? "" : wfruntime.GetNextMakers(request);
flowInstance.IsFinish = wfruntime.IsFinish()
? FlowInstanceStatus.Finished
: FlowInstanceStatus.Running;
}
@@ -515,7 +517,6 @@ namespace OpenAuth.App
{
flowInstance.IsFinish = FlowInstanceStatus.Disagree;
wfruntime.nextNodeId = "-1";
wfruntime.nextNodeType = 4;
}
var content =
@@ -619,8 +620,8 @@ namespace OpenAuth.App
/// <exception cref="Exception"></exception>
private void CheckNodeDesignate(NodeDesignateReq request)
{
if ((request.NodeDesignateType == Setinfo.RUNTIME_SPECIAL_ROLE
|| request.NodeDesignateType == Setinfo.RUNTIME_SPECIAL_USER) && request.NodeDesignates.Length == 0)
if ((request.NodeDesignateType == Define.RUNTIME_SPECIAL_ROLE
|| request.NodeDesignateType == Define.RUNTIME_SPECIAL_USER) && request.NodeDesignates.Length == 0)
{
throw new Exception("下个节点需要选择执行人或执行角色");
}
@@ -641,7 +642,7 @@ namespace OpenAuth.App
resp.CanWriteFormItemIds = runtime.currentNode.setInfo.CanWriteFormItemIds;
}
if (runtime.nextNode != null && runtime.nextNode.setInfo != null && runtime.nextNodeType != 4)
if (runtime.nextNode != null && runtime.nextNode.setInfo != null && runtime.GetNextNodeType() != Define.NODE_TYPE_END)
{
resp.NextNodeDesignateType = runtime.nextNode.setInfo.NodeDesignate;
resp.CanWriteFormItemIds = runtime.currentNode.setInfo.CanWriteFormItemIds;
@@ -695,22 +696,22 @@ namespace OpenAuth.App
else if (SugarClient.CurrentConnectionConfig.DbType == DbType.Oracle)
{
groupConcatSql = $@" (select listagg(Account, ',') within group (order by Account)
from SysUser
where fi.MakerList like '%' || Id || '%') ";
from SysUser
where fi.MakerList like '%' || Id || '%') ";
}
else if (SugarClient.CurrentConnectionConfig.DbType == DbType.PostgreSQL)
{
groupConcatSql = $@" (select string_agg(Account, ',')
from SysUser
where fi.MakerList like '%' || Id || '%') ";
from SysUser
where fi.MakerList like '%' || Id || '%') ";
}
string sql = String.Empty;
if (request.type == "wait") //待办事项(即需要我处理的流程)
{
sql = $@"
SELECT fi.Id,
sql =$@"
SELECT fi.Id,
fi.CreateUserName,
fi.ActivityName,
fi.CreateDate,
@@ -721,24 +722,38 @@ namespace OpenAuth.App
CASE
WHEN fi.MakerList = '1' THEN '所有人'
WHEN fi.MakerList = '00000000-0000-0000-0000-000000000000' THEN 'System'
ELSE {groupConcatSql}
ELSE {groupConcatSql}
END AS MakerList
FROM FlowInstance fi
JOIN (SELECT fith.Id
FROM FlowInstance fith
WHERE (MakerList = '1' or MakerList LIKE '%{user.User.Id}%')
and (fith.IsFinish = {FlowInstanceStatus.Running} or fith.IsFinish = {FlowInstanceStatus.Rejected})
and not exists (select 1
from flowapprover
where fith.Id = InstanceId
and fith.ActivityId = ActivityId
and Status = 0)
UNION
SELECT fa.InstanceId
FROM FlowApprover fa
WHERE fa.Status = 0
AND fa.ApproverId = '{user.User.Id}') UniqueInstanceIds
ON fi.Id = UniqueInstanceIds.Id";
FROM FlowInstance fith
WHERE (MakerList = '1' or MakerList LIKE '%{user.User.Id}%')
and (fith.IsFinish = {FlowInstanceStatus.Running} or fith.IsFinish = {FlowInstanceStatus.Rejected})
and not exists (select 1
from flowapprover
where fith.Id = InstanceId
and fith.ActivityId = ActivityId
and Status = 0)
union
select fa.instanceid
from flowapprover fa
where fa.status = 0
and fa.approverid = '{user.User.Id}'
and fa.approvetype <> '{Define.APPROVE_TYPE_SEQUENTIAL}'
union
select fa.instanceid
from flowapprover fa
where not exists (select 1
from flowapprover fa2
where fa2.instanceid = fa.instanceid
and fa2.orderno < fa.orderno
and fa2.status = 0
and fa2.approvetype = '{Define.APPROVE_TYPE_SEQUENTIAL}')
and fa.status = 0
and fa.approverid = '{user.User.Id}'
and fa.approvetype = '{Define.APPROVE_TYPE_SEQUENTIAL}') UniqueInstanceIds
ON fi.Id = UniqueInstanceIds.Id
";
}
else if (request.type == "disposed") //已办事项(即我参与过的流程)
{
@@ -757,15 +772,15 @@ namespace OpenAuth.App
ELSE {groupConcatSql}
END AS MakerList
FROM FlowInstance fi
JOIN (SELECT fith.InstanceId
FROM FlowInstanceOperationHistory fith
WHERE fith.CreateUserId = '{user.User.Id}'
UNION
SELECT fa.InstanceId
FROM FlowApprover fa
WHERE fa.Status <> 0
AND fa.ApproverId = '{user.User.Id}') UniqueInstanceIds
ON fi.Id = UniqueInstanceIds.InstanceId
JOIN (SELECT fith.InstanceId
FROM FlowInstanceOperationHistory fith
WHERE fith.CreateUserId = '{user.User.Id}'
UNION
SELECT fa.InstanceId
FROM FlowApprover fa
WHERE fa.Status <> 0
AND fa.ApproverId = '{user.User.Id}') UniqueInstanceIds
ON fi.Id = UniqueInstanceIds.InstanceId
";
}
else //我的流程(我创建的及知会我的)
@@ -785,25 +800,25 @@ namespace OpenAuth.App
ELSE {groupConcatSql}
END AS MakerList
FROM FlowInstance fi
JOIN (select Id as InstanceId
JOIN (select Id as InstanceId
from FlowInstance
where CreateUserId = '{user.User.Id}'
union
select distinct FirstId as InstanceId
from Relevance rel
inner join FlowInstance flow on rel.FirstId = flow.Id and flow.IsFinish = 1
inner join FlowInstance flow on rel.FirstId = flow.Id and flow.IsFinish = 1
where RelKey = '{Define.INSTANCE_NOTICE_USER}'
and SecondId = '{user.User.Id}'
and SecondId = '{user.User.Id}'
union
select distinct a.FirstId as InstanceId
from Relevance a
inner join (select SecondId as RoleId
from Relevance
where RelKey = 'UserRole'
and FirstId = '{user.User.Id}') b on a.SecondId = b.RoleId
inner join FlowInstance flow on a.FirstId = flow.Id and flow.IsFinish = 1
inner join (select SecondId as RoleId
from Relevance
where RelKey = 'UserRole'
and FirstId = '{user.User.Id}') b on a.SecondId = b.RoleId
inner join FlowInstance flow on a.FirstId = flow.Id and flow.IsFinish = 1
where a.RelKey = '{Define.INSTANCE_NOTICE_ROLE}') UniqueInstanceIds
ON fi.Id = UniqueInstanceIds.InstanceId
ON fi.Id = UniqueInstanceIds.InstanceId
";
}
@@ -860,8 +875,8 @@ namespace OpenAuth.App
var wfruntime = new FlowRuntime(flowInstance);
var user = _auth.GetCurrentUser();
if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_USER
|| wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_ROLE)
if (wfruntime.nextNode.setInfo.NodeDesignate == Define.RUNTIME_SPECIAL_USER
|| wfruntime.nextNode.setInfo.NodeDesignate == Define.RUNTIME_SPECIAL_ROLE)
{
throw new Exception("暂不支持【第二执行节点为运行时指定角色/账号执行】的流程恢复");
}
@@ -869,13 +884,12 @@ namespace OpenAuth.App
#region
flowInstance.ActivityId = wfruntime.nextNodeId;
flowInstance.ActivityType = wfruntime.GetNextNodeType();
flowInstance.ActivityName = wfruntime.nextNode.name;
flowInstance.PreviousId = wfruntime.currentNodeId;
flowInstance.CreateUserId = user.User.Id;
flowInstance.CreateUserName = user.User.Account;
flowInstance.MakerList = wfruntime.GetNextNodeType() != 4 ? wfruntime.GetNextMakers() : "";
flowInstance.IsFinish = wfruntime.GetNextNodeType() == 4
flowInstance.MakerList = (!wfruntime.IsFinish()) ? wfruntime.GetNextMakers() : "";
flowInstance.IsFinish = wfruntime.IsFinish()
? FlowInstanceStatus.Finished
: FlowInstanceStatus.Running;

View File

@@ -2,22 +2,17 @@
using System.Linq;
using System.Threading.Tasks;
using Infrastructure;
using Microsoft.EntityFrameworkCore;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.App.Response;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Interface;
using SqlSugar;
namespace OpenAuth.App
{
public class WmsInboundOrderDtblApp : BaseStringApp<WmsInboundOrderDtbl,OpenAuthDBContext>
public class WmsInboundOrderDtblApp : SqlSugarBaseApp<WmsInboundOrderDtbl>
{
private RevelanceManagerApp _revelanceApp;
private DbExtension _dbExtension;
/// <summary>
/// 加载列表
/// </summary>
@@ -29,19 +24,19 @@ namespace OpenAuth.App
{
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
}
var properties = loginContext.GetTableColumns("WmsInboundOrderDtbl");
if (properties == null || properties.Count == 0)
{
throw new Exception("请在代码生成界面配置WmsInboundOrderDtbl表的字段属性");
}
var result = new TableData();
var objs = UnitWork.Find<WmsInboundOrderDtbl>(null);
var objs = SugarClient.Queryable<WmsInboundOrderDtbl>();
if (!string.IsNullOrEmpty(request.InboundOrderId))
{
objs = objs.Where(u => u.OrderId == request.InboundOrderId);
}
if (!string.IsNullOrEmpty(request.key))
{
objs = objs.Where(u => u.GoodsId.Contains(request.key));
@@ -51,32 +46,34 @@ namespace OpenAuth.App
result.columnFields = properties;
result.data = objs.OrderBy(u => u.Id)
.Skip((request.page - 1) * request.limit)
.Take(request.limit).Select($"new ({propertyStr})");
.Take(request.limit).Select($"{propertyStr}").ToList();
result.count = await objs.CountAsync();
return result;
}
public void Add(AddOrUpdateWmsInboundOrderDtblReq req)
{
SugarClient.Ado.BeginTran();
AddNoSave(req);
UnitWork.Save();
SugarClient.Ado.CommitTran();
}
public void AddNoSave(AddOrUpdateWmsInboundOrderDtblReq req)
{
var obj = req.MapTo<WmsInboundOrderDtbl>();
//todo:补充或调整自己需要的字段
obj.CreateTime = DateTime.Now;
var user = _auth.GetCurrentUser().User;
obj.GenerateDefaultKeyVal();
obj.CreateUserId = user.Id;
obj.CreateUserName = user.Name;
UnitWork.Add(obj);
SugarClient.Insertable(obj).ExecuteCommand();
}
public void Update(AddOrUpdateWmsInboundOrderDtblReq obj)
public void Update(AddOrUpdateWmsInboundOrderDtblReq obj)
{
var user = _auth.GetCurrentUser().User;
UnitWork.Update<WmsInboundOrderDtbl>(u => u.Id == obj.Id, u => new WmsInboundOrderDtbl
Repository.Update(u => new WmsInboundOrderDtbl
{
Price = obj.Price,
PriceNoTax = obj.PriceNoTax,
@@ -98,15 +95,12 @@ namespace OpenAuth.App
UpdateUserId = user.Id,
UpdateUserName = user.Name
//todo:补充或调整自己需要的字段
});
}, u => u.Id == obj.Id);
}
public WmsInboundOrderDtblApp(IUnitWork<OpenAuthDBContext> unitWork, IRepository<WmsInboundOrderDtbl,OpenAuthDBContext> repository,
RevelanceManagerApp app, IAuth auth, DbExtension dbExtension) : base(unitWork, repository,auth)
public WmsInboundOrderDtblApp(ISqlSugarClient client, IAuth auth) : base(client, auth)
{
_dbExtension = dbExtension;
_revelanceApp = app;
}
}
}

View File

@@ -2,20 +2,17 @@
using System.Linq;
using System.Threading.Tasks;
using Infrastructure;
using Microsoft.EntityFrameworkCore;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.App.Response;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Interface;
using SqlSugar;
namespace OpenAuth.App
{
public class WmsInboundOrderTblApp : BaseStringApp<WmsInboundOrderTbl,OpenAuthDBContext>
public class WmsInboundOrderTblApp : SqlSugarBaseApp<WmsInboundOrderTbl>
{
private RevelanceManagerApp _revelanceApp;
private WmsInboundOrderDtblApp _wmsInboundOrderDtblApp;
/// <summary>
@@ -29,26 +26,32 @@ namespace OpenAuth.App
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
}
var columns = loginContext.GetTableColumns("WmsInboundOrderTbl");
if (columns == null || columns.Count == 0)
{
throw new Exception("请在代码生成界面配置WmsInboundOrderTbl表的字段属性");
}
var result = new TableData();
result.columnFields = columns;
var objs = GetDataPrivilege("u");
if (!string.IsNullOrEmpty(request.key))
{
objs = objs.Where(u => u.Id.Contains(request.key));
}
if (!string.IsNullOrEmpty(request.sqlWhere))
{
objs = objs.Where(request.sqlWhere);
}
var propertyStr = string.Join(',', columns.Select(u => u.ColumnName));
result.data = objs.OrderBy(u => u.Id)
.Skip((request.page - 1) * request.limit)
.Take(request.limit).Select($"new ({propertyStr})");
.Take(request.limit).Select($"{propertyStr}").ToList();
result.count = await objs.CountAsync();
return result;
}
@@ -61,7 +64,8 @@ namespace OpenAuth.App
var user = _auth.GetCurrentUser().User;
obj.CreateUserId = user.Id;
obj.CreateUserName = user.Name;
UnitWork.Add(obj);
SugarClient.Ado.BeginTran();
SugarClient.Insertable(obj).ExecuteCommand();
if (req.WmsInboundOrderDtblReqs != null && req.WmsInboundOrderDtblReqs.Any())
{
foreach (var detail in req.WmsInboundOrderDtblReqs)
@@ -71,72 +75,71 @@ namespace OpenAuth.App
}
}
UnitWork.Save();
SugarClient.Ado.CommitTran();
}
public void Update(AddOrUpdateWmsInboundOrderTblReq obj)
{
var user = _auth.GetCurrentUser().User;
UnitWork.ExecuteWithTransaction(() =>
SugarClient.Ado.BeginTran();
if (obj.WmsInboundOrderDtblReqs != null && obj.WmsInboundOrderDtblReqs.Any())
{
if (obj.WmsInboundOrderDtblReqs != null && obj.WmsInboundOrderDtblReqs.Any())
//id为空的添加
foreach (var detail in obj.WmsInboundOrderDtblReqs.Where(u => string.IsNullOrEmpty(u.Id)))
{
//id为空的添加
foreach (var detail in obj.WmsInboundOrderDtblReqs.Where(u => string.IsNullOrEmpty(u.Id)))
{
detail.OrderId = obj.Id;
_wmsInboundOrderDtblApp.AddNoSave(detail);
}
//id比数据库少的删除
var containids = obj.WmsInboundOrderDtblReqs.Select(u => u.Id)
.Where(u => !string.IsNullOrEmpty(u)).ToList();
if (containids.Any())
{
UnitWork.Delete<WmsInboundOrderDtbl>(u => (!containids.Contains(u.Id)) && u.OrderId == obj.Id);
}
//更新id相同的
foreach (var detail in obj.WmsInboundOrderDtblReqs.Where(u => !string.IsNullOrEmpty(u.Id)))
{
_wmsInboundOrderDtblApp.Update(detail);
}
detail.OrderId = obj.Id;
_wmsInboundOrderDtblApp.AddNoSave(detail);
}
UnitWork.Update<WmsInboundOrderTbl>(u => u.Id == obj.Id, u => new WmsInboundOrderTbl
//id比数据库少的删除
var containids = obj.WmsInboundOrderDtblReqs.Select(u => u.Id)
.Where(u => !string.IsNullOrEmpty(u)).ToList();
if (containids.Any())
{
ExternalNo = obj.ExternalNo,
ExternalType = obj.ExternalType,
Status = obj.Status,
OrderType = obj.OrderType,
GoodsType = obj.GoodsType,
PurchaseNo = obj.PurchaseNo,
StockId = obj.StockId,
OwnerId = obj.OwnerId,
ShipperId = obj.ShipperId,
SupplierId = obj.SupplierId,
ScheduledInboundTime = obj.ScheduledInboundTime,
Remark = obj.Remark,
Enable = obj.Enable,
TransferType = obj.TransferType,
InBondedArea = obj.InBondedArea,
ReturnBoxNum = obj.ReturnBoxNum,
UpdateTime = DateTime.Now,
UpdateUserId = user.Id,
UpdateUserName = user.Name
//todo:补充或调整自己需要的字段
});
SugarClient.Deleteable<WmsInboundOrderDtbl>(u => (!containids.Contains(u.Id)) && u.OrderId == obj.Id).ExecuteCommand();
}
//更新id相同的
foreach (var detail in obj.WmsInboundOrderDtblReqs.Where(u => !string.IsNullOrEmpty(u.Id)))
{
_wmsInboundOrderDtblApp.Update(detail);
}
}
Repository.Update(u => new WmsInboundOrderTbl
{
ExternalNo = obj.ExternalNo,
ExternalType = obj.ExternalType,
Status = obj.Status,
OrderType = obj.OrderType,
GoodsType = obj.GoodsType,
PurchaseNo = obj.PurchaseNo,
StockId = obj.StockId,
OwnerId = obj.OwnerId,
ShipperId = obj.ShipperId,
SupplierId = obj.SupplierId,
ScheduledInboundTime = obj.ScheduledInboundTime,
Remark = obj.Remark,
Enable = obj.Enable,
TransferType = obj.TransferType,
InBondedArea = obj.InBondedArea,
ReturnBoxNum = obj.ReturnBoxNum,
UpdateTime = DateTime.Now,
UpdateUserId = user.Id,
UpdateUserName = user.Name
//todo:补充或调整自己需要的字段
}, u => u.Id == obj.Id);
SugarClient.Ado.CommitTran();
UnitWork.Save();
});
}
public WmsInboundOrderTblApp(IUnitWork<OpenAuthDBContext> unitWork, IRepository<WmsInboundOrderTbl,OpenAuthDBContext> repository,
RevelanceManagerApp app, IAuth auth, WmsInboundOrderDtblApp wmsInboundOrderDtblApp) : base(unitWork,
repository, auth)
public WmsInboundOrderTblApp(ISqlSugarClient client, IAuth auth,
WmsInboundOrderDtblApp wmsInboundOrderDtblApp) : base(client, auth)
{
_revelanceApp = app;
_wmsInboundOrderDtblApp = wmsInboundOrderDtblApp;
}
}

View File

@@ -10,7 +10,7 @@
},
"AppSetting": {
"DbTypes": {
"OpenAuthDBContext":"MySql" //数据库类型SqlServer、MySql、Oracle
"OpenAuthDBContext":"MySql" //数据库类型SqlServer、MySql、Oracle、PostgreSql
}
}
}

View File

@@ -7,11 +7,10 @@
"AllowedHosts": "*",
"ConnectionStrings": {
"OpenAuthDBContext": "Data Source=.;Encrypt=false;Initial Catalog=OpenAuthDB;User=sa;Password=000000"
//"OpenAuthDBContext": "server=127.0.0.1;user id=root;database=openauthdb;password=000000" //my sql
},
"AppSetting": {
"DbTypes": {
"OpenAuthDBContext":"SqlServer" //数据库类型SqlServer、MySql、Oracle
"OpenAuthDBContext":"SqlServer" //数据库类型SqlServer、MySql、Oracle、PostgreSql
}
}
}

View File

@@ -39,7 +39,6 @@
<None Include="wwwroot\css\metroStyle\img\metro.gif" />
<None Include="wwwroot\css\metroStyle\img\metro.png" />
<None Include="wwwroot\css\metroStyle\metroStyle.css" />
<None Include="wwwroot\css\treetable.css" />
<None Include="wwwroot\images\alipay.jpg" />
<None Include="wwwroot\images\code.jpg" />
<None Include="wwwroot\images\face.jpg" />

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css"/>
}
<blockquote class="layui-elem-quote news_search toolList" id="menus">

View File

@@ -1,7 +1,7 @@

@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
<link href="/js/flow/GooFlow.css" rel="stylesheet" />

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,7 +1,7 @@

@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
<link href="/js/flow/GooFlow.css" rel="stylesheet" />

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,17 +1,52 @@

@section header
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
<link href="/js/flow/GooFlow.css" rel="stylesheet" />
<link href="/css/formpreview.css" rel="stylesheet" />
<!-- 添加自定义样式覆盖main.css中的冲突样式 -->
<style>
.verification-flex-container {
display: flex;
width: 100%;
min-height: 600px;
}
.verification-left-panel {
flex: 8;
padding-right: 10px;
}
.verification-right-panel {
flex: 4;
background-color: gainsboro;
padding: 10px;
}
/* 覆盖main.css中的绝对定位样式 */
.verification-tab .layui-tab-item {
position: relative !important;
top: auto !important;
bottom: auto !important;
left: auto !important;
right: auto !important;
min-height: 500px;
padding: 10px;
}
.verification-tab .layui-tab-content {
min-height: 500px;
position: relative;
}
</style>
}
<form class="layui-form " action="" id="formEdit">
<div class="layui-row ">
<div class="layui-col-xs8">
<div class="layui-tab layui-tab-brief" lay-filter="tab" style="margin: 0px">
<div class="verification-flex-container">
<div class="verification-left-panel">
<div class="layui-tab layui-tab-brief verification-tab" lay-filter="tab" style="margin: 0px">
<ul class="layui-tab-title">
<li class="layui-this">流程信息</li>
<li>表单信息</li>
@@ -19,18 +54,22 @@
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<div id="flowPanel"></div>
<div id="flowPanel">
<!-- 测试内容 -->
<p>流程内容应该显示在这里</p>
</div>
</div>
<div class="layui-tab-item">
<div id="frmPreview"></div>
<div id="frmPreview">
<!-- 测试内容 -->
<p>表单内容应该显示在这里</p>
</div>
</div>
</div>
</div>
</div>
<div class="layui-col-xs4" style="background-color: gainsboro; min-height: 600px">
<div class="verification-right-panel">
<input type="hidden" id="FlowInstanceId" name="FlowInstanceId"/>
<div class="layui-form-item">
@@ -50,7 +89,7 @@
</div>
</div>
</div>
</div>
</div>
<input type="hidden" lay-submit id="btnSubmit" lay-filter="formSubmit"/>
</form>

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
<link href="/js/flow/GooFlow.css" rel="stylesheet" />

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,7 +1,7 @@

@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
<link href="/js/flow/GooFlow.css" rel="stylesheet" />

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
<style>

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
}
<div class="layui-row">

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css"/>
<link rel="stylesheet" href="/js/dtree/dtree.css"/>
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css"/>
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
}
<blockquote class="layui-elem-quote news_search toolList" id="menus">
</blockquote>

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css"/>
<link rel="stylesheet" href="/js/dtree/dtree.css"/>
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css"/>
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css"/>
<link rel="stylesheet" href="/js/dtree/dtree.css"/>
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css"/>
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
}
<blockquote class="layui-elem-quote news_search toolList" id="menus">
</blockquote>

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
}
<blockquote class="layui-elem-quote news_search toolList" id="menus">
</blockquote>

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
<link rel="stylesheet" href="/js/dtree/dtree.css" />
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
}

View File

@@ -1,6 +1,6 @@
@section header
{
<link rel="stylesheet" href="/css/treetable.css"/>
}
<blockquote class="layui-elem-quote news_search toolList" id="menus">

View File

@@ -5,6 +5,14 @@
.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{ height:42px !important; }
.layui-layer-tab .layui-layer-title span{ min-width:45px !important; }
.marg0{ margin:0; }
/*统一按钮样式*/
.layui-btn {
height: 28px;
line-height: 28px;
padding: 0 10px;
font-size: 12px;
}
/*模拟加载层图标样式*/
.layui-layer-dialog .layui-layer-content .layui-layer-ico16{ background-size:100% 100% !important; }
@@ -26,6 +34,8 @@
.layui-elem-quote{
border-left: 5px solid #f8f8f8 !important; /*blockquote的左侧边框*/
padding:5px;
margin-block-end: 2px;
}
/*样式改变的过渡*/
@@ -72,15 +82,13 @@
.layui-nav-tree .layui-nav-child dd.layui-this a:hover{ background-color:#009688; }
/*右侧body*/
#top_tabs_box{ padding-right:138px; height:40px; border-bottom:1px solid #e2e2e2; }
#top_tabs_box{ padding-right:138px; height:35px; border-bottom:1px solid #e2e2e2; }
#top_tabs{ position: absolute; border-bottom:none;}
/*多窗口页面操作下拉*/
.closeBox{ position:absolute; right:0; background-color:#fff !important; color:#000; border-left:1px solid #e2e2e2; border-bottom:1px solid #e2e2e2; }
.closeBox .layui-nav-item{ line-height:40px; }
.closeBox .layui-nav-item{ line-height:35px; }
.closeBox .layui-nav-item a,.closeBox .layui-nav-item a:hover{ color:#000; }
.closeBox .layui-nav-more{ top:17px; }
.closeBox .layui-nav-mored{ top:11px; }
.closeBox .layui-nav-child{ top:42px; left:-12px; }
.closeBox .layui-nav-child{ top:37px; left:-12px; }
.closeBox .layui-nav-bar{ display:none; }
.closeBox .icon-caozuo{ font-size: 20px; position:absolute; top:1px; left:-2px; }
@@ -90,11 +98,18 @@
}
.layui-tab-content{ height:100%; padding:0; }
.layui-tab-item{ position: absolute; top: 41px; bottom:27px; left: 0; right: 0; padding: 0; margin: 0; -webkit-overflow-scrolling:touch; overflow:auto;}
.layui-tab-title .layui-this{ background-color:#18A093;}
.layui-tab .layui-tab-title{
height: 35px;
}
.layui-tab-title .layui-this:after{ border:none; }
.layui-tab-title li cite{ font-style: normal; padding-left:5px; }
.layui-tab-card .layui-tab-title{background-color: #ffffff}
.layui-tab-card .layui-tab-title .layui-this{background-color: #f2f2f2}
.layui-tab .layui-tab-title li {
line-height: 35px;
}
.clildFrame.layui-tab-content{ padding-right: 0; }
.clildFrame.layui-tab-content iframe{ width: 100%; height:100%; border:none; min-width: 320px; position:absolute; }
/*main.html*/
@@ -180,7 +195,11 @@
.orange .top_menu.layui-nav-itemed .layui-nav-more,.orange .top_menu.layui-nav .layui-nav-mored,.blue .top_menu.layui-nav-itemed .layui-nav-more,.blue .top_menu.layui-nav .layui-nav-mored{border-color:transparent transparent #fff !important;}
/*底部*/
.footer{ text-align: center; line-height:44px;border-left: 2px solid #1AA094;}
.footer{ text-align: center; }
.layui-layout-admin .layui-footer {
line-height: 35px !important;
height: 35px !important;
}
/*响应式*/

View File

@@ -1,12 +0,0 @@
.layui-elem-quote {
margin-bottom: 2px;
padding: 10px;
}
.layui-table-view {
margin: 0 !important;
}
ul.ztree {
margin-top: 0!important;
}

View File

@@ -17,7 +17,7 @@
haveHead: false,
haveTool: true,
headLabel: true,
toolBtns: ["start round mix", "end round", "node", "join", "fork"],
toolBtns: ["start", "end", "node", "join", "fork"],
haveGroup: true,
useOperStack: true
};
@@ -78,14 +78,14 @@
var _node = data.nodes[j];
var _flag = false;
switch (_node.type) {
case "start round mix":
case "start":
startroundFlag++;
if (fromlines[_node.id] == undefined) {
layer.msg("开始节点无法流转到下一个节点");
return -1;
}
break;
case "end round":
case "end":
endroundFlag++;
if (tolines[_node.id] == undefined) {
layer.msg("无法流转到结束节点");
@@ -173,7 +173,7 @@
$.each(options.nodeData,
function (i, item) {
$("#" + item.id).css("background", "#999");
if (item.type == "start round mix") {
if (item.type == "start") {
$("#" + item.id).css("background", "#5cb85c");
} else {
if (item.id == options.activityId) {

View File

@@ -62,6 +62,7 @@
});
};
mainList();
clickTableRow(table,'mainList', 'list');
//添加(编辑)对话框
var editDlg = function () {

View File

@@ -36,7 +36,7 @@
OpenNode: function (object) {
FlowDesignObject = object; //为NodeInfo窗口提供调用
if (object.type == 'start round mix' || object.type == 'end round') {
if (object.type == 'start' || object.type == 'end') {
return false;
}

View File

@@ -60,7 +60,7 @@
OpenNode: function (object) {
FlowDesignObject = object; //为NodeInfo窗口提供调用
if (object.type == 'start round mix' || object.type == 'end round') {
if (object.type == 'start' || object.type == 'end') {
layer.msg("开始节点与结束节点不能设置");
return false;
}

View File

@@ -16,7 +16,7 @@
OpenNode: function (object) {
FlowDesignObject = object; //为NodeInfo窗口提供调用
if (object.type == 'start round mix' || object.type == 'end round') {
if (object.type == 'start' || object.type == 'end') {
layer.msg("开始节点与结束节点不能设置");
return false;
}

View File

@@ -1,4 +1,11 @@
layui.config({
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2023-12-25 14:43:53
* @Description:
* @LastEditTime: 2025-04-14 15:55:51
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
*/
layui.config({
base: "/js/"
}).use(['form', 'vue', 'ztree', 'layer', 'jquery', 'table', 'droptree', 'openauth', 'utils'], function () {
var form = layui.form,
@@ -50,7 +57,7 @@
});
};
mainList();
clickTableRow(table,'mainList', 'list');
//监听表格内部按钮

View File

@@ -72,6 +72,7 @@
});
};
mainList();
clickTableRow(table,'mainList', 'list');
//添加(编辑)对话框
var editDlg = function () {

View File

@@ -27,7 +27,7 @@ namespace OpenAuth.Repository.Domain
this.VerifyComment = "";
this.CascadeId = "";
this.ApproverId = "";
this.ApproveType = 0;
this.ApproveType = "";
this.CreateDate = DateTime.Now;
this.CreateUserName = "";
this.ParentId = "";
@@ -70,10 +70,10 @@ namespace OpenAuth.Repository.Domain
public string ApproverId { get; set; }
/// <summary>
///类型(0顺序1并行且,2并行或)
///类型(sequential顺序all并行且,one并行或)
/// </summary>
[Description("类型(0顺序1并行且,2并行或)")]
public int ApproveType { get; set; }
[Description("类型(sequential顺序all并行且,one并行或)")]
public string ApproveType { get; set; }
/// <summary>
///加签时间

View File

@@ -70,11 +70,6 @@ namespace OpenAuth.Repository.Domain
[Description("当前节点ID")]
public string ActivityId { get; set; }
/// <summary>
/// 当前节点类型0会签节点
/// </summary>
[Description("当前节点类型0会签节点")]
public int? ActivityType { get; set; }
/// <summary>
/// 当前节点名称
/// </summary>
[Description("当前节点名称")]

View File

@@ -50,7 +50,7 @@ namespace OpenAuth.Repository.Domain
/// 开始节点类型
/// </summary>
[Description("开始节点类型")]
public int? FromNodeType { get; set; }
public string FromNodeType { get; set; }
/// <summary>
/// 开始节点名称
/// </summary>
@@ -65,7 +65,7 @@ namespace OpenAuth.Repository.Domain
/// 结束节点类型
/// </summary>
[Description("结束节点类型")]
public int? ToNodeType { get; set; }
public string ToNodeType { get; set; }
/// <summary>
/// 结束节点名称
/// </summary>

View File

@@ -54,13 +54,18 @@
## 📸效果预览
#### 后端启动效果
![API启动效果图](https://images.gitee.com/uploads/images/2021/0422/012037_ec51b7e6_362401.png "api启动.png")
#### vue版本效果
![工作流](snapshot/image.png)
![打印方案设计](snapshot/sysprinterplan.png)
![打印方案挂载业务系统](snapshot/sysprinterplan2.png)
![拖拽表单](snapshot/form.png)
#### layui开源版本效果
![开源版本效果](snapshot/layui.jpg)
## 📞官方QQ交流群
@@ -74,6 +79,7 @@
## 💡核心功能
项目深入参考《企业应用架构模式》《重构与模式》《ASP.NET设计模式》等巨著完成每一行代码编写。主要特性
* 支持最新版.Net 9.0.100
@@ -111,15 +117,5 @@
* 设计工具 PowerDesigner +PDManer + Enterprise Architect
## 💎秀外
![输入图片说明](https://gitee.com/uploads/images/2018/0328/173337_6e017075_362401.png "表单设计")
![输入图片说明](https://gitee.com/uploads/images/2018/0328/150758_26ef9d61_362401.png "流程设计")
## 🧠慧中
教科书级的分层思想哪怕苛刻的你阅读的是大神级精典大作《企业应用架构模式》《重构与模式》《ASP.NET设计模式》等你也可以参考本项目。
## 🔜后续
生命不息,更新不止

View File

@@ -1,192 +0,0 @@
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2023-08-12 10:48:24
* @LastEditTime: 2025-04-09 20:38:14
* @Description:
* @
* @Copyright (c) 2023 by yubaolee | ahfu~ , All Rights Reserved.
*/
module.exports = {
title: 'OpenAuth.Net',
description: '最好用的.net权限工作流框架,最好用的.net vue前后分离框架',
head: [
['link', {
rel: 'icon',
href: '/logo.png'
}],['script',{},
`var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script')
hm.src = 'https://hm.baidu.com/hm.js?93a7b9a145222f9b7109d643a0c58f8d'
var s = document.getElementsByTagName('script')[0]
s.parentNode.insertBefore(hm, s)
})();
`]
],
extendMarkdown: (md) => {
md.set({
breaks: true
})
md.use(require('markdown-it-plantuml'))
},
themeConfig: {
lastUpdated: '最后更新时间', // string | boolean
nav: [{
text: '首页',
link: 'http://openauth.net.cn/',
target: '_blank'
},
{
text: '在线文档',
ariaLabel: 'Proj Menu',
items: [{
text: 'OpenAuth.Net开源后端',
link: '/core/',
target: '_blank'
},
{
text: 'OpenAuth.Pro(vue3版本)',
link: '/pro/',
target: '_blank'
},
{
text: 'OpenAuth.Pro(vue2版本)',
link: '/vue2/',
target: '_blank'
}
],
},
{
text: '项目地址',
ariaLabel: 'Proj Menu',
items: [{
text: 'gitee',
link: 'https://gitee.com/dotnetchina/OpenAuth.Net',
target: '_blank'
},
{
text: 'github',
link: 'https://github.com/yubaolee/OpenAuth.Core',
target: '_blank'
},
],
},
{
text: '战略合作',
ariaLabel: 'Proj Menu',
items: [{
text: 'Variant Form - 可视化低代码表单',
link: 'https://www.vform666.com/',
target: '_blank'
},
{
text: 'SqlSugar',
link: 'https://www.donet5.com/',
target: '_blank'
}
],
},
],
sidebar: {
'/core/': [
['', '项目介绍'],
{
title: '后端开发', // 必要的
path: 'start', // 可选的, 标题的跳转链接,应为绝对路径且必须存在
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['start', 'specialist', 'deploy', 'deployapi', 'devnew', 'multidbs', 'multitenant', 'unitwork','sqlsugar', 'entity','dynamicapi', 'datavalidation', 'log', 'identity', 'job', 'cache', 'unittest','changesdk'],
},
{
title: '权限控制', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['moduleauth','apiauth', 'logininfo', 'dataprivilege', 'datapropertyrule'],
},
{
title: '表单设计', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['form'],
},
{
title: '工作流', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['flowinstance','flowinstanceconcept', 'flowinstancestatus', 'thirdparty'],
},
{
title: '前端开发', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['wwwarchitect'],
},
{
title: '更新日志', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['changelog', 'routineupdate'],
},
'faq',
],
'/pro/': [
['', '项目介绍'],
'deploy',
'structure',
'devnew',
{
title: '基础开发', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['router','openurl','keepalive'],
},
'datapropertyrule',
'printerplan',
{
title: '表单设计', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['startform','urlform','dragform','dragformdetail'],
},
{
title: '工作流', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['startflow','form'],
},
'components',
'faq',
],
'/vue2/': [
['', '项目介绍'],
'deploy',
'structure',
'devnew',
{
title: '基础开发', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['router','openurl','keepalive'],
},
'datapropertyrule',
'printerplan',
{
title: '表单设计', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['startform','dragform','dragformdetail'],
},
{
title: '工作流', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['startflow','form'],
},
'components',
'faq',
]
},
},
}

View File

@@ -1,28 +0,0 @@
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2024-06-19 20:41:42
* @LastEditTime: 2024-06-19 20:48:04
* @Description:
* @
* @Copyright (c) 2024 by yubaolee | ahfu~ , All Rights Reserved.
*/
// .vuepress/enhanceApp.js
export default ({ router }) => {
if (process.env.NODE_ENV === 'production' && typeof window !== 'undefined') {
// 百度统计代码
var _hmt = _hmt || []
;(function () {
var hm = document.createElement('script')
hm.src = 'https://hm.baidu.com/hm.js?93a7b9a145222f9b7109d643a0c58f8d'
var s = document.getElementsByTagName('script')[0]
s.parentNode.insertBefore(hm, s)
})();
// 路由切换时触发百度统计
router.afterEach(function (to) {
if (window._hmt) {
window._hmt.push(['_trackPageview', to.fullPath])
}
})
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -1,25 +0,0 @@
---
home: true
heroImage: /logo.png
heroText: OpenAuth.Net
tagline: 最好用的.net权限工作流框架,最实用的.net/vue前后端分离方案
actionText: 快速上手 →
actionLink: /core/start/
features:
- title: 简洁至上
details: 源于Martin Fowler企业级应用开发思想及最新技术组合。
- title: 灵活控制
details: 超强的自定义权限控制功能,可灵活配置用户、角色可访问的数据权限。
- title: 超酷体验
details: 可拖拽的表单设计,可视化流程设计。
- title: 紧随潮流
details: 最新的.net sdk配合最炫的vue框架。
- title: 功能强大
details: 角色授权、代码生成、API鉴权、智能打印、数据权限、拖拽表单、工作流引擎、定时任务。
- title: 主流技术
details: IdentityServer、EF、SqlSugar、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、VUE2、VUE3、Element-ui、Element-plus。
footer: Copyright © 2025- yubaolee
---

View File

@@ -1,2 +0,0 @@
{
}

View File

@@ -1,79 +0,0 @@
# 部署MVC
::: tip 提示
因.net core内部有自托管的Web服务器推荐使用控制台方式部署。本内容基于控制台命令的方式。如果部署到IIS请自行百度:cold_sweat:
:::
## 生成发布文件
* 修改部署环境的连接字符串信息,特别注意是`appsettings.Production.json`文件:
![说明](/configmvc.png "说明")
::: warning 注意
决定系统部署后读取`appsettings.json`还是`appsettings.Production.json`是通过操作系统的环境变量`ASPNETCORE_ENVIRONMENT`来控制的。
在centos切换成正式可以用
```shell
export ASPNETCORE_ENVIRONMENT=Production
```
或者修改/etc/profile配置在结尾添加
```shell
ASPNETCORE_ENVIRONMENT=Production
export ASPNETCORE_ENVIRONMENT
```
然后刷新:
```shell
source /etc/profile
```
在Widows系统中增加对应环境变量即可
:::
* 直接在解决方案资源管理器中选中OpenAuth.Mvc右键【发布】出现下面的配置框使用文件系统即可
![说明](http://pj.openauth.net.cn/zentao/file-read-8.png "说明")
* 发布完成后可以在输出目录看到发布详情(红色框内即为发布的文件夹):
![说明](http://pj.openauth.net.cn/zentao/file-read-69.png "说明")
## 部署OpenAuth.Mvc
将发布后的文件拷贝到服务器文件夹。直接使用`dotnet openauth.mvc.dll` 命令启动。启动成功后使用浏览器打开http://localhost:1802 即可访问,如下图所示:
![说明](/mvcmain.png "说明")
## jenkins部署OpenAuth.Mvc
OpenAuth.Net采用的是gitee托管源码只需使用Gitee WebHook构建触发器。配置如下
![说明](/giteesource.png "说明")
做好上面的配置后代码提交时就会触发jenkins工作。剩下的就是编写自己的构建脚本。增加构建步骤选择执行Shell。并输入以下脚本
```shell
#!/bin/bash
kill -9 $(ps -ef|grep OpenAuth.Mvc.dll|grep -v grep|awk '{print $2}')
#项目启动之后才不会被Jenkins杀掉。
export BUILD_ID=dontKillMe
pwd
echo $PATH
dotnet restore # 还原nuget包
cd ./OpenAuth.Mvc
dotnet build # 编译
rm -rf /data/openauthmvc #最终站点路径
mkdir /data/openauthmvc
dotnet publish -c:Release -o /data/openauthmvc # 生成发布文件到/data/openauthmvc。如果服务器上有多个.NET版本加上目标版本号-f net6.0
nohup dotnet /data/openauthmvc/OpenAuth.Mvc.dll &
echo '============================end build======================================='
```

View File

@@ -1,81 +0,0 @@
# 工作流介绍
OpenAuth.Net工作流基于国际标准的BPMN2.0规范,并在此基础上做了一些扩展,以满足国内各种需求。系统工作流分为两个大类:
1. 无业务关联流程,如请假、报销等。
![无业务关联流程](http://img.openauth.net.cn/2025-04-06-22-35-35.png)
2. 有业务关联流程,如采购、销售等。
![订单送审](http://img.openauth.net.cn/2025-04-06-22-34-34.png)
这两种流程的差异有以下几点:
| 对比维度 | 无业务关联流程 | 有业务关联流程 |
|---------|--------------|--------------|
| 适用场景 | 请假、报销等日常办公 | 采购、销售、入库等业务操作 |
| 发起方式 | 流程中心 -> 我的流程 -> 新的申请 | 直接在业务模块中发起(如:仓储中心 -> 入库订单 -> 送审) |
| 表单类型 | 简单表单,适用拖拽表单设计器 | 复杂表单需要自定义表单或URL表单 |
| 审批结束处理 | 仅更新流程状态 | 需要修改业务数据状态 |
表中提到的表单类型差异可以查看:[表单设计](./form.md)
# 基本操作
一个完整的工作流从设计到发起,到审批,需要经过:
1. 表单设计:【基础配置/表单设计】中添加一个用于流程的表单;
2. 流程设计:【基础配置/流程设计】中添加一个流程模版,流程模版选择刚刚建的表单;
3. 流程发起:【流程中心/我的流程】中【新的申请】创建一个流程实例,或在业务系统中直接【送审】发起;
4. 流程审批:【流程中心/待处理流程】中进行审批;
这里只介绍开源版本的操作流程vue版本操作流程请参考[操作手册](/pro/startflow.md)
# 流程审批逻辑
当最终用户在【待处理流程】中审批一个流程实例时,流程实例会经过下面步骤进行处理:
@startuml
skinparam handwritten true
skinparam backgroundColor #EEEBDC
start
if (当前活动节点类型为会签) then (yes)
:标识当前节点状态;
:从所有的分支中找到一个用户可以审批的节点canCheckId;
if (没找到?) then (yes)
stop
endif
:标识canCheckId节点状态;
#HotPink:进行会签,结果为res;
if(res == TagState.No) then (yes)
:修改流程最终状态为不同意;
else if(res != string.Empty) then (yes)
stop
else (no)
:修改流程最终状态,修改活动节点,修改可执行人;
:添加扭转记录;
endif
else (no)
:标识当前节点状态;
if (同意) then (yes)
:修改流程最终状态,修改活动节点,修改可执行人;
:添加扭转记录;
else
:修改流程最终状态为不同意;
endif
:操作记录;
endif
stop
@enduml

View File

@@ -1,133 +0,0 @@
# 流程实例
流程实例指正在运行的一个流程。数据存放在FlowInstance表中该表核心字段如下
#### IsFinish流程的当前状态
- -1 草稿/召回:流程发起人主动召回流程;
- 0 正在运行;
- 1 完成:流程结束,同时所有的审批都通过;
- 3 不同意:即流程结束,同时审批人员没有通过;
- 4 驳回:流程结束,可能发起的流程内容有问题,要求被驳回重新提交;
#### ActivityId: 当前活动节点,即待审批的节点
#### ActivityType当前节点的类型
- -1 无法运行,
- 0 会签开始,
- 1 会签结束,
- 2 一般节点,
- 3 开始节点,
- 4 流程运行结束
#### SchemeContent流程实例的具体内容
该字段存储的是一个JSON对象具体内容如下所示
```javascript
{
"title":"newFlow_1",
"nodes":[
{
"name":"node_1",
"left":75,
"top":90,
"type":"start round mix",
"id":1521797877921,
"width":26,
"height":26,
"alt":true
},
{
"name":"审核",
"left":235,
"top":97,
"type":"node",
"id":1521797879744,
"width":104,
"height":26,
"alt":true,
"setInfo":{
"NodeDesignateData":{
"users":[
"49df1602-f5f3-4d52-afb7-3802da619558",
"6ba79766-faa0-4259-8139-a4a6d35784e0"
],
"role":{
},
"org":{
}
},
"NodeCode":"FIRST",
"NodeName":"审核"
}
},
{
"name":"node_3",
"left":268,
"top":209,
"type":"end round",
"id":1521797881216,
"width":26,
"height":26,
"alt":true
}
],
"lines":[
{
"type":"sl",
"from":"1521797877921",
"to":"1521797879744",
"id":1521797883552,
"name":"",
"dash":false
},
{
"type":"sl",
"from":"1521797879744",
"to":"1521797881216",
"id":1521797884536,
"name":"",
"dash":false
}
],
"areas":{
},
"initNum":7
}
```
其中nodes为流程实例的所有节点。lines为流程实例的所有连线。节点的type属性为节点的类型属性对应上面提到的ActivityType
- -1无法运行
- 0会签开始即type为fork
- 1会签结束,即type为join
- 2一般节点,即type为node
- 3开始节点,即type为start
- 4流程运行结束即type为end
与流程实例密切相关的还有两个表流程实例的操作记录FlowInstanceOperationHistory及流转记录FlowInstanceTransitionHistory。它们有不同的作用
### 操作记录FlowInstanceOperationHistory
该表记录了流程实例的所有操作记录,包括流程的创建、撤回、驳回、同意、不同意等操作。
### 流转记录FlowInstanceTransitionHistory
记录某个流程实例所有已审批的从一个活动节点到下一个活动节点的操作人、操作时间。

View File

@@ -1,26 +0,0 @@
# 后端开发规范
## 数据库表及字段命名
SqlServer采用PascalCase命名Oracle采用全大写命名其他数据库采用camelCase命名。
::: tip 提示
开源版代码生成时通过表结尾Dtbl来判断是否是生成明细表代码。因此建议数据库表命名时按子系统名称+业务名称+表尾,其中表尾名称规则:
- 基础主数据以Mst结尾
- 普通业务表以Tbl结尾
- 业务明细表以Dtbl结尾
WMS系统入库订单明细表WmsInboundOrderDtbl
:::
## 数据库字段类型
主键id统一使用Domain:PrimaryKey针对SqlServer数据库非Sql Server根据需要定义
状态类,标识类的字段统一使用bit not null
表示分类的字段统一使用PrimaryKey。数值从Category中获取。

View File

@@ -1,124 +0,0 @@
# 前端结构
OpenAuth.Mvc前端采用典型的mvc结构部署其中
* Views: 为静态资源页面最终会渲染成html实在不懂百度Asp.Net Mvc中的View
* wwwroot/js: 通用的js组件
* wwwroot/userJs: 业务相关的js代码。通常一个csthml页面对应一个userJs中的js文件。如`Categories\Index.cshtml`对应`userJs\categories.js`
```shell
|-- OpenAuth.Mvc
|-- Views
| |-- _ViewStart.cshtml
| |-- Categories
| | |-- Index.cshtml
| |-- DataPrivilegeRules
| | |-- index.cshtml
| |-- Error
| | |-- Auth.cshtml
| |-- FlowInstances
| | |-- Detail.cshtml
| | |-- Disposed.cshtml
| | |-- Edit.cshtml
| | |-- Index.cshtml
| | |-- Verification.cshtml
| | |-- Wait.cshtml
| |-- FlowSchemes
| | |-- Design.cshtml
| | |-- Index.cshtml
| | |-- NodeInfo.cshtml
| | |-- Preview.cshtml
| |-- Forms
| | |-- Edit.cshtml
| | |-- index.cshtml
| | |-- Preview.cshtml
| |-- Home
| | |-- git.cshtml
| | |-- Index.cshtml
| | |-- Main.cshtml
| |-- Login
| | |-- Index.cshtml
| |-- ModuleManager
| | |-- Assign.cshtml
| | |-- Index.cshtml
| |-- OpenJobs
| | |-- index.cshtml
| |-- OrgManager
| | |-- Index.cshtml
| |-- Redirects
| | |-- IdentityAuth.cshtml
| |-- Resources
| | |-- Assign.cshtml
| | |-- Index.cshtml
| |-- RoleManager
| | |-- Assign.cshtml
| | |-- Index.cshtml
| |-- Shared
| | |-- _Layout.cshtml
| |-- SysLogs
| | |-- index.cshtml
| |-- SysMessages
| | |-- index.cshtml
| |-- UserManager
| | |-- ChangePassword.cshtml
| | |-- Index.cshtml
| | |-- Profile.cshtml
| |-- WmsInboundOrderTbls
| |-- index.cshtml
|-- wwwroot
|-- css
| |-- formpreview.css
| |-- images.css
| |-- login.css
| |-- main.css
| |-- treetable.css
|-- js
|-- bodyTab.js
|-- bootstrap.js
|-- cookie.js
|-- droptree.js
|-- dtree.js
|-- flowlayout.js
|-- iconPicker.js
|-- index.js
|-- leftNav.js
|-- openauth.js
|-- slimscroll.js
|-- utils.js
|-- vue.js
|-- ztree.js
|-- userJs
|-- assignModule.js
|-- assignResource.js
|-- assignRole.js
|-- categories.js
|-- changePwd.js
|-- dataprivilegerules.js
|-- flowinstanceDetail.js
|-- flowInstanceDisposed.js
|-- flowInstanceEdit.js
|-- flowInstances.js
|-- flowInstanceWait.js
|-- flowSchemeDesign.js
|-- flowSchemePreview.js
|-- flowSchemes.js
|-- formEdit.js
|-- forms.js
|-- login.js
|-- main.js
|-- modules.js
|-- nodeInfo.js
|-- openjobs.js
|-- orgs.js
|-- preview.js
|-- profile.js
|-- resources.js
|-- roles.js
|-- syslogs.js
|-- sysmessages.js
|-- users.js
|-- verification.js
|-- wmsinboundordertbls.js
```

View File

@@ -1,9 +0,0 @@
{
"scripts": {
"dev": "vuepress dev .",
"build": "vuepress build ."
},
"devDependencies": {
"vuepress": "^1.4.1"
}
}

View File

@@ -1,9 +0,0 @@
# 常见问题处理
## vue运行的时候报错
在启动企业版的时候,如果提示下面错误:
![](/oidcerror.png)
请使用`npm run dev`命令来启动项目

27
newdocs/README.md Normal file
View File

@@ -0,0 +1,27 @@
# open-auth-net-官方文档
The Site is generated using [vuepress](https://vuepress.vuejs.org/) and [vuepress-theme-plume](https://github.com/pengzhanbo/vuepress-theme-plume)
## Install
```sh
npm i
```
## Usage
```sh
# start dev server
npm run docs:dev
# build for production
npm run docs:build
# preview production build in local
npm run docs:preview
# update vuepress and theme
npm run vp-update
```
## Documents
- [vuepress](https://vuepress.vuejs.org/)
- [vuepress-theme-plume](https://theme-plume.vuejs.press/)

27
newdocs/README.zh-CN.md Normal file
View File

@@ -0,0 +1,27 @@
# open-auth-net-官方文档
网站使用 [vuepress](https://vuepress.vuejs.org/) 和 [vuepress-theme-plume](https://github.com/pengzhanbo/vuepress-theme-plume) 构建生成。
## Install
```sh
npm i
```
## Usage
```sh
# 启动开发服务
npm run docs:dev
# 构建生产包
npm run docs:build
# 本地预览生产服务
npm run docs:preview
# 更新 vuepress 和主题
npm run vp-update
```
## 文档
- [vuepress](https://vuepress.vuejs.org/)
- [vuepress-theme-plume](https://theme-plume.vuejs.press/)

View File

@@ -0,0 +1,31 @@
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2025-04-23 23:37:29
* @LastEditTime: 2025-04-26 15:00:36
* @Description:
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
*/
import { defineClientConfig } from 'vuepress/client'
import { h } from 'vue'
import { Layout } from 'vuepress-theme-plume/client'
// import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue'
// import NpmBadge from 'vuepress-theme-plume/features/NpmBadge.vue'
// import NpmBadgeGroup from 'vuepress-theme-plume/features/NpmBadgeGroup.vue'
// import Swiper from 'vuepress-theme-plume/features/Swiper.vue'
// import CustomComponent from './theme/components/Custom.vue'
// import './theme/styles/custom.css'
import AsideNav from './theme/components/AsideNav.vue'
export default defineClientConfig({
setup() {
// setupThemeColors()
},
layouts: {
Layout: h(Layout, null, {
'aside-outline-after': () => h(AsideNav),
}),
},
})

View File

@@ -0,0 +1,173 @@
import { viteBundler } from '@vuepress/bundler-vite'
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'
export default defineUserConfig({
base: '/',
lang: 'zh-CN',
title: 'OpenAuth.Net',
description: '最好用的.net权限工作流框架,最实用的.net/vue前后端分离方案',
head: [
// 配置站点图标
['link', { rel: 'icon', type: 'image/png', href: 'http://img.openauth.net.cn/2025-04-24-00-50-24.png' }],
],
bundler: viteBundler(),
shouldPrefetch: false, // 站点较大,页面数量较多时,不建议启用
theme: plumeTheme({
/* 添加您的部署域名, 有助于 SEO, 生成 sitemap */
hostname: 'http://doc.openauth.net.cn',
/* 文档仓库配置,用于 editLink */
// docsRepo: '',
// docsDir: 'docs',
// docsBranch: '',
/* 页内信息 */
// editLink: true,
// lastUpdated: true,
// contributors: true,
// changelog: false,
/**
* 博客
* @see https://theme-plume.vuejs.press/config/basic/#blog
*/
// blog: false, // 禁用博客
// blog: {
// postList: true, // 是否启用文章列表页
// tags: true, // 是否启用标签页
// archives: true, // 是否启用归档页
// categories: true, // 是否启用分类页
// postCover: 'right', // 文章封面位置
// pagination: 15, // 每页显示文章数量
// },
/* 博客文章页面链接前缀 */
article: '/article/',
/**
* 编译缓存,加快编译速度
* @see https://theme-plume.vuejs.press/config/basic/#cache
*/
cache: 'filesystem',
/**
* 为 markdown 文件自动添加 frontmatter 配置
* @see https://theme-plume.vuejs.press/config/basic/#autofrontmatter
*/
// autoFrontmatter: {
// permalink: true, // 是否生成永久链接
// createTime: true, // 是否生成创建时间
// title: true, // 是否生成标题
// },
/* 本地搜索, 默认启用 */
search: { provider: 'local' },
/**
* Algolia DocSearch
* 启用此搜索需要将 本地搜索 search 设置为 false
* @see https://theme-plume.vuejs.press/config/plugins/search/#algolia-docsearch
*/
// search: {
// provider: 'algolia',
// appId: '',
// apiKey: '',
// indexName: '',
// },
/**
* Shiki 代码高亮
* @see https://theme-plume.vuejs.press/config/plugins/code-highlight/
*/
// codeHighlighter: {
// twoslash: true, // 启用 twoslash
// whitespace: true, // 启用 空格/Tab 高亮
// lineNumbers: true, // 启用行号
// },
/* 文章字数统计、阅读时间,设置为 false 则禁用 */
// readingTime: true,
/**
* markdown
* @see https://theme-plume.vuejs.press/config/markdown/
*/
markdown: {
plantuml: true,
// abbr: true, // 启用 abbr 语法 *[label]: content
// annotation: true, // 启用 annotation 语法 [+label]: content
// pdf: true, // 启用 PDF 嵌入 @[pdf](/xxx.pdf)
// caniuse: true, // 启用 caniuse 语法 @[caniuse](feature_name)
// plot: true, // 启用隐秘文本语法 !!xxxx!!
bilibili: true, // 启用嵌入 bilibili视频 语法 @[bilibili](bid)
// youtube: true, // 启用嵌入 youtube视频 语法 @[youtube](video_id)
// artPlayer: true, // 启用嵌入 artPlayer 本地视频 语法 @[artPlayer](url)
// audioReader: true, // 启用嵌入音频朗读功能 语法 @[audioReader](url)
// icons: true, // 启用内置图标语法 :[icon-name]:
// codepen: true, // 启用嵌入 codepen 语法 @[codepen](user/slash)
// replit: true, // 启用嵌入 replit 语法 @[replit](user/repl-name)
// codeSandbox: true, // 启用嵌入 codeSandbox 语法 @[codeSandbox](id)
// jsfiddle: true, // 启用嵌入 jsfiddle 语法 @[jsfiddle](user/id)
// npmTo: true, // 启用 npm-to 容器 ::: npm-to
// demo: true, // 启用 demo 容器 ::: demo
// repl: { // 启用 代码演示容器
// go: true, // ::: go-repl
// rust: true, // ::: rust-repl
// kotlin: true, // ::: kotlin-repl
// },
// math: { // 启用数学公式
// type: 'katex',
// },
// chartjs: true, // 启用 chart.js
// echarts: true, // 启用 ECharts
// mermaid: true, // 启用 mermaid
// flowchart: true, // 启用 flowchart
// image: {
// figure: true, // 启用 figure
// lazyload: true, // 启用图片懒加载
// mark: true, // 启用图片标记
// size: true, // 启用图片大小
// },
// include: true, // 在 Markdown 文件中导入其他 markdown 文件内容
// imageSize: 'local', // 启用 自动填充 图片宽高属性,避免页面抖动
},
/**
* 水印
* @see https://theme-plume.vuejs.press/guide/features/watermark/
*/
// watermark: true,
/**
* 评论 comments
* @see https://theme-plume.vuejs.press/guide/features/comments/
*/
// comment: {
// provider: '', // "Artalk" | "Giscus" | "Twikoo" | "Waline"
// comment: true,
// repo: '',
// repoId: '',
// category: '',
// categoryId: '',
// mapping: 'pathname',
// reactionsEnabled: true,
// inputPosition: 'top',
// },
/**
* 资源链接替换
* @see https://theme-plume.vuejs.press/guide/features/replace-assets/
*/
// replaceAssets: 'https://cdn.example.com',
/**
* 加密功能
* @see https://theme-plume.vuejs.press/guide/features/encryption/
*/
// encrypt: {},
}),
})

View File

@@ -0,0 +1,16 @@
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2025-04-23 20:26:48
* @LastEditTime: 2025-04-26 10:31:59
* @Description: 顶部超链接
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
*/
import { defineNavbarConfig } from 'vuepress-theme-plume'
export const navbar = defineNavbarConfig([
{ text: '首页', link: 'http://www.openauth.net.cn', icon: 'mdi:home' },
{ text: '文档首页', link: '/', icon: 'mdi:book-open-page-variant' },
{ text: '开源版文档', link: '/notes/core/README.md', icon: 'logos:opensource' },
{ text: 'vue3版文档', link: '/notes/pro/README.md', icon: 'material-icon-theme:vue' },
{ text: 'vue2版文档', link: '/notes/vue2/README.md', icon: 'material-icon-theme:vue' }
])

View File

@@ -0,0 +1,120 @@
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2025-04-23 20:26:48
* @LastEditTime: 2025-05-07 20:49:08
* @Description: 笔记配置
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
*/
import { defineNoteConfig, defineNotesConfig } from 'vuepress-theme-plume'
//开源后端文档
const coreNote = defineNoteConfig({
dir: 'core',
link: '/core',
sidebar: [
'',
{
text: '基础开发',
collapsed: false,
items: [
'start', 'specialist', 'deploy', 'deployapi', 'devnew', 'multidbs', 'multitenant', 'unitwork','sqlsugar', 'entity','dynamicapi', 'datavalidation', 'log', 'identity', 'job', 'cache', 'unittest','changesdk'
]
},
{
text: '权限控制',
collapsed: true,
items: [
'moduleauth','apiauth', 'logininfo', 'dataprivilege', 'datapropertyrule'
]
},
{
text: '工作流',
collapsed: true,
items: ['form','flowinstance','flowinstanceconcept','flowinstancedev', 'thirdparty' ]
},
{
text: '前端开发',
collapsed: true,
items: ['wwwarchitect']
},
{
text: '其他',
collapsed: true,
items: ['changelog', 'routineupdate','faq']
}
],
})
// vue3版本
const proNote = defineNoteConfig({
dir: 'pro',
link: '/pro',
sidebar: [
'',
{
text: '基础开发',
collapsed: false,
items: ['start','deploy','structure','devnew', 'router','openurl','keepalive','datapropertyrule']
},
{
text: '内置组件',
collapsed: false,
items: ['table','querybuilder','columnsetting','components']
},
'printerplan',
{
text: '表单设计',
collapsed: true,
items: ['startform','urlform','dragform','dragformdetail']
},
{
text: '工作流',
collapsed: true,
items: ['startflow','form']
},
{
text: '其他',
collapsed: true,
items: ['faq']
}
]
})
// vue2版本
const vue2Note = defineNoteConfig({
dir: 'vue2',
link: '/vue2',
sidebar: [
'',
{
text: '基础开发',
collapsed: false,
items: [ 'deploy', 'structure', 'devnew','router','openurl','keepalive']
},
'datapropertyrule',
'printerplan',
{
text: '表单设计',
collapsed: true,
items: ['startform','dragform','dragformdetail']
},
{
text: '工作流',
collapsed: true,
items: ['startflow','form']
},
{
text: '其他',
collapsed: true,
items: ['components','faq']
}
]
})
export const notes = defineNotesConfig({
dir: 'notes',
link: '/',
notes: [coreNote, proNote, vue2Note],
})

View File

@@ -0,0 +1,76 @@
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2025-04-23 20:26:48
* @LastEditTime: 2025-04-24 01:27:38
* @Description: 配置
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
*/
import { defineThemeConfig } from 'vuepress-theme-plume'
import { navbar } from './navbar'
import { notes } from './notes'
/**
* @see https://theme-plume.vuejs.press/config/basic/
*/
export default defineThemeConfig({
logo: 'http://img.openauth.net.cn/2025-04-23-21-21-00.png',
appearance: true, // 配置 深色模式
social: [
{ icon: 'github', link: 'https://gitee.com/dotnetchina/OpenAuth.Net' },
],
// navbarSocialInclude: ['github'], // 允许显示在导航栏的 social 社交链接
// aside: true, // 页内侧边栏, 默认显示在右侧
// outline: [2, 3], // 页内大纲, 默认显示 h2, h3
/**
* 文章版权信息
* @see https://theme-plume.vuejs.press/guide/features/copyright/
*/
// copyright: true,
// prevPage: true, // 是否启用上一页链接
// nextPage: true, // 是否启用下一页链接
// createTime: true, // 是否显示文章创建时间
/* 站点页脚 */
footer: {
message: 'Copyright © 2025 <a target="_blank" href="http://www.openauth.net.cn">OpenAuth.Net</a>',
copyright: '',
},
/**
* @see https://theme-plume.vuejs.press/config/basic/#profile
*/
profile: {
avatar: 'http://img.openauth.net.cn/2025-04-23-21-21-00.png',
name: 'OpenAuth.Net官方文档',
description: '最好用的权限工作流框架',
// circle: true,
// location: '',
// organization: '',
},
navbar,
notes,
/**
* 公告板
* @see https://theme-plume.vuejs.press/guide/features/bulletin/
*/
// bulletin: {
// layout: 'top-right',
// contentType: 'markdown',
// title: '公告板标题',
// content: '公告板内容',
// },
/* 过渡动画 @see https://theme-plume.vuejs.press/config/basic/#transition */
// transition: {
// page: true, // 启用 页面间跳转过渡动画
// postList: true, // 启用 博客文章列表过渡动画
// appearance: 'fade', // 启用 深色模式切换过渡动画, 或配置过渡动画类型
// },
})

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -0,0 +1,86 @@
<!--
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2025-04-26 14:59:00
* @LastEditTime: 2025-04-26 15:02:32
* @Description: 右下角导航
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
-->
<script setup lang="ts">
import { computed } from 'vue'
import { VPLink } from 'vuepress-theme-plume/client'
import { useRouteLocale } from 'vuepress/client'
interface Locale {
star: string
issue: string
sponsor: string
}
const locales: Record<string, Locale> = {
'/': { star: '在 gitee 上 Star', issue: '遇到问题?', sponsor: '喝杯奶茶' },
'/en/': { star: 'Star on GitHub', issue: 'Create Issues', sponsor: 'Buy me a Bubble Tea' },
}
const lang = useRouteLocale()
const locale = computed(() => locales[lang.value])
</script>
<template>
<div class="aside-nav-wrapper">
<VPLink class="link" no-icon href="https://gitee.com/dotnetchina/OpenAuth.Net">
<span class="vpi-github-star" />
<span class="link-text">{{ locale.star }}</span>
<span class="vpi-arrow-right" />
</VPLink>
<VPLink class="link" no-icon href="https://gitee.com/dotnetchina/OpenAuth.Net/issues/new">
<span class="vpi-github-issue" />
<span class="link-text">{{ locale.issue }}</span>
<span class="vpi-arrow-right" />
</VPLink>
<!-- <VPLink class="link" href="/sponsor/">
<span class="vpi-bubble-tea" />
<span class="link-text">{{ locale.sponsor }}</span>
<span class="vpi-arrow-right" />
</VPLink> -->
</div>
</template>
<style scoped>
.aside-nav-wrapper {
display: flex;
flex-direction: column;
padding: 8px 0;
margin: 16px 16px 0;
border-top: solid 1px var(--vp-c-divider);
}
.aside-nav-wrapper .link {
display: flex;
gap: 8px;
align-items: center;
font-size: 14px;
color: var(--vp-c-text-2);
transition: color var(--vp-t-color);
}
.aside-nav-wrapper .link:hover {
color: var(--vp-c-brand-1);
}
.aside-nav-wrapper .link .link-text {
flex: 1 2;
font-size: 12px;
}
.vpi-github-star {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m12 1.5l3.1 6.3l6.9 1l-5 4.8l1.2 6.9l-6.2-3.2l-6.2 3.2L7 13.6L2 8.8l6.9-1z'/%3E%3C/svg%3E");
}
.vpi-github-issue {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='%23000' d='M8 9.5a1.5 1.5 0 1 0 0-3a1.5 1.5 0 0 0 0 3'/%3E%3Cpath fill='%23000' d='M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0M1.5 8a6.5 6.5 0 1 0 13 0a6.5 6.5 0 0 0-13 0'/%3E%3C/svg%3E");
}
.vpi-bubble-tea {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m17.95 9l-1.478 8.69c-.25 1.463-.374 2.195-.936 2.631c-1.2.931-6.039.88-7.172 0c-.562-.436-.687-1.168-.936-2.632L5.95 9M6 9l.514-1.286a5.908 5.908 0 0 1 10.972 0L18 9M5 9h14m-7 0l4-7m-5.99 12h.01m1 4h.01m1.99-2h.01'/%3E%3C/svg%3E");
}
</style>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ref } from 'vue'
const message = ref('Hello World!')
</script>
<template>
<div class="my-custom-content">
{{ message }}
</div>
</template>

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