mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2026-08-01 03:26:50 +08:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44d5b286aa | ||
|
|
5664792162 | ||
|
|
3be8644769 | ||
|
|
32e0ae1a6b | ||
|
|
ee396146d3 | ||
|
|
98808a65ea | ||
|
|
4dd882cf90 | ||
|
|
be1c79799d | ||
|
|
e84e5d47ee | ||
|
|
0570a58743 | ||
|
|
889445bbcf | ||
|
|
2d108586e7 | ||
|
|
18c6fbfaad | ||
|
|
50769b94c6 | ||
|
|
a5bbfad2ff | ||
|
|
89c3133889 | ||
|
|
7ad9b54fd2 | ||
|
|
66e33c779c | ||
|
|
430ae8c377 | ||
|
|
a76aa99cb9 | ||
|
|
4e6287808b | ||
|
|
12d327ddac | ||
|
|
ba511edf5b | ||
|
|
ea1cbb0f6b | ||
|
|
09c47a7a07 | ||
|
|
0392a1ff30 | ||
|
|
6a290fe30f | ||
|
|
92be71ac49 | ||
|
|
7316e17d3c | ||
|
|
6fc4300521 | ||
|
|
1369b08f70 | ||
|
|
04a557b6e6 | ||
|
|
b909a98d96 | ||
|
|
85d409f846 | ||
|
|
6b3ae29a19 | ||
|
|
5eec669cde | ||
|
|
329c2c9f07 | ||
|
|
f6b7ba8b88 | ||
|
|
b6a2707097 | ||
|
|
8608aea1e9 | ||
|
|
b8963d0557 | ||
|
|
1db14b7973 | ||
|
|
e244246028 | ||
|
|
d07b75201d | ||
|
|
b887ae372b |
@@ -7,27 +7,22 @@ Description: 列表页面
|
||||
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context"
|
||||
Description="连接的数据库" %>
|
||||
<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
|
||||
|
||||
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
|
||||
<%@ Assembly Name="SchemaExplorer" %>
|
||||
<%@ Import Namespace="SchemaExplorer" %>
|
||||
<%@ Assembly Src="Util.cs" %>
|
||||
<%@ Import Namespace="Util" %>
|
||||
|
||||
@section header
|
||||
{
|
||||
<link rel="stylesheet" href="/css/treetable.css" />
|
||||
}
|
||||
<blockquote class="layui-elem-quote news_search toolList" id="menus">
|
||||
</blockquote>
|
||||
|
||||
<div class="layui-card">
|
||||
|
||||
<table class="layui-table" id="mainList"
|
||||
lay-data="{height: 'full-80', page:true, id:'mainList'}"
|
||||
lay-filter="list" lay-size="sm">
|
||||
</table>
|
||||
|
||||
<script type="text/html" id="Disable">
|
||||
{{# if(d.Disable){ }}
|
||||
<span class="layui-badge">已禁用</span>
|
||||
@@ -35,41 +30,46 @@ Description="连接的数据库" %>
|
||||
<span class="layui-badge layui-bg-green">正常</span>
|
||||
{{# } }}
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
<!--添加/编辑窗口-->
|
||||
<div id="divEdit" style="display: none">
|
||||
<form class="layui-form" action="" id="formEdit">
|
||||
<form class="layui-form" action="" id="formEdit" lay-filter="formEdit">
|
||||
<% foreach (ColumnSchema column in this.SourceTable.Columns) {
|
||||
var typename = CSharpAlias[column.SystemType.FullName];
|
||||
//Response.WriteLine(typename);
|
||||
if(column.IsPrimaryKeyMember){%>
|
||||
<input type="hidden" name="<%=column.Name%>" v-model="tmp.<%=column.Name%>" />
|
||||
<input type="hidden" name="<%=column.Name%>" />
|
||||
<%}else if(CSharpAlias[column.SystemType.FullName] == "bool") {%>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><%=Tools.GetDescription(column)%></label>
|
||||
<div class="layui-input-block">
|
||||
<input type="checkbox" name="<%=column.Name%>" v-model="tmp.<%=column.Name%>" lay-skin="switch" value="1">
|
||||
<input type="checkbox" name="<%=column.Name%>" lay-skin="switch" value="1">
|
||||
</div>
|
||||
</div>
|
||||
<%}else if(CSharpAlias[column.SystemType.FullName] == "System.DateTime") {%>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><%=Tools.GetDescription(column)%></label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="<%=column.Name%>" id="<%=column.Name%>" lay-verify="date" placeholder="yyyy-MM-dd" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<%}else if(CSharpAlias[column.SystemType.FullName] == "int" ) {%>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><%=Tools.GetDescription(column)%></label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="<%=column.Name%>" value="1" title="value1" checked>
|
||||
<input type="radio" name="<%=column.Name%>" value="0" title="value2">
|
||||
<input type="number" name="<%=column.Name%>" placeholder="" autocomplete="off" class="layui-input" min="0" step="1" lay-affix="number">
|
||||
</div>
|
||||
</div>
|
||||
<%} else {%>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><%=Tools.GetDescription(column)%></label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="<%=column.Name%>" v-model="tmp.<%=column.Name%>" required lay-verify="required"
|
||||
<input type="text" name="<%=column.Name%>" required lay-verify="required"
|
||||
placeholder="<%=Tools.GetDescription(column)%>" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<%} %>
|
||||
<%} %>
|
||||
|
||||
<%if(Tools.NeedCascade(SourceTable)){ %>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">所属部门</label>
|
||||
@@ -82,7 +82,6 @@ Description="连接的数据库" %>
|
||||
</div>
|
||||
</div>
|
||||
<%} %>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="formSubmit">立即提交</button>
|
||||
@@ -91,8 +90,5 @@ Description="连接的数据库" %>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/layui/layui.js"></script>
|
||||
<script type="text/javascript" src="/userJs/<%=ModuleName.ToLower()%>s.js"></script>
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ Author: yubaolee
|
||||
--%>
|
||||
<%@ CodeTemplate Language="C#" TargetLanguage="C#" Debug="False" Encoding="utf-8" Description="添加模块" %>
|
||||
<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
|
||||
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context"
|
||||
Description="连接的数据库" %>
|
||||
|
||||
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
|
||||
<%@ Assembly Name="SchemaExplorer" %>
|
||||
@@ -13,9 +15,10 @@ Author: yubaolee
|
||||
|
||||
layui.config({
|
||||
base: "/js/"
|
||||
}).use(['form', 'vue', 'ztree', 'layer', 'jquery', 'table', 'droptree', 'openauth', 'utils'], function () {
|
||||
}).use(['form', 'laydate', 'ztree', 'layer', 'jquery', 'table', 'droptree', 'openauth', 'utils'], function () {
|
||||
var form = layui.form,
|
||||
layer = layui.layer,
|
||||
laydate = layui.laydate,
|
||||
$ = layui.jquery;
|
||||
var table = layui.table;
|
||||
var openauth = layui.openauth;
|
||||
@@ -23,30 +26,49 @@ layui.config({
|
||||
|
||||
$("#menus").loadMenus("<%=ModuleName%>");
|
||||
|
||||
<% foreach (ColumnSchema column in this.SourceTable.Columns) {
|
||||
if(CSharpAlias[column.SystemType.FullName] == "System.DateTime") { %>
|
||||
laydate.render({
|
||||
elem: '#<%=column.Name%>'
|
||||
});
|
||||
<%} }%>
|
||||
|
||||
var initVal = { //初始化的值
|
||||
<% foreach (ColumnSchema column in this.SourceTable.Columns) {
|
||||
if(CSharpAlias[column.SystemType.FullName] == "bool") { %>
|
||||
<%=column.Name%>: false,
|
||||
<%}else if(CSharpAlias[column.SystemType.FullName] == "int" ) {%>
|
||||
<%=column.Name%>: 0,
|
||||
<%}else if(CSharpAlias[column.SystemType.FullName] == "System.DateTime") {%>
|
||||
<%=column.Name%>: new Date().toISOString().split('T')[0],
|
||||
<%} else {%>
|
||||
<%=column.Name%>: '',
|
||||
<%} }%>
|
||||
}
|
||||
|
||||
//加载表头
|
||||
$.getJSON('/<%=ModuleName%>s/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: '/<%=ModuleName%>s/Load',
|
||||
cols: [columns]
|
||||
, response: {
|
||||
statusCode: 200 //规定成功的状态码,默认:0
|
||||
}
|
||||
});
|
||||
{ page: 1, limit: 1 },
|
||||
function (data) {
|
||||
var columns = data.columnFields.filter(u => u.IsList ===true).map(function (e) {
|
||||
return {
|
||||
field: e.ColumnName,
|
||||
title: e.Remark
|
||||
};
|
||||
});
|
||||
columns.unshift({
|
||||
type: 'checkbox',
|
||||
fixed: 'left'
|
||||
});
|
||||
table.render({
|
||||
elem: '#mainList',
|
||||
page: true,
|
||||
url: '/<%=ModuleName%>s/Load',
|
||||
cols: [columns]
|
||||
, response: {
|
||||
statusCode: 200 //规定成功的状态码,默认:0
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -69,9 +91,7 @@ layui.config({
|
||||
|
||||
//添加(编辑)对话框
|
||||
var editDlg = function () {
|
||||
var vm;
|
||||
var update = false; //是否为更新
|
||||
var show = function (data) {
|
||||
var show = function (update, data) {
|
||||
var title = update ? "编辑信息" : "添加";
|
||||
layer.open({
|
||||
title: title,
|
||||
@@ -79,32 +99,11 @@ layui.config({
|
||||
type: 1,
|
||||
content: $('#divEdit'),
|
||||
success: function () {
|
||||
if(vm == undefined){
|
||||
vm = new Vue({
|
||||
el: "#formEdit",
|
||||
data(){
|
||||
return {
|
||||
tmp:data //使用一个tmp封装一下,后面可以直接用vm.tmp赋值
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
tmp(val){
|
||||
this.$nextTick(function () {
|
||||
form.render(); //刷新select等
|
||||
layui.droptree("/Applications/GetList", "#AppName", "#AppId", false);
|
||||
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
form.render();
|
||||
layui.droptree("/Applications/GetList", "#AppName", "#AppId", false);
|
||||
|
||||
}
|
||||
});
|
||||
}else{
|
||||
vm.tmp = Object.assign({}, vm.tmp,data)
|
||||
}
|
||||
if(data == undefined){
|
||||
form.val("formEdit", initVal);
|
||||
}else{
|
||||
form.val("formEdit", data);
|
||||
}
|
||||
},
|
||||
end: mainList
|
||||
});
|
||||
@@ -125,15 +124,11 @@ layui.config({
|
||||
});
|
||||
}
|
||||
return {
|
||||
add: function () { //弹出添加
|
||||
update = false;
|
||||
show({
|
||||
Id: ''
|
||||
});
|
||||
add: function () { //弹出添加
|
||||
show(false);
|
||||
},
|
||||
update: function (data) { //弹出编辑框
|
||||
update = true;
|
||||
show(data);
|
||||
show(true, data);
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
//流程实例知会用户
|
||||
public const string INSTANCE_NOTICE_USER = "INSTANCE_NOTICE_USER";
|
||||
//流程实例知会角色
|
||||
public const string INSTANCE_NOTICE_ROLE = "INSTANCE_NOTICE_ROLE";
|
||||
public const string INSTANCE_NOTICE_ROLE = "INSTANCE_NOTICE_ROLE";
|
||||
|
||||
public const string API = "API_RESOURCE";
|
||||
}
|
||||
}
|
||||
@@ -35,10 +35,6 @@ namespace OpenAuth.App
|
||||
|
||||
public T Get(string id)
|
||||
{
|
||||
if (SugarClient.CurrentConnectionConfig.DbType == DbType.PostgreSQL)
|
||||
{
|
||||
return SugarClient.Queryable<T>().Where("\"Id\"=@id", new {id = id}).First();
|
||||
}
|
||||
return SugarClient.Queryable<T>().Where("Id=@id", new {id = id}).First();
|
||||
}
|
||||
|
||||
|
||||
@@ -60,14 +60,14 @@ namespace OpenAuth.App
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Add(AddOrUpdateCategoryReq req)
|
||||
public async Task Add(AddOrUpdateCategoryReq req)
|
||||
{
|
||||
var obj = req.MapTo<Category>();
|
||||
obj.CreateTime = DateTime.Now;
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
obj.CreateUserId = user.Id;
|
||||
obj.CreateUserName = user.Name;
|
||||
Repository.Add(obj);
|
||||
await Repository.AddAsync(obj);
|
||||
}
|
||||
|
||||
public void Update(AddOrUpdateCategoryReq obj)
|
||||
@@ -82,8 +82,8 @@ namespace OpenAuth.App
|
||||
TypeId = obj.TypeId,
|
||||
UpdateTime = DateTime.Now,
|
||||
UpdateUserId = user.Id,
|
||||
UpdateUserName = user.Name
|
||||
//todo:要修改的字段赋值
|
||||
UpdateUserName = user.Name,
|
||||
SortNo = obj.SortNo
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -3,34 +3,31 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Humanizer;
|
||||
using Infrastructure;
|
||||
using Infrastructure.Utilities;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OpenAuth.Repository;
|
||||
using OpenAuth.Repository.Core;
|
||||
using OpenAuth.Repository.Domain;
|
||||
using OpenAuth.Repository.QueryObj;
|
||||
using SqlSugar;
|
||||
|
||||
namespace OpenAuth.App
|
||||
{
|
||||
public class DbExtension
|
||||
{
|
||||
private List<DbContext> _contexts = new List<DbContext>();
|
||||
|
||||
protected ISqlSugarClient SugarClient;
|
||||
|
||||
private IOptions<AppSetting> _appConfiguration;
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public DbExtension(IOptions<AppSetting> appConfiguration, OpenAuthDBContext openAuthDbContext, IHttpContextAccessor httpContextAccessor)
|
||||
public DbExtension(IOptions<AppSetting> appConfiguration, ISqlSugarClient sugarClient, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_appConfiguration = appConfiguration;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_contexts.Add(openAuthDbContext); //如果有多个DBContext,可以按OpenAuthDBContext同样的方式添加到_contexts中
|
||||
SugarClient = sugarClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -42,27 +39,26 @@ namespace OpenAuth.App
|
||||
public List<BuilderTableColumn> GetTableColumnsFromDb(string moduleName)
|
||||
{
|
||||
var result = new List<BuilderTableColumn>();
|
||||
const string domain = "openauth.repository.domain.";
|
||||
IEntityType entity = null;
|
||||
_contexts.ForEach(u =>
|
||||
{
|
||||
entity = u.Model.GetEntityTypes()
|
||||
.FirstOrDefault(u => u.Name.ToLower() == domain + moduleName.ToLower());
|
||||
});
|
||||
if (entity == null)
|
||||
|
||||
//获取所有继承了StringEntity的类型
|
||||
//单元测试时,这个一直报错????奇怪
|
||||
var entiTypes = typeof(StringEntity).Assembly.GetTypes().Where(u => typeof(StringEntity).IsAssignableFrom(u) && !u.IsAbstract).ToList();
|
||||
|
||||
var entityType = entiTypes.FirstOrDefault(u => u.Name.ToLower() == moduleName.ToLower());
|
||||
if (entityType == null)
|
||||
{
|
||||
throw new Exception($"未能找到{moduleName}对应的实体类");
|
||||
}
|
||||
|
||||
foreach (var property in entity.ClrType.GetProperties())
|
||||
foreach (var property in entityType.GetProperties())
|
||||
{
|
||||
object[] objs = property.GetCustomAttributes(typeof(DescriptionAttribute), true);
|
||||
object[] browsableObjs = property.GetCustomAttributes(typeof(BrowsableAttribute), true);
|
||||
var description = objs.Length > 0 ? ((DescriptionAttribute) objs[0]).Description : property.Name;
|
||||
var description = objs.Length > 0 ? ((DescriptionAttribute)objs[0]).Description : property.Name;
|
||||
if (string.IsNullOrEmpty(description)) description = property.Name;
|
||||
//如果没有BrowsableAttribute或 [Browsable(true)]表示可见,其他均为不可见,需要前端配合显示
|
||||
bool browsable = browsableObjs == null || browsableObjs.Length == 0 ||
|
||||
((BrowsableAttribute) browsableObjs[0]).Browsable;
|
||||
((BrowsableAttribute)browsableObjs[0]).Browsable;
|
||||
var typeName = property.PropertyType.Name;
|
||||
if (Nullable.GetUnderlyingType(property.PropertyType) != null)
|
||||
{
|
||||
@@ -81,29 +77,6 @@ namespace OpenAuth.App
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库DbContext中所有的实体名称。
|
||||
/// <para>注意!并不能获取数据库中的所有表</para>
|
||||
/// </summary>
|
||||
public List<string> GetDbEntityNames()
|
||||
{
|
||||
var names = new List<string>();
|
||||
var models = _contexts.Select(u =>u.Model);
|
||||
|
||||
foreach (var model in models)
|
||||
{
|
||||
// Get all the entity types information contained in the DbContext class, ...
|
||||
var entityTypes = model.GetEntityTypes();
|
||||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
var tableNameAnnotation = entityType.GetAnnotation("Relational:TableName");
|
||||
names.Add(tableNameAnnotation.Value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库表结构信息
|
||||
/// </summary>
|
||||
@@ -135,63 +108,62 @@ namespace OpenAuth.App
|
||||
/// </summary>
|
||||
private IList<SysTableColumn> GetOracleStructure(string tableName)
|
||||
{
|
||||
tableName = tableName.ToUpper();
|
||||
var sql = $@"
|
||||
select utc.column_name as columnname
|
||||
, utc.data_type columntype
|
||||
, utc.data_length maxlength
|
||||
, case utc.nullable when 'N' then 0 else 1 end isnull
|
||||
, utc.data_default defaultval
|
||||
, ucc.comments ""COMMENT""
|
||||
, utc.table_name tablename
|
||||
, case utc.column_name
|
||||
when (select col.column_name
|
||||
from user_constraints con
|
||||
, user_cons_columns col
|
||||
where con.constraint_name = col.constraint_name
|
||||
and con.constraint_type = 'P'
|
||||
and col.table_name = '{tableName}') then 1
|
||||
else 0 end as iskey
|
||||
, case
|
||||
when utc.column_name in ('CreateUserId', 'UpdateUserId', 'Id')
|
||||
then 0
|
||||
else 1
|
||||
end as isdisplay
|
||||
, case
|
||||
when data_type in ('BIT', 'BOOL') then
|
||||
'bool'
|
||||
when data_type in ('SMALLINT') then 'short'
|
||||
when data_type in ('TINYINT') then 'bool'
|
||||
when data_type in ('NUMBER', 'CHAR', 'INT', 'Year') then
|
||||
'int'
|
||||
when data_type in ('BIGINT') then
|
||||
'bigint'
|
||||
when data_type in ('FLOAT', 'DOUBLE', 'DECIMAL') then
|
||||
'decimal'
|
||||
when data_type in
|
||||
('CHAR', 'VARCHAR', 'TINY TEXT', 'TEXT', 'MEDIUMTEXT', 'LONGTEXT', 'TINYBLOB', 'BLOB',
|
||||
'MEDIUMBLOB', 'LONGBLOB', 'Time') then
|
||||
'string'
|
||||
when data_type in ('Date', 'DateTime', 'TIMESTAMP(6)') then
|
||||
'DateTime'
|
||||
else 'string'
|
||||
end as entitytype
|
||||
from user_tab_columns utc
|
||||
, user_col_comments ucc
|
||||
where utc.table_name = ucc.table_name
|
||||
and utc.column_name = ucc.column_name
|
||||
and utc.table_name = '{tableName}'
|
||||
order by column_id; ";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
select utc.column_name as columnname
|
||||
, utc.data_type columntype
|
||||
, utc.data_length maxlength
|
||||
, case utc.nullable when 'N' then 0 else 1 end isnull
|
||||
, utc.data_default defaultval
|
||||
, ucc.comments ""COMMENT""
|
||||
, utc.table_name tablename
|
||||
, case utc.column_name
|
||||
when (select col.column_name
|
||||
from user_constraints con
|
||||
, user_cons_columns col
|
||||
where con.constraint_name = col.constraint_name
|
||||
and con.constraint_type = 'P'
|
||||
and col.table_name = '{tableName}') then 1
|
||||
else 0 end as iskey
|
||||
, case
|
||||
when utc.column_name in ('CreateUserId', 'UpdateUserId', 'Id')
|
||||
then 0
|
||||
else 1
|
||||
end as isdisplay
|
||||
, case
|
||||
when data_type in ('BIT', 'BOOL') then
|
||||
'bool'
|
||||
when data_type in ('SMALLINT') then 'short'
|
||||
when data_type in ('TINYINT') then 'bool'
|
||||
when data_type in ('NUMBER', 'CHAR', 'INT', 'Year') then
|
||||
'int'
|
||||
when data_type in ('BIGINT') then
|
||||
'bigint'
|
||||
when data_type in ('FLOAT', 'DOUBLE', 'DECIMAL') then
|
||||
'decimal'
|
||||
when data_type in
|
||||
('CHAR', 'VARCHAR', 'TINY TEXT', 'TEXT', 'MEDIUMTEXT', 'LONGTEXT', 'TINYBLOB', 'BLOB',
|
||||
'MEDIUMBLOB', 'LONGBLOB', 'Time') then
|
||||
'string'
|
||||
when data_type in ('DATE', 'DATETIME', 'TIMESTAMP(6)') then
|
||||
'DateTime'
|
||||
else 'string'
|
||||
end as entitytype
|
||||
from user_tab_columns utc
|
||||
, user_col_comments ucc
|
||||
where utc.table_name = ucc.table_name
|
||||
and utc.column_name = ucc.column_name
|
||||
and utc.table_name = '{tableName}'
|
||||
order by column_id; ";
|
||||
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
return columnList;
|
||||
}
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
|
||||
|
||||
return new List<SysTableColumn>();
|
||||
}
|
||||
|
||||
@@ -200,9 +172,9 @@ order by column_id; ";
|
||||
/// </summary>
|
||||
private IList<SysTableColumn> GetMySqlStructure(string tableName)
|
||||
{
|
||||
var sql = $@"SELECT DISTINCT
|
||||
var sql = $@"SELECT DISTINCT
|
||||
Column_Name AS ColumnName,
|
||||
'{ tableName}' as tableName,
|
||||
'{tableName}' as tableName,
|
||||
Column_Comment AS Comment,
|
||||
data_type as ColumnType,
|
||||
CASE
|
||||
@@ -247,105 +219,104 @@ order by column_id; ";
|
||||
WHERE
|
||||
table_name = '{tableName}'";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return new List<SysTableColumn>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取Mysql表结构信息
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取pgsql表结构信息
|
||||
/// </summary>
|
||||
private IList<SysTableColumn> GetPostgreStructure(string tableName)
|
||||
{
|
||||
var sql = $@"select attr.attrelid
|
||||
, schema.nspname as schemaname
|
||||
, class.relname as tablename --表名
|
||||
, attr.attname as columnname --列名
|
||||
, attr.atttypid --类型ID
|
||||
, attr.atttypmod
|
||||
, case when con.conname is not null then 1 else 0 end as iskey --是否主键
|
||||
, case when attr.attnotnull is true then 0 else 1 end as isnull --可空
|
||||
, t.typname columntype --类型名称
|
||||
, case
|
||||
when typname in ('BIT', 'BOOL', 'bit', 'bool') then
|
||||
'bool'
|
||||
when typname in ('smallint', 'SMALLINT') then 'short'
|
||||
when typname in ('tinyint', 'TINYINT') then 'bool'
|
||||
when typname in ('int4', 'int', 'INT') then
|
||||
'int'
|
||||
when typname in ('BIGINT', 'bigint') then
|
||||
'bigint'
|
||||
when typname in ('FLOAT', 'DOUBLE', 'DECIMAL', 'float', 'double', 'decimal') then
|
||||
'decimal'
|
||||
when typname in ('varchar', 'text') then
|
||||
'string'
|
||||
when typname in ('Date', 'DateTime', 'TimeStamp', 'date', 'datetime', 'timestamp') then
|
||||
'DateTime'
|
||||
else 'string'
|
||||
end as entitytype
|
||||
, comment.description as comment
|
||||
, 1 as iscolumndata
|
||||
, case
|
||||
when t.typname = 'varchar' or t.typname = 'bpchar' then attr.atttypmod - 4
|
||||
else 10
|
||||
end as columnwidth
|
||||
, 0 as orderno
|
||||
, case
|
||||
when t.typname = 'varchar' or t.typname = 'bpchar' then attr.atttypmod - 4
|
||||
else 10
|
||||
end as maxlength
|
||||
, case
|
||||
when attname in ('createid', 'modifyid', '')
|
||||
or con.conname is null then 0
|
||||
else 1
|
||||
end as isdisplay --是否显示
|
||||
from pg_catalog.pg_class class
|
||||
inner join pg_catalog.pg_attribute attr on attr.attrelid = class.oid
|
||||
left join pg_catalog.pg_constraint con
|
||||
on con.conrelid = class.oid and attr.attnum = any (con.conkey) and con.contype = 'p'
|
||||
left join pg_catalog.pg_type t on attr.atttypid = t.oid
|
||||
inner join pg_catalog.pg_description comment
|
||||
on comment.objoid = attr.attrelid and comment.objsubid = attr.attnum
|
||||
inner join pg_catalog.pg_namespace schema on schema.oid = class.relnamespace
|
||||
where attr.attnum > 0
|
||||
and not attr.attisdropped
|
||||
and schema.nspname = 'public' -- replace 'your_schema' with your schema name
|
||||
and class.relname = '{tableName}'";
|
||||
tableName = tableName.ToLower();
|
||||
var sql = $@"select attr.attrelid
|
||||
, schema.nspname as schemaname
|
||||
, class.relname as tablename --表名
|
||||
, attr.attname as columnname --列名
|
||||
, attr.atttypid --类型ID
|
||||
, attr.atttypmod
|
||||
, case when con.conname is not null then 1 else 0 end as iskey --是否主键
|
||||
, case when attr.attnotnull is true then 0 else 1 end as isnull --可空
|
||||
, t.typname columntype --类型名称
|
||||
, case
|
||||
when typname in ('BIT', 'BOOL', 'bit', 'bool') then
|
||||
'bool'
|
||||
when typname in ('smallint', 'SMALLINT') then 'short'
|
||||
when typname in ('tinyint', 'TINYINT') then 'bool'
|
||||
when typname in ('int4', 'int', 'INT') then
|
||||
'int'
|
||||
when typname in ('BIGINT', 'bigint') then
|
||||
'bigint'
|
||||
when typname in ('FLOAT', 'DOUBLE', 'DECIMAL', 'float', 'double', 'decimal') then
|
||||
'decimal'
|
||||
when typname in ('varchar', 'text') then
|
||||
'string'
|
||||
when typname in ('Date', 'DateTime', 'TimeStamp', 'date', 'datetime', 'timestamp') then
|
||||
'DateTime'
|
||||
else 'string'
|
||||
end as entitytype
|
||||
, comment.description as comment
|
||||
, 1 as iscolumndata
|
||||
, case
|
||||
when t.typname = 'varchar' or t.typname = 'bpchar' then attr.atttypmod - 4
|
||||
else 10
|
||||
end as columnwidth
|
||||
, 0 as orderno
|
||||
, case
|
||||
when t.typname = 'varchar' or t.typname = 'bpchar' then attr.atttypmod - 4
|
||||
else 10
|
||||
end as maxlength
|
||||
, case
|
||||
when attname in ('createid', 'modifyid', '')
|
||||
or con.conname is null then 0
|
||||
else 1
|
||||
end as isdisplay --是否显示
|
||||
from pg_catalog.pg_class class
|
||||
inner join pg_catalog.pg_attribute attr on attr.attrelid = class.oid
|
||||
left join pg_catalog.pg_constraint con
|
||||
on con.conrelid = class.oid and attr.attnum = any (con.conkey) and con.contype = 'p'
|
||||
left join pg_catalog.pg_type t on attr.atttypid = t.oid
|
||||
inner join pg_catalog.pg_description comment
|
||||
on comment.objoid = attr.attrelid and comment.objsubid = attr.attnum
|
||||
inner join pg_catalog.pg_namespace schema on schema.oid = class.relnamespace
|
||||
where attr.attnum > 0
|
||||
and not attr.attisdropped
|
||||
and schema.nspname = 'public' -- replace 'your_schema' with your schema name
|
||||
and class.relname = '{tableName}'";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
return columnList;
|
||||
}
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
|
||||
|
||||
return new List<SysTableColumn>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取SqlServer表结构信息
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <returns></returns>
|
||||
private IList<SysTableColumn> GetSqlServerStructure(string tableName)
|
||||
{
|
||||
var sql = $@"
|
||||
var sql = $@"
|
||||
SELECT TableName,
|
||||
LTRIM(RTRIM(ColumnName)) AS ColumnName,
|
||||
Comment,
|
||||
@@ -426,17 +397,14 @@ where attr.attnum > 0
|
||||
LEFT JOIN sys.extended_properties epTwo ON obj.id = epTwo.major_id
|
||||
AND epTwo.minor_id = 0
|
||||
AND epTwo.name = 'MS_Description'
|
||||
WHERE obj.name = '{ tableName}') AS t
|
||||
WHERE obj.name = '{tableName}') AS t
|
||||
ORDER BY t.colorder";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
return columnList;
|
||||
}
|
||||
return columnList;
|
||||
}
|
||||
return new List<SysTableColumn>();
|
||||
}
|
||||
|
||||
115
OpenAuth.App/ExtDataSourceApp/ExtDataSourceApp.cs
Normal file
115
OpenAuth.App/ExtDataSourceApp/ExtDataSourceApp.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure;
|
||||
using OpenAuth.App.Interface;
|
||||
using OpenAuth.App.Request;
|
||||
using OpenAuth.App.Response;
|
||||
using OpenAuth.Repository.Domain;
|
||||
using SqlSugar;
|
||||
|
||||
|
||||
namespace OpenAuth.App
|
||||
{
|
||||
public class ExtDataSourceApp : SqlSugarBaseApp<ExternalDataSource>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 加载列表
|
||||
/// </summary>
|
||||
public async Task<TableData> Load(QueryExternalDataSourceListReq request)
|
||||
{
|
||||
var loginContext = _auth.GetCurrentUser();
|
||||
if (loginContext == null)
|
||||
{
|
||||
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
var result = new TableData();
|
||||
var objs = GetDataPrivilege("u");
|
||||
if (!string.IsNullOrEmpty(request.key))
|
||||
{
|
||||
objs = objs.Where(u => u.Name.Contains(request.key));
|
||||
}
|
||||
|
||||
result.data = objs.OrderBy(u => u.Name)
|
||||
.Skip((request.page - 1) * request.limit)
|
||||
.Take(request.limit).ToList();
|
||||
result.count = await objs.CountAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TableData GetDbTypes()
|
||||
{
|
||||
var result = new TableData();
|
||||
// 创建包含键值对的列表
|
||||
var dbTypeList = Enum.GetValues(typeof(DbType))
|
||||
.Cast<DbType>()
|
||||
.Select(item => new { label = item.ToString(), value = (int)item })
|
||||
.ToList();
|
||||
result.data = dbTypeList;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试数据源连接
|
||||
/// </summary>
|
||||
/// <param name="id">数据源ID</param>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public bool TestConnection(TestConnectionReq req)
|
||||
{
|
||||
var conn = new SqlSugarClient(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = req.Connectionstring,
|
||||
DbType = (DbType)Enum.Parse(typeof(DbType), req.Dbtype.ToString()),
|
||||
IsAutoCloseConnection = true,
|
||||
});
|
||||
conn.Open();
|
||||
return true;
|
||||
}
|
||||
public void Add(AddOrUpdateExternalDataSourceReq req)
|
||||
{
|
||||
var obj = req.MapTo<ExternalDataSource>();
|
||||
obj.Id = Guid.NewGuid().ToString();
|
||||
obj.Createtime = DateTime.Now;
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
obj.Createuserid = user.Id;
|
||||
obj.Createusername = user.Name;
|
||||
Repository.Insert(obj);
|
||||
}
|
||||
|
||||
public void Update(AddOrUpdateExternalDataSourceReq obj)
|
||||
{
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
Repository.Update(u => new ExternalDataSource
|
||||
{
|
||||
Name = obj.Name,
|
||||
Dbtype = obj.Dbtype,
|
||||
Databasename = obj.Databasename,
|
||||
Server = obj.Server,
|
||||
Port = obj.Port,
|
||||
Username = obj.Username,
|
||||
Password = obj.Password,
|
||||
Description = obj.Description,
|
||||
Enabled = obj.Enabled,
|
||||
Testsuccess = obj.Testsuccess,
|
||||
Connectionstring = obj.Connectionstring,
|
||||
Updatetime = DateTime.Now,
|
||||
Updateuserid = user.Id,
|
||||
Updateusername = user.Name
|
||||
},u => u.Id == obj.Id);
|
||||
|
||||
}
|
||||
|
||||
public ExtDataSourceApp(ISqlSugarClient client, IAuth auth) : base(client, auth)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public record TestConnectionReq(string Connectionstring, int Dbtype);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// This code was generated by a CodeSmith Template.
|
||||
//
|
||||
// DO NOT MODIFY contents of this file. Changes to this
|
||||
// file will be lost if the code is regenerated.
|
||||
// Author:Yubao Li
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using OpenAuth.Repository.Core;
|
||||
|
||||
namespace OpenAuth.App.Request
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
||||
public class AddOrUpdateExternalDataSourceReq
|
||||
{
|
||||
/// <summary>
|
||||
///是否测试成功
|
||||
/// </summary>
|
||||
public bool? Testsuccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///主键
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///是否启用
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///连接字符串
|
||||
/// </summary>
|
||||
public string Connectionstring { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///描述
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///用户名
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///端口
|
||||
/// </summary>
|
||||
public int? Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///服务器地址
|
||||
/// </summary>
|
||||
public string Server { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库名称
|
||||
/// </summary>
|
||||
public string Databasename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库类型
|
||||
/// </summary>
|
||||
public int Dbtype { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据源名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace OpenAuth.App.Request
|
||||
{
|
||||
public class QueryExternalDataSourceListReq : PageReq
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -538,6 +538,57 @@ namespace OpenAuth.App.Flow
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 撤销当前节点的审批
|
||||
/// </summary>
|
||||
public void UndoVerification()
|
||||
{
|
||||
// 已结束的流程不能撤销
|
||||
if (flowInstance.IsFinish == FlowInstanceStatus.Finished
|
||||
|| flowInstance.IsFinish == FlowInstanceStatus.Rejected)
|
||||
{
|
||||
throw new Exception("流程已结束,不能撤销");
|
||||
}
|
||||
|
||||
if(Nodes[previousId].type == FlowNode.START)
|
||||
{
|
||||
throw new Exception("没有任何审批,不能撤销!你可以删除或召回这个流程");
|
||||
}
|
||||
|
||||
// 恢复到上一个节点
|
||||
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 = "";
|
||||
currentNode.setInfo.UserName = "";
|
||||
currentNode.setInfo.Description = "";
|
||||
currentNode.setInfo.TagedTime = "";
|
||||
|
||||
//删除当前节点的扭转记录
|
||||
var user = AutofacContainerModule.GetService<IAuth>().GetCurrentUser().User;
|
||||
var SugarClient = AutofacContainerModule.GetService<ISqlSugarClient>();
|
||||
SugarClient.Deleteable<FlowInstanceTransitionHistory>().Where(u => u.InstanceId == flowInstanceId && u.CreateUserId == user.Id && u.FromNodeId == currentNodeId).ExecuteCommand();
|
||||
|
||||
//删除当前节点的审批记录(只删除最新的一条)
|
||||
var latestRecord = SugarClient.Queryable<FlowInstanceOperationHistory>()
|
||||
.Where(u => u.InstanceId == flowInstanceId && u.CreateUserId == user.Id)
|
||||
.OrderByDescending(u => u.CreateDate)
|
||||
.First();
|
||||
if (latestRecord != null)
|
||||
{
|
||||
SugarClient.Deleteable<FlowInstanceOperationHistory>()
|
||||
.Where(u => u.Id == latestRecord.Id)
|
||||
.ExecuteCommand();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion 共有方法
|
||||
|
||||
#region 获取节点审批人
|
||||
|
||||
@@ -7,7 +7,6 @@ using OpenAuth.App.Interface;
|
||||
using OpenAuth.App.Request;
|
||||
using OpenAuth.App.Response;
|
||||
using OpenAuth.Repository.Domain;
|
||||
using Quartz.Listener;
|
||||
using SqlSugar;
|
||||
|
||||
|
||||
@@ -51,6 +50,15 @@ namespace OpenAuth.App
|
||||
}
|
||||
|
||||
Repository.InsertRange(objs);
|
||||
SugarClient.Insertable(new FlowInstanceOperationHistory
|
||||
{
|
||||
InstanceId = obj.InstanceId,
|
||||
CreateUserId = loginContext.User.Id,
|
||||
CreateUserName = loginContext.User.Name,
|
||||
CreateDate = DateTime.Now,
|
||||
Content = $"【加签】{loginContext.User.Name}加签给:{string.Join(",", objs.Select(u => u.ApproverName))}"
|
||||
}).ExecuteCommand();
|
||||
|
||||
}
|
||||
|
||||
public void Update(AddApproverReq application)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
|
||||
* @Date: 2024-12-13 16:55:17
|
||||
* @Description: 工作流实例表操作
|
||||
* @LastEditTime: 2025-02-19 11:43:24
|
||||
* @LastEditTime: 2025-03-08 13:59:47
|
||||
* Copyright (c) 2024 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
*/
|
||||
|
||||
@@ -332,6 +332,40 @@ namespace OpenAuth.App
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 撤销当前节点的审批
|
||||
/// </summary>
|
||||
public void UndoVerification(UndoVerificationReq request)
|
||||
{
|
||||
var flowInstance = Get(request.FlowInstanceId);
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
|
||||
// 获取运行实例
|
||||
var wfruntime = new FlowRuntime(flowInstance);
|
||||
|
||||
SugarClient.Ado.BeginTran();
|
||||
try
|
||||
{
|
||||
wfruntime.UndoVerification();
|
||||
|
||||
// 更新流程实例状态
|
||||
flowInstance.IsFinish = FlowInstanceStatus.Running;
|
||||
flowInstance.SchemeContent = JsonHelper.Instance.Serialize(wfruntime.ToSchemeObj());
|
||||
|
||||
SugarClient.Updateable(flowInstance).ExecuteCommand();
|
||||
|
||||
// 记录撤销操作
|
||||
// wfruntime.SaveOperationHis($"【撤销审批】{user.Name}撤销了对【{wfruntime.currentNode.name}】的审批。备注:{request.Description}");
|
||||
|
||||
SugarClient.Ado.CommitTran();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SugarClient.Ado.RollbackTran();
|
||||
throw new Exception("撤销审批失败:" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 会签
|
||||
/// </summary>
|
||||
@@ -507,7 +541,15 @@ namespace OpenAuth.App
|
||||
{
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
FlowInstance flowInstance = Get(reqest.FlowInstanceId);
|
||||
if (flowInstance.MakerList != "1" && !flowInstance.MakerList.Contains(user.Id))
|
||||
|
||||
var approvers = _flowApproverApp.GetApproverIds(new QueryApproverReq
|
||||
{
|
||||
FlowInstanceId = reqest.FlowInstanceId,
|
||||
ActivityId = flowInstance.ActivityId
|
||||
});
|
||||
|
||||
if (flowInstance.MakerList != "1" && !flowInstance.MakerList.Contains(user.Id) &&
|
||||
!approvers.Contains(user.Id))
|
||||
{
|
||||
throw new Exception("当前用户没有驳回该节点权限");
|
||||
}
|
||||
@@ -582,7 +624,32 @@ namespace OpenAuth.App
|
||||
resp.NextNodeDesignateType = runtime.nextNode.setInfo.NodeDesignate;
|
||||
resp.CanWriteFormItemIds = runtime.currentNode.setInfo.CanWriteFormItemIds;
|
||||
}
|
||||
|
||||
var user = _auth.GetCurrentUser();
|
||||
var query = SugarClient.Queryable<FlowInstanceOperationHistory>()
|
||||
.OrderByDescending(u => u.CreateDate)
|
||||
.First(u => u.InstanceId == id);
|
||||
if (query != null)
|
||||
{
|
||||
//最后一个审批人是当前用户,可以撤销
|
||||
resp.CanUndoVerify = query.CreateUserId == user.User.Id;
|
||||
}
|
||||
|
||||
var approvers = _flowApproverApp.GetApproverIds(new QueryApproverReq
|
||||
{
|
||||
FlowInstanceId = id,
|
||||
ActivityId = flowinstance.ActivityId
|
||||
});
|
||||
|
||||
if (flowinstance.MakerList != "1" && !flowinstance.MakerList.Contains(user.User.Id) &&
|
||||
!approvers.Contains(user.User.Id))
|
||||
{
|
||||
resp.CanVerify = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
resp.CanVerify = true; //当前登录用户可以审批当前流程
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
@@ -609,6 +676,12 @@ namespace OpenAuth.App
|
||||
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 || '%') ";
|
||||
}
|
||||
|
||||
string sql = String.Empty;
|
||||
|
||||
@@ -697,17 +770,17 @@ namespace OpenAuth.App
|
||||
select distinct FirstId as InstanceId
|
||||
from Relevance rel
|
||||
inner join FlowInstance flow on rel.FirstId = flow.Id and flow.IsFinish = 1
|
||||
where `Key` = '{Define.INSTANCE_NOTICE_USER}'
|
||||
where `key` = '{Define.INSTANCE_NOTICE_USER}'
|
||||
and SecondId = '{user.User.Id}'
|
||||
union
|
||||
select distinct a.FirstId as InstanceId
|
||||
from Relevance a
|
||||
inner join (select SecondId as RoleId
|
||||
from Relevance
|
||||
where `Key` = 'UserRole'
|
||||
where `key` = '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.`Key` = '{Define.INSTANCE_NOTICE_ROLE}') UniqueInstanceIds
|
||||
where a.`key` = '{Define.INSTANCE_NOTICE_ROLE}') UniqueInstanceIds
|
||||
ON fi.Id = UniqueInstanceIds.InstanceId
|
||||
";
|
||||
}
|
||||
@@ -715,11 +788,14 @@ namespace OpenAuth.App
|
||||
switch (SugarClient.CurrentConnectionConfig.DbType)
|
||||
{
|
||||
case DbType.SqlServer:
|
||||
sql = sql.Replace("`Key`", "[Key]");
|
||||
sql = sql.Replace("`key`", "[Key]");
|
||||
sql = sql.Replace("from dual", "");
|
||||
break;
|
||||
case DbType.Oracle:
|
||||
sql = sql.Replace("`Key`", "\"KEY\"");
|
||||
sql = sql.Replace("`key`", "\"KEY\"");
|
||||
break;
|
||||
case DbType.PostgreSQL:
|
||||
sql = sql.Replace("`key`", "key");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
17
OpenAuth.App/FlowInstance/Request/UndoVerificationReq.cs
Normal file
17
OpenAuth.App/FlowInstance/Request/UndoVerificationReq.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
public class UndoVerificationReq
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程实例ID
|
||||
/// </summary>
|
||||
public string FlowInstanceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销的节点ID
|
||||
/// </summary>
|
||||
public string NodeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销说明
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
}
|
||||
@@ -37,5 +37,17 @@ namespace OpenAuth.App.Response
|
||||
/// 当前节点的可写表单Id
|
||||
/// </summary>
|
||||
public string[] CanWriteFormItemIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以撤销审核
|
||||
///<param>流程最后一个已审批节点的审批人是当前登录人</param>
|
||||
/// </summary>
|
||||
public bool CanUndoVerify { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以审核
|
||||
///<param>待审批的节点需要当前登录人审批</param>
|
||||
/// </summary>
|
||||
public bool CanVerify{ get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<PackageReference Include="Autofac" Version="8.1.1" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageReference Include="Autofac.Extras.Quartz" Version="5.1.0" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="5.0.0" />
|
||||
@@ -26,6 +27,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.6.23" />
|
||||
<PackageReference Include="Moq" Version="4.13.1" />
|
||||
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
|
||||
17
OpenAuth.App/Relevance/Request/AssignRoleResources.cs
Normal file
17
OpenAuth.App/Relevance/Request/AssignRoleResources.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace OpenAuth.App.Request
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色分配资源
|
||||
/// </summary>
|
||||
public class AssignRoleResources
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色id
|
||||
/// </summary>
|
||||
public string RoleId { get; set; }
|
||||
/// <summary>
|
||||
/// 资源id列表
|
||||
/// </summary>
|
||||
public string[] ResourceIds { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -234,5 +234,28 @@ namespace OpenAuth.App
|
||||
UnitWork.Save();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为角色分配资源,需要统一提交,会删除以前该角色的所有资源
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
public void AssignRoleResources(AssignRoleResources request)
|
||||
{
|
||||
UnitWork.ExecuteWithTransaction(() =>
|
||||
{
|
||||
//删除以前的所有资源
|
||||
UnitWork.Delete<Relevance>(u => u.FirstId == request.RoleId && u.Key == Define.ROLERESOURCE);
|
||||
//批量分配角色资源
|
||||
UnitWork.BatchAdd((from firstId in request.ResourceIds
|
||||
select new Relevance
|
||||
{
|
||||
Key = Define.ROLERESOURCE,
|
||||
FirstId = request.RoleId,
|
||||
SecondId = firstId,
|
||||
OperateTime = DateTime.Now
|
||||
}).ToArray());
|
||||
UnitWork.Save();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure;
|
||||
using NUnit.Framework;
|
||||
using OpenAuth.App.Interface;
|
||||
using OpenAuth.App.Request;
|
||||
using OpenAuth.App.Response;
|
||||
@@ -17,6 +19,16 @@ namespace OpenAuth.App
|
||||
public class ResourceApp:SqlSugarBaseApp<SysResource>
|
||||
{
|
||||
private RevelanceManagerApp _revelanceApp;
|
||||
private ApiService _apiService;
|
||||
|
||||
private readonly IAuth _auth;
|
||||
|
||||
public ResourceApp(ISqlSugarClient client, IAuth auth, RevelanceManagerApp revelanceApp, ApiService apiService) : base(client, auth)
|
||||
{
|
||||
_revelanceApp = revelanceApp;
|
||||
_apiService = apiService;
|
||||
_auth = auth;
|
||||
}
|
||||
|
||||
public void Add(AddOrUpdateResReq resource)
|
||||
{
|
||||
@@ -85,10 +97,7 @@ namespace OpenAuth.App
|
||||
}
|
||||
|
||||
var columnnames = columnFields.Select(u => u.ColumnName);
|
||||
if (SugarClient.CurrentConnectionConfig.DbType == DbType.PostgreSQL)
|
||||
{
|
||||
columnnames = columnFields.Select(u => "\"" + u.ColumnName +"\"");
|
||||
}
|
||||
|
||||
var propertyStr = string.Join(',', columnnames);
|
||||
result.columnFields = columnFields;
|
||||
result.data = resources.OrderBy(u => u.TypeId)
|
||||
@@ -98,10 +107,92 @@ namespace OpenAuth.App
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourceApp(ISqlSugarClient client, IAuth auth, RevelanceManagerApp revelanceApp) : base(client, auth)
|
||||
/// <summary>
|
||||
/// 获取资源类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<SysResourceApp>> GetResourceApps()
|
||||
{
|
||||
_revelanceApp = revelanceApp;
|
||||
var types = await SugarClient.Queryable<SysResource>()
|
||||
.Distinct()
|
||||
.Select(u => new {u.AppId,u.AppName})
|
||||
.ToListAsync();
|
||||
return types.Select(u => new SysResourceApp(u.AppId, u.AppName)).ToList();
|
||||
}
|
||||
/// <summary>
|
||||
/// 同步站点API到资源列表
|
||||
/// <para>读取站点API信息,如果资源列表中不存在,则添加</para>
|
||||
/// </summary>
|
||||
public async Task Sync()
|
||||
{
|
||||
var apis = await _apiService.GetSwaggerEndpoints();
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
foreach (var api in apis)
|
||||
{
|
||||
//检查资源是否存在
|
||||
var resource = Repository.GetFirst(u => u.Name == api.Path && u.TypeId == Define.API);
|
||||
if (resource != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
resource = new SysResource
|
||||
{
|
||||
Id = api.Path,
|
||||
Name = api.Path,
|
||||
Disable = false,
|
||||
SortNo = 0,
|
||||
AppId = $"{Define.API}_{api.Tag}",
|
||||
AppName = $"API接口-{api.Tag}",
|
||||
TypeId = Define.API,
|
||||
TypeName = "API接口",
|
||||
Description = api.Summary??"",
|
||||
CreateTime = DateTime.Now,
|
||||
CreateUserId = user.Id,
|
||||
CreateUserName = user.Name
|
||||
};
|
||||
CaculateCascade(resource);
|
||||
Repository.Insert(resource);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断当前登录用户是否拥有访问该API的权限
|
||||
/// <para>如果角色没有做任何分配,则默认拥有权限。这个可以根据实际需要修改。</para>
|
||||
/// </summary>
|
||||
/// <param name="apiPath">API路径</param>
|
||||
/// <returns>true:拥有权限,false:没有权限</returns>
|
||||
public bool CanAccess(string apiPath)
|
||||
{
|
||||
var loginContext = _auth.GetCurrentUser();
|
||||
if (loginContext == null)
|
||||
{
|
||||
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
//如果当前登录用户是管理员,则拥有所有权限
|
||||
if(loginContext.User.Account == Define.SYSTEM_USERNAME){
|
||||
return true;
|
||||
}
|
||||
|
||||
var elementIds = _revelanceApp.Get(Define.ROLERESOURCE, true, loginContext.Roles.Select(u => u.Id).ToArray());
|
||||
//如果角色没有做任何分配,则默认拥有权限。这个可以根据实际需要修改。
|
||||
if(elementIds.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//如果分配了资源,则判断是否拥有权限
|
||||
var resource = Repository.GetFirst(u => u.Name.Contains(apiPath) && u.TypeId == Define.API && elementIds.Contains(u.Id));
|
||||
if(resource == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源类型
|
||||
/// </summary>
|
||||
public record SysResourceApp(string Id, string Name);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure;
|
||||
using OpenAuth.App.Interface;
|
||||
@@ -41,10 +40,7 @@ namespace OpenAuth.App
|
||||
}
|
||||
|
||||
var columnnames = columnFields.Select(u => u.ColumnName);
|
||||
if (SugarClient.CurrentConnectionConfig.DbType == DbType.PostgreSQL)
|
||||
{
|
||||
columnnames = columnFields.Select(u => "\"" + u.ColumnName +"\"");
|
||||
}
|
||||
|
||||
var propertyStr = string.Join(',', columnnames);
|
||||
result.columnFields = columnFields;
|
||||
result.data = objs.OrderByDescending(u => u.CreateTime)
|
||||
|
||||
99
OpenAuth.App/System/ApiService.cs
Normal file
99
OpenAuth.App/System/ApiService.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.OpenApi.Readers;
|
||||
|
||||
public class ApiService
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ApiService(IHttpClientFactory httpClientFactory, IConfiguration configuration)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有API接口信息
|
||||
/// <para>这个方法单元测试必须启动WebApi站点</para>
|
||||
/// </summary>
|
||||
public async Task<List<SwaggerEndpointInfo>> GetSwaggerEndpoints()
|
||||
{
|
||||
|
||||
var reader = new OpenApiStringReader();
|
||||
var client = _httpClientFactory.CreateClient();
|
||||
|
||||
var baseUrl = _configuration["AppSetting:HttpHost"]?.Replace("*", "localhost");
|
||||
|
||||
var apis = new List<SwaggerEndpointInfo>();
|
||||
var controllers = GetControllers();
|
||||
|
||||
foreach (var controller in controllers)
|
||||
{
|
||||
var groupname = GetSwaggerGroupName(controller);
|
||||
var swaggerJsonUrl = $"{baseUrl}/swagger/{groupname}/swagger.json";
|
||||
|
||||
var response = await client.GetAsync(swaggerJsonUrl).ConfigureAwait(false);
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var document = reader.Read(content, out var diagnostic);
|
||||
//获取所有api
|
||||
var controllerApis = document.Paths
|
||||
.SelectMany(path => path.Value.Operations
|
||||
.Select(op => new SwaggerEndpointInfo(
|
||||
path.Key,
|
||||
op.Key.ToString(),
|
||||
op.Value.Summary,
|
||||
op.Value.Description,
|
||||
op.Value.Tags.FirstOrDefault()?.Name)));
|
||||
|
||||
apis.AddRange(controllerApis);
|
||||
}
|
||||
|
||||
return apis;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取控制器对应的swagger分组值
|
||||
/// </summary>
|
||||
private string GetSwaggerGroupName(Type controller)
|
||||
{
|
||||
var groupname = controller.Name.Replace("Controller", "");
|
||||
var apisetting = controller.GetCustomAttribute(typeof(ApiExplorerSettingsAttribute));
|
||||
if (apisetting != null)
|
||||
{
|
||||
groupname = ((ApiExplorerSettingsAttribute)apisetting).GroupName;
|
||||
}
|
||||
|
||||
return groupname;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有的控制器
|
||||
/// </summary>
|
||||
private List<Type> GetControllers()
|
||||
{
|
||||
var webApiAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.FirstOrDefault(a => a.GetName().Name.Contains("OpenAuth.WebApi"));
|
||||
|
||||
var controlleractionlist = webApiAssembly.GetTypes()
|
||||
.Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type))
|
||||
.ToList();
|
||||
|
||||
return controlleractionlist;
|
||||
}
|
||||
}
|
||||
|
||||
public record SwaggerEndpointInfo(
|
||||
string Path,
|
||||
string HttpMethod,
|
||||
string Summary,
|
||||
string Description,
|
||||
string Tag);
|
||||
@@ -77,13 +77,27 @@ namespace OpenAuth.App.Test
|
||||
{
|
||||
DbType = dbType.Value,
|
||||
ConnectionString = connectionString,
|
||||
IsAutoCloseConnection = true,
|
||||
MoreSettings=new ConnMoreSettings() {
|
||||
PgSqlIsAutoToLower = false,//增删查改支持驼峰表
|
||||
PgSqlIsAutoToLowerCodeFirst = false, // 建表建驼峰表。5.1.3.30
|
||||
IsAutoToUpper=false //禁用自动转成大写表
|
||||
}
|
||||
IsAutoCloseConnection = true
|
||||
});
|
||||
|
||||
if(dbType.Value != SqlSugar.DbType.PostgreSQL){
|
||||
return sqlSugar;
|
||||
}
|
||||
// 配置bool类型转换为smallint
|
||||
sqlSugar.Aop.OnExecutingChangeSql = (sql, parameters) =>
|
||||
{
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (param.Value is bool boolValue)
|
||||
{
|
||||
param.DbType = System.Data.DbType.Int16;
|
||||
// 将 bool 转换为 smallint
|
||||
param.Value = boolValue ? (short)1 : (short)0;
|
||||
}
|
||||
}
|
||||
// 返回修改后的 SQL 和参数
|
||||
return new System.Collections.Generic.KeyValuePair<string, SugarParameter[]>(sql, parameters);
|
||||
};
|
||||
return sqlSugar;
|
||||
});
|
||||
|
||||
|
||||
@@ -19,15 +19,6 @@ namespace OpenAuth.App.Test
|
||||
var result = app.GetTableColumnsFromDb("Category");
|
||||
Console.WriteLine(JsonHelper.Instance.Serialize(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetDbEntityNames()
|
||||
{
|
||||
var app = _autofacServiceProvider.GetService<DbExtension>();
|
||||
|
||||
var result = app.GetDbEntityNames();
|
||||
Console.WriteLine(JsonHelper.Instance.Serialize(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetTables()
|
||||
|
||||
@@ -324,29 +324,31 @@ namespace OpenAuth.App
|
||||
{
|
||||
var sql = $@"
|
||||
select u.*
|
||||
from `USER` u
|
||||
from sysuser u
|
||||
join (select distinct SecondId as UserId
|
||||
from Relevance
|
||||
where `Key` = '{Define.INSTANCE_NOTICE_USER}'
|
||||
where `key` = '{Define.INSTANCE_NOTICE_USER}'
|
||||
and FirstId = '{instanceId}'
|
||||
union
|
||||
select distinct FirstId as UserId
|
||||
from Relevance a
|
||||
inner join (select SecondId as RoleId
|
||||
from Relevance
|
||||
where `Key` = '{Define.INSTANCE_NOTICE_ROLE}'
|
||||
where `key` = '{Define.INSTANCE_NOTICE_ROLE}'
|
||||
and FirstId = '{instanceId}') b on a.SecondId = b.RoleId
|
||||
where `Key` = 'UserRole') userids on u.Id = userids.UserId";
|
||||
where `key` = 'UserRole') userids on u.Id = userids.UserId";
|
||||
|
||||
if (UnitWork.GetDbContext().Database.GetDbConnection().GetType().Name == "SqlConnection")
|
||||
{
|
||||
sql = sql.Replace(" `USER` ", " [USER] ");
|
||||
sql = sql.Replace("`Key`", "[Key]");
|
||||
sql = sql.Replace("`key`", "[Key]");
|
||||
}
|
||||
else if (UnitWork.GetDbContext().Database.GetDbConnection().GetType().Name == "OracleConnection")
|
||||
{
|
||||
sql = sql.Replace(" `USER` ", " \"USER\" ");
|
||||
sql = sql.Replace("`Key`", "\"Key\"");
|
||||
sql = sql.Replace("`key`", "\"KEY\"");
|
||||
}
|
||||
else if (UnitWork.GetDbContext().Database.GetDbConnection().GetType().Name == "NpgsqlConnection")
|
||||
{
|
||||
sql = sql.Replace("`key`", "\"key\"");
|
||||
}
|
||||
|
||||
var users = UnitWork.FromSql<SysUser>(sql);
|
||||
|
||||
@@ -104,13 +104,27 @@ namespace OpenAuth.IdentityServer
|
||||
{
|
||||
DbType = sugarDbtype.Value,
|
||||
ConnectionString = connectionString,
|
||||
IsAutoCloseConnection = true,
|
||||
MoreSettings=new ConnMoreSettings() {
|
||||
PgSqlIsAutoToLower = false,//增删查改支持驼峰表
|
||||
PgSqlIsAutoToLowerCodeFirst = false, // 建表建驼峰表。5.1.3.30
|
||||
IsAutoToUpper=false //禁用自动转成大写表
|
||||
}
|
||||
IsAutoCloseConnection = true
|
||||
});
|
||||
|
||||
if(sugarDbtype.Value != SqlSugar.DbType.PostgreSQL){
|
||||
return sqlSugar;
|
||||
}
|
||||
// 配置bool类型转换为smallint
|
||||
sqlSugar.Aop.OnExecutingChangeSql = (sql, parameters) =>
|
||||
{
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (param.Value is bool boolValue)
|
||||
{
|
||||
param.DbType = System.Data.DbType.Int16;
|
||||
// 将 bool 转换为 smallint
|
||||
param.Value = boolValue ? (short)1 : (short)0;
|
||||
}
|
||||
}
|
||||
// 返回修改后的 SQL 和参数
|
||||
return new System.Collections.Generic.KeyValuePair<string, SugarParameter[]>(sql, parameters);
|
||||
};
|
||||
return sqlSugar;
|
||||
});
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@ namespace OpenAuth.Mvc.Controllers
|
||||
return View();
|
||||
}
|
||||
|
||||
public async Task<string> All([FromQuery]QueryCategoryListReq request)
|
||||
public async Task<string> All([FromQuery] QueryCategoryListReq request)
|
||||
{
|
||||
TableData data = new TableData();
|
||||
data = await _app.Load(request);
|
||||
return JsonHelper.Instance.Serialize(data);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[HttpPost]
|
||||
public string Delete(string[] ids)
|
||||
{
|
||||
Response resp = new Response();
|
||||
@@ -50,13 +50,13 @@ namespace OpenAuth.Mvc.Controllers
|
||||
return JsonHelper.Instance.Serialize(resp);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public string Add(AddOrUpdateCategoryReq obj)
|
||||
[HttpPost]
|
||||
public async Task<string> Add(AddOrUpdateCategoryReq obj)
|
||||
{
|
||||
Response resp = new Response();
|
||||
try
|
||||
{
|
||||
_app.Add(obj);
|
||||
await _app.Add(obj);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -66,7 +66,7 @@ namespace OpenAuth.Mvc.Controllers
|
||||
return JsonHelper.Instance.Serialize(resp);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[HttpPost]
|
||||
public string Update(AddOrUpdateCategoryReq obj)
|
||||
{
|
||||
Response resp = new Response();
|
||||
@@ -99,7 +99,7 @@ namespace OpenAuth.Mvc.Controllers
|
||||
resp.Message = e.Message;
|
||||
}
|
||||
return JsonHelper.Instance.Serialize(resp);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -109,12 +109,28 @@ namespace OpenAuth.Mvc
|
||||
{
|
||||
DbType = dbType.Value,
|
||||
ConnectionString = connectionString,
|
||||
IsAutoCloseConnection = true,
|
||||
MoreSettings=new ConnMoreSettings() {
|
||||
PgSqlIsAutoToLower = false,//增删查改支持驼峰表
|
||||
PgSqlIsAutoToLowerCodeFirst = false // 建表建驼峰表。5.1.3.30
|
||||
}
|
||||
IsAutoCloseConnection = true
|
||||
}, db => { db.Aop.OnLogExecuting = (sql, pars) => { logger.LogInformation(sql); }; });
|
||||
|
||||
if(dbType.Value != SqlSugar.DbType.PostgreSQL){
|
||||
return sqlSugar;
|
||||
}
|
||||
|
||||
// 配置bool类型转换为smallint
|
||||
sqlSugar.Aop.OnExecutingChangeSql = (sql, parameters) =>
|
||||
{
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (param.Value is bool boolValue)
|
||||
{
|
||||
param.DbType = System.Data.DbType.Int16;
|
||||
// 将 bool 转换为 smallint
|
||||
param.Value = boolValue ? (short)1 : (short)0;
|
||||
}
|
||||
}
|
||||
// 返回修改后的 SQL 和参数
|
||||
return new System.Collections.Generic.KeyValuePair<string, SugarParameter[]>(sql, parameters);
|
||||
};
|
||||
return sqlSugar;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
@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 rel="stylesheet" href="/css/treetable.css" />
|
||||
<link rel="stylesheet" href="/js/dtree/dtree.css" />
|
||||
<link rel="stylesheet" href="/js/dtree/font/dtreefont.css" />
|
||||
}
|
||||
|
||||
<blockquote class="layui-elem-quote news_search toolList" id="menus">
|
||||
</blockquote>
|
||||
|
||||
<table id="mainList"
|
||||
lay-data="{height: 'full-80',cellMinWidth:80, page:true, id:'mainList'}"
|
||||
lay-filter="list" lay-size="sm">
|
||||
<table id="mainList" lay-data="{height: 'full-80',cellMinWidth:80, page:true, id:'mainList'}" lay-filter="list"
|
||||
lay-size="sm">
|
||||
</table>
|
||||
|
||||
<script type="text/html" id="barList">
|
||||
@@ -22,27 +21,33 @@
|
||||
<!--用户添加/编辑窗口-->
|
||||
<div id="divEdit" style="display: none">
|
||||
<form class="layui-form layui-form-pane" action="" id="formEdit" lay-filter="formEdit">
|
||||
<input type="hidden" name="Id" />
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型标识</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="Id"
|
||||
placeholder="请输入类型标识" autocomplete="off" class="layui-input">
|
||||
<input type="text" name="DtCode" placeholder="请输入类型标识" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="Name" required lay-verify="required"
|
||||
placeholder="请输入名称" autocomplete="off" class="layui-input">
|
||||
<input type="text" name="Name" required lay-verify="required" placeholder="请输入名称" autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">值</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="DtValue" placeholder="请输入值" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型分类</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="TypeName" name="TypeName" required lay-verify="required" class="layui-input"/>
|
||||
<input id="TypeId" name="TypeId" required lay-verify="required" type="hidden"/>
|
||||
<input id="TypeName" name="TypeName" required lay-verify="required" class="layui-input" />
|
||||
<input id="TypeId" name="TypeId" required lay-verify="required" type="hidden" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,8 +55,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">描述</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="Description"
|
||||
placeholder="请输入描述" autocomplete="off" class="layui-input">
|
||||
<input type="text" name="Description" placeholder="请输入描述" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ tpwidget("init", {
|
||||
</div>
|
||||
<!-- 底部 -->
|
||||
<div class="layui-footer footer">
|
||||
<p>copyright @@2024 yubaolee <a onclick="donation()" class="layui-btn layui-btn-danger l·ayui-btn-small">捐赠作者</a></p>
|
||||
<p>copyright @@2025 yubaolee <a onclick="donation()" class="layui-btn layui-btn-danger l·ayui-btn-small">捐赠作者</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="panel col">
|
||||
<a href="javascript:;" data-url="/Rolemanager/index">
|
||||
<div class="panel_icon" style="background-color:#FF5722;">
|
||||
<i class="layui-icon layui-icon-vercode" ></i>
|
||||
<i class="layui-icon layui-icon-vercode" ></i>
|
||||
</div>
|
||||
<div class="panel_word roles">
|
||||
<span></span>
|
||||
@@ -75,14 +75,14 @@
|
||||
<p>官方博客:<a href="http://www.cnblogs.com/yubaolee/">http://www.cnblogs.com/yubaolee/</a> </p>
|
||||
<p>
|
||||
系统默认System账号登录,可以查看所有权限,如果用其他账号(如:admin/test)可以查看相应的授权/可见字段情况。
|
||||
数据库密码明文存储,不要问为什么不加密,因为你要问这些账号的密码我也记不住啊O(∩_∩)O
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://gitee.com/dotnetchina/OpenAuth.Net" target="_blank" class="layui-btn layui-btn-xs layui-btn-danger">项目地址</a>
|
||||
<a class="layui-btn layui-btn-xs" target="_blank" href="http://doc.openauth.net.cn">在线文档</a>
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" target="_blank" href="http://demo.openauth.net.cn:1803">企业版/高级版入口</a>
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" target="_blank" href="http://demo.openauth.net.cn:1803">企业Vue2演示</a>
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" target="_blank" href="http://demo.openauth.net.cn:1805">企业Vue3演示</a>
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" target="_blank" href="http://demo.openauth.net.cn:1804">企业版H5入口(请使用移动模式或者直接手机查看)</a>
|
||||
<span style="color: #f00;">注:【本框架遵循LGPL开源协议,企业单位如商用请联系作者授权,谢谢】</span>
|
||||
<span style="color: #f00;">注:【本框架遵循Apache开源协议,可以免费商用】</span>
|
||||
</p>
|
||||
<p>技术交流QQ群:484498493【已满】 626433139【已满】 566344079</p>
|
||||
</blockquote>
|
||||
|
||||
@@ -198,4 +198,4 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/layui/layui.js"></script>
|
||||
<script type="text/javascript" src="/userJs/modules.js?v2"></script>
|
||||
<script type="text/javascript" src="/userJs/modules.js?v2.1"></script>
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
.layui-body{overflow:hidden; border-top:5px solid #1AA094;border-left:2px solid #1AA094;}
|
||||
.layui-tab-content{ height:100%; padding:0; }
|
||||
.layui-tab-item{ position: absolute; top: 41px; bottom:0; left: 0; right: 0; padding: 0; margin: 0; -webkit-overflow-scrolling:touch; overflow:auto;}
|
||||
.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-title .layui-this:after{ border:none; }
|
||||
.layui-tab-title li cite{ font-style: normal; padding-left:5px; }
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
var $,tab,skyconsWeather;
|
||||
var $, tab, skyconsWeather;
|
||||
layui.config({
|
||||
base : "/js/"
|
||||
}).use(['bodyTab','form','element','layer','jquery','cookie'],function(){
|
||||
base: "/js/"
|
||||
}).use(['bodyTab', 'form', 'element', 'layer', 'jquery', 'cookie'], function () {
|
||||
var form = layui.form,
|
||||
layer = layui.layer,
|
||||
element = layui.element;
|
||||
$ = layui.jquery;
|
||||
tab = layui.bodyTab({
|
||||
openTabNum : "50", //最大可打开窗口数量
|
||||
url: "/UserSession/GetModulesTree" //获取菜单json地址
|
||||
});
|
||||
$ = layui.jquery;
|
||||
tab = layui.bodyTab({
|
||||
openTabNum: "50", //最大可打开窗口数量
|
||||
url: "/UserSession/GetModulesTree" //获取菜单json地址
|
||||
});
|
||||
|
||||
$(".menu_three").on("click", function () {
|
||||
|
||||
@@ -27,131 +27,131 @@ layui.config({
|
||||
$(this).addClass('three_this'); // 添加当前元素的样式
|
||||
})
|
||||
|
||||
$.get('/UserSession/GetUserName',
|
||||
function(data) {
|
||||
$("#username").html(data);
|
||||
$("#usernametop").html(data);
|
||||
});
|
||||
$.get('/UserSession/GetUserName',
|
||||
function (data) {
|
||||
$("#username").html(data);
|
||||
$("#usernametop").html(data);
|
||||
});
|
||||
|
||||
//todo:默认登录后取第一个机构的id作为默认,可以在【个人中心】界面修改默认
|
||||
//todo:默认登录后取第一个机构的id作为默认,可以在【个人中心】界面修改默认
|
||||
//在大型业务系统中,应该让用户登录成功后弹出选择框选择操作的机构
|
||||
$.get('/UserSession/GetOrgs',
|
||||
function(data) {
|
||||
var orgs = JSON.parse(data).Result;
|
||||
function (data) {
|
||||
var orgs = JSON.parse(data).Result;
|
||||
var defaultorgId = orgs[0].Id;
|
||||
$.cookie('defaultorgid', defaultorgId,{path: '/'});
|
||||
$.cookie('defaultorgid', defaultorgId, { path: '/' });
|
||||
});
|
||||
|
||||
|
||||
//更换皮肤
|
||||
function skins(){
|
||||
function skins() {
|
||||
var skin = window.sessionStorage.getItem("skin");
|
||||
if (skin) { //如果更换过皮肤
|
||||
if (window.sessionStorage.getItem("skinValue") != "自定义") {
|
||||
$("body").addClass(window.sessionStorage.getItem("skin"));
|
||||
} else {
|
||||
$(".layui-layout-admin .layui-header").css("background-color", skin.split(',')[0]);
|
||||
$(".layui-bg-black").css("background-color", skin.split(',')[1]);
|
||||
$(".hideMenu").css("background-color", skin.split(',')[2]);
|
||||
}
|
||||
if (window.sessionStorage.getItem("skinValue") != "自定义") {
|
||||
$("body").addClass(window.sessionStorage.getItem("skin"));
|
||||
} else {
|
||||
$(".layui-layout-admin .layui-header").css("background-color", skin.split(',')[0]);
|
||||
$(".layui-bg-black").css("background-color", skin.split(',')[1]);
|
||||
$(".hideMenu").css("background-color", skin.split(',')[2]);
|
||||
}
|
||||
} else {
|
||||
$("body").addClass("blue");
|
||||
$("body").addClass("blue");
|
||||
}
|
||||
}
|
||||
skins();
|
||||
$(".changeSkin").click(function(){
|
||||
$(".changeSkin").click(function () {
|
||||
layer.open({
|
||||
title : "更换皮肤",
|
||||
area : ["310px","280px"],
|
||||
type : "1",
|
||||
content : '<div class="skins_box">'+
|
||||
'<form class="layui-form">'+
|
||||
'<div class="layui-form-item">'+
|
||||
'<input type="radio" name="skin" value="默认" title="默认" lay-filter="default" checked="">'+
|
||||
'<input type="radio" name="skin" value="藏青" title="藏青" lay-filter="cyan">'+
|
||||
'<input type="radio" name="skin" value="蓝色" title="蓝色" lay-filter="blue">'+
|
||||
'<input type="radio" name="skin" value="自定义" title="自定义" lay-filter="custom">'+
|
||||
'<div class="skinCustom">'+
|
||||
'<input type="text" class="layui-input topColor" name="topSkin" placeholder="顶部颜色" />'+
|
||||
'<input type="text" class="layui-input leftColor" name="leftSkin" placeholder="左侧颜色" />'+
|
||||
'<input type="text" class="layui-input menuColor" name="btnSkin" placeholder="顶部菜单按钮" />'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'<div class="layui-form-item skinBtn">'+
|
||||
'<a href="javascript:;" class="layui-btn layui-btn-small layui-btn-normal" lay-submit="" lay-filter="changeSkin">确定更换</a>'+
|
||||
'<a href="javascript:;" class="layui-btn layui-btn-small layui-btn-primary" lay-submit="" lay-filter="noChangeSkin">我再想想</a>'+
|
||||
'</div>'+
|
||||
'</form>'+
|
||||
'</div>',
|
||||
success : function(index, layero){
|
||||
title: "更换皮肤",
|
||||
area: ["310px", "280px"],
|
||||
type: "1",
|
||||
content: '<div class="skins_box">' +
|
||||
'<form class="layui-form">' +
|
||||
'<div class="layui-form-item">' +
|
||||
'<input type="radio" name="skin" value="默认" title="默认" lay-filter="default" checked="">' +
|
||||
'<input type="radio" name="skin" value="藏青" title="藏青" lay-filter="cyan">' +
|
||||
'<input type="radio" name="skin" value="蓝色" title="蓝色" lay-filter="blue">' +
|
||||
'<input type="radio" name="skin" value="自定义" title="自定义" lay-filter="custom">' +
|
||||
'<div class="skinCustom">' +
|
||||
'<input type="text" class="layui-input topColor" name="topSkin" placeholder="顶部颜色" />' +
|
||||
'<input type="text" class="layui-input leftColor" name="leftSkin" placeholder="左侧颜色" />' +
|
||||
'<input type="text" class="layui-input menuColor" name="btnSkin" placeholder="顶部菜单按钮" />' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="layui-form-item skinBtn">' +
|
||||
'<a href="javascript:;" class="layui-btn layui-btn-small layui-btn-normal" lay-submit="" lay-filter="changeSkin">确定更换</a>' +
|
||||
'<a href="javascript:;" class="layui-btn layui-btn-small layui-btn-primary" lay-submit="" lay-filter="noChangeSkin">我再想想</a>' +
|
||||
'</div>' +
|
||||
'</form>' +
|
||||
'</div>',
|
||||
success: function (index, layero) {
|
||||
var skin = window.sessionStorage.getItem("skin");
|
||||
if(window.sessionStorage.getItem("skinValue")){
|
||||
$(".skins_box input[value="+window.sessionStorage.getItem("skinValue")+"]").attr("checked","checked");
|
||||
if (window.sessionStorage.getItem("skinValue")) {
|
||||
$(".skins_box input[value=" + window.sessionStorage.getItem("skinValue") + "]").attr("checked", "checked");
|
||||
};
|
||||
if($(".skins_box input[value=自定义]").attr("checked")){
|
||||
$(".skinCustom").css("visibility","inherit");
|
||||
if ($(".skins_box input[value=自定义]").attr("checked")) {
|
||||
$(".skinCustom").css("visibility", "inherit");
|
||||
$(".topColor").val(skin.split(',')[0]);
|
||||
$(".leftColor").val(skin.split(',')[1]);
|
||||
$(".menuColor").val(skin.split(',')[2]);
|
||||
};
|
||||
form.render();
|
||||
$(".skins_box").removeClass("layui-hide");
|
||||
$(".skins_box .layui-form-radio").on("click",function(){
|
||||
$(".skins_box .layui-form-radio").on("click", function () {
|
||||
var skinColor;
|
||||
if($(this).find("span").text() == "藏青"){
|
||||
if ($(this).find("span").text() == "藏青") {
|
||||
skinColor = "cyan";
|
||||
}else if($(this).find("span").text() == "蓝色"){
|
||||
} else if ($(this).find("span").text() == "蓝色") {
|
||||
skinColor = "blue";
|
||||
}else if($(this).find("span").text() == "默认"){
|
||||
} else if ($(this).find("span").text() == "默认") {
|
||||
skinColor = "";
|
||||
}
|
||||
if($(this).find("span").text() != "自定义"){
|
||||
if ($(this).find("span").text() != "自定义") {
|
||||
$(".topColor,.leftColor,.menuColor").val('');
|
||||
$("body").removeAttr("class").addClass("main_body "+skinColor+"");
|
||||
$("body").removeAttr("class").addClass("main_body " + skinColor + "");
|
||||
$(".skinCustom").removeAttr("style");
|
||||
$(".layui-bg-black,.hideMenu,.layui-layout-admin .layui-header").removeAttr("style");
|
||||
}else{
|
||||
$(".skinCustom").css("visibility","inherit");
|
||||
} else {
|
||||
$(".skinCustom").css("visibility", "inherit");
|
||||
}
|
||||
})
|
||||
var skinStr,skinColor;
|
||||
$(".topColor").blur(function(){
|
||||
$(".layui-layout-admin .layui-header").css("background-color",$(this).val());
|
||||
var skinStr, skinColor;
|
||||
$(".topColor").blur(function () {
|
||||
$(".layui-layout-admin .layui-header").css("background-color", $(this).val());
|
||||
})
|
||||
$(".leftColor").blur(function(){
|
||||
$(".layui-bg-black").css("background-color",$(this).val());
|
||||
$(".leftColor").blur(function () {
|
||||
$(".layui-bg-black").css("background-color", $(this).val());
|
||||
})
|
||||
$(".menuColor").blur(function(){
|
||||
$(".hideMenu").css("background-color",$(this).val());
|
||||
$(".menuColor").blur(function () {
|
||||
$(".hideMenu").css("background-color", $(this).val());
|
||||
})
|
||||
|
||||
form.on("submit(changeSkin)",function(data){
|
||||
if(data.field.skin != "自定义"){
|
||||
if(data.field.skin == "藏青"){
|
||||
form.on("submit(changeSkin)", function (data) {
|
||||
if (data.field.skin != "自定义") {
|
||||
if (data.field.skin == "藏青") {
|
||||
skinColor = "cyan";
|
||||
}else if(data.field.skin == "蓝色"){
|
||||
} else if (data.field.skin == "蓝色") {
|
||||
skinColor = "blue";
|
||||
}else if(data.field.skin == "默认"){
|
||||
} else if (data.field.skin == "默认") {
|
||||
skinColor = "";
|
||||
}
|
||||
window.sessionStorage.setItem("skin",skinColor);
|
||||
}else{
|
||||
skinStr = $(".topColor").val()+','+$(".leftColor").val()+','+$(".menuColor").val();
|
||||
window.sessionStorage.setItem("skin",skinStr);
|
||||
window.sessionStorage.setItem("skin", skinColor);
|
||||
} else {
|
||||
skinStr = $(".topColor").val() + ',' + $(".leftColor").val() + ',' + $(".menuColor").val();
|
||||
window.sessionStorage.setItem("skin", skinStr);
|
||||
$("body").removeAttr("class").addClass("main_body");
|
||||
}
|
||||
window.sessionStorage.setItem("skinValue",data.field.skin);
|
||||
window.sessionStorage.setItem("skinValue", data.field.skin);
|
||||
layer.closeAll("page");
|
||||
});
|
||||
form.on("submit(noChangeSkin)",function(){
|
||||
$("body").removeAttr("class").addClass("main_body "+window.sessionStorage.getItem("skin")+"");
|
||||
form.on("submit(noChangeSkin)", function () {
|
||||
$("body").removeAttr("class").addClass("main_body " + window.sessionStorage.getItem("skin") + "");
|
||||
$(".layui-bg-black,.hideMenu,.layui-layout-admin .layui-header").removeAttr("style");
|
||||
skins();
|
||||
layer.closeAll("page");
|
||||
});
|
||||
},
|
||||
cancel : function(){
|
||||
$("body").removeAttr("class").addClass("main_body "+window.sessionStorage.getItem("skin")+"");
|
||||
cancel: function () {
|
||||
$("body").removeAttr("class").addClass("main_body " + window.sessionStorage.getItem("skin") + "");
|
||||
$(".layui-bg-black,.hideMenu,.layui-layout-admin .layui-header").removeAttr("style");
|
||||
skins();
|
||||
}
|
||||
@@ -159,14 +159,14 @@ layui.config({
|
||||
})
|
||||
|
||||
//退出
|
||||
$(".signOut").click(function(){
|
||||
$(".signOut").click(function () {
|
||||
window.sessionStorage.removeItem("menu");
|
||||
menu = [];
|
||||
window.sessionStorage.removeItem("curmenu");
|
||||
})
|
||||
|
||||
//隐藏左侧导航
|
||||
$(".hideMenu").click(function(){
|
||||
$(".hideMenu").click(function () {
|
||||
$(".layui-layout-admin").toggleClass("showMenu");
|
||||
//渲染顶部窗口
|
||||
tab.tabMove();
|
||||
@@ -176,43 +176,43 @@ layui.config({
|
||||
tab.render();
|
||||
|
||||
//锁屏
|
||||
function lockPage(){
|
||||
function lockPage() {
|
||||
layer.open({
|
||||
title : false,
|
||||
type : 1,
|
||||
content : ' <div class="admin-header-lock" id="lock-box">'+
|
||||
'<div class="admin-header-lock-img"><img src="/images/face.jpg"/></div>'+
|
||||
'<div class="admin-header-lock-name" id="lockUserName">admin</div>'+
|
||||
'<div class="input_btn">'+
|
||||
'<input type="password" class="admin-header-lock-input layui-input" autocomplete="off" placeholder="请输入密码解锁.." name="lockPwd" id="lockPwd" />'+
|
||||
'<button class="layui-btn" id="unlock">解锁</button>'+
|
||||
'</div>'+
|
||||
'<p>请输入“123456”,否则不会解锁成功哦!!!</p>'+
|
||||
'</div>',
|
||||
closeBtn : 0,
|
||||
shade : 0.9
|
||||
title: false,
|
||||
type: 1,
|
||||
content: ' <div class="admin-header-lock" id="lock-box">' +
|
||||
'<div class="admin-header-lock-img"><img src="/images/face.jpg"/></div>' +
|
||||
'<div class="admin-header-lock-name" id="lockUserName">admin</div>' +
|
||||
'<div class="input_btn">' +
|
||||
'<input type="password" class="admin-header-lock-input layui-input" autocomplete="off" placeholder="请输入密码解锁.." name="lockPwd" id="lockPwd" />' +
|
||||
'<button class="layui-btn" id="unlock">解锁</button>' +
|
||||
'</div>' +
|
||||
'<p>请输入“123456”,否则不会解锁成功哦!!!</p>' +
|
||||
'</div>',
|
||||
closeBtn: 0,
|
||||
shade: 0.9
|
||||
})
|
||||
$(".admin-header-lock-input").focus();
|
||||
}
|
||||
$(".lockcms").on("click",function(){
|
||||
window.sessionStorage.setItem("lockcms",true);
|
||||
$(".lockcms").on("click", function () {
|
||||
window.sessionStorage.setItem("lockcms", true);
|
||||
lockPage();
|
||||
})
|
||||
// 判断是否显示锁屏
|
||||
if(window.sessionStorage.getItem("lockcms") == "true"){
|
||||
if (window.sessionStorage.getItem("lockcms") == "true") {
|
||||
lockPage();
|
||||
}
|
||||
// 解锁
|
||||
$("body").on("click","#unlock",function(){
|
||||
if($(this).siblings(".admin-header-lock-input").val() == ''){
|
||||
$("body").on("click", "#unlock", function () {
|
||||
if ($(this).siblings(".admin-header-lock-input").val() == '') {
|
||||
layer.msg("请输入解锁密码!");
|
||||
$(this).siblings(".admin-header-lock-input").focus();
|
||||
}else{
|
||||
if($(this).siblings(".admin-header-lock-input").val() == "123456"){
|
||||
window.sessionStorage.setItem("lockcms",false);
|
||||
} else {
|
||||
if ($(this).siblings(".admin-header-lock-input").val() == "123456") {
|
||||
window.sessionStorage.setItem("lockcms", false);
|
||||
$(this).siblings(".admin-header-lock-input").val('');
|
||||
layer.closeAll("page");
|
||||
}else{
|
||||
} else {
|
||||
layer.msg("密码错误,请重新输入!");
|
||||
$(this).siblings(".admin-header-lock-input").val('').focus();
|
||||
}
|
||||
@@ -223,18 +223,18 @@ layui.config({
|
||||
var treeMobile = $('.site-tree-mobile'),
|
||||
shadeMobile = $('.site-mobile-shade')
|
||||
|
||||
treeMobile.on('click', function(){
|
||||
treeMobile.on('click', function () {
|
||||
$('body').addClass('site-mobile');
|
||||
});
|
||||
|
||||
shadeMobile.on('click', function(){
|
||||
shadeMobile.on('click', function () {
|
||||
$('body').removeClass('site-mobile');
|
||||
});
|
||||
|
||||
// 添加新窗口
|
||||
$("body").on("click",".layui-nav .layui-nav-item a",function(){
|
||||
$("body").on("click", ".layui-nav .layui-nav-item a", function () {
|
||||
//如果不存在子级
|
||||
if($(this).siblings().length == 0){
|
||||
if ($(this).siblings().length == 0) {
|
||||
addTab($(this));
|
||||
$('body').removeClass('site-mobile'); //移动端点击菜单关闭菜单层
|
||||
}
|
||||
@@ -242,73 +242,73 @@ layui.config({
|
||||
})
|
||||
|
||||
//公告层
|
||||
function showNotice(){
|
||||
function showNotice() {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "系统公告",
|
||||
closeBtn: false,
|
||||
area: '310px',
|
||||
shade: 0.8,
|
||||
id: 'LAY_layuipro',
|
||||
btn: ['火速围观'],
|
||||
moveType: 1,
|
||||
content: '<div style="padding:15px 20px; text-align:justify; line-height: 22px; text-indent:2em;border-bottom:1px solid #e2e2e2;">' +
|
||||
'<p>郑重提示:OpenAuth.Net 6.0新版上线,如以前访问过本站点请清空缓存后访问</p>' +
|
||||
'<p>喜欢的,快快star吧!</p></div>',
|
||||
success: function(layero){
|
||||
type: 1,
|
||||
title: "系统公告",
|
||||
closeBtn: false,
|
||||
area: '310px',
|
||||
shade: 0.8,
|
||||
id: 'LAY_layuipro',
|
||||
btn: ['火速围观'],
|
||||
moveType: 1,
|
||||
content: '<div style="padding:15px 20px; text-align:justify; line-height: 22px; text-indent:2em;border-bottom:1px solid #e2e2e2;">' +
|
||||
'<p>郑重提示:OpenAuth.Net 7.1新版上线,如以前访问过本站点请清空缓存后访问</p>' +
|
||||
'<p>喜欢的,快快star吧!</p></div>',
|
||||
success: function (layero) {
|
||||
var btn = layero.find('.layui-layer-btn');
|
||||
btn.css('text-align', 'center');
|
||||
btn.on("click",function(){
|
||||
window.sessionStorage.setItem("showNotice","true");
|
||||
btn.on("click", function () {
|
||||
window.sessionStorage.setItem("showNotice", "true");
|
||||
})
|
||||
if($(window).width() > 432){ //如果页面宽度不足以显示顶部“系统公告”按钮,则不提示
|
||||
btn.on("click",function(){
|
||||
if ($(window).width() > 432) { //如果页面宽度不足以显示顶部“系统公告”按钮,则不提示
|
||||
btn.on("click", function () {
|
||||
layer.tips('系统公告躲在了这里', '#showNotice', {
|
||||
tips: 3
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
//判断是否处于锁屏状态(如果关闭以后则未关闭浏览器之前不再显示)
|
||||
if(window.sessionStorage.getItem("lockcms") != "true" && window.sessionStorage.getItem("showNotice") != "true"){
|
||||
if (window.sessionStorage.getItem("lockcms") != "true" && window.sessionStorage.getItem("showNotice") != "true") {
|
||||
showNotice();
|
||||
}
|
||||
$(".showNotice").on("click",function(){
|
||||
$(".showNotice").on("click", function () {
|
||||
showNotice();
|
||||
})
|
||||
|
||||
//刷新后还原打开的窗口
|
||||
if(window.sessionStorage.getItem("menu") != null){
|
||||
if (window.sessionStorage.getItem("menu") != null) {
|
||||
menu = JSON.parse(window.sessionStorage.getItem("menu"));
|
||||
curmenu = window.sessionStorage.getItem("curmenu");
|
||||
var openTitle = '';
|
||||
for(var i=0;i<menu.length;i++){
|
||||
for (var i = 0; i < menu.length; i++) {
|
||||
openTitle = '';
|
||||
if(menu[i].icon){
|
||||
if(menu[i].icon.split("-")[0] == 'icon'){
|
||||
openTitle += '<i class="iconfont '+menu[i].icon+'"></i>';
|
||||
}else{
|
||||
openTitle += '<i class="layui-icon">'+menu[i].icon+'</i>';
|
||||
if (menu[i].icon) {
|
||||
if (menu[i].icon.split("-")[0] == 'icon') {
|
||||
openTitle += '<i class="iconfont ' + menu[i].icon + '"></i>';
|
||||
} else {
|
||||
openTitle += '<i class="layui-icon">' + menu[i].icon + '</i>';
|
||||
}
|
||||
}
|
||||
openTitle += '<cite>'+menu[i].title+'</cite>';
|
||||
openTitle += '<i class="layui-icon layui-unselect layui-tab-close" data-id="'+menu[i].layId+'">ဆ</i>';
|
||||
element.tabAdd("bodyTab",{
|
||||
title : openTitle,
|
||||
content :"<iframe src='"+menu[i].href+"' data-id='"+menu[i].layId+"'></frame>",
|
||||
id : menu[i].layId
|
||||
openTitle += '<cite>' + menu[i].title + '</cite>';
|
||||
openTitle += '<i class="layui-icon layui-unselect layui-tab-close" data-id="' + menu[i].layId + '">ဆ</i>';
|
||||
element.tabAdd("bodyTab", {
|
||||
title: openTitle,
|
||||
content: "<iframe src='" + menu[i].href + "' data-id='" + menu[i].layId + "'></frame>",
|
||||
id: menu[i].layId
|
||||
})
|
||||
//定位到刷新前的窗口
|
||||
if(curmenu != "undefined"){
|
||||
if(curmenu == '' || curmenu == "null"){ //定位到后台首页
|
||||
element.tabChange("bodyTab",'');
|
||||
}else if(JSON.parse(curmenu).title == menu[i].title){ //定位到刷新前的页面
|
||||
element.tabChange("bodyTab",menu[i].layId);
|
||||
if (curmenu != "undefined") {
|
||||
if (curmenu == '' || curmenu == "null") { //定位到后台首页
|
||||
element.tabChange("bodyTab", '');
|
||||
} else if (JSON.parse(curmenu).title == menu[i].title) { //定位到刷新前的页面
|
||||
element.tabChange("bodyTab", menu[i].layId);
|
||||
}
|
||||
}else{
|
||||
element.tabChange("bodyTab",menu[menu.length-1].layId);
|
||||
} else {
|
||||
element.tabChange("bodyTab", menu[menu.length - 1].layId);
|
||||
}
|
||||
}
|
||||
//渲染顶部窗口
|
||||
@@ -316,61 +316,61 @@ layui.config({
|
||||
}
|
||||
|
||||
//刷新当前
|
||||
$(".refresh").on("click",function(){ //此处添加禁止连续点击刷新一是为了降低服务器压力,另外一个就是为了防止超快点击造成chrome本身的一些js文件的报错(不过貌似这个问题还是存在,不过概率小了很多)
|
||||
if($(this).hasClass("refreshThis")){
|
||||
$(".refresh").on("click", function () { //此处添加禁止连续点击刷新一是为了降低服务器压力,另外一个就是为了防止超快点击造成chrome本身的一些js文件的报错(不过貌似这个问题还是存在,不过概率小了很多)
|
||||
if ($(this).hasClass("refreshThis")) {
|
||||
$(this).removeClass("refreshThis");
|
||||
$(".clildFrame .layui-tab-item.layui-show").find("iframe")[0].contentWindow.location.reload(true);
|
||||
}else{
|
||||
} else {
|
||||
layer.msg("您点击的速度超过了服务器的响应速度,还是等两秒再刷新吧!");
|
||||
setTimeout(function(){
|
||||
setTimeout(function () {
|
||||
$(".refresh").addClass("refreshThis");
|
||||
},2000)
|
||||
}, 2000)
|
||||
}
|
||||
})
|
||||
|
||||
//关闭其他
|
||||
$(".closePageOther").on("click",function(){
|
||||
if($("#top_tabs li").length>2 && $("#top_tabs li.layui-this cite").text()!="后台首页"){
|
||||
$(".closePageOther").on("click", function () {
|
||||
if ($("#top_tabs li").length > 2 && $("#top_tabs li.layui-this cite").text() != "后台首页") {
|
||||
var menu = JSON.parse(window.sessionStorage.getItem("menu"));
|
||||
$("#top_tabs li").each(function(){
|
||||
if($(this).attr("lay-id") != '' && !$(this).hasClass("layui-this")){
|
||||
element.tabDelete("bodyTab",$(this).attr("lay-id")).init();
|
||||
$("#top_tabs li").each(function () {
|
||||
if ($(this).attr("lay-id") != '' && !$(this).hasClass("layui-this")) {
|
||||
element.tabDelete("bodyTab", $(this).attr("lay-id")).init();
|
||||
//此处将当前窗口重新获取放入session,避免一个个删除来回循环造成的不必要工作量
|
||||
for(var i=0;i<menu.length;i++){
|
||||
if($("#top_tabs li.layui-this cite").text() == menu[i].title){
|
||||
menu.splice(0,menu.length,menu[i]);
|
||||
window.sessionStorage.setItem("menu",JSON.stringify(menu));
|
||||
for (var i = 0; i < menu.length; i++) {
|
||||
if ($("#top_tabs li.layui-this cite").text() == menu[i].title) {
|
||||
menu.splice(0, menu.length, menu[i]);
|
||||
window.sessionStorage.setItem("menu", JSON.stringify(menu));
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}else if($("#top_tabs li.layui-this cite").text()=="后台首页" && $("#top_tabs li").length>1){
|
||||
$("#top_tabs li").each(function(){
|
||||
if($(this).attr("lay-id") != '' && !$(this).hasClass("layui-this")){
|
||||
element.tabDelete("bodyTab",$(this).attr("lay-id")).init();
|
||||
} else if ($("#top_tabs li.layui-this cite").text() == "后台首页" && $("#top_tabs li").length > 1) {
|
||||
$("#top_tabs li").each(function () {
|
||||
if ($(this).attr("lay-id") != '' && !$(this).hasClass("layui-this")) {
|
||||
element.tabDelete("bodyTab", $(this).attr("lay-id")).init();
|
||||
window.sessionStorage.removeItem("menu");
|
||||
menu = [];
|
||||
window.sessionStorage.removeItem("curmenu");
|
||||
}
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
layer.msg("没有可以关闭的窗口了@_@");
|
||||
}
|
||||
//渲染顶部窗口
|
||||
tab.tabMove();
|
||||
})
|
||||
//关闭全部
|
||||
$(".closePageAll").on("click",function(){
|
||||
if($("#top_tabs li").length > 1){
|
||||
$("#top_tabs li").each(function(){
|
||||
if($(this).attr("lay-id") != ''){
|
||||
element.tabDelete("bodyTab",$(this).attr("lay-id")).init();
|
||||
$(".closePageAll").on("click", function () {
|
||||
if ($("#top_tabs li").length > 1) {
|
||||
$("#top_tabs li").each(function () {
|
||||
if ($(this).attr("lay-id") != '') {
|
||||
element.tabDelete("bodyTab", $(this).attr("lay-id")).init();
|
||||
window.sessionStorage.removeItem("menu");
|
||||
menu = [];
|
||||
window.sessionStorage.removeItem("curmenu");
|
||||
}
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
layer.msg("没有可以关闭的窗口了@_@");
|
||||
}
|
||||
//渲染顶部窗口
|
||||
@@ -379,20 +379,20 @@ layui.config({
|
||||
})
|
||||
|
||||
//打开新窗口
|
||||
function addTab(_this){
|
||||
function addTab(_this) {
|
||||
tab.tabAdd(_this);
|
||||
}
|
||||
|
||||
//捐赠弹窗
|
||||
function donation(){
|
||||
function donation() {
|
||||
layer.tab({
|
||||
area : ['260px', '367px'],
|
||||
tab : [{
|
||||
title : "微信",
|
||||
content : "<div style='padding:30px;overflow:hidden;background:#d2d0d0;'><img src='/images/wechat.jpg'></div>"
|
||||
},{
|
||||
title : "支付宝",
|
||||
content : "<div style='padding:30px;overflow:hidden;background:#d2d0d0;'><img src='/images/alipay.jpg'></div>"
|
||||
area: ['260px', '367px'],
|
||||
tab: [{
|
||||
title: "微信",
|
||||
content: "<div style='padding:30px;overflow:hidden;background:#d2d0d0;'><img src='/images/wechat.jpg'></div>"
|
||||
}, {
|
||||
title: "支付宝",
|
||||
content: "<div style='padding:30px;overflow:hidden;background:#d2d0d0;'><img src='/images/alipay.jpg'></div>"
|
||||
}]
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
|
||||
/*
|
||||
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
|
||||
* @Date: 2024-11-29 22:16:54
|
||||
* @LastEditTime: 2025-03-07 09:49:51
|
||||
* @Description:
|
||||
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
*/
|
||||
|
||||
layui.define("jquery", function (exports) {
|
||||
var jQuery = layui.jquery,
|
||||
$ = layui.jquery;
|
||||
@@ -29,30 +36,62 @@ layui.define("jquery", function (exports) {
|
||||
loadMenus: function (modulecode) {
|
||||
var dom = $(this);
|
||||
$.ajax("/ModuleManager/LoadAuthorizedMenus?modulecode=" + modulecode,
|
||||
{
|
||||
async: false
|
||||
, success: function (data) {
|
||||
var obj = JSON.parse(data);
|
||||
var sb = '';
|
||||
$.each(obj,
|
||||
function () {
|
||||
var element = this;
|
||||
sb += ("<button " + " data-type='" + element.DomId +
|
||||
"' " + " class='layui-btn layui-btn-small " + element.Class +
|
||||
"' " + element.Attr + ">");
|
||||
{
|
||||
async: false
|
||||
, success: function (data) {
|
||||
var obj = JSON.parse(data);
|
||||
var sb = '';
|
||||
$.each(obj,
|
||||
function () {
|
||||
var element = this;
|
||||
sb += ("<button " + " data-type='" + element.DomId +
|
||||
"' " + " class='layui-btn layui-btn-small " + element.Class +
|
||||
"' " + element.Attr + ">");
|
||||
|
||||
if (element.Icon != null && element.Icon != '') {
|
||||
sb += ("<i class='layui-icon "+element.Icon+"'></i>");
|
||||
}
|
||||
sb += (element.Name + "</button>");
|
||||
});
|
||||
if (element.Icon != null && element.Icon != '') {
|
||||
sb += ("<i class='layui-icon " + element.Icon + "'></i>");
|
||||
}
|
||||
sb += (element.Name + "</button>");
|
||||
});
|
||||
|
||||
dom.html(sb);
|
||||
}
|
||||
});
|
||||
dom.html(sb);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 修改laytable点击行选中checkbox
|
||||
clickTableRow = function (table, id, filter, callback) {
|
||||
// 监听行单击事件
|
||||
table.on('row(' + filter + ')', function (obj) {
|
||||
// 先取消所有行的checkbox的选中状态
|
||||
var tableBox = obj.tr.parents('.layui-table-box');
|
||||
tableBox.find('.layui-table-body tr').each(function () {
|
||||
$(this).find('input[type="checkbox"]').prop('checked', false);
|
||||
var index = $(this).data('index');
|
||||
table.cache[id][index].LAY_CHECKED = false;
|
||||
});
|
||||
|
||||
// 取消选中行
|
||||
table.setRowChecked(id, {
|
||||
index: 'all', // 所有行
|
||||
checked: false // 此处若设置 true,则表示全选
|
||||
});
|
||||
|
||||
|
||||
// 设置当前行选中,这个方法可以让checkStatus()获取到值,但它不能改变checkbox的选中状态😓
|
||||
table.setRowChecked(id, {
|
||||
index: obj.tr.data('index')
|
||||
});
|
||||
|
||||
// 设置当前行checkbox 选中
|
||||
obj.tr.find('input[type="checkbox"]').prop('checked', true);
|
||||
obj.data.LAY_CHECKED = true;
|
||||
if (callback) {
|
||||
callback(obj);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports('utils');
|
||||
});
|
||||
@@ -24,7 +24,7 @@ layui.config({
|
||||
var columns = data.columnFields.filter(u => u.IsList === true).map(function (e) {
|
||||
return {
|
||||
field: e.ColumnName,
|
||||
title: e.Comment
|
||||
title: e.Remark
|
||||
};
|
||||
});
|
||||
columns.unshift({
|
||||
@@ -102,6 +102,7 @@ layui.config({
|
||||
};
|
||||
}();
|
||||
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//监听表格内部按钮
|
||||
table.on('tool(list)', function (obj) {
|
||||
var data = obj.data;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
var columns = data.columnFields.filter(u => u.IsList ===true).map(function (e) {
|
||||
return {
|
||||
field: e.ColumnName,
|
||||
title: e.Comment
|
||||
title: e.Remark
|
||||
};
|
||||
});
|
||||
columns.unshift({
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
}();
|
||||
$("#tree").height($("div.layui-table-view").height());
|
||||
|
||||
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//监听表格内部按钮
|
||||
table.on('tool(list)', function (obj) {
|
||||
var data = obj.data;
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
}();
|
||||
$("#tree").height($("div.layui-table-view").height());
|
||||
|
||||
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//监听表格内部按钮
|
||||
table.on('tool(list)', function (obj) {
|
||||
var data = obj.data;
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
};
|
||||
}();
|
||||
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//监听表格内部按钮
|
||||
table.on('tool(list)', function (obj) {
|
||||
var data = obj.data;
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
};
|
||||
}();
|
||||
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//监听表格内部按钮
|
||||
table.on('tool(list)', function (obj) {
|
||||
var data = obj.data;
|
||||
|
||||
@@ -108,7 +108,8 @@
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//监听表格内部按钮
|
||||
table.on('tool(list)', function (obj) {
|
||||
var data = obj.data;
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
/*
|
||||
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
|
||||
* @Date: 2023-12-25 14:43:53
|
||||
* @LastEditTime: 2024-12-03 14:00:32
|
||||
* @LastEditTime: 2025-02-25 19:46:11
|
||||
* @Description:
|
||||
* Copyright (c) 2024 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
*/
|
||||
layui.config({
|
||||
base : "/js/"
|
||||
}).use(['form','element','layer','jquery'],function(){
|
||||
var form = layui.form,
|
||||
layer = parent.layer === undefined ? layui.layer : parent.layer,
|
||||
element = layui.element,
|
||||
$ = layui.jquery;
|
||||
base: "/js/"
|
||||
}).use(['form', 'element', 'layer', 'jquery'], function () {
|
||||
var $ = layui.jquery;
|
||||
|
||||
$(".panel a").on("click",function(){
|
||||
window.parent.addTab($(this));
|
||||
})
|
||||
$(".panel a").on("click", function () {
|
||||
window.parent.addTab($(this));
|
||||
})
|
||||
|
||||
|
||||
//用户数
|
||||
$.getJSON("/UserManager/Load?limit=1&page=1",
|
||||
function(data){
|
||||
$(".userAll span").text(data.count);
|
||||
}
|
||||
)
|
||||
//用户数
|
||||
$.getJSON("/UserManager/Load?limit=1&page=1",
|
||||
function (data) {
|
||||
$(".userAll span").text(data.count);
|
||||
}
|
||||
)
|
||||
|
||||
//机构
|
||||
$.getJSON("/UserSession/GetOrgs",
|
||||
$.getJSON("/UserSession/GetOrgs",
|
||||
function (data) {
|
||||
$(".orgs span").text(data.Result.length);
|
||||
}
|
||||
@@ -60,13 +57,13 @@ layui.config({
|
||||
}
|
||||
)
|
||||
|
||||
//数字格式化
|
||||
$(".panel span").each(function(){
|
||||
$(this).html($(this).text()>9999 ? ($(this).text()/10000).toFixed(2) + "<em>万</em>" : $(this).text());
|
||||
})
|
||||
//数字格式化
|
||||
$(".panel span").each(function () {
|
||||
$(this).html($(this).text() > 9999 ? ($(this).text() / 10000).toFixed(2) + "<em>万</em>" : $(this).text());
|
||||
})
|
||||
|
||||
//系统基本参数
|
||||
$(".version").text("v6.5"); //当前版本
|
||||
//系统基本参数
|
||||
$(".version").text("v7.1"); //当前版本
|
||||
$(".author").text("yubaolee"); //开发作者
|
||||
$(".homePage").text("/Home/Index"); //网站首页
|
||||
$(".server").text("centos docker"); //服务器环境
|
||||
|
||||
@@ -62,7 +62,9 @@ layui.config({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clickTableRow(table,'mainList', 'list', function (obj) {
|
||||
menuList({moduleId: obj.data.Id});
|
||||
});
|
||||
//菜单列表
|
||||
var menucon = {}; //table的参数,如搜索key,点击tree的id
|
||||
var menuList = function (options) {
|
||||
@@ -177,7 +179,7 @@ layui.config({
|
||||
type: 1,
|
||||
content: $('#divMenuEdit'),
|
||||
success: function () {
|
||||
if (data == undefined) {
|
||||
if (!update) {
|
||||
form.val("mfromEdit", menuInital);
|
||||
} else {
|
||||
form.val("mfromEdit", data);
|
||||
@@ -204,6 +206,7 @@ layui.config({
|
||||
}
|
||||
return {
|
||||
add: function (moduleId) { //弹出添加
|
||||
menuInital.ModuleId = moduleId;
|
||||
show(false);
|
||||
},
|
||||
update: function (data) { //弹出编辑框
|
||||
@@ -212,10 +215,6 @@ layui.config({
|
||||
};
|
||||
}();
|
||||
|
||||
//监听行单击事件
|
||||
table.on('row(list)', function (obj) {
|
||||
menuList({moduleId: obj.data.Id});
|
||||
});
|
||||
|
||||
//监听页面主按钮操作
|
||||
var active = {
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
});
|
||||
};
|
||||
mainList();
|
||||
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
|
||||
//添加(编辑)对话框
|
||||
var editDlg = function () {
|
||||
var show = function (update, data) {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//左边树状机构列表
|
||||
var ztree = function () {
|
||||
var url = '/UserSession/GetOrgs';
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
|
||||
//加载表头
|
||||
$.getJSON('/Resources/Load',
|
||||
{page: 1, limit: 1},
|
||||
{ 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
|
||||
title: e.Remark
|
||||
};
|
||||
});
|
||||
columns.unshift({
|
||||
@@ -60,6 +60,7 @@
|
||||
});
|
||||
};
|
||||
mainList();
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
|
||||
//添加(编辑)对话框
|
||||
var editDlg = function () {
|
||||
@@ -140,7 +141,7 @@
|
||||
}
|
||||
|
||||
, search: function () { //搜索
|
||||
mainList({key: $('#key').val()});
|
||||
mainList({ key: $('#key').val() });
|
||||
}
|
||||
, btnRefresh: function () {
|
||||
mainList();
|
||||
|
||||
@@ -42,6 +42,7 @@ layui.config({
|
||||
}
|
||||
|
||||
mainList();
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
|
||||
//添加(编辑)对话框
|
||||
var editDlg = function() {
|
||||
|
||||
@@ -34,6 +34,7 @@ layui.config({
|
||||
}
|
||||
});
|
||||
}
|
||||
clickTableRow(table,'mainList', 'list');
|
||||
//左边树状机构列表
|
||||
var ztree = function () {
|
||||
var url = '/UserSession/GetOrgs';
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
var columns = data.columnFields.filter(u => u.IsList === true).map(function (e) {
|
||||
return {
|
||||
field: e.ColumnName,
|
||||
title: e.Comment
|
||||
title: e.Remark
|
||||
};
|
||||
});
|
||||
columns.unshift({
|
||||
|
||||
139
OpenAuth.Repository/Domain/ExternalDataSource.cs
Normal file
139
OpenAuth.Repository/Domain/ExternalDataSource.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using OpenAuth.Repository.Core;
|
||||
|
||||
namespace OpenAuth.Repository.Domain
|
||||
{
|
||||
/// <summary>
|
||||
///外部数据源
|
||||
/// </summary>
|
||||
[Table("ExternalDataSource")]
|
||||
public class ExternalDataSource : StringEntity
|
||||
{
|
||||
public ExternalDataSource()
|
||||
{
|
||||
this.Createtime = DateTime.Now;
|
||||
this.Createusername = "";
|
||||
this.Createuserid = "";
|
||||
this.Updateuserid = "";
|
||||
this.Updateusername = "";
|
||||
this.Testsuccess = false;
|
||||
this.Updatetime = DateTime.Now;
|
||||
this.Enabled = false;
|
||||
this.Connectionstring = "";
|
||||
this.Description = "";
|
||||
this.Password = "";
|
||||
this.Username = "";
|
||||
this.Port = null;
|
||||
this.Server = "";
|
||||
this.Databasename = "";
|
||||
this.Dbtype = 0;
|
||||
this.Name = "";
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
///创建时间
|
||||
/// </summary>
|
||||
[Description("创建时间")]
|
||||
public DateTime Createtime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///创建用户名
|
||||
/// </summary>
|
||||
[Description("创建用户名")]
|
||||
public string Createusername { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///创建用户ID
|
||||
/// </summary>
|
||||
[Description("创建用户ID")]
|
||||
public string Createuserid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///更新用户ID
|
||||
/// </summary>
|
||||
[Description("更新用户ID")]
|
||||
public string Updateuserid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///更新用户名
|
||||
/// </summary>
|
||||
[Description("更新用户名")]
|
||||
public string Updateusername { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///是否测试成功
|
||||
/// </summary>
|
||||
[Description("是否测试成功")]
|
||||
public bool? Testsuccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///最后测试时间
|
||||
/// </summary>
|
||||
[Description("最后测试时间")]
|
||||
public DateTime? Updatetime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///是否启用
|
||||
/// </summary>
|
||||
[Description("是否启用")]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///连接字符串
|
||||
/// </summary>
|
||||
[Description("连接字符串")]
|
||||
public string Connectionstring { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///描述
|
||||
/// </summary>
|
||||
[Description("描述")]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///密码
|
||||
/// </summary>
|
||||
[Description("密码")]
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///用户名
|
||||
/// </summary>
|
||||
[Description("用户名")]
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///端口
|
||||
/// </summary>
|
||||
[Description("端口")]
|
||||
public int? Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///服务器地址
|
||||
/// </summary>
|
||||
[Description("服务器地址")]
|
||||
public string Server { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库名称
|
||||
/// </summary>
|
||||
[Description("数据库名称")]
|
||||
public string Databasename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库类型
|
||||
/// </summary>
|
||||
[Description("数据库类型")]
|
||||
public int Dbtype { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据源名称
|
||||
/// </summary>
|
||||
[Description("数据源名称")]
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ namespace OpenAuth.Repository
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<DataPrivilegeRule>()
|
||||
.HasKey(c => new {c.Id});
|
||||
.HasKey(c => new { c.Id });
|
||||
modelBuilder.Entity<SysTableColumn>().HasNoKey();
|
||||
modelBuilder.Entity<QueryStringObj>().HasNoKey();
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace OpenAuth.Repository
|
||||
|| Database.ProviderName == "Oracle.EntityFrameworkCore")
|
||||
{
|
||||
var boolToSmallIntConverter = new ValueConverter<bool, short>(
|
||||
v => v ? (short) 1 : (short) 0,
|
||||
v => v ? (short)1 : (short)0,
|
||||
v => v != 0);
|
||||
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||
{
|
||||
@@ -102,26 +102,37 @@ namespace OpenAuth.Repository
|
||||
property.ClrType == typeof(DateTime))
|
||||
{
|
||||
property.SetValueConverter(new ValueConverter<DateTime, DateTime>(
|
||||
v => v.ToUniversalTime(), v => DateTime.SpecifyKind(v, DateTimeKind.Utc)));
|
||||
v => v.ToLocalTime(), v => DateTime.SpecifyKind(v, DateTimeKind.Local)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//如果数据库是Oracle,则将所有表名和字段名转换为大写
|
||||
if (Database.ProviderName == "Oracle.EntityFrameworkCore")
|
||||
// Oracle和PostgreSQL将所有属性映射到大写/小写列名
|
||||
foreach (var entity in modelBuilder.Model.GetEntityTypes())
|
||||
{
|
||||
foreach (var entity in modelBuilder.Model.GetEntityTypes())
|
||||
if (Database.ProviderName == "Oracle.EntityFrameworkCore")
|
||||
{
|
||||
entity.SetTableName(entity.GetTableName().ToUpper());
|
||||
// 将所有属性映射到大写列名
|
||||
foreach (var property in entity.GetProperties())
|
||||
}
|
||||
else if (Database.ProviderName == "Npgsql.EntityFrameworkCore.PostgreSQL" || Database.ProviderName == "Pomelo.EntityFrameworkCore.MySql")
|
||||
{
|
||||
entity.SetTableName(entity.GetTableName().ToLower());
|
||||
}
|
||||
|
||||
foreach (var property in entity.GetProperties())
|
||||
{
|
||||
var storeObject = StoreObjectIdentifier.Create(entity, StoreObjectType.Table);
|
||||
if (storeObject.HasValue)
|
||||
{
|
||||
var storeObject = StoreObjectIdentifier.Create(entity, StoreObjectType.Table);
|
||||
if (storeObject.HasValue)
|
||||
if (Database.ProviderName == "Oracle.EntityFrameworkCore")
|
||||
{
|
||||
property.SetColumnName(property.GetColumnName(storeObject.Value).ToUpper());
|
||||
}
|
||||
else if (Database.ProviderName == "Npgsql.EntityFrameworkCore.PostgreSQL" || Database.ProviderName == "Pomelo.EntityFrameworkCore.MySql")
|
||||
{
|
||||
property.SetColumnName(property.GetColumnName(storeObject.Value).ToLower());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,13 +83,28 @@ namespace OpenAuth.Repository.Test
|
||||
{
|
||||
DbType = dbType.Value,
|
||||
ConnectionString = connectionString,
|
||||
IsAutoCloseConnection = true,
|
||||
MoreSettings=new ConnMoreSettings() {
|
||||
PgSqlIsAutoToLower = false,//增删查改支持驼峰表
|
||||
PgSqlIsAutoToLowerCodeFirst = false, // 建表建驼峰表。5.1.3.30
|
||||
IsAutoToUpper=false //禁用自动转成大写表
|
||||
}
|
||||
IsAutoCloseConnection = true
|
||||
});
|
||||
|
||||
if(dbType.Value != SqlSugar.DbType.PostgreSQL){
|
||||
return sqlSugar;
|
||||
}
|
||||
|
||||
// 配置bool类型转换为smallint
|
||||
sqlSugar.Aop.OnExecutingChangeSql = (sql, parameters) =>
|
||||
{
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (param.Value is bool boolValue)
|
||||
{
|
||||
param.DbType = System.Data.DbType.Int16;
|
||||
// 将 bool 转换为 smallint
|
||||
param.Value = boolValue ? (short)1 : (short)0;
|
||||
}
|
||||
}
|
||||
// 返回修改后的 SQL 和参数
|
||||
return new System.Collections.Generic.KeyValuePair<string, SugarParameter[]>(sql, parameters);
|
||||
};
|
||||
return sqlSugar;
|
||||
});
|
||||
|
||||
|
||||
@@ -133,6 +133,26 @@ namespace OpenAuth.WebApi.Controllers
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色分配资源,整体提交,会覆盖之前的配置
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public Response AssignRoleResources([FromBody] AssignRoleResources request)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.AssignRoleResources(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 部门分配用户,整体提交,会覆盖之前的配置
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace OpenAuth.WebApi.Controllers
|
||||
public class CategorysController : ControllerBase
|
||||
{
|
||||
private readonly CategoryApp _app;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取分类详情
|
||||
/// </summary>
|
||||
@@ -45,14 +45,13 @@ namespace OpenAuth.WebApi.Controllers
|
||||
/// 添加分类
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public Response Add([FromBody] AddOrUpdateCategoryReq obj)
|
||||
[HttpPost]
|
||||
public async Task<Response> Add([FromBody] AddOrUpdateCategoryReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.Add(obj);
|
||||
|
||||
await _app.Add(obj);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -67,7 +66,7 @@ namespace OpenAuth.WebApi.Controllers
|
||||
/// 修改分类(字典)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[HttpPost]
|
||||
public Response Update([FromBody] AddOrUpdateCategoryReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
@@ -89,7 +88,7 @@ namespace OpenAuth.WebApi.Controllers
|
||||
/// 加载列表
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<TableData> Load([FromQuery]QueryCategoryListReq request)
|
||||
public async Task<TableData> Load([FromQuery] QueryCategoryListReq request)
|
||||
{
|
||||
return await _app.Load(request);
|
||||
}
|
||||
@@ -97,8 +96,8 @@ namespace OpenAuth.WebApi.Controllers
|
||||
/// <summary>
|
||||
/// 批量删除
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public Response Delete([FromBody]string[] ids)
|
||||
[HttpPost]
|
||||
public Response Delete([FromBody] string[] ids)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
@@ -115,7 +114,7 @@ namespace OpenAuth.WebApi.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
public CategorysController(CategoryApp app)
|
||||
public CategorysController(CategoryApp app)
|
||||
{
|
||||
_app = app;
|
||||
}
|
||||
|
||||
143
OpenAuth.WebApi/Controllers/ExternalDataSourcesController.cs
Normal file
143
OpenAuth.WebApi/Controllers/ExternalDataSourcesController.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OpenAuth.App;
|
||||
using OpenAuth.App.Request;
|
||||
using OpenAuth.App.Response;
|
||||
using OpenAuth.Repository.Domain;
|
||||
|
||||
namespace OpenAuth.WebApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// 外部数据源管理接口
|
||||
/// </summary>
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
[ApiExplorerSettings(GroupName = "外部数据源管理接口_ExternalDataSources")]
|
||||
public class ExternalDataSourcesController : ControllerBase
|
||||
{
|
||||
private readonly ExtDataSourceApp _app;
|
||||
|
||||
//获取详情
|
||||
[HttpGet]
|
||||
public Response<ExternalDataSource> Get(string id)
|
||||
{
|
||||
var result = new Response<ExternalDataSource>();
|
||||
try
|
||||
{
|
||||
result.Result = _app.Get(id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//添加
|
||||
[HttpPost]
|
||||
public Response Add([FromBody]AddOrUpdateExternalDataSourceReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.Add(obj);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//测试连接
|
||||
[HttpPost]
|
||||
public Response TestConnection([FromBody]TestConnectionReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.TestConnection(obj);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//修改
|
||||
[HttpPost]
|
||||
public Response Update([FromBody]AddOrUpdateExternalDataSourceReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.Update(obj);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载列表
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<TableData> Load([FromQuery]QueryExternalDataSourceListReq request)
|
||||
{
|
||||
return await _app.Load(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public TableData GetDbTypes()
|
||||
{
|
||||
|
||||
return _app.GetDbTypes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public Response Delete([FromBody]string[] ids)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.Delete(ids);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ExternalDataSourcesController(ExtDataSourceApp app)
|
||||
{
|
||||
_app = app;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,6 +167,27 @@ namespace OpenAuth.WebApi.Controllers
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 撤销最后一个节点审批
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public Response UndoVerification([FromBody] UndoVerificationReq request)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.UndoVerification(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载列表
|
||||
/// </summary>
|
||||
@@ -194,6 +215,9 @@ namespace OpenAuth.WebApi.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public FlowInstancesController(FlowInstanceApp app)
|
||||
{
|
||||
_app = app;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -22,7 +22,7 @@ namespace OpenAuth.WebApi.Controllers
|
||||
{
|
||||
private readonly ResourceApp _app;
|
||||
|
||||
public ResourcesController(IAuth authUtil, ResourceApp app)
|
||||
public ResourcesController(ResourceApp app)
|
||||
{
|
||||
_app = app;
|
||||
}
|
||||
@@ -32,6 +32,28 @@ namespace OpenAuth.WebApi.Controllers
|
||||
return await _app.Load(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步站点API到资源列表
|
||||
/// <para>读取站点API信息,如果资源列表中不存在,则添加</para>
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<Response> Sync()
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
await _app.Sync();
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public Response Delete([FromBody]string[] ids)
|
||||
{
|
||||
@@ -104,5 +126,23 @@ namespace OpenAuth.WebApi.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源所属应用
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<Response<List<SysResourceApp>>> GetResourceApps()
|
||||
{
|
||||
var result = new Response<List<SysResourceApp>>();
|
||||
try
|
||||
{
|
||||
result.Result = await _app.GetResourceApps();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = e.InnerException?.Message ?? e.Message;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,13 @@ namespace OpenAuth.WebApi.Model
|
||||
private readonly IAuth _authUtil;
|
||||
private readonly SysLogApp _logApp;
|
||||
|
||||
public OpenAuthFilter(IAuth authUtil, SysLogApp logApp)
|
||||
private readonly ResourceApp _resourceApp;
|
||||
|
||||
public OpenAuthFilter(IAuth authUtil, SysLogApp logApp, ResourceApp resourceApp)
|
||||
{
|
||||
_authUtil = authUtil;
|
||||
_logApp = logApp;
|
||||
_resourceApp = resourceApp;
|
||||
}
|
||||
|
||||
public void OnActionExecuting(ActionExecutingContext context)
|
||||
@@ -28,9 +31,9 @@ namespace OpenAuth.WebApi.Model
|
||||
var Controllername = description.ControllerName.ToLower();
|
||||
var Actionname = description.ActionName.ToLower();
|
||||
|
||||
//匿名标识
|
||||
var authorize = description.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute));
|
||||
if (authorize != null)
|
||||
//匿名访问的不需要验证
|
||||
var allowAnonymous = description.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute));
|
||||
if (allowAnonymous != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -41,14 +44,29 @@ namespace OpenAuth.WebApi.Model
|
||||
context.Result = new JsonResult(new Response
|
||||
{
|
||||
Code = 401,
|
||||
Message = "认证失败,请提供认证信息"
|
||||
Message = "登录已过期,请重新登录"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var apiPath = $"{Controllername}/{Actionname}";
|
||||
//判断登录角色是否拥有访问该URL的权限
|
||||
var resource = _resourceApp.CanAccess(apiPath);
|
||||
if(!resource)
|
||||
{
|
||||
context.Result = new JsonResult(new Response
|
||||
{
|
||||
Code = 500,
|
||||
Message = $"当前用户没有访问{apiPath}的权限,请在【角色管理】中分配资源"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_logApp.Add(new SysLog
|
||||
{
|
||||
Content = $"用户访问",
|
||||
Href = $"{Controllername}/{Actionname}",
|
||||
Href = apiPath,
|
||||
CreateName = _authUtil.GetUserName(),
|
||||
CreateId = _authUtil.GetCurrentUser().User.Id,
|
||||
TypeName = "访问日志"
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.6.23" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.0" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.2.22" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
|
||||
|
||||
@@ -184,12 +184,28 @@ namespace OpenAuth.WebApi
|
||||
{
|
||||
DbType = dbType.Value,
|
||||
ConnectionString = connectionString,
|
||||
IsAutoCloseConnection = true,
|
||||
MoreSettings=new ConnMoreSettings() {
|
||||
PgSqlIsAutoToLower = false,//增删查改支持驼峰表
|
||||
PgSqlIsAutoToLowerCodeFirst = false// 建表建驼峰表。5.1.3.30
|
||||
}
|
||||
IsAutoCloseConnection = true
|
||||
}, db => { db.Aop.OnLogExecuting = (sql, pars) => { logger.LogInformation(sql); }; });
|
||||
|
||||
if(dbType.Value != SqlSugar.DbType.PostgreSQL){
|
||||
return sqlSugar;
|
||||
}
|
||||
|
||||
// 配置bool类型转换为smallint
|
||||
sqlSugar.Aop.OnExecutingChangeSql = (sql, parameters) =>
|
||||
{
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (param.Value is bool boolValue)
|
||||
{
|
||||
param.DbType = System.Data.DbType.Int16;
|
||||
// 将 bool 转换为 smallint
|
||||
param.Value = boolValue ? (short)1 : (short)0;
|
||||
}
|
||||
}
|
||||
// 返回修改后的 SQL 和参数
|
||||
return new System.Collections.Generic.KeyValuePair<string, SugarParameter[]>(sql, parameters);
|
||||
};
|
||||
return sqlSugar;
|
||||
});
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
<div class="flex-column">
|
||||
<sticky :className="'sub-navbar'">
|
||||
<div class="filter-container">
|
||||
<el-input @keyup.enter.native="handleFilter" size="mini" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="firstQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="mini" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="mini" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
<el-input @keyup.enter.native="handleFilter" size="small" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="firstQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="small" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="small" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</div>
|
||||
</sticky>
|
||||
<div class="app-container flex-item flex-column">
|
||||
@@ -40,8 +40,8 @@
|
||||
<span v-if="radio == ''">明细</span>
|
||||
<span v-else>{{ radio }}明细</span>
|
||||
<div class="edit-buttons">
|
||||
<el-button v-if="editModel" class="filter-item edit-button" size="mini" v-waves icon="el-icon-plus" @click="onBtnClicked('btnAddDetail')">添加</el-button>
|
||||
<el-button v-if="editModel" class="filter-item edit-button delete-button" size="mini" v-waves icon="el-icon-delete" @click="onBtnClicked('btnDelDetail')">删除</el-button>
|
||||
<el-button v-if="editModel" class="filter-item edit-button" size="small" v-waves icon="el-icon-plus" @click="onBtnClicked('btnAddDetail')">添加</el-button>
|
||||
<el-button v-if="editModel" class="filter-item edit-button delete-button" size="small" v-waves icon="el-icon-delete" @click="onBtnClicked('btnDelDetail')">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<auth-table style="height:calc(100% - 52px - 34px)" ref="secondTable" border :editModel="editModel" :table-fields="secondHeaderList" :data="secondList" @row-click="rowClickSecondTable" @selection-change="selChangeSecondTable"></auth-table>
|
||||
@@ -52,9 +52,9 @@
|
||||
<el-card shadow="nerver" v-if="editModel" style="text-align: right;padding-bottom: 10px;">
|
||||
<el-row>
|
||||
<el-col :span="24"
|
||||
><el-button size="mini" @click="editModel = false">取消</el-button>
|
||||
<el-button size="mini" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="mini" v-else type="primary" @click="updateData">确认</el-button></el-col
|
||||
><el-button size="small" @click="editModel = false">取消</el-button>
|
||||
<el-button size="small" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="small" v-else type="primary" @click="updateData">确认</el-button></el-col
|
||||
>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
<div class="flex-column">
|
||||
<sticky :className="'sub-navbar'">
|
||||
<div class="filter-container">
|
||||
<el-input @keyup.enter.native="handleFilter" size="mini" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="firstQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="mini" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="mini" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
<el-input @keyup.enter.native="handleFilter" size="small" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="firstQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="small" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="small" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</div>
|
||||
</sticky>
|
||||
<div class="app-container flex-item flex-column">
|
||||
@@ -40,8 +40,8 @@
|
||||
<span v-if="radio == ''">明细</span>
|
||||
<span v-else>{{ radio }}明细</span>
|
||||
<div class="edit-buttons">
|
||||
<el-button v-if="editModel" class="filter-item edit-button" size="mini" v-waves icon="el-icon-plus" @click="onBtnClicked('btnAddDetail')">添加</el-button>
|
||||
<el-button v-if="editModel" class="filter-item edit-button delete-button" size="mini" v-waves icon="el-icon-delete" @click="onBtnClicked('btnDelDetail')">删除</el-button>
|
||||
<el-button v-if="editModel" class="filter-item edit-button" size="small" v-waves icon="el-icon-plus" @click="onBtnClicked('btnAddDetail')">添加</el-button>
|
||||
<el-button v-if="editModel" class="filter-item edit-button delete-button" size="small" v-waves icon="el-icon-delete" @click="onBtnClicked('btnDelDetail')">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<auth-table style="height:calc(100% - 52px - 34px)" ref="secondTable" border :editModel="editModel" :table-fields="secondHeaderList" :data="secondList" @row-click="rowClickSecondTable" @selection-change="selChangeSecondTable"></auth-table>
|
||||
@@ -52,9 +52,9 @@
|
||||
<el-card shadow="nerver" v-if="editModel" style="text-align: right;padding-bottom: 10px;">
|
||||
<el-row>
|
||||
<el-col :span="24"
|
||||
><el-button size="mini" @click="editModel = false">取消</el-button>
|
||||
<el-button size="mini" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="mini" v-else type="primary" @click="updateData">确认</el-button></el-col
|
||||
><el-button size="small" @click="editModel = false">取消</el-button>
|
||||
<el-button size="small" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="small" v-else type="primary" @click="updateData">确认</el-button></el-col
|
||||
>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<div class="flex-column">
|
||||
<sticky :className="'sub-navbar'">
|
||||
<div class="filter-container">
|
||||
<el-input @keyup.enter.native="handleFilter" size="mini" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="listQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="mini" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="mini" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
<el-input @keyup.enter.native="handleFilter" size="small" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="listQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="small" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="small" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</div>
|
||||
</sticky>
|
||||
<div class="app-container flex-item">
|
||||
@@ -29,9 +29,9 @@
|
||||
<el-dialog v-el-drag-dialog class="dialog-mini" width="500px" :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
|
||||
<auth-form ref="dataForm" :rules="rules" :edit-model="true" :form-fields="headerList" v-model="temp" :col-num="2"></auth-form>
|
||||
<div slot="footer">
|
||||
<el-button size="mini" @click="dialogFormVisible = false">取消</el-button>
|
||||
<el-button size="mini" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="mini" v-else type="primary" @click="updateData">确认</el-button>
|
||||
<el-button size="small" @click="dialogFormVisible = false">取消</el-button>
|
||||
<el-button size="small" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="small" v-else type="primary" @click="updateData">确认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
@@ -1,71 +1,36 @@
|
||||
<!--
|
||||
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
|
||||
* @Description: 代码生成器自动生成动态头部列表
|
||||
* @Copyright (c) 2022 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
* @Description: OpenAuth.Pro代码生成器自动生成
|
||||
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<div class="flex flex-column">
|
||||
<sticky>
|
||||
<el-input
|
||||
@keyup.enter="handleFilter"
|
||||
size="mini"
|
||||
style="width: 200px"
|
||||
class="filter-item"
|
||||
:placeholder="'名称'"
|
||||
v-model="listQuery.key"></el-input>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
size="mini"
|
||||
icon="el-icon-search"
|
||||
@click="handleFilter">
|
||||
搜索
|
||||
</el-button>
|
||||
<permission-btn
|
||||
size="mini"
|
||||
v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
<div class="search-box">
|
||||
<el-input @keyup.enter="handleFilter" size="small" class="custom-input w-200" :placeholder="'名称'"
|
||||
v-model="listQuery.key"></el-input>
|
||||
<el-button size="small" class="custom-button filter-item" icon="el-icon-search"
|
||||
@click="handleFilter">搜索</el-button>
|
||||
</div>
|
||||
<permission-btn v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</sticky>
|
||||
|
||||
<auth-table
|
||||
ref="mainTable"
|
||||
:select-type="'checkbox'"
|
||||
:table-fields="headerList"
|
||||
:data="list"
|
||||
:v-loading="listLoading"
|
||||
@row-click="rowClick"
|
||||
@selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit"
|
||||
@current-change="handleCurrentChange" />
|
||||
<auth-table ref="mainTableRef" :select-type="'checkbox'" :table-fields="headerList" :data="list"
|
||||
:v-loading="listLoading" @row-click="rowClick" @selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination v-show="total > 0" :total="total" v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit" @current-change="handleCurrentChange" />
|
||||
</div>
|
||||
<el-dialog
|
||||
draggable
|
||||
class="dialog-mini"
|
||||
width="500px"
|
||||
:title="txtDlgTitle[dialogStatus]"
|
||||
v-model="dialogFormVisible">
|
||||
<auth-form
|
||||
ref="dataForm"
|
||||
:rules="rules"
|
||||
:edit-model="true"
|
||||
:form-fields="headerList"
|
||||
:data="temp"
|
||||
<el-dialog draggable class="dialog-mini" width="500px" :title="dialogStatus==0?'新增':'编辑'" v-model="dialogFormVisible">
|
||||
<auth-form ref="dataFormRef" :rules="rules" :edit-model="true" :form-fields="headerList" :data="temp"
|
||||
:col-num="2"></auth-form>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<el-button size="mini" @click="dialogFormVisible = false">
|
||||
<el-button size="small" @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
v-if="dialogStatus == 'create'"
|
||||
type="primary"
|
||||
@click="createData">
|
||||
<el-button size="small" v-if="dialogStatus == 0" type="primary" @click="createData">
|
||||
确认
|
||||
</el-button>
|
||||
<el-button size="mini" v-else type="primary" @click="updateData">
|
||||
<el-button size="small" v-else type="primary" @click="updateData">
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -86,46 +51,35 @@ import Sticky from '@/components/Sticky/index.vue'
|
||||
import permissionBtn from '@/components/PermissionBtn/index.vue'
|
||||
import AuthForm from '../../components/Base/AuthForm.vue'
|
||||
import AuthTable from '../../components/Base/AuthTable.vue'
|
||||
|
||||
const headerList = ref([]) //列表头
|
||||
const multipleSelection = ref([]) //列表checkbox选中的值
|
||||
const list = ref([]) //列表值
|
||||
const total = ref(0) //总条数
|
||||
const listLoading = ref(true) //进度条
|
||||
const dialogFormVisible = ref(false) //是否显示编辑框
|
||||
const dialogStatus = ref('')
|
||||
const dialogStatus = ref(0) //0:新增 1:编辑
|
||||
let temp = reactive({}) //新增(编辑)绑定对话框
|
||||
|
||||
const listQuery = reactive({
|
||||
// 查询条件
|
||||
page: 1,
|
||||
limit: 20,
|
||||
key: undefined,
|
||||
})
|
||||
|
||||
const txtDlgTitle = reactive({
|
||||
//对话框标题
|
||||
update: '编辑',
|
||||
create: '添加',
|
||||
})
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
||||
})
|
||||
|
||||
//组件refs
|
||||
const mainTable = ref(null)
|
||||
const dataForm = ref(null)
|
||||
|
||||
const mainTableRef = ref(null)
|
||||
const dataFormRef = ref(null)
|
||||
onMounted(() => {
|
||||
headerList.value = [
|
||||
{HeaderList}
|
||||
{HeaderList}
|
||||
]
|
||||
getList()
|
||||
})
|
||||
|
||||
const rowClick = function (row) {
|
||||
mainTable.value.clearSelection()
|
||||
mainTable.value.toggleRowSelection(row)
|
||||
mainTableRef.value.clearSelection()
|
||||
mainTableRef.value.toggleRowSelection(row)
|
||||
}
|
||||
const handleSelectionChange = function (val) {
|
||||
multipleSelection.value = val
|
||||
@@ -137,27 +91,18 @@ const onBtnClicked = function (domId, callback) {
|
||||
break
|
||||
case 'btnEdit':
|
||||
if (multipleSelection.value.length !== 1) {
|
||||
ElMessage.error({
|
||||
message: '只能选中一个进行编辑',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('只能选中一个进行编辑')
|
||||
return
|
||||
}
|
||||
handleUpdate(multipleSelection.value[0])
|
||||
break
|
||||
case 'btnDel':
|
||||
if (multipleSelection.value.length < 1) {
|
||||
ElMessage.error({
|
||||
message: '至少删除一个',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('至少删除一个')
|
||||
return
|
||||
}
|
||||
handleDelete(multipleSelection.value)
|
||||
break
|
||||
case 'btnExport':
|
||||
mainTable.value.exportExcel('资源文件', callback)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -174,22 +119,12 @@ const handleFilter = function () {
|
||||
listQuery.page = 1
|
||||
getList()
|
||||
}
|
||||
const handleSizeChange = function (val) {
|
||||
listQuery.limit = val
|
||||
getList()
|
||||
}
|
||||
|
||||
const handleCurrentChange = function (val) {
|
||||
listQuery.page = val
|
||||
getList()
|
||||
}
|
||||
const handleModifyStatus = function (row, disable) {
|
||||
// 模拟修改状态
|
||||
ElMessage.success({
|
||||
message: '操作成功',
|
||||
type: 'success',
|
||||
})
|
||||
row.disable = disable
|
||||
}
|
||||
|
||||
const resetTemp = function () {
|
||||
let obj = {}
|
||||
headerList.value.forEach(item => {
|
||||
@@ -198,39 +133,30 @@ const resetTemp = function () {
|
||||
Object.assign(temp, obj)
|
||||
}
|
||||
const handleCreate = async function () {
|
||||
// 弹出添加框
|
||||
resetTemp()
|
||||
dialogStatus.value = 'create'
|
||||
dialogStatus.value = 0
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const createData = function () {
|
||||
// 保存提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
{TableName}s.add(temp).then(() => {
|
||||
list.value.unshift(temp)
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '创建成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('创建成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleUpdate = async function (row) {
|
||||
// 弹出编辑框
|
||||
Object.assign(temp, row) //必需这样赋值才能响应式
|
||||
dialogStatus.value = 'update'
|
||||
dialogStatus.value = 1
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const updateData = function () {
|
||||
// 更新提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
const tempData = Object.assign({}, temp)
|
||||
{TableName}s.update(tempData).then(() => {
|
||||
for (const v of list.value) {
|
||||
@@ -241,17 +167,11 @@ const updateData = function () {
|
||||
}
|
||||
}
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '更新成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('更新成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleDelete = function (rows) {
|
||||
// 多行删除
|
||||
delrows({TableName}s, rows)
|
||||
delrows({TableName}s, rows, getList)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,71 +1,36 @@
|
||||
<!--
|
||||
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
|
||||
* @Description: 代码生成器自动生成动态头部列表
|
||||
* @Copyright (c) 2022 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
* @Description: OpenAuth.Pro代码生成器自动生成
|
||||
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<div class="flex flex-column">
|
||||
<sticky>
|
||||
<el-input
|
||||
@keyup.enter="handleFilter"
|
||||
size="mini"
|
||||
style="width: 200px"
|
||||
class="filter-item"
|
||||
:placeholder="'名称'"
|
||||
v-model="listQuery.key"></el-input>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
size="mini"
|
||||
icon="el-icon-search"
|
||||
@click="handleFilter">
|
||||
搜索
|
||||
</el-button>
|
||||
<permission-btn
|
||||
size="mini"
|
||||
v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
<div class="search-box">
|
||||
<el-input @keyup.enter="handleFilter" size="small" class="custom-input w-200" :placeholder="'名称'"
|
||||
v-model="listQuery.key"></el-input>
|
||||
<el-button size="small" class="custom-button filter-item" icon="el-icon-search"
|
||||
@click="handleFilter">搜索</el-button>
|
||||
</div>
|
||||
<permission-btn v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</sticky>
|
||||
|
||||
<auth-table
|
||||
ref="mainTable"
|
||||
:select-type="'checkbox'"
|
||||
:table-fields="headerList"
|
||||
:data="list"
|
||||
:v-loading="listLoading"
|
||||
@row-click="rowClick"
|
||||
@selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit"
|
||||
@current-change="handleCurrentChange" />
|
||||
<auth-table ref="mainTableRef" :select-type="'checkbox'" :table-fields="headerList" :data="list"
|
||||
:v-loading="listLoading" @row-click="rowClick" @selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination v-show="total > 0" :total="total" v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit" @current-change="handleCurrentChange" />
|
||||
</div>
|
||||
<el-dialog
|
||||
draggable
|
||||
class="dialog-mini"
|
||||
width="500px"
|
||||
:title="txtDlgTitle[dialogStatus]"
|
||||
v-model="dialogFormVisible">
|
||||
<auth-form
|
||||
ref="dataForm"
|
||||
:rules="rules"
|
||||
:edit-model="true"
|
||||
:form-fields="headerList"
|
||||
:data="temp"
|
||||
<el-dialog draggable class="dialog-mini" width="500px" :title="dialogStatus==0?'新增':'编辑'" v-model="dialogFormVisible">
|
||||
<auth-form ref="dataFormRef" :rules="rules" :edit-model="true" :form-fields="headerList" :data="temp"
|
||||
:col-num="2"></auth-form>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<el-button size="mini" @click="dialogFormVisible = false">
|
||||
<el-button size="small" @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
v-if="dialogStatus == 'create'"
|
||||
type="primary"
|
||||
@click="createData">
|
||||
<el-button size="small" v-if="dialogStatus == 0" type="primary" @click="createData">
|
||||
确认
|
||||
</el-button>
|
||||
<el-button size="mini" v-else type="primary" @click="updateData">
|
||||
<el-button size="small" v-else type="primary" @click="updateData">
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -80,48 +45,41 @@ import { onMounted, ref, reactive, nextTick } from 'vue'
|
||||
import * as {TableName}s from '@/api/{TableName}s'
|
||||
import { defaultVal } from '@/utils/index'
|
||||
import { delrows } from '@/utils/delRows.js'
|
||||
import ColumnDefine from '@/interface/columnDefine'
|
||||
//引入组件
|
||||
import Sticky from '@/components/Sticky/index.vue'
|
||||
import permissionBtn from '@/components/PermissionBtn/index.vue'
|
||||
import AuthForm from '../../components/Base/AuthForm.vue'
|
||||
import AuthTable from '../../components/Base/AuthTable.vue'
|
||||
|
||||
const headerList = ref([]) //列表头
|
||||
const multipleSelection = ref([]) //列表checkbox选中的值
|
||||
const list = ref([]) //列表值
|
||||
const total = ref(0) //总条数
|
||||
const listLoading = ref(true) //进度条
|
||||
const dialogFormVisible = ref(false) //是否显示编辑框
|
||||
const dialogStatus = ref('')
|
||||
const dialogStatus = ref(0) //0:新增 1:编辑
|
||||
let temp = reactive({}) //新增(编辑)绑定对话框
|
||||
|
||||
const listQuery = reactive({
|
||||
// 查询条件
|
||||
page: 1,
|
||||
limit: 20,
|
||||
key: undefined,
|
||||
})
|
||||
|
||||
const txtDlgTitle = reactive({
|
||||
//对话框标题
|
||||
update: '编辑',
|
||||
create: '添加',
|
||||
})
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
||||
})
|
||||
|
||||
//组件refs
|
||||
const mainTable = ref(null)
|
||||
const dataForm = ref(null)
|
||||
|
||||
const mainTableRef = ref(null)
|
||||
const dataFormRef = ref(null)
|
||||
onMounted(() => {
|
||||
headerList.value = [
|
||||
{HeaderList}
|
||||
]
|
||||
getList()
|
||||
})
|
||||
|
||||
const rowClick = function (row) {
|
||||
mainTable.value.clearSelection()
|
||||
mainTable.value.toggleRowSelection(row)
|
||||
mainTableRef.value.clearSelection()
|
||||
mainTableRef.value.toggleRowSelection(row)
|
||||
}
|
||||
const handleSelectionChange = function (val) {
|
||||
multipleSelection.value = val
|
||||
@@ -133,27 +91,18 @@ const onBtnClicked = function (domId, callback) {
|
||||
break
|
||||
case 'btnEdit':
|
||||
if (multipleSelection.value.length !== 1) {
|
||||
ElMessage.error({
|
||||
message: '只能选中一个进行编辑',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('只能选中一个进行编辑')
|
||||
return
|
||||
}
|
||||
handleUpdate(multipleSelection.value[0])
|
||||
break
|
||||
case 'btnDel':
|
||||
if (multipleSelection.value.length < 1) {
|
||||
ElMessage.error({
|
||||
message: '至少删除一个',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('至少删除一个')
|
||||
return
|
||||
}
|
||||
handleDelete(multipleSelection.value)
|
||||
break
|
||||
case 'btnExport':
|
||||
mainTable.value.exportExcel('资源文件', callback)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -177,22 +126,12 @@ const handleFilter = function () {
|
||||
listQuery.page = 1
|
||||
getList()
|
||||
}
|
||||
const handleSizeChange = function (val) {
|
||||
listQuery.limit = val
|
||||
getList()
|
||||
}
|
||||
|
||||
const handleCurrentChange = function (val) {
|
||||
listQuery.page = val
|
||||
getList()
|
||||
}
|
||||
const handleModifyStatus = function (row, disable) {
|
||||
// 模拟修改状态
|
||||
ElMessage.success({
|
||||
message: '操作成功',
|
||||
type: 'success',
|
||||
})
|
||||
row.disable = disable
|
||||
}
|
||||
|
||||
const resetTemp = function () {
|
||||
let obj = {}
|
||||
headerList.value.forEach(item => {
|
||||
@@ -201,39 +140,30 @@ const resetTemp = function () {
|
||||
Object.assign(temp, obj)
|
||||
}
|
||||
const handleCreate = async function () {
|
||||
// 弹出添加框
|
||||
resetTemp()
|
||||
dialogStatus.value = 'create'
|
||||
dialogStatus.value = 0
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const createData = function () {
|
||||
// 保存提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
{TableName}s.add(temp).then(() => {
|
||||
list.value.unshift(temp)
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '创建成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('创建成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleUpdate = async function (row) {
|
||||
// 弹出编辑框
|
||||
Object.assign(temp, row) //必需这样赋值才能响应式
|
||||
dialogStatus.value = 'update'
|
||||
dialogStatus.value = 1
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const updateData = function () {
|
||||
// 更新提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
const tempData = Object.assign({}, temp)
|
||||
{TableName}s.update(tempData).then(() => {
|
||||
for (const v of list.value) {
|
||||
@@ -244,17 +174,11 @@ const updateData = function () {
|
||||
}
|
||||
}
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '更新成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('更新成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleDelete = function (rows) {
|
||||
// 多行删除
|
||||
delrows({TableName}s, rows)
|
||||
delrows({TableName}s, rows, getList)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<div class="flex-column">
|
||||
<sticky :className="'sub-navbar'">
|
||||
<div class="filter-container">
|
||||
<el-input @keyup.enter.native="handleFilter" size="mini" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="listQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="mini" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="mini" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
<el-input @keyup.enter.native="handleFilter" size="small" style="width: 200px;" class="filter-item" :placeholder="'名称'" v-model="listQuery.key"> </el-input>
|
||||
<el-button class="filter-item" size="small" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<permission-btn size="small" v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</div>
|
||||
</sticky>
|
||||
<div class="app-container flex-item">
|
||||
@@ -29,9 +29,9 @@
|
||||
<el-dialog v-el-drag-dialog class="dialog-mini" width="500px" :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
|
||||
<auth-form ref="dataForm" :rules="rules" :edit-model="true" :form-fields="headerList" v-model="temp" :col-num="2"></auth-form>
|
||||
<div slot="footer">
|
||||
<el-button size="mini" @click="dialogFormVisible = false">取消</el-button>
|
||||
<el-button size="mini" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="mini" v-else type="primary" @click="updateData">确认</el-button>
|
||||
<el-button size="small" @click="dialogFormVisible = false">取消</el-button>
|
||||
<el-button size="small" v-if="dialogStatus == 'create'" type="primary" @click="createData">确认</el-button>
|
||||
<el-button size="small" v-else type="primary" @click="updateData">确认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
🔥.Net权限管理及快速开发框架、最好用的权限工作流系统。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:角色授权、代码生成、智能打印、表单设计、工作流、定时任务等。架构易扩展,是中小企业的首选。
|
||||
🔥.Net权限管理及快速开发框架、最好用的权限工作流系统。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:角色授权、代码生成、API鉴权、智能打印、表单设计、工作流、定时任务等。架构易扩展,是中小企业的首选。
|
||||
|
||||

|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
* 超强的自定义权限控制功能,请参考:[通用权限设计与实现](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)
|
||||
|
||||
* 完整的字段权限控制,可以控制字段可见及API是否返回字段值
|
||||
* 完整API鉴权,可以控制角色可访问的API资源,及模块功能字段可见及是否返回,请参考:[按角色授权API资源](http://doc.openauth.net.cn/core/apiauth.html#%E6%8C%89%E8%A7%92%E8%89%B2%E6%8E%88%E6%9D%83api%E8%B5%84%E6%BA%90) 及 [字段权限](http://doc.openauth.net.cn/core/datapropertyrule.html)
|
||||
|
||||
* 可拖拽的表单设计。详情:[可拖拽表单](http://doc.openauth.net.cn/pro/dragform.html)
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
* 全网最好用的打印解决方案。详情:[智能打印](http://doc.openauth.net.cn/pro/printerplan.html)
|
||||
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能,请参考:[定时任务](http://doc.openauth.net.cn/core/job.html)
|
||||
|
||||
* 基于CodeSmith的代码生成功能,可快速生成带有头/明细结构的页面
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
* 支持多租户
|
||||
|
||||
* 集成IdentityServer4,实现基于OAuth2的登录体系
|
||||
* 支持搭建自己的IdentityServer服务器,实现基于OAuth2的登录体系,请参考:[登录认证及OAuth集成](http://doc.openauth.net.cn/core/identity.html)
|
||||
|
||||
* 建立三方对接规范,已有系统可以无缝对接流程引擎
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ features:
|
||||
- title: 紧随潮流
|
||||
details: 最新的.net sdk,配合最炫的vue框架。
|
||||
- title: 功能强大
|
||||
details: 角色授权、代码生成、智能打印、数据权限、拖拽表单、工作流引擎、定时任务。
|
||||
details: 角色授权、代码生成、API鉴权、智能打印、数据权限、拖拽表单、工作流引擎、定时任务。
|
||||
- title: 主流技术
|
||||
details: IdentityServer、EF、SqlSugar、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、VUE2、VUE3、Element-ui、Element-plus。
|
||||
footer: Copyright © 2024- yubaolee
|
||||
footer: Copyright © 2025- yubaolee
|
||||
---
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||

|
||||
|
||||
OpenAuth.Net是基于最新版.Net的开源权限工作流快速开发框架。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:组织机构、角色用户、权限授权、表单设计、工作流等。
|
||||
OpenAuth.Net是基于最新版.Net的开源权限工作流快速开发框架。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:角色授权、代码生成、API鉴权、智能打印、表单设计、工作流、定时任务等。
|
||||
|
||||
开源版本演示:[http://demo.openauth.net.cn:1802/](http://demo.openauth.net.cn:1802/)
|
||||
|
||||
@@ -33,7 +33,7 @@ gitee上面两个版本。其中:
|
||||
|
||||
* 超强的自定义权限控制功能,请参考:[通用权限设计与实现](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)
|
||||
|
||||
* 完整的字段权限控制,可以控制字段可见及API是否返回字段值
|
||||
* 完整API鉴权,可以控制角色可访问的API资源,及模块功能字段可见及是否返回,请参考:[按角色授权API资源](http://doc.openauth.net.cn/core/apiauth.html#%E6%8C%89%E8%A7%92%E8%89%B2%E6%8E%88%E6%9D%83api%E8%B5%84%E6%BA%90) 及 [字段权限](http://doc.openauth.net.cn/core/datapropertyrule.html)
|
||||
|
||||
* 可拖拽的表单设计。详情:[可拖拽表单](http://doc.openauth.net.cn/pro/dragform.html)
|
||||
|
||||
@@ -41,7 +41,7 @@ gitee上面两个版本。其中:
|
||||
|
||||
* 全网最好用的打印解决方案。详情:[智能打印](http://doc.openauth.net.cn/pro/printerplan.html)
|
||||
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能,请参考:[定时任务](http://doc.openauth.net.cn/core/job.html)
|
||||
|
||||
* 基于CodeSmith的代码生成功能,可快速生成带有头/明细结构的页面
|
||||
|
||||
@@ -51,7 +51,7 @@ gitee上面两个版本。其中:
|
||||
|
||||
* 支持多租户
|
||||
|
||||
* 集成IdentityServer4,实现基于OAuth2的登录体系
|
||||
* 支持搭建自己的IdentityServer服务器,实现基于OAuth2的登录体系,请参考:[登录认证及OAuth集成](http://doc.openauth.net.cn/core/identity.html)
|
||||
|
||||
* 建立三方对接规范,已有系统可以无缝对接流程引擎
|
||||
|
||||
|
||||
@@ -30,6 +30,15 @@ Host: localhost:52789
|
||||
X-Token: e4a5aa00
|
||||
|
||||
```
|
||||
## 按角色授权API资源
|
||||
|
||||
目前主流的接口平台都提供按角色(或账号)授权访问API的功能,OpenAuth.Net也不例外。在OpenAuth.Net中,接口API被当作资源处理。如图:
|
||||
|
||||

|
||||
|
||||
如果后端新增或删除API,点击【同步系统API资源】按钮,即可同步到资源列表中。在角色管理功能中,可以对登录的角色进行API资源授权。
|
||||
|
||||

|
||||
|
||||
## 不登录直接访问
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
# 字段权限
|
||||
|
||||
::: warning 注意
|
||||
@@ -59,7 +60,7 @@ return result;
|
||||
var columns = data.columnFields.filter(u => u.IsList ===true).map(function (e) {
|
||||
return {
|
||||
field: e.ColumnName,
|
||||
title: e.Comment
|
||||
title: e.Remark
|
||||
};
|
||||
});
|
||||
columns.unshift({
|
||||
|
||||
@@ -63,11 +63,11 @@ CodeSmith Generator Studio 8.0或以上
|
||||
|
||||
如下图,使用CodeSmith文件夹中的模板,右击【WebGenerate.cst】--【Execute】,选择需要生成的表(本文以Stock为例)及相关的上下文命名空间,点击【Generate】
|
||||
|
||||

|
||||

|
||||
|
||||
生成成功后,在CodeSmith/Csharp文件夹下面会有相关的界面代码,如下图:
|
||||
|
||||

|
||||

|
||||
|
||||
Controllers、Views直接覆盖到OpenAuth.Mvc项目中对应的文件夹即可
|
||||
|
||||
@@ -83,12 +83,12 @@ userJs直接覆盖到OpenAuth.Mvc/wwwroot中
|
||||
因为生成的Controller名称类似XXXsController,所以模块的Url地址应该是XXXs/Index
|
||||
:::
|
||||
|
||||
并为它添加菜单,这里我只添加一个菜单【btnAdd】,如下图:
|
||||
添加模块时,系统会自动添加三个默认菜单【添加】【编辑】【删除】。可根据需要调整。这里我再添加一个菜单【btnCancel】,如下图:
|
||||
|
||||

|
||||

|
||||
|
||||
重新登录系统,即可看到新加的仓储管理模块。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#### IsFinish:流程的当前状态
|
||||
|
||||
- -1 草稿/召回:流程发起人主动撤销流程;【新增】
|
||||
- -1 草稿/召回:流程发起人主动召回流程;
|
||||
|
||||
- 0 正在运行;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
- 4 驳回:流程结束,可能发起的流程内容有问题,要求被驳回重新提交;
|
||||
|
||||
|
||||
#### ActivityId: 当前活动节点,即待审批的节点
|
||||
|
||||
#### ActivityType:当前节点的类型
|
||||
|
||||
- -1 无法运行,
|
||||
@@ -121,3 +123,11 @@
|
||||
- 3:开始节点,即type为:‘start’;
|
||||
|
||||
- 4:流程运行结束,即type为’end’;
|
||||
|
||||
与流程实例密切相关的还有两个表:流程实例的操作记录FlowInstanceOperationHistory及流转记录FlowInstanceTransitionHistory。它们有不同的作用:
|
||||
|
||||
### 操作记录FlowInstanceOperationHistory
|
||||
该表记录了流程实例的所有操作记录,包括流程的创建、撤回、驳回、同意、不同意等操作。
|
||||
|
||||
### 流转记录FlowInstanceTransitionHistory
|
||||
记录某个流程实例所有已审批的从一个活动节点到下一个活动节点的操作人、操作时间。
|
||||
@@ -38,6 +38,25 @@ OpenAuth.Net支持两种登录认证方式:自定义token认证和基于Identi
|
||||
|
||||
当启用了Identity时,客户端调用API需要先通过OpenAuth.IdentityServer服务器的OAuth验证,才能调用接口。OpenAuth.Net调用API的客户端有两种:
|
||||
|
||||
#### OpenAuth.Pro vue3
|
||||
|
||||
在使用企业版vue界面访问OpenAuth.WebApi时,已经在文件`.env.dev`中配置好相关选项,可以直接使用,无需其他处理。
|
||||
|
||||
```python
|
||||
VITE_OIDC_AUTHORITY = http://localhost:12796 #Identity服务器地址
|
||||
VITE_OIDC_CLIENTID = OpenAuth.Pro #客户端名称
|
||||
VITE_OIDC_REDIRECTURI = http://localhost:1803 #登录回调
|
||||
VITE_OIDC_RESPONSETYPE = code #认证方式
|
||||
VITE_OIDC_SCOPE = openid profile openauthapi #认证范围
|
||||
VITE_OIDC_AUTOMATICSILENTRENEW = true #自动续期
|
||||
|
||||
```
|
||||
如果服务端启用了Identity认证,则打开登录界面如下:
|
||||

|
||||
|
||||
这时点击登录超链接,操作同OpenAuth.Mvc一样。
|
||||
|
||||
|
||||
#### SwaggerUI
|
||||
|
||||
当我们启动了OpenAuth.WebApi,在浏览器打开[http://localhost:52789/swagger/index.html](http://localhost:52789/swagger/index.html)时,其实是Swagger框架给我们生成的一个调动客户端,对于启用了Identity的服务,Swagger会有一个Authorise的操作按钮:
|
||||
@@ -54,21 +73,6 @@ OpenAuth.Net支持两种登录认证方式:自定义token认证和基于Identi
|
||||
|
||||

|
||||
|
||||
#### 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
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
# 开发规范
|
||||
# 后端开发规范
|
||||
|
||||
## 新增数据库名称规范
|
||||
## 数据库表及字段命名
|
||||
|
||||
子系统名称+业务名称+表尾,其中表尾名称规则如下:
|
||||
SqlServer采用PascalCase命名,Oracle采用全大写命名,其他数据库采用camelCase命名。
|
||||
|
||||
::: tip 提示
|
||||
|
||||
开源版代码生成时,通过表结尾Dtbl来判断是否是生成明细表代码。因此建议数据库表命名时按:子系统名称+业务名称+表尾,其中表尾名称规则:
|
||||
- 基础主数据以Mst结尾;
|
||||
|
||||
- 普通业务表以Tbl结尾;
|
||||
|
||||
- 业务明细表以Dtbl结尾;
|
||||
|
||||
比如:
|
||||
|
||||
- WMS系统客户主数据表:WmsCustomerMst
|
||||
|
||||
- WMS系统入库订单头表:WmsInboundOrderTbl
|
||||
|
||||
- WMS系统入库订单明细表:WmsInboundOrderDtbl
|
||||
|
||||
如:WMS系统入库订单明细表:WmsInboundOrderDtbl
|
||||
:::
|
||||
|
||||
|
||||
## 数据库字段类型
|
||||
|
||||
@@ -10,11 +10,11 @@ OpenAuth.Pro封装了一些组件,方便开发使用,组件全部在`src\com
|
||||
|
||||
静态字典。根据【字典分类】模块的`分类标识`关键字获取,如:
|
||||
```html
|
||||
<auth-select :isEdit="isEdit" @change="change" :data-source="'SYS_STATUS'" v-model="val" size="mini"></auth-select>
|
||||
<auth-select :isEdit="isEdit" @change="change" :data-source="'SYS_STATUS'" v-model="val" size="small"></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>
|
||||
<auth-select :default-props="{label:'name', value:'id'}" :isEdit="isEdit" @change="change" :type="'dynamic'" :data-source="'/CategoryTypes/Load'" v-model="val" size="small"></auth-select>
|
||||
```
|
||||
|
||||
该组件有以下几个参数:
|
||||
|
||||
1271
数据库脚本/MySql.sql
1271
数据库脚本/MySql.sql
File diff suppressed because it is too large
Load Diff
3228
数据库脚本/postgreSql.sql
3228
数据库脚本/postgreSql.sql
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user