This commit is contained in:
yubaolee 2023-08-11 17:47:02 +08:00
parent 2968aa27a2
commit 65dfe66dda
73 changed files with 3655 additions and 0 deletions

148
docs/.vuepress/config.js Normal file
View File

@ -0,0 +1,148 @@
/*
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
* @Date: 2020-07-21 23:45:00
* @LastEditTime: 2022-12-20 16:15:43
* @Description:
* @
* @Copyright (c) 2022 by yubaolee | ahfu~ , All Rights Reserved.
*/
module.exports = {
title: 'OpenAuth.Net',
description: '最好用的.net权限工作流框架,最好用的.net vue前后分离框架',
head: [
['link', {
rel: 'icon',
href: '/logo.png'
}]
],
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(.Net Core/.Net 5)',
link: '/core/',
target: '_blank'
},
{
text: 'OpenAuth.Pro(企业版)',
link: '/pro/',
target: '_blank'
},
{
text: '.Net 4.5版本文档',
link: '/net/',
target: '_blank'
},
],
},
{
text: '项目地址',
ariaLabel: 'Proj Menu',
items: [{
text: 'gitee',
link: 'https://gitee.com/yubaolee/OpenAuth.Core',
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'
}
],
},
],
sidebar: {
'/core/': [
['', '项目介绍'],
{
title: '后端开发', // 必要的
path: 'start', // 可选的, 标题的跳转链接,应为绝对路径且必须存在
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['start', 'specialist', 'deploy', 'deployapi', 'devnew', 'multidbs', 'multitenant', 'unitwork', 'entity', 'datavalidation', 'log', 'identity', 'job', 'cache', 'unittest'],
},
{
title: '权限控制', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['apiauth', 'logininfo', 'dataprivilege', 'datapropertyrule'],
},
'form',
{
title: '工作流', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['flowinstance', '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'],
},
'datapropertyrule',
{
title: '表单设计', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['startform','dragform','dragformdetail'],
},
{
title: '工作流', // 必要的
sidebarDepth: 1, // 可选的, 默认值是 1
collapsable: false,
children: ['startflow','form'],
},
'components',
'faq',
],
'/net/': [
['', '项目介绍'], 'start', 'deploy', 'devnew'
],
},
},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

25
docs/README.md Normal file
View File

@ -0,0 +1,25 @@
---
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: 组织机构、角色用户、数据权限、拖拽表单、工作流引擎、定时任务。
- title: 主流技术
details: IdentityServer、EF core、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、VUE、Element-ui。
footer: Copyright © 2022- yubaolee
---

2
docs/core/.vscode/settings.json vendored Normal file
View File

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

74
docs/core/README.md Normal file
View File

@ -0,0 +1,74 @@
![LOGO](/logocore.png "1.png")
OpenAuth.Net是基于 **.Net Core/.Net 5** 的开源权限工作流快速开发框架。框架汲取Martin Fowler企业级应用开发思想及全新技术组合IdentityServer、EF core、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、VUE、Element-ui等核心模块包括组织机构、角色用户、权限授权、表单设计、工作流等。
如果你想了解企业版的内容,请访问:[http://doc.openauth.net.cn/pro](http://doc.openauth.net.cn/pro/)
::: tip 提示
gitee上面两个版本仅SDK的版本不同代码完全相同。其中
* [OpenAuth.Net](https://gitee.com/dotnetchina/OpenAuth.Net) 的SDK版本为5.0.100,推荐使用该版本
* [OpenAuth.Core](https://gitee.com/yubaolee/OpenAuth.Core) 的SDK版本为.Net Core 3.1.100,历史原因暂且保留,未来的某天会关闭它
.Net目前SDK升级特别方便只需花费3分钟时间既可升级到.Net 6/7/8...等。请参考:[3分钟的时间把.net core 3.1的升级到.NET 5](https://www.cnblogs.com/yubaolee/p/Net3ToNet5.html)所以不要纠结SDK版本问题。
:::
## 技术栈
![](https://img.shields.io/badge/release-2.0-blue)
![](https://img.shields.io/badge/.net%20core-3.1.100-blue)
![](https://img.shields.io/badge/.Net-5.0-blue)
![](https://img.shields.io/badge/IdentityServer4-3.0.1-blue)
![](https://img.shields.io/badge/quartz-3.0.7-blue)
![](https://img.shields.io/badge/Autofac-5.1.2-blue)
![](https://img.shields.io/badge/NUnit-3.12-blue)
![](https://img.shields.io/badge/SwaggerUI-OAS%203.0-blue)
![](https://img.shields.io/badge/Moq-4.13-blue)
![](https://img.shields.io/badge/log4net-2.0.8-blue)
![](https://img.shields.io/badge/AutoMapper-9.0-blue)
![](https://img.shields.io/badge/vue-2.6.10-brightgreen)
![](https://img.shields.io/badge/element--ui-2.10.1-brightgreen)
![](https://img.shields.io/badge/node-%3E%3D14.0-brightgreen)
![](https://img.shields.io/badge/npm-6.14-brightgreen)
![](https://img.shields.io/badge/layui-2.5.6-brightgreen)
## 核心看点
* 支持.net core sdk 3.1.100 及.Net 5[一分钟从.net core 3.1切换至.Net 5](https://www.cnblogs.com/yubaolee/p/Net3ToNet5.html)
* 超强的自定义权限控制功能,请参考:[通用权限设计与实现](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)
* 完整的字段权限控制可以控制字段可见及API是否返回字段值
* 可拖拽的表单设计
* 可视化流程设计
* 基于Quartz.Net的定时任务控制,可随时启/停可视化配置Cron表达式功能
* 基于CodeSmith的代码生成功能可快速生成带有头/明细结构的页面
* 支持sqlserver、mysql、Oracle(已集成驱动,但无Oracle脚本可以利用工具把其他数据库的数据导过来理论上支持所有数据库
* 支持同时访问多数据源
* 支持多租户
* 集成IdentityServer4实现基于OAuth2的登录体系
* 建立三方对接规范,已有系统可以无缝对接流程引擎
* 前端采用 vue + layui + elementUI + ztree + gooflow + leipiformdesign
* 后端采用 .net core +EF core+ autofac + quartz +IdentityServer4 + nunit + swagger
* 设计工具 PowerDesigner + Enterprise Architect

46
docs/core/apiauth.md Normal file
View File

@ -0,0 +1,46 @@
# API权限控制
在使用OpenAuth.WebApi过程中系统会对所有的Api进行权限控制。如果没有登录就访问Api接口会提示下面信息
```javascript
{
"message": "认证失败,请提供认证信息",
"code": 401
}
```
如果想正常调用,必需先调用登录接口`/api/Check/Login`拿到登录`token`,如下:
```javascript
{
"returnUrl": "http://localhost:56813",
"token": "e4a5aa00",
"result": null,
"message": "操作成功",
"code": 200
}
```
把token值放置在http header X-Token中即可正常调用其他接口。如下
```javascript
GET /api/Applications/Load?page=1&limit=10 HTTP/1.1
Host: localhost:52789
X-Token: e4a5aa00
```
## 不登录直接访问
有些场景我们需要不进行登录直接访问接口,可以直接在接口上面加[AllowAnonymous]注解即可。如下:
```csharp
[HttpGet]
[AllowAnonymous]
public async Task<TableData> Load([FromQuery]QueryWmsInboundOrderDtblListReq request)
{
return await _app.Load(request);
}
```

61
docs/core/cache.md Normal file
View File

@ -0,0 +1,61 @@
# 缓存机制
## 服务器缓存
在OpenAuth中缓存通过`ICacheContext`接口实现的。系统有三个实现方式:
* 基于.net自带的`MemoryCache`实现的`CacheContext`
* 基于`StackExchange.Redis`实现的`RedisCacheContext`【新增💪】
* 基于`Enyim Memcache`实现的`EnyimMemcachedContext`
可以根据自己需要扩展其他缓存。OpenAuth.Mvc和OpenAuth.Api默认使用的是CacheContext。可以在`AutofacExt.cs`跟换自己喜欢的缓存:
```csharp
public static void InitAutofac(ContainerBuilder builder)
{
...
//更换缓存
builder.RegisterType(typeof(CacheContext)).As(typeof(ICacheContext));
}
```
## 服务器缓存有效时间
服务器默认缓存时间为10天在`LoginParse.cs`中设置
```csharp
_cacheContext.Set(currentSession.Token, currentSession, DateTime.Now.AddDays(10));
```
::: warning 注意事项1
默认使用的是.net的内存Cache在用IIS发布后由于IIS本身存在自动回收的机制会导致系统缓存20分钟就会失效。
:::
::: warning 注意事项2
如果使用Redis缓存注意调整配置文件中关于redis的配置
```csharp
"AppSetting": {
//其他配置..
"RedisConf": "your_redis_server:6379,password=your_redis_password" //redis配置信息
}
```
:::
## 企业版前端缓存
企业版前端使用js-cookie存储登录token信息。默认为`session cookie`也就是这个session在关闭浏览器后会被删除。如果想延长登录有效期限可以调整`src\utils\auth.js`中写入cookie的时间
```javascript
//设置登录有效期为7天
export function setToken(token) {
return Cookies.set(TokenKey, token, { expires: 7 })
}
```

154
docs/core/changelog.md Normal file
View File

@ -0,0 +1,154 @@
# 版本发布
### v4.0
* 【新增】集成Variant Form - 可视化低代码表单;
* 【新增】完成vue3 setup模式单表代码生成
### v3.3
* 【新增】流程表单项增加读写权限控制;
* 【新增】代码生成器增加主从表生成;
* 【新增】代码生成器设置可以控制界面展示;
* 【新增】流程处理增加消息通知;
* 【新增】优化swagger分组
### v3.2
* 【新增】在swagger界面查看接口调用时间及SQL执行时间; [查看使用说明](http://doc.openauth.net.cn/core/log.html#%E5%9C%A8swagger%E4%B8%AD%E8%BE%93%E5%87%BA%E6%97%A5%E5%BF%97 )
* 【新增】swagger接口分组;
* 【新增】流程编辑功能(草稿或驳回状态时);
* 【新增】流程召回功能;
* 【新增】运行时选定执行人、执行角色功能;
* 【新增】自定义模态验证异常返回信息;
* 【新增】配置启动端口;
### v3.1
* 【新增】Oracle数据库驱动
* 【新增】流程召回功能
* 【新增】调整APP层文件结构按功能划分
* 【新增】支持同时配置多个类型数据库的连接字符串,详见:[这里](http://doc.openauth.net.cn/core/multidbs.html)
### v3.0
* 【新增】多数据源支持
* 【新增】提供全新的事务接口方式
* 【新增】新增异步接口
* 【新增】新增灵活的API提交数据验证
* 【新增】新增附件管理,上传图片支持生成缩略图
* 【新增】调整代码生成器把CodeSmith改为站内代码生成
### v2.1
* 【新增】为角色分配用户
* 【新增】为部门分配用户
### v2.0
* 【新增】框架升级至.net core sdk 3.1.100
* 【新增】增加`个人中心`页面,可修改个人信息及切换当前默认部门
* 【优化】升级layui至2.5.6
* 【优化】可以灵活配置用户可访问的机构数据权限
* 【优化】优化会签功能呢
* 【优化】优化角色添加自动关联当前登录用户
### v1.6
* 【优化】优化导航排序、支持多级导航
* 【优化】企业版启用全新登录界面;
* 【新增】启用数据字典功能;
* 【新增】日志及用户消息板块;
* 【新增】企业版代码生成器,可以快速生成带有头/明细结构的页面;
* 【新增】数据权限控制,超强的自定义权限控制功能。详见:[这里](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)
* 【新增】完整的字段权限控制可以控制字段可见及API是否返回字段值
### v1.5
* 【优化】升级layui至2.5.4
* 【优化】流程处理页面展示流转记录;
* 【优化】流程支持角色审批;
* 【新增】集成IdentityServer4实现基于OAuth2的登录体系
* 【新增】建立三方对接规范,已有系统可以无缝对接流程引擎;
### v1.4
* 【优化】升级layui至2.4.5
* 【优化】升级vue至2.6.10
* 【优化】全面重写界面初始化交互优化layui与vue数据初始读取
* 【新增】全面实现数据字段权限控制。针对自定义模块,可以为角色分配可见字段;
* 【新增】模块可隐藏功能,只授权,但不在导航栏显示;
### v1.3
* 基于.Net Core 2.1开发;
* 全面支持sqlserver、mysql数据库
* 全面实现模块控制、菜单控制;
* 完整的代码生成器pro版本提供;
* 前端采用 vue + gooflow + leipiformdesign
* 后端采用 asp.net mvc core 2.1 + EF core+ autofac + json.net
* 代码生成工具 CodeSmith
* 设计工具 PowerDesigner + Enterprise Architect
### OpenAuth.Net 4.0 颠覆版(2018-)
* 版本重构,最重要的一个版本;
* 前后端完全分离,结构更加清晰。`我们不限制规则,只用主流的技术构建强大的框架`
* 前端采用 vue + layui + ztree + gooflow + leipiformdesign
* 后端采用 asp.net mvc + Web API + EF + autofac + swagger + json.net
* 代码生成工具 CodeSmith
* 设计工具 PowerDesigner + Enterprise Architect

View File

@ -0,0 +1,3 @@
# 数据权限
关于数据权限控制,可以详细查看博文:[通用权限设计与实现](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)

View File

@ -0,0 +1,86 @@
# 字段权限
::: warning 注意
字段权限只针对【非系统模块】有效即在添加新模块的时候需要设置模块属性“是否系统”为false。
:::
## 使用场景
字段权限控制分为两种:
1. 直接不返回字段的值。用于敏感数据不向客户端反馈。
1. 返回字段的值但界面不显示。常常用于数据需要和后端交互但不想在界面显示比如各种Id。这种直接在返回实体增加`[Browsable(false)]`注解即可。
## 如何做?
### 后端代码处理
针对场景1在做返回处理的时候需要过滤数据库查询字段如下本文以Resource表为例
```csharp
var columnFields = loginContext.GetTableColumnsFromDb("Resource");
if (columnFields == null || columnFields.Count == 0)
{
throw new Exception("未找到Resource表的字段属性");
}
var propertyStr = string.Join(',', columnFields.Select(u => u.ColumnName));
result.columnFields = columnFields;
result.data = resources.OrderBy(u => u.TypeId)
.Skip((request.page - 1) * request.limit)
.Take(request.limit).Select($"new ({propertyStr})");
result.count = await resources.CountAsync();
return result;
```
::: warning 注意
因为开源版没有代码生成器所以需要直接从数据读取表的字段结构使用的是loginContext.GetTableColumnsFromDb获取可访问的字段
:::
### 前端代码处理
在做表格的时候需要使用动态列。以`Views/Resources/index.cshtml`为例,如下:
```HTML
<table class="layui-table" id="mainList"
lay-data="{height: 'full-80', page:true, id:'mainList'}"
lay-filter="list" lay-size="sm">
</table>
```
在用户自定义的脚本`wwwroot/userJs/resources.js`中,动态加载列:
```javascript
//加载表头
$.getJSON('/Resources/Load',
{ page: 1, limit: 1 },
function (data) {
var columns = data.columnFields.filter(u => u.IsList ===true).map(function (e) {
return {
field: e.ColumnName,
title: e.Comment
};
});
columns.unshift({
type: 'checkbox',
fixed: 'left'
});
table.render({
elem: '#mainList',
page: true,
url: '/Resources/Load',
cols: [columns]
, response: {
statusCode: 200 //规定成功的状态码默认0
}
});
});
```
### 运行界面配置
完成代码编写后,在【基础配置】--【角色管理】--【为角色分配模块】最后为角色分配【可见字段】中分配权限
![](/roleassignproperty.png)

View File

@ -0,0 +1,58 @@
# WebApi请求验证
框架提供灵活的实体模型验证功能。可以方便地对实体进行验证。只需两步即可:
## 增加注解
在请求参数中添加验证注解
```csharp
namespace OpenAuth.App.Request
{
public class UpdateUserReq
{
/// <summary>
/// </summary>
/// <returns></returns>
[Required(ErrorMessage = "账号肯定不能为空啊~~")]
public string Account { get; set; }
/// <summary>
/// 用户姓名
/// </summary>
/// <returns></returns>
[Required(ErrorMessage="姓名不能为空")]
public string Name { get; set; }
/// <summary>
/// 所属组织Id多个可用分隔
/// </summary>
/// <value>The organizations.</value>
[Required(ErrorMessage = "请为用户分配机构")]
public string OrganizationIds { get; set; }
...
}
}
```
## 业务代码中验证
在OpenAuth.App中调用验证
```csharp
namespace OpenAuth.App
{
public class UserManagerApp : BaseApp<User,OpenAuthDBContext>
{
public void AddOrUpdate(UpdateUserReq request)
{
//验证Account/Name/OrganizationIds
request.ValidationEntity(u => new {u.Account,u.Name, u.OrganizationIds});
...//其他代码略
}
}
}
```

79
docs/core/deploy.md Normal file
View File

@ -0,0 +1,79 @@
# 部署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.Core采用的是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
nohup dotnet /data/openauthmvc/OpenAuth.Mvc.dll &
echo '============================end build======================================='
```

87
docs/core/deployapi.md Normal file
View File

@ -0,0 +1,87 @@
# 部署API
## 生成发布文件
* 修改部署环境的连接字符串信息,特别注意是`appsettings.Production.json`文件:
![20220101232738](http://img.openauth.net.cn/20220101232738.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.WebApi右键【发布】出现下面的配置框使用文件系统即可
![20220101232912](http://img.openauth.net.cn/20220101232912.png)
* 发布完成后可以在输出目录看到发布详情(红色框内即为发布的文件夹):
![20220101233049](http://img.openauth.net.cn/20220101233049.png)
* 将Debug目录中的OpenAuth.WebApi.xml拷贝到发布文件夹publish:
![20220101235436](http://img.openauth.net.cn/20220101235436.png)
## 部署OpenAuth.WebApi
将发布后的文件拷贝到服务器文件夹。直接使用`dotnet OpenAuth.WebApi.dll` 命令启动。启动成功后使用浏览器打开[http://localhost:52789/swagger/index.html](http://localhost:52789/swagger/index.html) 即可访问,如下图所示:
![20220101233542](http://img.openauth.net.cn/20220101233542.png)
## jenkins部署OpenAuth.WebApi
OpenAuth.Core采用的是gitee托管源码只需使用Gitee WebHook构建触发器。配置如下
![说明](/giteesource.png "说明")
做好上面的配置后代码提交时就会触发jenkins工作。剩下的就是编写自己的构建脚本。增加构建步骤选择执行Shell。并输入以下脚本
```shell
#!/bin/bash
kill -9 $(ps -ef|grep OpenAuth.WebApi.dll|grep -v grep|awk '{print $2}')
#export BUILD_ID=dontKillMe这一句很重要这样指定了项目启动之后才不会被Jenkins杀掉。
export BUILD_ID=dontKillMe
pwd
echo $PATH
dotnet restore
cd ./OpenAuth.WebApi
pwd
echo '============================begin build======================================='
dotnet build # 为了生成XML注释文件 用于swagger注释
rm -rf /data/openauthapi
mkdir /data/openauthapi
cp ./bin/Debug/netcoreapp3.1/OpenAuth.Repository.xml /data/openauthapi/
cp ./bin/Debug/netcoreapp3.1/OpenAuth.App.xml /data/openauthapi/
cp ./bin/Debug/netcoreapp3.1/Infrastructure.xml /data/openauthapi/
dotnet publish -c:Release -o /data/openauthapi # 如果针对给定运行时发布项目带上-r 如:-r centos.7-x64
nohup dotnet /data/openauthapi/OpenAuth.WebApi.dll &
#cp ./bin/Debug/netcoreapp2.0/您的项目路径.xml $WORKSPACE/jenkins_publish/ # 拷贝swagger注释
echo '============================end build======================================='
```

80
docs/core/devnew.md Normal file
View File

@ -0,0 +1,80 @@
# 添加新模块
## 前言
OpenAuth.Mvc添加新模块的方式非常简单完全可以参考系统已有的`资源管理`模块编写相应的代码。参考的`资源管理`功能对应的代码如下:
![](http://pj.openauth.net.cn/zentao/file-read-55.png)
如果我们想新加一个仓储管理的模块,模块标识为`Stock`。那么需要添加的文件如下:
├─OpenAuth.Mvc
│ ├─ Controllers
│ │ └─ StocksController.cs
│ ├─ Views
│ │ └─ Stocks
│ │ └─ index.cshtml
│ ├─ wwwroot
│ │ └─ userJs
│ │ └─ stock.js
├─OpenAuth.App
│ ├─ StockApp.cs
│ ├─ Request
│ │ └─ QueryStockReq.cs
├─ OpenAuth.Repository
│ ├─ OpenAuthDBContext.cs
│ ├─ Domain
│ └─ Stock.cs
当然全部手撸这些代码还是会疯的。用户可以直接使用项目`CodeSmith`文件夹里面的模板一键生成上述代码。而且CodeSmith模板本身也是全部源码可以根据自己需求调整生成的内容。
## 工具准备
CodeSmith Generator Studio 8.0或以上
数据库OpenAuthDB中添加仓储表【Stock】本文以该数据表为例
## 添加实体
如下图使用CodeSmith文件夹中的模板右击【ApiGenerate.cst】--【Execute】选择需要生成的表本文以Stock为例及相关的上下文命名空间点击【Generate】
![](http://pj.openauth.net.cn/zentao/file-read-26.jpg)
生成成功后在CodeSmith/Csharp文件夹下面会有Stock实体相关文档如下图
![](http://pj.openauth.net.cn/zentao/file-read-53.png)
把CSharp\OpenAuth.App覆盖到自己项目对应目录
把CSharp\OpenAuth.Repository\Domain覆盖到自己项目对应目录
**把CSharp\OpenAuth.Repository\OpenAuthDBContext.cs中的内容添加到自己项目的文件中千万不要直接覆盖文件**
**其他文件夹的内容为WebAPI项目使用可以不管。**
## 添加界面
如下图使用CodeSmith文件夹中的模板右击【WebGenerate.cst】--【Execute】选择需要生成的表本文以Stock为例及相关的上下文命名空间点击【Generate】
![](http://pj.openauth.net.cn/zentao/file-read-47.png)
生成成功后在CodeSmith/Csharp文件夹下面会有相关的界面代码如下图
![](http://pj.openauth.net.cn/zentao/file-read-50.png)
Controllers、Views直接覆盖到OpenAuth.Mvc项目中对应的文件夹即可
userJs直接覆盖到OpenAuth.Mvc/wwwroot中
## 添加模块
编写完上面代码后运行系统使用System账号登录系统在【模块管理】中添加`仓储管理`模块并为它添加菜单这里我只添加一个菜单【btnAdd】如下图
![](http://pj.openauth.net.cn/zentao/file-read-51.png)
重新登录系统,即可看到新加的仓储管理模块。
![](http://pj.openauth.net.cn/zentao/file-read-52.png)

127
docs/core/entity.md Normal file
View File

@ -0,0 +1,127 @@
# 数据库实体
## 更换主键名称
系统默认的主键是以`Id`命名,如果数据库主键是其他名称,可以直接用注解进行更改:
```csharp
[Column("CustomerId")]
public string Id { get; set; }
```
## 如何添加主键类型为numberic的业务代码
如果数据库表中存在其他类型的主键,可以通过继承`BaseEntity`实现。目前系统默认有三个实体基类:
- `StringEntity`针对数据库主键为varchar类型的数据表,主键按guid方式生成;
- `LongEntity`针对数据库主键为numberic(15)的数据表,主键按雪花算法生成;【新功能,官方推荐使用方式👍】
- `IntAutoGenEntity`针对数据库主键为numberic且为数据库自动生成的类型表通常为SqlServer的自动增长类型和Oracle的Sequence生成【新功能】
这三个基类可以覆盖90%以上的业务场景。如果这两个不能满足需求,可以自己按需求扩展。参考代码如下:
```csharp
/// <summary>
/// 数据库Id为int类型的数据实体使用该基类用法同Entity
/// </summary>
public class IntEntity :BaseEntity
{
[Browsable(false)]
public int Id { get; set; }
public override bool KeyIsNull()
{
return Id == 0;
}
/// <summary>
/// 需要自己有个生成随机ID的算法可参考LongEntity中的雪花算法
/// </summary>
public override void GenerateDefaultKeyVal()
{
Id = RandomInt();
}
}
```
## 具体如何做
我们以一个主键为numeric(16)的表表名为LongTable为例
```SQL
create table LongTable
(
Id numeric(16) not null
constraint LongTable_pk
primary key nonclustered,
Name varchar(50)
)
go
```
1. 首先创建对应的业务实体。在`OpenAuth.Repository.Domain`中添加:
```csharp
namespace OpenAuth.Repository.Domain
{
[Table("LongTable")]
public class LongTable :LongEntity
{
public string Name { get; set; }
}
}
```
2. 修改`OpenAuth.Repository.OpenAuthDBContext`,增加成员变量:
```csharp
public virtual DbSet<LongTable> IntTables { get; set; }
```
3. 最后创建对应的业务层代码。在`OpenAuth.App`中添加:
```csharp
namespace OpenAuth.App
{
/// <summary>
/// 主键为numberic类型的业务使用BaseLongApp基类
/// </summary>
public class LongTableApp :BaseLongApp<LongTable, OpenAuthDBContext>
{
public void Add(LongTable application)
{
Repository.Add(application);
}
public void Update(LongTable application)
{
Repository.Update(application);
}
public async Task<List<LongTable>> GetList(QueryAppListReq request)
{
var applications = UnitWork.Find<LongTable>(null) ;
return applications.ToList();
}
public LongTableApp(IUnitWork<OpenAuthDBContext> unitWork, IRepository<LongTable,OpenAuthDBContext> repository,IAuth auth)
: base(unitWork, repository, auth)
{
}
}
}
```
然后就可以像其他应用服务一样使用这个服务
::: warning 注意
最新版才支持以前的版本2.0或以前的版本可以参考BaseEntity进行改造
:::

108
docs/core/faq.md Normal file
View File

@ -0,0 +1,108 @@
# 常见问题处理
## 注释的使用
在Controller返回给前端的字段上通常会有两个“注释”如下
```csharp
/// <summary>
/// 用户登录帐号
/// </summary>
[Description("用户登录帐号")]
public string Account { get; set; }
```
开发者在使用的时候会觉得多余。但他们的用途不同:
* /// 注释是真正的代码注释用于方便读取代码并为swagger提供字段解释
* Description注解是当前端表格需要动态表头时返回的表头中文说明
## 项目显示不可用
![](/notavailable.png)
这种情况一般是开发工具或SDK的版本号不对。严格按照下面的提示打开项目
* v2.0及以后版本因使用.net core 3.1必须使用visual Studio 2019及以上版本打开
* v2.0以前的版本可以使用visual Studio 2017 及.net core 2.1.4
## 系统使用Sql Server 2008数据库的问题
在使用Sql Server 2008时会提示下面错误
> System.Data.SqlClient.SqlException:“'OFFSET' 附近有语法错误。在 FETCH 语句中选项 NEXT 的用法无效。
因为SQL SERVER 2008 不支持FETCH分页方式所以需要在startup.cs中修改配置
```csharp
optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=OpenAuthDB;User=sa;Password=123456;Integrated Security=True;",
b => b.UseRowNumberForPaging());
```
即使用rownumber的分页方式。 当然最好的解决方式是升级SQL SERVER到2012或以上版本。
::: warning 注意
OpenAuth.Core 2.0及以后版本因为使用了.net core 3.1该SDK已经放弃了这种方式因此只能通过升级Sql Server的方式解决该问题
:::
## 使用mysql时提示无法找到openauthdb.Org
在linux下面mysql是区分数据库大小写的但OpenAuth.Core使用EF映射数据库表是按照首字母大写来处理的。在mysql配置中里面加上
```shell
lower_case_table_names=1
```
从而不区分大小写,即可解决该问题
## WebApi里增加一个控制器,Swagger不显示
需要在控制器上面添加注释,如:
```csharp
/// <summary> 文件上传</summary>
[Route("api/[controller]/[action]")]
[ApiController]
public class FilesController :ControllerBase
```
## 实体没有主键
定义一个实体有时会出现没有主键的问题即提示“Unable to track an instance of type xxxx because it does not have a primary key.”,这时可以强制在`OpenAuthDbContext.cs`中指定一个主键,如下:
```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<DataPrivilegeRule>()
.HasKey(c => new { c.Id });
}
```
## 新添加数据,马上执行【删除】,不能删除数据库记录
原因新增记录时没有返回新增数据的ID信息导致删除不成功。
#### 解决方法一
重新加载列表,直接把 this.list.unshift(this.temp)换成this.getList()。如下:
```javascript
createData() {
// 保存提交
this.$refs['dataForm'].validate((valid) => {
if (valid) {
categorys.add(this.temp).then(() => {
this.getList();
...
})
}
})
},
```
#### 解决方法二
执行添加后把Id返回给前端界面。详情请参考网友博客[OpenAuth.net入门【5】——解决添加完数据在未刷新列表时执行删除数据未被真正删除的问题](https://www.cnblogs.com/wjx-blog/p/15892811.html)

53
docs/core/flowinstance.md Normal file
View File

@ -0,0 +1,53 @@
# 基本操作
一个完整的工作流包括流程设计及流程实例处理。分别对应系统中【基础配置/流程设计】及【流程中心】两个板块。具体包含以下几个步骤:
1. 在【基础配置/表单设计】中添加一个用于流程的表单开源版可使用动态表单企业版支持拖动表单及自定义的vue组件表单
1. 在【基础配置/流程设计】中添加一个流程模版,流程模版选择刚刚建的表单。建好流程模版,拥有该模版权限的用户就可以基于改模版创建流程实例了;
1. 在【流程中心/我的流程】中【新的申请】创建一个流程实例。创建成功后就可以在列表中看到该流程。流程节点对应的执行用户会在【流程中心/待处理流程】中看到该流程,选中需要审批的流程,点击【处理】按钮即可进行审批操作;
# 流程审批逻辑
当最终用户在【待处理流程】中审批一个流程实例时,流程实例会经过下面步骤进行处理:
@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

@ -0,0 +1,123 @@
# 流程实例
流程实例指正在运行的一个流程。数据存放在FlowInstance表中该表核心字段如下
#### IsFinish流程的当前状态
- -1 草稿/召回:流程发起人主动撤销流程;【新增】
- 0 正在运行;
- 1 完成:流程结束,同时所有的审批都通过;
- 3 不同意:即流程结束,同时审批人员没有通过;
- 4 驳回:流程结束,可能发起的流程内容有问题,要求被驳回重新提交;
#### 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

16
docs/core/form.md Normal file
View File

@ -0,0 +1,16 @@
# 表单设计
OpenAuth.Net内置的表单类型有以下三种
## 动态表单
动态表单适用于灵活设计界面,逻辑简单的表单。这种表单无需编码,即可直接集成到流程功能。
## 自定义开发表单【企业版】
该类型表单需要开发者在源码中先编写好表单界面基于vue component,再提供给用户选择使用。适用于交互复杂的界面。详细请参考:[企业版工作流添加自定义表单](/pro/form.html)
## 可拖拽表单【企业版】
适用场景和普通的动态表单一样。但该表单操作方便,与系统界面风格匹配度高,缺点是排版没有普通的动态表单灵活,只能做简单的行排列。详细请参考:[可拖拽表单](/pro/dragform.html)

74
docs/core/identity.md Normal file
View File

@ -0,0 +1,74 @@
# 登录认证及OAuth集成
OpenAuth.Net支持两种登录认证方式自定义token认证和基于IdentityServer的OAuth认证。
这两种方式通过配置webapi或mvc的appsettings.json可以自由切换:
```json
"IdentityServerUrl": "http://localhost:12796", //IdentityServer服务器地址。如果为空则不启用OAuth认证
```
1. 当IdentityServerUrl为空时采用普通的token认证这时不需要OpenAuth.Identity启动支持。
2. 当IdentityServerUrl配置了地址时则采用Identity认证方式。
## OpenAuth.Mvc OAuth认证
当启用了Identity时系统启动后界面如下
![MVC启用identity](/mvcidentity.png "mvcidentity")
这时点击登录超链接会跳转到OpenAuth.Identity登录界面。效果如下
![](/identity.png)
## OpenAuth.WebApi普通token认证
当IdentityServerUrl配置为空时采用普通的token认证客户端在访问的接口时先调用登录接口,得到授权token
![20220119182845](http://img.openauth.net.cn/20220119182845.png)
然后把获取到的token值添加到http header的X-Token中,即可调用对应的API接口。
![20220119182853](http://img.openauth.net.cn/20220119182853.png)
## OpenAuth.WebApi OAuth
当启用了Identity时客户端调用API需要先通过OpenAuth.IdentityServer服务器的OAuth验证才能调用接口。OpenAuth.Net调用API的客户端有两种
#### SwaggerUI
当我们启动了OpenAuth.WebApi在浏览器打开[http://localhost:52789/swagger/index.html](http://localhost:52789/swagger/index.html)时其实是Swagger框架给我们生成的一个调动客户端对于启用了Identity的服务Swagger会有一个Authorise的操作按钮
![20220119180445](http://img.openauth.net.cn/20220119180445.png)
![20220119180503](http://img.openauth.net.cn/20220119180503.png)
点击登录超链接会跳转到OpenAuth.Identity登录界面。登录成功后会自动跳转回来。提示授权成功
![20220119180546](http://img.openauth.net.cn/20220119180546.png)
这时所有的接口都可以直接访问访问时会在http头上自动加认证信息
![20220119180608](http://img.openauth.net.cn/20220119180608.png)
#### OpenAuth.Pro
在使用企业版vue界面访问OpenAuth.WebApi时已经在文件`.env.dev`中配置好相关选项,可以直接使用,无需其他处理。
```python
VUE_APP_OIDC_AUTHORITY = http://localhost:12796 #Identity服务器地址
VUE_APP_OIDC_CLIENTID = OpenAuth.Pro #客户端名称
VUE_APP_OIDC_REDIRECTURI = http://localhost:1803/#/oidc-callback #登录回调
VUE_APP_OIDC_POSTLOGOUTREDIRECTURI = http://localhost:1803 #退出登录回调
VUE_APP_OIDC_RESPONSETYPE = code #认证方式
VUE_APP_OIDC_SCOPE = openid profile openauthapi #认证范围
VUE_APP_OIDC_AUTOMATICSILENTRENEW = true
VUE_APP_OIDC_SILENTREDIRECTURI = http://localhost:1803/silent-renew-oidc.html
```

48
docs/core/job.md Normal file
View File

@ -0,0 +1,48 @@
# 定时任务
::: tip 提示
定时任务基于Quartz.Net开发
:::
## 编写任务代码
在OpenAuth.App中编写定时任务的执行代码。比如`TestJob`
```csharp
namespace OpenAuth.App.Jobs
{
public class TestJob : IJob
{
private OpenJobApp _openJobApp;
public TestJob(OpenJobApp openJobApp)
{
_openJobApp = openJobApp;
}
public Task Execute(IJobExecutionContext context)
{
var jobId = context.MergedJobDataMap.GetString(Define.JOBMAPKEY);
//todo:获取到定时任务的id可以可以加入自己的自动任务逻辑
_openJobApp.RecordRun(jobId);
return Task.Delay(1);
}
}
}
```
## 添加任务执行规则
编写完任务的执行代码后即可运行系统,在界面【基础配置】-【定时任务】中添加任务的执行规则,如图:
![](/addjob.png)
添加任务规则后,在界面直接点击`启用`即可
::: tip 提示
企业版提供可视化的CRON编辑界面,如图:
![](/addjobpro.png)
:::

120
docs/core/log.md Normal file
View File

@ -0,0 +1,120 @@
# 日志操作
## 普通日志
框架默认使用Log4Net作为记录日志的方式可以在Program.cs中配置日志参数或调整为其他日志。日志默认按日期生成日志文件并存放在`log\`目录下。简单用法如下:
```csharp
//具体代码参考OpenAuth.App/OpenJobApp.cs此处简化真实逻辑方便理解
public void RecordRun(string jobId)
{
//其他代码略
_logger.LogInformation($"运行了自动任务:{job.JobName}");
}
public OpenJobApp(IUnitWork unitWork, IRepository<OpenJob> repository,
IAuth auth, ILogger<OpenJobApp> logger) : base(unitWork, repository, auth)
{
_logger = logger;
}
```
## 数据库日志
如果想使用数据库记录业务日志(如系统默认的用户操作日志等),可以使用`SysLogApp`模块功能。日志可以在站点【消息日志】->【系统日志】中查看到记录的日志信息。简单用法如下:
```csharp
//具体代码参考OpenAuth.App/OpenJobApp.cs此处简化真实逻辑方便理解
public void RecordRun(string jobId)
{
//其他代码略
_sysLogApp.Add(new SysLog
{
CreateName = "Quartz",
CreateId = "Quartz",
TypeName = "定时任务",
TypeId = "AUTOJOB",
Content = $"运行了自动任务:{job.JobName}"
});
}
public OpenJobApp(IUnitWork<OpenAuthDBContext> unitWork, IRepository<OpenJob,OpenAuthDBContext> repository,
IAuth auth, SysLogApp sysLogApp) : base(unitWork, repository, auth)
{
_sysLogApp = sysLogApp;
}
```
## EF打印Sql日志
在调试数据库时需要打印真正执行的SQL信息。最简单的方式是使用下面方法输出到控制台
```csharp
public partial class OpenAuthDBContext : DbContext
{
public static readonly ILoggerFactory MyLoggerFactory
= LoggerFactory.Create(builder => { builder.AddConsole(); });
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableSensitiveDataLogging (true); //允许打印参数
optionsBuilder.UseLoggerFactory (MyLoggerFactory);
base.OnConfiguring (optionsBuilder);
}
}
```
## EF输出Sql到log4net
框架目前直接配置`appsettings.Development.json`即可完成输出sql语句到log4net对应的日志文件中。如下
```
"Logging": {
"LogLevel": {
"Microsoft.EntityFrameworkCore.Database.Command": "Information" //EF输出SQL语句
}
}
```
正式发布环境下,如无特殊需求,建议在`appsettings.Production.json`配置中关闭该输出
## 在Swagger中输出日志
框架集成mini profiler工具在swagger中或其他客户端调用WebApi接口时可以直接在swagger中显示日志信息需要刷新。如下图
![](/miniprofiler1.png)
点击`sql`列的时间查看详细的sql执行情况
![](/miniprofiler2.png)
如果需要订制日志信息,查看更详细的日志情况,可以自己调整代码实现。以登录接口为例,添加以下代码:
```csharp
[HttpPost]
[AllowAnonymous]
public LoginResult Login(PassportLoginRequest request)
{
var result = new LoginResult();
using (MiniProfiler.Current.Step("步骤一"))
{
result = _authUtil.Login(request.AppKey, request.Account, request.Password);
}
using (MiniProfiler.Current.Step("步骤二"))
{
//代码略
}
using (MiniProfiler.Current.Step("步骤三"))
{
//代码略
}
return result;
}
```
这时调用该API后即可看到具体步骤一、步骤二、步骤三的执行时间情况了

29
docs/core/logininfo.md Normal file
View File

@ -0,0 +1,29 @@
# 登录信息
框架在应用层任意业务逻辑中,均可以通过`IAuth`接口判断是否登录和获取登录信息。所有继承BaseApp的业务逻辑可以直接使用`_auth`成员变量直接获取登录用户信息。
```csharp
public class RoleApp : BaseApp<Role,OpenAuthDBContext>
{
/// <summary>
/// 加载当前登录用户可访问的全部角色
/// </summary>
public List<Role> Load(QueryRoleListReq request)
{
var loginUser = _auth.GetCurrentUser();
if (loginUser == null)
{
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
}
//其他代码略
}
public RoleApp(IUnitWork<OpenAuthDBContext> unitWork, IRepository<Role,OpenAuthDBContext> repository,IAuth auth) : base(unitWork, repository, auth)
{
}
}
```

98
docs/core/multidbs.md Normal file
View File

@ -0,0 +1,98 @@
# 配置多数据库
框架支持同时访问多个数据库。具体操作如下:
## 添加新数据库连接字符串
在配置文件appsettings.json中添加新的连接字符串`OpenAuthDBContext2`
```csharp
"ConnectionStrings": {
"OpenAuthDBContext": "Data Source=.;Initial Catalog=OpenAuthPro;User=sa;Password=000000",
"OpenAuthDBContext2": "Data Source=.;Initial Catalog=OpenAuthDB;User=sa;Password=000000"
}
"AppSetting": {
"DbTypes": {
"OpenAuthDBContext":"SqlServer" //数据库类型SqlServer、MySql、Oracle
,"OpenAuthDBContext2":"SqlServer" //链接字符串OpenAuthDBContext2对应的数据库类型
}
}
```
## 添加新的数据上下文
在OpenAuth.Repository中添加新的数据库上下文比如`OpenAuthDBContext2`
```csharp
public class OpenAuthDBContext2 : DbContext
{
private IConfiguration _configuration;
private ILoggerFactory _LoggerFactory;
private const string _connectstr = "OpenAuthDBContext2";
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory (_LoggerFactory);
string connect = _configuration.GetConnectionString(_connectstr);
if (string.IsNullOrEmpty(connect))
{
throw new Exception($"未能找到{_connectstr}对应的连接字符串信息");
}
//这个地方如果用IOption在单元测试的时候会获取不到AppSetting的值😅
var dbtypes = _configuration.GetSection("AppSetting:DbTypes").GetChildren()
.ToDictionary(x => x.Key, x => x.Value);
var dbType = dbtypes[_connectstr];
if (dbType == Define.DBTYPE_SQLSERVER)
{
optionsBuilder.UseSqlServer(connect);
}
else if(dbType == Define.DBTYPE_MYSQL) //mysql
{
optionsBuilder.UseMySql(connect);
}
else
{
optionsBuilder.UseOracle(connect);
}
base.OnConfiguring (optionsBuilder);
}
public OpenAuthDBContext2(DbContextOptions<OpenAuthDBContext2> options,
ILoggerFactory loggerFactory,IConfiguration configuration)
: base(options)
{
_LoggerFactory = loggerFactory;
_configuration = configuration;
}
... //其他代码请参考OpenAuthDbContext
}
```
## 注入新数据库
在项目OpenAuth.WebApi等的启动代码`Startup.cs`中,注入刚刚添加的数据库
```csharp
services.AddDbContext<OpenAuthDBContext2>();
```
## 编写业务代码
我们以系统日志模块为例,只需要调整以下代码,然后运行就可以发现,日志已经全部记录到新的数据库中。
```csharp
public class SysLogApp : BaseApp<SysLog,OpenAuthDBContext2>
{
public SysLogApp(IUnitWork<OpenAuthDBContext2> unitWork, IRepository<SysLog,OpenAuthDBContext2> repository) : base(unitWork, repository, null)
{
}
...//剩余的代码和系统自带的模块完全一致
}
```

80
docs/core/multitenant.md Normal file
View File

@ -0,0 +1,80 @@
# 多租户
目前市面上主流的多租户方案有三种:
1. **独立数据库** 即为不同的租户提供独立的数据库。
1. **共享数据库独立Schema** 即多个或所有租户共享一个数据库实例但是每个租户一个Schema也可叫做一个user。底层库比如是DB2、ORACLE等一个数据库下可以有多个SCHEMA。
1. **共享数据库共享Schema共享数据表** 即租户共享同一个数据库实例、同一个Schema但在表中增加TenantID多租户的数据字段在程序逻辑上进行区分。
为了兼容以前的版本OpenAuth采用的是第一种方式即为每个租户建一个新的数据库然后通过客户端请求的租户IdtenantId来分离数据。
## 如何增加一个新租户?
#### 后端添加
后端添加新租户连接字符串即可:
```javascript
"ConnectionStrings": {
"new_tenantid": "server=127.0.0.1;user id=root;database=openauthpro;password=000000" //新租户id对应的连接字符串
},
```
::: warning 注意
这里为了方便理解租户id用的是`new_tenantid`,真实环境里最好用类似UUID风格的无意义id
:::
#### 前端添加
比如在vue element-ui中,在登录时增加选择租户列表:
```html
<el-select v-model="tenant" placeholder="请选择" @change="tenantChange">
<el-option
v-for="item in tenants"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
export default {
name: 'login',
data() {
return {
tenant: this.tenantid || 'OpenAuthDBContext', //当前选择的租户
tenants:[{
value: 'OpenAuthDBContext',
label: '默认租户'
},{ //添加的新租户
value: 'new_tenantid',
label: '新租户'
}]
}
}
}
```
前端在所有http请求的时候在请求头中增加`tenantId`信息,保证每次请求带上租户信息。比如用axios请求时
```javascript
// 创建axios实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // api的base_url
timeout: 50000 // 请求超时时间
})
// request拦截器
service.interceptors.request.use(config => {
config.headers['tenantId'] = store.getters.tenantid
//其他代码略...
})
```

217
docs/core/routineupdate.md Normal file
View File

@ -0,0 +1,217 @@
# 日常提交(针对dev分支)
* 2022.12.22 退出登录时清空tag标签;
* 2022.12.20 修复多个模块名称相同时只能打开一个的BUG;
* 2022.12.17 fix 流程发起页面切换vform不能正常执行onCreated脚本;
* 2022.12.15 升级vform到2.3.6;
* 2022.11.26 修复[事务中使用异步方式后报错](https://gitee.com/dotnetchina/OpenAuth.Net/issues/I63AOC);
* 2022.11.18 修复[拖拽表单不能关联数据库](https://gitee.com/dotnetchina/OpenAuth.Net/issues/I61V1D);
* 2022.10.05 完成vue3多表代码生成器模版;
* 2022.10.01 增加vue3多表代码生成器模版;
* 2022.09.21 完成vue3 setup模式单表代码生成;
* 2022.09.15 增加vue3代码生成器模版完成单表动态头部生成;
* 2022.09.12 代码生成器增加vue3参数;
* 2022.08.15 修复选择租户;
* 2022.08.14 修复左侧导航栏异常;
* 2022.08.13 完成vue3版本流程设计、流程处理及展示;
* 2022.08.03 完成vue3版本流程图工具、画布处理;
* 2022.07.26 完成vue3 jsplumb引入;
* 2022.06.14 完成vue3版本表单设计器;
* 2022.06.12 完成vue2版本表单设计器;
* 2022.05.12 初始化vue3+vite版本;
* 2022.01.19 增加对sql只返回string的支持;
* 2022.01.17 修复添加表单时如果关联的数据库已存在的bug
* 2022.01.15 增加拖动表单生成数据库表
* 2022.01.03 增加plantuml支持
* 2022.01.01 增加API部署说明
* 2021.12.28 增加工作流添加自定义表单
* 2021.12.10 修复非动态头部生成vue界面时异常
* 2021.12.08 主从表以ParentId为准而不是DetailTable
* 2021.12.07 sqlserver float类型对应C# double类型
* 2021.11.30 修复子表加载失败的问题
* 2021.11.14 修复代码生成器
* 2021.11.04 简化代码
* 2021.10.18 采用代码生成器的表结构控制前端显示
* 2021.10.03 升级EF及所有三方的版本
* 2021.09.22 fix issue [OpenAuth.Pro前端可编辑数量为单数时只显示单数减一的字段数](https://gitee.com/yubaolee/OpenAuth.Core/issues/I4BBIG)
* 2021.09.11 发布3.3版;
* 2021.09.08 fix issue [删除角色后用户还有角色模块访问权限](https://gitee.com/dotnetchina/OpenAuth.Net/issues/I494N1)
* 2021.09.05 完成主从表生成;
* 2021.09.02 完成单个表格vue的生成
* 2021.08.31 使用全新的头部渲染;
* 2021.08.23 可以动态控制复杂界面显示编辑权限,采用代码生成的表定义来控制;
* 2021.07.09 流程审批时增加可编辑表单处理;
* 2021.07.02 fix issue 兼容oracle 11g
* 2021.06.22 系统消息按时间倒序排列;
* 2021.06.18 使用雪花算法做Id时出现异常
* 2021.06.15 修复加载消息列表异常;
* 2021.06.13 增加系统消息;
* 2021.06.02 删除已过期文件,优化注释;
* 2021.05.26 流程处理增加消息通知;
* 2021.05.24 集成miniprofiler可以监控API运行情况。[查看使用说明](http://doc.openauth.net.cn/core/log.html#%E5%9C%A8swagger%E4%B8%AD%E8%BE%93%E5%87%BA%E6%97%A5%E5%BF%97 )
* 2021.05.23 [模块管理页面加载时默认显示第一条](https://gitee.com/dotnetchina/OpenAuth.Net/issues/I3RUOR)
* 2021.05.21 新增编辑流程功能(草稿和驳回状态);
* 2021.05.17 [增加配置启动端口](https://gitee.com/dotnetchina/OpenAuth.Net/issues/I3QUV1)
* 2021.05.14 调整样式添加刷新页面tag标签保留功能
* 2021.05.12 [修复拖动表单上传异常](https://gitee.com/dotnetchina/OpenAuth.Net/issues/I3QN22)
* 2021.05.09 增加自定义模态验证异常返回信息;
* 2021.05.08 合并PR[增加API访问审计;禁用.net自动模态验证,采用系统全局异常捕获机制](https://gitee.com/dotnetchina/OpenAuth.Net/pulls/12)
* 2021.05.07 swagger增加分组的功能
* 2021.05.06 fix issue [会签节点异常,提示'-1' was not present in the dictionary](https://gitee.com/dotnetchina/OpenAuth.Net/issues/I3PE3R)
* 2021.05.01 fix issue [CodeSmith生成的后端代码报错](https://gitee.com/yubaolee/OpenAuth.Core/issues/I3OXJZ)
* 2021.04.28 增加站点启动时自动运行状态为【正在运行】的定时任务;
* 2021.04.27 增加存储过程调用的支持;
* 2021.04.26 fix issue [生成的更新字段不包含默认的CreateUser等](https://gitee.com/yubaolee/OpenAuth.Core/issues/I3O5S3)
* 2021.04.25 增加流程执行时可以选择用户或角色(而不是设计时选择);
* 2021.04.21 不同的租户,可以连不同类型数据库;
* 2021.04.16 增加Oracle驱动支持
* 2021.04.15 调整项目文件结构,代码生成器按新的结构生成;
* 2021.04.14 增加流程启动、撤销功能;
* 2021.04.13 增加新的流程状态-草稿;
* 2021.04.01 优化代码生成器,可以根据主键类型自动匹配父类;
* 2021.03.29 优化雪花算法;
* 2021.03.22 全面删除svg图标使用iconfont并增加图标选择
* 2021.03.18 fix https://gitee.com/dotnetchina/OpenAuth.Net/issues/I3BUF5
* 2021.03.17 驳回状态可以在待处理列表中展示并处理;
* 2021.03.13 增加雪花算法支持、增加自动增长型Id的支持
* 2021.03.09 增加redis缓存支持
* 2021.03.03 代码生成器加上删除时添加弹出提醒的代码;
* 2021.03.02 修复流程分支判定;
* 2021.03.01 修复流程分支不能判断字符串的问题;
* 2021.02.20 新增三级菜单名称前Icon小图标
* 2021.02.18 增加三级菜单支持
* 2021.01.17 调整非法租户逻辑;
* 2021.01.14 fix issue [#I2D0CX](https://gitee.com/yubaolee/OpenAuth.Core/issues/I2D0CX)
* 2021.01.10 完成对多租户的支持;
* 2021.01.06 fix issue [#I2C4K0](https://gitee.com/yubaolee/OpenAuth.Core/issues/I2C4K0)
* 2021.01.03 启动时显示连接字符串;
* 2020.12.28 新增多数据源;
* 2020.12.27 优化EF输出SQL语句
* 2020.12.26 对同时多个HTTP修改请求进行加锁处理
* 2020.12.21 增加附件管理;
* 2020.12.19 上传图片支持生成缩略图;
* 2020.12.17 增加异步测试、事务测试;
* 2020.12.16 完成UnitWork异步化
* 2020.12.11 Repository增加异步读写接口
* 2020.12.09 fix issue [#I1RFOQ](https://gitee.com/yubaolee/OpenAuth.Core/issues/I1RFOQ)
* 2020.12.02 所有数据加载调整为异步模式;
* 2020.11.15 修复layui选择组织机构时数据回写的BUG
* 2020.11.03 修复layui icon选择BUG
* 2020.10.20 修复代码生成器mysql创建主键字段
* 2020.10.13 调整代码生成器生成vue views的路径调整为小写
* 2020.09.23 发布企业版代码生成器功能;
* 2020.09.10 完成所有后端生成实体、生成业务功能、生成API
* 2020.08.12 完成代码生成器--自动创建WebApi Controller功能的开发
* 2020.08.10 完成代码生成器--自动创建实体功能的开发;
* 2020.08.06 增加代码生成器创建接口,为在线代码生成器做准备;
* 2020.08.04 修复企业版字典分类页面样式异常;增加获取数据库结构接口;
* 2020.08.01 获取实体属性时,按小写判断实体是否存在。修复:[I1PN8N](https://gitee.com/yubaolee/OpenAuth.Core/issues/I1PN8N) [I1PN5O](https://gitee.com/yubaolee/OpenAuth.Core/issues/I1PN5O) [I1PMYX](https://gitee.com/yubaolee/OpenAuth.Core/issues/I1PMYX)

32
docs/core/specialist.md Normal file
View File

@ -0,0 +1,32 @@
# 开发规范
## 新增数据库名称规范
子系统名称+业务名称+表尾,其中表尾名称规则如下:
- 基础主数据以Mst结尾
- 普通业务表以Tbl结尾
- 业务明细表以Dtbl结尾
比如:
- WMS系统客户主数据表WmsCustomerMst
- WMS系统入库订单头表WmsInboundOrderTbl
- WMS系统入库订单明细表WmsInboundOrderDtbl
## 数据库字段类型
主键id统一使用Domain:PrimaryKey针对SqlServer数据库非Sql Server根据需要定义
状态类,标识类的字段统一使用bit not null
表示分类的字段统一使用PrimaryKey。数值从Category中获取。

175
docs/core/start.md Normal file
View File

@ -0,0 +1,175 @@
# 快速开始
## 下载代码
gitee上面两个版本仅SDK的版本不同代码完全相同。其中
* [OpenAuth.Net](https://gitee.com/dotnetchina/OpenAuth.Net) 的SDK版本为5.0.100,推荐使用该版本
* [OpenAuth.Core](https://gitee.com/yubaolee/OpenAuth.Core) 的SDK版本为.Net Core 3.1.100,历史原因暂且保留,未来的某天会关闭它
.Net目前SDK升级特别方便只需花费3分钟时间既可升级到.Net 6/7/8...等。请参考:[3分钟的时间把.net core 3.1的升级到.NET 5](https://www.cnblogs.com/yubaolee/p/Net3ToNet5.html)所以不要纠结SDK版本问题。
## 安装sdk
下载安装微软官方SDK代码地址https://dotnet.microsoft.com/download
## 项目结构
OpenAuth.Net文件夹结构及功能说明如下
```
📦OpenAuth.Net
┣ 📂CodeSmith
┃ ┗ 📂CSharp
┃ ┃ ┗ 📜WebGenerate.cst //生成Web页面
┣ 📂Infrastructure //基础工具类
┣ 📂mysql初始化脚本
┣ 📂OpenAuth.App //应用逻辑代码
┣ 📂OpenAuth.Identity //IdentityServer4服务器提供OAuth服务
┣ 📂OpenAuth.Mvc //开源版Web站点
┣ 📂OpenAuth.Repository //数据库访问相关代码
┣ 📂OpenAuth.WebApi //WebApi接口站点
┣ 📂sql server 初始化脚本
┣ 📜.gitattributes
┣ 📜.gitignore
┣ 📜LICENSE
┣ 📜OpenAuth.Core.sln //解决方案
┗ 📜README.md
```
其中调用关系为:
@startuml
hide footbox
skinparam handwritten true
actor 用户
boundary index.cshtml
control XXController
entity OpenAuth.App
entity OpenAuth.Repository
database OpenAuthDB
box "OpenAuth.Mvc" #LightBlue
participant index.cshtml
participant XXController
end box
participant OpenAuth.App
participant OpenAuth.Repository
participant OpenAuthDB
用户 -> index.cshtml : 用户浏览页面
index.cshtml -> XXController : 前端通过ajax调用数据
XXController -> OpenAuth.App : 调用逻辑层
OpenAuth.App -> OpenAuth.Repository : 逻辑层调用仓储进行数据读写
OpenAuth.Repository -> OpenAuthDB : 仓储层进行数据库操作
@enduml
我们以【资源管理】功能为例,该功能涉及的文件如下:
![20220407153729](http://img.openauth.net.cn/20220407153729.png)
## 初始化数据库
使用数据库脚本`sql server 初始化脚本`或`mysql初始化脚本` 文件夹里面的结构脚本和数据脚本初始化数据库
::: warning 注意
如果使用企业版的OpenAuth.WebApi,则新建一个空数据库OpenAuthPro。使用OpenAuth.Pro前端源码文件夹【sql脚本】中运行`Sql Server脚本.sql`或mysql脚本
:::
## 打开项目
使用Visual Studio 2019或Rider打开 `OpenAuth.Core.sln`
::: tip 提示
v2.0及以后版本因使用.net core 3.1必须使用visual Studio 2019及以上版本打开
v2.0以前的版本可以使用visual Studio 2017
如果开发使用的电脑安装有多个版本的SDK如同时有.net core 3.1 和.net 5可以在根目录新建一个`global.json`文件来指定.net版本文件内容如下
```
{
"sdk": {
"version": "3.1.100"
}
}
```
:::
## 修改配置
`ASP.NET Core` 应用程序启动时默认加载`appsettings.json`作为应用配置。同时还支持不同的运行环境加载对应的配置文件,如:
- 开发环境Development对应 `appsettings.Development.json`
- 部署环境Production对应 `appsettings.Production.json`
::: tip 提示
- 很多用户部署后提示连接数据库失败,很大原因就是没有修改`appsettings.Production.json`里面连接字符串
- 有些用户找不到`appsettings.Production.json`在哪visual studio中点击`appsettings.json`左边的三角标识即可看到
:::
#### 修改单数据库连接字符串
* 修改OpenAuth.Mvc/appsettings.json连接字符串如下
```json
"ConnectionStrings": {
"OpenAuthDBContext": "Data Source=.;Initial Catalog=OpenAuthPro;User=sa;Password=000000"
},
"AppSetting": {
"DbTypes": {
"OpenAuthDBContext":"SqlServer" //数据库类型SqlServer、MySql、Oracle
}
```
#### 修改多数据库连接字符串
```json
"ConnectionStrings": {
"OpenAuthDBContext": "Data Source=.;Initial Catalog=OpenAuthPro;User=sa;Password=000000"
"OpenAuthDBContext2": "DATA SOURCE=192.168.0.118:1521/YUBAO;PASSWORD=000000;Validate Connection=true;PERSIST SECURITY INFO=True;USER ID=yubaolee;" //racle
"OpenAuthDBContext3": "server=127.0.0.1;user id=root;database=openauthpro;password=000000" //my sql
},
"AppSetting": {
"DbTypes": {
"OpenAuthDBContext":"SqlServer" //数据库类型SqlServer、MySql、Oracle
,"OpenAuthDBContext2":"Oracle"
,"OpenAuthDBContext3":"MySql"
},
```
## 编译运行MVC
使用visualstudio生成解决方案。
`注首次启动时visual studio会启动nuget还原第三方依赖包请保持网络通畅并等待一段时间`
启动openauth.mvc项目。
![启动](/startmvc.png "启动")
启动成功后使用浏览器打开[http://localhost:1802](http://localhost:1802) 即可访问,如下图所示:
![说明](/mvcmain.png "说明")
## 编译运行WebApi
使用visualstudio生成解决方案。
`注首次启动时visual studio会启动nuget还原第三方依赖包请保持网络通畅并等待一段时间`
启动openauth.webapi项目。
![20220102000528](http://img.openauth.net.cn/20220102000528.png)
启动成功后使用浏览器打开[http://localhost:52789/swagger/index.html](http://localhost:52789/swagger/index.html) 即可访问,如下图所示:
![20220101233542](http://img.openauth.net.cn/20220101233542.png)

37
docs/core/thirdparty.md Normal file
View File

@ -0,0 +1,37 @@
# 三方对接
* 在OpenAuth中设计表单注意表单中的控件名称在步骤3调用OpenAuth创建流程实例接口时frmData参数中的属性必须严格按该命名提交。
![](/formthirdparty.png "表单设计说明")
* 在OpenAuth中设计流程制定相关的工作流程并在每个流程节点配置回调URL路径如下
![](/flowthirdparty.png "三方URL设置")
* 三方已有系统界面提交表单时调用创建流程实例接口http://localhost:52789/api/FlowInstances/Add在OpenAuth中创建一条新的流程实例 接口参数如下:
```javascript
{
schemeId:'cdd8191e-6a99-4d66-aac0-fae52c0f2232', //流程模板中已存在的模板ID
schemeCode:'', //与流程模板ID二者选一个即可
frmData:'{\"TOOLS\":\"电脑\",\"NUMBERS\":\"1\"}', //严格按照第一步中表单规则
code:'1563811467051',
customName:'三方创建的新物品领用',
}
```
* 用户正常在OpenAuth中执行流程如果当前节点设置了回调URL的节点OpenAuth会采用WebAPI POST方式回调回调时具体参数如下
```javascript
{
flowInstanceId:"0ceff0f8-f848-440c-bc26-d8605ac858cd", //流程实例ID
nodeName: "admin审批", //节点名称
nodeId: "15333321", //节点ID
userId: "0ceff0f8-f848-440c-bc26-d8605ac858cd",
userName: "admin", //审核人账号
result: 1, //审核结果 1通过;2不通过3驳回
description: "做的不错", //审核描述
execTime: "2019-07-07 12:00:00", //审核时间
isFinish: true //是否结束
}
```

72
docs/core/unittest.md Normal file
View File

@ -0,0 +1,72 @@
# 单元测试
为了方便项目调试框架的所有层均支持单元测试。代码基于NUnit框架编写。测试内如大概如下
* OpenAuth.Reposiroty: 直接测试数据库是否可以正常读写测试级别DbContext。在该项目的`TestBase.cs`中配置连接字符串;
* OpenAuth.App: 测试所有业务逻辑测试级别为各种xxxApp/xxxService等。可以模拟用户登录和前端Cookie提交的信息。在该项目的`TestBase.cs`中配置连接字符串;
* OpenAuth.Mvc: 测试MVC的访问可以模拟用户登录和前端Cookie提交的信息。使用OpenAuth.App中的测试连接字符串
* OpenAuth.WebApi: 测试接口WebApi访问可以模拟用户登录和前端Cookie提交的信息。使用OpenAuth.App中的测试连接字符串
所有的测试代码均在每个项目的`Test`文件夹中编写。比如`OpenAuth.App\Test\TestAccessObjs.cs`
```csharp
/// <summary>
/// 测试为部门分配用户
/// </summary>
[Test]
public void AssignOrgUsers()
{
var app = _autofacServiceProvider.GetService<RevelanceManagerApp>();
var userApp = _autofacServiceProvider.GetService<UserManagerApp>();
app.AssignOrgUsers(new AssignOrgUsers
{
OrgId = "8e31553c-cab8-4eb3-90b5-5f8ff1d21801",
UserIds = new []{"96f63f9d-e8c8-4258-963e-3327ed7d6f56"}
});
//获取机构的所有用户
var result = userApp.Load(new QueryUserListReq
{
orgId = "8e31553c-cab8-4eb3-90b5-5f8ff1d21801",
page = 1,
limit = 10
});
Console.WriteLine(JsonHelper.Instance.Serialize(result));
}
```
::: warning 注意
每个单元测试类都会继承`TestBase`,该类有一个虚函数`GetService`默认只注入了缓存Cache配置Option。如果在测试的过程中需要模拟登录用户cookie等信息需要在测试类中重写该方法。比如一个典型的重写如下
```csharp
public override ServiceCollection GetService()
{
var services = new ServiceCollection();
//模拟帐号test3记录在缓存中并与tokentest关联
var cachemock = new Mock<ICacheContext>();
cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession { Account = "test3" });
services.AddScoped(x => cachemock.Object);
//模拟客户端请求的token值为`tokentest`
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TOKEN_NAME]).Returns("tokentest");
services.AddScoped(x => httpContextAccessorMock.Object);
//模拟httpclientfactory
var mockHttpFac = new Mock<IHttpClientFactory>();
services.AddScoped(x => mockHttpFac.Object);
return services;
}
```
:::

280
docs/core/unitwork.md Normal file
View File

@ -0,0 +1,280 @@
# 数据库读写及事务处理
OpenAuth.Core使用Repository和Unitwork两种方式访问数据库。
## 使用场景
Repository适用于单表操作没有事务需求的场景
Unitwork适用于多表操作尤其是更新操作有事务需求的场景
::: tip 什么是UnitWork
在web应用中由于每个用户的请求都是属于不同线程的需要保持每次请求的所有数据操作都成功的情况下提交数据只要有一个失败的操作则会对用户的此次请求的所有操作进行回滚以确保用户操作的数据始终处于有效的状态。其实就两个字**事务**
:::
## 单表操作Repository
假设数据库有一个表名称为Stock。则在OpenAuth.App中编写业务代码。比如`StockApp`
```csharp
namespace OpenAuth.App
{
public class StockApp : BaseApp<Stock,OpenAuthDBContext>
{
/// <summary>
/// 加载列表
/// </summary>
public TableData Load(QueryStockListReq request)
{
var result = new TableData();
var objs = Repository.Find(null);
if (!string.IsNullOrEmpty(request.key))
{
objs = objs.Where(u => u.Id.Contains(request.key));
}
result.data = objs.OrderBy(u => u.Id)
.Skip((request.page - 1) * request.limit)
.Take(request.limit);
result.count = objs.Count();
return result;
}
public void Add(AddOrUpdateStockReq req)
{
var obj = req.MapTo<Stock>();
//todo:补充或调整自己需要的字段
obj.CreateTime = DateTime.Now;
Repository.Add(obj);
}
public void Update(AddOrUpdateStockReq obj)
{
Repository.Update(u => u.Id == obj.Id, u => new Stock
{
//todo:补充或调整自己需要的字段
});
}
public StockApp(IUnitWork<OpenAuthDBContext> unitWork, IRepository<Stock,OpenAuthDBContext> repository,IAuth auth) : base(unitWork, repository,auth)
{
}
}
}
```
## 事务操作UnitWork
默认情况下EF每执行一次SaveChanges()方法时就会新建一个事务然后将context中的CUD操作都在这个事务中进行。使用方式如下
```csharp
public void Update(AddOrUpdateStockReq obj)
{
UnitWork.Add<SysLog>(new SysLog
{
//todo:模拟新增操作
});
var stock = UnitWork.FirstOrDefault<Stock>(u => u.Id == obj.Id);
stock.Name = "xxxx";
UnitWork.Update(stock); //更新操作
var other = UnitWork.FirstOrDefault<OtherTable>(u => u.Id == obj.Id);
other.Name = "xxxx";
UnitWork.Update(other); //其他更新操作
UnitWork.Save(); //只有一次Save()操作
}
```
如果在一个事务里面有多次`SaveChanges()`的情况需要使用OpenAuth.Core提供的`ExecuteWithTransaction`处理。如下:
```csharp
//代码详见TestTransaction.cs/NormalSubmit()
UnitWork.ExecuteWithTransaction(() =>
{
var account = "user_" + DateTime.Now.ToString("yyyy_MM_dd HH:mm:ss");
var user = new User
{
Id = account,
Account = account,
Name = account,
};
unitWork.Add(user);
unitWork.Save(); //第一次savechanges()
user.Account = "Trans_" + user.Account;
unitWork.Update(user);
unitWork.Save(); //第二次savechanges()
//Z.EntityFramework.Plus的Update内部自动调用了SaveChanges(),算第三次
unitWork.Update<User>(u => u.Id == account, u => new User
{
Account = "Trans2_" + user.Account
});
});
```
或者异步方式:
```csharp
public async Task AddUserAndLogAsync()
{
await UnitWork.ExecuteWithTransactionAsync(async () =>
{
var account = await AddUserAsync();
UnitWork.Add(new SysLog()
{
Content = $"新增了用户{account}",
Id = account
});
UnitWork.Save();
});
}
private async Task<string> AddUserAsync()
{
var account = "user_" + DateTime.Now.ToString("yyyy_MM_dd HH:mm:ss");
var user = new User
{
Account = account,
Name = account
};
await Repository.AddAsync(user);
return account;
}
```
发生这种情况,通常是因为在各个应用层逻辑内部已经调用了`UnitWrok.Save()`,比如:
```csharp
//详细代码请查看UserManagerApp.cs,本例简化真实逻辑,方便理解
private RevelanceManagerApp _revelanceApp;
public void AddOrUpdate(UpdateUserReq request)
{
UnitWork.ExecuteWithTransaction(() =>
{
User requser = request;
requser.CreateTime = DateTime.Now;
UnitWork.Add(requser);
UnitWork.Save();
string[] orgIds = request.OrganizationIds.Split(',').ToArray();
//下面两个方法各自内部都会调用UnitWork.Save()
_revelanceApp.DeleteBy(Define.USERORG, requser.Id);
_revelanceApp.Assign(Define.USERORG, orgIds.ToLookup(u => requser.Id));
});
}
```
## 多表查询
简单的多表查询可以使用UnitWork完成。例如
```csharp
/// <summary>
/// 加载用户的部门
/// </summary>
public List<Org> LoadForUser(string userId)
{
var result = from userorg in UnitWork.Find<Relevance>(null)
join org in UnitWork.Find<Org>(null) on userorg.SecondId equals org.Id
where userorg.FirstId == userId && userorg.Key == Define.USERORG
select org;
return result.ToList();
}
```
如果是复杂的SQL查询建议使用下面的SQL语句查询以获得更高的性能。
## SQL 语句查询
框架提供两个SQL语句查询的接口:
* FromSql: 返回数据库表对应的实体必需在在DbContext中增加对应的DbSset
::: tip 提示
EF Core 3.x版本或以前如果返回数据库中不存在的实体必需在在DbContext中增加DbQuery<实体>并且使用dbcontext.Query<XXX>("select * from xx")进行查询。EF Core 5.0以后已经全部统一为DbSet并使用FromSql进行查询
:::
### 返回数据库表
```csharp
//UserManagerApp.cs
var users = UnitWork.FromSql<User>("select * from user");
```
### 返回非数据库表
```csharp
//OpenAuthDBContext中添加访问
public virtual DbSet<UserResp> UserResps { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
modelBuilder.Entity<UserResp>().HasNoKey();
}
//使用
var users = UnitWork.FromSql<UserResp>("select * from user");
```
## 执行存储过程
#### Sql Server
UnitWork提供执行存储过程接口`ExecProcedure`,使用如下:
``` csharp
var unitWork = _autofacServiceProvider.GetService<IUnitWork<OpenAuthDBContext>>();
var param = new SqlParameter("keyword", SqlDbType.NVarChar);
param.Value = "test%";
var users = unitWork.ExecProcedure<User>("sp_alluser", new []{param});
Console.WriteLine(JsonHelper.Instance.Serialize(users));
```
存储过程`sp_alluser`定义如下:
```sql
create procedure sp_alluser @keyword nvarchar(20) as
begin
select * from [user] where Account like @keyword;
end;
```
#### MySql
UnitWork提供执行存储过程接口`ExecProcedure`,使用如下:
``` csharp
var unitWork = _autofacServiceProvider.GetService<IUnitWork<OpenAuthDBContext>>();
var param = new MySqlParameter("keyword", SqlDbType.NVarChar);
param.Value = "test%";
var users = unitWork.ExecProcedure<User>("sp_alluser", new []{param});
Console.WriteLine(JsonHelper.Instance.Serialize(users));
```
::: warning 特别注意
这里的MySqlParameter命名空间使用的是
``` csharp
using MySqlConnector;
```
:::
存储过程`sp_alluser`定义如下:
```sql
create procedure sp_alluser(in keyword nvarchar(20))
begin
select * from user where Account like keyword;
end;
```

124
docs/core/wwwarchitect.md Normal file
View File

@ -0,0 +1,124 @@
# 前端结构
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
```

42
docs/net/README.md Normal file
View File

@ -0,0 +1,42 @@
::: danger 郑重提示
本文档是针对[OpenAuth.Net 4.0分支](https://gitee.com/yubaolee/OpenAuth.Net/tree/4.0/)(基于.Net 4.5开发环境),如果你是用.Net Core 3.1/.Net 5或以后版本开发环境请移步 [.net core版本](/core)文档。
:::
![LOGO](https://gitee.com/uploads/images/2018/0425/163228_7077c3fd_362401.png "1.png")
OpenAuth.Net 4.0分支是基于 **.Net Framework 4.5** 的开源权限工作流快速开发框架(主分支已经更新为.Net 5跨平台开发环境。框架基于Martin Fowler企业级应用开发思想及全新技术组合Asp.Net MVC、EF、AutoFac、WebAPI、Swagger、Json.Net等核心模块包括组织机构、角色用户、权限授权、表单设计、工作流等。它的架构精良易于扩展是中小企业的首选。
## 特性
采用经典DDD架构,每一行代码都经过深思熟虑符合SOLID规则
符合国情的RBAC基于角色的访问控制可以直接应用到你的系统。
1. 菜单权限 经理和业务员登陆系统拥有的功能菜单是不一样的
1. 按钮权限 经理能够审批,而业务员不可以
1. 数据权限 A业务员看不到B业务员的单据
1. 字段权限 某些人查询客户信息时看不到客户的手机号或其它字段
**用户**应用系统的具体操作者,我这里设计用户是可以直接给用户分配菜单/按钮,也可以通过角色分配权限。
**角色**为了对许多拥有相似权限的用户进行分类管理定义了角色的概念以上所有的权限资源都可以分配给角色角色和用户N:N的关系。
**机构**树形的公司部门结构国内公司用的比较多它实际上就是一个用户组机构和用户设计成N:N的关系也就是说有时候一个用户可以从属于两个部门这种情况在我们客户需求中的确都出现过。
## 技术栈
* 前端 vue + layui + ztree + gooflow + leipiformdesign
* 后端 asp.net mvc + Web API + EF + autofac + swagger + json.net
* 代码生成工具 CodeSmith
* 设计工具 PowerDesigner + Enterprise Architect
## 系统工程结构:
1. OpenAuth.Repository 系统仓储层,用于数据库操作
1. OpenAuth.App 应用层,为界面提供接口
1. OpenAuth.Mvc Web站点
1. OpenAuth.UnitTest 单元测试
1. Infrastructure 通用工具集合
1. OpenAuth.WebApi SSO服务及为第三方提供接口服务

32
docs/net/deploy.md Normal file
View File

@ -0,0 +1,32 @@
# 发布部署
直接使用Visual Studio的发布功能发布到对应的文件夹
* OpenAuth.Mvc发布
![](/dotnetdeploy.png)
* OpenAuth.WebApi发布
![](/dotnetapideploy.png)
然后把对应的发布文件部署到IIS下。成功后直接访问
* [http://localhost:56813](http://localhost:56813) 为项目的主界面对应OpenAuth.Mvc项目。如下图所示
![说明](https://gitee.com/uploads/images/2018/0328/150659_6900820e_362401.png "说明")
* [http://localhost:52789/Swagger/ui/index](http://localhost:52789/Swagger/ui/index) 为项目WebApi接口部分对应OpenAuth.WebApi项目主要为其他项目提供数据接口及为OpenAuth.Mvc提供单点登录SSO功能。这是一个纯WebAPI项目本身是没有界面的所以3.0以前的版本会报找不到页面的错误为了美观增加了swagger的支持
![](/donetswagger.png)
::: warning 提别提醒
如果WebApi不是使用的52789端口需要在OpenAuth.Mvc的Web.config中修改下面配置
```xml
<add key="SSOPassport" value="http://localhost:你的端口号" />
```
:::

61
docs/net/devnew.md Normal file
View File

@ -0,0 +1,61 @@
# 添加新模块
本章节以项目自带的数据库OpenAuthDB中Stock表为基础介绍如何添加一个新模块并对新模块进行授权等操作。
暂且为该模块命名为`仓库管理`,现在开始:
## 编写代码
* 使用CodeSmith生成数据库实体访问代码用于操作数据库
* 使用CodeSmith Generator Studio 打开Openauth.Net项目中CodeSmith文件夹。
![](http://119.84.146.233:8887/upload_files/190110171420673.png " ")
* 右建Entity.cst选择Execute。弹出数据库的相关配置。
* 配置连接字符串SourceDatabase、Class命名空间的及Output输出文件夹。
* 点击`Generate`生成代码,生成后代码在`X:\~~\OpenAuth.Net\CodeSmith\CSharp`文件夹中。
* 将生成的代码按上图红色箭头的指示复制到项目中。可以只复制`Entities\Stock.cs`、`Mapping\StockMap.cs`、`OpenAuthDBContext.cs`
* 使用CodeSmith生成界面及逻辑代码
* 右建WebGenerate.cst选择Execute。弹出数据库的相关配置。
* 选择数据库中Stock表其他配置不变。
![](http://119.84.146.233:8887/upload_files/190110171420676.png "")
* 点击`Generate`生成代码,生成后代码在`X:\~~\OpenAuth.Net\CodeSmith\CSharp`文件夹中。
![](http://119.84.146.233:8887/upload_files/190110171757977.png "")
* 生成的代码严格按照应用层APP、控制器controllers、用户界面views、用户界面脚本userJs划分。将生成的代码复制到项目对应的文件夹中。
* 在visual studio中根据自己的业务做简单的调整然后编译生成。即完成了一个新模块的开发。
`注意` 使用代码生成器适用于大批量简单逻辑的代码生成,复杂逻辑可以基于现有代码直接手动修改。
## 创建模块
* 添加模块
![](http://119.84.146.233:8887/upload_files/190110172049261.png)
`注意` 模块标识必须和模块的controller一致否则模块不能正常加载
* 添加菜单
![](http://www.openauth.net.cn/upload/180523111946327.png)
默认的domId有`btnAdd`、`btnEdit`、`btnDel`可以参考`userJs\stocks.js`中的代码定义
* 授权
模块添加成功后如果用的是System账号退出重新登陆即可看到新加的模块。如果为其他角色分配模块按照下面的方式
![](http://119.84.146.233:8887/upload_files/190110172339544.png)
以上就是一个普通模块开发的全过程是不是so easy🙂快下载代码体验吧

62
docs/net/start.md Normal file
View File

@ -0,0 +1,62 @@
# 快速开始
## 下载代码
使用git工具下载代码代码地址https://gitee.com/yubaolee/OpenAuth.Net.git
## 修改连接字符串
* 修改OpenAuth.Mvc/Web.config连接字符串如下
```xml
<add name="OpenAuthDBContext" connectionString="Data Source=.;Initial Catalog=OpenAuthDB;Persist Security Info=True;User ID=sa;Password=000000;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
```
* 修改OpenAuth.WebApi/Web.config连接字符串,如下:
```xml
<add name="OpenAuthDBContext" connectionString="Data Source=.;Initial Catalog=OpenAuthDB;Persist Security Info=True;User ID=sa;Password=000000;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
```
## 设置启动项
在vs解决方案视图中右键解决方案“OpenAuth”属性调整启动项如下
![设置启动项](/dotnetstart.png "设置启动项")
::: warning 提别提醒
很多人启动的时候会遇到下面这个异常
![](/starterror.png)
99.9999%的人是因为没有启动OpenAuth.WebApi项目造成的。务必按上面进行启动项设置🙂
:::
## 编译运行
使用Visual Studio菜单栏中的【启动】按钮或快捷键F5启动运行。
`注首次启动时visual studio会启动nuget还原第三方依赖包请保持网络通畅并等待一段时间`
启动成功后,可以在浏览器访问两个网址:
* [http://localhost:56813](http://localhost:56813) 为项目的主界面对应OpenAuth.Mvc项目。如下图所示
![说明](https://gitee.com/uploads/images/2018/0328/150659_6900820e_362401.png "说明")
* [http://localhost:52789/Swagger/ui/index](http://localhost:52789/Swagger/ui/index) 为项目WebApi接口部分对应OpenAuth.WebApi项目主要为其他项目提供数据接口及为OpenAuth.Mvc提供单点登录SSO功能。这是一个纯WebAPI项目本身是没有界面的所以3.0以前的版本会报找不到页面的错误为了美观增加了swagger的支持
![](/donetswagger.png)
::: warning 提别提醒
如果WebApi不是使用的52789端口需要在OpenAuth.Mvc的Web.config中修改下面配置
```xml
<add key="SSOPassport" value="http://localhost:你的端口号" />
```
:::
## 更多文档
如需更多文档请点击[这里](http://openauth.net.cn/question/detail.html?id=a2be2d61-7fcb-4df8-8be2-9f296c22a89c)
![更多文档](http://demo.openauth.net.cn:8887/upload_files/200415002234330.png "更多文档")

9
docs/package.json Normal file
View File

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

59
docs/pro/README.md Normal file
View File

@ -0,0 +1,59 @@
OpenAuth.Pro是一套全新的前端界面基于vue-element-admin采用VUE全家桶VUE+VUEX+VUE-ROUTER单页面SPA开发。它使用开源版OpenAuth.Core的API接口OpenAuth.WebApi提供数据服务。二者的关系如下
![](/architect.png)
企业版代码获取方式:[http://www.openauth.net.cn/question/detail.html?id=a2be2d61-7fcb-4df8-8be2-9f296c22a89c](http://www.openauth.net.cn/question/detail.html?id=a2be2d61-7fcb-4df8-8be2-9f296c22a89c)
## 工具准备
#### NodeJs
前端环境为NodeJs下载地址[http://nodejs.cn/download/current/](http://nodejs.cn/download/current/)。其中:
OpenAuth.Pro v4.6.4及以后的版本使用Node 18
OpenAuth.Pro v4.6.3-v4.3 使用Node 16
OpenAuth.Pro v4.3及以前的版本使用Node 14
#### visual studio code
下载最新版的vs code用来作为OpenAuth.Pro的开发工具。
## 创建数据库
* 如果只使用开源的OpenAuth.Mvc。则新建一个空数据库OpenAuthDB。然后在OpenAuth.Core项目文件夹【sql server 初始化脚本】中,运行`Sql Server脚本.sql`或mysql初始化脚本
* 如果只使用企业版的OpenAuth.WebApi,则新建一个空数据库OpenAuthPro。使用OpenAuth.Pro前端源码文件夹【sql脚本】中运行`Sql Server脚本.sql`或mysql脚本
## 启动后端
启动后端请参考:[快速开始](/core/start.html)
## 启动前端
使用Vs Code或个人喜欢的工具打开OpenAuth.Pro/Client文件夹如下图
![20211214232057](http://img.openauth.net.cn/20211214232057.png)
安装程序运行所需的第三方包。使用npm install 命令经行安装,如下图:
![20211214232207](http://img.openauth.net.cn/20211214232207.png)
使用npm run dev 命令运行。如下图:
![20211214232229](http://img.openauth.net.cn/20211214232229.png)
启动成功后,使用浏览器访问[http://localhost:1803/](http://localhost:1803/) 即可打开企业版界面
::: warning 注意事项
开发环境配置文件为`.env.dev`,调试前请调整为自己的接口地址:
```javascript
VUE_APP_BASE_API = http://localhost:52789/api
VUE_APP_BASE_IMG_URL = http://localhost:52789
```

89
docs/pro/components.md Normal file
View File

@ -0,0 +1,89 @@
# 内置组件
OpenAuth.Pro封装了一些组件方便开发使用组件全部在`src\components`中定义。目前提供的三大核心组件关系如下:
![20211230063538](http://img.openauth.net.cn/20211230063538.png)
## 通用下拉选择 auth-select
通用下拉选择`auth-select`组件是用于渲染和编辑字典结构和动态列表返回key-valuel数据的组件。用法如下
静态字典。根据【字典分类】模块的`分类标识`关键字获取,如:
```html
<auth-select :isEdit="isEdit" @change="change" :data-source="'SYS_STATUS'" v-model="val" size="mini"></auth-select>
```
动态列表。从指定Url获取value/label结构的数据进行渲染
```html
<auth-select :default-props="{label:'name', value:'id'}" :isEdit="isEdit" @change="change" :type="'dynamic'" :data-source="'/CategoryTypes/Load'" v-model="val" size="mini"></auth-select>
```
该组件有以下几个参数:
isEdit:是否编辑如果为false则展示为label形式如果为true则为编辑状态
type选择类型。'dynamic'表示动态加载,空或'static'则从系统Category表中获取
data-source数据源。当type=='dynamic'时该值为一个Url地址该地址返回一个id/name结构的数组。当type=='static'或空时,该值为【字典分类】模块的`分类标识`
default-props: 数据源提供的数据类型。默认情况下为id/name的数组。如果设置该值则需要提供对应结构的数据:default-props="{label:'tableName', value:'id'}",则提供的数据格式如下:
```javascript
[
{id:'1',tableName:'category'},
{id:'2',tableName:'user'},
{id:'3',tableName:'module'},
....
]
```
## 表格组件 auth-table
用于渲染给定列定义,给定数据的表格,简单用法如下:
```html
<auth-table ref="tableName" :table-fields="tableFields" :data="dataList" ></auth-table>
```
支持的事件row-click selection-change
支持的方法exportExcel clearSelection
## 表单组件 auth-form
根据定义动态渲染表单项,减少表单的开发。用法如下:
```html
<auth-form ref="dataForm" :edit-model="editModel" :form-fields="firstHeaderList" :data="firstTemp" :col-num="3"></auth-form>
```
当父组件需要使用表单里面的数据,进行提交操作时,参考以下代码:
```javascript
submit() {
// 保存提交
this.$refs['dataForm'].validate(() => {
let tempData = Object.assign({}, this.firstTemp)
api.add(tempData).then((resp) => {
...
this.$notify({
title: '成功',
message: '提交成功',
type: 'success'
})
})
})
}
```
该组件有以下几个参数:
form-fields表单属性定义。为一个`ColumnDefine`的数组。典型的值如下:
```javascript
this.firstHeaderList = [
new ColumnDefine('id', 'id', false, false, 'text', '', 'string', 'varchar', ''),
new ColumnDefine('tableName', '表名', true, true, 'text', '', 'string', 'varchar', ''),
new ColumnDefine('parentTableId', '父表', true, true, 'selectDynamic', '/BuilderTables/AllMain', 'string', 'varchar', ''),
]
```

View File

@ -0,0 +1,73 @@
# 权限控制
## 数据权限
关于数据权限控制,可以详细查看博文:[通用权限设计与实现](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)
## 字段权限
::: warning 注意
字段权限只针对【非系统模块】有效即在添加新模块的时候需要设置模块属性“是否系统”为false。
:::
## 使用场景
字段权限控制分为两种:
1. 直接不返回字段的值。用于敏感数据不向客户端反馈。
1. 返回字段的值但界面不显示。常常用于数据需要和后端交互但不想在界面显示比如各种Id。这种直接在返回实体增加`[Browsable(false)]`注解即可。
## 如何做?
### 后端代码处理
针对场景1在做返回处理的时候需要过滤数据库查询字段如下本文以Resource表为例
```csharp
var columnFields = loginContext.GetTableColumns("Resource");
if (columnFields == null || columnFields.Count == 0)
{
throw new Exception("请在代码生成界面配置Resource表的字段属性");
}
var propertyStr = string.Join(',', columnFields.Select(u => u.ColumnName));
result.columnFields = columnFields;
result.data = resources.OrderBy(u => u.TypeId)
.Skip((request.page - 1) * request.limit)
.Take(request.limit).Select($"new ({propertyStr})");
result.count = await resources.CountAsync();
return result;
```
::: warning 注意
企业版表结构是通过【代码生成】功能获取获取表结构并存储在`buildertable`表中因此需要先在【代码生成】功能添加要控制的表字段。然后使用loginContext.GetTableColumns获取可访问的字段。
:::
### 前端代码处理
在做表格的时候需要使用动态列。以`views/Resources/index.vue`为例,如下:
```HTML
<auth-table ref="mainTable" :table-fields="headerList"></auth-table>
```
用户加载后台数据时,自动加载表格字段结构,并存储在`headerList`实现字段权限控制,如下:
```javascript
//加载表头
resources.getList(this.listQuery).then((response) => {
this.list = response.data
response.columnFields.forEach((item) => {
// 首字母小写
item.columnName = item.columnName.substring(0, 1).toLowerCase() + item.columnName.substring(1)
})
this.headerList = response.columnFields
})
```
### 运行界面配置
完成代码编写后,在【基础配置】--【角色管理】--【为角色分配模块】最后为角色分配【可见字段】中分配权限
![20211228210554](http://img.openauth.net.cn/20211228210554.png)

42
docs/pro/deploy.md Normal file
View File

@ -0,0 +1,42 @@
# 部署
后端接口部署请参考:[部署API](/core/deployapi.html),前端打包流程如下:
使用`npm run build`进行打包构建:
![20211214232752](http://img.openauth.net.cn/20211214232752.png)
::: warning 注意事项
前端部署时使用的配置文件为`.env.prod`,打包构建前请调整为自己的接口地址:
```javascript
VUE_APP_BASE_API = http://demo.openauth.net.cn:52789/api
VUE_APP_BASE_IMG_URL = demo.openauth.net.cn:52789
```
:::
构建完成后会生成dist文件夹。如下
![20211214232928](http://img.openauth.net.cn/20211214232928.png)
该文件夹为纯静态的页面可以使用任何自己喜欢的Web服务器进行部署如IIS/tomcat/nginx等。个人推荐使用nginx部署。
nginx下载安装可参考[https://blog.csdn.net/github_39088222/article/details/79482461](https://blog.csdn.net/github_39088222/article/details/79482461)
nginx.conf推荐配置如下
```javascript
server {
listen 1803;
#server_name pro.openauth.me;
location / {
alias /openauth.pro/Client/dist/;
expires 1d;
}
access_log /www/wwwlogs/pro.log;
}
```

118
docs/pro/devnew.md Normal file
View File

@ -0,0 +1,118 @@
# 企业版代码生成器
## 术语解释
#### 动态头部
如果启用动态头部,表示前端渲染列表(或表单)时,列表的列定义是从后端返回。常见的前端代码如下:
```html
<auth-table ref="mainTable" :table-fields="headerList"></auth-table>
```
```javascript
getList() {
resources.getList(this.listQuery).then((response) => {
...
this.headerList = response.columnFields
...
})
},
```
否则生成的前端列为固定的头部。如下:
```html
<auth-table ref="mainTable" :table-fields="headerList"></auth-table>
```
```javascript
initCfg() {
this.headerList = [
new ColumnDefine('id', 'id', false, false, 'text', '', 'string', 'varchar', ''),
new ColumnDefine('tableName', '表名', true, true, 'text', '', 'string', 'varchar', ''),
new ColumnDefine('moduleName', '模块名称', true, true, 'text', '', 'string', 'varchar', ''),
new ColumnDefine('parentTableId', '父表', true, true, 'selectDynamic', '/BuilderTables/AllMain', 'string', 'varchar', ''),
new ColumnDefine('foreignKey', '外键', true, true, 'text', '', 'string', 'varchar', ''),
]
```
## 准备工作
* 数据库OpenAuthPro中添加仓储表【Stock】本文以该数据表为例。参考表结构如下
```SQL
-- mysql示例
create table stock
(
createtime datetime not null comment '操作时间',
status int not null comment '出库/入库',
price decimal(10, 1) not null comment '产品单价',
number int not null comment '产品数量',
name text not null comment '产品名称',
orgid varchar(50) null comment '组织ID',
user varchar(50) not null comment '操作人',
viewable varchar(50) not null comment '可见范围',
id varchar(50) not null comment '数据ID'
primary key
)
```
* 使用Visual Studio 以开发模式启动后端。参考:[编译运行webapi](http://doc.openauth.net.cn/core/start.html#%E7%BC%96%E8%AF%91%E8%BF%90%E8%A1%8Cwebapi)
* 启动企业版前端。参考:[启动前端](http://doc.openauth.net.cn/pro/#%E5%90%AF%E5%8A%A8%E5%89%8D%E7%AB%AF)
后续操作全部在系统中完成。
## 单表添加
代码生成界面,点击`添加`按钮,输入想添加的模块信息。
![2021923224934](http://img.openauth.net.cn/2021923224934.png)
录入基础信息,点击`确认`保存后,系统会添加一条记录,并自动加载对应的字段信息。
![2021923225040](http://img.openauth.net.cn/2021923225040.png)
这时,编辑字段具体的属性。如是否【可显示】【可编辑】等。
## 子表添加
::: warning 注意
如果只生成单表结构,可以跳过本节
:::
如果需要添加主/从(父/子)结构,需要先添加子表信息。代码生成界面,点击`添加`按钮,输入想添加的模块信息。
![20211208001551](http://img.openauth.net.cn/20211208001551.png)
::: warning 注意
子表的`动态头部`属性务必与父表保持一致,否则会造成生成的代码不能正常运行
:::
## 生成模块
选中刚刚添加的`Stock`表依次点击【生成实体】【生成业务代码】【生成vue页面】;
如果存在子表,也进行相同的操作。即选中刚刚添加的`StockDetail`表依次点击【生成实体】【生成业务代码】【生成vue页面】;
## 配置模块地址
运行系统使用System账号登录系统在【模块管理】中添加“仓储管理”模块如下图
![20211207003212](http://img.openauth.net.cn/20211207003212.png)
::: warning 注意
完成以上步骤后请重启OpenAuth.WebApi用来重新加载刚刚生成的后台代码
子表不需要添加模块
:::
成功后可以进入新加的仓储管理界面:
![20211208011431](http://img.openauth.net.cn/20211208011431.png)

28
docs/pro/dragform.md Normal file
View File

@ -0,0 +1,28 @@
# 可拖拽表单
适用场景和普通的动态表单一样。但该表单操作方便,与系统界面风格匹配度高,缺点是排版没有普通的动态表单灵活,只能做简单的行排列。
## 设计表单
功能【基础配置】-【表单设计】中,点击`新增`按钮,拖拽设计自己想要的表单,然后点击右上角`保存`按钮即可完成添加表单。
![20221130142201](http://img.openauth.net.cn/20221130142201.png)
#### `关联数据库表`选项
在设计表单时,如果在`关联数据库表`中新增一个表名,并对拖拽的控件进行标准化命名,如:
![20221130142549](http://img.openauth.net.cn/20221130142549.png)
这时保存后,会自动在数据库生成该表单对应的表:
![20220223001508](http://img.openauth.net.cn/20220223001508.png)
在后面进行流程流转时,流程使用的表单数据会自动存放在该表中,方便统计及其他程序开发应用。
::: warning 注意
如果表单不配置关联数据库表流程使用的表单数据只能以json格式存放在`flowinstance`表的`FrmData`字段中,不利于后期数据分析和扩展。至于是否需要关联数据库表,可以根据自己需要进行选择
:::

View File

@ -0,0 +1,34 @@
# 可拖拽表单常规设置
企业版可拖拽表单使用的是VForm Pro版本详细的配置可参考:[https://www.vform666.com/](https://www.vform666.com/) 本节只做常用的配置说明。
## 后端加载下拉列表值
官网推荐通过数据源的方式给下拉列表赋值,简单点的方式是使用组件的`onCreated`事件。新建一个下拉先选框,唯一名称改为:`SelectVals`,在组件的`onCreated`事件中添加以下代码:
```javascript
var selectVals = this.getWidgetRef('SelectVals');
var addressAPI= 'http://localhost:52789/api/SelectVals/'
axios.get(addressAPI).then(function(res) {
if (res.data.code==200) {
selectVals.loadOptions(res.data.result);
}
}).catch(function(error) {
console.error(error)
})
```
基于OpenAuth.WebApi返回的数据格式
```javascript
{
"result": [{
"label": "选项值1",
"value": "1"
}, {
"label": "选项值2",
"value": "2"
}],
"message": "操作成功",
"code": 200
}
```

102
docs/pro/faq.md Normal file
View File

@ -0,0 +1,102 @@
# 常见问题处理
## vue3 启动时白屏
在启动vue3版本不刷新浏览器会出现白屏的现象。并且控制台报异常
![20230529200341](http://img.openauth.net.cn/20230529200341.png)
如果直接打开URL也会得到504错误比如:
https://localhost:1803/app/node_modules/.vite/deps/pusher-js.js?v=601736dc
但是去掉版本信息后,又完全正常:
https://ocalhost:1803/app/node_modules/.vite/deps/pusher-js.js
这时可以使用:
```shell
npm rebuild
```
或者
```shell
node ./node_modules/esbuild/install.js
```
详细原因可以查看:[https://github.com/vitejs/vite/discussions/8146](https://github.com/vitejs/vite/discussions/8146)
## vue运行的时候报错
在启动企业版的时候,如果提示下面错误:
![](/oidcerror.png)
请使用`npm run dev`命令来启动项目
## NodeJs v16中node-sass报错
在使用`npm install`时最常见的一个错误就是关于node-sass包安装的错误如下
```shell
npm ERR! code 1
npm ERR! path D:\OpenAuth.Pro\Client\node_modules\node-sass
npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c node scripts/build.js
npm ERR! Building: C:\Program Files\nodejs\node.exe D:\OpenAuth.Pro\Client\node_modules\node-gyp\bin\node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=
npm ERR! gyp info it worked if it ends with ok
npm ERR! gyp verb cli [
npm ERR! gyp verb cli 'C:\\Program Files\\nodejs\\node.exe',
npm ERR! gyp verb cli 'D:\\OpenAuth.Pro\\Client\\node_modules\\node-gyp\\bin\\node-gyp.js',
npm ERR! gyp verb cli 'rebuild',
npm ERR! gyp verb cli '--verbose',
npm ERR! gyp verb cli '--libsass_ext=',
npm ERR! gyp verb cli '--libsass_cflags=',
npm ERR! gyp verb cli '--libsass_ldflags=',
npm ERR! gyp verb cli '--libsass_library='
npm ERR! gyp verb cli ]
npm ERR! gyp info using node-gyp@3.8.0
npm ERR! gyp info using node@16.13.2 | win32 | x64
npm ERR! gyp verb command rebuild []
npm ERR! gyp verb command clean []
npm ERR! gyp verb clean removing "build" directory
npm ERR! gyp verb command configure []
npm ERR! gyp verb check python checking for Python executable "python2" in the PATH
npm ERR! gyp verb `which` failed Error: not found: python2
...
npm ERR! gyp verb check python checking for Python executable "python" in the PATH
npm ERR! gyp verb `which` failed Error: not found: python
npm ERR! gyp verb `which` failed at getNotFoundError (D:\OpenAuth.Pro\Client\node_modules\which\which.js:13:12)
...
npm ERR! gyp verb could not find "python". checking python launcher
npm ERR! gyp verb could not find "python". guessing location
npm ERR! gyp verb ensuring that file exists: C:\Python27\python.exe
npm ERR! gyp ERR! configure error
npm ERR! gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
npm ERR! gyp ERR! stack at PythonFinder.failNoPython (D:\OpenAuth.Pro\Client\node_modules\node-gyp\lib\configure.js:484:19)
npm ERR! gyp ERR! stack at PythonFinder.<anonymous> (D:\OpenAuth.Pro\Client\node_modules\node-gyp\lib\configure.js:509:16)
npm ERR! gyp ERR! stack at FSReqCallback.oncomplete (node:fs:198:21)
npm ERR! gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "D:\\OpenAuth.Pro\\Client\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
npm ERR! gyp ERR! cwd D:\OpenAuth.Pro\Client\node_modules\node-sass
npm ERR! gyp ERR! node -v v16.13.2
npm ERR! gyp ERR! node-gyp -v v3.8.0
npm ERR! gyp ERR! not ok
npm ERR! Build failed with error code: 1
```
修复方法:
* 修改package.json文件中node-sass版本
```javascript
"node-sass": "^6.0.1",
```
* 清理node缓存重新安装
```shell
npm cache clean --force
npm i
```

58
docs/pro/form.md Normal file
View File

@ -0,0 +1,58 @@
# 工作流添加自定义表单
OpenAuth.Pro使用的动态表单可以满足日常普通的审批功能但如果想`对用户提交的表单数据进行统计分析`、需要用户提交附件、需要`复杂的表单交互`,这时就需要开发者开发自己的表单页面。实现更加丰富的功能,效果如下:
![20211228212712](http://img.openauth.net.cn/20211228212712.png)
本文以如何添加一个请假流程为例:
## 添加数据库表结构
先在数据库中添加记录表单数据的表,即请假条中的内容。
![20211228212800](http://img.openauth.net.cn/20211228212800.png)
## 编写请假条表单代码
系统约定所有开发人员自己开发的表单全部放在views/forms文件夹下。并且以下图的文件结构进行放置。
![20211228212843](http://img.openauth.net.cn/20211228212843.png)
其中:
frmLeaveReq为业务表单的文件夹名称必须与数据库表名保持一致。
* add.vue为业务表单页面负责编写业务输入逻辑。内部methods必须包含方法
```javascript
getData() {
return this.temp
}
```
上层框架会调用该方法来获取表单中的数据,用于后续逻辑处理。
* detail.vue为业务表单的展示页面。
## 注册表单
在项目main.js中注入刚刚添加的组件
```javascript
// 请假条表单和详情
import FrmLeaveReqAdd from '@/views/forms/userDefine/frmLeaveReq/add'
import FrmLeaveReqDetail from '@/views/forms/userDefine/frmLeaveReq/detail'
Vue.component('FrmLeaveReqAdd', FrmLeaveReqAdd)
Vue.component('FrmLeaveReqDetail', FrmLeaveReqDetail)
```
并在表单添加的下拉框里添加:
![20211228213129](http://img.openauth.net.cn/20211228213129.png)
## 配置表单
编写完上面代码后,运行企业版。使用【基础配置】--【表单设计】--【添加】功能添加刚刚的表单:
![20211228213154](http://img.openauth.net.cn/20211228213154.png)
这样就可以在流程设计里面,选择使用刚刚添加的表单了。

25
docs/pro/openurl.md Normal file
View File

@ -0,0 +1,25 @@
# 打开指定URL
上一章节通过添加模块或直接在路由表中添加固定路由实现路由控制。在有些场景下需要代码中直接打开一个外部指定URL的地址不通过系统的【模块管理】功能添加到导航栏如下图
![20220331231338](http://img.openauth.net.cn/20220331231338.png)
可以直接使用下面代码实现:
```javascript
openUrl() {
let obj = {}
obj['openauth'] = { //这里的openauth可以改成你希望在浏览器地址栏中看到的url
name: '官网',
url: 'http://www.openauth.net.cn',
}
this.$store.dispatch('setIframeTagViews', obj, { root: true })
this.$router.push({ path: '/iframePage/openauth' })
},
```

49
docs/pro/router.md Normal file
View File

@ -0,0 +1,49 @@
# 路由操作
OpenAuth.Pro采用的是标准vue router来管理页面跳转基础知识请参考[https://router.vuejs.org/zh/](https://router.vuejs.org/zh/)。如果需要添加页面,可以通过以下两种方式:
## 模块管理添加页面
直接使用【基础配置】->【模块管理】功能添加自己想访问的页面。如图:
![20211211002313](http://img.openauth.net.cn/20211211002313.png)
::: tip 提示
如果添加的url里面带有`http`系统会自动使用iframe加载一个三方的站点无需特殊处理。如系统自带的【接口文档】模块
:::
## 不通过模块管理添加页面
在有些场景下,不想通过系统的【模块管理】功能添加页面,如登录、注册、帮助中心、站点介绍等,可以在路由表中直接添加。
打开`src\router\index.js`,在数组常量`constantRouterMap`中添加自己的路由信息:
```javascript
{
path: '/regster',
name: 'regster',
hidden: true, //是否在左侧导航栏隐藏
meta: {
title: '仓储中心',
icon: 'guide',
sortNo: 0
},
component: () => import('@/views/regster/index') //路由对应的页面视图
}
```
因为注册页面没有登录的用户信息,会被系统的权限体系拦截从而跳转到登录页面。需要添加到白名单中。
打开`src\permission.js`,在`whiteList`中加入刚刚的路由信息:
```javascript
const whiteList = ['/regster', ...] // 不重定向白名单
```
添加完成后,启动站点,直接浏览器访问`http://localhost:1803/#/regster`即可:

29
docs/pro/startflow.md Normal file
View File

@ -0,0 +1,29 @@
# 操作手册
一个完整的工作流包括流程设计及流程实例处理。分别对应系统中【基础配置/流程设计】及【流程中心】两个板块。具体包含以下几个步骤:
## 添加流程模版
在【基础配置/流程设计】中添加一个流程模版,建好流程模版,拥有该模版权限的用户就可以基于改模版创建流程实例。操作如下:
![20220224001909](http://img.openauth.net.cn/20220224001909.png)
::: warning 注意
流程模版使用的表单,需要在【基础配置/表单设计】中添加,具体查看[表单设计-基本介绍](/pro/startform.html)
:::
## 添加流程实例
在【流程中心/我的流程】中【新的申请】创建一个流程实例。创建成功后就可以在列表中看到该流程。
## 流程审批
流程节点对应的执行用户会在【流程中心/待处理流程】中看到该流程,并进行相应的处理;
适用场景和普通的动态表单一样。但该表单操作方便,与系统界面风格匹配度高,缺点是排版没有普通的动态表单灵活,只能做简单的行排列。

16
docs/pro/startform.md Normal file
View File

@ -0,0 +1,16 @@
# 基本介绍
OpenAuth.Pro内置的表单类型有以下三种
## 动态表单
动态表单适用于灵活设计界面,逻辑简单的表单。这种表单无需编码,即可直接集成到流程功能。
## 自定义开发表单
该类型表单需要开发者在源码中先编写好表单界面基于vue component,再提供给用户选择使用。适用于交互复杂的界面。详细请参考:[企业版工作流添加自定义表单](/pro/form.html)
## 可拖拽表单
适用场景和普通的动态表单一样。但该表单操作方便,与系统界面风格匹配度高,缺点是排版没有普通的动态表单灵活,只能做简单的行排列。详细请参考:[可拖拽表单](/pro/dragform.html)

11
docs/pro/structure.md Normal file
View File

@ -0,0 +1,11 @@
# 项目结构
![20211215221811](http://img.openauth.net.cn/20211215221811.png)
整个vue的入口是main.js这个可以在webpack.base.conf.js中调整配置代码如下
```javascript
entry: {
app: './src/main.js'
}
```
通过打包之后编译后的代码全部会注入到index.html的`<div id="app"></div>`里面。