Compare commits
	
		
			47 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f11b7f7ab4 | ||
| 
						 | 
					9bb9cd7419 | ||
| 
						 | 
					ba008ef8ba | ||
| 
						 | 
					28b533decf | ||
| 
						 | 
					9ee638c2f1 | ||
| 
						 | 
					d90fdbaf35 | ||
| 
						 | 
					b55e3db736 | ||
| 
						 | 
					dbee8496cb | ||
| 
						 | 
					044e78bea9 | ||
| 
						 | 
					fe79128d90 | ||
| 
						 | 
					34120da008 | ||
| 
						 | 
					4c62bb0b21 | ||
| 
						 | 
					46b16279c7 | ||
| 
						 | 
					0779efc5dd | ||
| 
						 | 
					8acdb780e8 | ||
| 
						 | 
					2e310b919e | ||
| 
						 | 
					4155c07269 | ||
| 
						 | 
					32fa833736 | ||
| 
						 | 
					2258f08555 | ||
| 
						 | 
					d90b32f165 | ||
| 
						 | 
					1492377322 | ||
| 
						 | 
					32eefbf545 | ||
| 
						 | 
					a825ca5f6f | ||
| 
						 | 
					e270b0c4f6 | ||
| 
						 | 
					6ae44ccf58 | ||
| 
						 | 
					1aa0df6339 | ||
| 
						 | 
					62c3693dbe | ||
| 
						 | 
					e4e503c97b | ||
| 
						 | 
					5ec1ee7627 | ||
| 
						 | 
					79789388fc | ||
| 
						 | 
					2c4194ee18 | ||
| 
						 | 
					1b2be585af | ||
| 
						 | 
					83736647e7 | ||
| 
						 | 
					b06405717d | ||
| 
						 | 
					298a1f2ed4 | ||
| 
						 | 
					74a47a1983 | ||
| 
						 | 
					a48a42abe4 | ||
| 
						 | 
					feb1d0a3c5 | ||
| 
						 | 
					92bca824e6 | ||
| 
						 | 
					025c699517 | ||
| 
						 | 
					53f8fbe4b1 | ||
| 
						 | 
					77bfabc41d | ||
| 
						 | 
					6427ee6ee0 | ||
| 
						 | 
					4c95997d62 | ||
| 
						 | 
					1d82cea40d | ||
| 
						 | 
					e78799424c | ||
| 
						 | 
					1000c8d38f | 
@@ -17,8 +17,7 @@
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<None Include="$(OutputPath)\$(TargetFileName)" Pack="true"
 | 
			
		||||
			  PackagePath="analyzers/dotnet/cs" Visible="false" />
 | 
			
		||||
		<None Include="$(OutputPath)\$(TargetFileName)" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
@@ -27,6 +26,6 @@
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
 | 
			
		||||
		<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" Private="false" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,63 +1,48 @@
 | 
			
		||||
using Microsoft.CodeAnalysis;
 | 
			
		||||
using Microsoft.CodeAnalysis.CSharp;
 | 
			
		||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
 | 
			
		||||
using Microsoft.CodeAnalysis.Text;
 | 
			
		||||
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.AspNetCore.Components;
 | 
			
		||||
 | 
			
		||||
[Generator]
 | 
			
		||||
public partial class SetParametersAsyncGenerator : ISourceGenerator
 | 
			
		||||
public sealed partial class SetParametersAsyncGenerator : IIncrementalGenerator
 | 
			
		||||
{
 | 
			
		||||
    private const string m_DoNotGenerateSetParametersAsyncAttribute = """ 
 | 
			
		||||
    using System;
 | 
			
		||||
    namespace Microsoft.AspNetCore.Components
 | 
			
		||||
    {
 | 
			
		||||
        [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
 | 
			
		||||
        internal sealed class DoNotGenerateSetParametersAsyncAttribute : Attribute { }
 | 
			
		||||
    }
 | 
			
		||||
""";
 | 
			
		||||
 | 
			
		||||
    private string m_DoNotGenerateSetParametersAsyncAttribute = """
 | 
			
		||||
        
 | 
			
		||||
        using System;
 | 
			
		||||
        namespace Microsoft.AspNetCore.Components
 | 
			
		||||
    private const string m_GenerateSetParametersAsyncAttribute = """ 
 | 
			
		||||
    using System;
 | 
			
		||||
    namespace Microsoft.AspNetCore.Components
 | 
			
		||||
    {
 | 
			
		||||
        [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
 | 
			
		||||
        internal sealed class GenerateSetParametersAsyncAttribute : Attribute
 | 
			
		||||
        {
 | 
			
		||||
            [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
 | 
			
		||||
            internal sealed class DoNotGenerateSetParametersAsyncAttribute : Attribute
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
            public bool RequireExactMatch { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
""";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        ;
 | 
			
		||||
    private string m_GenerateSetParametersAsyncAttribute = """
 | 
			
		||||
        
 | 
			
		||||
        using System;
 | 
			
		||||
        namespace Microsoft.AspNetCore.Components
 | 
			
		||||
    private const string m_GlobalGenerateSetParametersAsyncAttribute = """ 
 | 
			
		||||
    using System;
 | 
			
		||||
    namespace Microsoft.AspNetCore.Components
 | 
			
		||||
    {
 | 
			
		||||
        [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
 | 
			
		||||
        internal sealed class GlobalGenerateSetParametersAsyncAttribute : Attribute
 | 
			
		||||
        {
 | 
			
		||||
            [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
 | 
			
		||||
            internal sealed class GenerateSetParametersAsyncAttribute : Attribute
 | 
			
		||||
            {
 | 
			
		||||
                public bool RequireExactMatch { get; set; }
 | 
			
		||||
            }
 | 
			
		||||
            public bool Enable { get; }
 | 
			
		||||
            public GlobalGenerateSetParametersAsyncAttribute(bool enable = true) { Enable = enable; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        ;
 | 
			
		||||
    private string m_GlobalGenerateSetParametersAsyncAttribute = """
 | 
			
		||||
        
 | 
			
		||||
        using System;
 | 
			
		||||
        namespace Microsoft.AspNetCore.Components
 | 
			
		||||
        {
 | 
			
		||||
            [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
 | 
			
		||||
            internal sealed class GlobalGenerateSetParametersAsyncAttribute : Attribute
 | 
			
		||||
            {
 | 
			
		||||
                public bool Enable { get; }
 | 
			
		||||
 | 
			
		||||
                public GlobalGenerateSetParametersAsyncAttribute(bool enable = true)
 | 
			
		||||
                {
 | 
			
		||||
                    Enable = enable;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
""";
 | 
			
		||||
 | 
			
		||||
    private static readonly DiagnosticDescriptor ParameterNameConflict = new DiagnosticDescriptor(
 | 
			
		||||
        id: "TG0001",
 | 
			
		||||
@@ -68,36 +53,64 @@ public partial class SetParametersAsyncGenerator : ISourceGenerator
 | 
			
		||||
        isEnabledByDefault: true,
 | 
			
		||||
        description: "Parameter names must be case insensitive to be usable in routes. Rename the parameter to not be in conflict with other parameters.");
 | 
			
		||||
 | 
			
		||||
    public void Initialize(GeneratorInitializationContext context)
 | 
			
		||||
    public void Initialize(IncrementalGeneratorInitializationContext context)
 | 
			
		||||
    {
 | 
			
		||||
        context.RegisterForPostInitialization(a =>
 | 
			
		||||
        // 注入 attribute 源码
 | 
			
		||||
        context.RegisterPostInitializationOutput(ctx =>
 | 
			
		||||
        {
 | 
			
		||||
            a.AddSource(nameof(m_DoNotGenerateSetParametersAsyncAttribute), m_DoNotGenerateSetParametersAsyncAttribute);
 | 
			
		||||
            a.AddSource(nameof(m_GenerateSetParametersAsyncAttribute), m_GenerateSetParametersAsyncAttribute);
 | 
			
		||||
            a.AddSource(nameof(m_GlobalGenerateSetParametersAsyncAttribute), m_GlobalGenerateSetParametersAsyncAttribute);
 | 
			
		||||
            ctx.AddSource("DoNotGenerateSetParametersAsyncAttribute.g.cs", SourceText.From(m_DoNotGenerateSetParametersAsyncAttribute, Encoding.UTF8));
 | 
			
		||||
            ctx.AddSource("GenerateSetParametersAsyncAttribute.g.cs", SourceText.From(m_GenerateSetParametersAsyncAttribute, Encoding.UTF8));
 | 
			
		||||
            ctx.AddSource("GlobalGenerateSetParametersAsyncAttribute.g.cs", SourceText.From(m_GlobalGenerateSetParametersAsyncAttribute, Encoding.UTF8));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Register a syntax receiver that will be created for each generation pass
 | 
			
		||||
        context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
 | 
			
		||||
        // 筛选 ClassDeclarationSyntax
 | 
			
		||||
        var classDeclarations = context.SyntaxProvider
 | 
			
		||||
            .CreateSyntaxProvider(
 | 
			
		||||
                predicate: static (node, _) => node is ClassDeclarationSyntax,
 | 
			
		||||
                transform: static (ctx, _) => (ClassDeclarationSyntax)ctx.Node)
 | 
			
		||||
            .Where(static c => c is not null);
 | 
			
		||||
 | 
			
		||||
        // 合并 Compilation
 | 
			
		||||
        var compilationProvider = context.CompilationProvider;
 | 
			
		||||
 | 
			
		||||
        var candidateClasses = classDeclarations.Combine(compilationProvider);
 | 
			
		||||
 | 
			
		||||
        context.RegisterSourceOutput(candidateClasses, static (spc, tuple) =>
 | 
			
		||||
        {
 | 
			
		||||
            var (classDeclaration, compilation) = tuple;
 | 
			
		||||
            Execute(spc, compilation, classDeclaration);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void Execute(GeneratorExecutionContext context)
 | 
			
		||||
    private static void Execute(SourceProductionContext context, Compilation compilation, ClassDeclarationSyntax classDeclaration)
 | 
			
		||||
    {
 | 
			
		||||
        // https://github.com/dotnet/AspNetCore.Docs/blob/1e199f340780f407a685695e6c4d953f173fa891/aspnetcore/blazor/webassembly-performance-best-practices.md#implement-setparametersasync-manually
 | 
			
		||||
        if (context.SyntaxReceiver is not SyntaxReceiver receiver)
 | 
			
		||||
        {
 | 
			
		||||
        var model = compilation.GetSemanticModel(classDeclaration.SyntaxTree);
 | 
			
		||||
        var classSymbol = model.GetDeclaredSymbol(classDeclaration);
 | 
			
		||||
        if (classSymbol is null || classSymbol.Name == "_Imports")
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var candidate_classes = GetCandidateClasses(receiver, context);
 | 
			
		||||
        var positiveAttr = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.GenerateSetParametersAsyncAttribute");
 | 
			
		||||
        var negativeAttr = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.DoNotGenerateSetParametersAsyncAttribute");
 | 
			
		||||
 | 
			
		||||
        foreach (var class_symbol in candidate_classes.Distinct(SymbolEqualityComparer.Default).Cast<INamedTypeSymbol>())
 | 
			
		||||
        {
 | 
			
		||||
            GenerateSetParametersAsyncMethod(context, class_symbol);
 | 
			
		||||
        }
 | 
			
		||||
        if (classSymbol.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, negativeAttr)))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!IsPartial(classSymbol) || !IsComponent(classDeclaration, classSymbol, compilation))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        var globalEnable = compilation.Assembly.GetAttributes()
 | 
			
		||||
            .FirstOrDefault(a => a.AttributeClass?.ToDisplayString() == "Microsoft.AspNetCore.Components.GlobalGenerateSetParametersAsyncAttribute")
 | 
			
		||||
            ?.ConstructorArguments.FirstOrDefault().Value as bool? ?? false;
 | 
			
		||||
 | 
			
		||||
        var hasPositive = classSymbol.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, positiveAttr));
 | 
			
		||||
 | 
			
		||||
        if (!globalEnable && !hasPositive)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        GenerateSetParametersAsyncMethod(context, classSymbol);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void GenerateSetParametersAsyncMethod(GeneratorExecutionContext context, INamedTypeSymbol class_symbol)
 | 
			
		||||
    private static void GenerateSetParametersAsyncMethod(SourceProductionContext context, INamedTypeSymbol class_symbol)
 | 
			
		||||
    {
 | 
			
		||||
        var force_exact_match = class_symbol.GetAttributes().Any(a => a.NamedArguments.Any(na => na.Key == "RequireExactMatch" && na.Value.Value is bool v && v));
 | 
			
		||||
        var namespaceName = class_symbol.ContainingNamespace.ToDisplayString();
 | 
			
		||||
@@ -386,6 +399,31 @@ namespace {namespaceName}
 | 
			
		||||
#pragma warning restore CS0162");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static bool IsPartial(INamedTypeSymbol symbol)
 | 
			
		||||
    {
 | 
			
		||||
        return symbol.DeclaringSyntaxReferences
 | 
			
		||||
            .Select(r => r.GetSyntax())
 | 
			
		||||
            .OfType<ClassDeclarationSyntax>()
 | 
			
		||||
            .Any(c => c.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static bool IsComponent(ClassDeclarationSyntax classDeclaration, INamedTypeSymbol symbol, Compilation compilation)
 | 
			
		||||
    {
 | 
			
		||||
        if (HasUserDefinedSetParametersAsync(symbol))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (classDeclaration.SyntaxTree.FilePath.EndsWith(".razor") || classDeclaration.SyntaxTree.FilePath.EndsWith(".razor.cs"))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        var iComponent = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.IComponent");
 | 
			
		||||
        var componentBase = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.ComponentBase");
 | 
			
		||||
 | 
			
		||||
        if (iComponent == null || componentBase == null)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        return symbol.AllInterfaces.Contains(iComponent) || SymbolEqualityComparer.Default.Equals(symbol.BaseType, componentBase);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static bool HasUserDefinedSetParametersAsync(INamedTypeSymbol classSymbol)
 | 
			
		||||
    {
 | 
			
		||||
        return classSymbol
 | 
			
		||||
@@ -398,137 +436,4 @@ namespace {namespaceName}
 | 
			
		||||
                !m.IsStatic);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private static bool IsPartial(INamedTypeSymbol symbol)
 | 
			
		||||
    {
 | 
			
		||||
        return symbol.DeclaringSyntaxReferences
 | 
			
		||||
            .Select(r => r.GetSyntax())
 | 
			
		||||
            .OfType<ClassDeclarationSyntax>()
 | 
			
		||||
            .Any(c => c.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)));
 | 
			
		||||
    }
 | 
			
		||||
    private static bool IsComponent(ClassDeclarationSyntax classDeclarationSyntax, INamedTypeSymbol symbol, Compilation compilation)
 | 
			
		||||
    {
 | 
			
		||||
        if (HasUserDefinedSetParametersAsync(symbol))
 | 
			
		||||
        {
 | 
			
		||||
            // 用户自己写了方法,不生成
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!IsPartial(symbol))
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (classDeclarationSyntax.SyntaxTree.FilePath.EndsWith(".razor") || classDeclarationSyntax.SyntaxTree.FilePath.EndsWith(".razor.cs"))
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        var iComponent = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.IComponent");
 | 
			
		||||
        var componentBase = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.ComponentBase");
 | 
			
		||||
        if (iComponent == null || componentBase == null)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (SymbolEqualityComparer.Default.Equals(symbol, iComponent))
 | 
			
		||||
            return true;
 | 
			
		||||
        if (SymbolEqualityComparer.Default.Equals(symbol, componentBase))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Enumerate methods with at least one Group attribute
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    private static IEnumerable<INamedTypeSymbol> GetCandidateClasses(SyntaxReceiver receiver, GeneratorExecutionContext context)
 | 
			
		||||
    {
 | 
			
		||||
        var compilation = context.Compilation;
 | 
			
		||||
        var positiveAttributeSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.GenerateSetParametersAsyncAttribute");
 | 
			
		||||
        var negativeAttributeSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.DoNotGenerateSetParametersAsyncAttribute");
 | 
			
		||||
 | 
			
		||||
        // loop over the candidate methods, and keep the ones that are actually annotated
 | 
			
		||||
 | 
			
		||||
        // 找特性
 | 
			
		||||
        var assemblyAttributes = compilation.Assembly.GetAttributes();
 | 
			
		||||
 | 
			
		||||
        var enableAttr = assemblyAttributes.FirstOrDefault(attr =>
 | 
			
		||||
            attr.AttributeClass?.ToDisplayString() == "Microsoft.AspNetCore.Components.GlobalGenerateSetParametersAsyncAttribute");
 | 
			
		||||
 | 
			
		||||
        var globalEnable = false;
 | 
			
		||||
        if (enableAttr != null)
 | 
			
		||||
        {
 | 
			
		||||
            var arg = enableAttr.ConstructorArguments.FirstOrDefault();
 | 
			
		||||
            if (arg.Value is bool b)
 | 
			
		||||
                globalEnable = b;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach (ClassDeclarationSyntax class_declaration in receiver.CandidateClasses)
 | 
			
		||||
        {
 | 
			
		||||
            var model = compilation.GetSemanticModel(class_declaration.SyntaxTree);
 | 
			
		||||
            var class_symbol = model.GetDeclaredSymbol(class_declaration);
 | 
			
		||||
            if (class_symbol is null)
 | 
			
		||||
            {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (class_symbol.Name == "_Imports")
 | 
			
		||||
            {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 是否拒绝生成
 | 
			
		||||
            var hasNegative = class_symbol.GetAttributes().Any(ad =>
 | 
			
		||||
                ad.AttributeClass?.Equals(negativeAttributeSymbol, SymbolEqualityComparer.Default) == true);
 | 
			
		||||
 | 
			
		||||
            if (hasNegative)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (IsComponent(class_declaration, class_symbol, compilation))
 | 
			
		||||
            {
 | 
			
		||||
                if (globalEnable)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return class_symbol;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // 必须显式标注 Positive Attribute
 | 
			
		||||
                    var hasPositive = class_symbol.GetAttributes().Any(ad =>
 | 
			
		||||
                        ad.AttributeClass?.Equals(positiveAttributeSymbol, SymbolEqualityComparer.Default) == true);
 | 
			
		||||
 | 
			
		||||
                    if (hasPositive)
 | 
			
		||||
                        yield return class_symbol;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Created on demand before each generation pass
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class SyntaxReceiver : ISyntaxReceiver
 | 
			
		||||
    {
 | 
			
		||||
        public List<ClassDeclarationSyntax> CandidateClasses { get; } = new List<ClassDeclarationSyntax>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void OnVisitSyntaxNode(SyntaxNode syntax_node)
 | 
			
		||||
        {
 | 
			
		||||
            // any class with at least one attribute is a candidate for property generation
 | 
			
		||||
            if (syntax_node is ClassDeclarationSyntax classDeclarationSyntax)
 | 
			
		||||
            {
 | 
			
		||||
                CandidateClasses.Add(classDeclarationSyntax);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Components
 | 
			
		||||
{
 | 
			
		||||
    internal static class SourceGeneratorContextExtension
 | 
			
		||||
    {
 | 
			
		||||
        public static void AddCode(this GeneratorExecutionContext context, string hint_name, string code)
 | 
			
		||||
        public static void AddCode(this SourceProductionContext context, string hint_name, string code)
 | 
			
		||||
        {
 | 
			
		||||
            context.AddSource(hint_name.Replace("<", "_").Replace(">", "_"), SourceText.From(code, Encoding.UTF8));
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +0,0 @@
 | 
			
		||||
using Microsoft.CodeAnalysis;
 | 
			
		||||
using Microsoft.CodeAnalysis.CSharp;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.AspNetCore.Components
 | 
			
		||||
{
 | 
			
		||||
    internal static class StringExtension
 | 
			
		||||
    {
 | 
			
		||||
        public static string NormalizeWhitespace(this string code)
 | 
			
		||||
        {
 | 
			
		||||
            return CSharpSyntaxTree.ParseText(code).GetRoot().NormalizeWhitespace().ToFullString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,6 @@ using System.Collections.Concurrent;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,22 +33,22 @@ public static class CacheConst
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 资源表缓存Key
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Cache_SysResource = $"{CacheConst.Cache_Prefix_Admin}SysResource:";
 | 
			
		||||
    public const string Cache_SysResource = $"{CacheConst.Cache_Prefix_Admin}SysResource:List";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 角色表缓存Key
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Cache_SysRole = $"{CacheConst.Cache_Prefix_Admin}SysRole:";
 | 
			
		||||
    public const string Cache_SysRole = $"{CacheConst.Cache_Prefix_Admin}SysRole:List";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 用户表缓存Key
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Cache_SysUser = $"{CacheConst.Cache_Prefix_Admin}SysUser:";
 | 
			
		||||
    public const string Cache_SysUser = $"{CacheConst.Cache_Prefix_Admin}SysUser:Hash";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 用户账号关系缓存Key
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Cache_SysUserAccount = $"{CacheConst.Cache_Prefix_Admin}SysUserAccount:";
 | 
			
		||||
    public const string Cache_SysUserAccount = $"{CacheConst.Cache_Prefix_Admin}SysUserAccount:Hash";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 职位表缓存Key
 | 
			
		||||
@@ -58,7 +58,7 @@ public static class CacheConst
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 机构表缓存Key
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Cache_SysOrg = $"{CacheConst.Cache_Prefix_Admin}SysOrg:";
 | 
			
		||||
    public const string Cache_SysOrg = $"{CacheConst.Cache_Prefix_Admin}SysOrg:List";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 公司表缓存Key
 | 
			
		||||
@@ -67,12 +67,12 @@ public static class CacheConst
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 公司表缓存Key
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Cache_SysOrgTenant = $"{CacheConst.Cache_Prefix_Admin}OrgTenant:";
 | 
			
		||||
    public const string Cache_SysOrgTenant = $"{CacheConst.Cache_Prefix_Admin}OrgTenant:Hash";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Token表缓存Key
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Cache_Token = $"{CacheConst.Cache_Prefix_Admin}Token:";
 | 
			
		||||
    public const string Cache_Token = $"{CacheConst.Cache_Prefix_Admin}Token:Hash";
 | 
			
		||||
 | 
			
		||||
    #region 登录错误次数
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 | 
			
		||||
@@ -41,9 +39,9 @@ public class OpenApiController : ControllerBase
 | 
			
		||||
    [AllowAnonymous]
 | 
			
		||||
    public async Task<OpenApiLoginOutput> LoginAsync([FromBody] OpenApiLoginInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var output = await _authService.LoginAsync(input.Adapt<LoginInput>(), false).ConfigureAwait(false);
 | 
			
		||||
        var output = await _authService.LoginAsync(input.AdaptLoginInput(), false).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        var openApiLoginOutput = output.Adapt<OpenApiLoginOutput>();
 | 
			
		||||
        var openApiLoginOutput = output.AdaptOpenApiLoginOutput();
 | 
			
		||||
 | 
			
		||||
        return openApiLoginOutput;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,8 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
[SugarTable("sys_dict", TableDescription = "字典表")]
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,8 @@
 | 
			
		||||
// QQ群:605534569
 | 
			
		||||
// ------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,9 @@
 | 
			
		||||
// QQ群:605534569
 | 
			
		||||
// ------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,16 +8,12 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Components.Routing;
 | 
			
		||||
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,8 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,14 +8,9 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
using Riok.Mapperly.Abstractions;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -31,7 +26,7 @@ public class SysUser : BaseEntity
 | 
			
		||||
    ///</summary>
 | 
			
		||||
    [SugarColumn(ColumnDescription = "头像", ColumnDataType = StaticConfig.CodeFirst_BigString, IsNullable = true)]
 | 
			
		||||
    [AutoGenerateColumn(Visible = true, Sortable = false, Filterable = false)]
 | 
			
		||||
    [AdaptIgnore]
 | 
			
		||||
    [MapperIgnore]
 | 
			
		||||
    public virtual string? Avatar { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,7 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.List;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
using ThingsGateway.Common.List;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,23 +8,30 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
using System.Text;
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Razor;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// <see cref="Encoding"/> Master规则
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class EncodingMapper : IRegister
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
[ThingsGateway.DependencyInjection.SuppressSniffer]
 | 
			
		||||
public static class SchemeHelper
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public void Register(TypeAdapterConfig config)
 | 
			
		||||
 | 
			
		||||
    public static string GetOrCreate()
 | 
			
		||||
    {
 | 
			
		||||
        config.ForType<Encoding, Encoding>()
 | 
			
		||||
            .Ignore(dest => dest.EncoderFallback)
 | 
			
		||||
            .Ignore(dest => dest.DecoderFallback)
 | 
			
		||||
              .ConstructUsing(src => Encoding.GetEncoding(src.CodePage));
 | 
			
		||||
        var path = "Keys/SchemeKey.txt";
 | 
			
		||||
        if (File.Exists(path))
 | 
			
		||||
        {
 | 
			
		||||
            var data = File.ReadAllText(path);
 | 
			
		||||
            return data;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            var data = DateTime.UtcNow.ToDefaultDateTimeFormat();
 | 
			
		||||
            Directory.CreateDirectory("Keys");
 | 
			
		||||
            File.WriteAllText(path, data);
 | 
			
		||||
            return data;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -79,7 +79,7 @@ public class RequestAuditFilter : IAsyncActionFilter, IOrderedFilter
 | 
			
		||||
 | 
			
		||||
        logData.TimeOperationElapsedMilliseconds = timeOperation.ElapsedMilliseconds;
 | 
			
		||||
 | 
			
		||||
        var resultHttpContext = (resultContext as FilterContext).HttpContext;
 | 
			
		||||
        var resultHttpContext = (resultContext as Microsoft.AspNetCore.Mvc.Filters.FilterContext).HttpContext;
 | 
			
		||||
 | 
			
		||||
        // 获取 HttpContext 和 HttpRequest 对象
 | 
			
		||||
        var httpContext = context.HttpContext;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,4 +8,15 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
global using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
global using Microsoft.Extensions.Localization;
 | 
			
		||||
global using Microsoft.Extensions.Options;
 | 
			
		||||
 | 
			
		||||
global using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
global using System.Globalization;
 | 
			
		||||
 | 
			
		||||
global using ThingsGateway.Common;
 | 
			
		||||
global using ThingsGateway.DB;
 | 
			
		||||
global using ThingsGateway.NewLife.Extension;
 | 
			
		||||
global using ThingsGateway.SqlSugar;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,7 @@
 | 
			
		||||
// ------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.Hosting;
 | 
			
		||||
using Microsoft.Extensions.Localization;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
 | 
			
		||||
@@ -20,7 +18,6 @@ using ThingsGateway.NewLife;
 | 
			
		||||
using ThingsGateway.NewLife.Caching;
 | 
			
		||||
using ThingsGateway.NewLife.Threading;
 | 
			
		||||
using ThingsGateway.Schedule;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -53,8 +50,8 @@ public class HardwareJob : IJob, IHardwareJob
 | 
			
		||||
 | 
			
		||||
    #endregion 属性
 | 
			
		||||
 | 
			
		||||
    private MemoryCache MemoryCache = new() { };
 | 
			
		||||
    private const string CacheKey = "HistoryHardwareInfo";
 | 
			
		||||
    private ICache MemoryCache => App.CacheService;
 | 
			
		||||
    private const string CacheKey = $"{CacheConst.Cache_HardwareInfo}HistoryHardwareInfo";
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<List<HistoryHardwareInfo>> GetHistoryHardwareInfos()
 | 
			
		||||
    {
 | 
			
		||||
@@ -62,7 +59,7 @@ public class HardwareJob : IJob, IHardwareJob
 | 
			
		||||
        if (historyHardwareInfos == null)
 | 
			
		||||
        {
 | 
			
		||||
            using var db = DbContext.GetDB<HistoryHardwareInfo>(); ;
 | 
			
		||||
            historyHardwareInfos = await db.Queryable<HistoryHardwareInfo>().Where(a => a.Date > DateTime.Now.AddDays(-3)).ToListAsync().ConfigureAwait(false);
 | 
			
		||||
            historyHardwareInfos = await db.Queryable<HistoryHardwareInfo>().Where(a => a.Date > DateTime.Now.AddDays(-3)).Take(1000).ToListAsync().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            MemoryCache.Set(CacheKey, historyHardwareInfos);
 | 
			
		||||
        }
 | 
			
		||||
@@ -81,8 +78,7 @@ public class HardwareJob : IJob, IHardwareJob
 | 
			
		||||
            {
 | 
			
		||||
                if (HardwareInfo.MachineInfo == null)
 | 
			
		||||
                {
 | 
			
		||||
                    MachineInfo.Register();
 | 
			
		||||
                    HardwareInfo.MachineInfo = MachineInfo.Current;
 | 
			
		||||
                    HardwareInfo.MachineInfo = MachineInfo.GetCurrent();
 | 
			
		||||
 | 
			
		||||
                    string currentPath = Directory.GetCurrentDirectory();
 | 
			
		||||
                    DriveInfo drive = new(Path.GetPathRoot(currentPath));
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,6 @@ using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.Logging;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,31 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://thingsgateway.cn/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Riok.Mapperly.Abstractions;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, RequiredMappingStrategy = RequiredMappingStrategy.None)]
 | 
			
		||||
public static partial class AdminMapper
 | 
			
		||||
{
 | 
			
		||||
    public static partial LoginInput AdaptLoginInput(this OpenApiLoginInput src);
 | 
			
		||||
    public static partial OpenApiLoginOutput AdaptOpenApiLoginOutput(this LoginOutput src);
 | 
			
		||||
    public static partial SessionOutput AdaptSessionOutput(this SysUser src);
 | 
			
		||||
    public static partial SysUser AdaptSysUser(this SysUser src);
 | 
			
		||||
    public static partial UserSelectorOutput AdaptUserSelectorOutput(this SysUser src);
 | 
			
		||||
    public static partial List<SysResource> AdaptListSysResource(this IEnumerable<SysResource> src);
 | 
			
		||||
    public static partial AppConfig AdaptAppConfig(this AppConfig src);
 | 
			
		||||
    public static partial WorkbenchInfo AdaptWorkbenchInfo(this WorkbenchInfo src);
 | 
			
		||||
    public static partial QueryData<UserSelectorOutput> AdaptQueryDataUserSelectorOutput(this QueryData<SysUser> src);
 | 
			
		||||
    public static partial LoginInput AdaptLoginInput(this LoginInput src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.Hosting;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authentication;
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Components;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
@@ -116,7 +115,7 @@ public class BlazorAuthenticationHandler : AppAuthorizeHandler
 | 
			
		||||
                {
 | 
			
		||||
                    // 路由名称
 | 
			
		||||
                    var routeName = routeData.PageType.CustomAttributes.FirstOrDefault(x =>
 | 
			
		||||
                        x.AttributeType == typeof(RouteAttribute))?.ConstructorArguments?[0].Value as string;
 | 
			
		||||
                        x.AttributeType == typeof(Microsoft.AspNetCore.Components.RouteAttribute))?.ConstructorArguments?[0].Value as string;
 | 
			
		||||
                    if (routeName == null) return true;
 | 
			
		||||
 | 
			
		||||
                    if ((!user.PermissionCodeList.Contains(routeName.CutStart("/")) && !user.PermissionCodeList.Contains(routeName))) //如果当前路由信息不包含在角色授权路由列表中则认证失败
 | 
			
		||||
 
 | 
			
		||||
@@ -11,11 +11,9 @@
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.Filters;
 | 
			
		||||
using Microsoft.Extensions.Localization;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.DataValidation;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
using ThingsGateway.UnifyResult;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,19 +9,15 @@
 | 
			
		||||
// ------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.Controllers;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
 | 
			
		||||
using Swashbuckle.AspNetCore.SwaggerGen;
 | 
			
		||||
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Common.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authentication.Cookies;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Localization;
 | 
			
		||||
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,8 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife.DictionaryExtensions;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Components.Forms;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.Extensions.Localization;
 | 
			
		||||
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Web;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,8 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.Data;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
internal sealed class SysOperateLogService : BaseService<SysOperateLog>, ISysOperateLogService
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,6 @@
 | 
			
		||||
// QQ群:605534569
 | 
			
		||||
// ------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,8 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,6 @@
 | 
			
		||||
// QQ群:605534569
 | 
			
		||||
// ------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,7 @@
 | 
			
		||||
// QQ群:605534569
 | 
			
		||||
// ------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,14 +8,9 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -23,7 +18,7 @@ internal sealed class SysResourceService : BaseService<SysResource>, ISysResourc
 | 
			
		||||
{
 | 
			
		||||
    private readonly IRelationService _relationService;
 | 
			
		||||
 | 
			
		||||
    private string CacheKey = $"{CacheConst.Cache_SysResource}-{CultureInfo.CurrentUICulture.Name}";
 | 
			
		||||
    private string CacheKey = $"{CacheConst.Cache_SysResource}";
 | 
			
		||||
 | 
			
		||||
    public SysResourceService(IRelationService relationService)
 | 
			
		||||
    {
 | 
			
		||||
@@ -32,7 +27,6 @@ internal sealed class SysResourceService : BaseService<SysResource>, ISysResourc
 | 
			
		||||
 | 
			
		||||
    #region 增删改查
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [OperDesc("CopyResource")]
 | 
			
		||||
    public async Task CopyAsync(IEnumerable<long> ids, long moduleId)
 | 
			
		||||
    {
 | 
			
		||||
@@ -143,12 +137,12 @@ internal sealed class SysResourceService : BaseService<SysResource>, ISysResourc
 | 
			
		||||
    /// <returns>全部资源列表</returns>
 | 
			
		||||
    public async Task<List<SysResource>> GetAllAsync()
 | 
			
		||||
    {
 | 
			
		||||
        var sysResources = App.CacheService.Get<List<SysResource>>(CacheKey);
 | 
			
		||||
        var sysResources = App.CacheService.Get<List<SysResource>>(CacheConst.Cache_SysResource);
 | 
			
		||||
        if (sysResources == null)
 | 
			
		||||
        {
 | 
			
		||||
            using var db = GetDB();
 | 
			
		||||
            sysResources = await db.Queryable<SysResource>().ToListAsync().ConfigureAwait(false);
 | 
			
		||||
            App.CacheService.Set(CacheKey, sysResources);
 | 
			
		||||
            App.CacheService.Set(CacheConst.Cache_SysResource, sysResources);
 | 
			
		||||
        }
 | 
			
		||||
        return sysResources;
 | 
			
		||||
    }
 | 
			
		||||
@@ -258,7 +252,7 @@ internal sealed class SysResourceService : BaseService<SysResource>, ISysResourc
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void RefreshCache()
 | 
			
		||||
    {
 | 
			
		||||
        App.CacheService.Remove(CacheKey);
 | 
			
		||||
        App.CacheService.Remove(CacheConst.Cache_SysResource);
 | 
			
		||||
        //删除超级管理员的缓存
 | 
			
		||||
        App.RootServices.GetRequiredService<ISysUserService>().DeleteUserFromCache(RoleConst.SuperAdminId);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,8 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
public interface ISessionService
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
internal sealed class SessionService : BaseService<SysUser>, ISessionService
 | 
			
		||||
@@ -69,7 +63,7 @@ internal sealed class SessionService : BaseService<SysUser>, ISessionService
 | 
			
		||||
 | 
			
		||||
            var r = items.Select((it) =>
 | 
			
		||||
            {
 | 
			
		||||
                var reuslt = it.Adapt<SessionOutput>();
 | 
			
		||||
                var reuslt = it.AdaptSessionOutput();
 | 
			
		||||
                if (verificatInfoDicts.TryGetValue(it.Id, out var verificatInfos))
 | 
			
		||||
                {
 | 
			
		||||
                    reuslt.VerificatCount = verificatInfos.Count;//令牌数量
 | 
			
		||||
@@ -94,7 +88,7 @@ internal sealed class SessionService : BaseService<SysUser>, ISessionService
 | 
			
		||||
 | 
			
		||||
            var r = items.Select((it) =>
 | 
			
		||||
            {
 | 
			
		||||
                var reuslt = it.Adapt<SessionOutput>();
 | 
			
		||||
                var reuslt = it.AdaptSessionOutput();
 | 
			
		||||
                if (verificatInfoDicts.TryGetValue(it.Id, out var verificatInfos))
 | 
			
		||||
                {
 | 
			
		||||
                    reuslt.VerificatCount = verificatInfos.Count;//令牌数量
 | 
			
		||||
@@ -117,7 +111,7 @@ internal sealed class SessionService : BaseService<SysUser>, ISessionService
 | 
			
		||||
 | 
			
		||||
            var r = items.Select((it) =>
 | 
			
		||||
            {
 | 
			
		||||
                var reuslt = it.Adapt<SessionOutput>();
 | 
			
		||||
                var reuslt = it.AdaptSessionOutput();
 | 
			
		||||
                if (verificatInfoDicts.TryGetValue(it.Id, out var verificatInfos))
 | 
			
		||||
                {
 | 
			
		||||
                    reuslt.VerificatCount = verificatInfos.Count;//令牌数量
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,16 +8,12 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Common.Extension;
 | 
			
		||||
using ThingsGateway.Common.Extension.Generic;
 | 
			
		||||
using ThingsGateway.DataEncryption;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -452,7 +448,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
 | 
			
		||||
 | 
			
		||||
        if (changedType == ItemChangedType.Add)
 | 
			
		||||
        {
 | 
			
		||||
            var sysUser = input.Adapt<SysUser>();
 | 
			
		||||
            var sysUser = input.AdaptSysUser();
 | 
			
		||||
            //获取默认密码
 | 
			
		||||
            sysUser.Avatar = input.Avatar;
 | 
			
		||||
            sysUser.Password = await GetDefaultPassWord(true).ConfigureAwait(false);//设置密码
 | 
			
		||||
@@ -872,7 +868,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
 | 
			
		||||
            sysUser.OrgAndPosIdList.AddRange(sysUser.OrgId, sysUser.PositionId ?? 0);//添加组织和职位Id
 | 
			
		||||
            if (sysUser.DirectorId != null)
 | 
			
		||||
            {
 | 
			
		||||
                sysUser.DirectorInfo = (await GetUserByIdAsync(sysUser.DirectorId.Value).ConfigureAwait(false)).Adapt<UserSelectorOutput>();//获取主管信息
 | 
			
		||||
                sysUser.DirectorInfo = (await GetUserByIdAsync(sysUser.DirectorId.Value).ConfigureAwait(false)).AdaptUserSelectorOutput();//获取主管信息
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //获取按钮码
 | 
			
		||||
 
 | 
			
		||||
@@ -8,16 +8,13 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Common.Extension;
 | 
			
		||||
using ThingsGateway.DataEncryption;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,13 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.UnifyResult;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
@@ -40,7 +41,6 @@ public class Startup : AppStartup
 | 
			
		||||
 | 
			
		||||
        services.AddSingleton<IVerificatInfoService, VerificatInfoService>();
 | 
			
		||||
 | 
			
		||||
        services.AddScoped<IAuthRazorService, AuthRazorService>();
 | 
			
		||||
        services.AddSingleton<IApiPermissionService, ApiPermissionService>();
 | 
			
		||||
        services.AddSingleton<IFileService, FileService>();
 | 
			
		||||
        services.AddSingleton<IImportExportService, ImportExportService>();
 | 
			
		||||
@@ -64,10 +64,77 @@ public class Startup : AppStartup
 | 
			
		||||
 | 
			
		||||
        services.AddSingleton(typeof(IEventService<>), typeof(EventService<>));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region 控制台美化
 | 
			
		||||
 | 
			
		||||
        services.AddConsoleFormatter(options =>
 | 
			
		||||
        {
 | 
			
		||||
            options.WriteFilter = (logMsg) =>
 | 
			
		||||
            {
 | 
			
		||||
                if (App.HostApplicationLifetime.ApplicationStopping.IsCancellationRequested && logMsg.LogLevel >= LogLevel.Warning) return false;
 | 
			
		||||
                if (string.IsNullOrEmpty(logMsg.Message)) return false;
 | 
			
		||||
                else return true;
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            options.MessageFormat = (logMsg) =>
 | 
			
		||||
            {
 | 
			
		||||
                //如果不是LoggingMonitor日志才格式化
 | 
			
		||||
                if (logMsg.LogName != "System.Logging.LoggingMonitor")
 | 
			
		||||
                {
 | 
			
		||||
                    var stringBuilder = new StringBuilder();
 | 
			
		||||
                    stringBuilder.AppendLine("【日志级别】:" + logMsg.LogLevel);
 | 
			
		||||
                    stringBuilder.AppendLine("【日志类名】:" + logMsg.LogName);
 | 
			
		||||
                    stringBuilder.AppendLine("【日志时间】:" + DateTime.Now.ToDefaultDateTimeFormat());
 | 
			
		||||
                    stringBuilder.AppendLine("【日志内容】:" + logMsg.Message);
 | 
			
		||||
                    if (logMsg.Exception != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        stringBuilder.AppendLine("【异常信息】:" + logMsg.Exception);
 | 
			
		||||
                    }
 | 
			
		||||
                    return stringBuilder.ToString();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return logMsg.Message;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            options.WriteHandler = (logMsg, scopeProvider, writer, fmtMsg, opt) =>
 | 
			
		||||
            {
 | 
			
		||||
                ConsoleColor consoleColor = ConsoleColor.White;
 | 
			
		||||
                switch (logMsg.LogLevel)
 | 
			
		||||
                {
 | 
			
		||||
                    case LogLevel.Information:
 | 
			
		||||
                        consoleColor = ConsoleColor.DarkGreen;
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                    case LogLevel.Warning:
 | 
			
		||||
                        consoleColor = ConsoleColor.DarkYellow;
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                    case LogLevel.Error:
 | 
			
		||||
                        consoleColor = ConsoleColor.DarkRed;
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                writer.WriteWithColor(fmtMsg, ConsoleColor.Black, consoleColor);
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        #endregion 控制台美化
 | 
			
		||||
        //日志写入数据库配置
 | 
			
		||||
        services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>
 | 
			
		||||
        {
 | 
			
		||||
            options.NameFilter = (name) =>
 | 
			
		||||
            {
 | 
			
		||||
                return (
 | 
			
		||||
                name == "System.Logging.RequestAudit"
 | 
			
		||||
                );
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void Use(IServiceProvider serviceProvider)
 | 
			
		||||
    {
 | 
			
		||||
        NewLife.Log.XTrace.UnhandledExceptionLogEnable = () => !App.HostApplicationLifetime.ApplicationStopping.IsCancellationRequested;
 | 
			
		||||
 | 
			
		||||
        //检查ConfigId
 | 
			
		||||
        var configIdGroup = DbContext.DbConfigs.GroupBy(it => it.ConfigId);
 | 
			
		||||
        foreach (var configId in configIdGroup)
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
	
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
 | 
			
		||||
		<PackageReference Include="Rougamo.Fody" Version="5.0.1" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
	<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ namespace ThingsGateway.Admin.Application
 | 
			
		||||
            Settings = new UserAgentSettings();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private MemoryCache MemoryCache { get; set; } = new();
 | 
			
		||||
        private ICache MemoryCache => App.CacheService;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Parses the specified user agent string.
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,8 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
@@ -88,7 +85,7 @@ public class BlazorAppContext
 | 
			
		||||
        if (UserManager.UserId > 0)
 | 
			
		||||
        {
 | 
			
		||||
            url = url.StartsWith('/') ? url : $"/{url}";
 | 
			
		||||
            var sysResources = (await ResourceService.GetAllAsync()).Adapt<List<SysResource>>();
 | 
			
		||||
            var sysResources = (await ResourceService.GetAllAsync()).AdaptListSysResource();
 | 
			
		||||
            if (TitleLocalizer != null)
 | 
			
		||||
            {
 | 
			
		||||
                sysResources.ForEach(a =>
 | 
			
		||||
@@ -121,7 +118,7 @@ public class BlazorAppContext
 | 
			
		||||
                CurrentModuleId = moduleId.Value;
 | 
			
		||||
            }
 | 
			
		||||
            UserWorkBench = await UserCenterService.GetLoginWorkbenchAsync(UserManager.UserId);
 | 
			
		||||
            OwnMenus = (await UserCenterService.GetOwnMenuAsync(UserManager.UserId, 0)).Adapt<List<SysResource>>();
 | 
			
		||||
            OwnMenus = (await UserCenterService.GetOwnMenuAsync(UserManager.UserId, 0)).AdaptListSysResource();
 | 
			
		||||
 | 
			
		||||
            if (TitleLocalizer != null)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,10 @@ global using Microsoft.Extensions.Options;
 | 
			
		||||
 | 
			
		||||
global using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
global using ThingsGateway.Common;
 | 
			
		||||
global using ThingsGateway.DB;
 | 
			
		||||
global using ThingsGateway.NewLife.Extension;
 | 
			
		||||
global using ThingsGateway.Razor;
 | 
			
		||||
 | 
			
		||||
global using ThingsGateway.SqlSugar;
 | 
			
		||||
[assembly: SuppressMessage("Reliability", "CA2007", Justification = "<挂起>", Scope = "module")]
 | 
			
		||||
[assembly: GlobalGenerateSetParametersAsync(true)]
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Components.Forms;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
@@ -30,7 +28,7 @@ public partial class AppConfigPage
 | 
			
		||||
 | 
			
		||||
    protected override async Task OnParametersSetAsync()
 | 
			
		||||
    {
 | 
			
		||||
        AppConfig = (await SysDictService.GetAppConfigAsync()).Adapt<AppConfig>();
 | 
			
		||||
        AppConfig = (await SysDictService.GetAppConfigAsync()).AdaptAppConfig();
 | 
			
		||||
        await base.OnParametersSetAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Components.Forms;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -90,8 +90,8 @@
 | 
			
		||||
                                        <h6>   @((100 - (availableMemory * 100.00 / memory)).ToString("F2") + " %")  </h6>
 | 
			
		||||
 | 
			
		||||
                                        <span>   @Localizer["WorkingSet"] <i> @(HardwareJob.HardwareInfo.WorkingSet + " MB")</i></span>
 | 
			
		||||
                                        <span>   @Localizer["AvailableMemory"] <i> @((availableMemory / 1024.00 / 1024 / 1024).ToString("F2") + " GB")</i></span>
 | 
			
		||||
                                        <span>   @Localizer["TotalMemory"] <i> @((memory / 1024.00 / 1024 / 1024).ToString("F2") + " GB")</i></span>
 | 
			
		||||
                                        <span>   @Localizer["AvailableMemory"] <i> @((availableMemory / 1024.00 / 1024).ToString("F2") + " GB")</i></span>
 | 
			
		||||
                                        <span>   @Localizer["TotalMemory"] <i> @((memory / 1024.00 / 1024).ToString("F2") + " GB")</i></span>
 | 
			
		||||
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </Circle>
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,7 @@ public partial class HardwareInfoPage : IDisposable
 | 
			
		||||
 | 
			
		||||
    private async Task<ChartDataSource> OnInit()
 | 
			
		||||
    {
 | 
			
		||||
        if (App.HostApplicationLifetime.ApplicationStopping.IsCancellationRequested) return (new ChartDataSource());
 | 
			
		||||
        if (ChartDataSource == null)
 | 
			
		||||
        {
 | 
			
		||||
            var hisHardwareInfos = await HardwareJob.GetHistoryHardwareInfos();
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ public partial class OperLogPage
 | 
			
		||||
 | 
			
		||||
    private async Task<ChartDataSource> OnInit()
 | 
			
		||||
    {
 | 
			
		||||
        if (App.HostApplicationLifetime.ApplicationStopping.IsCancellationRequested) return (new ChartDataSource());
 | 
			
		||||
        if (ChartDataSource == null)
 | 
			
		||||
        {
 | 
			
		||||
            var dayStatisticsOutputs = await SysOperateLogService.StatisticsByDayAsync(7);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
using ThingsGateway.SqlSugar;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.Extension.Generic;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
@@ -47,10 +45,7 @@ public partial class RoleChoiceDialog
 | 
			
		||||
    private ISysRoleService? SysRoleService { get; set; }
 | 
			
		||||
    private async Task<QueryData<SysRole>> OnQueryAsync(QueryPageOptions options)
 | 
			
		||||
    {
 | 
			
		||||
        var data = await SysRoleService.PageAsync(options, a => a.Where(b => b.OrgId == OrgId));
 | 
			
		||||
        QueryData<SysRole> queryData = data.Adapt<QueryData<SysRole>>();
 | 
			
		||||
 | 
			
		||||
        return queryData;
 | 
			
		||||
        return await SysRoleService.PageAsync(options, a => a.Where(b => b.OrgId == OrgId));
 | 
			
		||||
    }
 | 
			
		||||
    #region 查询
 | 
			
		||||
    private long OrgId { get; set; }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@
 | 
			
		||||
using Microsoft.AspNetCore.Components.Forms;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
@@ -56,7 +54,7 @@ public partial class UserChoiceDialog
 | 
			
		||||
            OrgId = OrgId,
 | 
			
		||||
            PositionId = PositionId,
 | 
			
		||||
        });
 | 
			
		||||
        QueryData<UserSelectorOutput> queryData = data.Adapt<QueryData<UserSelectorOutput>>();
 | 
			
		||||
        QueryData<UserSelectorOutput> queryData = data.AdaptQueryDataUserSelectorOutput();
 | 
			
		||||
 | 
			
		||||
        return queryData;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Components.Forms;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
@@ -37,9 +35,9 @@ public partial class UserCenterPage
 | 
			
		||||
 | 
			
		||||
    protected override async Task OnParametersSetAsync()
 | 
			
		||||
    {
 | 
			
		||||
        SysUser = AppContext.CurrentUser.Adapt<SysUser>();
 | 
			
		||||
        SysUser = AppContext.CurrentUser.AdaptSysUser();
 | 
			
		||||
        SysUser.Avatar = AppContext.Avatar;
 | 
			
		||||
        WorkbenchInfo = (await UserCenterService.GetLoginWorkbenchAsync(SysUser.Id)).Adapt<WorkbenchInfo>();
 | 
			
		||||
        WorkbenchInfo = (await UserCenterService.GetLoginWorkbenchAsync(SysUser.Id)).AdaptWorkbenchInfo();
 | 
			
		||||
 | 
			
		||||
        await base.OnParametersSetAsync();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,11 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.NewLife.Json.Extension;
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
internal sealed class AuthRazorService : IAuthRazorService
 | 
			
		||||
{
 | 
			
		||||
@@ -8,9 +8,9 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class HybridAuthRazorService : IAuthRazorService
 | 
			
		||||
@@ -8,9 +8,9 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
 | 
			
		||||
public interface IAuthRazorService
 | 
			
		||||
{
 | 
			
		||||
@@ -18,6 +18,7 @@ public class Startup : AppStartup
 | 
			
		||||
    public void Configure(IServiceCollection services)
 | 
			
		||||
    {
 | 
			
		||||
        services.AddScoped<IMenuService, MenuService>();
 | 
			
		||||
        services.AddScoped<IAuthRazorService, AuthRazorService>();
 | 
			
		||||
        services.AddBootstrapBlazorTableExportService();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<ProjectReference Include="..\BlazorSetParametersAsyncGenerator\BlazorSetParametersAsyncGenerator.csproj" PrivateAssets="all" OutputItemType="Analyzer" />
 | 
			
		||||
		<ProjectReference Include="..\ThingsGateway.Razor\ThingsGateway.Razor.csproj" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
	
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
@@ -122,31 +120,4 @@ public static class ResourceUtil
 | 
			
		||||
        return trees;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 构建树节点
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static List<TreeViewItem<T>> BuildTreeItemList<T>(IEnumerable<SysResource> sysresources, List<long> selectedItems, Microsoft.AspNetCore.Components.RenderFragment<T> render, long parentId = 0, TreeViewItem<T>? parent = null, Func<SysResource, bool> disableFunc = null) where T : class
 | 
			
		||||
    {
 | 
			
		||||
        if (sysresources == null) return null;
 | 
			
		||||
        var trees = new List<TreeViewItem<T>>();
 | 
			
		||||
        var roots = sysresources.Where(i => i.ParentId == parentId).OrderBy(i => i.SortCode);
 | 
			
		||||
        foreach (var node in roots)
 | 
			
		||||
        {
 | 
			
		||||
            var item = new TreeViewItem<T>(node.Adapt<T>())
 | 
			
		||||
            {
 | 
			
		||||
                Text = node.Title,
 | 
			
		||||
                Icon = node.Icon,
 | 
			
		||||
                IsDisabled = disableFunc == null ? false : disableFunc(node),
 | 
			
		||||
                IsActive = selectedItems.Any(v => node.Id == v),
 | 
			
		||||
                IsExpand = true,
 | 
			
		||||
                Parent = parent,
 | 
			
		||||
                Template = render,
 | 
			
		||||
                CheckedState = selectedItems.Any(i => i == node.Id) ? CheckboxState.Checked : CheckboxState.UnChecked
 | 
			
		||||
            };
 | 
			
		||||
            item.Items = BuildTreeItemList(sysresources, selectedItems, render, node.Id, item, disableFunc) ?? new();
 | 
			
		||||
            trees.Add(item);
 | 
			
		||||
        }
 | 
			
		||||
        return trees;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,5 +15,5 @@
 | 
			
		||||
 | 
			
		||||
@using BootstrapBlazor.Components
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@using ThingsGateway.Common.Extension;
 | 
			
		||||
@using ThingsGateway.Razor;
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
      "ThingsGateway.SqlSugar",
 | 
			
		||||
      "ThingsGateway.Admin.Application",
 | 
			
		||||
      "ThingsGateway.Admin.Razor",
 | 
			
		||||
      "ThingsGateway.Common",
 | 
			
		||||
      "ThingsGateway.DB",
 | 
			
		||||
      "ThingsGateway.Razor"
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
      "ThingsGateway.SqlSugar",
 | 
			
		||||
      "ThingsGateway.Admin.Application",
 | 
			
		||||
      "ThingsGateway.Admin.Razor",
 | 
			
		||||
      "ThingsGateway.Common",
 | 
			
		||||
      "ThingsGateway.DB",
 | 
			
		||||
      "ThingsGateway.Razor"
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								src/Admin/ThingsGateway.AdminServer/Configuration/Cache.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Admin/ThingsGateway.AdminServer/Configuration/Cache.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
{
 | 
			
		||||
  "Cache": {
 | 
			
		||||
    "CacheType": "Memory", // 可选:Memory 或 Redis
 | 
			
		||||
 | 
			
		||||
    "MemoryCacheOptions": {
 | 
			
		||||
      "Expire": 3600,
 | 
			
		||||
      "Capacity": 100000,
 | 
			
		||||
      "Period": 60
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    "RedisCacheOptions": {
 | 
			
		||||
      "InstanceName": "ThingsGateway",
 | 
			
		||||
      "Configuration": "server=127.0.0.1:6379;password=123456;db=3;timeout=3000",
 | 
			
		||||
      "Server": "127.0.0.1:6379",
 | 
			
		||||
      "Db": 3,
 | 
			
		||||
      "UserName": "",
 | 
			
		||||
      "Password": "123456",
 | 
			
		||||
      "Timeout": 3000,
 | 
			
		||||
      "Prefix": "ThingsGateway:"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
@using ThingsGateway.Admin.Razor
 | 
			
		||||
@using ThingsGateway.Extension;
 | 
			
		||||
@using ThingsGateway.Razor
 | 
			
		||||
@using ThingsGateway.Common.Extension;
 | 
			
		||||
 | 
			
		||||
<div class="login h-100">
 | 
			
		||||
    @* 左侧说明 *@
 | 
			
		||||
 
 | 
			
		||||
@@ -11,8 +11,6 @@
 | 
			
		||||
#pragma warning disable CA2007 // 考虑对等待的任务调用 ConfigureAwait
 | 
			
		||||
using BootstrapBlazor.Components;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Components;
 | 
			
		||||
using Microsoft.AspNetCore.Components.Forms;
 | 
			
		||||
using Microsoft.Extensions.Localization;
 | 
			
		||||
@@ -21,6 +19,8 @@ using Microsoft.Extensions.Options;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.Admin.Razor;
 | 
			
		||||
using ThingsGateway.Common;
 | 
			
		||||
using ThingsGateway.DataEncryption;
 | 
			
		||||
using ThingsGateway.NewLife.Extension;
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
@@ -71,7 +71,7 @@ public partial class Login
 | 
			
		||||
 | 
			
		||||
    private async Task LoginAsync(EditContext context)
 | 
			
		||||
    {
 | 
			
		||||
        var model = loginModel.Adapt<LoginInput>();
 | 
			
		||||
        var model = loginModel.AdaptLoginInput();
 | 
			
		||||
        model.Password = DESEncryption.Encrypt(model.Password);
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,11 @@
 | 
			
		||||
@using Microsoft.AspNetCore.Authorization
 | 
			
		||||
@using Microsoft.AspNetCore.Components.Authorization
 | 
			
		||||
@using Microsoft.Extensions.Localization
 | 
			
		||||
@using ThingsGateway.Common.Extension;
 | 
			
		||||
 | 
			
		||||
@using System.ComponentModel
 | 
			
		||||
@using System.ComponentModel.DataAnnotations
 | 
			
		||||
@using ThingsGateway.DB;
 | 
			
		||||
 | 
			
		||||
@inject NavigationManager NavigationManager
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.Admin.Razor;
 | 
			
		||||
using ThingsGateway.Common;
 | 
			
		||||
using ThingsGateway.Razor;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.AdminServer;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,8 @@ using Microsoft.AspNetCore.ResponseCompression;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.DB;
 | 
			
		||||
using ThingsGateway.NewLife.Log;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.AdminServer;
 | 
			
		||||
@@ -29,6 +31,8 @@ public class Program
 | 
			
		||||
        // 增加中文编码支持
 | 
			
		||||
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
 | 
			
		||||
 | 
			
		||||
        ClaimConst.Scheme = $"{typeof(Program).Assembly.GetName().Name}{SchemeHelper.GetOrCreate()}";
 | 
			
		||||
 | 
			
		||||
        #region 控制台输出Logo
 | 
			
		||||
 | 
			
		||||
        Console.Write(Environment.NewLine);
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ public class SingleFilePublish : ISingleFilePublish
 | 
			
		||||
            "ThingsGateway.NewLife.X",
 | 
			
		||||
            "ThingsGateway.Razor",
 | 
			
		||||
            "ThingsGateway.Admin.Razor"   ,
 | 
			
		||||
            "ThingsGateway.Common",
 | 
			
		||||
             "ThingsGateway.DB",
 | 
			
		||||
            "ThingsGateway.Admin.Application",
 | 
			
		||||
            "ThingsGateway.SqlSugar",
 | 
			
		||||
 
 | 
			
		||||
@@ -21,14 +21,13 @@ using Microsoft.Extensions.Options;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
 | 
			
		||||
using System.Security.Cryptography.X509Certificates;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.Encodings.Web;
 | 
			
		||||
using System.Text.Unicode;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Application;
 | 
			
		||||
using ThingsGateway.Admin.Razor;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.NewLife.Caching;
 | 
			
		||||
using ThingsGateway.DB;
 | 
			
		||||
using ThingsGateway.VirtualFileServer;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.AdminServer;
 | 
			
		||||
 | 
			
		||||
@@ -60,8 +59,6 @@ public class Startup : AppStartup
 | 
			
		||||
            options.AddPersistence<JobPersistence>();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 缓存
 | 
			
		||||
        services.AddSingleton<ICache, MemoryCache>();
 | 
			
		||||
 | 
			
		||||
        // 允许跨域
 | 
			
		||||
        services.AddCorsAccessor();
 | 
			
		||||
@@ -111,7 +108,7 @@ public class Startup : AppStartup
 | 
			
		||||
         .AddHubOptions(options =>
 | 
			
		||||
         {
 | 
			
		||||
             //单个传入集线器消息的最大大小。默认 32 KB
 | 
			
		||||
             options.MaximumReceiveMessageSize = 1024 * 1024;
 | 
			
		||||
             options.MaximumReceiveMessageSize = 32 * 1024 * 1024;
 | 
			
		||||
             //可为客户端上载流缓冲的最大项数。 如果达到此限制,则会阻止处理调用,直到服务器处理流项。
 | 
			
		||||
             options.StreamBufferCapacity = 30;
 | 
			
		||||
             options.ClientTimeoutInterval = TimeSpan.FromMinutes(2);
 | 
			
		||||
@@ -130,7 +127,7 @@ public class Startup : AppStartup
 | 
			
		||||
        }).AddHubOptions(options =>
 | 
			
		||||
        {
 | 
			
		||||
            //单个传入集线器消息的最大大小。默认 32 KB
 | 
			
		||||
            options.MaximumReceiveMessageSize = 1024 * 1024;
 | 
			
		||||
            options.MaximumReceiveMessageSize = 32 * 1024 * 1024;
 | 
			
		||||
            //可为客户端上载流缓冲的最大项数。 如果达到此限制,则会阻止处理调用,直到服务器处理流项。
 | 
			
		||||
            options.StreamBufferCapacity = 30;
 | 
			
		||||
            options.ClientTimeoutInterval = TimeSpan.FromMinutes(2);
 | 
			
		||||
@@ -152,101 +149,9 @@ public class Startup : AppStartup
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region 控制台美化
 | 
			
		||||
 | 
			
		||||
        services.AddConsoleFormatter(options =>
 | 
			
		||||
        {
 | 
			
		||||
            options.WriteFilter = (logMsg) =>
 | 
			
		||||
            {
 | 
			
		||||
                if (App.HostApplicationLifetime.ApplicationStopping.IsCancellationRequested && logMsg.LogLevel >= LogLevel.Warning) return false;
 | 
			
		||||
                if (string.IsNullOrEmpty(logMsg.Message)) return false;
 | 
			
		||||
                else return true;
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            options.MessageFormat = (logMsg) =>
 | 
			
		||||
            {
 | 
			
		||||
                //如果不是LoggingMonitor日志才格式化
 | 
			
		||||
                if (logMsg.LogName != "System.Logging.LoggingMonitor")
 | 
			
		||||
                {
 | 
			
		||||
                    var stringBuilder = new StringBuilder();
 | 
			
		||||
                    stringBuilder.AppendLine("【日志级别】:" + logMsg.LogLevel);
 | 
			
		||||
                    stringBuilder.AppendLine("【日志类名】:" + logMsg.LogName);
 | 
			
		||||
                    stringBuilder.AppendLine("【日志时间】:" + DateTime.Now.ToDefaultDateTimeFormat());
 | 
			
		||||
                    stringBuilder.AppendLine("【日志内容】:" + logMsg.Message);
 | 
			
		||||
                    if (logMsg.Exception != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        stringBuilder.AppendLine("【异常信息】:" + logMsg.Exception);
 | 
			
		||||
                    }
 | 
			
		||||
                    return stringBuilder.ToString();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return logMsg.Message;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            options.WriteHandler = (logMsg, scopeProvider, writer, fmtMsg, opt) =>
 | 
			
		||||
            {
 | 
			
		||||
                ConsoleColor consoleColor = ConsoleColor.White;
 | 
			
		||||
                switch (logMsg.LogLevel)
 | 
			
		||||
                {
 | 
			
		||||
                    case LogLevel.Information:
 | 
			
		||||
                        consoleColor = ConsoleColor.DarkGreen;
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                    case LogLevel.Warning:
 | 
			
		||||
                        consoleColor = ConsoleColor.DarkYellow;
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                    case LogLevel.Error:
 | 
			
		||||
                        consoleColor = ConsoleColor.DarkRed;
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                writer.WriteWithColor(fmtMsg, ConsoleColor.Black, consoleColor);
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        #endregion 控制台美化
 | 
			
		||||
 | 
			
		||||
        #region api日志
 | 
			
		||||
 | 
			
		||||
        //Monitor日志配置
 | 
			
		||||
        //services.AddMonitorLogging(options =>
 | 
			
		||||
        //{
 | 
			
		||||
        //    options.JsonIndented = true;// 是否美化 JSON
 | 
			
		||||
        //    options.GlobalEnabled = false;//全局启用
 | 
			
		||||
        //    options.ConfigureLogger((logger, logContext, context) =>
 | 
			
		||||
        //    {
 | 
			
		||||
        //        var httpContext = context.HttpContext;//获取httpContext
 | 
			
		||||
 | 
			
		||||
        //        //获取客户端信息
 | 
			
		||||
        //        var client = App.GetService<IAppService>().UserAgent;
 | 
			
		||||
        //        // 获取控制器/操作描述器
 | 
			
		||||
        //        var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
 | 
			
		||||
        //        //操作名称默认是控制器名加方法名,自定义操作名称要在action上加Description特性
 | 
			
		||||
        //        var option = $"{controllerActionDescriptor.ControllerName}/{controllerActionDescriptor.ActionName}";
 | 
			
		||||
 | 
			
		||||
        //        var desc = App.CreateLocalizerByType(controllerActionDescriptor.ControllerTypeInfo.AsType())[controllerActionDescriptor.MethodInfo.Name];
 | 
			
		||||
        //        //获取特性
 | 
			
		||||
        //        option = desc.Value;//则将操作名称赋值为控制器上写的title
 | 
			
		||||
 | 
			
		||||
        //        logContext.Set(LoggingConst.CateGory, option);//传操作名称
 | 
			
		||||
        //        logContext.Set(LoggingConst.Operation, option);//传操作名称
 | 
			
		||||
        //        logContext.Set(LoggingConst.Client, client);//客户端信息
 | 
			
		||||
        //        logContext.Set(LoggingConst.Path, httpContext.Request.Path.Value);//请求地址
 | 
			
		||||
        //        logContext.Set(LoggingConst.Method, httpContext.Request.Method);//请求方法
 | 
			
		||||
        //    });
 | 
			
		||||
        //});
 | 
			
		||||
 | 
			
		||||
        //日志写入数据库配置
 | 
			
		||||
        services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>
 | 
			
		||||
        {
 | 
			
		||||
            options.WriteFilter = (logMsg) =>
 | 
			
		||||
            {
 | 
			
		||||
                return logMsg.LogName == "System.Logging.RequestAudit";
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        #endregion api日志
 | 
			
		||||
 | 
			
		||||
        //已添加AddOptions
 | 
			
		||||
        // 增加多语言支持配置信息
 | 
			
		||||
@@ -301,7 +206,7 @@ public class Startup : AppStartup
 | 
			
		||||
        var certificate = new X509Certificate2("ThingsGateway.pfx", "ThingsGateway", X509KeyStorageFlags.EphemeralKeySet);
 | 
			
		||||
#endif
 | 
			
		||||
        services.AddDataProtection()
 | 
			
		||||
            .PersistKeysToFileSystem(new DirectoryInfo("keys"))
 | 
			
		||||
            .PersistKeysToFileSystem(new DirectoryInfo("Keys"))
 | 
			
		||||
            .ProtectKeysWithCertificate(certificate)
 | 
			
		||||
            .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
 | 
			
		||||
            {
 | 
			
		||||
@@ -369,7 +274,7 @@ public class Startup : AppStartup
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // 特定文件类型(文件后缀)处理
 | 
			
		||||
        var contentTypeProvider = GetFileExtensionContentTypeProvider();
 | 
			
		||||
        var contentTypeProvider = FS.GetFileExtensionContentTypeProvider();
 | 
			
		||||
        // contentTypeProvider.Mappings[".文件后缀"] = "MIME 类型";
 | 
			
		||||
        app.UseStaticFiles(new StaticFileOptions
 | 
			
		||||
        {
 | 
			
		||||
@@ -413,32 +318,4 @@ public class Startup : AppStartup
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 初始化文件 ContentType 提供器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    private static FileExtensionContentTypeProvider GetFileExtensionContentTypeProvider()
 | 
			
		||||
    {
 | 
			
		||||
        var fileExtensionProvider = new FileExtensionContentTypeProvider();
 | 
			
		||||
        fileExtensionProvider.Mappings[".iec"] = "application/octet-stream";
 | 
			
		||||
        fileExtensionProvider.Mappings[".patch"] = "application/octet-stream";
 | 
			
		||||
        fileExtensionProvider.Mappings[".apk"] = "application/vnd.android.package-archive";
 | 
			
		||||
        fileExtensionProvider.Mappings[".pem"] = "application/x-x509-user-cert";
 | 
			
		||||
        fileExtensionProvider.Mappings[".gzip"] = "application/x-gzip";
 | 
			
		||||
        fileExtensionProvider.Mappings[".7zip"] = "application/zip";
 | 
			
		||||
        fileExtensionProvider.Mappings[".jpg2"] = "image/jp2";
 | 
			
		||||
        fileExtensionProvider.Mappings[".et"] = "application/kset";
 | 
			
		||||
        fileExtensionProvider.Mappings[".dps"] = "application/ksdps";
 | 
			
		||||
        fileExtensionProvider.Mappings[".cdr"] = "application/x-coreldraw";
 | 
			
		||||
        fileExtensionProvider.Mappings[".shtml"] = "text/html";
 | 
			
		||||
        fileExtensionProvider.Mappings[".php"] = "application/x-httpd-php";
 | 
			
		||||
        fileExtensionProvider.Mappings[".php3"] = "application/x-httpd-php";
 | 
			
		||||
        fileExtensionProvider.Mappings[".php4"] = "application/x-httpd-php";
 | 
			
		||||
        fileExtensionProvider.Mappings[".phtml"] = "application/x-httpd-php";
 | 
			
		||||
        fileExtensionProvider.Mappings[".pcd"] = "image/x-photo-cd";
 | 
			
		||||
        fileExtensionProvider.Mappings[".bcmap"] = "application/octet-stream";
 | 
			
		||||
        fileExtensionProvider.Mappings[".properties"] = "application/octet-stream";
 | 
			
		||||
        fileExtensionProvider.Mappings[".m3u8"] = "application/x-mpegURL";
 | 
			
		||||
        return fileExtensionProvider;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
		<TargetFrameworks>net8.0;net9.0;</TargetFrameworks>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
	<Import Project="Admin.targets" Condition=" '$(Configuration)' != 'Debug' " />
 | 
			
		||||
	<!--<Import Project="Admin.targets" Condition=" '$(Configuration)' != 'Debug' " />-->
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
 | 
			
		||||
		<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
		<!--<PlatformTarget>x86</PlatformTarget>-->
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<ProjectReference Include="..\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
@@ -45,9 +45,7 @@
 | 
			
		||||
		</Content>
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<PackageReference Include="Microsoft.Data.Sqlite" Version="$(NET9Version)" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
	<!--安装服务守护-->
 | 
			
		||||
	<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user