mirror of
https://gitee.com/iioter/iotgateway.git
synced 2024-12-02 03:38:01 +08:00
添加前后端框架源码
This commit is contained in:
parent
8648886afd
commit
507b0c2114
Binary file not shown.
@ -45,7 +45,27 @@
|
|||||||
"ProjectGuid": "e5f79995-ab61-41f4-820d-ba39967b406b",
|
"ProjectGuid": "e5f79995-ab61-41f4-820d-ba39967b406b",
|
||||||
"DisplayName": "PluginInterface",
|
"DisplayName": "PluginInterface",
|
||||||
"ColorIndex": 7
|
"ColorIndex": 7
|
||||||
|
},
|
||||||
|
"c2672620-8e65-486c-b967-c4c673f8da0f": {
|
||||||
|
"ProjectGuid": "c2672620-8e65-486c-b967-c4c673f8da0f",
|
||||||
|
"DisplayName": "WalkingTec.Mvvm.Core",
|
||||||
|
"ColorIndex": 8
|
||||||
|
},
|
||||||
|
"b370f699-965b-4d86-93b1-0f022c95b5c9": {
|
||||||
|
"ProjectGuid": "b370f699-965b-4d86-93b1-0f022c95b5c9",
|
||||||
|
"DisplayName": "WalkingTec.Mvvm.Mvc",
|
||||||
|
"ColorIndex": 9
|
||||||
|
},
|
||||||
|
"81cbfd0e-1d89-440a-8cc3-e32672504ff4": {
|
||||||
|
"ProjectGuid": "81cbfd0e-1d89-440a-8cc3-e32672504ff4",
|
||||||
|
"DisplayName": "WalkingTec.Mvvm.TagHelpers.LayUI",
|
||||||
|
"ColorIndex": 10
|
||||||
|
},
|
||||||
|
"402e5b3a-ad95-4b6a-a4b0-c8ffcbf494c3": {
|
||||||
|
"ProjectGuid": "402e5b3a-ad95-4b6a-a4b0-c8ffcbf494c3",
|
||||||
|
"DisplayName": "test",
|
||||||
|
"ColorIndex": 11
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"NextColorIndex": 8
|
"NextColorIndex": 12
|
||||||
}
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6,13 +6,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="WalkingTec.Mvvm.Core" Version="5.7.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Plugins\PluginInterface\PluginInterface.csproj" />
|
<ProjectReference Include="..\Plugins\PluginInterface\PluginInterface.csproj" />
|
||||||
|
<ProjectReference Include="..\WalkingTec.Mvvm\WalkingTec.Mvvm.Core\WalkingTec.Mvvm.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
@ -21,6 +21,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Drivers", "Drivers", "{52D9
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DriverModbusTCP", "Plugins\Drivers\DriverModbusTCP\DriverModbusTCP.csproj", "{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DriverModbusTCP", "Plugins\Drivers\DriverModbusTCP\DriverModbusTCP.csproj", "{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WalkingTec.Mvvm", "WalkingTec.Mvvm", "{98B1C9F0-028C-48D8-8148-54B69CCA4590}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalkingTec.Mvvm.Core", "WalkingTec.Mvvm\WalkingTec.Mvvm.Core\WalkingTec.Mvvm.Core.csproj", "{C2672620-8E65-486C-B967-C4C673F8DA0F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalkingTec.Mvvm.Mvc", "WalkingTec.Mvvm\WalkingTec.Mvvm.Mvc\WalkingTec.Mvvm.Mvc.csproj", "{B370F699-965B-4D86-93B1-0F022C95B5C9}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalkingTec.Mvvm.TagHelpers.LayUI", "WalkingTec.Mvvm\WalkingTec.Mvvm.TagHelpers.LayUI\WalkingTec.Mvvm.TagHelpers.LayUI.csproj", "{81CBFD0E-1D89-440A-8CC3-E32672504FF4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -55,6 +63,18 @@ Global
|
|||||||
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C2672620-8E65-486C-B967-C4C673F8DA0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C2672620-8E65-486C-B967-C4C673F8DA0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C2672620-8E65-486C-B967-C4C673F8DA0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C2672620-8E65-486C-B967-C4C673F8DA0F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B370F699-965B-4D86-93B1-0F022C95B5C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B370F699-965B-4D86-93B1-0F022C95B5C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B370F699-965B-4D86-93B1-0F022C95B5C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B370F699-965B-4D86-93B1-0F022C95B5C9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{81CBFD0E-1D89-440A-8CC3-E32672504FF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{81CBFD0E-1D89-440A-8CC3-E32672504FF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{81CBFD0E-1D89-440A-8CC3-E32672504FF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{81CBFD0E-1D89-440A-8CC3-E32672504FF4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -64,6 +84,9 @@ Global
|
|||||||
{E5F79995-AB61-41F4-820D-BA39967B406B} = {FBED048F-7AB9-4348-AD56-F9BF4D9E3A55}
|
{E5F79995-AB61-41F4-820D-BA39967B406B} = {FBED048F-7AB9-4348-AD56-F9BF4D9E3A55}
|
||||||
{52D96C24-2F2F-49B5-9F29-00414DEA41D8} = {FBED048F-7AB9-4348-AD56-F9BF4D9E3A55}
|
{52D96C24-2F2F-49B5-9F29-00414DEA41D8} = {FBED048F-7AB9-4348-AD56-F9BF4D9E3A55}
|
||||||
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD} = {52D96C24-2F2F-49B5-9F29-00414DEA41D8}
|
{7B432FC9-57E6-44BF-B8A7-2A1FB31D6ADD} = {52D96C24-2F2F-49B5-9F29-00414DEA41D8}
|
||||||
|
{C2672620-8E65-486C-B967-C4C673F8DA0F} = {98B1C9F0-028C-48D8-8148-54B69CCA4590}
|
||||||
|
{B370F699-965B-4D86-93B1-0F022C95B5C9} = {98B1C9F0-028C-48D8-8148-54B69CCA4590}
|
||||||
|
{81CBFD0E-1D89-440A-8CC3-E32672504FF4} = {98B1C9F0-028C-48D8-8148-54B69CCA4590}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {1F219808-E6E8-4C1D-B846-41F2F7CF20FA}
|
SolutionGuid = {1F219808-E6E8-4C1D-B846-41F2F7CF20FA}
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.13" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.13" />
|
||||||
<PackageReference Include="WalkingTec.Mvvm.TagHelpers.LayUI" Version="5.7.0" />
|
|
||||||
<PackageReference Include="WalkingTec.Mvvm.Mvc" Version="5.7.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -25,6 +23,8 @@
|
|||||||
<ProjectReference Include="..\IoTGateway.DataAccess\IoTGateway.DataAccess.csproj" />
|
<ProjectReference Include="..\IoTGateway.DataAccess\IoTGateway.DataAccess.csproj" />
|
||||||
<ProjectReference Include="..\IoTGateway.ViewModel\IoTGateway.ViewModel.csproj" />
|
<ProjectReference Include="..\IoTGateway.ViewModel\IoTGateway.ViewModel.csproj" />
|
||||||
<ProjectReference Include="..\Plugins\Plugin\Plugin.csproj" />
|
<ProjectReference Include="..\Plugins\Plugin\Plugin.csproj" />
|
||||||
|
<ProjectReference Include="..\WalkingTec.Mvvm\WalkingTec.Mvvm.Mvc\WalkingTec.Mvvm.Mvc.csproj" />
|
||||||
|
<ProjectReference Include="..\WalkingTec.Mvvm\WalkingTec.Mvvm.TagHelpers.LayUI\WalkingTec.Mvvm.TagHelpers.LayUI.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标记Controller和Action的描述
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class ActionDescriptionAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 描述
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string ClassFullName { get; set; }
|
||||||
|
public bool IsPage { get; set; }
|
||||||
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 新建一个描述
|
||||||
|
/// </summary>
|
||||||
|
public ActionDescriptionAttribute(string desc)
|
||||||
|
{
|
||||||
|
this.Description = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionDescriptionAttribute(string desc, string classFullName)
|
||||||
|
{
|
||||||
|
this.Description = desc;
|
||||||
|
this.ClassFullName = classFullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionDescriptionAttribute(string desc, string classFullName, bool ispage)
|
||||||
|
{
|
||||||
|
this.Description = desc;
|
||||||
|
this.ClassFullName = classFullName;
|
||||||
|
this.IsPage = ispage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLoccalizer(Type controllertype)
|
||||||
|
{
|
||||||
|
_localizer = Core.CoreProgram._localizer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标记Controller或Action不受权限控制,只要登录任何人都可访问
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class AllRightsAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class DebugOnlyAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public enum DBOperationEnum { Default, Read, Write }
|
||||||
|
/// <summary>
|
||||||
|
/// 标记Controller或Action使用固定的连接字符串,不受其他设定控制
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class FixConnectionAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 连接字符串名称
|
||||||
|
/// </summary>
|
||||||
|
public string CsName { get; set; }
|
||||||
|
|
||||||
|
public DBTypeEnum? DbType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 操作类型,读或写
|
||||||
|
/// </summary>
|
||||||
|
public DBOperationEnum Operation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新建固定连接字符串标记
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Operation">Operation</param>
|
||||||
|
/// <param name="CsName">the key of the ConnectionString in appsettings</param>
|
||||||
|
public FixConnectionAttribute(DBOperationEnum Operation = DBOperationEnum.Default, string CsName = "")
|
||||||
|
{
|
||||||
|
this.CsName = CsName;
|
||||||
|
this.Operation = Operation;
|
||||||
|
this.DbType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 操作类型,读或写
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="DbType">the database type, if t is Default, the value in appsettings will be used</param>
|
||||||
|
/// <param name="Operation">Operation</param>
|
||||||
|
/// <param name="CsName">the key of the ConnectionString in appsettings</param>
|
||||||
|
public FixConnectionAttribute(DBTypeEnum DbType, DBOperationEnum Operation = DBOperationEnum.Default, string CsName = "")
|
||||||
|
{
|
||||||
|
this.CsName = CsName;
|
||||||
|
this.Operation = Operation;
|
||||||
|
this.DbType = DbType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Attributes
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标记某个Model是一个多对多的中间表
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class MiddleTableAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class NoLogAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
//[Obsolete("已废弃,预计v3.0版本及v2.10版本开始将删除")]
|
||||||
|
/// <summary>
|
||||||
|
/// 标记Action返回的为公共页面,跳过权限验证,不需要登录即可访问
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class PublicAttribute : Attribute, IAllowAnonymous
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public enum ReInitModes { FAILEDONLY, SUCCESSONLY, ALWAYS }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标记VM中的ReInit方法是在提交错误时触发,提交成功时触发,或是都触发。这是为了一些特殊逻辑的VM设计的
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class ReInitAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 触发模式
|
||||||
|
/// </summary>
|
||||||
|
public ReInitModes ReInitMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新建触发标记
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mode">触发模式</param>
|
||||||
|
public ReInitAttribute(ReInitModes mode)
|
||||||
|
{
|
||||||
|
this.ReInitMode = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
public class ValidateFormItemOnlyAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
419
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseBatchVM.cs
Normal file
419
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseBatchVM.cs
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
using WalkingTec.Mvvm.Core.Support.FileHandlers;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 批量操作VM接口
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEditModel">批量修改的VM</typeparam>
|
||||||
|
public interface IBaseBatchVM<out TEditModel>
|
||||||
|
where TEditModel : BaseVM
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 批量修改的VM
|
||||||
|
/// </summary>
|
||||||
|
TEditModel LinkedVM { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量列表VM
|
||||||
|
/// </summary>
|
||||||
|
IBasePagedListVM<TopBasePoco, ISearcher> ListVM { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列表数据的Id数组
|
||||||
|
/// </summary>
|
||||||
|
//IEnumerable<Guid> Ids { get; set; }
|
||||||
|
string[] Ids { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量操作的错误
|
||||||
|
/// </summary>
|
||||||
|
Dictionary<string, string> ErrorMessage { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量操作的基础VM,所有批量操作的VM应继承本类
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TModel">批量修改的VM</typeparam>
|
||||||
|
/// <typeparam name="TLinkModel">批量列表VM</typeparam>
|
||||||
|
public class BaseBatchVM<TModel, TLinkModel> : BaseVM, IBaseBatchVM<TLinkModel> where TModel : TopBasePoco,new() where TLinkModel : BaseVM
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 批量修改的VM
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public TLinkModel LinkedVM { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量列表VM
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public IBasePagedListVM<TopBasePoco, ISearcher> ListVM { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量操作的错误
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public Dictionary<string, string> ErrorMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列表数据的Id数组
|
||||||
|
/// </summary>
|
||||||
|
public string[] Ids { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
public BaseBatchVM()
|
||||||
|
{
|
||||||
|
//this.Ids = new List<Guid>();
|
||||||
|
ErrorMessage = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加错误信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">错误</param>
|
||||||
|
/// <param name="id">数据Id</param>
|
||||||
|
protected void SetExceptionMessage(Exception e, string id)
|
||||||
|
{
|
||||||
|
if (id != null)
|
||||||
|
{
|
||||||
|
ErrorMessage.Add(id, e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否可以删除,当进行批量删除操作时会调用本函数。子类如果有特殊判断应重载本函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">数据Id</param>
|
||||||
|
/// <param name="errorMessage">错误信息</param>
|
||||||
|
/// <returns>true代表可以删除,false代表不能删除</returns>
|
||||||
|
protected virtual bool CheckIfCanDelete(object id, out string errorMessage)
|
||||||
|
{
|
||||||
|
errorMessage = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量删除,默认对Ids中包含的主键的数据进行删除。子类如果有特殊判断应重载本函数
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true代表成功,false代表失败</returns>
|
||||||
|
public virtual bool DoBatchDelete()
|
||||||
|
{
|
||||||
|
bool rv = true;
|
||||||
|
//循环所有数据Id
|
||||||
|
List<string> idsData = Ids.ToList();
|
||||||
|
var modelType = typeof(TModel);
|
||||||
|
var pros = modelType.GetAllProperties();
|
||||||
|
//如果包含附件,则先删除附件
|
||||||
|
List<Guid> fileids = new List<Guid>();
|
||||||
|
var fa = pros.Where(x => x.PropertyType == typeof(FileAttachment) || typeof(TopBasePoco).IsAssignableFrom(x.PropertyType)).ToList();
|
||||||
|
var isPersist =typeof(IPersistPoco).IsAssignableFrom(modelType);
|
||||||
|
var isBasePoco = typeof(IBasePoco).IsAssignableFrom(modelType);
|
||||||
|
var query = DC.Set<TModel>().AsQueryable();
|
||||||
|
var fas = pros.Where(x => typeof(IEnumerable<ISubFile>).IsAssignableFrom(x.PropertyType)).ToList();
|
||||||
|
foreach (var f in fas)
|
||||||
|
{
|
||||||
|
query = query.Include(f.Name);
|
||||||
|
}
|
||||||
|
query = query.AsNoTracking().CheckIDs(idsData);
|
||||||
|
var entityList = query.ToList();
|
||||||
|
for (int i = 0; i < entityList.Count; i++)
|
||||||
|
{
|
||||||
|
string checkErro = null;
|
||||||
|
//检查是否可以删除,如不能删除则直接跳过
|
||||||
|
if (CheckIfCanDelete(idsData[i], out checkErro) == false)
|
||||||
|
{
|
||||||
|
ErrorMessage.Add(idsData[i], checkErro);
|
||||||
|
rv = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//进行删除
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var Entity = entityList[i];
|
||||||
|
if (isPersist)
|
||||||
|
{
|
||||||
|
(Entity as IPersistPoco).IsValid = false;
|
||||||
|
DC.UpdateProperty(Entity, "IsValid");
|
||||||
|
if (isBasePoco)
|
||||||
|
{
|
||||||
|
(Entity as IBasePoco).UpdateTime = DateTime.Now;
|
||||||
|
(Entity as IBasePoco).UpdateBy = LoginUserInfo.ITCode;
|
||||||
|
DC.UpdateProperty(Entity, "UpdateTime");
|
||||||
|
DC.UpdateProperty(Entity, "UpdateBy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach (var f in fa)
|
||||||
|
{
|
||||||
|
if (f.PropertyType == typeof(FileAttachment))
|
||||||
|
{
|
||||||
|
string fidfield = DC.GetFKName2(modelType, f.Name);
|
||||||
|
var fidpro = pros.Where(x => x.Name == fidfield).FirstOrDefault();
|
||||||
|
var idresult = fidpro.GetValue(Entity);
|
||||||
|
if(idresult != null)
|
||||||
|
{
|
||||||
|
Guid fid = Guid.Empty;
|
||||||
|
if(Guid.TryParse(idresult.ToString(), out fid) == true)
|
||||||
|
{
|
||||||
|
fileids.Add(fid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.SetValue(Entity, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var f in fas)
|
||||||
|
{
|
||||||
|
var subs = f.GetValue(Entity) as IEnumerable<ISubFile>;
|
||||||
|
if (subs != null)
|
||||||
|
{
|
||||||
|
foreach (var sub in subs)
|
||||||
|
{
|
||||||
|
fileids.Add(sub.FileId);
|
||||||
|
}
|
||||||
|
f.SetValue(Entity, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof(TModel) != typeof(FileAttachment))
|
||||||
|
{
|
||||||
|
foreach (var pro in pros)
|
||||||
|
{
|
||||||
|
if (pro.PropertyType.GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)))
|
||||||
|
{
|
||||||
|
pro.SetValue(Entity, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DC.DeleteEntity(Entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
SetExceptionMessage(e, idsData[i]);
|
||||||
|
rv = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//进行数据库的删除操作
|
||||||
|
if (rv == true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DC.SaveChanges();
|
||||||
|
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
|
||||||
|
foreach (var item in fileids)
|
||||||
|
{
|
||||||
|
fp.DeleteFile(item.ToString(), DC.ReCreate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
SetExceptionMessage(e, null);
|
||||||
|
rv = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果失败,添加错误信息
|
||||||
|
if (rv == false)
|
||||||
|
{
|
||||||
|
if (ErrorMessage.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var id in idsData)
|
||||||
|
{
|
||||||
|
if (!ErrorMessage.ContainsKey(id))
|
||||||
|
{
|
||||||
|
ErrorMessage.Add(id, CoreProgram._localizer?["Sys.Rollback"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListVM?.DoSearch();
|
||||||
|
if (ListVM != null)
|
||||||
|
{
|
||||||
|
foreach (var item in ListVM?.GetEntityList())
|
||||||
|
{
|
||||||
|
item.BatchError = ErrorMessage.Where(x => x.Key == item.GetID().ToString()).Select(x => x.Value).FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MSD.AddModelError("", CoreProgram._localizer?["Sys.DataCannotDelete"]);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量修改,默认对Ids中包含的数据进行修改,子类如果有特殊判断应重载本函数
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true代表成功,false代表失败</returns>
|
||||||
|
public virtual bool DoBatchEdit()
|
||||||
|
{
|
||||||
|
//获取批量修改VM的所有属性
|
||||||
|
var pros = LinkedVM.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
|
||||||
|
bool rv = true;
|
||||||
|
List<string> idsData = Ids.ToList();
|
||||||
|
string currentvmname = this.GetType().Name;
|
||||||
|
Type vmtype = null;
|
||||||
|
//找到对应的BaseCRUDVM,并初始化
|
||||||
|
if (currentvmname.ToLower().Contains("apibatchvm"))
|
||||||
|
{
|
||||||
|
vmtype = this.GetType().Assembly.GetExportedTypes().Where(x => x.IsSubclassOf(typeof(BaseCRUDVM<TModel>)) && x.Name.ToLower().Contains("apivm") == true).FirstOrDefault();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vmtype = this.GetType().Assembly.GetExportedTypes().Where(x => x.IsSubclassOf(typeof(BaseCRUDVM<TModel>)) && x.Name.ToLower().Contains("apivm") == false).FirstOrDefault();
|
||||||
|
}
|
||||||
|
IBaseCRUDVM<TModel> vm = null;
|
||||||
|
if (vmtype != null)
|
||||||
|
{
|
||||||
|
vm = vmtype.GetConstructor(System.Type.EmptyTypes).Invoke(null) as IBaseCRUDVM<TModel>;
|
||||||
|
vm.CopyContext(this);
|
||||||
|
}
|
||||||
|
var entityList = DC.Set<TModel>().CheckIDs(idsData).ToList();
|
||||||
|
//循环所有数据
|
||||||
|
for (int i = 0; i < entityList.Count; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//如果找不到对应数据,则输出错误
|
||||||
|
TModel entity = entityList[i];
|
||||||
|
if (vm != null)
|
||||||
|
{
|
||||||
|
vm.SetEntity(entity);
|
||||||
|
}
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
ErrorMessage.Add(idsData[i], CoreProgram._localizer?["Sys.DataNotExist"]);
|
||||||
|
rv = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//如果能找到,则循环LinkedVM中的属性,给entity中同名属性赋值
|
||||||
|
foreach (var pro in pros)
|
||||||
|
{
|
||||||
|
var proToSet = entity.GetType().GetSingleProperty(pro.Name);
|
||||||
|
var val = FC.ContainsKey("LinkedVM." + pro.Name) ? FC["LinkedVM." + pro.Name] : null;
|
||||||
|
if(val == null && FC.ContainsKey("LinkedVM." + pro.Name + "[]"))
|
||||||
|
{
|
||||||
|
val = FC["LinkedVM." + pro.Name + "[]"];
|
||||||
|
}
|
||||||
|
if (proToSet != null && val != null)
|
||||||
|
{
|
||||||
|
var hasvalue = true;
|
||||||
|
if ( val is StringValues sv && StringValues.IsNullOrEmpty(sv) == true)
|
||||||
|
{
|
||||||
|
hasvalue = false;
|
||||||
|
}
|
||||||
|
if (hasvalue)
|
||||||
|
{
|
||||||
|
proToSet.SetValue(entity, pro.GetValue(LinkedVM));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//调用controller方法验证model
|
||||||
|
//try
|
||||||
|
//{
|
||||||
|
// Controller.GetType().GetMethod("RedoValidation").Invoke(Controller, new object[] { entity });
|
||||||
|
//}
|
||||||
|
//catch { }
|
||||||
|
//如果有对应的BaseCRUDVM则使用其进行数据验证
|
||||||
|
if (vm != null)
|
||||||
|
{
|
||||||
|
vm.Validate();
|
||||||
|
var errors = vm.MSD;
|
||||||
|
if (errors != null && errors.Count > 0)
|
||||||
|
{
|
||||||
|
var error = "";
|
||||||
|
foreach (var key in errors.Keys)
|
||||||
|
{
|
||||||
|
if (errors[key].Count > 0)
|
||||||
|
{
|
||||||
|
error += errors[key].Select(x => x.ErrorMessage).ToSepratedString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error != "")
|
||||||
|
{
|
||||||
|
ErrorMessage.Add(idsData[i], error);
|
||||||
|
rv = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof(IBasePoco).IsAssignableFrom( typeof(TModel)))
|
||||||
|
{
|
||||||
|
IBasePoco ent = entity as IBasePoco;
|
||||||
|
if (ent.UpdateTime == null)
|
||||||
|
{
|
||||||
|
ent.UpdateTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(ent.UpdateBy))
|
||||||
|
{
|
||||||
|
ent.UpdateBy = LoginUserInfo?.ITCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DC.UpdateEntity(entity);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
SetExceptionMessage(e, idsData[i]);
|
||||||
|
rv = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//进行数据库的修改操作
|
||||||
|
if (rv == true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DC.SaveChanges();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
SetExceptionMessage(e, null);
|
||||||
|
rv = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果有错误,输出错误信息
|
||||||
|
if (rv == false)
|
||||||
|
{
|
||||||
|
if (ErrorMessage.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var id in idsData)
|
||||||
|
{
|
||||||
|
if (!ErrorMessage.ContainsKey(id))
|
||||||
|
{
|
||||||
|
ErrorMessage.Add(id, CoreProgram._localizer?["Sys.Rollback"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RefreshErrorList();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void RefreshErrorList()
|
||||||
|
{
|
||||||
|
ListVM.DoSearch();
|
||||||
|
foreach (var item in ListVM.GetEntityList())
|
||||||
|
{
|
||||||
|
item.BatchError = ErrorMessage.Where(x => x.Key == item.GetID().ToString()).Select(x => x.Value).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1054
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseCRUDVM.cs
Normal file
1054
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseCRUDVM.cs
Normal file
File diff suppressed because it is too large
Load Diff
1443
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseImportVM.cs
Normal file
1443
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseImportVM.cs
Normal file
File diff suppressed because it is too large
Load Diff
1228
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BasePagedListVM.cs
Normal file
1228
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BasePagedListVM.cs
Normal file
File diff suppressed because it is too large
Load Diff
196
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseSearcher.cs
Normal file
196
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseSearcher.cs
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 搜索条件基类,一般和ListVM配合使用实现对ListVM的搜索功能。
|
||||||
|
/// </summary>
|
||||||
|
public class BaseSearcher : ISearcher
|
||||||
|
{
|
||||||
|
#region Property
|
||||||
|
|
||||||
|
#region 分页相关
|
||||||
|
/// <summary>
|
||||||
|
/// 当前页
|
||||||
|
/// </summary>
|
||||||
|
public int Page { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 每页数
|
||||||
|
/// </summary>
|
||||||
|
public int Limit { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 记录数
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public long Count { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 分页数
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public int PageCount { get; set; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录 Controller 中的表单数据
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public Dictionary<string, object> FC { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IModelStateService MSD { get => Wtm?.MSD; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取VM的全名
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string VMFullName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var name = GetType().AssemblyQualifiedName;
|
||||||
|
name = name.Substring(0, name.LastIndexOf(", Version="));
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IDataContext _dc;
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库环境
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public IDataContext DC
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_dc == null)
|
||||||
|
{
|
||||||
|
return Wtm?.DC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _dc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_dc = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Session信息
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public ISessionService Session { get => Wtm?.Session; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前登录人信息
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public LoginUserInfo LoginUserInfo { get => Wtm?.LoginUserInfo; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ViewDivId { get; set; }
|
||||||
|
#region 未使用
|
||||||
|
/// <summary>
|
||||||
|
/// 排序信息
|
||||||
|
/// </summary>
|
||||||
|
public SortInfo SortInfo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前台搜索框是否展开
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool? IsExpanded { get; set; }
|
||||||
|
|
||||||
|
private Guid _uniqueId;
|
||||||
|
[JsonIgnore]
|
||||||
|
public string UniqueId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_uniqueId == Guid.Empty)
|
||||||
|
{
|
||||||
|
_uniqueId = Guid.NewGuid();
|
||||||
|
}
|
||||||
|
return _uniqueId.ToNoSplitString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public WTMContext Wtm { get; set; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// InitVM 完成后触发的事件
|
||||||
|
/// </summary>
|
||||||
|
public event Action<ISearcher> OnAfterInit;
|
||||||
|
/// <summary>
|
||||||
|
/// ReInitVM 完成后触发的事件
|
||||||
|
/// </summary>
|
||||||
|
public event Action<ISearcher> OnAfterReInit;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Method
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用 InitVM 并触发 OnAfterInit 事件
|
||||||
|
/// </summary>
|
||||||
|
public void DoInit()
|
||||||
|
{
|
||||||
|
InitVM();
|
||||||
|
OnAfterInit?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用 ReInitVM 并触发 OnAfterReInit 事件
|
||||||
|
/// </summary>
|
||||||
|
public void DoReInit()
|
||||||
|
{
|
||||||
|
ReInitVM();
|
||||||
|
OnAfterReInit?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化ViewModel,框架会在创建VM实例之后自动调用本函数
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void InitVM()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从新初始化ViewModel,框架会在验证失败时自动调用本函数
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void ReInitVM()
|
||||||
|
{
|
||||||
|
InitVM();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Validate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 将源 VM 的 FC 等内容复制到本VM中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vm"></param>
|
||||||
|
public void CopyContext(IBaseVM vm)
|
||||||
|
{
|
||||||
|
FC = vm.FC;
|
||||||
|
this.Wtm = vm.Wtm;
|
||||||
|
this.ViewDivId = vm.ViewDivId;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
345
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseTemplateVM.cs
Normal file
345
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseTemplateVM.cs
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Data;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using NPOI.HSSF.UserModel;
|
||||||
|
using NPOI.HSSF.Util;
|
||||||
|
using NPOI.SS.UserModel;
|
||||||
|
using NPOI.XSSF.UserModel;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public class BaseTemplateVM : BaseVM
|
||||||
|
{
|
||||||
|
#region 属性
|
||||||
|
/// <summary>
|
||||||
|
/// 下载模板显示名称
|
||||||
|
/// </summary>
|
||||||
|
public string FileDisplayName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否验证模板类型(当其他系统模板导入到某模块时可设置为False)
|
||||||
|
/// </summary>
|
||||||
|
public bool ValidityTemplateType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 需要导出的数据
|
||||||
|
/// </summary>
|
||||||
|
public DataTable TemplateDataTable { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载模版页面参数
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, string> Parms { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Excel索引
|
||||||
|
/// </summary>
|
||||||
|
public long ExcelIndex { get; set; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 构造函数
|
||||||
|
public BaseTemplateVM()
|
||||||
|
{
|
||||||
|
ValidityTemplateType = true;
|
||||||
|
Parms = new Dictionary<string, string>();
|
||||||
|
var propetys = this.GetType().GetFields().Where(x => x.FieldType == typeof(ExcelPropety)).ToList();
|
||||||
|
for (int porpetyIndex = 0; porpetyIndex < propetys.Count(); porpetyIndex++)
|
||||||
|
{
|
||||||
|
ExcelPropety excelPropety = (ExcelPropety)propetys[porpetyIndex].GetValue(this);
|
||||||
|
if (propetys[porpetyIndex].GetCustomAttributes(typeof(DisplayAttribute), false).Length == 0)
|
||||||
|
{
|
||||||
|
excelPropety.ColumnName = excelPropety.FieldDisplayName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
excelPropety.ColumnName = propetys[porpetyIndex].GetPropertyDisplayName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 初始化Excel属性数据
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化Excel属性数据 包括动态列,列表中的下拉选项
|
||||||
|
/// </summary>
|
||||||
|
public virtual void InitExcelData()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void InitCustomFormat()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 初始化模版数据
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化模版数据
|
||||||
|
/// </summary>
|
||||||
|
public virtual void SetTemplateDataValus()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 生成模板
|
||||||
|
/// <summary>
|
||||||
|
/// 生成模板
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="displayName">文件名</param>
|
||||||
|
/// <returns>生成的模版文件</returns>
|
||||||
|
public byte[] GenerateTemplate(out string displayName)
|
||||||
|
{
|
||||||
|
//设置导出的文件名称
|
||||||
|
string SheetName = !string.IsNullOrEmpty(FileDisplayName) ? FileDisplayName : this.GetType().Name;
|
||||||
|
displayName = SheetName + "_" + DateTime.Now.ToString("yyyy-MM-dd") + "_" + DateTime.Now.ToString("hh^mm^ss") + ".xlsx";
|
||||||
|
|
||||||
|
//1.声明Excel文档
|
||||||
|
IWorkbook workbook = new XSSFWorkbook();
|
||||||
|
|
||||||
|
//加载初始化数据和下拉菜单数据,可重载
|
||||||
|
InitExcelData();
|
||||||
|
|
||||||
|
//设置TemplateDataTable的各列的类型
|
||||||
|
CreateDataTable();
|
||||||
|
|
||||||
|
//设置初始化数据到DataTable中
|
||||||
|
SetTemplateDataValus();
|
||||||
|
|
||||||
|
//2.设置workbook的sheet页
|
||||||
|
ISheet sheet = workbook.CreateSheet();
|
||||||
|
workbook.SetSheetName(0, SheetName);
|
||||||
|
|
||||||
|
//3.设置Sheet页的Row
|
||||||
|
IRow row = sheet.CreateRow(0);
|
||||||
|
row.HeightInPoints = 20;
|
||||||
|
|
||||||
|
ISheet enumSheet = workbook.CreateSheet();
|
||||||
|
IRow enumSheetRow1 = enumSheet.CreateRow(0);
|
||||||
|
enumSheetRow1.CreateCell(0).SetCellValue(CoreProgram._localizer?["Sys.Yes"]);
|
||||||
|
enumSheetRow1.CreateCell(1).SetCellValue(CoreProgram._localizer?["Sys.No"]);
|
||||||
|
enumSheetRow1.CreateCell(2).SetCellValue(this.GetType().Name); //为模板添加标记,必要时可添加版本号
|
||||||
|
|
||||||
|
ISheet dataSheet = workbook.CreateSheet();
|
||||||
|
|
||||||
|
#region 设置excel模板列头
|
||||||
|
//默认灰色
|
||||||
|
var headerStyle = GetCellStyle(workbook);
|
||||||
|
headerStyle.IsLocked = true;
|
||||||
|
|
||||||
|
//黄色
|
||||||
|
var yellowStyle = GetCellStyle(workbook, BackgroudColorEnum.Yellow);
|
||||||
|
yellowStyle.IsLocked = true;
|
||||||
|
|
||||||
|
//红色
|
||||||
|
var redStyle = GetCellStyle(workbook, BackgroudColorEnum.Red);
|
||||||
|
redStyle.IsLocked = true;
|
||||||
|
|
||||||
|
//取得所有ExcelPropety
|
||||||
|
var propetys = this.GetType().GetFields().Where(x => x.FieldType == typeof(ExcelPropety)).ToList();
|
||||||
|
|
||||||
|
//设置列的索引
|
||||||
|
int _currentColunmIndex = 0;
|
||||||
|
|
||||||
|
//设置Excel是否需要保护,默认不保护
|
||||||
|
bool IsProtect = false;
|
||||||
|
|
||||||
|
//循环类的属性,赋值给列
|
||||||
|
for (int porpetyIndex = 0; porpetyIndex < propetys.Count(); porpetyIndex++)
|
||||||
|
{
|
||||||
|
//依次获取属性字段
|
||||||
|
ExcelPropety excelPropety = (ExcelPropety)propetys[porpetyIndex].GetValue(this);
|
||||||
|
ColumnDataType dateType = (excelPropety.DataType == ColumnDataType.DateTime || excelPropety.DataType == ColumnDataType.Date) ? ColumnDataType.Text : excelPropety.DataType; //日期类型默认设置成Text类型,在赋值时会进行日期验证
|
||||||
|
|
||||||
|
//设置是否保护Excel
|
||||||
|
if (excelPropety.ReadOnly)
|
||||||
|
{
|
||||||
|
IsProtect = true;
|
||||||
|
}
|
||||||
|
//给必填项加星号
|
||||||
|
string colName = excelPropety.IsNullAble ? excelPropety.ColumnName : excelPropety.ColumnName + "*";
|
||||||
|
row.CreateCell(_currentColunmIndex).SetCellValue(colName);
|
||||||
|
|
||||||
|
//修改列头样式
|
||||||
|
switch (excelPropety.BackgroudColor)
|
||||||
|
{
|
||||||
|
case BackgroudColorEnum.Yellow:
|
||||||
|
row.Cells[_currentColunmIndex].CellStyle = yellowStyle;
|
||||||
|
break;
|
||||||
|
case BackgroudColorEnum.Red:
|
||||||
|
row.Cells[_currentColunmIndex].CellStyle = redStyle;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
row.Cells[_currentColunmIndex].CellStyle = headerStyle;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataStyle = workbook.CreateCellStyle();
|
||||||
|
var dataFormat = workbook.CreateDataFormat();
|
||||||
|
|
||||||
|
if (dateType == ColumnDataType.Dynamic)
|
||||||
|
{
|
||||||
|
int dynamicColCount = excelPropety.DynamicColumns.Count();
|
||||||
|
for (int dynamicColIndex = 0; dynamicColIndex < dynamicColCount; dynamicColIndex++)
|
||||||
|
{
|
||||||
|
var dynamicCol = excelPropety.DynamicColumns.ToList()[dynamicColIndex];
|
||||||
|
string dynamicColName = excelPropety.IsNullAble ? dynamicCol.ColumnName : dynamicCol.ColumnName + "*";
|
||||||
|
row.CreateCell(_currentColunmIndex).SetCellValue(dynamicColName);
|
||||||
|
row.Cells[_currentColunmIndex].CellStyle = headerStyle;
|
||||||
|
if (dynamicCol.ReadOnly)
|
||||||
|
{
|
||||||
|
IsProtect = true;
|
||||||
|
}
|
||||||
|
//设定列宽
|
||||||
|
if (excelPropety.CharCount > 0)
|
||||||
|
{
|
||||||
|
sheet.SetColumnWidth(_currentColunmIndex, excelPropety.CharCount * 256);
|
||||||
|
dataStyle.WrapText = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sheet.AutoSizeColumn(_currentColunmIndex);
|
||||||
|
}
|
||||||
|
//设置单元格样式及数据类型
|
||||||
|
dataStyle.IsLocked = excelPropety.ReadOnly;
|
||||||
|
dynamicCol.SetColumnFormat(dynamicCol.DataType, _currentColunmIndex, sheet, dataSheet, dataStyle, dataFormat);
|
||||||
|
_currentColunmIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//设定列宽
|
||||||
|
if (excelPropety.CharCount > 0)
|
||||||
|
{
|
||||||
|
sheet.SetColumnWidth(_currentColunmIndex, excelPropety.CharCount * 256);
|
||||||
|
dataStyle.WrapText = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sheet.AutoSizeColumn(_currentColunmIndex);
|
||||||
|
}
|
||||||
|
//设置是否锁定
|
||||||
|
dataStyle.IsLocked = excelPropety.ReadOnly;
|
||||||
|
//设置单元格样式及数据类型
|
||||||
|
excelPropety.SetColumnFormat(dateType, _currentColunmIndex, sheet, dataSheet, dataStyle, dataFormat);
|
||||||
|
_currentColunmIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 添加模版数据
|
||||||
|
if (TemplateDataTable.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < TemplateDataTable.Rows.Count; i++)
|
||||||
|
{
|
||||||
|
DataRow tableRow = TemplateDataTable.Rows[i];
|
||||||
|
IRow dataRow = sheet.CreateRow(1 + i);
|
||||||
|
for (int porpetyIndex = 0; porpetyIndex < propetys.Count(); porpetyIndex++)
|
||||||
|
{
|
||||||
|
string colName = propetys[porpetyIndex].Name;
|
||||||
|
tableRow[colName].ToString();
|
||||||
|
dataRow.CreateCell(porpetyIndex).SetCellValue(tableRow[colName].ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
//冻结行
|
||||||
|
sheet.CreateFreezePane(0, 1, 0, 1);
|
||||||
|
|
||||||
|
//锁定excel
|
||||||
|
if (IsProtect)
|
||||||
|
{
|
||||||
|
sheet.ProtectSheet("password");
|
||||||
|
}
|
||||||
|
|
||||||
|
//隐藏前2个Sheet
|
||||||
|
workbook.SetSheetHidden(1, SheetState.Hidden);
|
||||||
|
workbook.SetSheetHidden(2, SheetState.Hidden);
|
||||||
|
|
||||||
|
//返回byte数组
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
workbook.Write(ms);
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 取得表头的样式
|
||||||
|
private static ICellStyle GetCellStyle(IWorkbook workbook, BackgroudColorEnum backgroudColor = BackgroudColorEnum.Grey)
|
||||||
|
{
|
||||||
|
var headerStyle = workbook.CreateCellStyle();
|
||||||
|
|
||||||
|
//设定表头样式
|
||||||
|
headerStyle.BorderBottom = BorderStyle.Thin;
|
||||||
|
headerStyle.BorderLeft = BorderStyle.Thin;
|
||||||
|
headerStyle.BorderRight = BorderStyle.Thin;
|
||||||
|
headerStyle.BorderTop = BorderStyle.Thin;
|
||||||
|
|
||||||
|
//用灰色填充背景
|
||||||
|
short headerbg;
|
||||||
|
|
||||||
|
switch (backgroudColor)
|
||||||
|
{
|
||||||
|
case BackgroudColorEnum.Grey:
|
||||||
|
headerbg = HSSFColor.LightBlue.Index;
|
||||||
|
break;
|
||||||
|
case BackgroudColorEnum.Yellow:
|
||||||
|
headerbg = HSSFColor.LightYellow.Index;
|
||||||
|
break;
|
||||||
|
case BackgroudColorEnum.Red:
|
||||||
|
headerbg = HSSFColor.Pink.Index;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
headerbg = HSSFColor.Pink.Index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
headerStyle.FillForegroundColor = headerbg;
|
||||||
|
headerStyle.FillPattern = FillPattern.SolidForeground;
|
||||||
|
headerStyle.FillBackgroundColor = headerbg;
|
||||||
|
headerStyle.Alignment = HorizontalAlignment.Center;
|
||||||
|
return headerStyle;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 初始化DataTable(不含动态列)
|
||||||
|
private void CreateDataTable()
|
||||||
|
{
|
||||||
|
TemplateDataTable = new DataTable();
|
||||||
|
var propetys = this.GetType().GetFields().Where(x => x.FieldType == typeof(ExcelPropety)).ToList();
|
||||||
|
foreach (var p in propetys)
|
||||||
|
{
|
||||||
|
ExcelPropety excelPropety = (ExcelPropety)p.GetValue(this);
|
||||||
|
ColumnDataType dateType = excelPropety.DataType;
|
||||||
|
switch (dateType)
|
||||||
|
{
|
||||||
|
case ColumnDataType.Bool:
|
||||||
|
TemplateDataTable.Columns.Add(p.Name, typeof(bool));
|
||||||
|
break;
|
||||||
|
case ColumnDataType.Date:
|
||||||
|
TemplateDataTable.Columns.Add(p.Name, typeof(string));
|
||||||
|
break;
|
||||||
|
case ColumnDataType.Number:
|
||||||
|
TemplateDataTable.Columns.Add(p.Name, typeof(int));
|
||||||
|
break;
|
||||||
|
case ColumnDataType.Text:
|
||||||
|
TemplateDataTable.Columns.Add(p.Name, typeof(string));
|
||||||
|
break;
|
||||||
|
case ColumnDataType.Float:
|
||||||
|
TemplateDataTable.Columns.Add(p.Name, typeof(decimal));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TemplateDataTable.Columns.Add(p.Name, typeof(string));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
284
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseVM.cs
Normal file
284
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseVM.cs
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
using WalkingTec.Mvvm.Core.Support.Json;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所有ViewModel的基类,提供了基本的功能
|
||||||
|
/// </summary>
|
||||||
|
public class BaseVM : IBaseVM
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// BaseVM
|
||||||
|
/// </summary>
|
||||||
|
public BaseVM()
|
||||||
|
{
|
||||||
|
FC = new Dictionary<string, object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Property
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public WTMContext Wtm { get; set; }
|
||||||
|
|
||||||
|
private Guid _uniqueId;
|
||||||
|
/// <summary>
|
||||||
|
/// VM实例的Id
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string UniqueId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_uniqueId == Guid.Empty)
|
||||||
|
{
|
||||||
|
_uniqueId = Guid.NewGuid();
|
||||||
|
}
|
||||||
|
return _uniqueId.ToNoSplitString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前台传递过来的弹出窗口ID,多层弹出窗口用逗号分隔
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string WindowIds { get => Wtm?.WindowIds; }
|
||||||
|
|
||||||
|
private string _viewdivid;
|
||||||
|
/// <summary>
|
||||||
|
/// PartialView中主Div的Id
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ViewDivId
|
||||||
|
{
|
||||||
|
set { _viewdivid = value; }
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_viewdivid))
|
||||||
|
{
|
||||||
|
_viewdivid = "ViewDiv" + UniqueId;
|
||||||
|
}
|
||||||
|
return _viewdivid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private IDataContext _dc;
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库环境
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public IDataContext DC
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_dc == null)
|
||||||
|
{
|
||||||
|
return Wtm?.DC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _dc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_dc = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取VM的全名
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string VMFullName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var name = GetType().AssemblyQualifiedName;
|
||||||
|
name = name.Substring(0, name.LastIndexOf(", Version="));
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取VM所在Dll
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string CreatorAssembly
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前使用的连接字符串
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string CurrentCS { get => Wtm?.CurrentCS; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录Controller中传递过来的表单数据
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public Dictionary<string, object> FC { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取配置文件的信息
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public Configs ConfigInfo { get=> Wtm?.ConfigInfo; }
|
||||||
|
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IUIService UIService { get=> Wtm?.UIService; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前弹出层ID
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string CurrentWindowId { get => Wtm?.CurrentWindowId; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 父级弹出层ID
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ParentWindowId { get => Wtm?.ParentWindowId; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IDistributedCache Cache { get => Wtm?.Cache; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前登录人信息
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public LoginUserInfo LoginUserInfo { get=> Wtm?.LoginUserInfo;}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前Url
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string CurrentUrl { get => Wtm?.BaseUrl; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录原始提交页面
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string FromView { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录当前页面
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string CurrentView { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Session信息
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public ISessionService Session { get => Wtm?.Session; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller传递过来的ModelState信息
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public IModelStateService MSD { get => Wtm?.MSD; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用于保存删除的附件ID
|
||||||
|
/// </summary>
|
||||||
|
public List<string> DeletedFileIds { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ControllerName { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IStringLocalizer Localizer { get => Wtm?.Localizer; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// InitVM完成后触发的事件
|
||||||
|
/// </summary>
|
||||||
|
public event Action<IBaseVM> OnAfterInit;
|
||||||
|
/// <summary>
|
||||||
|
/// ReInitVM完成后触发的事件
|
||||||
|
/// </summary>
|
||||||
|
public event Action<IBaseVM> OnAfterReInit;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Method
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用 InitVM 并触发 OnAfterInit 事件
|
||||||
|
/// </summary>
|
||||||
|
public void DoInit()
|
||||||
|
{
|
||||||
|
InitVM();
|
||||||
|
OnAfterInit?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用 ReInitVM 并触发 OnAfterReInit 事件
|
||||||
|
/// </summary>
|
||||||
|
public void DoReInit()
|
||||||
|
{
|
||||||
|
ReInitVM();
|
||||||
|
OnAfterReInit?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化ViewModel,框架会在创建VM实例之后自动调用本函数
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void InitVM()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从新初始化ViewModel,框架会在验证失败时自动调用本函数
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void ReInitVM()
|
||||||
|
{
|
||||||
|
InitVM();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证函数,MVC会在提交数据的时候自动调用本函数
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual void Validate()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将源VM的上数据库上下文,Session,登录用户信息,模型状态信息,缓存信息等内容复制到本VM中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vm">复制的源</param>
|
||||||
|
public void CopyContext(BaseVM vm)
|
||||||
|
{
|
||||||
|
Wtm = vm.Wtm;
|
||||||
|
FC = vm.FC;
|
||||||
|
CreatorAssembly = vm.CreatorAssembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
59
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/CS.cs
Normal file
59
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/CS.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public class CS
|
||||||
|
{
|
||||||
|
public string Key { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
public DBTypeEnum? DbType { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
public string DbContext { get; set; }
|
||||||
|
|
||||||
|
public ConstructorInfo DcConstructor;
|
||||||
|
|
||||||
|
public IDataContext CreateDC()
|
||||||
|
{
|
||||||
|
if (DcConstructor == null)
|
||||||
|
{
|
||||||
|
var AllAssembly = Utils.GetAllAssembly();
|
||||||
|
List<ConstructorInfo> cis = new List<ConstructorInfo>();
|
||||||
|
if (AllAssembly != null)
|
||||||
|
{
|
||||||
|
foreach (var ass in AllAssembly)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var t = ass.GetExportedTypes().Where(x => typeof(DbContext).IsAssignableFrom(x) && x.Name != "DbContext" && x.Name != "FrameworkContext" && x.Name != "EmptyContext").ToList();
|
||||||
|
foreach (var st in t)
|
||||||
|
{
|
||||||
|
var ci = st.GetConstructor(new Type[] { typeof(CS) });
|
||||||
|
if (ci != null)
|
||||||
|
{
|
||||||
|
cis.Add(ci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
string dcname = DbContext;
|
||||||
|
if (string.IsNullOrEmpty(dcname))
|
||||||
|
{
|
||||||
|
dcname = "DataContext";
|
||||||
|
}
|
||||||
|
DcConstructor = cis.Where(x => x.DeclaringType.Name.ToLower() == dcname.ToLower()).FirstOrDefault();
|
||||||
|
if (DcConstructor == null)
|
||||||
|
{
|
||||||
|
DcConstructor = cis.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (IDataContext)DcConstructor?.Invoke(new object[] { this });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
480
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/Configs.cs
Normal file
480
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/Configs.cs
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using WalkingTec.Mvvm.Core.ConfigOptions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Configs
|
||||||
|
/// </summary>
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
#region ConnectionStrings
|
||||||
|
|
||||||
|
private List<CS> _connectStrings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ConnectionStrings
|
||||||
|
/// </summary>
|
||||||
|
public List<CS> Connections
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_connectStrings == null)
|
||||||
|
{
|
||||||
|
_connectStrings = new List<CS>();
|
||||||
|
}
|
||||||
|
return _connectStrings;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_connectStrings = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Domains
|
||||||
|
|
||||||
|
private Dictionary<string,Domain> _domains;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ConnectionStrings
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, Domain> Domains
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_domains == null)
|
||||||
|
{
|
||||||
|
_domains = new Dictionary<string, Domain>();
|
||||||
|
}
|
||||||
|
return _domains;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_domains = value;
|
||||||
|
foreach (var item in _domains)
|
||||||
|
{
|
||||||
|
if(item.Value != null)
|
||||||
|
{
|
||||||
|
item.Value.Name = item.Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region QuickDebug
|
||||||
|
|
||||||
|
private bool? _isQuickDebug;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is debug mode
|
||||||
|
/// </summary>
|
||||||
|
public bool IsQuickDebug
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _isQuickDebug ?? false;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isQuickDebug = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public string ErrorHandler { get; set; } = "/_Framework/Error";
|
||||||
|
|
||||||
|
#region Cookie prefix
|
||||||
|
|
||||||
|
private string _cookiePre;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cookie prefix
|
||||||
|
/// </summary>
|
||||||
|
public string CookiePre
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _cookiePre ?? string.Empty;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_cookiePre = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region PageMode
|
||||||
|
|
||||||
|
private PageModeEnum? _pageMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PageMode
|
||||||
|
/// </summary>
|
||||||
|
public PageModeEnum PageMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_pageMode == null)
|
||||||
|
{
|
||||||
|
_pageMode = PageModeEnum.Single;
|
||||||
|
}
|
||||||
|
return _pageMode.Value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_pageMode = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region TabMode
|
||||||
|
|
||||||
|
private TabModeEnum? _tabMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TabMode
|
||||||
|
/// </summary>
|
||||||
|
public TabModeEnum TabMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_tabMode == null)
|
||||||
|
{
|
||||||
|
_tabMode = TabModeEnum.Default;
|
||||||
|
}
|
||||||
|
return _tabMode.Value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_tabMode = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region BlazorMode
|
||||||
|
|
||||||
|
private BlazorModeEnum? _blazorMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TabMode
|
||||||
|
/// </summary>
|
||||||
|
public BlazorModeEnum BlazorMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_blazorMode == null)
|
||||||
|
{
|
||||||
|
_blazorMode = BlazorModeEnum.Server;
|
||||||
|
}
|
||||||
|
return _blazorMode.Value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_blazorMode = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Custom settings
|
||||||
|
|
||||||
|
private Dictionary<string,string> _appSettings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom settings
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, string> AppSettings
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_appSettings == null)
|
||||||
|
{
|
||||||
|
_appSettings = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
return _appSettings;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_appSettings = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region FileOptions
|
||||||
|
|
||||||
|
private FileUploadOptions _fileUploadOptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FileOptions
|
||||||
|
/// </summary>
|
||||||
|
public FileUploadOptions FileUploadOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_fileUploadOptions == null)
|
||||||
|
{
|
||||||
|
_fileUploadOptions = new FileUploadOptions()
|
||||||
|
{
|
||||||
|
UploadLimit = DefaultConfigConsts.DEFAULT_UPLOAD_LIMIT,
|
||||||
|
SaveFileMode = "database",
|
||||||
|
Settings = new Dictionary<string, List<FileHandlerOptions>>()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return _fileUploadOptions;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_fileUploadOptions = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UIOptions
|
||||||
|
|
||||||
|
private UIOptions _uiOptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UIOptions
|
||||||
|
/// </summary>
|
||||||
|
public UIOptions UIOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_uiOptions == null)
|
||||||
|
{
|
||||||
|
_uiOptions = new UIOptions();
|
||||||
|
if (_uiOptions.DataTable == null)
|
||||||
|
_uiOptions.DataTable = new UIOptions.DataTableOptions
|
||||||
|
{
|
||||||
|
RPP = DefaultConfigConsts.DEFAULT_RPP
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_uiOptions.ComboBox == null)
|
||||||
|
_uiOptions.ComboBox = new UIOptions.ComboBoxOptions
|
||||||
|
{
|
||||||
|
DefaultEnableSearch = DefaultConfigConsts.DEFAULT_COMBOBOX_DEFAULT_ENABLE_SEARCH
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_uiOptions.DateTime == null)
|
||||||
|
_uiOptions.DateTime = new UIOptions.DateTimeOptions
|
||||||
|
{
|
||||||
|
DefaultReadonly = DefaultConfigConsts.DEFAULT_DATETIME_DEFAULT_READONLY
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_uiOptions.SearchPanel == null)
|
||||||
|
_uiOptions.SearchPanel = new UIOptions.SearchPanelOptions
|
||||||
|
{
|
||||||
|
DefaultExpand = DefaultConfigConsts.DEFAULT_SEARCHPANEL_DEFAULT_EXPAND
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return _uiOptions;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_uiOptions = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Is FileAttachment public
|
||||||
|
|
||||||
|
private bool? _isFilePublic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is FileAttachment public
|
||||||
|
/// </summary>
|
||||||
|
public bool IsFilePublic
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _isFilePublic ?? false;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isFilePublic = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UEditorOptions
|
||||||
|
|
||||||
|
private UEditorOptions _ueditorOptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UEditor配置
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public UEditorOptions UEditorOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_ueditorOptions == null)
|
||||||
|
{
|
||||||
|
_ueditorOptions = new UEditorOptions();
|
||||||
|
}
|
||||||
|
return _ueditorOptions;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_ueditorOptions = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Cors configs
|
||||||
|
|
||||||
|
private Cors _cors;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cors configs
|
||||||
|
/// </summary>
|
||||||
|
public Cors CorsOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_cors == null)
|
||||||
|
{
|
||||||
|
_cors = new Cors();
|
||||||
|
_cors.Policy = new List<CorsPolicy>();
|
||||||
|
}
|
||||||
|
return _cors;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_cors = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Support Languages
|
||||||
|
|
||||||
|
private string _languages;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Support Languages
|
||||||
|
/// </summary>
|
||||||
|
public string Languages
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty((_languages)))
|
||||||
|
{
|
||||||
|
_languages = "zh";
|
||||||
|
}
|
||||||
|
return _languages;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_languages = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CultureInfo> _supportLanguages;
|
||||||
|
public List<CultureInfo> SupportLanguages
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(_supportLanguages == null)
|
||||||
|
{
|
||||||
|
_supportLanguages = new List<CultureInfo>();
|
||||||
|
var lans = Languages.Split(",");
|
||||||
|
foreach (var lan in lans)
|
||||||
|
{
|
||||||
|
_supportLanguages.Add(new CultureInfo(lan));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return _supportLanguages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public string HostRoot { get; set; } = "";
|
||||||
|
|
||||||
|
|
||||||
|
#region CookieOption configs
|
||||||
|
|
||||||
|
private CookieOption _cookieOption;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cors configs
|
||||||
|
/// </summary>
|
||||||
|
public CookieOption CookieOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_cookieOption == null)
|
||||||
|
{
|
||||||
|
_cookieOption = new CookieOption();
|
||||||
|
}
|
||||||
|
return _cookieOption;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_cookieOption = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region JwtOption configs
|
||||||
|
|
||||||
|
private JwtOption _jwtOption;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cors configs
|
||||||
|
/// </summary>
|
||||||
|
public JwtOption JwtOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_jwtOption == null)
|
||||||
|
{
|
||||||
|
_jwtOption = new JwtOption();
|
||||||
|
}
|
||||||
|
return _jwtOption;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_jwtOption = value;
|
||||||
|
if(_jwtOption.SecurityKey.Length < 18)
|
||||||
|
{
|
||||||
|
var count = 18 - _jwtOption.SecurityKey.Length;
|
||||||
|
for (int i = 0; i < count; i++){
|
||||||
|
_jwtOption.SecurityKey += "x";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public IDataContext CreateDC(string csName = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(csName))
|
||||||
|
{
|
||||||
|
csName = "default";
|
||||||
|
}
|
||||||
|
var cs = Connections.Where(x => x.Key.ToLower() == csName.ToLower()).FirstOrDefault();
|
||||||
|
return cs?.CreateDC();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public class CookieOption
|
||||||
|
{
|
||||||
|
public string Issuer { get; set; } = "http://localhost";
|
||||||
|
public string Audience { get; set; } = "http://localhost";
|
||||||
|
public int Expires { get; set; } = 3600;
|
||||||
|
public bool SlidingExpiration { get; set; } = true;
|
||||||
|
public string LoginPath { get; set; } = "/Login/Login";
|
||||||
|
public string LogoutPath { get; set; } = "/Login/Logout";
|
||||||
|
public string AccessDeniedPath { get; set; } = "/Login/Login";
|
||||||
|
public string Domain { get; set; } = "";
|
||||||
|
public string ReturnUrlParameter { get; set; } = CookieAuthenticationDefaults.ReturnUrlParameter;
|
||||||
|
}
|
||||||
|
}
|
18
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/Cors.cs
Normal file
18
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/Cors.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public class Cors
|
||||||
|
{
|
||||||
|
public bool EnableAll { get; set; }
|
||||||
|
public List<CorsPolicy> Policy { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CorsPolicy
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Domain { get; set; }
|
||||||
|
}
|
||||||
|
}
|
35
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/DFS.cs
Normal file
35
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/DFS.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DFS
|
||||||
|
/// </summary>
|
||||||
|
public class DFS
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// StorageMaxConnection
|
||||||
|
/// </summary>
|
||||||
|
public int? StorageMaxConnection { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TrackerMaxConnection
|
||||||
|
/// </summary>
|
||||||
|
public int? TrackerMaxConnection { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ConnectionTimeout
|
||||||
|
/// </summary>
|
||||||
|
public int? ConnectionTimeout { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ConnectionLifeTime
|
||||||
|
/// </summary>
|
||||||
|
public int? ConnectionLifeTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Trackers
|
||||||
|
/// </summary>
|
||||||
|
public List<DFSTracker> Trackers { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DFSTracker
|
||||||
|
/// </summary>
|
||||||
|
public class DFSTracker
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IP
|
||||||
|
/// </summary>
|
||||||
|
public string IP { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Port
|
||||||
|
/// </summary>
|
||||||
|
public int Port { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
namespace WalkingTec.Mvvm.Core.ConfigOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DefaultConfigConsts
|
||||||
|
/// </summary>
|
||||||
|
public static class DefaultConfigConsts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 默认上传路径
|
||||||
|
/// </summary>
|
||||||
|
public const string DEFAULT_UPLOAD_DIR = ".\\upload";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认列表行数
|
||||||
|
/// </summary>
|
||||||
|
public const int DEFAULT_RPP = 20;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认上传文件限制
|
||||||
|
/// </summary>
|
||||||
|
public const int DEFAULT_UPLOAD_LIMIT = 20 * 1024 * 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认允许ComboBox搜索
|
||||||
|
/// </summary>
|
||||||
|
public const bool DEFAULT_COMBOBOX_DEFAULT_ENABLE_SEARCH = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认开启DateTime只读
|
||||||
|
/// </summary>
|
||||||
|
public const bool DEFAULT_DATETIME_DEFAULT_READONLY = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认展开SearchPanel内容
|
||||||
|
/// </summary>
|
||||||
|
public const bool DEFAULT_SEARCHPANEL_DEFAULT_EXPAND = true;
|
||||||
|
}
|
||||||
|
}
|
46
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/Domain.cs
Normal file
46
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/Domain.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.ConfigOptions
|
||||||
|
{
|
||||||
|
public class Domain
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Address { get; set; }
|
||||||
|
|
||||||
|
public string InnerAddress { get; set; }
|
||||||
|
|
||||||
|
public string EntryUrl { get; set; }
|
||||||
|
|
||||||
|
public string Url
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var rv = Address;
|
||||||
|
if (string.IsNullOrEmpty(rv) == false && rv.ToLower().StartsWith("http://") == false && rv.ToLower().StartsWith("https://") == false)
|
||||||
|
{
|
||||||
|
rv = "http://" + rv;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string InnerUrl
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var rv = InnerAddress;
|
||||||
|
if (string.IsNullOrEmpty(rv) == false && rv.ToLower().StartsWith("http://") == false && rv.ToLower().StartsWith("https://") == false)
|
||||||
|
{
|
||||||
|
rv = "http://" + rv;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.ConfigOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// FileOptions
|
||||||
|
/// </summary>
|
||||||
|
public class FileUploadOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件保存位置
|
||||||
|
/// </summary>
|
||||||
|
public string SaveFileMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传文件限制 单位字节 默认 20 * 1024 * 1024 = 20971520 bytes
|
||||||
|
/// </summary>
|
||||||
|
public long UploadLimit { get; set; } = 20971520;
|
||||||
|
|
||||||
|
|
||||||
|
public Dictionary<string, List<FileHandlerOptions>> Settings { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FileHandlerOptions
|
||||||
|
{
|
||||||
|
public string GroupName { get; set; }
|
||||||
|
public string GroupLocation { get; set; }
|
||||||
|
public string ServerUrl { get; set; }
|
||||||
|
|
||||||
|
public string Key { get; set; }
|
||||||
|
public string Secret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public class JwtOption
|
||||||
|
{
|
||||||
|
public string Issuer { get; set; } = "http://localhost";
|
||||||
|
public string Audience { get; set; } = "http://localhost";
|
||||||
|
public int Expires { get; set; } = 3600;
|
||||||
|
public string SecurityKey { get; set; } = "wtm";
|
||||||
|
public string LoginPath { get; set; }
|
||||||
|
public int RefreshTokenExpires { get; set; }
|
||||||
|
}
|
||||||
|
}
|
19
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/KV.cs
Normal file
19
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ConfigOptions/KV.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// KV
|
||||||
|
/// </summary>
|
||||||
|
public class KV
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Key
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Value
|
||||||
|
/// </summary>
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,386 @@
|
|||||||
|
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.ConfigOptions
|
||||||
|
{
|
||||||
|
public class UEditorOptions
|
||||||
|
{
|
||||||
|
#region 上传图片配置项
|
||||||
|
/// <summary>
|
||||||
|
/// 执行上传图片的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageActionName")]
|
||||||
|
public string ImageActionName { get; set; } = "UploadForLayUIUEditor";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交的图片表单名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageFieldName")]
|
||||||
|
public string ImageFieldName { get; set; } = "FileID";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传大小限制,单位B
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageMaxSize")]
|
||||||
|
public int ImageMaxSize { get; set; } = 2048000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传图片格式显示
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageAllowFiles")]
|
||||||
|
public string[] ImageAllowFiles { get; set; } = new string[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否压缩图片,默认是true
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageCompressEnable")]
|
||||||
|
public bool ImageCompressEnable { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片压缩最长边限制
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageCompressBorder")]
|
||||||
|
public int ImageCompressBorder { get; set; } = 1600;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 插入的图片浮动方式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageInsertAlign")]
|
||||||
|
public string ImageInsertAlign { get; set; } = "none";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片访问路径前缀 默认返回全路径
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageUrlPrefix")]
|
||||||
|
public string ImageUrlPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
|
||||||
|
/* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
|
||||||
|
/* {time} 会替换成时间戳 */
|
||||||
|
/* {yyyy} 会替换成四位年份 */
|
||||||
|
/* {yy} 会替换成两位年份 */
|
||||||
|
/* {mm} 会替换成两位月份 */
|
||||||
|
/* {dd} 会替换成两位日期 */
|
||||||
|
/* {hh} 会替换成两位小时 */
|
||||||
|
/* {ii} 会替换成两位分钟 */
|
||||||
|
/* {ss} 会替换成两位秒 */
|
||||||
|
/* 非法字符 \ : * ? " < > | */
|
||||||
|
/* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传保存路径,可以自定义保存路径和文件名格式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imagePathFormat")]
|
||||||
|
public string ImagePathFormat { get; set; } = "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 涂鸦图片上传配置项
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行上传涂鸦的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("scrawlActionName")]
|
||||||
|
public string ScrawlActionName { get; set; } = "UploadForLayUIUEditor";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交的图片表单名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("scrawlFieldName")]
|
||||||
|
public string ScrawlFieldName { get; set; } = "FileID";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传保存路径,可以自定义保存路径和文件名格式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("scrawlPathFormat")]
|
||||||
|
public string ScrawlPathFormat { get; set; } = "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传大小限制,单位B
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("scrawlMaxSize")]
|
||||||
|
public int ScrawlMaxSize { get; set; } = 2048000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片访问路径前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("scrawlUrlPrefix")]
|
||||||
|
public string ScrawlUrlPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 插入的图片浮动方式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("scrawlInsertAlign")]
|
||||||
|
public string ScrawlInsertAlign { get; set; } = "none";
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 截图工具上传
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行上传截图的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("snapscreenActionName")]
|
||||||
|
public string SnapscreenActionName { get; set; } = "UploadForLayUIUEditor";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传保存路径,可以自定义保存路径和文件名格式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("snapscreenPathFormat")]
|
||||||
|
public string SnapscreenPathFormat { get; set; } = "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片访问路径前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("snapscreenUrlPrefix")]
|
||||||
|
public string SnapscreenUrlPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 插入的图片浮动方式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("snapscreenInsertAlign")]
|
||||||
|
public string SnapscreenInsertAlign { get; set; } = "none";
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 抓取远程图片配置
|
||||||
|
|
||||||
|
[JsonPropertyName("catcherLocalDomain")]
|
||||||
|
public string[] CatcherLocalDomain { get; set; } = new string[] { "127.0.0.1", "localhost", "img.baidu.com" };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行抓取远程图片的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("catcherActionName")]
|
||||||
|
public string CatcherActionName { get; set; } = "catchimage";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交的图片列表表单名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("catcherFieldName")]
|
||||||
|
public string CatcherFieldName { get; set; } = "source";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传保存路径,可以自定义保存路径和文件名格式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("catcherPathFormat")]
|
||||||
|
public string CatcherPathFormat { get; set; } = "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片访问路径前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("catcherUrlPrefix")]
|
||||||
|
public string CatcherUrlPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传大小限制,单位B
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("catcherMaxSize")]
|
||||||
|
public int CatcherMaxSize { get; set; } = 2048000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 抓取图片格式显示
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("catcherAllowFiles")]
|
||||||
|
public string[] CatcherAllowFiles { get; set; } = new string[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 上传视频配置
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行上传视频的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("videoActionName")]
|
||||||
|
public string VideoActionName { get; set; } = "UploadForLayUIUEditor";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交的视频表单名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("videoFieldName")]
|
||||||
|
public string VideoFieldName { get; set; } = "FileID";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传保存路径,可以自定义保存路径和文件名格式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("videoPathFormat")]
|
||||||
|
public string VideoPathFormat { get; set; } = "upload/video/{yyyy}{mm}{dd}/{time}{rand:6}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频访问路径前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("videoUrlPrefix")]
|
||||||
|
public string VideoUrlPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传大小限制,单位B,默认100MB
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("videoMaxSize")]
|
||||||
|
public int VideoMaxSize { get; set; } = 102400000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传视频格式显示
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("videoAllowFiles")]
|
||||||
|
public string[] VideoAllowFiles { get; set; } = new string[] { ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid" };
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 上传文件配置
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// controller里,执行上传视频的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileActionName")]
|
||||||
|
public string FileActionName { get; set; } = "UploadForLayUIUEditor";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交的文件表单名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileFieldName")]
|
||||||
|
public string FileFieldName { get; set; } = "FileID";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传保存路径,可以自定义保存路径和文件名格式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("filePathFormat")]
|
||||||
|
public string FilePathFormat { get; set; } = "upload/file/{yyyy}{mm}{dd}/{time}{rand:6}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件访问路径前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileUrlPrefix")]
|
||||||
|
public string FileUrlPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传大小限制,单位B,默认50MB
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileMaxSize")]
|
||||||
|
public int FileMaxSize { get; set; } = 51200000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传文件格式显示
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileAllowFiles")]
|
||||||
|
public string[] FileAllowFiles { get; set; } = new string[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" };
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 列出指定目录下的图片
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行图片管理的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageManagerActionName")]
|
||||||
|
public string ImageManagerActionName { get; set; } = "listimage";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 指定要列出图片的目录
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageManagerListPath")]
|
||||||
|
public string ImageManagerListPath { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每次列出文件数量
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageManagerListSize")]
|
||||||
|
public int ImageManagerListSize { get; set; } = 20;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片访问路径前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageManagerUrlPrefix")]
|
||||||
|
public string ImageManagerUrlPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 插入的图片浮动方式
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageManagerInsertAlign")]
|
||||||
|
public string ImageManagerInsertAlign { get; set; } = "none";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列出的文件类型
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("imageManagerAllowFiles")]
|
||||||
|
public string[] ImageManagerAllowFiles { get; set; } = new string[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 列出指定目录下的文件
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行文件管理的action名称
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileManagerActionName")]
|
||||||
|
public string FileManagerActionName { get; set; } = "listfile";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 指定要列出文件的目录
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileManagerListPath")]
|
||||||
|
public string FileManagerListPath { get; set; } = "upload/file";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件访问路径前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileManagerUrlPrefix")]
|
||||||
|
public string FileManagerUrlPrefix { get; set; } = "/ueditor/net/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每次列出文件数量
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileManagerListSize")]
|
||||||
|
public int FileManagerListSize { get; set; } = 20;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列出的文件类型
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[JsonPropertyName("fileManagerAllowFiles")]
|
||||||
|
public string[] FileManagerAllowFiles { get; set; } = new string[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" };
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
namespace WalkingTec.Mvvm.Core.ConfigOptions
|
||||||
|
{
|
||||||
|
public class UIOptions
|
||||||
|
{
|
||||||
|
public DataTableOptions DataTable { get; set; }
|
||||||
|
public ComboBoxOptions ComboBox { get; set; }
|
||||||
|
public DateTimeOptions DateTime { get; set; }
|
||||||
|
public SearchPanelOptions SearchPanel { get; set; }
|
||||||
|
|
||||||
|
public class DataTableOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 默认列表行数
|
||||||
|
/// </summary>
|
||||||
|
public int RPP { get; set; }
|
||||||
|
|
||||||
|
public bool ShowPrint { get; set; }
|
||||||
|
|
||||||
|
public bool ShowFilter { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ComboBoxOptions
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认允许ComboBox搜索
|
||||||
|
/// </summary>
|
||||||
|
public bool DefaultEnableSearch { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DateTimeOptions
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认开启DateTime只读
|
||||||
|
/// </summary>
|
||||||
|
public bool DefaultReadonly { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SearchPanelOptions
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认展开SearchPanel内容
|
||||||
|
/// </summary>
|
||||||
|
public bool DefaultExpand { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/CoreProgram.cs
Normal file
34
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/CoreProgram.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public class CoreProgram
|
||||||
|
{
|
||||||
|
public static IStringLocalizer _localizer {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonSerializerOptions DefaultJsonOption
|
||||||
|
{
|
||||||
|
get;set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonSerializerOptions DefaultPostJsonOption
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string[] Buildindll = new string[]
|
||||||
|
{
|
||||||
|
"WalkingTec.Mvvm.Core",
|
||||||
|
"WalkingTec.Mvvm.Mvc",
|
||||||
|
"WalkingTec.Mvvm.Admin",
|
||||||
|
"WalkingTec.Mvvm.Taghelpers"
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
1269
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/DataContext.cs
Normal file
1269
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/DataContext.cs
Normal file
File diff suppressed because it is too large
Load Diff
156
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Enums.cs
Normal file
156
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Enums.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public enum HttpMethodEnum
|
||||||
|
{
|
||||||
|
GET,
|
||||||
|
POST,
|
||||||
|
PUT,
|
||||||
|
DELETE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列表操作列类型
|
||||||
|
/// </summary>
|
||||||
|
public enum ColumnFormatTypeEnum
|
||||||
|
{
|
||||||
|
Dialog,//弹出窗口
|
||||||
|
Button,//按钮
|
||||||
|
Download,//下载
|
||||||
|
ViewPic,//查看图片
|
||||||
|
Script,//脚本
|
||||||
|
Html
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库类型
|
||||||
|
/// </summary>
|
||||||
|
public enum DBTypeEnum { SqlServer, MySql, PgSql, Memory, SQLite, Oracle }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面显示方式
|
||||||
|
/// </summary>
|
||||||
|
public enum PageModeEnum { Single, Tab }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tab页的显示方式
|
||||||
|
/// </summary>
|
||||||
|
public enum TabModeEnum { Default, Simple }
|
||||||
|
|
||||||
|
public enum BlazorModeEnum { Server, Wasm}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按钮
|
||||||
|
/// </summary>
|
||||||
|
public enum ButtonTypesEnum
|
||||||
|
{
|
||||||
|
Button,
|
||||||
|
Link
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按钮
|
||||||
|
/// </summary>
|
||||||
|
public enum RedirectTypesEnum
|
||||||
|
{
|
||||||
|
Layer,
|
||||||
|
Self,
|
||||||
|
NewWindow,
|
||||||
|
NewTab,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 日期类型
|
||||||
|
/// </summary>
|
||||||
|
public enum DateTimeTypeEnum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 日期选择器
|
||||||
|
/// 可选择:年、月、日
|
||||||
|
/// </summary>
|
||||||
|
Date,
|
||||||
|
/// <summary>
|
||||||
|
/// 日期时间选择器
|
||||||
|
/// 可选择:年、月、日、时、分、秒
|
||||||
|
/// </summary>
|
||||||
|
DateTime,
|
||||||
|
/// <summary>
|
||||||
|
/// 年选择器
|
||||||
|
/// 只提供年列表选择
|
||||||
|
/// </summary>
|
||||||
|
Year,
|
||||||
|
/// <summary>
|
||||||
|
/// 年月选择器
|
||||||
|
/// 只提供年、月选择
|
||||||
|
/// </summary>
|
||||||
|
Month,
|
||||||
|
/// <summary>
|
||||||
|
/// 时间选择器
|
||||||
|
/// 只提供时、分、秒选择
|
||||||
|
/// </summary>
|
||||||
|
Time
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图形枚举
|
||||||
|
/// </summary>
|
||||||
|
public enum ChartEnum
|
||||||
|
{
|
||||||
|
line,
|
||||||
|
pie,
|
||||||
|
column,
|
||||||
|
bubble,
|
||||||
|
barcolumn
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图形统计值类型
|
||||||
|
/// </summary>
|
||||||
|
public enum ChartValueType
|
||||||
|
{
|
||||||
|
sum,
|
||||||
|
count,
|
||||||
|
sumpct,
|
||||||
|
countpct
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 图形统计分区类型
|
||||||
|
/// </summary>
|
||||||
|
public enum PartitionType
|
||||||
|
{
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum UIEnum
|
||||||
|
{ LayUI, React, VUE,Blazor }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public enum BoolComboTypes { YesNo, ValidInvalid, MaleFemale, HaveNotHave, Custom }
|
||||||
|
|
||||||
|
public enum SortDir { Asc, Desc }
|
||||||
|
|
||||||
|
public enum BackgroudColorEnum
|
||||||
|
{
|
||||||
|
Grey,
|
||||||
|
Yellow,
|
||||||
|
Red
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum GenderEnum
|
||||||
|
{
|
||||||
|
[Display(Name = "Sys.Male")]
|
||||||
|
Male = 0,
|
||||||
|
[Display(Name = "Sys.Female")]
|
||||||
|
Female = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Exceptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 对象为 null 或 空字符串 异常
|
||||||
|
/// </summary>
|
||||||
|
public class NullOrEmptyStringException : Exception
|
||||||
|
{
|
||||||
|
public const string DEFAULT_EXCEPTION_MSG = "对象为 null 或 空字符串 异常";
|
||||||
|
public NullOrEmptyStringException() : base(DEFAULT_EXCEPTION_MSG) { }
|
||||||
|
public NullOrEmptyStringException(string message) : base(message) { }
|
||||||
|
public NullOrEmptyStringException(string message, Exception innerException) : base(message, innerException) { }
|
||||||
|
protected NullOrEmptyStringException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,192 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class ConfigExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configBuilder"></param>
|
||||||
|
/// <param name="env"></param>
|
||||||
|
/// <param name="jsonFileDir"></param>
|
||||||
|
/// <param name="jsonFileName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IConfigurationBuilder WTMConfig(this IConfigurationBuilder configBuilder, IHostEnvironment env, string jsonFileDir=null, string jsonFileName = null)
|
||||||
|
{
|
||||||
|
IConfigurationBuilder rv = configBuilder;
|
||||||
|
if (string.IsNullOrEmpty(jsonFileDir))
|
||||||
|
{
|
||||||
|
rv = rv.WTM_SetCurrentDictionary();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = rv.SetBasePath(jsonFileDir);
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(jsonFileName))
|
||||||
|
{
|
||||||
|
rv = rv.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = rv.AddJsonFile(jsonFileName, optional: true, reloadOnChange: true);
|
||||||
|
}
|
||||||
|
rv = rv.AddEnvironmentVariables();
|
||||||
|
if (env != null)
|
||||||
|
{
|
||||||
|
rv = rv.AddInMemoryCollection(new Dictionary<string, string> { { "HostRoot", env.ContentRootPath } });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = rv.AddInMemoryCollection(new Dictionary<string, string> { { "HostRoot", Directory.GetCurrentDirectory() } });
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static IConfigurationBuilder WTM_SetCurrentDictionary(this IConfigurationBuilder cb)
|
||||||
|
{
|
||||||
|
CurrentDirectoryHelpers.SetCurrentDirectory();
|
||||||
|
|
||||||
|
if (!File.Exists(Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json")))
|
||||||
|
{
|
||||||
|
var binLocation = Assembly.GetEntryAssembly()?.Location;
|
||||||
|
if (!string.IsNullOrEmpty(binLocation))
|
||||||
|
{
|
||||||
|
var binPath = new FileInfo(binLocation).Directory?.FullName;
|
||||||
|
if (File.Exists(Path.Combine(binPath, "appsettings.json")))
|
||||||
|
{
|
||||||
|
Directory.SetCurrentDirectory(binPath);
|
||||||
|
cb.SetBasePath(binPath);
|
||||||
|
//.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
//.AddEnvironmentVariables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cb.SetBasePath(Directory.GetCurrentDirectory());
|
||||||
|
}
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 解决IIS InProgress下CurrentDirectory获取错误的问题
|
||||||
|
/// </summary>
|
||||||
|
internal class CurrentDirectoryHelpers
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
|
||||||
|
|
||||||
|
private static extern IntPtr GetModuleHandle(string lpModuleName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[System.Runtime.InteropServices.DllImport(AspNetCoreModuleDll)]
|
||||||
|
|
||||||
|
private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||||
|
|
||||||
|
private struct IISConfigurationData
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
public IntPtr pNativeApplication;
|
||||||
|
|
||||||
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
|
||||||
|
|
||||||
|
public string pwzFullApplicationPath;
|
||||||
|
|
||||||
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
|
||||||
|
|
||||||
|
public string pwzVirtualApplicationPath;
|
||||||
|
|
||||||
|
public bool fWindowsAuthEnabled;
|
||||||
|
|
||||||
|
public bool fBasicAuthEnabled;
|
||||||
|
|
||||||
|
public bool fAnonymousAuthEnable;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void SetCurrentDirectory()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
// Check if physical path was provided by ANCM
|
||||||
|
|
||||||
|
var sitePhysicalPath = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(sitePhysicalPath))
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
// Skip if not running ANCM InProcess
|
||||||
|
|
||||||
|
if (GetModuleHandle(AspNetCoreModuleDll) == IntPtr.Zero)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IISConfigurationData configurationData = default(IISConfigurationData);
|
||||||
|
|
||||||
|
if (http_get_application_properties(ref configurationData) != 0)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sitePhysicalPath = configurationData.pwzFullApplicationPath;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Environment.CurrentDirectory = sitePhysicalPath;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
catch
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
// ignore
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1112
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Extensions/DCExtension.cs
Normal file
1112
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Extensions/DCExtension.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class DistinctExtensions
|
||||||
|
{
|
||||||
|
public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector)
|
||||||
|
{
|
||||||
|
return source.Distinct(new CommonEqualityComparer<T, V>(keySelector));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 树形结构Model的扩展函数
|
||||||
|
/// </summary>
|
||||||
|
public static class ITreeDataExtension
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取一个父节点下的所有子节点,包括子节点的子节点
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">树形结构类</typeparam>
|
||||||
|
/// <param name="self">树形结构实例</param>
|
||||||
|
/// <param name="order">排序字段,可为空</param>
|
||||||
|
/// <returns>树形结构列表,包含所有子节点</returns>
|
||||||
|
public static List<T> GetAllChildren<T>(this T self, Func<T, object> order = null)
|
||||||
|
where T : TreePoco<T>
|
||||||
|
{
|
||||||
|
List<T> rv = new List<T>();
|
||||||
|
var children = self.Children;
|
||||||
|
if(order != null && children != null)
|
||||||
|
{
|
||||||
|
children = children.OrderBy(order).ToList();
|
||||||
|
}
|
||||||
|
if (children != null && children.Count() > 0)
|
||||||
|
{
|
||||||
|
//var dictinct = children.Where(x => x.GetID().ToString() != self.GetID().ToString()).ToList();
|
||||||
|
foreach (var item in children)
|
||||||
|
{
|
||||||
|
rv.Add(item);
|
||||||
|
//递归添加子节点的子节点
|
||||||
|
rv.AddRange(item.GetAllChildren(order));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetLevel<T>(this T self)
|
||||||
|
where T : TreePoco<T>
|
||||||
|
{
|
||||||
|
int level = 0;
|
||||||
|
while (self.Parent != null)
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
self = self.Parent;
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询数据库,根据某个节点ID递归获取其下所有级别的子节点ID
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">树形结构类</typeparam>
|
||||||
|
/// <param name="self">树形结构实例</param>
|
||||||
|
/// <param name="dc">dc</param>
|
||||||
|
/// <param name="subids">子节点ID列表</param>
|
||||||
|
/// <returns>所有级别子节点ID</returns>
|
||||||
|
public static List<Guid> GetAllChildrenIDs<T>(this T self
|
||||||
|
, IDataContext dc
|
||||||
|
, List<Guid> subids = null)
|
||||||
|
where T : TreePoco<T>
|
||||||
|
{
|
||||||
|
List<Guid> rv = new List<Guid>();
|
||||||
|
List<Guid> ids = null;
|
||||||
|
if (subids == null)
|
||||||
|
{
|
||||||
|
ids = dc.Set<T>().Where(x => x.ParentId == self.ID).Select(x => x.ID).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ids = dc.Set<T>().Where(x => subids.Contains(x.ParentId.Value)).Select(x => x.ID).ToList();
|
||||||
|
}
|
||||||
|
if (ids != null && ids.Count > 0)
|
||||||
|
{
|
||||||
|
rv.AddRange(ids);
|
||||||
|
rv.AddRange(self.GetAllChildrenIDs(dc, ids));
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将树形结构列表转变为标准列表
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">树形结构类</typeparam>
|
||||||
|
/// <param name="self">树形结构实例</param>
|
||||||
|
/// <param name="order">排序字段,可以为空</param>
|
||||||
|
/// <returns>返回标准列表,所有节点都在同一级上</returns>
|
||||||
|
public static List<T> FlatTree<T>(this List<T> self, Func<T,object> order = null)
|
||||||
|
where T :TreePoco<T>
|
||||||
|
{
|
||||||
|
List<T> rv = new List<T>();
|
||||||
|
if(order != null)
|
||||||
|
{
|
||||||
|
self = self.OrderBy(order).ToList();
|
||||||
|
}
|
||||||
|
foreach (var item in self)
|
||||||
|
{
|
||||||
|
rv.Add(item);
|
||||||
|
rv.AddRange(item.GetAllChildren(order));
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将树形结构列表转变为标准列表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">树形结构实例</param>
|
||||||
|
/// <param name="order">排序字段,可以为空</param>
|
||||||
|
/// <returns>返回标准列表,所有节点都在同一级上</returns>
|
||||||
|
public static IEnumerable<TreeSelectListItem> FlatTreeSelectList(this IEnumerable<TreeSelectListItem> self, Func<TreeSelectListItem, object> order = null)
|
||||||
|
{
|
||||||
|
List<TreeSelectListItem> rv = new List<TreeSelectListItem>();
|
||||||
|
if (order != null)
|
||||||
|
{
|
||||||
|
self = self.OrderBy(order).ToList();
|
||||||
|
}
|
||||||
|
foreach (var item in self)
|
||||||
|
{
|
||||||
|
rv.Add(item);
|
||||||
|
if (item.Children != null)
|
||||||
|
{
|
||||||
|
rv.AddRange(item.GetTreeSelectChildren(order));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取TreeSelect节点下所有子节点
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="order"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<TreeSelectListItem> GetTreeSelectChildren(this TreeSelectListItem self, Func<TreeSelectListItem, object> order = null)
|
||||||
|
{
|
||||||
|
List<TreeSelectListItem> rv = new List<TreeSelectListItem>();
|
||||||
|
var children = self.Children;
|
||||||
|
if (order != null && children != null)
|
||||||
|
{
|
||||||
|
children = children.OrderBy(order).ToList();
|
||||||
|
}
|
||||||
|
if (children != null && children.Count() > 0)
|
||||||
|
{
|
||||||
|
var dictinct = children.Where(x => x.Value != self.Value).ToList();
|
||||||
|
foreach (var item in dictinct)
|
||||||
|
{
|
||||||
|
rv.Add(item);
|
||||||
|
//递归添加子节点的子节点
|
||||||
|
rv.AddRange(item.GetTreeSelectChildren(order));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
178
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Extensions/ListExtension.cs
Normal file
178
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Extensions/ListExtension.cs
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class ListExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将数据的List转化为下拉菜单数据List
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">源数据类</typeparam>
|
||||||
|
/// <param name="self">源数据List</param>
|
||||||
|
/// <param name="textField">指向text字段的表达式</param>
|
||||||
|
/// <param name="valueField">指向value字段的表达式</param>
|
||||||
|
/// <param name="selectedCondition">默认被选中的条件</param>
|
||||||
|
/// <returns>下拉菜单数据List</returns>
|
||||||
|
public static List<ComboSelectListItem> ToListItems<T>(this List<T> self
|
||||||
|
, Expression<Func<T, object>> textField
|
||||||
|
, Expression<Func<T, object>> valueField
|
||||||
|
, Expression<Func<T, bool>> selectedCondition = null)
|
||||||
|
{
|
||||||
|
var rv = new List<ComboSelectListItem>();
|
||||||
|
if (self != null)
|
||||||
|
{
|
||||||
|
//循环列表中的数据
|
||||||
|
foreach (var item in self)
|
||||||
|
{
|
||||||
|
//获取textField的值作为text
|
||||||
|
string text = textField.Compile().Invoke(item).ToString();
|
||||||
|
//获取valueField的值作为value
|
||||||
|
string value = valueField.Compile().Invoke(item).ToString();
|
||||||
|
//添加到下拉菜单List中
|
||||||
|
ComboSelectListItem li = new ComboSelectListItem();
|
||||||
|
li.Text = text;
|
||||||
|
li.Value = value;
|
||||||
|
//如果有默认选择的条件,则将当前数据带入到判断表达式中,如果返回true,则将下拉数据的selected属性设为true
|
||||||
|
if (selectedCondition != null)
|
||||||
|
{
|
||||||
|
if (selectedCondition.Compile().Invoke(item))
|
||||||
|
{
|
||||||
|
li.Selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv.Add(li);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object ToChartData<T>(this List<T> self, int radius = 100, string seriesname = "Info")
|
||||||
|
{
|
||||||
|
//var data = string.Empty;
|
||||||
|
if (self != null && self.Count > 0)
|
||||||
|
{
|
||||||
|
var cd = self as List<ChartData>;
|
||||||
|
var i = 0;
|
||||||
|
for (i = 0; i < cd.Count; i++)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(cd[i].Series))
|
||||||
|
{
|
||||||
|
cd[i].Series = "Data";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string[] series = cd.Select(x => x.Series).Distinct().ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
var yCount = cd.GroupBy(x => x.Category).ToList();
|
||||||
|
var isScatter = cd.Any(x => x.ValueX > 0);
|
||||||
|
var dataset = "{\"source\":[";
|
||||||
|
if (isScatter)
|
||||||
|
{
|
||||||
|
dataset = "[{\"source\":[";
|
||||||
|
i = 0;
|
||||||
|
foreach (var item in cd)
|
||||||
|
{
|
||||||
|
|
||||||
|
dataset += $"[{item.ValueX},{item.Value},{item.Addition},\"{item.Category}\",\"{item.Series}\"]";
|
||||||
|
|
||||||
|
if (i < cd.Count - 1)
|
||||||
|
{
|
||||||
|
dataset += ",";
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
dataset += "]},";
|
||||||
|
for (i = 0; i < series.Length; i++)
|
||||||
|
{
|
||||||
|
dataset += $"{{\"transform\": {{\"type\": \"filter\",\"config\": {{\"dimension\": 4,\"value\": \"{series[i]}\"}}}}}}";
|
||||||
|
if (i < series.Length - 1)
|
||||||
|
{
|
||||||
|
dataset += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataset += "]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object[,] rtc = new object[yCount.Count + 1, series.Length + 1];
|
||||||
|
rtc[0, 0] = $"{seriesname}";
|
||||||
|
|
||||||
|
for (i = 0; i < series.Length; i++)
|
||||||
|
{
|
||||||
|
rtc[0, i + 1] = series[i];
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
foreach (var item in yCount)
|
||||||
|
{
|
||||||
|
rtc[i + 1, 0] = item.Key;
|
||||||
|
for (int j = 0; j < series.Length; j++)
|
||||||
|
{
|
||||||
|
var ser = item.Where(x => x.Series == series[j])?.FirstOrDefault();
|
||||||
|
if (ser != null)
|
||||||
|
{
|
||||||
|
rtc[i + 1, j + 1] = ser.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rtc[i + 1, j + 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
for (i = 0; i <= yCount.Count; i++)
|
||||||
|
{
|
||||||
|
dataset += "[";
|
||||||
|
for (int j = 0; j <= series.Length; j++)
|
||||||
|
{
|
||||||
|
dataset += $"\"{rtc[i, j]}\"";
|
||||||
|
if (j < series.Length)
|
||||||
|
{
|
||||||
|
dataset += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataset += "]";
|
||||||
|
if (i < yCount.Count)
|
||||||
|
{
|
||||||
|
dataset += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataset += "]}";
|
||||||
|
}
|
||||||
|
var seriesStr = "[";
|
||||||
|
var legend = "{\"data\":[";
|
||||||
|
var max = cd.Max(x => x.Addition);
|
||||||
|
for (i = 0; i < series.Length; i++)
|
||||||
|
{
|
||||||
|
seriesStr += $"{{\"type\":\"charttype\"";
|
||||||
|
if (isScatter)
|
||||||
|
{
|
||||||
|
seriesStr += $",\"encode\":{{\"x\":0,\"y\":1,\"tooltip\":[2,3]}},\"name\": \"{series[i]}\",\"datasetIndex\": {i + 1}";
|
||||||
|
seriesStr += $",\"symbolSize\": \"function(data) {{return data[2] / ({max} / {radius})}}\"";
|
||||||
|
}
|
||||||
|
seriesStr += "}";
|
||||||
|
legend += $"\"{series[i]}\"";
|
||||||
|
if (i < series.Length - 1)
|
||||||
|
{
|
||||||
|
seriesStr += ",";
|
||||||
|
legend += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
legend += "]}";
|
||||||
|
seriesStr += "]";
|
||||||
|
return new { dataset = dataset, series = seriesStr, legend = legend };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dataset = "{\"source\":[]}";
|
||||||
|
var seriesStr = "[]";
|
||||||
|
var legend = "{\"data\":[]}";
|
||||||
|
return new { dataset = dataset, series = seriesStr, legend = legend };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,377 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class ListVMExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取Jason格式的列表数据
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">是否需要对数据进行Json编码</param>
|
||||||
|
/// <param name="returnColumnObject">不在后台进行ColumnFormatInfo的转化,而是直接输出ColumnFormatInfo的json结构到前端,由前端处理,默认False</param>
|
||||||
|
/// <param name="enumToString"></param>
|
||||||
|
/// <returns>Json格式的数据</returns>
|
||||||
|
public static string GetDataJson<T>(this IBasePagedListVM<T, BaseSearcher> self, bool returnColumnObject = false, bool enumToString = true) where T : TopBasePoco, new()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
self.GetHeaders();
|
||||||
|
if (self.IsSearched == false)
|
||||||
|
{
|
||||||
|
self.DoSearch();
|
||||||
|
}
|
||||||
|
var el = self.GetEntityList().ToList();
|
||||||
|
//如果列表主键都为0,则生成自增主键,避免主键重复
|
||||||
|
if (el.All(x => {
|
||||||
|
var id = x.GetID();
|
||||||
|
if(id == null || (id is Guid gid && gid == Guid.Empty) || (id is int iid && iid==0) || (id is long lid && lid == 0))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} ))
|
||||||
|
{
|
||||||
|
el.ForEach(x => x.ID = Guid.NewGuid());
|
||||||
|
}
|
||||||
|
//循环生成列表数据
|
||||||
|
for (int x = 0; x < el.Count; x++)
|
||||||
|
{
|
||||||
|
var sou = el[x];
|
||||||
|
sb.Append(self.GetSingleDataJson(sou, returnColumnObject, x, enumToString));
|
||||||
|
if (x < el.Count - 1)
|
||||||
|
{
|
||||||
|
sb.Append(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $"[{sb}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetFormatResult(BaseVM vm, ColumnFormatInfo info)
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
switch (info.FormatType)
|
||||||
|
{
|
||||||
|
case ColumnFormatTypeEnum.Dialog:
|
||||||
|
rv = vm.UIService.MakeDialogButton(info.ButtonType, info.Url, info.Text, info.Width, info.Height, info.Title, info.ButtonID, info.ShowDialog, info.Resizable, info.Maxed, info.ButtonClass, info.Style).ToString();
|
||||||
|
break;
|
||||||
|
case ColumnFormatTypeEnum.Button:
|
||||||
|
rv = vm.UIService.MakeButton(info.ButtonType, info.Url, info.Text, info.Width, info.Height, info.Title, info.ButtonID, info.Resizable, info.Maxed, vm.ViewDivId, info.ButtonClass, info.Style, info.RType).ToString();
|
||||||
|
break;
|
||||||
|
case ColumnFormatTypeEnum.Download:
|
||||||
|
if (info.FileID == null)
|
||||||
|
{
|
||||||
|
rv = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = vm.UIService.MakeDownloadButton(info.ButtonType, info.FileID.Value, info.Text, vm.CurrentCS, info.ButtonClass, info.Style).ToString();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ColumnFormatTypeEnum.ViewPic:
|
||||||
|
if (info.FileID == null)
|
||||||
|
{
|
||||||
|
rv = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = vm.UIService.MakeViewButton(info.ButtonType, info.FileID.Value, info.Text, info.Width, info.Height, info.Title, info.Resizable, vm.CurrentCS, info.Maxed, info.ButtonClass, info.Style).ToString();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ColumnFormatTypeEnum.Script:
|
||||||
|
rv = vm.UIService.MakeScriptButton(info.ButtonType, info.Text, info.Script, info.ButtonID, info.Url, info.ButtonClass, info.Style).ToString();
|
||||||
|
break;
|
||||||
|
case ColumnFormatTypeEnum.Html:
|
||||||
|
rv = info.Html;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成单条数据的Json格式
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="obj">数据</param>
|
||||||
|
/// <param name="returnColumnObject">不在后台进行ColumnFormatInfo的转化,而是直接输出ColumnFormatInfo的json结构到前端,由前端处理,默认False</param>
|
||||||
|
/// <param name="index">index</param>
|
||||||
|
/// <param name="enumToString"></param>
|
||||||
|
/// <returns>Json格式的数据</returns>
|
||||||
|
public static string GetSingleDataJson<T>(this IBasePagedListVM<T, BaseSearcher> self, object obj, bool returnColumnObject, int index = 0, bool enumToString = true) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
bool inner = false;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var RowBgColor = string.Empty;
|
||||||
|
var RowColor = string.Empty;
|
||||||
|
if (obj is not T sou)
|
||||||
|
{
|
||||||
|
sou = self.CreateEmptyEntity();
|
||||||
|
}
|
||||||
|
RowBgColor = self.SetFullRowBgColor(sou);
|
||||||
|
RowColor = self.SetFullRowColor(sou);
|
||||||
|
var isSelected = self.GetIsSelected(sou);
|
||||||
|
//循环所有列
|
||||||
|
sb.Append('{');
|
||||||
|
bool containsID = false;
|
||||||
|
bool addHiddenID = false;
|
||||||
|
Dictionary<string, (string, string)> colorcolumns = new Dictionary<string, (string, string)>();
|
||||||
|
foreach (var baseCol in self.GetHeaders())
|
||||||
|
{
|
||||||
|
foreach (var col in baseCol.BottomChildren)
|
||||||
|
{
|
||||||
|
inner = false;
|
||||||
|
if (col.ColumnType != GridColumnTypeEnum.Normal)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (col.FieldName?.ToLower() == "id")
|
||||||
|
{
|
||||||
|
containsID = true;
|
||||||
|
}
|
||||||
|
var backColor = col.GetBackGroundColor(sou);
|
||||||
|
//获取ListVM中设定的单元格前景色
|
||||||
|
var foreColor = col.GetForeGroundColor(sou);
|
||||||
|
|
||||||
|
if (backColor == string.Empty)
|
||||||
|
{
|
||||||
|
backColor = RowBgColor;
|
||||||
|
}
|
||||||
|
if (foreColor == string.Empty)
|
||||||
|
{
|
||||||
|
foreColor = RowColor;
|
||||||
|
}
|
||||||
|
(string bgcolor, string forecolor) colors = (null, null);
|
||||||
|
if (backColor != string.Empty)
|
||||||
|
{
|
||||||
|
colors.bgcolor = backColor;
|
||||||
|
}
|
||||||
|
if (foreColor != string.Empty)
|
||||||
|
{
|
||||||
|
colors.forecolor = foreColor;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(colors.bgcolor) == false || string.IsNullOrEmpty(colors.forecolor) == false)
|
||||||
|
{
|
||||||
|
colorcolumns.Add(col.Field, colors);
|
||||||
|
}
|
||||||
|
//设定列名,如果是主键ID,则列名为id,如果不是主键列,则使用f0,f1,f2...这种方式命名,避免重复
|
||||||
|
var ptype = col.FieldType;
|
||||||
|
if (col.Field?.ToLower() == "children" && typeof(IEnumerable<T>).IsAssignableFrom(ptype))
|
||||||
|
{
|
||||||
|
var children = ((IEnumerable<T>)col.GetObject(obj))?.ToList();
|
||||||
|
if (children == null || children.Count == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var html = string.Empty;
|
||||||
|
|
||||||
|
if (col.EditType == EditTypeEnum.Text || col.EditType == null)
|
||||||
|
{
|
||||||
|
if (typeof(IEnumerable<T>).IsAssignableFrom(ptype))
|
||||||
|
{
|
||||||
|
var children = ((IEnumerable<T>)col.GetObject(obj))?.ToList();
|
||||||
|
if (children != null)
|
||||||
|
{
|
||||||
|
html = "[";
|
||||||
|
for (int i = 0; i < children.Count; i++)
|
||||||
|
{
|
||||||
|
var item = children[i];
|
||||||
|
html += self.GetSingleDataJson(item, returnColumnObject,0,enumToString);
|
||||||
|
if (i < children.Count - 1)
|
||||||
|
{
|
||||||
|
html += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += "]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//html = "[]";
|
||||||
|
}
|
||||||
|
inner = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (returnColumnObject == true)
|
||||||
|
{
|
||||||
|
html = col.GetText(sou, false).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var info = col.GetText(sou);
|
||||||
|
|
||||||
|
if (info is ColumnFormatInfo)
|
||||||
|
{
|
||||||
|
html = GetFormatResult(self as BaseVM, info as ColumnFormatInfo);
|
||||||
|
}
|
||||||
|
else if (info is List<ColumnFormatInfo>)
|
||||||
|
{
|
||||||
|
var temp = string.Empty;
|
||||||
|
foreach (var item in info as List<ColumnFormatInfo>)
|
||||||
|
{
|
||||||
|
temp += GetFormatResult(self as BaseVM, item);
|
||||||
|
temp += " ";
|
||||||
|
}
|
||||||
|
html = temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
html = info.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果列是布尔值,直接返回true或false,让前台生成CheckBox
|
||||||
|
if (ptype == typeof(bool) || ptype == typeof(bool?))
|
||||||
|
{
|
||||||
|
if(enumToString == false)
|
||||||
|
{
|
||||||
|
html = html.ToLower();
|
||||||
|
inner = true;
|
||||||
|
}
|
||||||
|
else if (returnColumnObject == false)
|
||||||
|
{
|
||||||
|
if (html.ToLower() == "true")
|
||||||
|
{
|
||||||
|
html = (self as BaseVM).UIService.MakeCheckBox(true, isReadOnly: true);
|
||||||
|
}
|
||||||
|
if (html.ToLower() == "false" || html == string.Empty)
|
||||||
|
{
|
||||||
|
html = (self as BaseVM).UIService.MakeCheckBox(false, isReadOnly: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (html != null && html != string.Empty)
|
||||||
|
{
|
||||||
|
html = html.ToLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果列是枚举,直接使用枚举的文本作为多语言的Key查询多语言文字
|
||||||
|
else if (ptype.IsEnumOrNullableEnum())
|
||||||
|
{
|
||||||
|
if (enumToString == true)
|
||||||
|
{
|
||||||
|
string enumdisplay = PropertyHelper.GetEnumDisplayName(ptype, html);
|
||||||
|
if (string.IsNullOrEmpty(enumdisplay) == false)
|
||||||
|
{
|
||||||
|
html = enumdisplay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If this column is a class or list, html will be set to a json string, sest inner to true to remove the "
|
||||||
|
if (returnColumnObject == true && ptype?.Namespace.Equals("System") == false && ptype?.IsEnumOrNullableEnum() == false)
|
||||||
|
{
|
||||||
|
inner = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (enumToString == false && string.IsNullOrEmpty(html))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string val = col.GetText(sou).ToString();
|
||||||
|
string name = $"{self.DetailGridPrix}[{index}].{col.Field}";
|
||||||
|
switch (col.EditType)
|
||||||
|
{
|
||||||
|
case EditTypeEnum.TextBox:
|
||||||
|
html = (self as BaseVM).UIService.MakeTextBox(name, val);
|
||||||
|
break;
|
||||||
|
case EditTypeEnum.CheckBox:
|
||||||
|
_ = bool.TryParse(val, out bool nb);
|
||||||
|
html = (self as BaseVM).UIService.MakeCheckBox(nb, null, name, "true");
|
||||||
|
break;
|
||||||
|
case EditTypeEnum.ComboBox:
|
||||||
|
html = (self as BaseVM).UIService.MakeCombo(name, col.ListItems, val);
|
||||||
|
break;
|
||||||
|
case EditTypeEnum.Datetime:
|
||||||
|
html = (self as BaseVM).UIService.MakeDateTime(name, val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(self.DetailGridPrix) == false && addHiddenID == false)
|
||||||
|
{
|
||||||
|
html += $@"<input hidden name='{self.DetailGridPrix}[{index}].ID' value='{sou.GetID()}'/>";
|
||||||
|
addHiddenID = true;
|
||||||
|
}
|
||||||
|
if (inner == false)
|
||||||
|
{
|
||||||
|
html = "\"" + html.Replace(Environment.NewLine, "").Replace("\t", string.Empty).Replace("\n", string.Empty).Replace("\r", string.Empty).Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
||||||
|
}
|
||||||
|
sb.Append($"\"{col.Field}\":");
|
||||||
|
sb.Append(html);
|
||||||
|
sb.Append(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.Append($"\"TempIsSelected\":\"{ (isSelected == true ? "1" : "0") }\"");
|
||||||
|
foreach (var cc in colorcolumns)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(cc.Value.Item1) == false)
|
||||||
|
{
|
||||||
|
string bg = cc.Value.Item1;
|
||||||
|
if (bg.StartsWith("#") == false)
|
||||||
|
{
|
||||||
|
bg = "#" + bg;
|
||||||
|
}
|
||||||
|
sb.Append($",\"{cc.Key}__bgcolor\":\"{bg}\"");
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(cc.Value.Item2) == false)
|
||||||
|
{
|
||||||
|
string fore = cc.Value.Item2;
|
||||||
|
if (fore.StartsWith("#") == false)
|
||||||
|
{
|
||||||
|
fore = "#" + fore;
|
||||||
|
}
|
||||||
|
sb.Append($",\"{cc.Key}__forecolor\":\"{fore}\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (containsID == false)
|
||||||
|
{
|
||||||
|
sb.Append($",\"ID\":\"{(sou as dynamic).ID}\"");
|
||||||
|
}
|
||||||
|
// 标识当前行数据是否被选中
|
||||||
|
sb.Append($@",""LAY_CHECKED"":{sou.Checked.ToString().ToLower()}");
|
||||||
|
sb.Append(string.Empty);
|
||||||
|
sb.Append('}');
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get json format string of ListVM's search result
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Model type</typeparam>
|
||||||
|
/// <param name="self">a listvm</param>
|
||||||
|
/// <param name="PlainText">true to return plain text, false to return formated html, such as checkbox,buttons ...</param>
|
||||||
|
/// <param name="enumToString">use enum display name</param>
|
||||||
|
/// <returns>json string</returns>
|
||||||
|
public static string GetJson<T>(this IBasePagedListVM<T, BaseSearcher> self, bool PlainText = true, bool enumToString = true) where T : TopBasePoco, new()
|
||||||
|
{
|
||||||
|
return $@"{{""Data"":{self.GetDataJson(PlainText,enumToString)},""Count"":{self.Searcher.Count},""Page"":{self.Searcher.Page},""PageCount"":{self.Searcher.PageCount},""Msg"":""success"",""Code"":200}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object GetJsonForApi<T>(this IBasePagedListVM<T, BaseSearcher> self, bool PlainText = true) where T : TopBasePoco, new()
|
||||||
|
{
|
||||||
|
return new { Data = self.GetEntityList(), Count = self.Searcher.Count, PageCount = self.Searcher.PageCount, Page = self.Searcher.Page, Msg = "success", Code = 200 };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string GetError<T>(this IBasePagedListVM<T, BaseSearcher> self) where T : TopBasePoco, new()
|
||||||
|
{
|
||||||
|
return $@"{{""Data"":{{}},""Count"":0,""Page"":0,""PageCount"":0,""Msg"":""{(self as BaseVM).MSD.GetFirstError()}"",""Code"":400}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
|
||||||
|
using WalkingTec.Mvvm.Core.Auth;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class LoginUserInfoExtension
|
||||||
|
{
|
||||||
|
public static ClaimsPrincipal CreatePrincipal(this LoginUserInfo self)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(self.ITCode)) throw new ArgumentException("Id is mandatory", nameof(self.ITCode));
|
||||||
|
var claims = new List<Claim> { new Claim(AuthConstants.JwtClaimTypes.Subject, self.ITCode) };
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(self.Name))
|
||||||
|
{
|
||||||
|
claims.Add(new Claim(AuthConstants.JwtClaimTypes.Name, self.Name));
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(self.TenantCode))
|
||||||
|
{
|
||||||
|
claims.Add(new Claim(AuthConstants.JwtClaimTypes.TenantCode, self.TenantCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = new ClaimsIdentity(
|
||||||
|
claims.Distinct(new ClaimComparer()),
|
||||||
|
AuthConstants.AuthenticationType,
|
||||||
|
AuthConstants.JwtClaimTypes.Name,
|
||||||
|
AuthConstants.JwtClaimTypes.TenantCode);
|
||||||
|
return new ClaimsPrincipal(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,323 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class PagedListExtension
|
||||||
|
{
|
||||||
|
#region MakeGridColumn 生成GridColumn
|
||||||
|
/// <summary>
|
||||||
|
/// 生成GridColumn
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
/// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
/// <param name="self">self</param>
|
||||||
|
/// <param name="ColumnExp">指向T中字段的表达式</param>
|
||||||
|
/// <param name="Format">格式化显示内容的委托函数,函数接受两个参数,第一个是整行数据,第二个是所选列的数据</param>
|
||||||
|
/// <param name="Header">表头名称</param>
|
||||||
|
/// <param name="Width">列宽</param>
|
||||||
|
/// <param name="Flex">是否填充</param>
|
||||||
|
/// <param name="AllowMultiLine">是否允许多行</param>
|
||||||
|
/// <param name="NeedGroup">是否需要分组</param>
|
||||||
|
/// <param name="ForeGroundFunc">设置前景色的委托函数</param>
|
||||||
|
/// <param name="BackGroundFunc">设置背景色的委托函数</param>
|
||||||
|
/// <returns>返回设置好的GridColumn类的实例</returns>
|
||||||
|
public static GridColumn<T> MakeGridColumn<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
, Expression<Func<T, object>> ColumnExp
|
||||||
|
, ColumnFormatCallBack<T> Format = null
|
||||||
|
, string Header = null
|
||||||
|
, int? Width = null
|
||||||
|
, int? Flex = null
|
||||||
|
, bool AllowMultiLine = true
|
||||||
|
, bool NeedGroup = false
|
||||||
|
, Func<T, string> ForeGroundFunc = null
|
||||||
|
, Func<T, string> BackGroundFunc = null)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
GridColumn<T> rv = new GridColumn<T>(ColumnExp, Format, Header, Width, Flex, AllowMultiLine, NeedGroup, ForeGroundFunc, BackGroundFunc);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MakeActionGridColumn 生成Grid动作列(增删该查)
|
||||||
|
///// <summary>
|
||||||
|
///// 生成Grid动作列(增删该查)
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
///// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
///// <param name="self">self</param>
|
||||||
|
///// <param name="Header">表头名称</param>
|
||||||
|
///// <param name="Width">列宽</param>
|
||||||
|
///// <returns>返回设置好的动作列</returns>
|
||||||
|
//public static GridColumn<T> MakeActionGridColumn<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
// , string Header = null
|
||||||
|
// , int? Width = null)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
// where V : ISearcher
|
||||||
|
//{
|
||||||
|
// ActionGridColumn<T> rv = new ActionGridColumn<T>(Header, Width);
|
||||||
|
// rv.Sortable = false;
|
||||||
|
// return rv;
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MakeGridAction 创建一个新的列表动作
|
||||||
|
///// <summary>
|
||||||
|
///// 创建一个新的列表动作
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
///// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
///// <param name="self">self</param>
|
||||||
|
///// <param name="name">动作名</param>
|
||||||
|
///// <param name="dialogTitle">弹出窗口标题</param>
|
||||||
|
///// <param name="controllerName">动作的Controller</param>
|
||||||
|
///// <param name="actionName">动作的Action</param>
|
||||||
|
///// <param name="paraType">动作类型</param>
|
||||||
|
///// <param name="showInRow">是否在每行都显示</param>
|
||||||
|
///// <param name="areaName">域名</param>
|
||||||
|
///// <param name="showDialog">是否需要弹出窗口,默认为true</param>
|
||||||
|
///// <param name="dialogWidth">弹出窗口的宽度</param>
|
||||||
|
///// <param name="dialogHeight">弹出窗口的高度</param>
|
||||||
|
///// <param name="iconCls">动作图标css,默认为null,没有图标</param>
|
||||||
|
///// <param name="hideOnToolBar">是否在工具栏隐藏 默认false</param>
|
||||||
|
///// <param name="buttonId">Button的id 默认自动生成</param>
|
||||||
|
///// <param name="isRedirect">是否在新页面打开</param>
|
||||||
|
///// <returns>列表动作</returns>
|
||||||
|
//public static GridAction MakeGridAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
// , string name
|
||||||
|
// , string dialogTitle
|
||||||
|
// , string controllerName
|
||||||
|
// , string actionName
|
||||||
|
// , GridActionParameterTypesEnum paraType
|
||||||
|
// , bool showInRow
|
||||||
|
// , string areaName = null
|
||||||
|
// , bool showDialog = true
|
||||||
|
// , int? dialogWidth = null
|
||||||
|
// , int? dialogHeight = null
|
||||||
|
// , string iconCls = null
|
||||||
|
// , bool hideOnToolBar = false
|
||||||
|
// , string buttonId = null
|
||||||
|
// , bool isRedirect = false
|
||||||
|
// , bool resizable = true)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
// where V : ISearcher
|
||||||
|
//{
|
||||||
|
// return new GridAction { Name = name, Area = areaName, ControllerName = controllerName, DialogTitle = dialogTitle, ActionName = actionName, DialogWidth = dialogWidth, DialogHeight = dialogHeight, ParameterType = paraType, ShowInRow = showInRow, OnClickFunc = null, ShowDialog = showDialog, IconCls = iconCls, HideOnToolBar = hideOnToolBar, ButtonId = buttonId, IsRedirect = isRedirect, Resizable = resizable };
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MakeScriptGridAction 创建一个执行自定义js的列表动作
|
||||||
|
///// <summary>
|
||||||
|
///// 创建一个执行自定义js的列表动作
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
///// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
///// <param name="self">self</param>
|
||||||
|
///// <param name="controllerName">动作的Controller</param>
|
||||||
|
///// <param name="actionName">动作的Action</param>
|
||||||
|
///// <param name="name">动作名</param>
|
||||||
|
///// <param name="script">点击动作按钮执行的js</param>
|
||||||
|
///// <param name="showInRow">是否在操作列中显示 默认true</param>
|
||||||
|
///// <param name="hideOnToolBar">是否在工具栏中隐藏 默认true</param>
|
||||||
|
///// <param name="areaName">动作的区域</param>
|
||||||
|
///// <param name="buttonId">Button的id 默认自动生成</param>
|
||||||
|
///// <returns>列表动作</returns>
|
||||||
|
///// <remarks>
|
||||||
|
///// 框架的自动权限验证无法验证自定义的js中跳转到的链接,
|
||||||
|
///// 所以虽然只是运行js,但如果js最终跳转到某个链接,则还是需要在这里指定Controller和Action,这样框架就可以自动判断权限
|
||||||
|
///// </remarks>
|
||||||
|
//public static GridAction MakeScriptGridAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
// , string controllerName
|
||||||
|
// , string actionName
|
||||||
|
// , string name
|
||||||
|
// , string script
|
||||||
|
// , string areaName = null
|
||||||
|
// , string buttonId = null
|
||||||
|
// , bool showInRow = true
|
||||||
|
// , bool hideOnToolBar = true
|
||||||
|
// , bool resizable = true)//add by wuwh 2014.05.07 添加hideOnToolBar参数
|
||||||
|
// where T : TopBasePoco
|
||||||
|
// where V : ISearcher
|
||||||
|
//{
|
||||||
|
// return new GridAction { Area = areaName, ControllerName = controllerName, ActionName = actionName, Name = name, OnClickFunc = script, ShowInRow = showInRow, ButtonId = buttonId, HideOnToolBar = hideOnToolBar, Resizable = resizable };
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MakeStandardAction 创建标准动作
|
||||||
|
////新增参数 whereStr
|
||||||
|
///// <summary>
|
||||||
|
///// 创建标准动作
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
///// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
///// <param name="self">self</param>
|
||||||
|
///// <param name="controllerName">动作的Controller</param>
|
||||||
|
///// <param name="standardType">标准动作类型</param>
|
||||||
|
///// <param name="dialogTitle">弹出窗口的标题</param>
|
||||||
|
///// <param name="areaName">域名</param>
|
||||||
|
///// <param name="dialogWidth">弹出窗口的宽度</param>
|
||||||
|
///// <param name="dialogHeight">弹出窗口的高度</param>
|
||||||
|
///// <param name="name">动作名,默认为‘新建’</param>
|
||||||
|
///// <param name="buttonId">Button的id 默认自动生成</param>
|
||||||
|
///// <returns>列表动作</returns>
|
||||||
|
///// <remarks>
|
||||||
|
///// 根据标准动作类型,创建默认属性的标准动作
|
||||||
|
///// </remarks>
|
||||||
|
//public static GridAction MakeStandardAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
// , string controllerName
|
||||||
|
// , GridActionStandardTypesEnum standardType
|
||||||
|
// , string dialogTitle
|
||||||
|
// , string areaName = null
|
||||||
|
// , int? dialogWidth = null
|
||||||
|
// , int? dialogHeight = null
|
||||||
|
// , string name = null
|
||||||
|
// , string buttonId = null
|
||||||
|
// , bool resizable = true
|
||||||
|
// , params Expression<Func<T, object>>[] whereStr)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
// where V : ISearcher
|
||||||
|
//{
|
||||||
|
// string iconcls = "";
|
||||||
|
// string action = "";
|
||||||
|
// string gridname = "";
|
||||||
|
// GridActionParameterTypesEnum paraType = GridActionParameterTypesEnum.NoId;
|
||||||
|
// bool showinrow = false;
|
||||||
|
// bool hideontoolbar = false;
|
||||||
|
// switch (standardType)
|
||||||
|
// {
|
||||||
|
// case GridActionStandardTypesEnum.Create:
|
||||||
|
// iconcls = "icon-add";
|
||||||
|
// action = "Create";
|
||||||
|
// gridname = "新建";
|
||||||
|
// paraType = GridActionParameterTypesEnum.NoId;
|
||||||
|
// break;
|
||||||
|
// case GridActionStandardTypesEnum.Edit:
|
||||||
|
// iconcls = "icon-edit";
|
||||||
|
// action = "Edit";
|
||||||
|
// gridname = "修改";
|
||||||
|
// paraType = GridActionParameterTypesEnum.SingleId;
|
||||||
|
// showinrow = true;
|
||||||
|
// hideontoolbar = true;
|
||||||
|
// break;
|
||||||
|
// case GridActionStandardTypesEnum.Delete:
|
||||||
|
// iconcls = "icon-delete";
|
||||||
|
// action = "Delete";
|
||||||
|
// gridname = "删除";
|
||||||
|
// paraType = GridActionParameterTypesEnum.SingleId;
|
||||||
|
// showinrow = true;
|
||||||
|
// hideontoolbar = true;
|
||||||
|
// break;
|
||||||
|
// case GridActionStandardTypesEnum.Details:
|
||||||
|
// iconcls = "icon-details";
|
||||||
|
// action = "Details";
|
||||||
|
// gridname = "详细";
|
||||||
|
// paraType = GridActionParameterTypesEnum.SingleId;
|
||||||
|
// showinrow = true;
|
||||||
|
// hideontoolbar = true;
|
||||||
|
// break;
|
||||||
|
// case GridActionStandardTypesEnum.BatchEdit:
|
||||||
|
// iconcls = "icon-edit";
|
||||||
|
// action = "BatchEdit";
|
||||||
|
// gridname = "批量修改";
|
||||||
|
// paraType = GridActionParameterTypesEnum.MultiIds;
|
||||||
|
// break;
|
||||||
|
// case GridActionStandardTypesEnum.BatchDelete:
|
||||||
|
// iconcls = "icon-delete";
|
||||||
|
// action = "BatchDelete";
|
||||||
|
// gridname = "批量删除";
|
||||||
|
// paraType = GridActionParameterTypesEnum.MultiIds;
|
||||||
|
// break;
|
||||||
|
// case GridActionStandardTypesEnum.Import:
|
||||||
|
// iconcls = "icon-details";
|
||||||
|
// action = "ImportExcelData";
|
||||||
|
// gridname = "导入";
|
||||||
|
// paraType = GridActionParameterTypesEnum.NoId;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// List<string> list = new List<string>();
|
||||||
|
// foreach (var item in whereStr)
|
||||||
|
// {
|
||||||
|
// list.Add(PropertyHelper.GetPropertyName(item));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return new GridAction { Name = (name == null ? gridname : name), DialogTitle = dialogTitle, IconCls = iconcls, ControllerName = controllerName, ActionName = action, Area = areaName, DialogWidth = dialogWidth, DialogHeight = dialogHeight, ParameterType = paraType, ShowInRow = showinrow, ShowDialog = true, HideOnToolBar = hideontoolbar, ButtonId = buttonId, Resizable = resizable, whereStr = list.ToArray() };
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MakeStandardExportAction 创建标准导出按钮
|
||||||
|
///// <summary>
|
||||||
|
///// 创建标准导出按钮
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
///// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
///// <param name="self">self</param>
|
||||||
|
///// <param name="gridid">vmGuid</param>
|
||||||
|
///// <param name="MustSelect"></param>
|
||||||
|
///// <param name="exportType">导出类型 默认null,支持所有导出</param>
|
||||||
|
///// <param name="param">参数</param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static GridAction MakeStandardExportAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
// , string gridid = null
|
||||||
|
// , bool MustSelect = false
|
||||||
|
// , ExportEnum? exportType = null
|
||||||
|
// , params KeyValuePair<string, string>[] param)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
// where V : ISearcher
|
||||||
|
//{
|
||||||
|
// string excelscript = "";
|
||||||
|
// string pdfscript = "";
|
||||||
|
|
||||||
|
// string parameters = "?";
|
||||||
|
// foreach (var item in param)
|
||||||
|
// {
|
||||||
|
// parameters += item.Key + "=" + item.Value + "&";
|
||||||
|
// }
|
||||||
|
// if (self.FromFixedCon == true)
|
||||||
|
// {
|
||||||
|
// parameters += "DONOTUSECSName=" + self.CurrentCS + "&";
|
||||||
|
// }
|
||||||
|
// parameters += "1=1";
|
||||||
|
// if (gridid == null)
|
||||||
|
// {
|
||||||
|
// gridid = "Grid" + self.UniqueId;
|
||||||
|
// }
|
||||||
|
// if (MustSelect == false)
|
||||||
|
// {
|
||||||
|
// excelscript = string.Format("FF_ShowMask(\"{1}\");FF_DownloadExcelOrPdfPost(\"{0}\",\"/WebApi/Home/ExportExcel{2}\");", gridid, "正在生成文件...", parameters);
|
||||||
|
// pdfscript = string.Format("FF_ShowMask(\"{1}\");FF_DownloadExcelOrPdfPost(\"{0}\",\"/WebApi/Home/ExportPdf{2}\");", gridid, "正在生成文件...", parameters);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// excelscript += "var sels = Ext.getCmp(\"" + gridid + "\").getSelectionModel().getSelection();";
|
||||||
|
// excelscript += "if(sels.length == 0){ FF_OpenSimpleDialog(\"" + "错误" + "\",\"" + "请至少选择一条数据" + "\");} else{";
|
||||||
|
// excelscript += string.Format("FF_ShowMask(\"{1}\");FF_DownloadExcelOrPdfPost(\"{0}\",\"/WebApi/Home/ExportExcel{2}\");", gridid, "正在生成文件...", parameters) + "}";
|
||||||
|
|
||||||
|
// pdfscript += "var sels = Ext.getCmp(\"" + gridid + "\").getSelectionModel().getSelection();";
|
||||||
|
// pdfscript += "if(sels.length == 0){ FF_OpenSimpleDialog(\"" + "错误" + "\",\"" + "请至少选择一条数据" + "\");} else{";
|
||||||
|
// pdfscript += string.Format("FF_ShowMask(\"{1}\");FF_DownloadExcelOrPdfPost(\"{0}\",\"/WebApi/Home/ExportPdf{2}\");", gridid, "正在生成文件...", parameters) + "}";
|
||||||
|
// }
|
||||||
|
// GridAction ga = null;
|
||||||
|
// if (exportType == ExportEnum.Excel)
|
||||||
|
// {
|
||||||
|
// ga = new GridAction { Area = "WebApi", ControllerName = "Home", ActionName = "ExportExcel", Name = "导出Excel", ParameterType = GridActionParameterTypesEnum.NoId, OnClickFunc = excelscript, ShowInRow = false, Resizable = true };
|
||||||
|
// }
|
||||||
|
// else if (exportType == ExportEnum.PDF)
|
||||||
|
// {
|
||||||
|
// ga = new GridAction { Area = "WebApi", ControllerName = "Home", ActionName = "ExportExcel", Name = "导出PDF", ParameterType = GridActionParameterTypesEnum.NoId, OnClickFunc = excelscript, ShowInRow = false, Resizable = true };
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// ga = new GridAction { Area = "WebApi", ControllerName = "Home", ActionName = "ExportExcel", Name = "导出", ParameterType = GridActionParameterTypesEnum.NoId, OnClickFunc = excelscript, ShowInRow = false, Resizable = true };
|
||||||
|
// GridAction excel = new GridAction { Area = "WebApi", ControllerName = "Home", ActionName = "ExportExcel", Name = "导出Excel", ParameterType = GridActionParameterTypesEnum.NoId, OnClickFunc = excelscript, ShowInRow = false, Resizable = true };
|
||||||
|
// GridAction pdf = new GridAction { Area = "WebApi", ControllerName = "Home", ActionName = "ExportPdf", Name = "导出PDF", ParameterType = GridActionParameterTypesEnum.NoId, OnClickFunc = pdfscript, ShowInRow = false, Resizable = true };
|
||||||
|
// ga.SubActions = new List<GridAction> { excel, pdf };
|
||||||
|
// }
|
||||||
|
// return ga;
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DateTime Helper
|
||||||
|
/// </summary>
|
||||||
|
public static class DateTimeHelper
|
||||||
|
{
|
||||||
|
#region DateTime Helper
|
||||||
|
|
||||||
|
public static int WeekOfYear(this DateTime self)
|
||||||
|
{
|
||||||
|
var startDayOfYear = new DateTime(self.Year,1,1);
|
||||||
|
var weekOffset = 7 - ( startDayOfYear.DayOfWeek == DayOfWeek.Sunday ? 7 : (int)startDayOfYear.DayOfWeek) + 1;
|
||||||
|
var weekOfYear = (int)Math.Ceiling((self.DayOfYear - weekOffset) / 7.0 + (weekOffset == 0 ? 0 : 1));
|
||||||
|
|
||||||
|
return weekOfYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取 指定的一周所在年份 的开始及结束时间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="yearNum">所在年份</param>
|
||||||
|
/// <param name="weekOfYear">周数</param>
|
||||||
|
/// <param name="startDay">指定周开始时间</param>
|
||||||
|
/// <param name="endDay">指定周结束时间</param>
|
||||||
|
public static void WeekDays(int yearNum, int weekOfYear, out DateTime startDay, out DateTime endDay)
|
||||||
|
{
|
||||||
|
var startDayOfYear = new DateTime(yearNum,1,1,0,0,0);
|
||||||
|
|
||||||
|
var weekOffset = 7 - ( startDayOfYear.DayOfWeek == DayOfWeek.Sunday ? 7 : (int)startDayOfYear.DayOfWeek) + 1;
|
||||||
|
startDay = startDayOfYear.AddDays(7 * (weekOfYear - (weekOffset == 0 ? 0 : 1)) + weekOffset - 7);
|
||||||
|
endDay = startDay.AddDays(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region DateTime Extensions
|
||||||
|
|
||||||
|
private static readonly DateTime _jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0,DateTimeKind.Utc);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UTC 1970/01/01 00:00:00
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime Jan1st1970 => _jan1st1970;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 时间戳 ms
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns>返回标准时间戳 单位 毫秒 注:从 1970/01/01 00:00:00 开始</returns>
|
||||||
|
public static long ToMilliseconds(this DateTime self)
|
||||||
|
{
|
||||||
|
return (long)(self.ToUniversalTime() - Jan1st1970).TotalMilliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 时间戳 microsecond
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns>返回标准时间戳 单位 微秒 注:从 1970/01/01 00:00:00 开始</returns>
|
||||||
|
public static long ToMicroseconds(this DateTime self)
|
||||||
|
{
|
||||||
|
return (long)((self.ToUniversalTime() - Jan1st1970).TotalMilliseconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前时间所在周的开始及结束时间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="startDay">指定周开始时间</param>
|
||||||
|
/// <param name="endDay">指定周结束时间</param>
|
||||||
|
public static void WeekDays(this DateTime self, out DateTime startDay, out DateTime endDay)
|
||||||
|
{
|
||||||
|
WeekDays(self.Year, self.WeekOfYear(), out startDay, out endDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
//
|
||||||
|
// DistributedCacheExtensions.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael,Vito
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 WTM
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class DistributedCacheExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CachingKey 分割符
|
||||||
|
/// </summary>
|
||||||
|
private const string SPLIT_CHAR = ":";
|
||||||
|
|
||||||
|
private static string _instanceName;
|
||||||
|
private static string InstanceName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instanceName == null)
|
||||||
|
{
|
||||||
|
_instanceName = Assembly.GetEntryAssembly().GetName().Name + SPLIT_CHAR;
|
||||||
|
}
|
||||||
|
return _instanceName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetInstanceName(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string instanceName)
|
||||||
|
{
|
||||||
|
_instanceName = instanceName + SPLIT_CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Get
|
||||||
|
|
||||||
|
public static T Get<T>(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string key)
|
||||||
|
{
|
||||||
|
var value = cache.GetString(InstanceName + key.ToLower());
|
||||||
|
if (value == null)
|
||||||
|
return default;
|
||||||
|
else
|
||||||
|
return JsonSerializer.Deserialize<T>(value,Core.CoreProgram.DefaultJsonOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<T> GetAsync<T>(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string key,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var value = await cache.GetStringAsync(InstanceName + key.ToLower(), token);
|
||||||
|
if (value == null)
|
||||||
|
return default;
|
||||||
|
else
|
||||||
|
return JsonSerializer.Deserialize<T>(value, Core.CoreProgram.DefaultJsonOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetValue<T>(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string key,
|
||||||
|
out T outValue)
|
||||||
|
{
|
||||||
|
var value = cache.GetString(InstanceName + key.ToLower());
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
outValue = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outValue = JsonSerializer.Deserialize<T>(value, Core.CoreProgram.DefaultJsonOption);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Set
|
||||||
|
|
||||||
|
public static void Add<T>(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string key,
|
||||||
|
T value,
|
||||||
|
DistributedCacheEntryOptions options = null)
|
||||||
|
{
|
||||||
|
if (options == null)
|
||||||
|
cache.Set(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, CoreProgram.DefaultJsonOption)));
|
||||||
|
else
|
||||||
|
cache.Set(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, CoreProgram.DefaultJsonOption)), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task AddAsync<T>(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string key,
|
||||||
|
T value,
|
||||||
|
DistributedCacheEntryOptions options = null,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (options == null)
|
||||||
|
await cache.SetAsync(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, CoreProgram.DefaultJsonOption)), token);
|
||||||
|
else
|
||||||
|
await cache.SetAsync(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, CoreProgram.DefaultJsonOption)), options, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Delete
|
||||||
|
|
||||||
|
public static void Delete(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string key)
|
||||||
|
{
|
||||||
|
cache.Remove(InstanceName + key.ToLower());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task DeleteAsync(
|
||||||
|
this IDistributedCache cache,
|
||||||
|
string key,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
await cache.RemoveAsync(InstanceName + key.ToLower(), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 枚举扩展函数
|
||||||
|
/// </summary>
|
||||||
|
public static class EnumExtension
|
||||||
|
{
|
||||||
|
#region 将枚举类型转化为下拉列表
|
||||||
|
/// <summary>
|
||||||
|
/// 将枚举类型转化为下拉列表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">枚举类型</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
/// <param name="pleaseSelect">pleaseSelect</param>
|
||||||
|
/// <returns>下拉菜单数据列表</returns>
|
||||||
|
public static List<ComboSelectListItem> ToListItems(this Type self, object value = null, bool pleaseSelect = false)
|
||||||
|
{
|
||||||
|
string[] names = null;
|
||||||
|
Array values = null;
|
||||||
|
//如果是枚举
|
||||||
|
if (self.IsEnum)
|
||||||
|
{
|
||||||
|
names = Enum.GetNames(self);
|
||||||
|
values = Enum.GetValues(self);
|
||||||
|
}
|
||||||
|
//如果是nullable的枚举
|
||||||
|
if (self.IsGenericType && self.GenericTypeArguments[0].IsEnum)
|
||||||
|
{
|
||||||
|
names = Enum.GetNames(self.GenericTypeArguments[0]);
|
||||||
|
values = Enum.GetValues(self.GenericTypeArguments[0]);
|
||||||
|
}
|
||||||
|
//生成下拉菜单数据
|
||||||
|
List<ComboSelectListItem> rv = new List<ComboSelectListItem>();
|
||||||
|
if (names != null)
|
||||||
|
{
|
||||||
|
for(int i=0;i<names.Length;i++)
|
||||||
|
{
|
||||||
|
var name = names[i];
|
||||||
|
var newitem = new ComboSelectListItem { Text = PropertyHelper.GetEnumDisplayName(self, name), Value = values.GetValue(i).ToString() };
|
||||||
|
if(value is string)
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
string v = value.ToString();
|
||||||
|
var vs = v.Split(',');
|
||||||
|
foreach (var item in vs)
|
||||||
|
{
|
||||||
|
if (item != null && (newitem.Value.ToString() == item.ToString())||name == item.ToString())
|
||||||
|
{
|
||||||
|
newitem.Selected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (value is IEnumerable it)
|
||||||
|
{
|
||||||
|
foreach (var item in it)
|
||||||
|
{
|
||||||
|
if (item != null && name == item.ToString())
|
||||||
|
{
|
||||||
|
newitem.Selected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value != null && name == value.ToString())
|
||||||
|
{
|
||||||
|
newitem.Selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv.Add(newitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pleaseSelect == true)
|
||||||
|
{
|
||||||
|
rv.Insert(0, new ComboSelectListItem { Text = CoreProgram._localizer?["Sys.PleaseSelect"], Value = "" });
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,230 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 字符串辅助类
|
||||||
|
/// </summary>
|
||||||
|
public static class StringExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 根据名字获取Id形式
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fieldName">名字</param>
|
||||||
|
/// <returns>将[].转换成_形式的Id</returns>
|
||||||
|
public static string GetIdByName(this string fieldName)
|
||||||
|
{
|
||||||
|
return fieldName == null ? "" : fieldName.Replace(".", "_").Replace("[", "_").Replace("]", "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 格式化URL
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">初始url</param>
|
||||||
|
/// <returns>格式化后的url</returns>
|
||||||
|
public static string CorrectUrl(this string url)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(url) == true)
|
||||||
|
{
|
||||||
|
url = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = url.ToLower();
|
||||||
|
url = url.Trim('/', '\\');
|
||||||
|
if (url.StartsWith("http://") == false && url.StartsWith("https://") == false)
|
||||||
|
{
|
||||||
|
url = "http://" + url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 将数据列表转化为逗号分隔的字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">源数据类</typeparam>
|
||||||
|
/// <typeparam name="V">文本字段</typeparam>
|
||||||
|
/// <param name="self">源数据List</param>
|
||||||
|
/// <param name="textField">要拼接的文本字段</param>
|
||||||
|
/// <param name="Format">转化文本字段的表达式</param>
|
||||||
|
/// <param name="seperator">分隔符,默认为逗号</param>
|
||||||
|
/// <returns>转化后的字符串</returns>
|
||||||
|
public static string ToSepratedString<T, V>(this IEnumerable<T> self, Expression<Func<T, V>> textField, Func<V, string> Format = null, string seperator = ",")
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
//循环所有数据
|
||||||
|
for (int i = 0; i < self.Count(); i++)
|
||||||
|
{
|
||||||
|
//获取文本字段的值
|
||||||
|
V text = textField.Compile().Invoke(self.ElementAt(i));
|
||||||
|
string str = "";
|
||||||
|
//如果有转换函数,则调用获取转换后的字符串
|
||||||
|
if (Format == null)
|
||||||
|
{
|
||||||
|
if (text == null)
|
||||||
|
{
|
||||||
|
str = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str = text.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str = Format.Invoke(text);
|
||||||
|
}
|
||||||
|
rv += str;
|
||||||
|
//拼接分隔符
|
||||||
|
if (i < self.Count() - 1)
|
||||||
|
{
|
||||||
|
rv += seperator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//返回转化后的字符串
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToSepratedString(this IEnumerable self, Func<object, string> Format = null, string seperator = ",")
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
foreach (var item in self)
|
||||||
|
{
|
||||||
|
var s = "";
|
||||||
|
if (Format == null)
|
||||||
|
{
|
||||||
|
s = item.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s = Format.Invoke(item);
|
||||||
|
}
|
||||||
|
if(string.IsNullOrEmpty(s) == false)
|
||||||
|
{
|
||||||
|
rv += s + seperator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rv.Length > 0)
|
||||||
|
{
|
||||||
|
rv = rv.Substring(0, rv.Length - 1);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToSepratedString(this NameValueCollection self, string seperator = ",")
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
foreach (var item in self)
|
||||||
|
{
|
||||||
|
rv += item.ToString() + "=" + self[item.ToString()] + seperator;
|
||||||
|
}
|
||||||
|
if (rv.Length > 0)
|
||||||
|
{
|
||||||
|
rv = rv.Substring(0, rv.Length - 1);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AppendQuery(this string self,string query)
|
||||||
|
{
|
||||||
|
if(self == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (self.Contains("?"))
|
||||||
|
{
|
||||||
|
self += "&" + query;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self += "?" + query;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AppendQuery(this string self, IDictionary data)
|
||||||
|
{
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string query = "";
|
||||||
|
foreach (IDictionaryEnumerator item in data)
|
||||||
|
{
|
||||||
|
query += item.Key + "=" + item.Value + "&";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.Contains("?"))
|
||||||
|
{
|
||||||
|
self += "&" + query;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self += "?" + query;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AppendQuery(this string self, List<KeyValuePair<string, string>> data)
|
||||||
|
{
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string query = "";
|
||||||
|
foreach (var item in data)
|
||||||
|
{
|
||||||
|
query += item.Key + "=" + item.Value + "&";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.Contains("?"))
|
||||||
|
{
|
||||||
|
self += "&" + query;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self += "?" + query;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToQueryString(this IEnumerable self, string name=null)
|
||||||
|
{
|
||||||
|
if(self == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
name = "id";
|
||||||
|
}
|
||||||
|
string rv = "";
|
||||||
|
foreach (var item in self)
|
||||||
|
{
|
||||||
|
rv += $"{name}={item?.ToString()}&";
|
||||||
|
}
|
||||||
|
if(rv.Length > 0)
|
||||||
|
{
|
||||||
|
rv = rv[0..^1];
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// System Extension
|
||||||
|
/// </summary>
|
||||||
|
public static class SystemExtension
|
||||||
|
{
|
||||||
|
#region Guid Extensions
|
||||||
|
|
||||||
|
public static string ToNoSplitString(this Guid self)
|
||||||
|
{
|
||||||
|
return self.ToString().Replace("-", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将CrudVM中Entity的关联字段设为空并返回一个新的CrudVM
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static object GetCleanCrudVM(this object self)
|
||||||
|
{
|
||||||
|
var mtype = self.GetType();
|
||||||
|
if(typeof(IBaseCRUDVM<TopBasePoco>).IsAssignableFrom(mtype))
|
||||||
|
{
|
||||||
|
var rv = mtype.GetConstructor(Type.EmptyTypes).Invoke(null);
|
||||||
|
var toppros = mtype.GetAllProperties();
|
||||||
|
foreach (var tpro in toppros)
|
||||||
|
{
|
||||||
|
if(tpro.Name == "Entity")
|
||||||
|
{
|
||||||
|
var entity = tpro.GetValue(self);
|
||||||
|
var pros = tpro.PropertyType.GetAllProperties();
|
||||||
|
var newEntity = tpro.PropertyType.GetConstructor(Type.EmptyTypes).Invoke(null);
|
||||||
|
bool isBasePoco = typeof(IBasePoco).IsAssignableFrom(tpro.PropertyType);
|
||||||
|
//将所有TopBasePoco的属性赋空值,防止添加关联的重复内容
|
||||||
|
foreach (var pro in pros)
|
||||||
|
{
|
||||||
|
if (pro.PropertyType.GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)) == false)
|
||||||
|
{
|
||||||
|
if (isBasePoco == false || (pro.Name != "UpdateTime" && pro.Name != "UpdateBy"))
|
||||||
|
{
|
||||||
|
pro.SetValue(newEntity, pro.GetValue(entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tpro.SetValue(rv, newEntity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tpro.CanWrite)
|
||||||
|
{
|
||||||
|
tpro.SetValue(rv, tpro.GetValue(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,527 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Fare;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Type的扩展函数
|
||||||
|
/// </summary>
|
||||||
|
public static class TypeExtension
|
||||||
|
{
|
||||||
|
public static ImmutableDictionary<string, List<PropertyInfo>> _propertyCache { get; set; } = new Dictionary<string, List<PropertyInfo>>().ToImmutableDictionary();
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否是泛型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">Type类</param>
|
||||||
|
/// <param name="innerType">泛型类型</param>
|
||||||
|
/// <returns>判断结果</returns>
|
||||||
|
public static bool IsGeneric(this Type self, Type innerType)
|
||||||
|
{
|
||||||
|
if (self.GetTypeInfo().IsGenericType && self.GetGenericTypeDefinition() == innerType)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否为Nullable<>类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">Type类</param>
|
||||||
|
/// <returns>判断结果</returns>
|
||||||
|
public static bool IsNullable(this Type self)
|
||||||
|
{
|
||||||
|
return self.IsGeneric(typeof(Nullable<>));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否为List<>类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">Type类</param>
|
||||||
|
/// <returns>判断结果</returns>
|
||||||
|
public static bool IsList(this Type self)
|
||||||
|
{
|
||||||
|
return self.IsGeneric(typeof(List<>)) || self.IsGeneric(typeof(IEnumerable<>));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否为List<>类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">Type类</param>
|
||||||
|
/// <returns>判断结果</returns>
|
||||||
|
public static bool IsListOf<T>(this Type self)
|
||||||
|
{
|
||||||
|
if (self.IsGeneric(typeof(List<>)) && typeof(T).IsAssignableFrom(self.GenericTypeArguments[0]))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 判断是否为枚举
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否为枚举
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">Type类</param>
|
||||||
|
/// <returns>判断结果</returns>
|
||||||
|
public static bool IsEnum(this Type self)
|
||||||
|
{
|
||||||
|
return self.GetTypeInfo().IsEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否为枚举或者可空枚举
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsEnumOrNullableEnum(this Type self)
|
||||||
|
{
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (self.IsEnum)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (self.IsGenericType && self.GetGenericTypeDefinition() == typeof(Nullable<>) && self.GetGenericArguments()[0].IsEnum)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否为值类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">Type类</param>
|
||||||
|
/// <returns>判断结果</returns>
|
||||||
|
public static bool IsPrimitive(this Type self)
|
||||||
|
{
|
||||||
|
return self.GetTypeInfo().IsPrimitive || self == typeof(decimal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsNumber(this Type self)
|
||||||
|
{
|
||||||
|
Type checktype = self;
|
||||||
|
if (self.IsNullable())
|
||||||
|
{
|
||||||
|
checktype = self.GetGenericArguments()[0];
|
||||||
|
}
|
||||||
|
if (checktype == typeof(int) || checktype == typeof(short) || checktype == typeof(long) || checktype == typeof(float) || checktype == typeof(decimal) || checktype == typeof(double))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 判断是否是Bool
|
||||||
|
|
||||||
|
public static bool IsBool(this Type self)
|
||||||
|
{
|
||||||
|
return self == typeof(bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否是 bool or bool?类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsBoolOrNullableBool(this Type self)
|
||||||
|
{
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (self == typeof(bool) || self == typeof(bool?))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static Dictionary<string, string> GetRandomValues(this Type self)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> rv = new Dictionary<string, string>();
|
||||||
|
string pat = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||||
|
var pros = self.GetAllProperties();
|
||||||
|
List<string> skipFields = new List<string>()
|
||||||
|
{
|
||||||
|
nameof(TopBasePoco.BatchError),
|
||||||
|
nameof(TopBasePoco.Checked),
|
||||||
|
nameof(TopBasePoco.ExcelIndex),
|
||||||
|
};
|
||||||
|
if (typeof(IBasePoco).IsAssignableFrom(self))
|
||||||
|
{
|
||||||
|
skipFields.AddRange(
|
||||||
|
new string[]{
|
||||||
|
nameof(IBasePoco.CreateBy),
|
||||||
|
nameof(IBasePoco.CreateTime),
|
||||||
|
nameof(IBasePoco.UpdateBy),
|
||||||
|
nameof(IBasePoco.UpdateTime) }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (typeof(IPersistPoco).IsAssignableFrom(self))
|
||||||
|
{
|
||||||
|
skipFields.Add(nameof(IPersistPoco.IsValid));
|
||||||
|
}
|
||||||
|
foreach (var pro in pros)
|
||||||
|
{
|
||||||
|
string key = pro.Name;
|
||||||
|
string val = "";
|
||||||
|
var notmapped = pro.GetCustomAttribute<NotMappedAttribute>();
|
||||||
|
if (notmapped == null &&
|
||||||
|
pro.PropertyType.IsList() == false &&
|
||||||
|
pro.PropertyType.IsSubclassOf(typeof(TopBasePoco)) == false &&
|
||||||
|
skipFields.Contains(key) == false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (pro.PropertyType.IsNumber())
|
||||||
|
{
|
||||||
|
var range = pro.GetCustomAttribute<RangeAttribute>();
|
||||||
|
int start = 0;
|
||||||
|
int end = 100;
|
||||||
|
if (range != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
start = (int)Math.Truncate(double.Parse(range.Minimum.ToString()));
|
||||||
|
end = (int)Math.Truncate(double.Parse(range.Maximum.ToString()));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
Random r = new Random();
|
||||||
|
val = r.Next(start, end).ToString();
|
||||||
|
}
|
||||||
|
else if (pro.PropertyType.IsBoolOrNullableBool())
|
||||||
|
{
|
||||||
|
List<string> boolvalues = new List<string> { "true", "false" };
|
||||||
|
if (pro.PropertyType.IsNullable())
|
||||||
|
{
|
||||||
|
boolvalues.Add("null");
|
||||||
|
}
|
||||||
|
Random r = new Random();
|
||||||
|
var index = r.Next(0, boolvalues.Count);
|
||||||
|
val = boolvalues[index];
|
||||||
|
}
|
||||||
|
else if (pro.PropertyType.IsEnumOrNullableEnum())
|
||||||
|
{
|
||||||
|
List<string> enumvalues = new List<string>();
|
||||||
|
Type enumtype = null;
|
||||||
|
if (pro.PropertyType.IsNullable())
|
||||||
|
{
|
||||||
|
enumtype = pro.PropertyType.GenericTypeArguments[0];
|
||||||
|
enumvalues.Add("null");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enumtype = pro.PropertyType;
|
||||||
|
}
|
||||||
|
var vs = Enum.GetValues(enumtype);
|
||||||
|
Random r = new Random();
|
||||||
|
var index = r.Next(0, vs.Length);
|
||||||
|
val = enumtype.FullName+"."+ vs.GetValue(index).ToString();
|
||||||
|
}
|
||||||
|
else if (pro.PropertyType == typeof(string))
|
||||||
|
{
|
||||||
|
var length = pro.GetCustomAttribute<StringLengthAttribute>();
|
||||||
|
var min = 1;
|
||||||
|
var max = 20;
|
||||||
|
var l = 0;
|
||||||
|
if (length != null)
|
||||||
|
{
|
||||||
|
if (length.MaximumLength > 0)
|
||||||
|
{
|
||||||
|
max = length.MaximumLength;
|
||||||
|
}
|
||||||
|
if(length.MinimumLength > 0)
|
||||||
|
{
|
||||||
|
min = length.MinimumLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(min == max)
|
||||||
|
{
|
||||||
|
l = max;
|
||||||
|
}
|
||||||
|
else if(min < max)
|
||||||
|
{
|
||||||
|
l = new Random().Next(min, max);
|
||||||
|
}
|
||||||
|
Random r = new Random();
|
||||||
|
for (int i = 0; i < l; i++)
|
||||||
|
{
|
||||||
|
int index = r.Next(pat.Length);
|
||||||
|
val += pat[index];
|
||||||
|
}
|
||||||
|
val = "\"" + val + "\"";
|
||||||
|
}
|
||||||
|
else if(pro.PropertyType == typeof(DateTime) || pro.PropertyType == typeof(DateTime?))
|
||||||
|
{
|
||||||
|
Random r = new Random();
|
||||||
|
val = DateTime.Now.AddDays(r.Next(-500, 500)).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
val = $"DateTime.Parse(\"{val}\")";
|
||||||
|
}
|
||||||
|
if (pros.Where(x => x.Name.ToLower() + "id" == key.ToLower()).Any())
|
||||||
|
{
|
||||||
|
val = "$fk$";
|
||||||
|
}
|
||||||
|
if (val != "")
|
||||||
|
{
|
||||||
|
if (rv.ContainsKey(key) == false)
|
||||||
|
{
|
||||||
|
rv.Add(key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, string> GetRandomValuesForTestData(this Type self)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> rv = new Dictionary<string, string>();
|
||||||
|
string pat = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||||
|
var pros = self.GetAllProperties();
|
||||||
|
List<string> skipFields = new List<string>()
|
||||||
|
{
|
||||||
|
nameof(TopBasePoco.BatchError),
|
||||||
|
nameof(TopBasePoco.Checked),
|
||||||
|
nameof(TopBasePoco.ExcelIndex),
|
||||||
|
};
|
||||||
|
if (typeof(IBasePoco).IsAssignableFrom(self))
|
||||||
|
{
|
||||||
|
skipFields.AddRange(
|
||||||
|
new string[]{
|
||||||
|
nameof(IBasePoco.CreateBy),
|
||||||
|
nameof(IBasePoco.CreateTime),
|
||||||
|
nameof(IBasePoco.UpdateBy),
|
||||||
|
nameof(IBasePoco.UpdateTime) }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (typeof(IPersistPoco).IsAssignableFrom(self))
|
||||||
|
{
|
||||||
|
skipFields.Add(nameof(IPersistPoco.IsValid));
|
||||||
|
}
|
||||||
|
foreach (var pro in pros)
|
||||||
|
{
|
||||||
|
string key = pro.Name;
|
||||||
|
string val = "";
|
||||||
|
var notmapped = pro.GetCustomAttribute<NotMappedAttribute>();
|
||||||
|
var required = pro.GetCustomAttributes<RequiredAttribute>() != null;
|
||||||
|
if (notmapped == null &&
|
||||||
|
pro.PropertyType.IsList() == false &&
|
||||||
|
pro.PropertyType.IsSubclassOf(typeof(TopBasePoco)) == false &&
|
||||||
|
skipFields.Contains(key) == false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (pro.PropertyType.IsNumber())
|
||||||
|
{
|
||||||
|
if (pro.Name == "ID")
|
||||||
|
{
|
||||||
|
val = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var range = pro.GetCustomAttribute<RangeAttribute>();
|
||||||
|
int start = 0;
|
||||||
|
int end = 100;
|
||||||
|
if (range != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
start = (int)Math.Truncate(double.Parse(range.Minimum.ToString()));
|
||||||
|
end = (int)Math.Truncate(double.Parse(range.Maximum.ToString()));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
Random r = new Random();
|
||||||
|
val = r.Next(start, end).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pro.PropertyType.IsBoolOrNullableBool())
|
||||||
|
{
|
||||||
|
List<string> boolvalues = new List<string> { "true", "false" };
|
||||||
|
if (pro.PropertyType.IsNullable())
|
||||||
|
{
|
||||||
|
if (required == false)
|
||||||
|
{
|
||||||
|
boolvalues.Add("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Random r = new Random();
|
||||||
|
var index = r.Next(0, boolvalues.Count);
|
||||||
|
val = boolvalues[index];
|
||||||
|
}
|
||||||
|
else if (pro.PropertyType.IsEnumOrNullableEnum())
|
||||||
|
{
|
||||||
|
List<string> enumvalues = new List<string>();
|
||||||
|
Type enumtype = null;
|
||||||
|
if (pro.PropertyType.IsNullable())
|
||||||
|
{
|
||||||
|
enumtype = pro.PropertyType.GenericTypeArguments[0];
|
||||||
|
if (required == false)
|
||||||
|
{
|
||||||
|
enumvalues.Add("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enumtype = pro.PropertyType;
|
||||||
|
}
|
||||||
|
var vs = Enum.GetValues(enumtype);
|
||||||
|
foreach (var item in vs)
|
||||||
|
{
|
||||||
|
enumvalues.Add((int)item + "");
|
||||||
|
}
|
||||||
|
Random r = new Random();
|
||||||
|
var index = r.Next(0, enumvalues.Count);
|
||||||
|
val = enumvalues[index];
|
||||||
|
}
|
||||||
|
else if (pro.PropertyType == typeof(string))
|
||||||
|
{
|
||||||
|
|
||||||
|
var reg = pro.GetCustomAttribute<RegularExpressionAttribute>();
|
||||||
|
var length = pro.GetCustomAttribute<StringLengthAttribute>();
|
||||||
|
|
||||||
|
if (reg != null) {
|
||||||
|
Xeger x = new Xeger(reg.Pattern);
|
||||||
|
val = x.Generate();
|
||||||
|
if(length != null)
|
||||||
|
{
|
||||||
|
if(length.MaximumLength > 0 && val.Length > length.MaximumLength)
|
||||||
|
{
|
||||||
|
val = val.Substring(0, length.MaximumLength-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var min = 1;
|
||||||
|
var max = 20;
|
||||||
|
var l = 0;
|
||||||
|
if (length != null)
|
||||||
|
{
|
||||||
|
if (length.MaximumLength > 0)
|
||||||
|
{
|
||||||
|
max = length.MaximumLength;
|
||||||
|
}
|
||||||
|
if (length.MinimumLength > 0)
|
||||||
|
{
|
||||||
|
min = length.MinimumLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (min == max)
|
||||||
|
{
|
||||||
|
l = max;
|
||||||
|
}
|
||||||
|
else if (min < max)
|
||||||
|
{
|
||||||
|
l = new Random().Next(min, max);
|
||||||
|
}
|
||||||
|
Random r = new Random();
|
||||||
|
for (int i = 0; i < l; i++)
|
||||||
|
{
|
||||||
|
int index = r.Next(pat.Length);
|
||||||
|
val += pat[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val = "\"" + val + "\"";
|
||||||
|
}
|
||||||
|
else if (pro.PropertyType == typeof(DateTime) || pro.PropertyType == typeof(DateTime?))
|
||||||
|
{
|
||||||
|
Random r = new Random();
|
||||||
|
val = DateTime.Now.AddDays(r.Next(-500, 500)).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
}
|
||||||
|
if (pros.Where(x => x.Name.ToLower() + "id" == key.ToLower()).Any())
|
||||||
|
{
|
||||||
|
val = "$fk$";
|
||||||
|
}
|
||||||
|
if (val != "")
|
||||||
|
{
|
||||||
|
if (rv.ContainsKey(key) == false)
|
||||||
|
{
|
||||||
|
rv.Add(key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static PropertyInfo GetSingleProperty(this Type self, string name)
|
||||||
|
{
|
||||||
|
if (_propertyCache.ContainsKey(self.FullName) == false)
|
||||||
|
{
|
||||||
|
var properties = self.GetProperties().ToList();
|
||||||
|
_propertyCache = _propertyCache.Add(self.FullName, properties);
|
||||||
|
return properties.Where(x => x.Name == name).FirstOrDefault();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _propertyCache[self.FullName].Where(x => x.Name == name).FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PropertyInfo GetSingleProperty(this Type self, Func<PropertyInfo,bool> where)
|
||||||
|
{
|
||||||
|
if (_propertyCache.ContainsKey(self.FullName) == false)
|
||||||
|
{
|
||||||
|
var properties = self.GetProperties().ToList();
|
||||||
|
_propertyCache = _propertyCache.Add(self.FullName, properties);
|
||||||
|
return properties.Where(where).FirstOrDefault();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _propertyCache[self.FullName].Where(where).FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<PropertyInfo> GetAllProperties(this Type self)
|
||||||
|
{
|
||||||
|
if (_propertyCache.ContainsKey(self.FullName) == false)
|
||||||
|
{
|
||||||
|
var properties = self.GetProperties().ToList();
|
||||||
|
_propertyCache = _propertyCache.Add(self.FullName, properties);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _propertyCache[self.FullName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
10
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/GlobalConstants.cs
Normal file
10
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/GlobalConstants.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public static class GlobalConstants
|
||||||
|
{
|
||||||
|
public static class CacheKey
|
||||||
|
{
|
||||||
|
public const string UserInfo = "WtmUserInfo";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/GlobalData.cs
Normal file
59
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/GlobalData.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using WalkingTec.Mvvm.Core.Support.Json;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 应用全局缓存
|
||||||
|
/// </summary>
|
||||||
|
public class GlobalData
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 程序集
|
||||||
|
/// </summary>
|
||||||
|
public List<Assembly> AllAssembly { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可访问的url地址
|
||||||
|
/// </summary>
|
||||||
|
public List<string> AllAccessUrls { get; set; }
|
||||||
|
|
||||||
|
public Type CustomUserType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 模块
|
||||||
|
/// </summary>
|
||||||
|
public List<SimpleModule> AllModule { get; set; }
|
||||||
|
|
||||||
|
private Func<List<SimpleMenu>> MenuGetFunc;
|
||||||
|
|
||||||
|
public List<SimpleMenu> AllMenus => MenuGetFunc?.Invoke();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置菜单委托
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="func"></param>
|
||||||
|
public void SetMenuGetFunc(Func<List<SimpleMenu>> func) => MenuGetFunc = func;
|
||||||
|
|
||||||
|
public List<Type> GetTypesAssignableFrom<T>()
|
||||||
|
{
|
||||||
|
var rv = new List<Type>();
|
||||||
|
foreach (var ass in AllAssembly)
|
||||||
|
{
|
||||||
|
var types = new List<Type>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
types.AddRange(ass.GetExportedTypes());
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
rv.AddRange(types.Where(x => typeof(T).IsAssignableFrom(x) && x != typeof(T) && x.IsAbstract == false).ToList());
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
70
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/GlobalServices.cs
Normal file
70
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/GlobalServices.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// GlobalServices
|
||||||
|
/// </summary>
|
||||||
|
//public static class GlobalServices
|
||||||
|
//{
|
||||||
|
// private static IServiceProvider _serviceProvider = null;
|
||||||
|
// /// <summary>
|
||||||
|
// /// IocContainer
|
||||||
|
// /// </summary>
|
||||||
|
// public static IServiceProvider ServiceProvider => _serviceProvider;
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// SetServiceProvider
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="container"></param>
|
||||||
|
// public static void SetServiceProvider(IServiceProvider container) { _serviceProvider = container; }
|
||||||
|
|
||||||
|
// #region GetServicce
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// GetService
|
||||||
|
// /// </summary>
|
||||||
|
// /// <typeparam name="T"></typeparam>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public static T GetService<T>() where T : class => ServiceProvider?.GetService<T>();
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// GetService
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="type"></param>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public static object GetService(Type type) => ServiceProvider?.GetService(type);
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// GetServices
|
||||||
|
// /// </summary>
|
||||||
|
// /// <typeparam name="T"></typeparam>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public static IEnumerable<T> GetServices<T>() where T : class => ServiceProvider?.GetServices<T>();
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// GetServices
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="type"></param>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public static IEnumerable<object> GetServices(Type type) => ServiceProvider?.GetServices(type);
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// GetRequiredService
|
||||||
|
// /// </summary>
|
||||||
|
// /// <typeparam name="T"></typeparam>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public static T GetRequiredService<T>() where T : class => ServiceProvider?.GetRequiredService<T>();
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// GetRequiredService
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="type"></param>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public static object GetRequiredService(Type type) => ServiceProvider?.GetRequiredService(type);
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
//}
|
||||||
|
}
|
224
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridAction.cs
Normal file
224
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridAction.cs
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
#region 列表动作类型
|
||||||
|
/// <summary>
|
||||||
|
/// 列表动作类型
|
||||||
|
/// </summary>
|
||||||
|
public enum GridActionParameterTypesEnum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 不需要传递Id
|
||||||
|
/// </summary>
|
||||||
|
NoId,
|
||||||
|
/// <summary>
|
||||||
|
/// 只传递一个Id
|
||||||
|
/// </summary>
|
||||||
|
SingleId,
|
||||||
|
/// <summary>
|
||||||
|
/// 传递多个Id
|
||||||
|
/// </summary>
|
||||||
|
MultiIds,
|
||||||
|
/// <summary>
|
||||||
|
/// 只传递一个Id,但 Id 可能为null
|
||||||
|
/// </summary>
|
||||||
|
SingleIdWithNull,
|
||||||
|
/// <summary>
|
||||||
|
/// 传递多个 Id 或 null
|
||||||
|
/// </summary>
|
||||||
|
MultiIdWithNull,
|
||||||
|
AddRow,
|
||||||
|
RemoveRow
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 标准列表动作
|
||||||
|
/// <summary>
|
||||||
|
/// 标准列表动作
|
||||||
|
/// </summary>
|
||||||
|
public enum GridActionStandardTypesEnum
|
||||||
|
{
|
||||||
|
Create,
|
||||||
|
Edit,
|
||||||
|
Delete,
|
||||||
|
SimpleDelete,
|
||||||
|
Details,
|
||||||
|
BatchEdit,
|
||||||
|
BatchDelete,
|
||||||
|
SimpleBatchDelete,
|
||||||
|
Import,
|
||||||
|
ExportExcel,
|
||||||
|
AddRow,
|
||||||
|
RemoveRow,
|
||||||
|
ActionsGroup
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 导出枚举
|
||||||
|
public enum ExportEnum
|
||||||
|
{
|
||||||
|
[Display(Name = "Excel")]
|
||||||
|
Excel = 0,
|
||||||
|
[Display(Name = "PDF")]
|
||||||
|
PDF = 1
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列表动作类,负责处理列表动作条中的动作按钮
|
||||||
|
/// </summary>
|
||||||
|
public class GridAction
|
||||||
|
{
|
||||||
|
#region Action属性
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按钮Id,一般不需要设定,系统会自动生成唯一Id。如果设定请确保 Id 的唯一性
|
||||||
|
/// </summary>
|
||||||
|
public string ButtonId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按钮名称
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 弹出窗口的标题
|
||||||
|
/// </summary>
|
||||||
|
public string DialogTitle { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 如果不为null,则只运行这个变量设定的script,其他的属性都不起作用
|
||||||
|
/// </summary>
|
||||||
|
public string OnClickFunc { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在每行都显示
|
||||||
|
/// </summary>
|
||||||
|
public bool ShowInRow { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在工具栏上隐藏按钮
|
||||||
|
/// </summary>
|
||||||
|
public bool HideOnToolBar { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// bind to a column name to deside whether or not to show this action
|
||||||
|
/// </summary>
|
||||||
|
public string BindVisiableColName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// additional css class of button
|
||||||
|
/// </summary>
|
||||||
|
public string ButtonClass { get; set;}
|
||||||
|
/// <summary>
|
||||||
|
/// if the dialog need to be maximax
|
||||||
|
/// </summary>
|
||||||
|
public bool Max { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this action is to download a file
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDownload { get; set; }
|
||||||
|
|
||||||
|
#region 请求链接相关
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的Area
|
||||||
|
/// </summary>
|
||||||
|
public string Area { get; set; }
|
||||||
|
|
||||||
|
public bool IsExport { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的Controller
|
||||||
|
/// </summary>
|
||||||
|
public string ControllerName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的Action
|
||||||
|
/// </summary>
|
||||||
|
public string ActionName { get; set; }
|
||||||
|
|
||||||
|
public string Url
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var rv = "";
|
||||||
|
if(string.IsNullOrEmpty(ControllerName) == false){
|
||||||
|
rv = $"/{HttpUtility.UrlEncode(ControllerName)}/{HttpUtility.UrlEncode(ActionName)}";
|
||||||
|
if (!string.IsNullOrEmpty(Area))
|
||||||
|
{
|
||||||
|
rv = $"/{HttpUtility.UrlEncode(Area)}{rv}";
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(QueryString))
|
||||||
|
{
|
||||||
|
rv = $"{rv}?{QueryString}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = $"{rv}?1=1"; ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否跳转到新页面
|
||||||
|
/// </summary>
|
||||||
|
public bool IsRedirect { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 弹出问询框
|
||||||
|
/// </summary>
|
||||||
|
public string PromptMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型
|
||||||
|
/// </summary>
|
||||||
|
public GridActionParameterTypesEnum ParameterType { get; set; }
|
||||||
|
|
||||||
|
public bool ForcePost { get; set; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 暂时无用
|
||||||
|
/// <summary>
|
||||||
|
/// 是否可以resizable
|
||||||
|
/// </summary>
|
||||||
|
public bool Resizable { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 动作图标css
|
||||||
|
/// </summary>
|
||||||
|
public string IconCls { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的QueryString
|
||||||
|
/// </summary>
|
||||||
|
public string QueryString { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 弹出窗口的宽度
|
||||||
|
/// </summary>
|
||||||
|
public int? DialogWidth { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 弹出窗口的高度
|
||||||
|
/// </summary>
|
||||||
|
public int? DialogHeight { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否需要弹出窗口
|
||||||
|
/// </summary>
|
||||||
|
public bool ShowDialog { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 如果设定了SubActions,则代表需要用SplitButton的形式展示,主GridAction将不起作用
|
||||||
|
/// </summary>
|
||||||
|
public List<GridAction> SubActions { get; set; }
|
||||||
|
|
||||||
|
public string[] whereStr { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
424
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridActionExtension.cs
Normal file
424
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridActionExtension.cs
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// GridActionExtension
|
||||||
|
/// </summary>
|
||||||
|
public static class GridActionExtensions
|
||||||
|
{
|
||||||
|
#region MakeStandardAction 创建标准动作
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建标准动作
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
/// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
/// <param name="self">self</param>
|
||||||
|
/// <param name="controllerName">动作的Controller</param>
|
||||||
|
/// <param name="standardType">标准动作类型</param>
|
||||||
|
/// <param name="dialogTitle">弹出窗口的标题,可为空,代表使用默认文字</param>
|
||||||
|
/// <param name="areaName">域名</param>
|
||||||
|
/// <param name="dialogWidth">弹出窗口的宽度</param>
|
||||||
|
/// <param name="dialogHeight">弹出窗口的高度</param>
|
||||||
|
/// <param name="name">按钮显示的文字</param>
|
||||||
|
/// <param name="buttonId">Button的id 默认自动生成</param>
|
||||||
|
/// <param name="whereStr">whereStr</param>
|
||||||
|
/// <returns>列表动作</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 根据标准动作类型,创建默认属性的标准动作
|
||||||
|
/// </remarks>
|
||||||
|
public static GridAction MakeStandardAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
, string controllerName
|
||||||
|
, GridActionStandardTypesEnum standardType
|
||||||
|
, string dialogTitle
|
||||||
|
, string areaName = null
|
||||||
|
, int? dialogWidth = null
|
||||||
|
, int? dialogHeight = null
|
||||||
|
, string name = null
|
||||||
|
, string buttonId = null
|
||||||
|
, params Expression<Func<T, object>>[] whereStr)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
var iconcls = string.Empty;
|
||||||
|
var actionName = standardType.ToString();
|
||||||
|
var gridname = string.Empty;
|
||||||
|
var paraType = GridActionParameterTypesEnum.NoId;
|
||||||
|
var showInRow = false;
|
||||||
|
var hideOnToolBar = false;
|
||||||
|
var showDialog = true;
|
||||||
|
var isexport = false;
|
||||||
|
string msg = null;
|
||||||
|
var ispost = false;
|
||||||
|
string qs = null;
|
||||||
|
switch (standardType)
|
||||||
|
{
|
||||||
|
case GridActionStandardTypesEnum.Create:
|
||||||
|
iconcls = "layui-icon layui-icon-add-1";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Create"];
|
||||||
|
paraType = GridActionParameterTypesEnum.NoId;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.AddRow:
|
||||||
|
iconcls = "layui-icon layui-icon-add-1";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Create"];
|
||||||
|
paraType = GridActionParameterTypesEnum.AddRow;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.Edit:
|
||||||
|
iconcls = "layui-icon layui-icon-edit";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Edit"];
|
||||||
|
paraType = GridActionParameterTypesEnum.SingleId;
|
||||||
|
showInRow = true;
|
||||||
|
hideOnToolBar = true;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.Delete:
|
||||||
|
iconcls = "layui-icon layui-icon-delete";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Delete"];
|
||||||
|
paraType = GridActionParameterTypesEnum.SingleId;
|
||||||
|
showInRow = true;
|
||||||
|
hideOnToolBar = true;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.SimpleDelete:
|
||||||
|
iconcls = "layui-icon layui-icon-delete";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Delete"];
|
||||||
|
paraType = GridActionParameterTypesEnum.SingleIdWithNull;
|
||||||
|
showInRow = true;
|
||||||
|
hideOnToolBar = true;
|
||||||
|
showDialog = false;
|
||||||
|
actionName = "BatchDelete";
|
||||||
|
qs = "_donotuse_sd=1";
|
||||||
|
ispost = true;
|
||||||
|
msg = CoreProgram._localizer?["Sys.DeleteConfirm"];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GridActionStandardTypesEnum.RemoveRow:
|
||||||
|
iconcls = "layui-icon layui-icon-delete";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Delete"];
|
||||||
|
paraType = GridActionParameterTypesEnum.RemoveRow;
|
||||||
|
showInRow = true;
|
||||||
|
hideOnToolBar = true;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.Details:
|
||||||
|
iconcls = "layui-icon layui-icon-form";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Details"];
|
||||||
|
paraType = GridActionParameterTypesEnum.SingleId;
|
||||||
|
showInRow = true;
|
||||||
|
hideOnToolBar = true;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.BatchEdit:
|
||||||
|
iconcls = "layui-icon layui-icon-edit";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.BatchEdit"];
|
||||||
|
paraType = GridActionParameterTypesEnum.MultiIds;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.BatchDelete:
|
||||||
|
iconcls = "layui-icon layui-icon-delete";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.BatchDelete"];
|
||||||
|
paraType = GridActionParameterTypesEnum.MultiIds;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.SimpleBatchDelete:
|
||||||
|
iconcls = "layui-icon layui-icon-delete";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.BatchDelete"];
|
||||||
|
paraType = GridActionParameterTypesEnum.MultiIds;
|
||||||
|
showDialog = false;
|
||||||
|
msg = CoreProgram._localizer?["Sys.BatchDeleteConfirm"];
|
||||||
|
actionName = "BatchDelete";
|
||||||
|
ispost = true;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.Import:
|
||||||
|
iconcls = "layui-icon layui-icon-templeate-1";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Import"];
|
||||||
|
paraType = GridActionParameterTypesEnum.NoId;
|
||||||
|
break;
|
||||||
|
case GridActionStandardTypesEnum.ExportExcel:
|
||||||
|
iconcls = "layui-icon layui-icon-download-circle";
|
||||||
|
gridname = CoreProgram._localizer?["Sys.Export"];
|
||||||
|
paraType = GridActionParameterTypesEnum.MultiIdWithNull;
|
||||||
|
name = CoreProgram._localizer?["Sys.ExportExcel"];
|
||||||
|
showInRow = false;
|
||||||
|
showDialog = false;
|
||||||
|
hideOnToolBar = false;
|
||||||
|
isexport = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(dialogTitle))
|
||||||
|
{
|
||||||
|
dialogTitle = gridname;
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = new List<string>();
|
||||||
|
foreach (var item in whereStr)
|
||||||
|
{
|
||||||
|
list.Add(PropertyHelper.GetPropertyName(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GridAction
|
||||||
|
{
|
||||||
|
ButtonId = buttonId,
|
||||||
|
Name = (name ?? gridname),
|
||||||
|
DialogTitle = dialogTitle,
|
||||||
|
Area = areaName,
|
||||||
|
ControllerName = controllerName,
|
||||||
|
ActionName = actionName,
|
||||||
|
ParameterType = paraType,
|
||||||
|
IconCls = iconcls,
|
||||||
|
DialogWidth = dialogWidth ?? 800,
|
||||||
|
DialogHeight = dialogHeight,
|
||||||
|
ShowInRow = showInRow,
|
||||||
|
ShowDialog = showDialog,
|
||||||
|
HideOnToolBar = hideOnToolBar,
|
||||||
|
PromptMessage = msg,
|
||||||
|
ForcePost = ispost,
|
||||||
|
QueryString = qs,
|
||||||
|
IsExport = isexport,
|
||||||
|
whereStr = list.ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MakeAction 创建按钮
|
||||||
|
/// <summary>
|
||||||
|
/// 创建标准动作
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
/// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
/// <param name="self">self</param>
|
||||||
|
/// <param name="controllerName">动作的Controller</param>
|
||||||
|
/// <param name="actionName">actionName</param>
|
||||||
|
/// <param name="name">动作名,默认为‘新建’</param>
|
||||||
|
/// <param name="dialogTitle">弹出窗口的标题</param>
|
||||||
|
/// <param name="paraType">paraType</param>
|
||||||
|
/// <param name="areaName">域名</param>
|
||||||
|
/// <param name="dialogWidth">弹出窗口的宽度</param>
|
||||||
|
/// <param name="dialogHeight">弹出窗口的高度</param>
|
||||||
|
/// <param name="buttonId">Button的id 默认自动生成</param>
|
||||||
|
/// <param name="whereStr">whereStr</param>
|
||||||
|
/// <returns>列表动作</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 根据标准动作类型,创建默认属性的标准动作
|
||||||
|
/// </remarks>
|
||||||
|
public static GridAction MakeAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
, string controllerName
|
||||||
|
, string actionName
|
||||||
|
, string name
|
||||||
|
, string dialogTitle
|
||||||
|
, GridActionParameterTypesEnum paraType
|
||||||
|
, string areaName = null
|
||||||
|
, int? dialogWidth = null
|
||||||
|
, int? dialogHeight = null
|
||||||
|
, string buttonId = null
|
||||||
|
, params Expression<Func<T, object>>[] whereStr)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
var iconcls = string.Empty;
|
||||||
|
|
||||||
|
var list = new List<string>();
|
||||||
|
foreach (var item in whereStr)
|
||||||
|
{
|
||||||
|
list.Add(PropertyHelper.GetPropertyName(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GridAction
|
||||||
|
{
|
||||||
|
ButtonId = buttonId,
|
||||||
|
Name = name,
|
||||||
|
DialogTitle = dialogTitle,
|
||||||
|
Area = areaName,
|
||||||
|
ControllerName = controllerName,
|
||||||
|
ActionName = actionName,
|
||||||
|
ParameterType = paraType,
|
||||||
|
IconCls = iconcls,
|
||||||
|
DialogWidth = dialogWidth ?? 800,
|
||||||
|
DialogHeight = dialogHeight,
|
||||||
|
ShowDialog = true,
|
||||||
|
whereStr = list.ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GridAction MakeActionsGroup<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
, string name
|
||||||
|
, List<GridAction> subActions
|
||||||
|
, params Expression<Func<T, object>>[] whereStr)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
var iconcls = string.Empty;
|
||||||
|
|
||||||
|
var list = new List<string>();
|
||||||
|
foreach (var item in whereStr)
|
||||||
|
{
|
||||||
|
list.Add(PropertyHelper.GetPropertyName(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GridAction
|
||||||
|
{
|
||||||
|
ButtonId = Guid.NewGuid().ToString(),
|
||||||
|
Name = name,
|
||||||
|
DialogTitle = "",
|
||||||
|
Area = "",
|
||||||
|
ControllerName = "",
|
||||||
|
ActionName = "ActionsGroup",
|
||||||
|
ParameterType = GridActionParameterTypesEnum.NoId,
|
||||||
|
IconCls = iconcls,
|
||||||
|
DialogWidth = 0,
|
||||||
|
DialogHeight = 0,
|
||||||
|
ShowDialog = false,
|
||||||
|
whereStr = list.ToArray(),
|
||||||
|
SubActions= subActions
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MakeStandardExportAction 创建标准导出按钮
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建标准导出按钮
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">继承自TopBasePoco的类</typeparam>
|
||||||
|
/// <typeparam name="V">继承自ISearcher的类</typeparam>
|
||||||
|
/// <param name="self">self</param>
|
||||||
|
/// <param name="gridid">vmGuid</param>
|
||||||
|
/// <param name="MustSelect"></param>
|
||||||
|
/// <param name="exportType">导出类型 默认null,支持所有导出</param>
|
||||||
|
/// <param name="param">参数</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Obsolete("Will be removed in future, use MakeStandardAction with GridActionStandardTypesEnum.ExportExcel instead")]
|
||||||
|
public static GridAction MakeStandardExportAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
, string gridid = null
|
||||||
|
, bool MustSelect = false
|
||||||
|
, ExportEnum? exportType = null
|
||||||
|
, params KeyValuePair<string, string>[] param)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
exportType = ExportEnum.Excel;
|
||||||
|
|
||||||
|
var action = new GridAction
|
||||||
|
{
|
||||||
|
Name = CoreProgram._localizer?["Sys.ExportExcel"],
|
||||||
|
DialogTitle = CoreProgram._localizer?["Sys.ExportExcel"],
|
||||||
|
Area = string.Empty,
|
||||||
|
ControllerName = "_Framework",
|
||||||
|
ActionName = "GetExportExcel",
|
||||||
|
ParameterType = GridActionParameterTypesEnum.MultiIdWithNull,
|
||||||
|
|
||||||
|
IconCls = "layui-icon layui-icon-download-circle",
|
||||||
|
ShowInRow = false,
|
||||||
|
ShowDialog = false,
|
||||||
|
HideOnToolBar = false
|
||||||
|
};
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Set Property
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the dialog to be maximized
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="Max"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetMax(this GridAction self, bool Max = true)
|
||||||
|
{
|
||||||
|
self.Max = Max;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the dialog to be maximized
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="buttonclass">button class.
|
||||||
|
/// Some of the layui defined class to control color:
|
||||||
|
/// layui-btn-primary
|
||||||
|
/// layui-btn-normal
|
||||||
|
/// layui-btn-warm
|
||||||
|
/// layui-btn-danger
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetButtonClass(this GridAction self, string buttonclass)
|
||||||
|
{
|
||||||
|
self.ButtonClass = buttonclass;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the dialog to be maximized
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="isDownload"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetIsDownload(this GridAction self, bool isDownload = true)
|
||||||
|
{
|
||||||
|
self.IsDownload = isDownload;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GridAction SetIsExport(this GridAction self, bool isExport= true)
|
||||||
|
{
|
||||||
|
self.IsExport = isExport;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set prompt message
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="msg"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetPromptMessage(this GridAction self, string msg)
|
||||||
|
{
|
||||||
|
self.PromptMessage = msg;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在每行都显示
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="showInRow"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetShowInRow(this GridAction self, bool showInRow = true)
|
||||||
|
{
|
||||||
|
self.ShowInRow = showInRow;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在工具栏上隐藏按钮
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="hideOnToolBar"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetHideOnToolBar(this GridAction self, bool hideOnToolBar = true)
|
||||||
|
{
|
||||||
|
self.HideOnToolBar = hideOnToolBar;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 把按钮当作容器,添加按钮的子按钮
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="subActions">子按钮</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetSubActions(this GridAction self, List<GridAction> subActions)
|
||||||
|
{
|
||||||
|
self.SubActions = subActions;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,205 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// GridActionExtension
|
||||||
|
/// </summary>
|
||||||
|
public static class GridActionExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 按钮Id,一般不需要设定,系统会自动生成唯一Id。如果设定请确保 Id 的唯一性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="buttonId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetButtonId(this GridAction self, string buttonId)
|
||||||
|
{
|
||||||
|
self.ButtonId = buttonId;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 按钮名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetName(this GridAction self, string name)
|
||||||
|
{
|
||||||
|
self.Name = name;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 弹出窗口的标题
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="dialogTitle"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetDialogTitle(this GridAction self, string dialogTitle)
|
||||||
|
{
|
||||||
|
self.DialogTitle = dialogTitle;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 动作图标css
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="iconCls"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetIconCls(this GridAction self, string iconCls)
|
||||||
|
{
|
||||||
|
self.IconCls = iconCls;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的Area
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="area"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetArea(this GridAction self, string area)
|
||||||
|
{
|
||||||
|
self.Area = area;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的Controller
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="controllerName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetControllerName(this GridAction self, string controllerName)
|
||||||
|
{
|
||||||
|
self.ControllerName = controllerName;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的Action
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="actionName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetActionName(this GridAction self, string actionName)
|
||||||
|
{
|
||||||
|
self.ActionName = actionName;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 动作的QueryString
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="queryString"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetQueryString(this GridAction self, string queryString)
|
||||||
|
{
|
||||||
|
self.QueryString = queryString;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 弹出窗口的宽度、高度
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="dialogWidth"></param>
|
||||||
|
/// <param name="dialogHeight"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetSize(this GridAction self, int? dialogWidth, int? dialogHeight)
|
||||||
|
{
|
||||||
|
self.DialogWidth = dialogWidth;
|
||||||
|
self.DialogHeight = dialogHeight;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 是否需要弹出窗口
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="showDialog"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetShowDialog(this GridAction self, bool showDialog = true)
|
||||||
|
{
|
||||||
|
self.ShowDialog = showDialog;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
public static GridAction SetForcePost(this GridAction self, bool forcepost = true)
|
||||||
|
{
|
||||||
|
self.ForcePost = forcepost;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否跳转到新页面
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="isRedirect"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetIsRedirect(this GridAction self, bool isRedirect = true)
|
||||||
|
{
|
||||||
|
self.IsRedirect = isRedirect;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="parameterType"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetParameterType(this GridAction self, GridActionParameterTypesEnum parameterType)
|
||||||
|
{
|
||||||
|
self.ParameterType = parameterType;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 如果不为null,则只运行这个变量设定的script,其他的属性都不起作用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="onClickScript"></param>
|
||||||
|
/// <remarks>
|
||||||
|
/// 如设置SetOnClickScript("test"),点击按钮时框架会调用页面上的javascript方法: function test(ids,datas){}
|
||||||
|
/// ids是勾选的id数组,datas是勾选的所有字段数组
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetOnClickScript(this GridAction self, string onClickScript)
|
||||||
|
{
|
||||||
|
self.OnClickFunc = onClickScript;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 如果设定了SubActions,则代表需要用SplitButton的形式展示,主GridAction将不起作用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="gridActions"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetSubAction(this GridAction self, params GridAction[] gridActions)
|
||||||
|
{
|
||||||
|
if (self.SubActions == null)
|
||||||
|
{
|
||||||
|
self.SubActions = new List<GridAction>();
|
||||||
|
}
|
||||||
|
self.SubActions.AddRange(gridActions);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 是否可以拖动改变弹出窗体大小
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="resizable"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetNotResizable(this GridAction self, bool resizable = false)
|
||||||
|
{
|
||||||
|
self.Resizable = resizable;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置一个布尔值的列名,当改列值为true的时候才显示本行的这个动作按钮
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="colName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridAction SetBindVisiableColName(this GridAction self, string colName)
|
||||||
|
{
|
||||||
|
self.BindVisiableColName = colName;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
510
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridColumn.cs
Normal file
510
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridColumn.cs
Normal file
@ -0,0 +1,510 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 列表列的定义
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">列表的数据源类</typeparam>
|
||||||
|
public class GridColumn<T> : IGridColumn<T> where T : TopBasePoco
|
||||||
|
{
|
||||||
|
public bool? ShowTotal { get; set; }
|
||||||
|
public GridColumn(Expression<Func<T, object>> columnExp, int? width)
|
||||||
|
{
|
||||||
|
ColumnExp = columnExp;
|
||||||
|
Width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表头类型
|
||||||
|
/// </summary>
|
||||||
|
public GridColumnTypeEnum ColumnType { get; set; }
|
||||||
|
private string _field;
|
||||||
|
/// <summary>
|
||||||
|
/// 设定字段名
|
||||||
|
/// </summary>
|
||||||
|
public string Field
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_field == null)
|
||||||
|
{
|
||||||
|
_field = PI?.Name;
|
||||||
|
if (_field == null)
|
||||||
|
{
|
||||||
|
_field = CompiledCol?.Invoke(null).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _field;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_field = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _title;
|
||||||
|
/// <summary>
|
||||||
|
/// 标题名称
|
||||||
|
/// </summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_title == null && PI != null)
|
||||||
|
{
|
||||||
|
_title = PropertyHelper.GetPropertyDisplayName(PI) ?? string.Empty;
|
||||||
|
}
|
||||||
|
return _title;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_title = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列宽
|
||||||
|
/// </summary>
|
||||||
|
public int? Width { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// //监听单元格事件
|
||||||
|
/// </summary>
|
||||||
|
public string Event { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许排序
|
||||||
|
/// </summary>
|
||||||
|
public bool? Sort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否固定列
|
||||||
|
/// </summary>
|
||||||
|
public GridColumnFixedEnum? Fixed { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对齐方式
|
||||||
|
/// </summary>
|
||||||
|
public GridColumnAlignEnum Align { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否可改变列宽
|
||||||
|
/// </summary>
|
||||||
|
public bool? UnResize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 隐藏列
|
||||||
|
/// </summary>
|
||||||
|
public bool? Hide { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否禁止导出此列
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableExport { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 子列
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<IGridColumn<T>> Children { get; set; }
|
||||||
|
private int? _childrenLen;
|
||||||
|
/// <summary>
|
||||||
|
/// 底层子列数量
|
||||||
|
/// </summary>
|
||||||
|
public int ChildrenLength
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_childrenLen == null)
|
||||||
|
{
|
||||||
|
var len = 0;
|
||||||
|
if (Children != null && Children.Any())
|
||||||
|
{
|
||||||
|
len += Children.Where(x => x.Children == null || !x.Children.Any()).Count();
|
||||||
|
var tempChildren = Children.Where(x => x.Children != null && x.Children.Any()).ToList();
|
||||||
|
foreach (var item in tempChildren)
|
||||||
|
{
|
||||||
|
len += item.ChildrenLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_childrenLen = len;
|
||||||
|
}
|
||||||
|
return _childrenLen.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditTypeEnum? EditType { get; set; }
|
||||||
|
|
||||||
|
public List<ComboSelectListItem> ListItems { get; set; }
|
||||||
|
|
||||||
|
#region 只读属性 生成 Excel 及其 表头用
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 递归获取子列数量最大层的子列数量
|
||||||
|
/// </summary>
|
||||||
|
public int MaxChildrenCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int rv = 1;
|
||||||
|
if (this.Children != null && Children.Any())
|
||||||
|
{
|
||||||
|
rv = 0;
|
||||||
|
foreach (var child in this.Children)
|
||||||
|
{
|
||||||
|
rv += child.MaxChildrenCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 获取最大层数
|
||||||
|
/// </summary>
|
||||||
|
public int MaxLevel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int rv = 1;
|
||||||
|
if (this.Children != null && Children.Any())
|
||||||
|
{
|
||||||
|
int max = 0;
|
||||||
|
foreach (var child in this.Children)
|
||||||
|
{
|
||||||
|
int temp = child.MaxLevel;
|
||||||
|
if (max < temp)
|
||||||
|
{
|
||||||
|
max = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv += max;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private PropertyInfo _pi;
|
||||||
|
protected PropertyInfo PI
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_pi == null && ColumnExp != null)
|
||||||
|
{
|
||||||
|
_pi = PropertyHelper.GetPropertyInfo(ColumnExp);
|
||||||
|
}
|
||||||
|
return _pi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ColumnExp
|
||||||
|
/// </summary>
|
||||||
|
public Expression<Func<T, object>> ColumnExp { get; set; }
|
||||||
|
|
||||||
|
private int? _maxDepth;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大深度
|
||||||
|
/// </summary>
|
||||||
|
public int MaxDepth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_maxDepth == null)
|
||||||
|
{
|
||||||
|
_maxDepth = 1;
|
||||||
|
if (Children?.Count() > 0)
|
||||||
|
{
|
||||||
|
_maxDepth += Children.Max(x => x.MaxDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _maxDepth.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 暂时没有用
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
private Func<T, object> _compiledCol;
|
||||||
|
protected Func<T, object> CompiledCol
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_compiledCol == null)
|
||||||
|
{
|
||||||
|
if (ColumnExp == null)
|
||||||
|
{
|
||||||
|
_compiledCol = (T) => "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_compiledCol = ColumnExp.Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _compiledCol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Type _fieldType;
|
||||||
|
/// <summary>
|
||||||
|
/// 获取值域类型
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Type FieldType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _fieldType ?? PI?.PropertyType;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_fieldType = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FieldName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return PI?.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本列是否需要分组
|
||||||
|
/// </summary>
|
||||||
|
public bool NeedGroup { get; set; }
|
||||||
|
public bool IsLocked { get; set; }
|
||||||
|
public bool Sortable { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许换行
|
||||||
|
/// </summary>
|
||||||
|
public bool AllowMultiLine { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 设置某列是否应该尽量充满
|
||||||
|
/// </summary>
|
||||||
|
public int? Flex { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 列内容的格式化函数
|
||||||
|
/// </summary>
|
||||||
|
public ColumnFormatCallBack<T> Format { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本列前景色函数
|
||||||
|
/// </summary>
|
||||||
|
public Func<T, string> ForeGroundFunc { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 本列背景色函数
|
||||||
|
/// </summary>
|
||||||
|
public Func<T, string> BackGroundFunc { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取最底层的子列
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<IGridColumn<T>> BottomChildren
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<IGridColumn<T>> rv = new List<IGridColumn<T>>();
|
||||||
|
if (Children != null && Children.Any())
|
||||||
|
{
|
||||||
|
foreach (var child in Children)
|
||||||
|
{
|
||||||
|
rv.AddRange(child.BottomChildren);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv.Add(this);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据设置前景色的函数返回前景色
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">源数据</param>
|
||||||
|
/// <returns>前景色</returns>
|
||||||
|
public string GetForeGroundColor(object source)
|
||||||
|
{
|
||||||
|
if (ForeGroundFunc == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ForeGroundFunc.Invoke(source as T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据设置背景色的函数返回背景色
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">源数据</param>
|
||||||
|
/// <returns>背景色</returns>
|
||||||
|
public string GetBackGroundColor(object source)
|
||||||
|
{
|
||||||
|
if (BackGroundFunc == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BackGroundFunc.Invoke(source as T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool HasFormat()
|
||||||
|
{
|
||||||
|
if(Format != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取单元格要输出的内容
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">源数据</param>
|
||||||
|
/// <param name="needFormat">是否使用format</param>
|
||||||
|
/// <returns>Html内容</returns>
|
||||||
|
public virtual object GetText(object source, bool needFormat = true)
|
||||||
|
{
|
||||||
|
object rv = null;
|
||||||
|
var col = CompiledCol?.Invoke(source as T);
|
||||||
|
if(needFormat == false && Format != null)
|
||||||
|
{
|
||||||
|
var test = Format.Invoke(source as T, col);
|
||||||
|
if(test is ColumnFormatInfo == false && test is List<ColumnFormatInfo> == false)
|
||||||
|
{
|
||||||
|
return test??"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Format == null || needFormat == false)
|
||||||
|
{
|
||||||
|
if (col == null)
|
||||||
|
{
|
||||||
|
rv = "";
|
||||||
|
}
|
||||||
|
else if (col is DateTime || col is DateTime?)
|
||||||
|
{
|
||||||
|
var datevalue = col as DateTime?;
|
||||||
|
if(datevalue != null)
|
||||||
|
{
|
||||||
|
if (datevalue.Value.Hour == 0 && datevalue.Value.Minute == 0 && datevalue.Value.Second == 0)
|
||||||
|
{
|
||||||
|
rv = datevalue.Value.ToString("yyyy-MM-dd");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = datevalue.Value.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (col.GetType().IsEnumOrNullableEnum())
|
||||||
|
{
|
||||||
|
rv = col.ToString();
|
||||||
|
}
|
||||||
|
else if (col.GetType().Namespace.Equals("System") == false)
|
||||||
|
{
|
||||||
|
if (needFormat == false)
|
||||||
|
{
|
||||||
|
rv = JsonSerializer.Serialize(col, CoreProgram.DefaultJsonOption);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = col.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = col.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = Format.Invoke(source as T, col);
|
||||||
|
}
|
||||||
|
if (rv == null)
|
||||||
|
{
|
||||||
|
rv = "";
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual object GetObject(object source)
|
||||||
|
{
|
||||||
|
object rv = CompiledCol?.Invoke(source as T);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取列头内容
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Html内容</returns>
|
||||||
|
protected virtual string GetHeader()
|
||||||
|
{
|
||||||
|
string rv = PropertyHelper.GetPropertyDisplayName(PI);
|
||||||
|
return rv ?? "";
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 默认构造函数
|
||||||
|
/// </summary>
|
||||||
|
public GridColumn()
|
||||||
|
{
|
||||||
|
AllowMultiLine = true;
|
||||||
|
this.Sortable = true;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ColumnExp"></param>
|
||||||
|
/// <param name="Format"></param>
|
||||||
|
/// <param name="Header"></param>
|
||||||
|
/// <param name="Width"></param>
|
||||||
|
/// <param name="Flex"></param>
|
||||||
|
/// <param name="AllowMultiLine"></param>
|
||||||
|
/// <param name="NeedGroup"></param>
|
||||||
|
/// <param name="ForeGroundFunc"></param>
|
||||||
|
/// <param name="BackGroundFunc"></param>
|
||||||
|
/// <param name="sortable"></param>
|
||||||
|
public GridColumn(Expression<Func<T, object>> ColumnExp, ColumnFormatCallBack<T> Format = null, string Header = null, int? Width = null, int? Flex = null, bool AllowMultiLine = true, bool NeedGroup = false, Func<T, string> ForeGroundFunc = null, Func<T, string> BackGroundFunc = null, bool sortable = true)
|
||||||
|
{
|
||||||
|
this.ColumnExp = ColumnExp;
|
||||||
|
this.Format = Format;
|
||||||
|
this.Title = Header;
|
||||||
|
this.Width = Width;
|
||||||
|
this.NeedGroup = NeedGroup;
|
||||||
|
this.ForeGroundFunc = ForeGroundFunc;
|
||||||
|
this.BackGroundFunc = BackGroundFunc;
|
||||||
|
this.AllowMultiLine = AllowMultiLine;
|
||||||
|
this.Flex = Flex;
|
||||||
|
this.Sortable = sortable;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,218 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// GridColumnExtension
|
||||||
|
/// </summary>
|
||||||
|
public static class GridColumnExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// GetAllBottomColumns
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<IGridColumn<T>> GetAllBottomColumns<T>(this IEnumerable<IGridColumn<T>> self)
|
||||||
|
{
|
||||||
|
List<IGridColumn<T>> rv = new List<IGridColumn<T>>();
|
||||||
|
foreach (var item in self)
|
||||||
|
{
|
||||||
|
rv.AddRange(item.BottomChildren);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Id
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetId<T>(this GridColumn<T> self, string id) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Id = id;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 列头
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="header"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetHeader<T>(this GridColumn<T> self, string header) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Title = header;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 本列是否需要分组
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="needGroup"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetNeedGroup<T>(this GridColumn<T> self, bool needGroup) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.NeedGroup = needGroup;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
public static GridColumn<T> SetLocked<T>(this GridColumn<T> self, bool locked) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.IsLocked = locked;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
public static GridColumn<T> SetSortable<T>(this GridColumn<T> self, bool sortable = false) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Sortable = sortable;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 列宽
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="width"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetWidth<T>(this GridColumn<T> self, int? width) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Width = width;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许换行
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="allowMultiLine"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetAllowMultiLine<T>(this GridColumn<T> self, bool allowMultiLine) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.AllowMultiLine = allowMultiLine;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置某列是否应该尽量充满
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="flex"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetFlex<T>(this GridColumn<T> self, int? flex) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Flex = flex;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
///// <summary>
|
||||||
|
///// 时间与数字类型Format
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T"></typeparam>
|
||||||
|
///// <param name="self"></param>
|
||||||
|
///// <param name="format"></param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static GridColumn<T> SetFormat<T>(this GridColumn<T> self, string format) where T : TopBasePoco
|
||||||
|
//{
|
||||||
|
// self.StringFormat = format;
|
||||||
|
// return self;
|
||||||
|
//}
|
||||||
|
/// <summary>
|
||||||
|
/// 列内容的格式化函数
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="format"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetFormat<T>(this GridColumn<T> self, ColumnFormatCallBack<T> format) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Format = format;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 计算列值的表达式
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="columnExp"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetColumnExp<T>(this GridColumn<T> self, Expression<Func<T, object>> columnExp) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.ColumnExp = columnExp;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 子列
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="childrens"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetChildren<T>(this GridColumn<T> self, params GridColumn<T>[] childrens) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
List<GridColumn<T>> temp = new List<GridColumn<T>>();
|
||||||
|
if (self.Children == null)
|
||||||
|
{
|
||||||
|
temp = new List<GridColumn<T>>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp = self.Children.Cast<GridColumn<T>>().ToList();
|
||||||
|
}
|
||||||
|
temp.AddRange(childrens);
|
||||||
|
self.Children = temp;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 本列前景色函数
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="foreGroundFunc"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetForeGroundFunc<T>(this GridColumn<T> self, Func<T, string> foreGroundFunc) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.ForeGroundFunc = foreGroundFunc;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 本列背景色函数
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="backGroundFunc"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetBackGroundFunc<T>(this GridColumn<T> self, Func<T, string> backGroundFunc) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.BackGroundFunc = backGroundFunc;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置本列是否显示汇总
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="show">是否显示</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetShowTotal<T>(this GridColumn<T> self, bool show = true) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.ShowTotal = show;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置禁止导出此列数据
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetDisableExport<T>(this GridColumn<T> self) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.DisableExport = true;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
310
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridHeaderExtension.cs
Normal file
310
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/GridHeaderExtension.cs
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// GridColumn Extension
|
||||||
|
/// </summary>
|
||||||
|
public static class GridHeaderExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 创建表头
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <typeparam name="V"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="columnExp">绑定猎头表达式</param>
|
||||||
|
/// <param name="width">宽度</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> MakeGridHeader<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
, Expression<Func<T, object>> columnExp
|
||||||
|
, int? width = null
|
||||||
|
)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
MemberExpression me = null;
|
||||||
|
if (columnExp is MemberExpression)
|
||||||
|
{
|
||||||
|
me = columnExp as MemberExpression;
|
||||||
|
}
|
||||||
|
else if (columnExp is LambdaExpression)
|
||||||
|
{
|
||||||
|
var le = columnExp as LambdaExpression;
|
||||||
|
if (le.Body is MemberExpression)
|
||||||
|
{
|
||||||
|
me = le.Body as MemberExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var alignType = GridColumnAlignEnum.Center;
|
||||||
|
if (me != null)
|
||||||
|
{
|
||||||
|
var propType = me.Type;
|
||||||
|
if (propType == typeof(string))
|
||||||
|
{
|
||||||
|
alignType = GridColumnAlignEnum.Left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GridColumn<T>(columnExp, width) { ColumnType = GridColumnTypeEnum.Normal, Align = alignType };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建一个间隙列
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <typeparam name="V"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> MakeGridHeaderSpace<T, V>(this IBasePagedListVM<T, V> self)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
return new GridColumn<T>() { ColumnType = GridColumnTypeEnum.Space };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建一个父级表头
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <typeparam name="V"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="title">标题</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> MakeGridHeaderParent<T, V>(this IBasePagedListVM<T, V> self, string title
|
||||||
|
)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
return new GridColumn<T>() { Title = title };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GridColumn<T> MakeGridHeaderAction<T, V>(this IBasePagedListVM<T, V> self
|
||||||
|
, string title = null
|
||||||
|
, int? width = 160
|
||||||
|
, int? rowspan = null
|
||||||
|
)
|
||||||
|
where T : TopBasePoco
|
||||||
|
where V : ISearcher
|
||||||
|
{
|
||||||
|
return new GridColumn<T>()
|
||||||
|
{
|
||||||
|
ColumnType = GridColumnTypeEnum.Action,
|
||||||
|
Width = width,
|
||||||
|
Fixed = GridColumnFixedEnum.Right,
|
||||||
|
Title = title ?? CoreProgram._localizer?["Sys.Operation"]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#region GridColumn Property Setter
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定字段名
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="field">字段名的设定非常重要,是表格数据列的唯一标识,默认属性对应的名字</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetField<T>(this GridColumn<T> self, string field)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Field = field;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定标题名称
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="title">即表头各列的标题,默认属性对应的 DisplayName 或 属性名 </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetTitle<T>(this GridColumn<T> self, string title)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Title = title;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定列宽
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="width">列宽的设定也通常是必须的(“特殊列”除外,如:复选框列、工具列等),它关系到表格的整体美观程度。</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetWidth<T>(this GridColumn<T> self, int width)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Width = width;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 单元格事件名称
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="eEvent"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetEvent<T>(this GridColumn<T> self, string eEvent) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Event = eEvent;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// 设定当前列头 列横跨的单元格数
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T"></typeparam>
|
||||||
|
///// <param name="self"></param>
|
||||||
|
///// <param name="colspan">这种情况下不用设置 Field 和 Width </param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static GridColumn<T> SetColspan<T>(this GridColumn<T> self, int colspan)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
//{
|
||||||
|
// self.Colspan = colspan;
|
||||||
|
// return self;
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// 设定当前列头 纵向跨越的单元格数
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T"></typeparam>
|
||||||
|
///// <param name="self"></param>
|
||||||
|
///// <param name="rowspan">纵向跨越的单元格数</param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static GridColumn<T> SetRowspan<T>(this GridColumn<T> self, int rowspan)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
//{
|
||||||
|
// self.Rowspan = rowspan;
|
||||||
|
// return self;
|
||||||
|
//}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定是否允许排序 (ASCII码排序)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="sort">如果设置 true,则在对应的表头显示排序icon,从而对列开启排序功能。</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetSort<T>(this GridColumn<T> self, bool sort = true)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Sort = sort;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定是否固定列
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="fixed">如果设置 Left 或 Right,则对应的列将会被固定在左或右,不随滚动条而滚动。</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetFixed<T>(this GridColumn<T> self, GridColumnFixedEnum? @fixed)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Fixed = @fixed;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定对齐方式
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="align"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetAlign<T>(this GridColumn<T> self, GridColumnAlignEnum align)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Align = align;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// 设定是否允许编辑
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T"></typeparam>
|
||||||
|
///// <param name="self"></param>
|
||||||
|
///// <param name="edit">如果设置 true,则对应列的单元格将会被允许编辑,目前只支持type="text"的input编辑。</param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static GridColumn<T> SetEdit<T>(this GridColumn<T> self, bool edit = true)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
//{
|
||||||
|
// self.Edit = edit;
|
||||||
|
// return self;
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// 设定自定义模板
|
||||||
|
///// </summary>
|
||||||
|
///// <typeparam name="T"></typeparam>
|
||||||
|
///// <param name="self"></param>
|
||||||
|
///// <param name="templet">在默认情况下,单元格的内容是完全按照数据接口返回的content原样输出的,
|
||||||
|
///// 如果你想对某列的单元格添加链接等其它元素,你可以借助该参数来轻松实现。
|
||||||
|
///// 这是一个非常实用的功能,你的表格内容会因此而丰富多样。
|
||||||
|
///// </param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static GridColumn<T> SetTemplet<T>(this GridColumn<T> self, string templet)
|
||||||
|
// where T : TopBasePoco
|
||||||
|
//{
|
||||||
|
// self.Templet = templet;
|
||||||
|
// return self;
|
||||||
|
//}
|
||||||
|
|
||||||
|
[Obsolete("该方法已经被弃用,请使用 SetHide 代替")]
|
||||||
|
public static GridColumn<T> SetHidden<T>(this GridColumn<T> self, bool hidden = true) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否隐藏
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="hide"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetHide<T>(this GridColumn<T> self, bool hide = true) where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.Hide = hide;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定列宽不可改变
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="unresize"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetUnResize<T>(this GridColumn<T> self, bool unresize = true)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.UnResize = unresize;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定单元格编辑类型
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="editType">单元格编辑类型</param>
|
||||||
|
/// <param name="listitems">listitems</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static GridColumn<T> SetEditType<T>(this GridColumn<T> self, EditTypeEnum editType = EditTypeEnum.Text, List<ComboSelectListItem> listitems = null)
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
self.EditType = editType;
|
||||||
|
self.ListItems = listitems;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
225
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/IGridColumn.cs
Normal file
225
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Grid/IGridColumn.cs
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Grid Column Content Fixed Enum
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||||
|
public enum GridColumnFixedEnum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 规定在左侧
|
||||||
|
/// </summary>
|
||||||
|
Left = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// 规定在右侧
|
||||||
|
/// </summary>
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Grid Column Edit Type Enum
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||||
|
public enum EditTypeEnum
|
||||||
|
{
|
||||||
|
Text,
|
||||||
|
TextBox,
|
||||||
|
ComboBox,
|
||||||
|
Datetime,
|
||||||
|
CheckBox
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Grid Column Content Align Enum
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||||
|
public enum GridColumnAlignEnum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Center
|
||||||
|
/// </summary>
|
||||||
|
Center = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Left
|
||||||
|
/// </summary>
|
||||||
|
Left,
|
||||||
|
/// <summary>
|
||||||
|
/// Right
|
||||||
|
/// </summary>
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Grid Column Type Enum
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||||
|
public enum GridColumnTypeEnum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 正常列
|
||||||
|
/// </summary>
|
||||||
|
Normal = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// 空列
|
||||||
|
/// </summary>
|
||||||
|
Space,
|
||||||
|
/// <summary>
|
||||||
|
/// 操作列
|
||||||
|
/// </summary>
|
||||||
|
Action
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IGridColumn
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public interface IGridColumn<out T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表头类型
|
||||||
|
/// </summary>
|
||||||
|
GridColumnTypeEnum ColumnType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定字段名
|
||||||
|
/// </summary>
|
||||||
|
string Field { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标题名称
|
||||||
|
/// </summary>
|
||||||
|
string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列宽
|
||||||
|
/// </summary>
|
||||||
|
int? Width { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// //监听单元格事件
|
||||||
|
/// </summary>
|
||||||
|
string Event { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许排序
|
||||||
|
/// </summary>
|
||||||
|
bool? Sort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否固定列
|
||||||
|
/// </summary>
|
||||||
|
GridColumnFixedEnum? Fixed { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对齐方式
|
||||||
|
/// </summary>
|
||||||
|
GridColumnAlignEnum Align { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否可改变列宽
|
||||||
|
/// </summary>
|
||||||
|
bool? UnResize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 隐藏列
|
||||||
|
/// </summary>
|
||||||
|
bool? Hide { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否显示汇总
|
||||||
|
/// </summary>
|
||||||
|
bool? ShowTotal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 子列
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<IGridColumn<T>> Children { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 底层子列数量
|
||||||
|
/// </summary>
|
||||||
|
int ChildrenLength { get; }
|
||||||
|
|
||||||
|
EditTypeEnum? EditType { get; set; }
|
||||||
|
|
||||||
|
List<ComboSelectListItem> ListItems { get; set; }
|
||||||
|
|
||||||
|
#region 只读属性 生成 Excel 及其 表头用
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大子列数量
|
||||||
|
/// </summary>
|
||||||
|
int MaxChildrenCount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多表头的最大层数
|
||||||
|
/// </summary>
|
||||||
|
int MaxLevel { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最下层列
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<IGridColumn<T>> BottomChildren { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大深度
|
||||||
|
/// </summary>
|
||||||
|
int MaxDepth { get; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 暂时没有用
|
||||||
|
|
||||||
|
string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否需要分组
|
||||||
|
/// </summary>
|
||||||
|
bool NeedGroup { get; set; }
|
||||||
|
|
||||||
|
bool IsLocked { get; set; }
|
||||||
|
|
||||||
|
bool Sortable { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许多行
|
||||||
|
/// </summary>
|
||||||
|
bool AllowMultiLine { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否填充
|
||||||
|
/// </summary>
|
||||||
|
int? Flex { get; set; }
|
||||||
|
|
||||||
|
Type FieldType { get; }
|
||||||
|
|
||||||
|
string FieldName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取内容
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">源数据</param>
|
||||||
|
/// <param name="needFormat">是否适用format</param>
|
||||||
|
/// <returns>内容</returns>
|
||||||
|
object GetText(object source, bool needFormat = true);
|
||||||
|
|
||||||
|
object GetObject(object source);
|
||||||
|
/// <summary>
|
||||||
|
/// 获取前景色
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">源数据</param>
|
||||||
|
/// <returns>前景色</returns>
|
||||||
|
string GetForeGroundColor(object source);
|
||||||
|
/// <summary>
|
||||||
|
/// 获取背景色
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">源数据</param>
|
||||||
|
/// <returns>背景色</returns>
|
||||||
|
string GetBackGroundColor(object source);
|
||||||
|
bool HasFormat();
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
166
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/EntityHelper.cs
Normal file
166
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/EntityHelper.cs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DataTable和Entity之间转换的辅助类
|
||||||
|
/// </summary>
|
||||||
|
public static class EntityHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 根据DataTable获取Entity列表
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Entity类型</typeparam>
|
||||||
|
/// <param name="table">DataTable</param>
|
||||||
|
/// <returns>Entity列表</returns>
|
||||||
|
public static IList<T> GetEntityList<T>(DataTable table)
|
||||||
|
{
|
||||||
|
IList<T> entityList = new List<T>();
|
||||||
|
|
||||||
|
if (typeof(T) == typeof(DynamicData))
|
||||||
|
{
|
||||||
|
foreach (DataRow row in table.Rows)
|
||||||
|
{
|
||||||
|
//新建Entity
|
||||||
|
T entity = (T)Activator.CreateInstance(typeof(T));
|
||||||
|
foreach (DataColumn col in table.Columns)
|
||||||
|
{
|
||||||
|
(entity as DynamicData).Add(col.ColumnName, row[col] == DBNull.Value ? null : row[col]);
|
||||||
|
}
|
||||||
|
entityList.Add(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var properties = typeof(T).GetAllProperties().ToLookup(property => property.Name, property => property).ToDictionary(i => i.Key, i => i.First()).Values;
|
||||||
|
|
||||||
|
//循环Datable中的每一行
|
||||||
|
foreach (DataRow row in table.Rows)
|
||||||
|
{
|
||||||
|
//新建Entity
|
||||||
|
T entity = (T)Activator.CreateInstance(typeof(T));
|
||||||
|
//循环Entity的每一个属性
|
||||||
|
foreach (var item in properties)
|
||||||
|
{
|
||||||
|
//如果DataTable中有列名和属性名一致,则把单元格内容赋值给Entity的该属性
|
||||||
|
if (row.Table.Columns.Contains(item.Name))
|
||||||
|
{
|
||||||
|
//判断null值
|
||||||
|
if (string.IsNullOrEmpty(row[item.Name].ToString()))
|
||||||
|
{
|
||||||
|
item.SetValue(entity, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var ptype = item.PropertyType;
|
||||||
|
if (ptype.IsNullable())
|
||||||
|
{
|
||||||
|
ptype = ptype.GenericTypeArguments[0];
|
||||||
|
}
|
||||||
|
//如果是Guid或Guid?类型
|
||||||
|
if (ptype == typeof(Guid))
|
||||||
|
{
|
||||||
|
item.SetValue(entity, Guid.Parse(row[item.Name].ToString()));
|
||||||
|
}
|
||||||
|
//如果是enum或enum?类型
|
||||||
|
else if (ptype.IsEnum)
|
||||||
|
{
|
||||||
|
item.SetValue(entity, Enum.ToObject(ptype, row[item.Name]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.SetValue(entity, Convert.ChangeType(row[item.Name], ptype));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entityList.Add(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 实体类转换成DataTable
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体类转换成DataSet
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelList">实体类列表</param>
|
||||||
|
/// <returns>DataSet</returns>
|
||||||
|
public static DataSet ToDataSet<T>(List<T> modelList) where T : new()
|
||||||
|
{
|
||||||
|
if (modelList == null || modelList.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DataSet ds = new DataSet();
|
||||||
|
ds.Tables.Add(ToDataTable(modelList));
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体类转换成DataTable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelList">实体类列表</param>
|
||||||
|
/// <returns>DataTable</returns>
|
||||||
|
public static DataTable ToDataTable<T>(List<T> modelList) where T : new()
|
||||||
|
{
|
||||||
|
if (modelList == null || modelList.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DataTable dt = CreateData(modelList[0]);
|
||||||
|
|
||||||
|
foreach (T model in modelList)
|
||||||
|
{
|
||||||
|
DataRow dataRow = dt.NewRow();
|
||||||
|
//循环实体类所有属性,给对应的DataTable字段赋值
|
||||||
|
foreach (PropertyInfo propertyInfo in typeof(T).GetAllProperties())
|
||||||
|
{
|
||||||
|
var res = propertyInfo.GetValue(model);
|
||||||
|
dataRow[propertyInfo.Name] = res ?? DBNull.Value;
|
||||||
|
}
|
||||||
|
dt.Rows.Add(dataRow);
|
||||||
|
}
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据实体类得到表结构
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="model">实体类</param>
|
||||||
|
/// <returns>DataTable</returns>
|
||||||
|
private static DataTable CreateData<T>(T model) where T : new()
|
||||||
|
{
|
||||||
|
DataTable dataTable = new DataTable(typeof(T).Name);
|
||||||
|
foreach (PropertyInfo propertyInfo in typeof(T).GetAllProperties())
|
||||||
|
{
|
||||||
|
if (propertyInfo.PropertyType.IsGenericType)
|
||||||
|
{
|
||||||
|
if (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) && propertyInfo.PropertyType.GenericTypeArguments.Length > 0)
|
||||||
|
{
|
||||||
|
dataTable.Columns.Add(propertyInfo.Name, propertyInfo.PropertyType.GenericTypeArguments[0]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataTable.Columns.Add(propertyInfo.Name, propertyInfo.PropertyType);
|
||||||
|
}
|
||||||
|
return dataTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
using WalkingTec.Mvvm.Core.Support.FileHandlers;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public static class IServiceExtension
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddWtmContextForConsole(this IServiceCollection services, string jsonFileDir = null, string jsonFileName = null, Func<IWtmFileHandler, string> fileSubDirSelector = null)
|
||||||
|
{
|
||||||
|
var configBuilder = new ConfigurationBuilder();
|
||||||
|
IConfigurationRoot ConfigRoot = configBuilder.WTMConfig(null,jsonFileDir,jsonFileName).Build();
|
||||||
|
var WtmConfigs = ConfigRoot.Get<Configs>();
|
||||||
|
services.Configure<Configs>(ConfigRoot);
|
||||||
|
services.AddLogging(builder =>
|
||||||
|
{
|
||||||
|
builder.ClearProviders();
|
||||||
|
builder.AddConfiguration(ConfigRoot.GetSection("Logging"))
|
||||||
|
.AddConsole()
|
||||||
|
.AddDebug()
|
||||||
|
.AddWTMLogger();
|
||||||
|
});
|
||||||
|
var gd = GetGlobalData();
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
services.AddSingleton(gd);
|
||||||
|
WtmFileProvider._subDirFunc = fileSubDirSelector;
|
||||||
|
services.TryAddScoped<IDataContext, NullContext>();
|
||||||
|
services.AddScoped<WTMContext>();
|
||||||
|
services.AddScoped<WtmFileProvider>();
|
||||||
|
services.AddHttpClient();
|
||||||
|
if (WtmConfigs.Domains != null)
|
||||||
|
{
|
||||||
|
foreach (var item in WtmConfigs.Domains)
|
||||||
|
{
|
||||||
|
services.AddHttpClient(item.Key, x =>
|
||||||
|
{
|
||||||
|
x.BaseAddress = new Uri(item.Value.Url);
|
||||||
|
x.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
|
||||||
|
x.DefaultRequestHeaders.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
services.AddDistributedMemoryCache();
|
||||||
|
var cs = WtmConfigs.Connections;
|
||||||
|
foreach (var item in cs)
|
||||||
|
{
|
||||||
|
var dc = item.CreateDC();
|
||||||
|
dc.Database.EnsureCreated();
|
||||||
|
}
|
||||||
|
WtmFileProvider.Init(WtmConfigs, gd);
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GlobalData GetGlobalData()
|
||||||
|
{
|
||||||
|
GlobalData gd = new GlobalData();
|
||||||
|
gd.AllAssembly = Utils.GetAllAssembly();
|
||||||
|
return gd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/LogDebug.cs
Normal file
62
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/LogDebug.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//using System;
|
||||||
|
//using System.Diagnostics;
|
||||||
|
|
||||||
|
//namespace WalkingTec.Mvvm.Core
|
||||||
|
//{
|
||||||
|
// /// <summary>
|
||||||
|
// /// LogDebug 只有定义了DEBUG常量才会生效,可以理解为只在Debug模式下才会输出
|
||||||
|
// /// </summary>
|
||||||
|
// public sealed class LogDebug
|
||||||
|
// {
|
||||||
|
// /// <summary>
|
||||||
|
// /// Debug
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("DEBUG")]
|
||||||
|
// public static void Debug(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// LogTrace.Debug(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Info
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("DEBUG")]
|
||||||
|
// public static void Info(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// LogTrace.Info(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Warn
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("DEBUG")]
|
||||||
|
// public static void Warn(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// LogTrace.Warn(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Error
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("DEBUG")]
|
||||||
|
// public static void Error(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// LogTrace.Error(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Fatal
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("DEBUG")]
|
||||||
|
// public static void Fatal(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// LogTrace.Fatal(message, ex);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
126
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/LogTrace.cs
Normal file
126
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/LogTrace.cs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
//using System;
|
||||||
|
//using System.Diagnostics;
|
||||||
|
//using System.Reflection;
|
||||||
|
//using log4net;
|
||||||
|
|
||||||
|
//namespace WalkingTec.Mvvm.Core
|
||||||
|
//{
|
||||||
|
// /// <summary>
|
||||||
|
// /// Trace 只有定义了TRACE常量才会生效,可以理解为在Debug与Release下均会输出
|
||||||
|
// /// </summary>
|
||||||
|
// public sealed class LogTrace
|
||||||
|
// {
|
||||||
|
// private static ILog _logger;
|
||||||
|
// private static ILog Logger
|
||||||
|
// {
|
||||||
|
// get
|
||||||
|
// {
|
||||||
|
// if (_logger == null)
|
||||||
|
// {
|
||||||
|
// _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
// }
|
||||||
|
// return _logger;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// Write
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// public static void Write(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// OutputWindowWriteLine(message);
|
||||||
|
// if (ex == null)
|
||||||
|
// Logger.Debug(message);
|
||||||
|
// else
|
||||||
|
// Logger.Debug(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Debug
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("TRACE")]
|
||||||
|
// public static void Debug(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// Write(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Info
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("TRACE")]
|
||||||
|
// public static void Info(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// OutputWindowWriteLine(message);
|
||||||
|
// if (ex == null)
|
||||||
|
// Logger.Info(message);
|
||||||
|
// else
|
||||||
|
// Logger.Info(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Warn
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("TRACE")]
|
||||||
|
// public static void Warn(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// OutputWindowWriteLine(message);
|
||||||
|
// if (ex == null)
|
||||||
|
// Logger.Warn(message);
|
||||||
|
// else
|
||||||
|
// Logger.Warn(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Error
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("TRACE")]
|
||||||
|
// public static void Error(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// OutputWindowWriteLine(message);
|
||||||
|
// if (ex == null)
|
||||||
|
// Logger.Error(message);
|
||||||
|
// else
|
||||||
|
// Logger.Error(message, ex);
|
||||||
|
// }
|
||||||
|
// /// <summary>
|
||||||
|
// /// Fatal
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="message"></param>
|
||||||
|
// /// <param name="ex"></param>
|
||||||
|
// [Conditional("TRACE")]
|
||||||
|
// public static void Fatal(string message, Exception ex = null)
|
||||||
|
// {
|
||||||
|
// OutputWindowWriteLine(message);
|
||||||
|
// if (ex == null)
|
||||||
|
// Logger.Fatal(message);
|
||||||
|
// else
|
||||||
|
// Logger.Fatal(message, ex);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #region Output Window
|
||||||
|
// [Conditional("DEBUG")]
|
||||||
|
// private static void OutputWindowWriteLine(string message, int level = 0, string category = null)
|
||||||
|
// {
|
||||||
|
// if (System.Diagnostics.Debugger.IsLogging())
|
||||||
|
// {
|
||||||
|
// //调用Debugger.Log方法,这个方法可以输出信息到DebugView中
|
||||||
|
// System.Diagnostics.Debugger.Log(level, category, $"{message}\r\n");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// [Conditional("DEBUG")]
|
||||||
|
// private static void OutputWindowWrite(string message, int level = 0, string category = null)
|
||||||
|
// {
|
||||||
|
// if (System.Diagnostics.Debugger.IsLogging())
|
||||||
|
// {
|
||||||
|
// System.Diagnostics.Debugger.Log(level, category, message);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// #endregion
|
||||||
|
// }
|
||||||
|
//}
|
826
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/PropertyHelper.cs
Normal file
826
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Helper/PropertyHelper.cs
Normal file
@ -0,0 +1,826 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 属性辅助类
|
||||||
|
/// </summary>
|
||||||
|
public static class PropertyHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
public static object GetExpressionRootObj(Expression expression)
|
||||||
|
{
|
||||||
|
if (expression == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
Expression me = null;
|
||||||
|
LambdaExpression le = null;
|
||||||
|
if (expression is MemberExpression)
|
||||||
|
{
|
||||||
|
me = expression as MemberExpression;
|
||||||
|
}
|
||||||
|
if (expression is LambdaExpression)
|
||||||
|
{
|
||||||
|
le = expression as LambdaExpression;
|
||||||
|
if (le.Body is MemberExpression)
|
||||||
|
{
|
||||||
|
me = le.Body as MemberExpression;
|
||||||
|
}
|
||||||
|
if (le.Body is UnaryExpression)
|
||||||
|
{
|
||||||
|
me = (le.Body as UnaryExpression).Operand as MemberExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (me != null && me.NodeType == ExpressionType.MemberAccess)
|
||||||
|
{
|
||||||
|
Expression exp = (me as MemberExpression).Expression;
|
||||||
|
if (exp is MemberExpression)
|
||||||
|
{
|
||||||
|
me = exp as MemberExpression;
|
||||||
|
}
|
||||||
|
else if (exp is MethodCallExpression)
|
||||||
|
{
|
||||||
|
var mexp = exp as MethodCallExpression;
|
||||||
|
if (mexp.Method.Name == "get_Item")
|
||||||
|
{
|
||||||
|
object index = 0;
|
||||||
|
if (mexp.Arguments[0] is MemberExpression)
|
||||||
|
{
|
||||||
|
var obj = ((mexp.Arguments[0] as MemberExpression).Expression as ConstantExpression).Value;
|
||||||
|
index = obj.GetType().GetField((mexp.Arguments[0] as MemberExpression).Member.Name).GetValue(obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = (mexp.Arguments[0] as ConstantExpression).Value;
|
||||||
|
}
|
||||||
|
me = mexp.Object as MemberExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
me = exp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(me.NodeType == ExpressionType.Constant)
|
||||||
|
{
|
||||||
|
return (me as ConstantExpression)?.Value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Func<object, object> GetPropertyExpression(Type objtype, string property)
|
||||||
|
{
|
||||||
|
property = Regex.Replace(property, @"\[[^\]]*\]", string.Empty);
|
||||||
|
List<string> level = new List<string>();
|
||||||
|
if (property.Contains('.'))
|
||||||
|
{
|
||||||
|
level.AddRange(property.Split('.'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
level.Add(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pe = Expression.Parameter(objtype);
|
||||||
|
var member = Expression.Property(pe, objtype.GetSingleProperty(level[0]));
|
||||||
|
for (int i = 1; i < level.Count; i++)
|
||||||
|
{
|
||||||
|
member = Expression.Property(member, member.Type.GetSingleProperty(level[i]));
|
||||||
|
}
|
||||||
|
return Expression.Lambda<Func<object, object>>(member, pe).Compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性名
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">属性表达式</param>
|
||||||
|
/// <param name="getAll">是否获取全部级别名称,比如a.b.c</param>
|
||||||
|
/// <returns>属性名</returns>
|
||||||
|
public static string GetPropertyName(this Expression expression, bool getAll = true)
|
||||||
|
{
|
||||||
|
if (expression == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
MemberExpression me = null;
|
||||||
|
LambdaExpression le = null;
|
||||||
|
if (expression is MemberExpression)
|
||||||
|
{
|
||||||
|
me = expression as MemberExpression;
|
||||||
|
}
|
||||||
|
if (expression is LambdaExpression)
|
||||||
|
{
|
||||||
|
le = expression as LambdaExpression;
|
||||||
|
if (le.Body is MemberExpression)
|
||||||
|
{
|
||||||
|
me = le.Body as MemberExpression;
|
||||||
|
}
|
||||||
|
if (le.Body is UnaryExpression)
|
||||||
|
{
|
||||||
|
me = (le.Body as UnaryExpression).Operand as MemberExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string rv = "";
|
||||||
|
if (me != null)
|
||||||
|
{
|
||||||
|
rv = me.Member.Name;
|
||||||
|
}
|
||||||
|
while (me != null && getAll && me.NodeType == ExpressionType.MemberAccess)
|
||||||
|
{
|
||||||
|
Expression exp = me.Expression;
|
||||||
|
if (exp is MemberExpression)
|
||||||
|
{
|
||||||
|
rv = (exp as MemberExpression).Member.Name + "." + rv;
|
||||||
|
me = exp as MemberExpression;
|
||||||
|
}
|
||||||
|
else if (exp is MethodCallExpression)
|
||||||
|
{
|
||||||
|
var mexp = exp as MethodCallExpression;
|
||||||
|
if (mexp.Method.Name == "get_Item")
|
||||||
|
{
|
||||||
|
object index = 0;
|
||||||
|
if (mexp.Arguments[0] is MemberExpression)
|
||||||
|
{
|
||||||
|
var obj = ((mexp.Arguments[0] as MemberExpression).Expression as ConstantExpression).Value;
|
||||||
|
index = obj.GetType().GetField((mexp.Arguments[0] as MemberExpression).Member.Name).GetValue(obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = (mexp.Arguments[0] as ConstantExpression).Value;
|
||||||
|
}
|
||||||
|
rv = (mexp.Object as MemberExpression).Member.Name + "[" + index + "]." + rv;
|
||||||
|
me = mexp.Object as MemberExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Expression GetMemberExp(this ParameterExpression self, Expression member)
|
||||||
|
{
|
||||||
|
return self.GetMemberExp(member.GetPropertyName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Expression GetMemberExp(this ParameterExpression self, string memberName)
|
||||||
|
{
|
||||||
|
var names = memberName.Split(',');
|
||||||
|
Expression rv = Expression.PropertyOrField(self, names[0]); ;
|
||||||
|
for (int i = 1; i < names.Length; i++)
|
||||||
|
{
|
||||||
|
rv = Expression.PropertyOrField(rv, names[i]);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性名的Id形式,将属性名中的.转换为_,适合作为HTML中的Id使用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">属性表达式</param>
|
||||||
|
/// <param name="getAll">是否获取全部级别名称,比如a.b.c</param>
|
||||||
|
/// <returns>属性Id</returns>
|
||||||
|
public static string GetPropertyId(this Expression expression, bool getAll = true)
|
||||||
|
{
|
||||||
|
return GetPropertyName(expression, getAll).GetIdByName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取正则表达式错误
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pi">属性信息</param>
|
||||||
|
/// <returns>错误文本</returns>
|
||||||
|
public static string GetRegexErrorMessage(this MemberInfo pi)
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
|
||||||
|
if (pi.GetCustomAttributes(typeof(RegularExpressionAttribute), false).FirstOrDefault() is RegularExpressionAttribute dis && !string.IsNullOrEmpty(dis.ErrorMessage))
|
||||||
|
{
|
||||||
|
rv = dis.ErrorMessage;
|
||||||
|
if (CoreProgram._localizer != null)
|
||||||
|
{
|
||||||
|
rv = CoreProgram._localizer[rv];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = "";
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性显示名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pi">属性信息</param>
|
||||||
|
/// <param name="local"></param>
|
||||||
|
/// <returns>属性名称</returns>
|
||||||
|
public static string GetPropertyDisplayName(this MemberInfo pi, IStringLocalizer local = null)
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
if (pi.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault() is DisplayAttribute dis && !string.IsNullOrEmpty(dis.Name))
|
||||||
|
{
|
||||||
|
rv = dis.Name;
|
||||||
|
if (local == null)
|
||||||
|
{
|
||||||
|
if (CoreProgram._localizer != null)
|
||||||
|
{
|
||||||
|
rv = CoreProgram._localizer[rv];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = local[rv];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = pi.Name;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性显示名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">属性表达式</param>
|
||||||
|
/// <param name="local"></param>
|
||||||
|
/// <returns>属性显示名称</returns>
|
||||||
|
public static string GetPropertyDisplayName(this Expression expression, IStringLocalizer local = null)
|
||||||
|
{
|
||||||
|
return GetPropertyDisplayName(expression.GetPropertyInfo(), local);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取枚举显示名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">枚举值</param>
|
||||||
|
/// <returns>枚举显示名称</returns>
|
||||||
|
public static string GetEnumDisplayName(this Enum value)
|
||||||
|
{
|
||||||
|
return GetEnumDisplayName(value.GetType(), value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">属性表达式</param>
|
||||||
|
/// <returns>属性信息</returns>
|
||||||
|
public static PropertyInfo GetPropertyInfo(this Expression expression)
|
||||||
|
{
|
||||||
|
MemberExpression me = null;
|
||||||
|
LambdaExpression le = null;
|
||||||
|
if (expression is MemberExpression)
|
||||||
|
{
|
||||||
|
me = expression as MemberExpression;
|
||||||
|
}
|
||||||
|
if (expression is LambdaExpression)
|
||||||
|
{
|
||||||
|
le = expression as LambdaExpression;
|
||||||
|
if (le.Body is MemberExpression)
|
||||||
|
{
|
||||||
|
me = le.Body as MemberExpression;
|
||||||
|
}
|
||||||
|
if (le.Body is UnaryExpression)
|
||||||
|
{
|
||||||
|
me = (le.Body as UnaryExpression).Operand as MemberExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyInfo rv = null;
|
||||||
|
if (me != null)
|
||||||
|
{
|
||||||
|
rv = me.Member.DeclaringType.GetSingleProperty(me.Member.Name);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exp">属性表达式</param>
|
||||||
|
/// <param name="obj">属性所在实例</param>
|
||||||
|
/// <returns>属性值</returns>
|
||||||
|
public static object GetPropertyValue(this object obj, LambdaExpression exp)
|
||||||
|
{
|
||||||
|
//获取表达式的值,并过滤单引号
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var expValue = exp.Compile().DynamicInvoke(obj);
|
||||||
|
object val = expValue;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object GetPropertyValue(this object obj, string property)
|
||||||
|
{
|
||||||
|
//获取表达式的值,并过滤单引号
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return obj.GetType().GetSingleProperty(property).GetValue(obj); ;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<string> GetPropertySiblingValues(this object obj, string propertyName)
|
||||||
|
{
|
||||||
|
if(obj == null)
|
||||||
|
{
|
||||||
|
return new List<string>();
|
||||||
|
}
|
||||||
|
Regex reg = new Regex("(.*?)\\[\\-?\\d?\\]\\.(.*?)$");
|
||||||
|
var match = reg.Match(propertyName);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var name1 = match.Groups[1].Value;
|
||||||
|
var name2 = match.Groups[2].Value;
|
||||||
|
|
||||||
|
var levels = name1.Split('.');
|
||||||
|
var objtype = obj.GetType();
|
||||||
|
var pe = Expression.Parameter(objtype);
|
||||||
|
var member = Expression.Property(pe, objtype.GetSingleProperty(levels[0]));
|
||||||
|
for (int i = 1; i < levels.Length; i++)
|
||||||
|
{
|
||||||
|
member = Expression.Property(member, member.Type.GetSingleProperty(levels[i]));
|
||||||
|
}
|
||||||
|
var pe2 = Expression.Parameter(member.Type.GetGenericArguments()[0]);
|
||||||
|
var cast = Expression.Call(typeof(Enumerable), "Cast", new Type[] { pe2.Type }, member);
|
||||||
|
|
||||||
|
var name2exp = Expression.Property(pe2, pe2.Type.GetSingleProperty(name2));
|
||||||
|
var selectexp = Expression.Call(name2exp, "ToString", Type.EmptyTypes);
|
||||||
|
|
||||||
|
Expression select = Expression.Call(
|
||||||
|
typeof(Enumerable),
|
||||||
|
"Select",
|
||||||
|
new Type[] { pe2.Type, typeof(string) },
|
||||||
|
cast,
|
||||||
|
Expression.Lambda(selectexp, pe2));
|
||||||
|
|
||||||
|
|
||||||
|
var lambda = Expression.Lambda(select, pe);
|
||||||
|
var rv = new List<string>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
rv = (lambda.Compile().DynamicInvoke(obj) as IEnumerable<string>)?.ToList();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断属性是否必填
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pi">属性信息</param>
|
||||||
|
/// <returns>是否必填</returns>
|
||||||
|
public static bool IsPropertyRequired(this MemberInfo pi)
|
||||||
|
{
|
||||||
|
bool isRequired = false;
|
||||||
|
if (pi != null)
|
||||||
|
{
|
||||||
|
//如果需要显示星号,则判断是否是必填项,如果是必填则在内容后面加上星号
|
||||||
|
//所有int,float。。。这种Primitive类型的,肯定都是必填
|
||||||
|
Type t = pi.GetMemberType();
|
||||||
|
if (t != null && (t.IsPrimitive() || t.IsEnum() || t == typeof(decimal) || t == typeof(Guid)))
|
||||||
|
{
|
||||||
|
isRequired = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//对于其他类,检查是否有RequiredAttribute,如果有就是必填
|
||||||
|
if (pi.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault() is RequiredAttribute required && required.AllowEmptyStrings == false)
|
||||||
|
{
|
||||||
|
isRequired = true;
|
||||||
|
}
|
||||||
|
else if (pi.GetCustomAttributes(typeof(KeyAttribute), false).FirstOrDefault() != null)
|
||||||
|
{
|
||||||
|
isRequired = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置属性值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">属性所在实例</param>
|
||||||
|
/// <param name="property">属性名</param>
|
||||||
|
/// <param name="value">要赋的值</param>
|
||||||
|
/// <param name="prefix">属性前缀</param>
|
||||||
|
/// <param name="stringBasedValue">是否为字符串格式的值</param>
|
||||||
|
public static void SetPropertyValue(this object source, string property, object value, string prefix = null, bool stringBasedValue = false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
property = Regex.Replace(property, @"\[[^\]]*\]", string.Empty);
|
||||||
|
List<string> level = new List<string>();
|
||||||
|
if (property.Contains('.'))
|
||||||
|
{
|
||||||
|
level.AddRange(property.Split('.'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
level.Add(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(prefix))
|
||||||
|
{
|
||||||
|
level.Insert(0, prefix);
|
||||||
|
}
|
||||||
|
object temp = source;
|
||||||
|
Type tempType = source.GetType();
|
||||||
|
for (int i = 0; i < level.Count - 1; i++)
|
||||||
|
{
|
||||||
|
var member = tempType.GetMember(level[i])[0];
|
||||||
|
if (member != null)
|
||||||
|
{
|
||||||
|
var va = member.GetMemberValue(temp);
|
||||||
|
if (va != null)
|
||||||
|
{
|
||||||
|
temp = va;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var newInstance = member.GetMemberType().GetConstructor(Type.EmptyTypes).Invoke(null);
|
||||||
|
member.SetMemberValue(temp, newInstance, null);
|
||||||
|
temp = newInstance;
|
||||||
|
}
|
||||||
|
tempType = member.GetMemberType();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var memberInfos = tempType.GetMember(level.Last());
|
||||||
|
if (!memberInfos.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var fproperty = memberInfos[0];
|
||||||
|
if (value == null || ((value is StringValues s) && StringValues.IsNullOrEmpty(s)))
|
||||||
|
{
|
||||||
|
fproperty.SetMemberValue(temp, null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isArray = false;
|
||||||
|
if (value != null && value.GetType().IsArray == true)
|
||||||
|
{
|
||||||
|
isArray = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stringBasedValue == true)
|
||||||
|
{
|
||||||
|
Type propertyType = fproperty.GetMemberType();
|
||||||
|
if (propertyType.IsGeneric(typeof(List<>)) == true)
|
||||||
|
{
|
||||||
|
var list = propertyType.GetConstructor(Type.EmptyTypes).Invoke(null) as IList;
|
||||||
|
|
||||||
|
var gs = propertyType.GenericTypeArguments;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (value.GetType() == typeof(StringValues))
|
||||||
|
{
|
||||||
|
var strVals = (StringValues)value;
|
||||||
|
var a = strVals.ToArray();
|
||||||
|
for (int i = 0; i < a.Length; i++)
|
||||||
|
{
|
||||||
|
list.Add(a[i].ConvertValue(gs[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isArray)
|
||||||
|
{
|
||||||
|
var a = (value as object[]);
|
||||||
|
for (int i = 0; i < a.Length; i++)
|
||||||
|
{
|
||||||
|
list.Add(a[i].ConvertValue(gs[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list = value.ConvertValue(propertyType) as IList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
fproperty.SetMemberValue(temp, list, null);
|
||||||
|
}
|
||||||
|
else if (propertyType.IsArray)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var strVals = (StringValues)value;
|
||||||
|
var eletype = propertyType.GetElementType();
|
||||||
|
var arr = Array.CreateInstance(eletype, strVals.Count);
|
||||||
|
for (int i = 0; i < arr.Length; i++)
|
||||||
|
{
|
||||||
|
arr.SetValue(strVals[i].ConvertValue(eletype), i);
|
||||||
|
}
|
||||||
|
fproperty.SetMemberValue(temp, arr, null);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isArray)
|
||||||
|
{
|
||||||
|
var a = (value as object[]);
|
||||||
|
if (a.Length == 1)
|
||||||
|
{
|
||||||
|
value = a[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value is string)
|
||||||
|
{
|
||||||
|
value = value.ToString().Replace("\\", "/");
|
||||||
|
}
|
||||||
|
fproperty.SetMemberValue(temp, value, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value is string)
|
||||||
|
{
|
||||||
|
value = value.ToString().Replace("\\", "/");
|
||||||
|
}
|
||||||
|
fproperty.SetMemberValue(temp, value, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据MemberInfo获取值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mi">MemberInfo</param>
|
||||||
|
/// <param name="obj">所在实例</param>
|
||||||
|
/// <param name="index">如果是数组,指定数组下标。默认为null</param>
|
||||||
|
/// <returns>MemberInfo的值</returns>
|
||||||
|
public static object GetMemberValue(this MemberInfo mi, object obj, object[] index = null)
|
||||||
|
{
|
||||||
|
object rv = null;
|
||||||
|
if (mi.MemberType == MemberTypes.Property)
|
||||||
|
{
|
||||||
|
rv = ((PropertyInfo)mi).GetValue(obj, index);
|
||||||
|
}
|
||||||
|
else if (mi.MemberType == MemberTypes.Field)
|
||||||
|
{
|
||||||
|
rv = ((FieldInfo)mi).GetValue(obj);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设定MemberInfo的值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mi">MemberInfo</param>
|
||||||
|
/// <param name="obj">所在实例</param>
|
||||||
|
/// <param name="val">要赋的值</param>
|
||||||
|
/// <param name="index">如果是数组,指定数组下标。默认为null</param>
|
||||||
|
public static void SetMemberValue(this MemberInfo mi, object obj, object val, object[] index = null)
|
||||||
|
{
|
||||||
|
object newval = val;
|
||||||
|
if (val is string s)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(s))
|
||||||
|
{
|
||||||
|
val = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (val != null && val.GetType() != mi.GetMemberType())
|
||||||
|
{
|
||||||
|
newval = val.ConvertValue(mi.GetMemberType());
|
||||||
|
}
|
||||||
|
if (mi.MemberType == MemberTypes.Property)
|
||||||
|
{
|
||||||
|
((PropertyInfo)mi).SetValue(obj, newval, index);
|
||||||
|
}
|
||||||
|
else if (mi.MemberType == MemberTypes.Field)
|
||||||
|
{
|
||||||
|
((FieldInfo)mi).SetValue(obj, newval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取某个MemberInfo的类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mi">MemberInfo</param>
|
||||||
|
/// <returns>类型</returns>
|
||||||
|
public static Type GetMemberType(this MemberInfo mi)
|
||||||
|
{
|
||||||
|
Type rv = null;
|
||||||
|
if (mi != null)
|
||||||
|
{
|
||||||
|
if (mi.MemberType == MemberTypes.Property)
|
||||||
|
{
|
||||||
|
rv = ((PropertyInfo)mi).PropertyType;
|
||||||
|
}
|
||||||
|
else if (mi.MemberType == MemberTypes.Field)
|
||||||
|
{
|
||||||
|
rv = ((FieldInfo)mi).FieldType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取枚举显示名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="enumType">枚举类型</param>
|
||||||
|
/// <param name="value">枚举值</param>
|
||||||
|
/// <returns>枚举显示名称</returns>
|
||||||
|
public static string GetEnumDisplayName(Type enumType, string value)
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
FieldInfo field = null;
|
||||||
|
|
||||||
|
if (enumType.IsEnum())
|
||||||
|
{
|
||||||
|
field = enumType.GetField(value);
|
||||||
|
}
|
||||||
|
//如果是nullable的枚举
|
||||||
|
if (enumType.IsGeneric(typeof(Nullable<>)) && enumType.GetGenericArguments()[0].IsEnum())
|
||||||
|
{
|
||||||
|
field = enumType.GenericTypeArguments[0].GetField(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
var attribs = field.GetCustomAttributes(typeof(DisplayAttribute), true).ToList();
|
||||||
|
if (attribs.Count > 0)
|
||||||
|
{
|
||||||
|
rv = ((DisplayAttribute)attribs[0]).GetName();
|
||||||
|
if (CoreProgram._localizer != null)
|
||||||
|
{
|
||||||
|
rv = CoreProgram._localizer[rv];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetEnumDisplayName(Type enumType, int value)
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
FieldInfo field = null;
|
||||||
|
string ename = "";
|
||||||
|
if (enumType.IsEnum())
|
||||||
|
{
|
||||||
|
ename = enumType.GetEnumName(value);
|
||||||
|
field = enumType.GetField(ename);
|
||||||
|
}
|
||||||
|
//如果是nullable的枚举
|
||||||
|
if (enumType.IsGeneric(typeof(Nullable<>)) && enumType.GetGenericArguments()[0].IsEnum())
|
||||||
|
{
|
||||||
|
ename = enumType.GenericTypeArguments[0].GetEnumName(value);
|
||||||
|
field = enumType.GenericTypeArguments[0].GetField(ename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
var attribs = field.GetCustomAttributes(typeof(DisplayAttribute), true).ToList();
|
||||||
|
if (attribs.Count > 0)
|
||||||
|
{
|
||||||
|
rv = ((DisplayAttribute)attribs[0]).GetName();
|
||||||
|
if (CoreProgram._localizer != null)
|
||||||
|
{
|
||||||
|
rv = CoreProgram._localizer[rv];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = ename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 转化值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">要转换的值</param>
|
||||||
|
/// <param name="propertyType">转换后的类型</param>
|
||||||
|
/// <returns>转换后的值</returns>
|
||||||
|
public static object ConvertValue(this object value, Type propertyType)
|
||||||
|
{
|
||||||
|
object val = null;
|
||||||
|
if (propertyType.IsGeneric(typeof(Nullable<>)) == true)
|
||||||
|
{
|
||||||
|
var gs = propertyType.GenericTypeArguments;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
val = ConvertValue(value, gs[0]);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
else if (propertyType.IsEnum())
|
||||||
|
{
|
||||||
|
val = Enum.Parse(propertyType, value.ToString());
|
||||||
|
}
|
||||||
|
else if (propertyType == typeof(string))
|
||||||
|
{
|
||||||
|
val = value?.ToString().Trim();
|
||||||
|
}
|
||||||
|
else if (propertyType == typeof(Guid))
|
||||||
|
{
|
||||||
|
bool suc = Guid.TryParse(value?.ToString(), out Guid g);
|
||||||
|
if (suc)
|
||||||
|
{
|
||||||
|
val = g;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = Guid.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (propertyType == typeof(DateRange))
|
||||||
|
{
|
||||||
|
if (DateRange.TryParse(value.ToString(), out var result))
|
||||||
|
{
|
||||||
|
val = result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = DateRange.Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (value.ToString().StartsWith("`") && value.ToString().EndsWith("`"))
|
||||||
|
{
|
||||||
|
string inner = value.ToString().Trim('`').TrimEnd(',');
|
||||||
|
if (!string.IsNullOrWhiteSpace(inner))
|
||||||
|
{
|
||||||
|
val = propertyType.GetConstructor(Type.EmptyTypes).Invoke(null);
|
||||||
|
string[] pair = inner.Split(',');
|
||||||
|
var gs = propertyType.GetGenericArguments();
|
||||||
|
foreach (var p in pair)
|
||||||
|
{
|
||||||
|
(val as IList).Add(Convert.ChangeType(p, gs[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = Convert.ChangeType(value.ToString(), propertyType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object MakeList(Type innerType, string propertyName, object[] values)
|
||||||
|
{
|
||||||
|
object rv = typeof(List<>).MakeGenericType(innerType).GetConstructor(Type.EmptyTypes).Invoke(null);
|
||||||
|
var mi = rv.GetType().GetMethod("Add");
|
||||||
|
var con = innerType.GetConstructor(Type.EmptyTypes);
|
||||||
|
foreach (var item in values)
|
||||||
|
{
|
||||||
|
var newobj = con.Invoke(null);
|
||||||
|
newobj.SetPropertyValue(propertyName, item);
|
||||||
|
mi.Invoke(rv, new object[] { newobj });
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
162
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IBasePagedListVM.cs
Normal file
162
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IBasePagedListVM.cs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ListVM接口
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">ListVM中的Model类</typeparam>
|
||||||
|
/// <typeparam name="S">ListVM使用的Searcher类</typeparam>
|
||||||
|
public interface IBasePagedListVM<out T, out S> : IBaseVM
|
||||||
|
where T : TopBasePoco
|
||||||
|
where S : ISearcher
|
||||||
|
{
|
||||||
|
Type ModelType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多级表头深度 默认 1级
|
||||||
|
/// </summary>
|
||||||
|
int GetChildrenDepth();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GetHeaders
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
|
||||||
|
IEnumerable<IGridColumn<T>> GetHeaders();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面动作
|
||||||
|
/// </summary>
|
||||||
|
List<GridAction> GetGridActions();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询并生成Excel
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Excel文件</returns>
|
||||||
|
byte[] GenerateExcel();
|
||||||
|
|
||||||
|
string TotalText { get; set; }
|
||||||
|
#region Old
|
||||||
|
event Action<IBasePagedListVM<T, S>> OnAfterInitList;
|
||||||
|
/// <summary>
|
||||||
|
///记录批量操作时列表中选择的Id
|
||||||
|
/// </summary>
|
||||||
|
List<string> Ids { get; set; }
|
||||||
|
string SelectorValueField { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取Model集合
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Model集合</returns>
|
||||||
|
IEnumerable<T> GetEntityList();
|
||||||
|
|
||||||
|
void ClearEntityList();
|
||||||
|
/// <summary>
|
||||||
|
/// 获取Searcher
|
||||||
|
/// </summary>
|
||||||
|
S Searcher { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// GetIsSelected
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool GetIsSelected(object item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否已经搜索过
|
||||||
|
/// </summary>
|
||||||
|
bool IsSearched { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PassSearch
|
||||||
|
/// </summary>
|
||||||
|
bool PassSearch { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 搜索模式
|
||||||
|
/// </summary>
|
||||||
|
ListVMSearchModeEnum SearcherMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否需要分页
|
||||||
|
/// </summary>
|
||||||
|
bool NeedPage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 允许导出Excel的最大行数,超过行数会分成多个文件,最多不能超过100万
|
||||||
|
/// </summary>
|
||||||
|
int ExportMaxCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据允许导出的Excel最大行数,算出最终导出的Excel个数
|
||||||
|
/// </summary>
|
||||||
|
int ExportExcelCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除操作列
|
||||||
|
/// </summary>
|
||||||
|
void RemoveActionColumn(object root = null);
|
||||||
|
|
||||||
|
void RemoveAction();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 填加错误信息列,用于批量操作的列表
|
||||||
|
/// </summary>
|
||||||
|
void AddErrorColumn();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 搜索条件Panel的Id
|
||||||
|
/// </summary>
|
||||||
|
string SearcherDivId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GetSearchQuery
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
IOrderedQueryable<T> GetSearchQuery();
|
||||||
|
/// <summary>
|
||||||
|
/// DoSearch
|
||||||
|
/// </summary>
|
||||||
|
void DoSearch();
|
||||||
|
/// <summary>
|
||||||
|
/// CopyContext
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vm"></param>
|
||||||
|
void CopyContext(BaseVM vm);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ReplaceWhere
|
||||||
|
/// </summary>
|
||||||
|
Expression ReplaceWhere { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SetFullRowColor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
string SetFullRowColor(object entity);
|
||||||
|
/// <summary>
|
||||||
|
/// SetFullRowBgColor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
string SetFullRowBgColor(object entity);
|
||||||
|
|
||||||
|
T CreateEmptyEntity();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用于为子表生成可编辑Grid时,内部控件名称前缀
|
||||||
|
/// </summary>
|
||||||
|
string DetailGridPrix { get; set; }
|
||||||
|
|
||||||
|
void DoInitListVM();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
85
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IBaseVM.cs
Normal file
85
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IBaseVM.cs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IBaseVM
|
||||||
|
/// </summary>
|
||||||
|
public interface IBaseVM
|
||||||
|
{
|
||||||
|
#region Property
|
||||||
|
|
||||||
|
WTMContext Wtm { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UniqueId
|
||||||
|
/// </summary>
|
||||||
|
string UniqueId { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// WindowIds
|
||||||
|
/// </summary>
|
||||||
|
string WindowIds { get;}
|
||||||
|
/// <summary>
|
||||||
|
/// ViewDivId
|
||||||
|
/// </summary>
|
||||||
|
string ViewDivId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// DC
|
||||||
|
/// </summary>
|
||||||
|
IDataContext DC { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// VMFullName
|
||||||
|
/// </summary>
|
||||||
|
string VMFullName { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// CreatorAssembly
|
||||||
|
/// </summary>
|
||||||
|
string CreatorAssembly { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// CurrentCS
|
||||||
|
/// </summary>
|
||||||
|
string CurrentCS { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// FC
|
||||||
|
/// </summary>
|
||||||
|
Dictionary<string, object> FC { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Config
|
||||||
|
/// </summary>
|
||||||
|
Configs ConfigInfo { get; }
|
||||||
|
|
||||||
|
ISessionService Session { get; }
|
||||||
|
|
||||||
|
IDistributedCache Cache { get; }
|
||||||
|
|
||||||
|
LoginUserInfo LoginUserInfo { get; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// InitVM 完成后触发的事件
|
||||||
|
/// </summary>
|
||||||
|
event Action<IBaseVM> OnAfterInit;
|
||||||
|
/// <summary>
|
||||||
|
/// ReInitVM 完成后触发的事件
|
||||||
|
/// </summary>
|
||||||
|
event Action<IBaseVM> OnAfterReInit;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Method
|
||||||
|
/// <summary>
|
||||||
|
/// 调用 InitVM 并触发 OnAfterInit 事件
|
||||||
|
/// </summary>
|
||||||
|
void DoInit();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用 ReInitVM 并触发 OnAfterReInit 事件
|
||||||
|
/// </summary>
|
||||||
|
void DoReInit();
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
143
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IDataContext.cs
Normal file
143
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IDataContext.cs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IDataContext
|
||||||
|
/// </summary>
|
||||||
|
public interface IDataContext : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IsFake
|
||||||
|
/// </summary>
|
||||||
|
bool IsFake { get; set; }
|
||||||
|
|
||||||
|
bool IsDebug { get; set; }
|
||||||
|
|
||||||
|
DBTypeEnum DBType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// AddEntity
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="entity"></param>
|
||||||
|
void AddEntity<T>(T entity) where T : TopBasePoco;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UpdateEntity
|
||||||
|
/// </summary>
|
||||||
|
void UpdateEntity<T>(T entity) where T : TopBasePoco;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UpdateProperty
|
||||||
|
/// </summary>
|
||||||
|
void UpdateProperty<T>(T entity, Expression<Func<T, object>> fieldExp) where T : TopBasePoco;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UpdateProperty
|
||||||
|
/// </summary>
|
||||||
|
void UpdateProperty<T>(T entity, string fieldName) where T : TopBasePoco;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DeleteEntity
|
||||||
|
/// </summary>
|
||||||
|
void DeleteEntity<T>(T entity) where T : TopBasePoco;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CascadeDelete
|
||||||
|
/// </summary>
|
||||||
|
void CascadeDelete<T>(T entity) where T : TreePoco;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
DbSet<T> Set<T>() where T : class;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Model
|
||||||
|
/// </summary>
|
||||||
|
IModel Model { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database
|
||||||
|
/// </summary>
|
||||||
|
DatabaseFacade Database { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CSName
|
||||||
|
/// </summary>
|
||||||
|
string CSName { get; set; }
|
||||||
|
|
||||||
|
#region SaveChange
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SaveChanges
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
int SaveChanges();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SaveChanges
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
int SaveChanges(bool acceptAllChangesOnSuccess);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SaveChangesAsync
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SaveChangesAsync
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="AllModel"></param>
|
||||||
|
/// <param name="IsSpa"></param>
|
||||||
|
/// <returns>返回true即数据新建完成,进入初始化操作,返回false即数据库已经存在</returns>
|
||||||
|
Task<bool> DataInit(object AllModel, bool IsSpa);
|
||||||
|
|
||||||
|
IDataContext CreateNew();
|
||||||
|
IDataContext ReCreate();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行存储过程,返回datatable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">存储过程名称</param>
|
||||||
|
/// <param name="paras">参数</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
DataTable RunSP(string command, params object[] paras);
|
||||||
|
IEnumerable<TElement> RunSP<TElement>(string command, params object[] paras);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行sql语句,返回datatable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">查询sql语句</param>
|
||||||
|
/// <param name="paras">参数</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
DataTable RunSQL(string command, params object[] paras);
|
||||||
|
IEnumerable<TElement> RunSQL<TElement>(string sql, params object[] paras);
|
||||||
|
DataTable Run(string sql, CommandType commandType, params object[] paras);
|
||||||
|
IEnumerable<TElement> Run<TElement>(string sql, CommandType commandType, params object[] paras);
|
||||||
|
object CreateCommandParameter(string name, object value, ParameterDirection dir);
|
||||||
|
|
||||||
|
void SetLoggerFactory(ILoggerFactory factory);
|
||||||
|
}
|
||||||
|
}
|
12
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ISessionService.cs
Normal file
12
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/ISessionService.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Session接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ISessionService
|
||||||
|
{
|
||||||
|
T Get<T>(string key);
|
||||||
|
void Set<T>(string key, T val);
|
||||||
|
string SessionId { get; }
|
||||||
|
}
|
||||||
|
}
|
28
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IUIService.cs
Normal file
28
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/IUIService.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public interface IUIService
|
||||||
|
{
|
||||||
|
string MakeButton(ButtonTypesEnum buttonType, string url, string buttonText, int? width, int? height, string title = null, string buttonID = null,bool resizable = true, bool max = false, string currentdivid = "", string buttonClass = null, string style = null, RedirectTypesEnum rtype = RedirectTypesEnum.Layer);
|
||||||
|
string MakeDialogButton(ButtonTypesEnum buttonType, string url, string buttonText, int? width, int? height, string title = null, string buttonID = null, bool showDialog = true, bool resizable = true, bool max = false,string buttonClass = null, string style = null);
|
||||||
|
|
||||||
|
string MakeDownloadButton(ButtonTypesEnum buttonType, Guid fileID, string buttonText = null, string _DONOT_USE_CS = "default", string buttonClass = null, string style = null);
|
||||||
|
|
||||||
|
string MakeViewButton(ButtonTypesEnum buttonType, Guid fileID, string buttonText = null, int? width = null, int? height = null, string title = null, bool resizable = true, string _DONOT_USE_CS = "default", bool maxed = false, string buttonClass = null, string style = null);
|
||||||
|
|
||||||
|
string MakeScriptButton(ButtonTypesEnum buttonType, string buttonText, string script = "", string buttonID = null, string url = null, string buttonClass = null, string style = null);
|
||||||
|
|
||||||
|
string MakeCheckBox(bool ischeck, string text = null, string name = null, string value = null, bool isReadOnly = false);
|
||||||
|
|
||||||
|
string MakeRadio(bool ischeck, string text = null, string name = null, string value = null, bool isReadOnly = false);
|
||||||
|
|
||||||
|
string MakeCombo(string name = null, List<ComboSelectListItem> value = null, string selectedValue = null, string emptyText = null, bool isReadOnly = false);
|
||||||
|
|
||||||
|
string MakeTextBox(string name = null, string value = null, string emptyText = null, bool isReadOnly = false);
|
||||||
|
string MakeDateTime(string name = null, string value = null, string emptyText = null, bool isReadOnly = false);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Implement
|
||||||
|
{
|
||||||
|
public class DefaultUIService : IUIService
|
||||||
|
{
|
||||||
|
public string MakeDialogButton(ButtonTypesEnum buttonType, string url, string buttonText, int? width, int? height, string title = null, string buttonID = null, bool showDialog = true, bool resizable = true, bool max = false, string buttonClass = null, string style = null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeDownloadButton(ButtonTypesEnum buttonType, Guid fileID, string buttonText = null, string _DONOT_USE_CS = "default", string buttonClass = null, string style = null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeCheckBox(bool ischeck, string text = null, string name = null, string value = null, bool isReadOnly = false)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeButton(ButtonTypesEnum buttonType, string url, string buttonText, int? width, int? height, string title = null, string buttonID = null, bool resizable = true, bool max = false, string currentdivid = "", string buttonClass = null, string style = null, RedirectTypesEnum rtype = RedirectTypesEnum.Layer)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeViewButton(ButtonTypesEnum buttonType, Guid fileID, string buttonText = null, int? width = null, int? height = null, string title = null, bool resizable = true, string _DONOT_USE_CS = "default", bool maxed = false, string buttonClass = null, string style = null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeScriptButton(ButtonTypesEnum buttonType, string buttonText, string script = "", string buttonID = null, string url = null, string buttonClass = null, string style = null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeRadio(bool ischeck, string text = null, string name = null, string value = null, bool isReadOnly = false)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeCombo(string name = null, List<ComboSelectListItem> value = null, string selectedValue = null, string emptyText = null, bool isReadOnly = false)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeTextBox(string name = null, string value = null, string emptyText = null, bool isReadOnly = false)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MakeDateTime(string name = null, string value = null, string emptyText = null, bool isReadOnly = false)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/BodyConverter.cs
Normal file
105
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/BodyConverter.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// StringIgnoreLTGTConvert
|
||||||
|
/// 忽略客户端提交的 <及>字符
|
||||||
|
/// </summary>
|
||||||
|
public class BodyConverter : JsonConverter<PostedBody>
|
||||||
|
{
|
||||||
|
public override PostedBody Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var rv = new PostedBody();
|
||||||
|
rv.ProNames = new List<string>();
|
||||||
|
List<string> prefix = new List<string>();
|
||||||
|
int depth = 0;
|
||||||
|
string lastObjecName = "";
|
||||||
|
int insideArray = 0;
|
||||||
|
JsonTokenType lastToken = JsonTokenType.Null;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.StartArray)
|
||||||
|
{
|
||||||
|
insideArray++;
|
||||||
|
depth++;
|
||||||
|
prefix.Add(lastObjecName + "[0]");
|
||||||
|
}
|
||||||
|
if (reader.TokenType == JsonTokenType.EndArray)
|
||||||
|
{
|
||||||
|
insideArray--;
|
||||||
|
depth--;
|
||||||
|
prefix.RemoveAt(prefix.Count - 1);
|
||||||
|
}
|
||||||
|
if (reader.TokenType == JsonTokenType.StartObject)
|
||||||
|
{
|
||||||
|
if (insideArray == 0)
|
||||||
|
{
|
||||||
|
depth++;
|
||||||
|
prefix.Add(lastObjecName);
|
||||||
|
if (rv.ProNames.Count > 0)
|
||||||
|
{
|
||||||
|
rv.ProNames.RemoveAt(rv.ProNames.Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (lastToken != JsonTokenType.StartArray)
|
||||||
|
{
|
||||||
|
reader.TrySkip();
|
||||||
|
reader.Read();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reader.TokenType == JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
var pname = reader.GetString();
|
||||||
|
lastObjecName = pname;
|
||||||
|
var p = prefix.Take(depth).ToSepratedString(seperator: ".");
|
||||||
|
if (string.IsNullOrEmpty(p) == false)
|
||||||
|
{
|
||||||
|
pname = p + "." + pname;
|
||||||
|
}
|
||||||
|
if (rv.ProNames.Contains(pname) == false)
|
||||||
|
{
|
||||||
|
rv.ProNames.Add(pname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
if (insideArray == 0)
|
||||||
|
{
|
||||||
|
depth--;
|
||||||
|
prefix.RemoveAt(prefix.Count - 1);
|
||||||
|
}
|
||||||
|
if (reader.IsFinalBlock == true && reader.CurrentDepth == 0)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastToken = reader.TokenType;
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, PostedBody value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PostedBody
|
||||||
|
{
|
||||||
|
public List<string> ProNames { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Unicode;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
public class BoolStringConverter :
|
||||||
|
JsonConverter<bool>
|
||||||
|
{
|
||||||
|
|
||||||
|
public override bool Read(
|
||||||
|
ref Utf8JsonReader reader,
|
||||||
|
Type typeToConvert,
|
||||||
|
JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
|
||||||
|
JsonTokenType token = reader.TokenType;
|
||||||
|
|
||||||
|
if (token == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
var s = reader.GetString() ?? "";
|
||||||
|
if (s.ToLower() == "true")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (s.ToLower() == "false")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (token == JsonTokenType.True || token == JsonTokenType.False)
|
||||||
|
{
|
||||||
|
return reader.GetBoolean();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(
|
||||||
|
Utf8JsonWriter writer,
|
||||||
|
bool data,
|
||||||
|
JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteBooleanValue(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using WalkingTec.Mvvm.Core;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
public class DateRangeConverter : JsonConverter<DateRange>
|
||||||
|
{
|
||||||
|
public override DateRange Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.Null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.StartArray)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
string[] ds = new string[2];
|
||||||
|
ds[0] = reader.GetString();
|
||||||
|
reader.Read();
|
||||||
|
ds[1] = reader.GetString();
|
||||||
|
reader.Read();
|
||||||
|
if (DateRange.TryParse(ds, out var dateRange))
|
||||||
|
{
|
||||||
|
return dateRange;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, DateRange value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//writer.WriteStringValue(JsonSerializer.Serialize(value),);
|
||||||
|
writer.WriteStartArray();
|
||||||
|
writer.WriteStringValue(value.GetStartTime().ToString());
|
||||||
|
writer.WriteStringValue(value.GetEndTime().ToString());
|
||||||
|
writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
|
||||||
|
public class DateTimeConverter : JsonConverter<DateTime>
|
||||||
|
{
|
||||||
|
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
if (DateTime.TryParse(reader.GetString(), out DateTime date))
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
return reader.GetDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
public class DynamicDataConverter : JsonConverter<DynamicData>
|
||||||
|
{
|
||||||
|
public override DynamicData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DynamicData rv = new DynamicData();
|
||||||
|
rv.Fields = new Dictionary<string, object>();
|
||||||
|
string currentkey = "";
|
||||||
|
//object currentvalue;
|
||||||
|
int level = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if(reader.TokenType == JsonTokenType.StartObject) {
|
||||||
|
if(level > 0)
|
||||||
|
{
|
||||||
|
var inner = JsonSerializer.Deserialize<DynamicData>(ref reader, options);
|
||||||
|
rv.Fields.Add(currentkey, inner);
|
||||||
|
}
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
if(reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
level--;
|
||||||
|
}
|
||||||
|
if (reader.TokenType == JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
currentkey = reader.GetString();
|
||||||
|
}
|
||||||
|
if(reader.TokenType == JsonTokenType.String || reader.TokenType == JsonTokenType.Number || reader.TokenType == JsonTokenType.True || reader.TokenType == JsonTokenType.False || reader.TokenType == JsonTokenType.Null)
|
||||||
|
{
|
||||||
|
var val = JsonSerializer.Deserialize<object>(ref reader,options);
|
||||||
|
rv.Fields.Add(currentkey, val);
|
||||||
|
}
|
||||||
|
if (reader.IsFinalBlock && level == 0)
|
||||||
|
{
|
||||||
|
//reader.Read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, DynamicData value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value == null || value.Fields == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
foreach (var item in value.Fields)
|
||||||
|
{
|
||||||
|
if(item.Value == null)
|
||||||
|
{
|
||||||
|
if (options.IgnoreNullValues == false)
|
||||||
|
{
|
||||||
|
writer.WriteNull(item.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WritePropertyName(item.Key);
|
||||||
|
JsonSerializer.Serialize(writer, item.Value, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
163
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/PocoConverter.cs
Normal file
163
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/PocoConverter.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Text.Unicode;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
public class PocoConverter : JsonConverterFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
public override bool CanConvert(Type typeToConvert)
|
||||||
|
{
|
||||||
|
return typeof(TopBasePoco).IsAssignableFrom(typeToConvert);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override JsonConverter CreateConverter(
|
||||||
|
Type type,
|
||||||
|
JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
|
||||||
|
var temp = CloneOptions(options);
|
||||||
|
foreach (var item in options.Converters)
|
||||||
|
{
|
||||||
|
if(item.GetType() != typeof(PocoConverter))
|
||||||
|
{
|
||||||
|
temp.Converters.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
|
||||||
|
typeof(PocoConverterInner<>).MakeGenericType(
|
||||||
|
new Type[] { type }),
|
||||||
|
BindingFlags.Instance | BindingFlags.Public,
|
||||||
|
binder: null,
|
||||||
|
args: new object[] { temp },
|
||||||
|
culture: null);
|
||||||
|
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonSerializerOptions CloneOptions(JsonSerializerOptions op)
|
||||||
|
{
|
||||||
|
JsonSerializerOptions rv = new JsonSerializerOptions();
|
||||||
|
rv.PropertyNamingPolicy = op.PropertyNamingPolicy;
|
||||||
|
rv.AllowTrailingCommas = op.AllowTrailingCommas;
|
||||||
|
rv.DefaultBufferSize = op.DefaultBufferSize;
|
||||||
|
rv.DefaultIgnoreCondition = op.DefaultIgnoreCondition;
|
||||||
|
rv.DictionaryKeyPolicy = op.DictionaryKeyPolicy;
|
||||||
|
rv.Encoder = op.Encoder;
|
||||||
|
rv.IgnoreNullValues = op.IgnoreNullValues;
|
||||||
|
rv.IgnoreReadOnlyFields = op.IgnoreReadOnlyFields;
|
||||||
|
rv.IgnoreReadOnlyProperties = op.IgnoreReadOnlyProperties;
|
||||||
|
rv.IncludeFields = op.IncludeFields;
|
||||||
|
rv.DefaultIgnoreCondition = op.DefaultIgnoreCondition;
|
||||||
|
rv.DictionaryKeyPolicy = op.DictionaryKeyPolicy;
|
||||||
|
rv.MaxDepth = op.MaxDepth;
|
||||||
|
rv.NumberHandling = op.NumberHandling;
|
||||||
|
rv.ReadCommentHandling = op.ReadCommentHandling;
|
||||||
|
rv.ReferenceHandler = op.ReferenceHandler;
|
||||||
|
rv.WriteIndented = op.WriteIndented;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PocoConverterInner<T> :
|
||||||
|
JsonConverter<T> where T : TopBasePoco
|
||||||
|
{
|
||||||
|
protected readonly JsonSerializerOptions _options;
|
||||||
|
public PocoConverterInner(JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override T Read(
|
||||||
|
ref Utf8JsonReader reader,
|
||||||
|
Type typeToConvert,
|
||||||
|
JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
|
||||||
|
return JsonSerializer.Deserialize<T>(ref reader, _options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(
|
||||||
|
Utf8JsonWriter writer,
|
||||||
|
T data,
|
||||||
|
JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var _datacache = new Dictionary<string, int>();
|
||||||
|
RemoveCycleReference(data, _datacache);
|
||||||
|
JsonSerializer.Serialize(writer, data, typeof(T), _options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveCycleReference(object Entity, Dictionary<string, int> datacache)
|
||||||
|
{
|
||||||
|
var pros = Entity.GetType().GetAllProperties();
|
||||||
|
var mainkey = Entity.GetType().FullName + (Entity as TopBasePoco).GetID();
|
||||||
|
datacache.TryAdd(mainkey, 1);
|
||||||
|
|
||||||
|
foreach (var pro in pros)
|
||||||
|
{
|
||||||
|
if (typeof(TopBasePoco).IsAssignableFrom(pro.PropertyType))
|
||||||
|
{
|
||||||
|
var subentity = pro.GetValue(Entity) as TopBasePoco;
|
||||||
|
string key = pro.PropertyType.FullName + subentity?.GetID() ?? "";
|
||||||
|
if (subentity != null && datacache.ContainsKey(key) == false)
|
||||||
|
{
|
||||||
|
RemoveCycleReference(subentity, datacache);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pro.SetValue(Entity,null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//找到类型为List<xxx>的字段
|
||||||
|
if (pro.PropertyType.GenericTypeArguments.Count() > 0)
|
||||||
|
{
|
||||||
|
//获取xxx的类型
|
||||||
|
var ftype = pro.PropertyType.GenericTypeArguments.First();
|
||||||
|
//如果xxx继承自TopBasePoco
|
||||||
|
if (ftype.IsSubclassOf(typeof(TopBasePoco)))
|
||||||
|
{
|
||||||
|
//界面传过来的子表数据
|
||||||
|
|
||||||
|
if (pro.GetValue(Entity) is IEnumerable<TopBasePoco> list && list.Count() > 0)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
foreach (var newitem in list)
|
||||||
|
{
|
||||||
|
if (newitem != null)
|
||||||
|
{
|
||||||
|
string subkey = ftype.FullName + newitem?.GetID() ?? "";
|
||||||
|
if (datacache.ContainsKey(subkey) == false)
|
||||||
|
{
|
||||||
|
RemoveCycleReference(newitem, datacache.ToDictionary(x=>x.Key,x=>x.Value));
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found == false)
|
||||||
|
{
|
||||||
|
pro.SetValue(Entity, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Unicode;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
public class RawStringConverter : JsonConverter<string>
|
||||||
|
{
|
||||||
|
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.Null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
string rv = reader.GetString();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var txt = JsonEncodedText.Encode($"_raw_{value}_raw_", JavaScriptEncoder.UnsafeRelaxedJsonEscaping);
|
||||||
|
writer.WriteStringValue(txt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/StringConverter.cs
Normal file
40
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/StringConverter.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace System.Text.Json.Serialization
|
||||||
|
{
|
||||||
|
public class JsonStringConverter : JsonConverter<string>
|
||||||
|
{
|
||||||
|
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.Null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
return reader.GetString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace System.Text.Json.Serialization
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// StringIgnoreLTGTConvert
|
||||||
|
/// 忽略客户端提交的 <及>字符
|
||||||
|
/// </summary>
|
||||||
|
public class StringIgnoreLTGTConverter : JsonConverter<string>
|
||||||
|
{
|
||||||
|
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.Null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
return reader.GetString().Replace("<", string.Empty).Replace(">", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/TypeConverter.cs
Normal file
25
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Json/TypeConverter.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Unicode;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using WalkingTec.Mvvm.Core.Extensions;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core.Json
|
||||||
|
{
|
||||||
|
public class TypeConverter : JsonConverter<Type>
|
||||||
|
{
|
||||||
|
public override Type Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteNullValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/JsonResultModel.cs
Normal file
38
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/JsonResultModel.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DataTableResult
|
||||||
|
/// </summary>
|
||||||
|
public class DataTableResult<T> : JsonResultT<IEnumerable<T>>
|
||||||
|
where T : TopBasePoco
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Data Count
|
||||||
|
/// </summary>
|
||||||
|
public long Count { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// JsonResultT
|
||||||
|
/// </summary>
|
||||||
|
public class JsonResultT<T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Status Code
|
||||||
|
/// <see cref="Microsoft.AspNetCore.Http.StatusCodes">
|
||||||
|
/// </summary>
|
||||||
|
public int Code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message
|
||||||
|
/// </summary>
|
||||||
|
public string Msg { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data
|
||||||
|
/// </summary>
|
||||||
|
public T Data { get; set; }
|
||||||
|
}
|
||||||
|
}
|
143
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/LoginUserInfo.cs
Normal file
143
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/LoginUserInfo.cs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using WalkingTec.Mvvm.Core.Support.Json;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户登录信息,需要保存在Session中,所以使用Serializable标记
|
||||||
|
/// </summary>
|
||||||
|
public class LoginUserInfo
|
||||||
|
{
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登录用户
|
||||||
|
/// </summary>
|
||||||
|
public string ITCode { get; set; }
|
||||||
|
|
||||||
|
public string TenantCode { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Memo { get; set; }
|
||||||
|
|
||||||
|
public Guid? PhotoId { get; set; }
|
||||||
|
|
||||||
|
public List<SimpleRole> Roles { get; set; }
|
||||||
|
|
||||||
|
public List<SimpleGroup> Groups { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, object> Attributes { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 用户的页面权限列表
|
||||||
|
/// </summary>
|
||||||
|
public List<SimpleFunctionPri> FunctionPrivileges { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 用户的数据权限列表
|
||||||
|
/// </summary>
|
||||||
|
public List<SimpleDataPri> DataPrivileges { get; set; }
|
||||||
|
|
||||||
|
public async System.Threading.Tasks.Task LoadBasicInfoAsync(WTMContext context)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(this.ITCode) || context?.DC == null || context.BaseUserQuery == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var DC = context.DC;
|
||||||
|
var userInfo = await context.BaseUserQuery
|
||||||
|
.Where(x => x.ITCode.ToLower() == this.ITCode.ToLower() && x.IsValid)
|
||||||
|
.Select(x => new {
|
||||||
|
user = x,
|
||||||
|
UserRoles = DC.Set<FrameworkUserRole>().Where(y => y.UserCode == x.ITCode).ToList(),
|
||||||
|
UserGroups = DC.Set<FrameworkUserGroup>().Where(y => y.UserCode == x.ITCode).ToList(),
|
||||||
|
})
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (userInfo != null)
|
||||||
|
{
|
||||||
|
// 初始化用户信息
|
||||||
|
var roleIDs = userInfo.UserRoles.Select(x => x.RoleCode).ToList();
|
||||||
|
var groupIDs = userInfo.UserGroups.Select(x => x.GroupCode).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
var dataPris = await DC.Set<DataPrivilege>().AsNoTracking()
|
||||||
|
.Where(x => x.UserCode == userInfo.user.ITCode || (x.GroupCode != null && groupIDs.Contains(x.GroupCode)))
|
||||||
|
.Distinct()
|
||||||
|
.ToListAsync();
|
||||||
|
ProcessTreeDp(dataPris,context);
|
||||||
|
|
||||||
|
//查找登录用户的页面权限
|
||||||
|
var funcPrivileges = await DC.Set<FunctionPrivilege>().AsNoTracking()
|
||||||
|
.Where(x => x.RoleCode != null && roleIDs.Contains(x.RoleCode))
|
||||||
|
.Distinct()
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var roles = DC.Set<FrameworkRole>().AsNoTracking().Where(x => roleIDs.Contains(x.RoleCode)).ToList();
|
||||||
|
var groups = DC.Set<FrameworkGroup>().AsNoTracking().Where(x => groupIDs.Contains(x.GroupCode)).ToList();
|
||||||
|
this.ITCode = userInfo.user.ITCode;
|
||||||
|
if (string.IsNullOrEmpty(this.Name))
|
||||||
|
{
|
||||||
|
this.Name = userInfo.user.Name;
|
||||||
|
}
|
||||||
|
if (this.PhotoId == null)
|
||||||
|
{
|
||||||
|
this.PhotoId = userInfo.user.PhotoId;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(this.TenantCode))
|
||||||
|
{
|
||||||
|
this.TenantCode = userInfo.user.TenantCode;
|
||||||
|
}
|
||||||
|
this.Roles = roles.Select(x => new SimpleRole { ID = x.ID, RoleCode = x.RoleCode, RoleName = x.RoleName }).ToList();
|
||||||
|
this.Groups = groups.Select(x => new SimpleGroup { ID = x.ID, GroupCode = x.GroupCode, GroupName = x.GroupName }).ToList();
|
||||||
|
this.DataPrivileges = dataPris.Select(x => new SimpleDataPri { ID = x.ID, RelateId = x.RelateId, TableName = x.TableName, UserCode = x.UserCode, GroupCode = x.GroupCode }).ToList();
|
||||||
|
this.FunctionPrivileges = funcPrivileges.Select(x => new SimpleFunctionPri { ID = x.ID, RoleCode = x.RoleCode, Allowed = x.Allowed, MenuItemId = x.MenuItemId }).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessTreeDp(List<DataPrivilege> dps, WTMContext context)
|
||||||
|
{
|
||||||
|
var dpsSetting = context.DataPrivilegeSettings;
|
||||||
|
foreach (var dp in dpsSetting)
|
||||||
|
{
|
||||||
|
if (typeof(TreePoco).IsAssignableFrom(dp.ModelType))
|
||||||
|
{
|
||||||
|
var ids = dps.Where(x => x.TableName == dp.ModelName).Select(x => x.RelateId).ToList();
|
||||||
|
if (ids.Count > 0 && ids.Contains(null) == false)
|
||||||
|
{
|
||||||
|
var skipids = dp.GetTreeParentIds(context, dps);
|
||||||
|
List<string> subids = new List<string>();
|
||||||
|
subids.AddRange(GetSubIds(dp, ids, dp.ModelType, skipids,context));
|
||||||
|
subids = subids.Distinct().ToList();
|
||||||
|
subids.ForEach(x => dps.Add(new DataPrivilege
|
||||||
|
{
|
||||||
|
TableName = dp.ModelName,
|
||||||
|
RelateId = x.ToString()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private IEnumerable<string> GetSubIds(IDataPrivilege dp, List<string> p_id, Type modelType, List<string> skipids,WTMContext context)
|
||||||
|
{
|
||||||
|
var ids = p_id.Where(x => skipids.Contains(x) == false).ToList();
|
||||||
|
var subids = dp.GetTreeSubIds(context, ids);
|
||||||
|
if (subids.Count > 0)
|
||||||
|
{
|
||||||
|
return subids.Concat(GetSubIds(dp, subids, modelType, skipids,context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
104
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/MSD.cs
Normal file
104
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/MSD.cs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 模型状态接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IModelStateService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 索引
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<MsdError> this[string name] { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 添加模型错误
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">字段名称</param>
|
||||||
|
/// <param name="errorMessage">错误信息</param>
|
||||||
|
void AddModelError(string key, string errorMessage);
|
||||||
|
void RemoveModelError(string key);
|
||||||
|
int Count { get; }
|
||||||
|
|
||||||
|
IEnumerable<string> Keys { get; }
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
string GetFirstError();
|
||||||
|
|
||||||
|
bool IsValid { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录错误的简单类
|
||||||
|
/// </summary>
|
||||||
|
public class MsdError
|
||||||
|
{
|
||||||
|
public string ErrorMessage { get; set; }
|
||||||
|
public Exception Exception { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class BasicMSD : IModelStateService
|
||||||
|
{
|
||||||
|
private Dictionary<string, string> _states;
|
||||||
|
|
||||||
|
public BasicMSD()
|
||||||
|
{
|
||||||
|
this._states = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MsdError> this[string name]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _states.Where(x => x.Key == name).Select(x => new MsdError { ErrorMessage = x.Value }).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加错误信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">错误的字段名</param>
|
||||||
|
/// <param name="errorMessage">错误信息</param>
|
||||||
|
public void AddModelError(string key, string errorMessage)
|
||||||
|
{
|
||||||
|
_states.Add(key, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveModelError(string key)
|
||||||
|
{
|
||||||
|
_states.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_states.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFirstError()
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
foreach (var key in Keys)
|
||||||
|
{
|
||||||
|
if (this[key].Count > 0)
|
||||||
|
{
|
||||||
|
rv = this[key].First().ErrorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count => _states.Count;
|
||||||
|
|
||||||
|
public IEnumerable<string> Keys => _states.Keys;
|
||||||
|
|
||||||
|
bool IModelStateService.IsValid => _states.Count > 0 ? false : true;
|
||||||
|
}
|
||||||
|
}
|
77
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/ActionLog.cs
Normal file
77
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/ActionLog.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
public enum ActionLogTypesEnum
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.Normal")]
|
||||||
|
Normal,
|
||||||
|
[Display(Name = "_Admin.Exception")]
|
||||||
|
Exception,
|
||||||
|
[Display(Name = "_Admin.Debug")]
|
||||||
|
Debug
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ActionLog
|
||||||
|
/// </summary>
|
||||||
|
[Table("ActionLogs")]
|
||||||
|
public class ActionLog : BasePoco, ICloneable
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.Module")]
|
||||||
|
[StringLength(255, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string ModuleName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Action")]
|
||||||
|
[StringLength(255, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string ActionName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Account")]
|
||||||
|
[StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string ITCode { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "Url")]
|
||||||
|
[StringLength(250, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string ActionUrl { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.ActionTime")]
|
||||||
|
public DateTime ActionTime { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Duration")]
|
||||||
|
public double Duration { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Remark")]
|
||||||
|
public string Remark { get; set; }
|
||||||
|
|
||||||
|
[StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
[Display(Name = "IP")]
|
||||||
|
public string IP { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.LogType")]
|
||||||
|
public ActionLogTypesEnum LogType { get; set; }
|
||||||
|
|
||||||
|
public object Clone()
|
||||||
|
{
|
||||||
|
return this.MemberwiseClone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetLogString()
|
||||||
|
{
|
||||||
|
return $@"
|
||||||
|
|-{Core.CoreProgram._localizer?["_Admin.ActionTime"]}:{this.ActionTime}
|
||||||
|
|-{Core.CoreProgram._localizer?["_Admin.Account"]}:{this.ITCode??""}
|
||||||
|
|-IP:{this.IP??""}
|
||||||
|
|-{Core.CoreProgram._localizer?["_Admin.Module"]}:{this.ModuleName??""}
|
||||||
|
|-{Core.CoreProgram._localizer?["_Admin.MethodName"]}:{this.ActionName ?? ""}
|
||||||
|
|-Url:{this.ActionUrl ?? ""}
|
||||||
|
|-{Core.CoreProgram._localizer?["_Admin.Duration"]}:{this.Duration.ToString("F2")+" s"}
|
||||||
|
|-{Core.CoreProgram._localizer?["_Admin.Remark"]}:{this.Remark}
|
||||||
|
";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
44
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/BasePoco.cs
Normal file
44
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/BasePoco.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
|
||||||
|
public interface IBasePoco
|
||||||
|
{
|
||||||
|
DateTime? CreateTime { get; set; }
|
||||||
|
string CreateBy { get; set; }
|
||||||
|
DateTime? UpdateTime { get; set; }
|
||||||
|
string UpdateBy { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Model层的基类,所有的model都应该继承这个类。这会使所有的model层对应的数据库表都有一个自增主键
|
||||||
|
/// </summary>
|
||||||
|
public class BasePoco : TopBasePoco, IBasePoco
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CreateTime
|
||||||
|
/// </summary>
|
||||||
|
[Display(Name = "_Admin.CreateTime")]
|
||||||
|
public DateTime? CreateTime { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// CreateBy
|
||||||
|
/// </summary>
|
||||||
|
[Display(Name = "_Admin.CreateBy")]
|
||||||
|
[StringLength(50,ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string CreateBy { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// UpdateTime
|
||||||
|
/// </summary>
|
||||||
|
[Display(Name = "_Admin.UpdateTime")]
|
||||||
|
public DateTime? UpdateTime { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// UpdateBy
|
||||||
|
/// </summary>
|
||||||
|
[Display(Name = "_Admin.UpdateBy")]
|
||||||
|
[StringLength(50,ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string UpdateBy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
30
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/DataPrivilege.cs
Normal file
30
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/DataPrivilege.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DataPrivilege
|
||||||
|
/// </summary>
|
||||||
|
[Table("DataPrivileges")]
|
||||||
|
public class DataPrivilege : BasePoco
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.User")]
|
||||||
|
public string UserCode { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Group")]
|
||||||
|
public string GroupCode { get; set; }
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
[StringLength(50,ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
[Display(Name = "_Admin.TableName")]
|
||||||
|
public string TableName { get; set; }
|
||||||
|
public string RelateId { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Domain")]
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using WalkingTec.Mvvm.Core.Models;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// FileAttachment
|
||||||
|
/// </summary>
|
||||||
|
[Table("FileAttachments")]
|
||||||
|
public class FileAttachment : TopBasePoco, IWtmFile, IDisposable
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.FileName")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.FileExt")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
[StringLength(10)]
|
||||||
|
public string FileExt { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Path")]
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Length")]
|
||||||
|
public long Length { get; set; }
|
||||||
|
|
||||||
|
public DateTime UploadTime { get; set; }
|
||||||
|
|
||||||
|
public string SaveMode { get; set; }
|
||||||
|
|
||||||
|
public byte[] FileData { get; set; }
|
||||||
|
|
||||||
|
public string ExtraInfo { get; set; }
|
||||||
|
public string HandlerInfo { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
[JsonIgnore]
|
||||||
|
public Stream DataStream { get; set; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if(DataStream != null)
|
||||||
|
{
|
||||||
|
DataStream.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string IWtmFile.GetID()
|
||||||
|
{
|
||||||
|
return ID.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
|
||||||
|
[Table("FrameworkGroups")]
|
||||||
|
public class FrameworkGroup : BasePoco
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.GroupCode")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
[RegularExpression("^[0-9]*$", ErrorMessage = "Validate.{0}number")]
|
||||||
|
[StringLength(100, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string GroupCode { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.GroupName")]
|
||||||
|
[StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public string GroupName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Remark")]
|
||||||
|
public string GroupRemark { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
[Display(Name = "_Admin.UsersCount")]
|
||||||
|
public int UsersCount { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Tenant")]
|
||||||
|
public string TenantCode { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
80
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/FrameworkMenu.cs
Normal file
80
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/FrameworkMenu.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// FrameworkMenu
|
||||||
|
/// </summary>
|
||||||
|
[Table("FrameworkMenus")]
|
||||||
|
public class FrameworkMenu : TreePoco<FrameworkMenu>
|
||||||
|
{
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.PageName")]
|
||||||
|
[StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public string PageName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.ActionName")]
|
||||||
|
public string ActionName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "Codegen.ModuleName")]
|
||||||
|
public string ModuleName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.FolderOnly")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public bool FolderOnly { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.IsInherit")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public bool IsInherit { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Privileges")]
|
||||||
|
public List<FunctionPrivilege> Privileges { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ClassName
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public string ClassName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MethodName
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public string MethodName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Domain")]
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.ShowOnMenu")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public bool ShowOnMenu { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.IsPublic")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public bool IsPublic { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.DisplayOrder")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public int? DisplayOrder { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.IsInside")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public bool? IsInside { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Url
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Icon")]
|
||||||
|
[StringLength(50)]
|
||||||
|
public string Icon { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
39
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/FrameworkRole.cs
Normal file
39
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/FrameworkRole.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// FrameworkRole
|
||||||
|
/// </summary>
|
||||||
|
[Table("FrameworkRoles")]
|
||||||
|
public class FrameworkRole : BasePoco
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.RoleCode")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
[RegularExpression("^[0-9]*$", ErrorMessage = "Validate.{0}number")]
|
||||||
|
[StringLength(100, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string RoleCode { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.RoleName")]
|
||||||
|
[StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public string RoleName { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Remark")]
|
||||||
|
public string RoleRemark { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Tenant")]
|
||||||
|
public string TenantCode { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
[Display(Name = "_Admin.UsersCount")]
|
||||||
|
public int UsersCount { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
48
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/FrameworkUser.cs
Normal file
48
WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Models/FrameworkUser.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using WalkingTec.Mvvm.Core.Support.Json;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// FrameworkUser
|
||||||
|
/// </summary>
|
||||||
|
[Table("FrameworkUsers")]
|
||||||
|
public class FrameworkUserBase : BasePoco
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.Account")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
[StringLength(50,ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string ITCode { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Password")]
|
||||||
|
[Required(AllowEmptyStrings = false, ErrorMessage = "Validate.{0}required")]
|
||||||
|
[StringLength(32, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Name")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
[StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.IsValid")]
|
||||||
|
public bool IsValid { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Photo")]
|
||||||
|
public Guid? PhotoId { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Photo")]
|
||||||
|
[JsonIgnore]
|
||||||
|
public FileAttachment Photo { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Tenant")]
|
||||||
|
public string TenantCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using WalkingTec.Mvvm.Core.Attributes;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
[Table("FrameworkUserGroups")]
|
||||||
|
public class FrameworkUserGroup : BasePoco
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string UserCode { get; set; }
|
||||||
|
[Display(Name = "_Admin.Group")]
|
||||||
|
[Required]
|
||||||
|
public string GroupCode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using WalkingTec.Mvvm.Core.Attributes;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
[Table("FrameworkUserRoles")]
|
||||||
|
public class FrameworkUserRole : BasePoco
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string UserCode { get; set; }
|
||||||
|
[Required]
|
||||||
|
[Display(Name = "_Admin.Role")]
|
||||||
|
public string RoleCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace WalkingTec.Mvvm.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// FunctionPrivilege
|
||||||
|
/// </summary>
|
||||||
|
[Table("FunctionPrivileges")]
|
||||||
|
public class FunctionPrivilege : BasePoco
|
||||||
|
{
|
||||||
|
[Display(Name = "_Admin.Role")]
|
||||||
|
public string RoleCode { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.MenuItem")]
|
||||||
|
public Guid MenuItemId { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.MenuItem")]
|
||||||
|
public FrameworkMenu MenuItem { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "_Admin.Allowed")]
|
||||||
|
[Required(ErrorMessage = "Validate.{0}required")]
|
||||||
|
public bool? Allowed { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user