using JNPF.Common.Core.Manager;
using JNPF.Common.Core.Manager.Files;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Filter;
using JNPF.Common.Security;
using JNPF.DependencyInjection;
using JNPF.DynamicApiController;
using JNPF.FriendlyException;
using JNPF.Systems.Entitys.Model.DataBase;
using JNPF.Systems.Entitys.Permission;
using JNPF.Systems.Entitys.System;
using JNPF.VisualDev.Engine.Core;
using JNPF.VisualDev.Engine.Model;
using JNPF.VisualDev.Interfaces;
using JNPF.WorkFlow.Entitys.Dto.FlowEngine;
using JNPF.WorkFlow.Entitys.Dto.FlowForm;
using JNPF.WorkFlow.Entitys.Entity;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
namespace JNPF.WorkFlow.Service;
///
/// 流程设计.
///
[ApiDescriptionSettings(Tag = "FlowForm", Name = "Form", Order = 301)]
[Route("api/flowForm/Form")]
public class FlowFormService : IDynamicApiController, ITransient
{
private readonly ISqlSugarRepository _repository;
private readonly IRunService _runService;
private readonly IVisualDevService _visualDevService;
private readonly IUserManager _userManager;
private readonly IFileManager _fileManager;
private readonly IDataBaseManager _dataBaseManager;
private readonly ITenant _db;
public FlowFormService(
ISqlSugarRepository repository,
IRunService runService,
IVisualDevService visualDevService,
IUserManager userManager,
IFileManager fileManager,
IDataBaseManager dataBaseManager,
ISqlSugarClient context)
{
_repository = repository;
_runService = runService;
_visualDevService = visualDevService;
_userManager = userManager;
_fileManager = fileManager;
_dataBaseManager = dataBaseManager;
_db = context.AsTenant();
}
#region GET
///
/// 列表.
///
/// 请求参数.
///
[HttpGet("")]
public async Task GetList([FromQuery] FlowEngineListInput input)
{
var list = await _repository.AsQueryable()
.Where(a => a.DeleteMark == null && !(a.FormType == 2 && a.FlowType == 1))
.WhereIF(input.category.IsNotEmptyOrNull(), a => a.Category == input.category)
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
.Select(a => new FlowFormListOutput
{
id = a.Id,
creatorTime = a.CreatorTime,
creatorUser = SqlFunc.Subqueryable().Where(u => u.Id == a.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)),
enCode = a.EnCode,
enabledMark = a.EnabledMark,
fullName = a.FullName,
formType = a.FormType,
flowType = a.FlowType,
lastModifyTime = a.LastModifyTime,
sortCode = a.SortCode,
}).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc)
.OrderByIF(!string.IsNullOrEmpty(input.keyword), t => t.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize);
return PageResult.SqlSugarPageResult(list);
}
///
/// 信息.
///
/// 主键值.
///
[HttpGet("{id}")]
public async Task GetInfo_Api(string id)
{
var entity = await GetInfo(id);
var res = entity.Adapt();
var draft = entity.DraftJson?.ToObject().Adapt();
res.propertyJson = entity.PropertyJson;
res.draftJson = draft != null && draft.propertyJson.IsNotEmptyOrNull() ? draft?.propertyJson : entity.PropertyJson;
return res;
}
///
/// 列表(下拉).
///
/// (预留字段).
///
[HttpGet("Select")]
public async Task Select([FromQuery] FlowEngineListInput input)
{
var list = await _repository.AsSugarClient().Queryable()
.Where(a => a.DeleteMark == null && a.EnabledMark.Equals(1) && a.FlowType == input.flowType)
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
.Select(a => new FlowFormListOutput
{
category = SqlFunc.Subqueryable().Where(it => it.EnCode.Equals(a.Category)).Select(it => it.FullName),
id = a.Id,
description = a.Description,
creatorTime = a.CreatorTime,
enCode = a.EnCode,
enabledMark = a.EnabledMark,
fullName = a.FullName,
formType = a.FormType,
flowType = a.FlowType,
sortCode = a.SortCode,
}).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize);
return PageResult.SqlSugarPageResult(list);
}
///
/// 导出.
///
///
///
[HttpGet("{id}/Actions/ExportData")]
public async Task ActionsExport(string id)
{
var info = await GetInfo(id);
info.DraftJson = info.ToJsonString();
var jsonStr = info.ToJsonString();
return await _fileManager.Export(jsonStr, info.FullName, ExportFileType.fff);
}
///
/// 复制.
///
/// 主键值.
///
[HttpGet("{id}/Actions/Copy")]
public async Task ActionsCopy(string id)
{
var entity = await GetInfo(id);
var random = RandomExtensions.NextLetterAndNumberString(new Random(), 5).ToLower();
entity.Id = SnowflakeIdHelper.NextId();
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
throw Oops.Oh(ErrorCode.COM1009);
entity.EnabledMark = 0;
//entity.TableJson = "[]";
entity.DraftJson = entity.ToJsonString();
entity.LastModifyTime = null;
var result = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync();
_ = result ?? throw Oops.Oh(ErrorCode.WF0002);
}
///
/// 根据表单Id 获取流程信息.
///
/// 主键值.
///
[HttpGet("GetFormById/{id}")]
public async Task GetFormById(string id)
{
var model = new { id = string.Empty, enCode = string.Empty, enabledMark = 0 };
var form = await GetInfo(id);
if (form == null) throw Oops.Oh(ErrorCode.COM1019);
if (form != null && form.FlowId.IsNotEmptyOrNull())
model = _repository.AsSugarClient().Queryable().Where(x => x.Id.Equals(form.FlowId)).Select(x => new { id = x.Id, enCode = x.EnCode, enabledMark = (int)x.EnabledMark }).First();
if (model == null || model.id.IsNullOrEmpty()) throw Oops.Oh(ErrorCode.COM1016);
if (form.FlowType == 1 && form.FormType == 1 && model.enabledMark != 1)
{
// 代码生成的功能流程需要判断流程是否启用。
throw Oops.Oh(ErrorCode.COM1017);
}
return model;
}
#endregion
#region POST
///
/// 删除.
///
/// 主键值.
///
[HttpDelete("{id}")]
public async Task Delete(string id)
{
var flowFormEntity = await GetInfo(id);
if (flowFormEntity == null)
throw Oops.Oh(ErrorCode.COM1005);
if (await _repository.AsSugarClient().Queryable().Where(x => x.FormId.Equals(id)).AnyAsync())
throw Oops.Oh(ErrorCode.COM1012);
var isOk = await _repository.AsSugarClient().Updateable(flowFormEntity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync();
await _repository.AsSugarClient().Deleteable().Where(x => x.FormId.Equals(id)).ExecuteCommandAsync();
if (!isOk)
throw Oops.Oh(ErrorCode.COM1002);
}
///
/// 新建.
///
/// 请求参数.
///
[HttpPost("")]
public async Task Create([FromBody] FlowEngineCrInput input)
{
if (await _repository.IsAnyAsync(x => (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null))
throw Oops.Oh(ErrorCode.COM1004);
var flowFormEntity = input.Adapt();
flowFormEntity.Id = SnowflakeIdHelper.NextId();
flowFormEntity.EnabledMark = 0;
flowFormEntity.PropertyJson = flowFormEntity.DraftJson;
flowFormEntity.DraftJson = flowFormEntity.ToJsonString();
if (input.formType.Equals(2) && input.draftJson.IsNotEmptyOrNull())
{
TemplateParsingBase? tInfo = new TemplateParsingBase(flowFormEntity.PropertyJson, flowFormEntity.TableJson); // 解析模板
if (!tInfo.VerifyTemplate()) throw Oops.Oh(ErrorCode.D1401); // 验证模板
await VerifyPrimaryKeyPolicy(tInfo, flowFormEntity.DbLinkId); // 验证雪花Id 和自增长Id 主键是否支持
}
var result = await _repository.AsSugarClient().Insertable(flowFormEntity).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync();
_ = result ?? throw Oops.Oh(ErrorCode.COM1000);
}
///
/// 更新.
///
/// 主键值.
/// 请求参数.
///
[HttpPut("")]
public async Task Update([FromBody] FlowEngineUpInput input)
{
if (await _repository.IsAnyAsync(x => x.Id != input.id && (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null))
throw Oops.Oh(ErrorCode.COM1004);
if (await _repository.AsQueryable().AnyAsync(x => x.Id.Equals(input.id) && x.EnabledMark.Equals(1) && x.FormType == 2))
{
if (input.tableJson.IsNullOrWhiteSpace() || input.tableJson.Equals("[]"))
throw Oops.Oh(ErrorCode.D1416); // 已发布的模板 表不能为空.
input.enabledMark = 1;
}
var isOk = false;
var fEntity = input.Adapt();
if (fEntity != null)
{
if (input.formType.Equals(2) && input.draftJson.IsNotEmptyOrNull())
{
TemplateParsingBase? tInfo = new TemplateParsingBase(fEntity.DraftJson, fEntity.TableJson); // 解析模板
if (!tInfo.VerifyTemplate()) throw Oops.Oh(ErrorCode.D1401); // 验证模板
await VerifyPrimaryKeyPolicy(tInfo, fEntity.DbLinkId); // 验证雪花Id 和自增长Id 主键是否支持
}
// EnabledMark=0 未发布,EnabledMark=1 已发布
if (fEntity.EnabledMark.Equals(0))
{
fEntity.PropertyJson = fEntity.DraftJson;
fEntity.DraftJson = fEntity.ToJsonString();
// 修改流程表单
isOk = await _repository.AsSugarClient().Updateable(fEntity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
}
else
{
var nEntity = await _repository.AsSugarClient().Queryable().Where(x => x.Id.Equals(input.id)).FirstAsync();
fEntity.PropertyJson = fEntity.DraftJson;
nEntity.DraftJson = fEntity.ToJsonString();
nEntity.FullName = fEntity.FullName;
nEntity.EnCode = fEntity.EnCode;
nEntity.SortCode = fEntity.SortCode;
nEntity.Description = fEntity.Description;
nEntity.TableJson = fEntity.TableJson;
nEntity.DbLinkId = fEntity.DbLinkId;
nEntity.AppUrlAddress = fEntity.AppUrlAddress;
nEntity.UrlAddress = fEntity.UrlAddress;
nEntity.InterfaceUrl = fEntity.InterfaceUrl;
// 修改流程表单
isOk = await _repository.AsSugarClient().Updateable(nEntity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
}
}
if (!isOk)
throw Oops.Oh(ErrorCode.COM1001);
}
///
/// 导入.
///
///
///
[HttpPost("Actions/ImportData")]
public async Task ActionsImport(IFormFile file)
{
var fileType = Path.GetExtension(file.FileName).Replace(".", string.Empty);
if (!fileType.ToLower().Equals(ExportFileType.fff.ToString()))
throw Oops.Oh(ErrorCode.D3006);
var josn = _fileManager.Import(file);
var model = new FlowFormEntity();
try
{
model = josn.ToObject();
}
catch
{
throw Oops.Oh(ErrorCode.D3006);
}
if (model == null)
throw Oops.Oh(ErrorCode.D3006);
await ImportData(model);
}
///
/// 发布.
///
/// 主键值.
///
[HttpPost("Release/{id}")]
public async Task Release(string id, [FromQuery] int isRelease)
{
var entity = await GetInfo(id);
// 0 回滚表单 , 1 发布表单.
if (isRelease.Equals(0))
{
if (entity == null) throw Oops.Oh(ErrorCode.COM1005);
var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => it.DraftJson == entity.ToJsonString()).Where(it => it.Id == id).ExecuteCommandHasChangeAsync();
if (!isOk) throw Oops.Oh(ErrorCode.COM1003);
}
else
{
if (entity == null || entity.PropertyJson.IsNullOrEmpty()) throw Oops.Oh(ErrorCode.COM1013);
var newEntity = entity.DraftJson.ToObject();
if (newEntity == null)
{
newEntity = entity;
}
entity.TableJson = newEntity.TableJson;
entity.PropertyJson = newEntity.PropertyJson;
if (entity.FormType == 2)
{
// 无表转有表
if (entity.TableJson.IsNullOrEmpty() || entity.TableJson == "[]")
{
// 主表名称
var mTableName = "wf_" + entity.EnCode;
if (mTableName.Length > 24) mTableName = "wf_" + SnowflakeIdHelper.NextId();
var devEntity = new VisualDev.Entitys.VisualDevEntity()
{
Id = entity.Id,
State = 1,
WebType = 3,
EnableFlow = 1,
FullName = entity.FullName,
EnCode = entity.EnCode,
FormData = entity.PropertyJson
};
var res = await _visualDevService.NoTblToTable(devEntity, mTableName);
if (res == null) throw Oops.Oh(ErrorCode.COM1000);
entity.TableJson = res.Tables;
entity.PropertyJson = res.FormData;
//await _repository.AsSugarClient().Insertable(res).CallEntityMethod(m => m.Create()).ExecuteCommandAsync();
}
//else if (await _repository.AsSugarClient().Queryable().Where(x => x.Id.Equals(id)).AnyAsync())
//await _repository.AsSugarClient().Updateable().SetColumns(it => it.IsRelease == 1).Where(it => it.Id == id).ExecuteCommandHasChangeAsync();
}
var dbLink = await _runService.GetDbLink(newEntity.DbLinkId);
var MainTable = newEntity.TableJson.ToList().Find(m => m.typeId.Equals("1")); // 主表
if (MainTable != null)
{
if (!_dataBaseManager.IsAnyColumn(dbLink, MainTable?.table, "f_flowtaskid"))
{
var pFieldList = new List() { new DbTableFieldModel() { field = "F_FlowTaskId", fieldName = "流程任务Id", dataType = "varchar", dataLength = "50", allowNull = 1 } };
_dataBaseManager.AddTableColumn(dbLink, MainTable?.table, pFieldList);
}
if (!_dataBaseManager.IsAnyColumn(dbLink, MainTable?.table, "f_flowid"))
{
var pFieldList = new List() { new DbTableFieldModel() { field = "F_FlowId", fieldName = "流程引擎Id", dataType = "varchar", dataLength = "50", allowNull = 1 } };
_dataBaseManager.AddTableColumn(dbLink, MainTable?.table, pFieldList);
}
}
entity.DraftJson = entity.ToJsonString();
entity.EnabledMark = 1;
var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(x => x.LastModify()).ExecuteCommandHasChangeAsync();
if (!isOk) throw Oops.Oh(ErrorCode.COM1003);
}
}
///
/// 回滚.
///
/// 主键值.
///
[HttpPost("Stop/{id}")]
public async Task Stop(string id)
{
var entity = await GetInfo(id);
}
#endregion
#region PrivateMethod
///
/// 详情.
///
/// 主键.
///
[NonAction]
private async Task GetInfo(string id)
{
return await _repository.GetFirstAsync(a => a.Id == id && a.DeleteMark == null);
}
///
/// 导入数据.
///
/// 导入实例.
///
private async Task ImportData(FlowFormEntity entity)
{
if (await _repository.IsAnyAsync(x => (x.EnCode.Equals(entity.EnCode) || x.FullName.Equals(entity.FullName)) && x.DeleteMark == null)) throw Oops.Oh(ErrorCode.COM1004);
// 在线开发生成导入版本自带ID
//entity.Id = SnowflakeIdHelper.NextId();
try
{
_db.BeginTran();
// 存在更新不存在插入 根据主键
var stor = _repository.AsSugarClient().Storageable(entity).Saveable().ToStorage();
// 执行插入
await stor.AsInsertable.ExecuteCommandAsync();
// await stor.AsUpdateable.ExecuteCommandAsync(); //执行更新,停用原因:Oracle 数据库环境会抛异常:ora-01704: 字符串文字太长
// 执行更新
await _repository.AsSugarClient().Updateable(entity).ExecuteCommandAsync();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
throw Oops.Oh(ErrorCode.D3006);
}
}
///
/// 验证主键策略 数据库表是否支持.
///
/// 模板信息.
/// 数据库连接id.
private async Task VerifyPrimaryKeyPolicy(TemplateParsingBase tInfo, string dbLinkId)
{
if (tInfo.IsHasTable)
{
DbLinkEntity link = await _runService.GetDbLink(dbLinkId);
tInfo.AllTable.ForEach(item =>
{
var tableList = _dataBaseManager.GetFieldList(link, item.table); // 获取主表所有列
var mainPrimary = tableList.Find(t => t.primaryKey); // 主表主键
if (mainPrimary == null) throw Oops.Oh(ErrorCode.D1409, "主键为空", item.table);
if (tInfo.FormModel.primaryKeyPolicy.Equals(2) && !mainPrimary.identity)
{
throw Oops.Oh(ErrorCode.D1409, "自增长ID,没有自增标识", item.table);
}
if (tInfo.FormModel.primaryKeyPolicy.Equals(1) && !(mainPrimary.dataType.ToLower().Equals("string") || mainPrimary.dataType.ToLower().Equals("varchar") || mainPrimary.dataType.ToLower().Equals("nvarchar")))
throw Oops.Oh(ErrorCode.D1409, "雪花ID", item.table);
});
_dataBaseManager.ChangeDataBase(_dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName));
}
}
#endregion
}