diff --git a/Directory.Build.props b/Directory.Build.props
index fca2783..e95d177 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,7 +1,7 @@
-
-
+
+
-
+
diff --git a/TIKU-BACKEND.slnx b/TIKU-BACKEND.slnx
index 1071a5c..bf5db79 100644
--- a/TIKU-BACKEND.slnx
+++ b/TIKU-BACKEND.slnx
@@ -1,14 +1,14 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tiku.Api/ApiProgramMarker.cs b/Tiku.Api/ApiProgramMarker.cs
index c563f59..46142b7 100644
--- a/Tiku.Api/ApiProgramMarker.cs
+++ b/Tiku.Api/ApiProgramMarker.cs
@@ -1,3 +1,3 @@
namespace Tiku.Api;
-public sealed class ApiProgramMarker;
+public sealed class ApiProgramMarker;
\ No newline at end of file
diff --git a/Tiku.Api/Background/DevelopmentTenantDomainLifecycleHostedService.cs b/Tiku.Api/Background/DevelopmentTenantDomainLifecycleHostedService.cs
index 9078077..a439145 100644
--- a/Tiku.Api/Background/DevelopmentTenantDomainLifecycleHostedService.cs
+++ b/Tiku.Api/Background/DevelopmentTenantDomainLifecycleHostedService.cs
@@ -13,10 +13,7 @@ internal sealed class DevelopmentTenantDomainLifecycleHostedService(
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
- if (!options.EnableDevelopmentLocalhostBypass)
- {
- return;
- }
+ if (!options.EnableDevelopmentLocalhostBypass) return;
var interval = TimeSpan.FromSeconds(Math.Clamp(options.PollSeconds, 1, 3600));
while (!stoppingToken.IsCancellationRequested)
@@ -30,9 +27,7 @@ internal sealed class DevelopmentTenantDomainLifecycleHostedService(
.GetRequiredService()
.ProcessPendingAsync(stoppingToken);
if (processed > 0)
- {
logger.LogInformation("Processed {DomainCount} pending Development tenant domains.", processed);
- }
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
@@ -46,4 +41,4 @@ internal sealed class DevelopmentTenantDomainLifecycleHostedService(
await Task.Delay(interval, stoppingToken);
}
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Caching/TenantPublicCacheInvalidator.cs b/Tiku.Api/Caching/TenantPublicCacheInvalidator.cs
index 7d9d8f5..9cce2bd 100644
--- a/Tiku.Api/Caching/TenantPublicCacheInvalidator.cs
+++ b/Tiku.Api/Caching/TenantPublicCacheInvalidator.cs
@@ -6,9 +6,13 @@ namespace Tiku.Api.Caching;
internal sealed class TenantPublicCacheInvalidator(IOutputCacheStore outputCacheStore)
: ITenantPublicCacheInvalidator
{
- public ValueTask InvalidateCoreAsync(Guid tenantId, CancellationToken cancellationToken) =>
- outputCacheStore.EvictByTagAsync($"tenant:{tenantId:N}", cancellationToken);
-
- public async Task InvalidateAsync(Guid tenantId, CancellationToken cancellationToken = default) =>
+ public async Task InvalidateAsync(Guid tenantId, CancellationToken cancellationToken = default)
+ {
await InvalidateCoreAsync(tenantId, cancellationToken);
-}
+ }
+
+ public ValueTask InvalidateCoreAsync(Guid tenantId, CancellationToken cancellationToken)
+ {
+ return outputCacheStore.EvictByTagAsync($"tenant:{tenantId:N}", cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Caching/TenantPublicOutputCachePolicy.cs b/Tiku.Api/Caching/TenantPublicOutputCachePolicy.cs
index 9ff7feb..1008ee2 100644
--- a/Tiku.Api/Caching/TenantPublicOutputCachePolicy.cs
+++ b/Tiku.Api/Caching/TenantPublicOutputCachePolicy.cs
@@ -30,8 +30,10 @@ internal sealed class TenantPublicOutputCachePolicy : IOutputCachePolicy
return ValueTask.CompletedTask;
}
- public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken) =>
- ValueTask.CompletedTask;
+ public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken)
+ {
+ return ValueTask.CompletedTask;
+ }
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellationToken)
{
@@ -39,10 +41,8 @@ internal sealed class TenantPublicOutputCachePolicy : IOutputCachePolicy
if (response.StatusCode != StatusCodes.Status200OK ||
!StringValues.IsNullOrEmpty(response.Headers.SetCookie) ||
context.HttpContext.User.Identity?.IsAuthenticated == true)
- {
context.AllowCacheStorage = false;
- }
return ValueTask.CompletedTask;
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/ApiPresentationExtensions.cs b/Tiku.Api/Configuration/ApiPresentationExtensions.cs
index 06b6ded..d2d74fd 100644
--- a/Tiku.Api/Configuration/ApiPresentationExtensions.cs
+++ b/Tiku.Api/Configuration/ApiPresentationExtensions.cs
@@ -9,7 +9,7 @@ internal static class ApiPresentationExtensions
internal static IServiceCollection AddApiPresentation(this IServiceCollection services)
{
services.AddControllers(options =>
- options.Conventions.Add(new EndpointAuthorizationMetadataConvention()))
+ options.Conventions.Add(new EndpointAuthorizationMetadataConvention()))
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
@@ -23,4 +23,4 @@ internal static class ApiPresentationExtensions
return services;
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs b/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs
index 6f2d687..b255284 100644
--- a/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs
+++ b/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs
@@ -42,4 +42,4 @@ public static class ApplicationBuilderExtensions
return app;
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/AuthenticationExtensions.cs b/Tiku.Api/Configuration/AuthenticationExtensions.cs
index 464bd20..66a2980 100644
--- a/Tiku.Api/Configuration/AuthenticationExtensions.cs
+++ b/Tiku.Api/Configuration/AuthenticationExtensions.cs
@@ -3,6 +3,7 @@ using System.IdentityModel.Tokens.Jwt;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Tiku.Api.Options;
using Tiku.Api.Security;
@@ -98,9 +99,7 @@ internal static class AuthenticationExtensions
if (string.IsNullOrWhiteSpace(context.Request.Headers.Authorization) &&
IsSameOriginBrowserRequest(context.Request) &&
context.Request.Cookies.TryGetValue(BrowserAuthOptions.AccessCookie, out var accessToken))
- {
context.Token = accessToken;
- }
return Task.CompletedTask;
},
OnTokenValidated = ValidateTokenAsync,
@@ -111,16 +110,11 @@ internal static class AuthenticationExtensions
private static bool IsSameOriginBrowserRequest(HttpRequest request)
{
var source = request.Headers.Origin.ToString();
- if (string.IsNullOrWhiteSpace(source))
- {
- source = request.Headers.Referer.ToString();
- }
+ if (string.IsNullOrWhiteSpace(source)) source = request.Headers.Referer.ToString();
if (Uri.TryCreate(source, UriKind.Absolute, out var uri))
- {
return string.Equals(uri.Scheme, request.Scheme, StringComparison.OrdinalIgnoreCase) &&
string.Equals(uri.Authority, request.Host.Value, StringComparison.OrdinalIgnoreCase);
- }
return string.Equals(
request.Headers["Sec-Fetch-Site"].ToString(),
@@ -154,14 +148,14 @@ internal static class AuthenticationExtensions
var tenantId = Guid.TryParse(tenantIdValue, out var parsedTenantId)
? parsedTenantId
: (Guid?)null;
- if (realm is null || (realm == AuthRealm.Tenant) != tenantId.HasValue)
+ if (realm is null || realm == AuthRealm.Tenant != tenantId.HasValue)
{
context.Fail("Token scope and tenant claims are inconsistent.");
return;
}
var resolutionOptions = context.HttpContext.RequestServices
- .GetRequiredService>().Value;
+ .GetRequiredService>().Value;
var requestHost = context.HttpContext.Request.Host.Host.Trim().TrimEnd('.');
var isPlatformHost = resolutionOptions.PlatformHosts.Any(host =>
string.Equals(host.Trim().TrimEnd('.'), requestHost, StringComparison.OrdinalIgnoreCase));
@@ -218,10 +212,7 @@ internal static class AuthenticationExtensions
private static async Task WriteTenantConflictChallengeAsync(JwtBearerChallengeContext context)
{
- if (!context.HttpContext.Items.ContainsKey("tenant_context_conflict"))
- {
- return;
- }
+ if (!context.HttpContext.Items.ContainsKey("tenant_context_conflict")) return;
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status403Forbidden;
@@ -232,4 +223,4 @@ internal static class AuthenticationExtensions
Extensions = { ["code"] = "tenant_context_conflict" }
});
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/DataProtectionExtensions.cs b/Tiku.Api/Configuration/DataProtectionExtensions.cs
index d5eee4b..c96fa4f 100644
--- a/Tiku.Api/Configuration/DataProtectionExtensions.cs
+++ b/Tiku.Api/Configuration/DataProtectionExtensions.cs
@@ -25,20 +25,15 @@ internal static class DataProtectionExtensions
.Get() ?? new DataProtectionKeyRingOptions();
ApplyEnvironmentOverrides(keyRingOptions, configuration);
if (!DataProtectionKeyRingOptions.BeValid(keyRingOptions, requireProtectedKeys))
- {
throw new InvalidOperationException(
"Data Protection requires an application name and, outside Development, an X509 certificate path.");
- }
var dataProtection = services
.AddDataProtection()
.SetApplicationName(keyRingOptions.ApplicationName.Trim())
.PersistKeysToDbContext();
var certificate = keyRingOptions.LoadCertificate(requireProtectedKeys);
- if (certificate is not null)
- {
- dataProtection.ProtectKeysWithCertificate(certificate);
- }
+ if (certificate is not null) dataProtection.ProtectKeysWithCertificate(certificate);
return services;
}
@@ -54,4 +49,4 @@ internal static class DataProtectionExtensions
options.CertificatePassword =
configuration["TIKU_DATA_PROTECTION_CERTIFICATE_PASSWORD"] ?? options.CertificatePassword;
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/DependencyInjection.cs b/Tiku.Api/Configuration/DependencyInjection.cs
index 9ce5326..8f44516 100644
--- a/Tiku.Api/Configuration/DependencyInjection.cs
+++ b/Tiku.Api/Configuration/DependencyInjection.cs
@@ -1,13 +1,14 @@
-using Serilog;
-using Tiku.Application;
-using Tiku.Infrastructure;
-using Tiku.Infrastructure.Security;
-using Tiku.Api.Caching;
-using Microsoft.AspNetCore.ResponseCompression;
using System.IO.Compression;
+using Microsoft.AspNetCore.ResponseCompression;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Serilog;
+using Tiku.Api.Caching;
+using Tiku.Api.Options;
+using Tiku.Application;
using Tiku.Application.Security;
using Tiku.Application.Tenancy;
-using Microsoft.Extensions.DependencyInjection.Extensions;
+using Tiku.Infrastructure;
+using Tiku.Infrastructure.Security;
namespace Tiku.Api.Configuration;
@@ -16,10 +17,10 @@ public static class DependencyInjection
public static WebApplicationBuilder AddApiServices(this WebApplicationBuilder builder)
{
builder.Services.AddSerilog((services, configuration) => configuration
- .ReadFrom.Configuration(builder.Configuration)
- .ReadFrom.Services(services)
- .Enrich.FromLogContext(),
- preserveStaticLogger: true);
+ .ReadFrom.Configuration(builder.Configuration)
+ .ReadFrom.Services(services)
+ .Enrich.FromLogContext(),
+ true);
builder.Services.AddApiPresentation();
builder.Services.AddHealthChecks();
@@ -28,11 +29,12 @@ public static class DependencyInjection
builder.Services.AddNetworkConfiguration(builder.Configuration, builder.Environment);
builder.Services.AddApiRateLimiting(builder.Configuration);
- var connectionString = Options.OptionsValidation.ResolveDatabaseConnectionString(
+ var connectionString = OptionsValidation.ResolveDatabaseConnectionString(
builder.Configuration,
builder.Environment.IsDevelopment());
builder.Services.AddInfrastructure(connectionString);
- var redisConnectionString = builder.Configuration.GetConnectionString("Redis") ?? builder.Configuration["REDIS_URL"];
+ var redisConnectionString =
+ builder.Configuration.GetConnectionString("Redis") ?? builder.Configuration["REDIS_URL"];
builder.Services.AddOptions()
.Configure(options => options.ConnectionString = redisConnectionString ?? string.Empty)
.Validate(
@@ -46,14 +48,10 @@ public static class DependencyInjection
"Authorization cache durations must be positive and jitter must be between 0 and 50 percent.")
.ValidateOnStart();
if (!string.IsNullOrWhiteSpace(redisConnectionString))
- {
builder.Services.AddRedisSecurity(redisConnectionString, builder.Environment.EnvironmentName);
- }
else if (builder.Environment.IsProduction())
- {
throw new InvalidOperationException(
"Redis is required in Production. Configure ConnectionStrings:Redis or REDIS_URL.");
- }
builder.Services.AddOutputCache(options =>
{
@@ -63,13 +61,11 @@ public static class DependencyInjection
builder.Services.RemoveAll();
builder.Services.AddSingleton();
if (builder.Environment.IsProduction() && !string.IsNullOrWhiteSpace(redisConnectionString))
- {
builder.Services.AddStackExchangeRedisOutputCache(options =>
{
options.Configuration = redisConnectionString;
options.InstanceName = $"tiku:{builder.Environment.EnvironmentName.ToLowerInvariant()}:output:";
});
- }
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
@@ -77,7 +73,8 @@ public static class DependencyInjection
options.Providers.Add();
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(["application/json"]);
});
- builder.Services.Configure(options => options.Level = CompressionLevel.Fastest);
+ builder.Services.Configure(options =>
+ options.Level = CompressionLevel.Fastest);
builder.Services.Configure(options => options.Level = CompressionLevel.Fastest);
builder.Services.AddApiDataProtection(builder.Configuration, builder.Environment);
builder.Services.AddExternalServiceOptions(builder.Configuration, builder.Environment);
@@ -85,4 +82,4 @@ public static class DependencyInjection
return builder;
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/ExternalServiceOptionsExtensions.cs b/Tiku.Api/Configuration/ExternalServiceOptionsExtensions.cs
index e954624..ad0ac08 100644
--- a/Tiku.Api/Configuration/ExternalServiceOptionsExtensions.cs
+++ b/Tiku.Api/Configuration/ExternalServiceOptionsExtensions.cs
@@ -1,7 +1,9 @@
+using Microsoft.Extensions.Options;
using Tiku.Application.Auth;
+using Tiku.Application.Storage;
+using Tiku.Infrastructure.Assets;
using Tiku.Infrastructure.Commerce;
using Tiku.Infrastructure.Storage;
-using Tiku.Infrastructure.Assets;
namespace Tiku.Api.Configuration;
@@ -54,21 +56,21 @@ internal static class ExternalServiceOptionsExtensions
services.AddOptions()
.Validate(
options => !environment.IsProduction() ||
- options.DefaultProvider == Tiku.Application.Storage.ObjectStorageProviders.AliyunOss,
+ options.DefaultProvider == ObjectStorageProviders.AliyunOss,
"Production managed storage must use the configured Aliyun OSS provider.")
.ValidateOnStart();
services.AddOptions()
- .Validate>(
+ .Validate>(
(aliyun, storage) =>
!environment.IsProduction() ||
- storage.Value.DefaultProvider != Tiku.Application.Storage.ObjectStorageProviders.AliyunOss ||
+ storage.Value.DefaultProvider != ObjectStorageProviders.AliyunOss ||
aliyun.IsConfigured,
"Aliyun OSS credentials and region or endpoint are required when it is the default provider.")
.ValidateOnStart();
services.AddOptions()
.Bind(configuration.GetSection(ClamAvOptions.SectionName))
.Validate(ClamAvOptions.BeValid, "ClamAV settings are invalid.")
- .Validate>(
+ .Validate>(
(clamAv, storage) => clamAv.StreamMaxLength >= storage.Value.MaxUploadBytes,
"ClamAV StreamMaxLength must be greater than or equal to the storage max upload size.")
.ValidateOnStart();
@@ -104,8 +106,10 @@ internal static class ExternalServiceOptionsExtensions
return services;
}
- private static string[] SplitLegacyList(string? value, string[] fallback) =>
- string.IsNullOrWhiteSpace(value)
+ private static string[] SplitLegacyList(string? value, string[] fallback)
+ {
+ return string.IsNullOrWhiteSpace(value)
? fallback
: value.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
-}
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/NetworkConfigurationExtensions.cs b/Tiku.Api/Configuration/NetworkConfigurationExtensions.cs
index 2361ee4..6f1df3f 100644
--- a/Tiku.Api/Configuration/NetworkConfigurationExtensions.cs
+++ b/Tiku.Api/Configuration/NetworkConfigurationExtensions.cs
@@ -2,8 +2,8 @@ using System.Net;
using Microsoft.AspNetCore.HttpOverrides;
using Tiku.Api.Background;
using Tiku.Api.Options;
-using Tiku.Application.Tenancy;
using Tiku.Application.PlatformAdmin;
+using Tiku.Application.Tenancy;
namespace Tiku.Api.Configuration;
@@ -17,7 +17,8 @@ internal static class NetworkConfigurationExtensions
services.AddOptions()
.Bind(configuration.GetSection(TenantResolutionOptions.SectionName))
.Validate(
- options => OptionsValidation.BeValidTenantResolutionOptions(options, configuration, environment.IsProduction()),
+ options => OptionsValidation.BeValidTenantResolutionOptions(options, configuration,
+ environment.IsProduction()),
"Production requires formal platform hosts, non-wildcard AllowedHosts, and trusted proxy addresses.")
.ValidateOnStart();
services.Configure(options =>
@@ -34,22 +35,15 @@ internal static class NetworkConfigurationExtensions
.GetSection(TenantResolutionOptions.SectionName)
.Get() ?? new TenantResolutionOptions();
foreach (var address in resolution.TrustedProxyAddresses)
- {
if (IPAddress.TryParse(address, out var proxy))
- {
options.KnownProxies.Add(proxy);
- }
- }
});
services.AddOptions()
.Bind(configuration.GetSection("TenantDomains"))
.Validate(options => environment.IsDevelopment() || !options.EnableDevelopmentLocalhostBypass,
"The .localhost domain lifecycle bypass can only be enabled in Development.")
.ValidateOnStart();
- if (environment.IsDevelopment())
- {
- services.AddHostedService();
- }
+ if (environment.IsDevelopment()) services.AddHostedService();
services.AddOptions()
.Bind(configuration.GetSection(TenantProvisioningOptions.SectionName))
.Validate(options => !string.IsNullOrWhiteSpace(options.DefaultBaseOfferingCode) &&
@@ -57,17 +51,15 @@ internal static class NetworkConfigurationExtensions
options.OwnerActivationMinutes is >= 5 and <= 1440 &&
options.OwnerActivationUrlTemplate.Contains("{host}", StringComparison.Ordinal) &&
Uri.TryCreate(
- options.OwnerActivationUrlTemplate.Replace("{host}", "tenant.example.com", StringComparison.Ordinal),
+ options.OwnerActivationUrlTemplate.Replace("{host}", "tenant.example.com",
+ StringComparison.Ordinal),
UriKind.Absolute,
out var activationOrigin) &&
activationOrigin.Scheme == Uri.UriSchemeHttps &&
ValidateDevelopmentActivationTemplate(options, environment.IsDevelopment()),
"Tenant provisioning requires a default offering code, valid trial/activation durations, an HTTPS owner activation URL template, and permits an HTTP template only for Development .localhost sites.")
.ValidateOnStart();
- if (environment.IsProduction())
- {
- services.AddHostedService();
- }
+ if (environment.IsProduction()) services.AddHostedService();
services.AddOptions()
.Bind(configuration.GetSection(CorsOptions.SectionName))
@@ -90,19 +82,13 @@ internal static class NetworkConfigurationExtensions
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToArray();
- if (origins.Length > 0)
- {
- policy.WithOrigins(origins);
- }
+ if (origins.Length > 0) policy.WithOrigins(origins);
policy
.WithHeaders(corsOptions.AllowedHeaders)
.WithMethods(corsOptions.AllowedMethods);
- if (corsOptions.AllowCredentials)
- {
- policy.AllowCredentials();
- }
+ if (corsOptions.AllowCredentials) policy.AllowCredentials();
});
});
@@ -113,10 +99,7 @@ internal static class NetworkConfigurationExtensions
TenantProvisioningOptions options,
bool isDevelopment)
{
- if (string.IsNullOrWhiteSpace(options.DevelopmentLocalhostOwnerActivationUrlTemplate))
- {
- return true;
- }
+ if (string.IsNullOrWhiteSpace(options.DevelopmentLocalhostOwnerActivationUrlTemplate)) return true;
return isDevelopment &&
options.DevelopmentLocalhostOwnerActivationUrlTemplate.Contains("{host}", StringComparison.Ordinal) &&
@@ -128,4 +111,4 @@ internal static class NetworkConfigurationExtensions
(developmentOrigin.Scheme == Uri.UriSchemeHttp ||
developmentOrigin.Scheme == Uri.UriSchemeHttps);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/ObservabilityExtensions.cs b/Tiku.Api/Configuration/ObservabilityExtensions.cs
index f540393..3ccec6e 100644
--- a/Tiku.Api/Configuration/ObservabilityExtensions.cs
+++ b/Tiku.Api/Configuration/ObservabilityExtensions.cs
@@ -18,31 +18,30 @@ internal static class ObservabilityExtensions
services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddService(
- serviceName: environment.ApplicationName,
+ environment.ApplicationName,
serviceVersion: typeof(ObservabilityExtensions).Assembly.GetName().Version?.ToString()))
.WithTracing(tracing => tracing
.AddAspNetCoreInstrumentation(options =>
options.Filter = context => !context.Request.Path.StartsWithSegments("/api/system/health"))
.AddHttpClientInstrumentation()
.AddSource("Npgsql")
- .ApplyIf(hasOtlpEndpoint, builder => builder.AddOtlpExporter(options => options.Endpoint = endpointUri!)))
+ .ApplyIf(hasOtlpEndpoint,
+ builder => builder.AddOtlpExporter(options => options.Endpoint = endpointUri!)))
.WithMetrics(metrics => metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddMeter(DatabasePerformanceTelemetry.MeterName, WorkerTelemetry.MeterName,
AuthorizationCacheTelemetry.MeterName, "Tiku.Security.Redis", "Tiku.Learning", "Npgsql")
- .ApplyIf(hasOtlpEndpoint, builder => builder.AddOtlpExporter(options => options.Endpoint = endpointUri!)));
+ .ApplyIf(hasOtlpEndpoint,
+ builder => builder.AddOtlpExporter(options => options.Endpoint = endpointUri!)));
return services;
}
private static TBuilder ApplyIf(this TBuilder builder, bool condition, Action configure)
{
- if (condition)
- {
- configure(builder);
- }
+ if (condition) configure(builder);
return builder;
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/RateLimitingExtensions.cs b/Tiku.Api/Configuration/RateLimitingExtensions.cs
index 767c1b4..e49df58 100644
--- a/Tiku.Api/Configuration/RateLimitingExtensions.cs
+++ b/Tiku.Api/Configuration/RateLimitingExtensions.cs
@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Tiku.Api.Middleware;
using Tiku.Api.Options;
-using Tiku.Application.Auth;
using Tiku.Application.Security;
namespace Tiku.Api.Configuration;
@@ -34,7 +33,6 @@ internal static class RateLimitingExtensions
{
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
if (rateLimitOptions.Enabled)
- {
options.GlobalLimiter = PartitionedRateLimiter.Create(httpContext =>
{
var partitionKey =
@@ -49,7 +47,6 @@ internal static class RateLimitingExtensions
rateLimitOptions.QueueLimit,
rateLimitOptions.WindowSeconds));
});
- }
options.AddPolicy(
AuthRateLimitPolicies.Password,
@@ -76,8 +73,9 @@ internal static class RateLimitingExtensions
private static FixedWindowRateLimiterOptions CreateLimiterOptions(
int permitLimit,
int queueLimit,
- int windowSeconds) =>
- new()
+ int windowSeconds)
+ {
+ return new FixedWindowRateLimiterOptions
{
AutoReplenishment = true,
PermitLimit = permitLimit,
@@ -85,15 +83,14 @@ internal static class RateLimitingExtensions
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
Window = TimeSpan.FromSeconds(windowSeconds)
};
+ }
private static async ValueTask WriteRateLimitProblemAsync(
OnRejectedContext context,
CancellationToken cancellationToken)
{
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
- {
context.HttpContext.Response.Headers.RetryAfter = ((int)retryAfter.TotalSeconds).ToString();
- }
var problem = new ProblemDetails
{
@@ -107,4 +104,4 @@ internal static class RateLimitingExtensions
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
await context.HttpContext.Response.WriteAsJsonAsync(problem, cancellationToken);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Configuration/TenantProvisioningStartupValidator.cs b/Tiku.Api/Configuration/TenantProvisioningStartupValidator.cs
index 19b4c4e..4d5fe11 100644
--- a/Tiku.Api/Configuration/TenantProvisioningStartupValidator.cs
+++ b/Tiku.Api/Configuration/TenantProvisioningStartupValidator.cs
@@ -41,13 +41,14 @@ internal sealed class TenantProvisioningStartupValidator(
cancellationToken);
if (!available)
- {
throw new InvalidOperationException(
$"TenantProvisioning:DefaultBaseOfferingCode '{offeringCode}' does not resolve to an effective published base offering version.");
- }
logger.LogInformation("Validated default tenant provisioning offering {OfferingCode}", offeringCode);
}
- public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
-}
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/AssetAccessDtos.cs b/Tiku.Api/Contracts/AssetAccessDtos.cs
index 880ec51..cc3ed66 100644
--- a/Tiku.Api/Contracts/AssetAccessDtos.cs
+++ b/Tiku.Api/Contracts/AssetAccessDtos.cs
@@ -7,25 +7,25 @@ using Tiku.Domain.Content;
namespace Tiku.Api.Contracts;
///
-/// 资产访问签名查询参数。
+/// 资产访问签名查询参数。
///
public sealed class AssetAccessQueryDto
{
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
public string? TenantCode { get; set; }
///
- /// 有效期秒数。
+ /// 有效期秒数。
///
[Range(1, 7200)]
public int? ExpiresInSeconds { get; set; }
}
///
-/// 资产访问签名响应。
+/// 资产访问签名响应。
///
public sealed record AssetAccessResponseDto(
ContentAssetAccessSummaryDto Item,
@@ -47,7 +47,7 @@ public sealed record AssetAccessResponseDto(
}
///
-/// 内容资产访问摘要。
+/// 内容资产访问摘要。
///
public sealed record ContentAssetAccessSummaryDto(
Guid Id,
@@ -76,7 +76,7 @@ public sealed record ContentAssetAccessSummaryDto(
}
///
-/// 资产访问Principal请求 DTO。
+/// 资产访问Principal请求 DTO。
///
public sealed record AssetAccessPrincipalDto(
Guid? UserId,
@@ -84,7 +84,7 @@ public sealed record AssetAccessPrincipalDto(
bool HasSvip);
///
-/// SignedStorageUrl请求 DTO。
+/// SignedStorageUrl请求 DTO。
///
public sealed record SignedStorageUrlDto(
string Provider,
@@ -110,4 +110,4 @@ public sealed record SignedStorageUrlDto(
(int)signedUrl.ExpiresIn.TotalSeconds,
signedUrl.SignatureMode);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/AssetDtos.cs b/Tiku.Api/Contracts/AssetDtos.cs
index a1b7b3b..87790df 100644
--- a/Tiku.Api/Contracts/AssetDtos.cs
+++ b/Tiku.Api/Contracts/AssetDtos.cs
@@ -4,82 +4,82 @@ using Tiku.Application.Assets;
namespace Tiku.Api.Contracts;
///
-/// 资产查询参数。
+/// 资产查询参数。
///
public sealed class AssetQueryDto
{
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
public string? TenantCode { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
///
- /// 分类 ID。
+ /// 分类 ID。
///
public Guid? CategoryId { get; set; }
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
///
- /// 题目 ID。
+ /// 题目 ID。
///
public Guid? QuestionId { get; set; }
///
- /// 资产 ID。
+ /// 资产 ID。
///
public Guid? AssetId { get; set; }
///
- /// 资产类型。
+ /// 资产类型。
///
[StringLength(50)]
public string? AssetType { get; set; }
///
- /// 分类。
+ /// 分类。
///
[StringLength(100)]
public string? Category { get; set; }
///
- /// 资产键。
+ /// 资产键。
///
[StringLength(200)]
public string? AssetKey { get; set; }
///
- /// 关键字。
+ /// 关键字。
///
[StringLength(100)]
public string? Keyword { get; set; }
///
- /// 是否包含锁定资源。
+ /// 是否包含锁定资源。
///
public bool IncludeLocked { get; set; }
///
- /// 是否包含停用数据。
+ /// 是否包含停用数据。
///
public bool IncludeInactive { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
@@ -102,4 +102,4 @@ public sealed class AssetQueryDto
IncludeInactive,
Limit);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/AssetManagementDtos.cs b/Tiku.Api/Contracts/AssetManagementDtos.cs
index 615bac8..58aa3f1 100644
--- a/Tiku.Api/Contracts/AssetManagementDtos.cs
+++ b/Tiku.Api/Contracts/AssetManagementDtos.cs
@@ -6,128 +6,128 @@ using Tiku.Domain.Common;
namespace Tiku.Api.Contracts;
///
-/// 创建资产上传签名请求。
+/// 创建资产上传签名请求。
///
public sealed class AssetUploadSignDto
{
///
- /// 资产 ID。
+ /// 资产 ID。
///
public Guid? AssetId { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
///
- /// 分类 ID。
+ /// 分类 ID。
///
public Guid? CategoryId { get; set; }
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
///
- /// 资产键。
+ /// 资产键。
///
[StringLength(200)]
public string? AssetKey { get; set; }
///
- /// 标题。
+ /// 标题。
///
[StringLength(300)]
public string? Title { get; set; }
///
- /// 分类。
+ /// 分类。
///
[StringLength(100)]
public string? Category { get; set; }
///
- /// 说明。
+ /// 说明。
///
[StringLength(1000)]
public string? Description { get; set; }
///
- /// 文件名。
+ /// 文件名。
///
[Required]
[StringLength(500)]
public string FileName { get; set; } = string.Empty;
///
- /// MIME 类型。
+ /// MIME 类型。
///
[Required]
[StringLength(200)]
public string MimeType { get; set; } = string.Empty;
///
- /// 文件大小,单位为字节。
+ /// 文件大小,单位为字节。
///
[Range(0, long.MaxValue)]
public long? FileSizeBytes { get; set; }
///
- /// SHA-256 校验值。
+ /// SHA-256 校验值。
///
[RegularExpression("^[A-Fa-f0-9]{64}$")]
public string? ChecksumSha256 { get; set; }
///
- /// 资产类型。
+ /// 资产类型。
///
[StringLength(50)]
public string? AssetType { get; set; }
///
- /// 可见性。
+ /// 可见性。
///
[StringLength(50)]
public string? Visibility { get; set; }
///
- /// 是否公开。
+ /// 是否公开。
///
public bool? IsPublic { get; set; }
///
- /// 服务提供方。
+ /// 服务提供方。
///
[StringLength(50)]
public string? Provider { get; set; }
///
- /// 存储桶。
+ /// 存储桶。
///
[StringLength(200)]
public string? Bucket { get; set; }
///
- /// 对象存储键。
+ /// 对象存储键。
///
[StringLength(1000)]
public string? ObjectKey { get; set; }
///
- /// 有效期秒数。
+ /// 有效期秒数。
///
[Range(1, 3600)]
public int? ExpiresInSeconds { get; set; }
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -159,30 +159,30 @@ public sealed class AssetUploadSignDto
}
///
-/// 确认资产上传请求。
+/// 确认资产上传请求。
///
public sealed class AssetUploadConfirmDto
{
///
- /// 资产 ID。
+ /// 资产 ID。
///
[Required]
public Guid AssetId { get; set; }
///
- /// MIME 类型。
+ /// MIME 类型。
///
[StringLength(200)]
public string? MimeType { get; set; }
///
- /// 文件大小,单位为字节。
+ /// 文件大小,单位为字节。
///
[Range(0, long.MaxValue)]
public long? FileSizeBytes { get; set; }
///
- /// SHA-256 校验值。
+ /// SHA-256 校验值。
///
[RegularExpression("^[A-Fa-f0-9]{64}$")]
public string? ChecksumSha256 { get; set; }
@@ -194,116 +194,142 @@ public sealed class AssetUploadConfirmDto
}
///
-/// 新增或更新内容资产请求。
+/// 新增或更新内容资产请求。
///
public sealed class UpsertAssetDto
{
///
- /// 资产 ID。
+ /// 资产 ID。
///
public Guid? AssetId { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
+
///
- /// 分类 ID。
+ /// 分类 ID。
///
public Guid? CategoryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 资产键。
+ /// 资产键。
///
public string? AssetKey { get; set; }
+
///
- /// 标题。
+ /// 标题。
///
public string? Title { get; set; }
+
///
- /// 分类。
+ /// 分类。
///
public string? Category { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 文件名。
+ /// 文件名。
///
public string? FileName { get; set; }
+
///
- /// CDN 地址。
+ /// CDN 地址。
///
public string? CdnUrl { get; set; }
+
///
- /// 是否公开。
+ /// 是否公开。
///
public bool? IsPublic { get; set; }
+
///
- /// 资产类型。
+ /// 资产类型。
///
public string? AssetType { get; set; }
+
///
- /// 可见性。
+ /// 可见性。
///
public string? Visibility { get; set; }
+
///
- /// 状态。
+ /// 状态。
///
public string? Status { get; set; }
+
///
- /// 服务提供方。
+ /// 服务提供方。
///
public string? Provider { get; set; }
+
///
- /// 存储桶。
+ /// 存储桶。
///
public string? Bucket { get; set; }
+
///
- /// 对象存储键。
+ /// 对象存储键。
///
public string? ObjectKey { get; set; }
+
///
- /// MIME 类型。
+ /// MIME 类型。
///
public string? MimeType { get; set; }
+
///
- /// 文件大小,单位为字节。
+ /// 文件大小,单位为字节。
///
public long? FileSizeBytes { get; set; }
+
///
- /// SHA-256 校验值。
+ /// SHA-256 校验值。
///
public string? ChecksumSha256 { get; set; }
+
///
- /// 预览地址。
+ /// 预览地址。
///
public string? PreviewUrl { get; set; }
+
///
- /// 预览对象存储键。
+ /// 预览对象存储键。
///
public string? PreviewObjectKey { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 访问规则。
+ /// 访问规则。
///
public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -341,18 +367,18 @@ public sealed class UpsertAssetDto
}
///
-/// 创建资产访问签名请求。
+/// 创建资产访问签名请求。
///
public sealed class AssetAccessSignDto
{
///
- /// 资产 ID。
+ /// 资产 ID。
///
[Required]
public Guid AssetId { get; set; }
///
- /// 有效期秒数。
+ /// 有效期秒数。
///
[Range(60, 3600)]
public int? ExpiresInSeconds { get; set; }
@@ -364,62 +390,62 @@ public sealed class AssetAccessSignDto
}
///
-/// 资产管理查询参数。
+/// 资产管理查询参数。
///
public sealed class AssetManagementQueryDto
{
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
///
- /// 分类 ID。
+ /// 分类 ID。
///
public Guid? CategoryId { get; set; }
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
///
- /// 资产类型。
+ /// 资产类型。
///
[StringLength(50)]
public string? AssetType { get; set; }
///
- /// 分类。
+ /// 分类。
///
[StringLength(100)]
public string? Category { get; set; }
///
- /// 上传状态。
+ /// 上传状态。
///
[StringLength(50)]
public string? UploadStatus { get; set; }
///
- /// 安全扫描状态。
+ /// 安全扫描状态。
///
[StringLength(50)]
public string? SecurityScanStatus { get; set; }
///
- /// 关键字。
+ /// 关键字。
///
[StringLength(100)]
public string? Keyword { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
@@ -441,21 +467,22 @@ public sealed class AssetManagementQueryDto
}
///
-/// 资产事件查询参数。
+/// 资产事件查询参数。
///
public sealed class AssetEventQueryDto
{
///
- /// 资产 ID。
+ /// 资产 ID。
///
public Guid? AssetId { get; set; }
+
///
- /// 用户 ID。
+ /// 用户 ID。
///
public Guid? UserId { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
@@ -467,30 +494,30 @@ public sealed class AssetEventQueryDto
}
///
-/// 导入任务查询参数。
+/// 导入任务查询参数。
///
public sealed class ImportJobQueryDto
{
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 导入Type。
+ /// 导入Type。
///
[StringLength(50)]
public string? ImportType { get; set; }
///
- /// 来源格式。
+ /// 来源格式。
///
[StringLength(50)]
public string? SourceFormat { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
@@ -499,4 +526,4 @@ public sealed class ImportJobQueryDto
{
return new ImportJobFilter(Status, ImportType, SourceFormat, Limit);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/AuthDtos.cs b/Tiku.Api/Contracts/AuthDtos.cs
index a790b5f..2bf65e8 100644
--- a/Tiku.Api/Contracts/AuthDtos.cs
+++ b/Tiku.Api/Contracts/AuthDtos.cs
@@ -6,38 +6,39 @@ using Tiku.Domain.Tenancy;
namespace Tiku.Api.Contracts;
///
-/// PasswordLogin请求 DTO。
+/// PasswordLogin请求 DTO。
///
public sealed class PasswordLoginDto
{
///
- /// 认证域。
+ /// 认证域。
///
[Required]
public AuthRealm? Realm { get; set; }
+
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
[Description("平台控制域名登录时使用的租户代码;自定义域名登录可省略。")]
public string? TenantCode { get; set; }
///
- /// 账号标识。
+ /// 账号标识。
///
[StringLength(320)]
[Description("账号标识。tenant 可使用手机号,platform 可使用邮箱或用户名。")]
public string? Identifier { get; set; }
///
- /// 兼容手机号字段;新客户端应使用 identifier。
+ /// 兼容手机号字段;新客户端应使用 identifier。
///
[StringLength(32)]
[Description("兼容手机号字段;新客户端应使用 identifier。")]
public string? Phone { get; set; }
///
- /// 密码。
+ /// 密码。
///
[Required]
[StringLength(128, MinimumLength = 8)]
@@ -46,24 +47,25 @@ public sealed class PasswordLoginDto
}
///
-/// SmsLogin请求 DTO。
+/// SmsLogin请求 DTO。
///
public sealed class SmsLoginDto
{
///
- /// 认证域。
+ /// 认证域。
///
[Required]
public AuthRealm? Realm { get; set; }
+
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
[Description("平台控制域名登录时使用的租户代码;自定义域名登录可省略。")]
public string? TenantCode { get; set; }
///
- /// 手机号。
+ /// 手机号。
///
[Required]
[StringLength(32)]
@@ -71,7 +73,7 @@ public sealed class SmsLoginDto
public string Phone { get; set; } = string.Empty;
///
- /// 编码。
+ /// 编码。
///
[Required]
[StringLength(12, MinimumLength = 4)]
@@ -80,55 +82,56 @@ public sealed class SmsLoginDto
}
///
-/// 发送短信验证码请求。
+/// 发送短信验证码请求。
///
public sealed class SendSmsCodeDto
{
///
- /// 认证域。
+ /// 认证域。
///
[Required]
public AuthRealm? Realm { get; set; }
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
public string? TenantCode { get; set; }
///
- /// 手机号。
+ /// 手机号。
///
[Required]
[StringLength(32)]
public string Phone { get; set; } = string.Empty;
///
- /// 设备 ID。
+ /// 设备 ID。
///
[StringLength(256)]
public string? DeviceId { get; set; }
}
///
-/// O认证编码请求 DTO。
+/// O认证编码请求 DTO。
///
public sealed class OAuthCodeDto
{
///
- /// 认证域。
+ /// 认证域。
///
[Required]
public AuthRealm? Realm { get; set; }
+
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
[Description("平台控制域名登录时使用的租户代码;自定义域名登录可省略。")]
public string? TenantCode { get; set; }
///
- /// 编码。
+ /// 编码。
///
[Required]
[StringLength(512)]
@@ -136,13 +139,13 @@ public sealed class OAuthCodeDto
public string Code { get; set; } = string.Empty;
///
- /// 公开用户资料。
+ /// 公开用户资料。
///
[Description("客户端可提供的公开用户资料,不允许包含 token/secret。当前后端先保留模板字段,后续按业务需要逐步使用。")]
public Dictionary? Profile { get; set; }
///
- /// 语言。
+ /// 语言。
///
[StringLength(20)]
[Description("微信用户资料语言,例如 zh_CN。当前微信小程序登录不会使用该字段。")]
@@ -150,12 +153,12 @@ public sealed class OAuthCodeDto
}
///
-/// 刷新会话请求 DTO。
+/// 刷新会话请求 DTO。
///
public sealed class RefreshSessionDto
{
///
- /// 刷新令牌。
+ /// 刷新令牌。
///
[Required]
[StringLength(2048)]
@@ -164,42 +167,42 @@ public sealed class RefreshSessionDto
}
///
-/// Authenticated用户请求 DTO。
+/// Authenticated用户请求 DTO。
///
public sealed class AuthenticatedUserDto
{
///
- /// 用户 ID。
+ /// 用户 ID。
///
public Guid UserId { get; init; }
///
- /// 手机号。
+ /// 手机号。
///
public string? Phone { get; init; }
///
- /// 邮箱。
+ /// 邮箱。
///
public string? Email { get; init; }
///
- /// 名称。
+ /// 名称。
///
public string? Name { get; init; }
///
- /// 认证域。
+ /// 认证域。
///
public AuthRealm Realm { get; init; }
///
- /// 租户成员摘要。
+ /// 租户成员摘要。
///
public TenantMembershipSummary? Tenant { get; init; }
///
- /// 访问令牌和刷新令牌。
+ /// 访问令牌和刷新令牌。
///
public AuthTokenPair Tokens { get; init; } = default!;
@@ -219,50 +222,56 @@ public sealed class AuthenticatedUserDto
}
///
-/// 登录认证结果。
+/// 登录认证结果。
///
public sealed class AuthenticationResultDto
{
///
- /// 状态。
+ /// 状态。
///
public AuthenticationStatus Status { get; init; }
+
///
- /// 用户信息。
+ /// 用户信息。
///
public AuthenticatedUserDto? User { get; init; }
+
///
- /// 挑战令牌。
+ /// 挑战令牌。
///
public string? ChallengeToken { get; init; }
+
///
- /// 挑战令牌过期时间。
+ /// 挑战令牌过期时间。
///
public DateTimeOffset? ChallengeExpiresAt { get; init; }
- public static AuthenticationResultDto FromApplication(AuthenticationResult result) => new()
+ public static AuthenticationResultDto FromApplication(AuthenticationResult result)
{
- Status = result.Status,
- User = result.User is null ? null : AuthenticatedUserDto.FromApplication(result.User),
- ChallengeToken = result.ChallengeToken,
- ChallengeExpiresAt = result.ChallengeExpiresAt
- };
+ return new AuthenticationResultDto
+ {
+ Status = result.Status,
+ User = result.User is null ? null : AuthenticatedUserDto.FromApplication(result.User),
+ ChallengeToken = result.ChallengeToken,
+ ChallengeExpiresAt = result.ChallengeExpiresAt
+ };
+ }
}
///
-/// 首次登录必改密码请求。
+/// 首次登录必改密码请求。
///
public sealed class RequiredPasswordChangeDto
{
///
- /// 挑战令牌。
+ /// 挑战令牌。
///
[Required]
[StringLength(2048)]
public string ChallengeToken { get; set; } = string.Empty;
///
- /// 新密码。
+ /// 新密码。
///
[Required]
[StringLength(128, MinimumLength = 8)]
@@ -270,7 +279,7 @@ public sealed class RequiredPasswordChangeDto
}
///
-/// 请求租户短信密码重置验证码。
+/// 请求租户短信密码重置验证码。
///
public sealed class PasswordResetSmsSendDto
{
@@ -279,7 +288,8 @@ public sealed class PasswordResetSmsSendDto
public string? TenantCode { get; set; }
/// 绑定到账号的手机号。
- [Required, StringLength(32)]
+ [Required]
+ [StringLength(32)]
public string Phone { get; set; } = string.Empty;
/// 客户端设备标识,用于安全频控。
@@ -288,7 +298,7 @@ public sealed class PasswordResetSmsSendDto
}
///
-/// 使用短信验证码重置租户账号密码。
+/// 使用短信验证码重置租户账号密码。
///
public sealed class PasswordResetDto
{
@@ -297,48 +307,55 @@ public sealed class PasswordResetDto
public string? TenantCode { get; set; }
/// 绑定到账号的手机号。
- [Required, StringLength(32)]
+ [Required]
+ [StringLength(32)]
public string Phone { get; set; } = string.Empty;
/// 短信验证码。
- [Required, StringLength(12, MinimumLength = 4)]
+ [Required]
+ [StringLength(12, MinimumLength = 4)]
public string Code { get; set; } = string.Empty;
/// 符合当前密码策略的新密码。
- [Required, StringLength(128, MinimumLength = 8)]
+ [Required]
+ [StringLength(128, MinimumLength = 8)]
public string NewPassword { get; set; } = string.Empty;
}
///
-/// 已登录用户修改密码。
+/// 已登录用户修改密码。
///
public sealed class AuthenticatedPasswordChangeDto
{
/// 当前密码。
- [Required, StringLength(128, MinimumLength = 1)]
+ [Required]
+ [StringLength(128, MinimumLength = 1)]
public string CurrentPassword { get; set; } = string.Empty;
/// 符合当前密码策略的新密码。
- [Required, StringLength(128, MinimumLength = 8)]
+ [Required]
+ [StringLength(128, MinimumLength = 8)]
public string NewPassword { get; set; } = string.Empty;
}
///
-/// 管理员为用户设置一次性临时密码。
+/// 管理员为用户设置一次性临时密码。
///
public sealed class AdministrativePasswordResetDto
{
/// 符合当前密码策略的临时密码。
- [Required, StringLength(128, MinimumLength = 12)]
+ [Required]
+ [StringLength(128, MinimumLength = 12)]
public string TemporaryPassword { get; set; } = string.Empty;
/// 审计原因。
- [Required, StringLength(1000, MinimumLength = 3)]
+ [Required]
+ [StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
}
///
-/// 完成租户负责人一次性激活。
+/// 完成租户负责人一次性激活。
///
public sealed class CompleteOwnerActivationDto
{
@@ -347,12 +364,17 @@ public sealed class CompleteOwnerActivationDto
public Guid ActivationId { get; set; }
/// 只显示一次的激活令牌。
- [Required, StringLength(512, MinimumLength = 32)]
+ [Required]
+ [StringLength(512, MinimumLength = 32)]
public string Token { get; set; } = string.Empty;
/// 符合当前密码策略的新密码。
- [Required, StringLength(128, MinimumLength = 8)]
+ [Required]
+ [StringLength(128, MinimumLength = 8)]
public string NewPassword { get; set; } = string.Empty;
- public CompleteOwnerActivationRequest ToRequest() => new(ActivationId, Token, NewPassword);
-}
+ public CompleteOwnerActivationRequest ToRequest()
+ {
+ return new CompleteOwnerActivationRequest(ActivationId, Token, NewPassword);
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/BackgroundJobDtos.cs b/Tiku.Api/Contracts/BackgroundJobDtos.cs
index 57864e8..55c2f4b 100644
--- a/Tiku.Api/Contracts/BackgroundJobDtos.cs
+++ b/Tiku.Api/Contracts/BackgroundJobDtos.cs
@@ -1,29 +1,34 @@
+using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Tiku.Application.Jobs;
namespace Tiku.Api.Contracts;
///
-/// 创建租户后台任务请求。
+/// 创建租户后台任务请求。
///
public sealed class CreateBackgroundJobDto
{
///
- /// 任务类型。
+ /// 任务类型。
///
public string JobType { get; set; } = string.Empty;
+
///
- /// 任务载荷。
+ /// 任务载荷。
///
public JsonElement Payload { get; set; }
+
///
- /// 计划运行时间。
+ /// 计划运行时间。
///
public DateTimeOffset? RunAfter { get; set; }
+
///
- /// 最大重试次数。
+ /// 最大重试次数。
///
public int MaxRetries { get; set; } = 3;
+
/// 同租户同任务类型内的可选幂等键。
public string? IdempotencyKey { get; set; }
@@ -43,7 +48,7 @@ public sealed class CreateBackgroundJobDto
public sealed class CancelBackgroundJobDto
{
/// 取消原因。
- [System.ComponentModel.DataAnnotations.Required]
- [System.ComponentModel.DataAnnotations.StringLength(1000, MinimumLength = 3)]
+ [Required]
+ [StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/BackofficeDtos.cs b/Tiku.Api/Contracts/BackofficeDtos.cs
index 0b9641b..f62f045 100644
--- a/Tiku.Api/Contracts/BackofficeDtos.cs
+++ b/Tiku.Api/Contracts/BackofficeDtos.cs
@@ -5,32 +5,37 @@ using Tiku.Domain.Operations;
namespace Tiku.Api.Contracts;
///
-/// 创建或更新后台角色请求。
+/// 创建或更新后台角色请求。
///
public sealed class UpsertBackofficeRoleDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 编码。
+ /// 编码。
///
public string Code { get; set; } = string.Empty;
+
///
- /// 名称。
+ /// 名称。
///
public string Name { get; set; } = string.Empty;
+
///
- /// 状态。
+ /// 状态。
///
public BackendRoleStatus Status { get; set; } = BackendRoleStatus.Active;
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 数据范围配置。
+ /// 数据范围配置。
///
public JsonElement? DataScope { get; set; }
@@ -41,16 +46,17 @@ public sealed class UpsertBackofficeRoleDto
}
///
-/// 替换角色权限绑定请求。
+/// 替换角色权限绑定请求。
///
public sealed class ReplaceRoleBindingsDto
{
///
- /// 权限编码列表。
+ /// 权限编码列表。
///
public IReadOnlyCollection PermissionCodes { get; set; } = [];
+
///
- /// 菜单编码列表。
+ /// 菜单编码列表。
///
public IReadOnlyCollection MenuCodes { get; set; } = [];
@@ -61,12 +67,12 @@ public sealed class ReplaceRoleBindingsDto
}
///
-/// 替换用户角色请求。
+/// 替换用户角色请求。
///
public sealed class ReplaceUserRolesDto
{
///
- /// 角色 ID 列表。
+ /// 角色 ID 列表。
///
public IReadOnlyCollection RoleIds { get; set; } = [];
@@ -74,4 +80,4 @@ public sealed class ReplaceUserRolesDto
{
return new ReplaceUserRolesCommand(userId, RoleIds);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/CatalogDtos.cs b/Tiku.Api/Contracts/CatalogDtos.cs
index b5338a8..96c3d5a 100644
--- a/Tiku.Api/Contracts/CatalogDtos.cs
+++ b/Tiku.Api/Contracts/CatalogDtos.cs
@@ -4,67 +4,67 @@ using Tiku.Application.Catalog;
namespace Tiku.Api.Contracts;
///
-/// 目录查询参数。
+/// 目录查询参数。
///
public sealed class CatalogQueryDto
{
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
public string? TenantCode { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// ModuleId。
+ /// ModuleId。
///
public Guid? ModuleId { get; set; }
///
- /// 父节点 ID;传 root 表示根节点。
+ /// 父节点 ID;传 root 表示根节点。
///
[StringLength(64)]
[RegularExpression("^(root|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$")]
public string? ParentId { get; set; }
///
- /// 院校 ID。
+ /// 院校 ID。
///
public Guid? SchoolId { get; set; }
///
- /// 专业 ID。
+ /// 专业 ID。
///
public Guid? MajorId { get; set; }
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
///
- /// 节点 ID。
+ /// 节点 ID。
///
public Guid? NodeId { get; set; }
///
- /// 关键字。
+ /// 关键字。
///
[StringLength(100)]
public string? Keyword { get; set; }
///
- /// 类型。
+ /// 类型。
///
[StringLength(50)]
public string? Type { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 2000)]
public int? Limit { get; set; }
@@ -90,4 +90,4 @@ public sealed class CatalogQueryDto
Type,
Limit);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/CommerceDtos.cs b/Tiku.Api/Contracts/CommerceDtos.cs
index 359fb5a..48166fa 100644
--- a/Tiku.Api/Contracts/CommerceDtos.cs
+++ b/Tiku.Api/Contracts/CommerceDtos.cs
@@ -4,47 +4,47 @@ using Tiku.Application.Commerce;
namespace Tiku.Api.Contracts;
///
-/// 创建交易订单请求 DTO。
+/// 创建交易订单请求 DTO。
///
public sealed class CreateCommerceOrderDto
{
///
- /// 套餐 ID。
+ /// 套餐 ID。
///
[Required]
public Guid PlanId { get; set; }
///
- /// 数量。
+ /// 数量。
///
[Range(1, 99)]
public int Quantity { get; set; } = 1;
///
- /// 支付方式。
+ /// 支付方式。
///
[StringLength(50)]
public string? PayMethod { get; set; }
///
- /// 支付渠道。
+ /// 支付渠道。
///
[StringLength(50)]
public string? PayProvider { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 优惠券码。
+ /// 优惠券码。
///
[StringLength(100)]
public string? CouponCode { get; set; }
///
- /// 优惠券领取记录 ID。
+ /// 优惠券领取记录 ID。
///
public Guid? CouponRedemptionId { get; set; }
@@ -62,63 +62,63 @@ public sealed class CreateCommerceOrderDto
}
///
-/// 交易订单查询参数。
+/// 交易订单查询参数。
///
public sealed class CommerceOrderQueryDto
{
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 100)]
public int? Limit { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(32)]
public string? Status { get; set; }
}
///
-/// 创建交易支付请求 DTO。
+/// 创建交易支付请求 DTO。
///
public sealed class CreateCommercePaymentDto
{
///
- /// 订单号。
+ /// 订单号。
///
[Required]
[StringLength(100)]
public string OrderNo { get; set; } = string.Empty;
///
- /// 服务提供方。
+ /// 服务提供方。
///
[Required]
[StringLength(50)]
public string Provider { get; set; } = string.Empty;
///
- /// 方式。
+ /// 方式。
///
[Required]
[StringLength(50)]
public string Method { get; set; } = string.Empty;
///
- /// 微信或支付渠道 openid。
+ /// 微信或支付渠道 openid。
///
[StringLength(255)]
public string? OpenId { get; set; }
///
- /// 支付完成返回地址。
+ /// 支付完成返回地址。
///
[StringLength(2048)]
public string? ReturnUrl { get; set; }
///
- /// 支付取消返回地址。
+ /// 支付取消返回地址。
///
[StringLength(2048)]
public string? QuitUrl { get; set; }
@@ -136,18 +136,18 @@ public sealed class CreateCommercePaymentDto
}
///
-/// 交易优惠券查询参数。
+/// 交易优惠券查询参数。
///
public sealed class CommerceCouponQueryDto
{
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 100)]
public int? Limit { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(32)]
public string? Status { get; set; }
@@ -159,12 +159,12 @@ public sealed class CommerceCouponQueryDto
}
///
-/// 领取交易优惠券请求 DTO。
+/// 领取交易优惠券请求 DTO。
///
public sealed class ClaimCommerceCouponDto
{
///
- /// 优惠券码。
+ /// 优惠券码。
///
[Required]
[StringLength(100)]
@@ -177,35 +177,35 @@ public sealed class ClaimCommerceCouponDto
}
///
-/// 校验交易优惠券请求 DTO。
+/// 校验交易优惠券请求 DTO。
///
public sealed class CheckCommerceCouponDto
{
///
- /// 优惠券码。
+ /// 优惠券码。
///
[StringLength(100)]
public string? CouponCode { get; set; }
///
- /// 优惠券领取记录 ID。
+ /// 优惠券领取记录 ID。
///
public Guid? CouponRedemptionId { get; set; }
///
- /// 套餐 ID。
+ /// 套餐 ID。
///
[Required]
public Guid PlanId { get; set; }
///
- /// 数量。
+ /// 数量。
///
[Range(1, 99)]
public int Quantity { get; set; } = 1;
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
@@ -213,4 +213,4 @@ public sealed class CheckCommerceCouponDto
{
return new CheckCommerceCouponCommand(CouponCode, CouponRedemptionId, PlanId, Quantity, RegionId);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/CommissionDtos.cs b/Tiku.Api/Contracts/CommissionDtos.cs
index 44aba4e..c6ff62e 100644
--- a/Tiku.Api/Contracts/CommissionDtos.cs
+++ b/Tiku.Api/Contracts/CommissionDtos.cs
@@ -6,293 +6,373 @@ using Tiku.Application.Growth;
namespace Tiku.Api.Contracts;
///
-/// 保存佣金配置请求。
+/// 保存佣金配置请求。
///
public sealed class UpdateCommissionSettingsDto
{
///
- /// 默认佣金比例。
+ /// 默认佣金比例。
///
[Range(0, 1)]
public decimal? DefaultRate { get; set; }
+
///
- /// 最低结算金额,单位为分。
+ /// 最低结算金额,单位为分。
///
[Range(0, int.MaxValue)]
public int? MinSettlementCents { get; set; }
+
///
- /// 结算周期。
+ /// 结算周期。
///
[StringLength(50)]
public string? SettlementCycle { get; set; }
+
///
- /// 配置内容。
+ /// 配置内容。
///
public JsonElement? Config { get; set; }
- public UpdateCommissionSettingsCommand ToCommand() => new(DefaultRate, MinSettlementCents, SettlementCycle, Config);
+
+ public UpdateCommissionSettingsCommand ToCommand()
+ {
+ return new UpdateCommissionSettingsCommand(DefaultRate, MinSettlementCents, SettlementCycle, Config);
+ }
}
///
-/// 调整成员佣金比例请求。
+/// 调整成员佣金比例请求。
///
public sealed class UpdateMemberCommissionRateDto
{
///
- /// 用户 ID。
+ /// 用户 ID。
///
[Required]
public Guid UserId { get; set; }
+
///
- /// 成员佣金比例。
+ /// 成员佣金比例。
///
[Range(0, 1)]
public decimal? CommissionRate { get; set; }
+
///
- /// 佣金扩展配置。
+ /// 佣金扩展配置。
///
public JsonElement? CommissionConfig { get; set; }
- public UpdateMemberCommissionRateCommand ToCommand() => new(UserId, CommissionRate, CommissionConfig);
+
+ public UpdateMemberCommissionRateCommand ToCommand()
+ {
+ return new UpdateMemberCommissionRateCommand(UserId, CommissionRate, CommissionConfig);
+ }
}
///
-/// 佣金统计周期查询参数。
+/// 佣金统计周期查询参数。
///
public class CommissionPeriodQueryDto
{
///
- /// 开始日期,格式为 yyyy-MM-dd。
+ /// 开始日期,格式为 yyyy-MM-dd。
///
[RegularExpression("^\\d{4}-\\d{2}-\\d{2}$")]
public string? StartDate { get; set; }
+
///
- /// 结束日期,格式为 yyyy-MM-dd。
+ /// 结束日期,格式为 yyyy-MM-dd。
///
[RegularExpression("^\\d{4}-\\d{2}-\\d{2}$")]
public string? EndDate { get; set; }
+
///
- /// 推荐人用户 ID。
+ /// 推荐人用户 ID。
///
public Guid? ReferrerUserId { get; set; }
+
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
- public CommissionPeriodQuery ToQuery() => new(ParseDate(StartDate), ParseDate(EndDate), ReferrerUserId, Limit);
- protected static DateOnly? ParseDate(string? value) => string.IsNullOrWhiteSpace(value) ? null : DateOnly.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture);
+
+ public CommissionPeriodQuery ToQuery()
+ {
+ return new CommissionPeriodQuery(ParseDate(StartDate), ParseDate(EndDate), ReferrerUserId, Limit);
+ }
+
+ protected static DateOnly? ParseDate(string? value)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? null
+ : DateOnly.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture);
+ }
}
///
-/// 佣金结算单查询参数。
+/// 佣金结算单查询参数。
///
public sealed class CommissionSettlementsQueryDto
{
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
+
///
- /// 推荐人用户 ID。
+ /// 推荐人用户 ID。
///
public Guid? ReferrerUserId { get; set; }
+
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
- public CommissionSettlementQuery ToQuery() => new(Status, ReferrerUserId, Limit);
+
+ public CommissionSettlementQuery ToQuery()
+ {
+ return new CommissionSettlementQuery(Status, ReferrerUserId, Limit);
+ }
}
///
-/// 生成佣金结算单请求 DTO。
+/// 生成佣金结算单请求 DTO。
///
public sealed class GenerateCommissionSettlementDto
{
///
- /// 开始日期,格式为 yyyy-MM-dd。
+ /// 开始日期,格式为 yyyy-MM-dd。
///
[Required]
[RegularExpression("^\\d{4}-\\d{2}-\\d{2}$")]
public string StartDate { get; set; } = string.Empty;
+
///
- /// 结束日期,格式为 yyyy-MM-dd。
+ /// 结束日期,格式为 yyyy-MM-dd。
///
[Required]
[RegularExpression("^\\d{4}-\\d{2}-\\d{2}$")]
public string EndDate { get; set; } = string.Empty;
+
///
- /// 推荐人用户 ID。
+ /// 推荐人用户 ID。
///
[Required]
public Guid ReferrerUserId { get; set; }
+
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
+
///
- /// 备注。
+ /// 备注。
///
[StringLength(1000)]
public string? Remark { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement? Metadata { get; set; }
- public GenerateCommissionSettlementCommand ToCommand() => new(Parse(StartDate), Parse(EndDate), ReferrerUserId, Status, Remark, Metadata);
- private static DateOnly Parse(string value) => DateOnly.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture);
+
+ public GenerateCommissionSettlementCommand ToCommand()
+ {
+ return new GenerateCommissionSettlementCommand(Parse(StartDate), Parse(EndDate), ReferrerUserId, Status, Remark,
+ Metadata);
+ }
+
+ private static DateOnly Parse(string value)
+ {
+ return DateOnly.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture);
+ }
}
///
-/// 更新佣金结算单状态请求 DTO。
+/// 更新佣金结算单状态请求 DTO。
///
public sealed class UpdateCommissionSettlementStatusDto
{
///
- /// 结算单 ID。
+ /// 结算单 ID。
///
[Required]
public Guid SettlementId { get; set; }
+
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
+
///
- /// 审核备注。
+ /// 审核备注。
///
[StringLength(1000)]
public string? ReviewNote { get; set; }
+
///
- /// 支付方式。
+ /// 支付方式。
///
[StringLength(100)]
public string? PaymentMethod { get; set; }
+
///
- /// 收款账号。
+ /// 收款账号。
///
[StringLength(200)]
public string? PaymentAccount { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement? Metadata { get; set; }
- public UpdateCommissionSettlementStatusCommand ToCommand() => new(SettlementId, Status, ReviewNote, PaymentMethod, PaymentAccount, Metadata);
+
+ public UpdateCommissionSettlementStatusCommand ToCommand()
+ {
+ return new UpdateCommissionSettlementStatusCommand(SettlementId, Status, ReviewNote, PaymentMethod,
+ PaymentAccount, Metadata);
+ }
}
///
-/// 佣金结算单导出查询参数。
+/// 佣金结算单导出查询参数。
///
public sealed class CommissionSettlementExportQueryDto
{
///
- /// 结算单 ID。
+ /// 结算单 ID。
///
[Required]
public Guid SettlementId { get; set; }
+
///
- /// 导出格式。
+ /// 导出格式。
///
[StringLength(10)]
public string? Format { get; set; }
}
///
-/// 佣金结算单凭证查询参数。
+/// 佣金结算单凭证查询参数。
///
public sealed class CommissionSettlementProofQueryDto
{
///
- /// 结算单 ID。
+ /// 结算单 ID。
///
[Required]
public Guid SettlementId { get; set; }
}
///
-/// 创建佣金结算凭证请求。
+/// 创建佣金结算凭证请求。
///
public sealed class CreateCommissionProofDto
{
///
- /// 结算单 ID。
+ /// 结算单 ID。
///
[Required]
public Guid SettlementId { get; set; }
+
///
- /// 凭证类型。
+ /// 凭证类型。
///
[StringLength(50)]
public string? ProofType { get; set; }
+
///
- /// 标题。
+ /// 标题。
///
[StringLength(200)]
public string? Title { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
[StringLength(2000)]
public string? Description { get; set; }
+
///
- /// 资产 ID。
+ /// 资产 ID。
///
public Guid? AssetId { get; set; }
+
///
- /// 外部链接。
+ /// 外部链接。
///
[StringLength(2048)]
public string? ExternalUrl { get; set; }
+
///
- /// 金额,单位为分。
+ /// 金额,单位为分。
///
[Range(0, int.MaxValue)]
public int? AmountCents { get; set; }
+
///
- /// 支付方式。
+ /// 支付方式。
///
[StringLength(100)]
public string? PaymentMethod { get; set; }
+
///
- /// 收款账号。
+ /// 收款账号。
///
[StringLength(200)]
public string? PaymentAccount { get; set; }
+
///
- /// 支付时间。
+ /// 支付时间。
///
public DateTimeOffset? PaidAt { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement? Metadata { get; set; }
- public CreateCommissionProofCommand ToCommand() => new(SettlementId, ProofType, Title, Description, AssetId, ExternalUrl, AmountCents, PaymentMethod, PaymentAccount, PaidAt, Metadata);
+
+ public CreateCommissionProofCommand ToCommand()
+ {
+ return new CreateCommissionProofCommand(SettlementId, ProofType, Title, Description, AssetId, ExternalUrl,
+ AmountCents, PaymentMethod,
+ PaymentAccount, PaidAt, Metadata);
+ }
}
///
-/// 更新佣金结算凭证状态请求。
+/// 更新佣金结算凭证状态请求。
///
public sealed class UpdateCommissionProofStatusDto
{
///
- /// 凭证 ID。
+ /// 凭证 ID。
///
[Required]
public Guid ProofId { get; set; }
+
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
+
///
- /// 审核备注。
+ /// 审核备注。
///
[StringLength(1000)]
public string? ReviewNote { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement? Metadata { get; set; }
- public UpdateCommissionProofStatusCommand ToCommand() => new(ProofId, Status, ReviewNote, Metadata);
-}
+
+ public UpdateCommissionProofStatusCommand ToCommand()
+ {
+ return new UpdateCommissionProofStatusCommand(ProofId, Status, ReviewNote, Metadata);
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/ContentManagementDtos.cs b/Tiku.Api/Contracts/ContentManagementDtos.cs
index c0e7174..73bbc35 100644
--- a/Tiku.Api/Contracts/ContentManagementDtos.cs
+++ b/Tiku.Api/Contracts/ContentManagementDtos.cs
@@ -8,74 +8,74 @@ using Tiku.Domain.Content;
namespace Tiku.Api.Contracts;
///
-/// 内容管理查询参数。
+/// 内容管理查询参数。
///
public sealed class ContentManagementQueryDto
{
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
///
- /// 节点 ID。
+ /// 节点 ID。
///
public Guid? NodeId { get; set; }
///
- /// 题集 ID。
+ /// 题集 ID。
///
public Guid? CollectionId { get; set; }
///
- /// 父节点 ID;传 root 表示根节点。
+ /// 父节点 ID;传 root 表示根节点。
///
[StringLength(64)]
[RegularExpression("^(root|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$")]
public string? ParentId { get; set; }
///
- /// 入口类型。
+ /// 入口类型。
///
[StringLength(50)]
public string? EntryType { get; set; }
///
- /// 题集类型。
+ /// 题集类型。
///
[StringLength(50)]
public string? CollectionType { get; set; }
///
- /// 模式。
+ /// 模式。
///
[StringLength(50)]
public string? Mode { get; set; }
///
- /// 标记类型。
+ /// 标记类型。
///
[StringLength(50)]
public string? MarkerType { get; set; }
///
- /// 关键字。
+ /// 关键字。
///
[StringLength(100)]
public string? Keyword { get; set; }
///
- /// 是否包含停用数据。
+ /// 是否包含停用数据。
///
public bool IncludeInactive { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 1000)]
public int? Limit { get; set; }
@@ -99,86 +99,86 @@ public sealed class ContentManagementQueryDto
}
///
-/// 新增或更新内容条目请求 DTO。
+/// 新增或更新内容条目请求 DTO。
///
public sealed class UpsertContentEntryDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
[StringLength(64)]
public string? LegacyId { get; set; }
///
- /// 入口键。
+ /// 入口键。
///
[StringLength(100)]
public string? EntryKey { get; set; }
///
- /// 名称。
+ /// 名称。
///
[Required]
[StringLength(300)]
public string Name { get; set; } = string.Empty;
///
- /// 入口类型。
+ /// 入口类型。
///
[StringLength(50)]
public string? EntryType { get; set; }
///
- /// 图标。
+ /// 图标。
///
[StringLength(100)]
public string? Icon { get; set; }
///
- /// 路由地址。
+ /// 路由地址。
///
[StringLength(500)]
public string? Route { get; set; }
///
- /// 说明。
+ /// 说明。
///
[StringLength(2000)]
public string? Description { get; set; }
///
- /// 可见性。
+ /// 可见性。
///
[StringLength(50)]
public string? Visibility { get; set; }
///
- /// 访问规则。
+ /// 访问规则。
///
public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
///
- /// 布局配置。
+ /// 布局配置。
///
public JsonElement LayoutConfig { get; set; } = JsonDefaults.Object();
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
@@ -203,94 +203,94 @@ public sealed class UpsertContentEntryDto
}
///
-/// 新增或更新内容节点请求 DTO。
+/// 新增或更新内容节点请求 DTO。
///
public sealed class UpsertContentNodeDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
[Required]
public Guid EntryId { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 父节点 ID。
+ /// 父节点 ID。
///
public Guid? ParentId { get; set; }
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
[StringLength(64)]
public string? LegacyId { get; set; }
///
- /// 节点键。
+ /// 节点键。
///
[StringLength(100)]
public string? NodeKey { get; set; }
///
- /// 名称。
+ /// 名称。
///
[Required]
[StringLength(300)]
public string Name { get; set; } = string.Empty;
///
- /// 节点Type。
+ /// 节点Type。
///
[StringLength(50)]
public string? NodeType { get; set; }
///
- /// 标记类型。
+ /// 标记类型。
///
[StringLength(50)]
public string? MarkerType { get; set; }
///
- /// 标记配置。
+ /// 标记配置。
///
public JsonElement MarkerConfig { get; set; } = JsonDefaults.Object();
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
///
- /// 是否可选择。
+ /// 是否可选择。
///
public bool? IsSelectable { get; set; }
///
- /// 是否叶子节点。
+ /// 是否叶子节点。
///
public bool? IsLeaf { get; set; }
///
- /// 访问规则。
+ /// 访问规则。
///
public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -317,103 +317,103 @@ public sealed class UpsertContentNodeDto
}
///
-/// 新增或更新题目题集请求 DTO。
+/// 新增或更新题目题集请求 DTO。
///
public sealed class UpsertQuestionCollectionDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
///
- /// 节点 ID。
+ /// 节点 ID。
///
public Guid? NodeId { get; set; }
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
///
- /// 分类 ID。
+ /// 分类 ID。
///
public Guid? CategoryId { get; set; }
///
- /// 题库 ID。
+ /// 题库 ID。
///
public Guid? QuestionBankId { get; set; }
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
[StringLength(64)]
public string? LegacyId { get; set; }
///
- /// 名称。
+ /// 名称。
///
[Required]
[StringLength(300)]
public string Name { get; set; } = string.Empty;
///
- /// 题集类型。
+ /// 题集类型。
///
[StringLength(50)]
public string? CollectionType { get; set; }
///
- /// 来源类型。
+ /// 来源类型。
///
[StringLength(50)]
public string? SourceType { get; set; }
///
- /// 筛选条件。
+ /// 筛选条件。
///
public JsonElement Filters { get; set; } = JsonDefaults.Object();
///
- /// 总分。
+ /// 总分。
///
public decimal? TotalScore { get; set; }
///
- /// 时长,单位为分钟。
+ /// 时长,单位为分钟。
///
public int? DurationMinutes { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
///
- /// 访问规则。
+ /// 访问规则。
///
public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -442,45 +442,45 @@ public sealed class UpsertQuestionCollectionDto
}
///
-/// 题集题目请求 DTO。
+/// 题集题目请求 DTO。
///
public sealed class CollectionQuestionDto
{
///
- /// 题目 ID。
+ /// 题目 ID。
///
[Required]
public Guid QuestionId { get; set; }
///
- /// 来源。
+ /// 来源。
///
[Required]
public QuestionSource Source { get; set; } = QuestionSource.Tenant;
///
- /// 分段键。
+ /// 分段键。
///
[StringLength(100)]
public string? SectionKey { get; set; }
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
///
- /// 分数。
+ /// 分数。
///
public decimal? Score { get; set; }
///
- /// 是否必填。
+ /// 是否必填。
///
public bool? Required { get; set; }
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -497,18 +497,18 @@ public sealed class CollectionQuestionDto
}
///
-/// 替换题集Items请求 DTO。
+/// 替换题集Items请求 DTO。
///
public sealed class ReplaceCollectionItemsDto
{
///
- /// 题集 ID。
+ /// 题集 ID。
///
[Required]
public Guid CollectionId { get; set; }
///
- /// 题目列表。
+ /// 题目列表。
///
public IReadOnlyCollection Questions { get; set; } = [];
@@ -521,103 +521,103 @@ public sealed class ReplaceCollectionItemsDto
}
///
-/// 新增或更新练习Blueprint请求 DTO。
+/// 新增或更新练习Blueprint请求 DTO。
///
public sealed class UpsertPracticeBlueprintDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
///
- /// 节点 ID。
+ /// 节点 ID。
///
public Guid? NodeId { get; set; }
///
- /// 题集 ID。
+ /// 题集 ID。
///
public Guid? CollectionId { get; set; }
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
[StringLength(64)]
public string? LegacyId { get; set; }
///
- /// 名称。
+ /// 名称。
///
[Required]
[StringLength(300)]
public string Name { get; set; } = string.Empty;
///
- /// 模式。
+ /// 模式。
///
[StringLength(50)]
public string? Mode { get; set; }
///
- /// 组卷方式。
+ /// 组卷方式。
///
[StringLength(50)]
public string? AssemblyType { get; set; }
///
- /// 题目数量上限。
+ /// 题目数量上限。
///
public int? QuestionLimit { get; set; }
///
- /// 时长,单位为分钟。
+ /// 时长,单位为分钟。
///
public int? DurationMinutes { get; set; }
///
- /// 总分。
+ /// 总分。
///
public decimal? TotalScore { get; set; }
///
- /// 及格分。
+ /// 及格分。
///
public decimal? PassScore { get; set; }
///
- /// 分段配置。
+ /// 分段配置。
///
public JsonElement Sections { get; set; } = JsonDefaults.Array();
///
- /// 规则配置。
+ /// 规则配置。
///
public JsonElement Rules { get; set; } = JsonDefaults.Object();
///
- /// 访问规则。
+ /// 访问规则。
///
public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
@@ -646,20 +646,20 @@ public sealed class UpsertPracticeBlueprintDto
}
///
-/// 导入Template查询参数。
+/// 导入Template查询参数。
///
public sealed class ImportTemplateQueryDto
{
///
- /// 导入Type。
+ /// 导入Type。
///
[Required]
[StringLength(50)]
public string ImportType { get; set; } = string.Empty;
///
- /// 导出格式。
+ /// 导出格式。
///
[StringLength(10)]
public string? Format { get; set; }
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/ContentNavigationDtos.cs b/Tiku.Api/Contracts/ContentNavigationDtos.cs
index 6156165..e7aa9f2 100644
--- a/Tiku.Api/Contracts/ContentNavigationDtos.cs
+++ b/Tiku.Api/Contracts/ContentNavigationDtos.cs
@@ -4,85 +4,85 @@ using Tiku.Application.Content;
namespace Tiku.Api.Contracts;
///
-/// 内容Navigation查询参数。
+/// 内容Navigation查询参数。
///
public sealed class ContentNavigationQueryDto
{
///
- /// 租户编码。
+ /// 租户编码。
///
[StringLength(100)]
public string? TenantCode { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
///
- /// 节点 ID。
+ /// 节点 ID。
///
public Guid? NodeId { get; set; }
///
- /// 题集 ID。
+ /// 题集 ID。
///
public Guid? CollectionId { get; set; }
///
- /// 父节点 ID;传 root 表示根节点。
+ /// 父节点 ID;传 root 表示根节点。
///
[StringLength(64)]
[RegularExpression("^(root|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$")]
public string? ParentId { get; set; }
///
- /// 入口类型。
+ /// 入口类型。
///
[StringLength(50)]
public string? EntryType { get; set; }
///
- /// 题集类型。
+ /// 题集类型。
///
[StringLength(50)]
public string? CollectionType { get; set; }
///
- /// 模式。
+ /// 模式。
///
[StringLength(50)]
public string? Mode { get; set; }
///
- /// 标记类型。
+ /// 标记类型。
///
[StringLength(50)]
public string? MarkerType { get; set; }
///
- /// 关键字。
+ /// 关键字。
///
[StringLength(100)]
public string? Keyword { get; set; }
///
- /// 是否包含隐藏数据。
+ /// 是否包含隐藏数据。
///
public bool IncludeHidden { get; set; }
///
- /// 是否包含停用数据。
+ /// 是否包含停用数据。
///
public bool IncludeInactive { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 1000)]
public int? Limit { get; set; }
@@ -113,4 +113,4 @@ public sealed class ContentNavigationQueryDto
IncludeInactive,
Limit);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/CrmDtos.cs b/Tiku.Api/Contracts/CrmDtos.cs
index 2c75056..62458d3 100644
--- a/Tiku.Api/Contracts/CrmDtos.cs
+++ b/Tiku.Api/Contracts/CrmDtos.cs
@@ -5,69 +5,69 @@ using Tiku.Application.Growth;
namespace Tiku.Api.Contracts;
///
-/// 新增或更新CRM配置请求 DTO。
+/// 新增或更新CRM配置请求 DTO。
///
public sealed class UpsertCrmConfigDto
{
///
- /// 是否启用。
+ /// 是否启用。
///
public bool Enabled { get; set; }
///
- /// 访问地址。
+ /// 访问地址。
///
[StringLength(2048)]
public string? Url { get; set; }
///
- /// 密钥引用。
+ /// 密钥引用。
///
[StringLength(300)]
public string? SecretRef { get; set; }
///
- /// 密钥内容。
+ /// 密钥内容。
///
public string? Secret { get; set; }
///
- /// 表单名称。
+ /// 表单名称。
///
[StringLength(200)]
public string? FormName { get; set; }
///
- /// 考试类型。
+ /// 考试类型。
///
[StringLength(100)]
public string? ExamType { get; set; }
///
- /// 超时时长,单位为秒。
+ /// 超时时长,单位为秒。
///
[Range(1, 120)]
public int? TimeoutSeconds { get; set; }
///
- /// 延迟秒数。
+ /// 延迟秒数。
///
[Range(0, 86400)]
public int? DelaySeconds { get; set; }
///
- /// 分配模式。
+ /// 分配模式。
///
[StringLength(50)]
public string? AssignmentMode { get; set; }
///
- /// 分配池。
+ /// 分配池。
///
public JsonElement? AssignmentPool { get; set; }
///
- /// 分配配置。
+ /// 分配配置。
///
public JsonElement? AssignmentConfig { get; set; }
@@ -89,29 +89,29 @@ public sealed class UpsertCrmConfigDto
}
///
-/// CRM队列查询参数。
+/// CRM队列查询参数。
///
public sealed class CrmQueueQueryDto
{
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 队列任务 ID。
+ /// 队列任务 ID。
///
public Guid? QueueId { get; set; }
///
- /// 来源。
+ /// 来源。
///
[StringLength(200)]
public string? Source { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
@@ -123,17 +123,17 @@ public sealed class CrmQueueQueryDto
}
///
-/// CRM队列日志查询参数。
+/// CRM队列日志查询参数。
///
public sealed class CrmQueueLogQueryDto
{
///
- /// 队列任务 ID。
+ /// 队列任务 ID。
///
public Guid? QueueId { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 200)]
public int? Limit { get; set; }
@@ -145,30 +145,30 @@ public sealed class CrmQueueLogQueryDto
}
///
-/// CRM队列Action请求 DTO。
+/// CRM队列Action请求 DTO。
///
public sealed class CrmQueueActionDto
{
///
- /// 队列任务 ID。
+ /// 队列任务 ID。
///
[Required]
public Guid QueueId { get; set; }
///
- /// 操作。
+ /// 操作。
///
[StringLength(50)]
public string? Action { get; set; }
///
- /// 备注。
+ /// 备注。
///
[StringLength(500)]
public string? Note { get; set; }
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement? Metadata { get; set; }
@@ -176,4 +176,4 @@ public sealed class CrmQueueActionDto
{
return new CrmQueueActionCommand(QueueId, Action, Note, Metadata);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/DirectContentDtos.cs b/Tiku.Api/Contracts/DirectContentDtos.cs
index 3263aad..1dd3ef5 100644
--- a/Tiku.Api/Contracts/DirectContentDtos.cs
+++ b/Tiku.Api/Contracts/DirectContentDtos.cs
@@ -6,71 +6,80 @@ using Tiku.Domain.Common;
namespace Tiku.Api.Contracts;
///
-/// 管理侧内容查询参数。
+/// 管理侧内容查询参数。
///
public sealed class DirectContentQueryDto
{
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 父节点 ID。
+ /// 父节点 ID。
///
public Guid? ParentId { get; set; }
+
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
+
///
- /// 章节 ID。
+ /// 章节 ID。
///
public Guid? ChapterId { get; set; }
+
///
- /// 单元 ID。
+ /// 单元 ID。
///
public Guid? UnitId { get; set; }
+
///
- /// 院校 ID。
+ /// 院校 ID。
///
public Guid? SchoolId { get; set; }
+
///
- /// 专业 ID。
+ /// 专业 ID。
///
public Guid? MajorId { get; set; }
+
///
- /// 题目 ID。
+ /// 题目 ID。
///
public Guid? QuestionId { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 关键字。
+ /// 关键字。
///
[StringLength(200)]
public string? Keyword { get; set; }
///
- /// 年份。
+ /// 年份。
///
[Range(1900, 3000)]
public int? Year { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 1000)]
public int? Limit { get; set; }
@@ -96,119 +105,143 @@ public sealed class DirectContentQueryDto
}
///
-/// 管理侧题目写入请求。
+/// 管理侧题目写入请求。
///
public sealed class DirectQuestionWriteDto
{
///
- /// 题目 ID。
+ /// 题目 ID。
///
public Guid? QuestionId { get; set; }
+
///
- /// 题库 ID。
+ /// 题库 ID。
///
public Guid? QuestionBankId { get; set; }
+
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
+
///
- /// 分类 ID。
+ /// 分类 ID。
///
public Guid? CategoryId { get; set; }
+
///
- /// 节点 ID。
+ /// 节点 ID。
///
public Guid? NodeId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 主题集 ID。
+ /// 主题集 ID。
///
public Guid? PrimaryCollectionId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 类型。
+ /// 类型。
///
public string? Type { get; set; }
+
///
- /// 类型显示名。
+ /// 类型显示名。
///
public string? TypeLabel { get; set; }
///
- /// 难度。
+ /// 难度。
///
[Range(1, 5)]
public int? Difficulty { get; set; }
///
- /// 标签列表。
+ /// 标签列表。
///
public JsonElement Tags { get; set; } = JsonDefaults.Array();
+
///
- /// 内容。
+ /// 内容。
///
public string? Content { get; set; }
+
///
- /// 选项配置。
+ /// 选项配置。
///
public JsonElement Options { get; set; } = JsonDefaults.Array();
+
///
- /// 正确选项索引。
+ /// 正确选项索引。
///
public int? CorrectOptionIndex { get; set; }
+
///
- /// 正确选项索引列表。
+ /// 正确选项索引列表。
///
public JsonElement CorrectOptionIndices { get; set; } = JsonDefaults.Array();
+
///
- /// 文字答案。
+ /// 文字答案。
///
public string? AnswerText { get; set; }
+
///
- /// 解析。
+ /// 解析。
///
public string? Explanation { get; set; }
+
///
- /// 子题列表。
+ /// 子题列表。
///
public JsonElement SubQuestions { get; set; } = JsonDefaults.Array();
+
///
- /// 代码语言。
+ /// 代码语言。
///
public string? CodeLang { get; set; }
+
///
- /// 代码模板。
+ /// 代码模板。
///
public string? CodeTemplate { get; set; }
+
///
- /// 媒体地址。
+ /// 媒体地址。
///
public string? MediaUrl { get; set; }
+
///
- /// 状态。
+ /// 状态。
///
public string? Status { get; set; }
+
///
- /// 考试标记配置。
+ /// 考试标记配置。
///
public JsonElement ExamMarkers { get; set; } = JsonDefaults.Object();
+
///
- /// 来源哈希。
+ /// 来源哈希。
///
public string? SourceHash { get; set; }
+
///
- /// 是否创建题目版本。
+ /// 是否创建题目版本。
///
public bool? CreateVersion { get; set; }
@@ -246,124 +279,149 @@ public sealed class DirectQuestionWriteDto
}
///
-/// 管理侧词汇单元写入请求。
+/// 管理侧词汇单元写入请求。
///
public sealed class DirectVocabularyUnitDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 名称。
+ /// 名称。
///
public required string Name { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 单词数量。
+ /// 单词数量。
///
public int? WordCount { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
public VocabularyUnitCommand ToCommand()
{
- return new VocabularyUnitCommand(Id, RegionId, EntryId, ContentNodeId, LegacyId, Name, Description, WordCount, Order, IsActive, Metadata);
+ return new VocabularyUnitCommand(Id, RegionId, EntryId, ContentNodeId, LegacyId, Name, Description, WordCount,
+ Order, IsActive, Metadata);
}
}
///
-/// 管理侧词汇单词写入请求。
+/// 管理侧词汇单词写入请求。
///
public sealed class DirectVocabularyWordDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 单元 ID。
+ /// 单元 ID。
///
public Guid? UnitId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 单词。
+ /// 单词。
///
public required string Word { get; set; }
+
///
- /// 音标。
+ /// 音标。
///
public string? Phonetic { get; set; }
+
///
- /// 释义。
+ /// 释义。
///
public string? Meaning { get; set; }
+
///
- /// 例句。
+ /// 例句。
///
public string? Example { get; set; }
+
///
- /// 例句翻译。
+ /// 例句翻译。
///
public string? ExampleTranslation { get; set; }
+
///
- /// 难度。
+ /// 难度。
///
public int? Difficulty { get; set; }
+
///
- /// 标签列表。
+ /// 标签列表。
///
public JsonElement Tags { get; set; } = JsonDefaults.Array();
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -389,68 +447,82 @@ public sealed class DirectVocabularyWordDto
}
///
-/// 管理侧知识手册科目写入请求。
+/// 管理侧知识手册科目写入请求。
///
public sealed class DirectHandbookSubjectDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 院校 ID。
+ /// 院校 ID。
///
public Guid? SchoolId { get; set; }
+
///
- /// 专业 ID。
+ /// 专业 ID。
///
public Guid? MajorId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 名称。
+ /// 名称。
///
public required string Name { get; set; }
+
///
- /// 类型。
+ /// 类型。
///
public string? Type { get; set; }
+
///
- /// 图标。
+ /// 图标。
///
public string? Icon { get; set; }
+
///
- /// 颜色。
+ /// 颜色。
///
public string? Color { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -476,144 +548,171 @@ public sealed class DirectHandbookSubjectDto
}
///
-/// 管理侧知识手册章节写入请求。
+/// 管理侧知识手册章节写入请求。
///
public sealed class DirectHandbookChapterDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 名称。
+ /// 名称。
///
public required string Name { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
public HandbookChapterCommand ToCommand()
{
- return new HandbookChapterCommand(Id, SubjectId, EntryId, ContentNodeId, LegacyId, Name, Description, Order, IsActive, Metadata);
+ return new HandbookChapterCommand(Id, SubjectId, EntryId, ContentNodeId, LegacyId, Name, Description, Order,
+ IsActive, Metadata);
}
}
///
-/// 管理侧知识手册条目写入请求。
+/// 管理侧知识手册条目写入请求。
///
public sealed class DirectHandbookEntryDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 章节 ID。
+ /// 章节 ID。
///
public Guid? ChapterId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 标题。
+ /// 标题。
///
public required string Title { get; set; }
+
///
- /// 摘要。
+ /// 摘要。
///
public string? Summary { get; set; }
+
///
- /// 内容。
+ /// 内容。
///
public string? Content { get; set; }
+
///
- /// 标签列表。
+ /// 标签列表。
///
public JsonElement Tags { get; set; } = JsonDefaults.Array();
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
public HandbookEntryCommand ToCommand()
{
- return new HandbookEntryCommand(Id, ChapterId, EntryId, ContentNodeId, LegacyId, Title, Summary, Content, Tags, Order, IsActive, Metadata);
+ return new HandbookEntryCommand(Id, ChapterId, EntryId, ContentNodeId, LegacyId, Title, Summary, Content, Tags,
+ Order, IsActive, Metadata);
}
}
///
-/// 管理侧院校写入请求。
+/// 管理侧院校写入请求。
///
public sealed class DirectSchoolDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 名称。
+ /// 名称。
///
public required string Name { get; set; }
+
///
- /// 专业考试日期。
+ /// 专业考试日期。
///
public string? ProfessionalExamDate { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -624,44 +723,52 @@ public sealed class DirectSchoolDto
}
///
-/// 管理侧专业写入请求。
+/// 管理侧专业写入请求。
///
public sealed class DirectMajorDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 院校 ID。
+ /// 院校 ID。
///
public Guid? SchoolId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 名称。
+ /// 名称。
///
public required string Name { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 备考建议。
+ /// 备考建议。
///
public string? StudyTips { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
@@ -672,68 +779,82 @@ public sealed class DirectMajorDto
}
///
-/// 管理侧分数线字段写入请求。
+/// 管理侧分数线字段写入请求。
///
public sealed class DirectScorelineFieldDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 字段键。
+ /// 字段键。
///
public required string FieldKey { get; set; }
+
///
- /// 字段名称。
+ /// 字段名称。
///
public required string FieldName { get; set; }
+
///
- /// 字段类型。
+ /// 字段类型。
///
public string? FieldType { get; set; }
+
///
- /// 单位。
+ /// 单位。
///
public string? Unit { get; set; }
+
///
- /// 是否可筛选。
+ /// 是否可筛选。
///
public bool? IsFilter { get; set; }
+
///
- /// 是否必填。
+ /// 是否必填。
///
public bool? IsRequired { get; set; }
+
///
- /// 是否可见。
+ /// 是否可见。
///
public bool? IsVisible { get; set; }
+
///
- /// 是否参与趋势展示。
+ /// 是否参与趋势展示。
///
public bool? IsTrend { get; set; }
+
///
- /// 选项配置。
+ /// 选项配置。
///
public JsonElement Options { get; set; } = JsonDefaults.Array();
+
///
- /// 占位提示。
+ /// 占位提示。
///
public string? Placeholder { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
@@ -759,47 +880,53 @@ public sealed class DirectScorelineFieldDto
}
///
-/// 管理侧分数线记录写入请求。
+/// 管理侧分数线记录写入请求。
///
public sealed class DirectScorelineRecordDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 院校 ID。
+ /// 院校 ID。
///
public Guid? SchoolId { get; set; }
+
///
- /// 专业 ID。
+ /// 专业 ID。
///
public Guid? MajorId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
///
- /// 年份。
+ /// 年份。
///
[Range(1900, 3000)]
public int Year { get; set; }
///
- /// 院校名称。
+ /// 院校名称。
///
public string? SchoolName { get; set; }
+
///
- /// 专业名称。
+ /// 专业名称。
///
public string? MajorName { get; set; }
+
///
- /// 动态字段值。
+ /// 动态字段值。
///
public JsonElement FieldValues { get; set; } = JsonDefaults.Object();
@@ -819,64 +946,77 @@ public sealed class DirectScorelineRecordDto
}
///
-/// 管理侧视频写入请求。
+/// 管理侧视频写入请求。
///
public sealed class DirectVideoDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 标题。
+ /// 标题。
///
public required string Title { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 视频地址。
+ /// 视频地址。
///
public string? VideoUrl { get; set; }
+
///
- /// 缩略图地址。
+ /// 缩略图地址。
///
public string? ThumbnailUrl { get; set; }
+
///
- /// 时长,单位为秒。
+ /// 时长,单位为秒。
///
public int? DurationSeconds { get; set; }
+
///
- /// 知识标签。
+ /// 知识标签。
///
public JsonElement KnowledgeTags { get; set; } = JsonDefaults.Array();
+
///
- /// 是否通用视频。
+ /// 是否通用视频。
///
public bool? IsGeneral { get; set; }
+
///
- /// 难度。
+ /// 难度。
///
public int? Difficulty { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -901,32 +1041,37 @@ public sealed class DirectVideoDto
}
///
-/// 管理侧题目视频绑定请求。
+/// 管理侧题目视频绑定请求。
///
public sealed class DirectQuestionVideoDto
{
///
- /// 题目 ID。
+ /// 题目 ID。
///
public Guid QuestionId { get; set; }
+
///
- /// 视频 ID。
+ /// 视频 ID。
///
public Guid VideoId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 视频类型。
+ /// 视频类型。
///
public string? VideoType { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -937,92 +1082,112 @@ public sealed class DirectQuestionVideoDto
}
///
-/// 管理侧运营内容写入请求。
+/// 管理侧运营内容写入请求。
///
public sealed class DirectOperationContentDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 院校 ID。
+ /// 院校 ID。
///
public Guid? SchoolId { get; set; }
+
///
- /// 历史系统 ID。
+ /// 历史系统 ID。
///
public string? LegacyId { get; set; }
+
///
- /// 标题。
+ /// 标题。
///
public string? Title { get; set; }
+
///
- /// 副标题。
+ /// 副标题。
///
public string? Subtitle { get; set; }
+
///
- /// 内容。
+ /// 内容。
///
public string? Content { get; set; }
+
///
- /// 问题。
+ /// 问题。
///
public string? Question { get; set; }
+
///
- /// 答案。
+ /// 答案。
///
public string? Answer { get; set; }
+
///
- /// 链接地址。
+ /// 链接地址。
///
public string? Link { get; set; }
+
///
- /// 按钮文案。
+ /// 按钮文案。
///
public string? ButtonText { get; set; }
+
///
- /// 按钮链接。
+ /// 按钮链接。
///
public string? ButtonLink { get; set; }
+
///
- /// 背景颜色。
+ /// 背景颜色。
///
public string? BackgroundColor { get; set; }
+
///
- /// 边框颜色。
+ /// 边框颜色。
///
public string? BorderColor { get; set; }
+
///
- /// 考试名称。
+ /// 考试名称。
///
public string? ExamName { get; set; }
+
///
- /// 考试时间。
+ /// 考试时间。
///
public DateTimeOffset? ExamAt { get; set; }
+
///
- /// 考试类型。
+ /// 考试类型。
///
public string? ExamType { get; set; }
+
///
- /// 说明。
+ /// 说明。
///
public string? Description { get; set; }
+
///
- /// 显示顺序。
+ /// 显示顺序。
///
public int? Order { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool? IsActive { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -1054,88 +1219,107 @@ public sealed class DirectOperationContentDto
}
///
-/// 管理侧内容导入请求。
+/// 管理侧内容导入请求。
///
public sealed class DirectImportDto
{
///
- /// 来源格式。
+ /// 来源格式。
///
public string? SourceFormat { get; set; }
+
///
- /// 来源名称。
+ /// 来源名称。
///
public string? SourceName { get; set; }
+
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
+
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
+
///
- /// 科目 ID。
+ /// 科目 ID。
///
public Guid? SubjectId { get; set; }
+
///
- /// 分类 ID。
+ /// 分类 ID。
///
public Guid? CategoryId { get; set; }
+
///
- /// 题库 ID。
+ /// 题库 ID。
///
public Guid? QuestionBankId { get; set; }
+
///
- /// 题集 ID。
+ /// 题集 ID。
///
public Guid? CollectionId { get; set; }
+
///
- /// 是否异步执行。
+ /// 是否异步执行。
///
public bool? Async { get; set; }
+
///
- /// 数据项列表。
+ /// 数据项列表。
///
public IReadOnlyCollection? Items { get; set; }
+
///
- /// 单元数据列表。
+ /// 单元数据列表。
///
public IReadOnlyCollection? Units { get; set; }
+
///
- /// 单词数据列表。
+ /// 单词数据列表。
///
public IReadOnlyCollection? Words { get; set; }
+
///
- /// 科目数据列表。
+ /// 科目数据列表。
///
public IReadOnlyCollection? Subjects { get; set; }
+
///
- /// 条目数据列表。
+ /// 条目数据列表。
///
public IReadOnlyCollection? Entries { get; set; }
+
///
- /// 字段数据列表。
+ /// 字段数据列表。
///
public IReadOnlyCollection? Fields { get; set; }
+
///
- /// 院校数据列表。
+ /// 院校数据列表。
///
public IReadOnlyCollection? Schools { get; set; }
+
///
- /// 专业数据列表。
+ /// 专业数据列表。
///
public IReadOnlyCollection? Majors { get; set; }
+
///
- /// 记录数据列表。
+ /// 记录数据列表。
///
public IReadOnlyCollection? Records { get; set; }
+
///
- /// 视频数据列表。
+ /// 视频数据列表。
///
public IReadOnlyCollection? Videos { get; set; }
@@ -1171,12 +1355,12 @@ public sealed class DirectImportDto
}
///
-/// 管理侧内容导入任务查询请求。
+/// 管理侧内容导入任务查询请求。
///
public sealed class DirectImportJobDto
{
///
- /// 任务 ID。
+ /// 任务 ID。
///
public Guid JobId { get; set; }
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/HealthDtos.cs b/Tiku.Api/Contracts/HealthDtos.cs
index d200c01..22cd94d 100644
--- a/Tiku.Api/Contracts/HealthDtos.cs
+++ b/Tiku.Api/Contracts/HealthDtos.cs
@@ -1,15 +1,15 @@
namespace Tiku.Api.Contracts;
///
-/// 健康检查响应。
+/// 健康检查响应。
///
/// 服务状态,例如 ok。
/// 服务名称。
/// 检查时间。
///
-/// 健康检查Response请求 DTO。
+/// 健康检查Response请求 DTO。
///
public sealed record HealthResponseDto(
string Status,
string Service,
- DateTimeOffset CheckedAt);
+ DateTimeOffset CheckedAt);
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/LearningDtos.cs b/Tiku.Api/Contracts/LearningDtos.cs
index 2262137..0d6122a 100644
--- a/Tiku.Api/Contracts/LearningDtos.cs
+++ b/Tiku.Api/Contracts/LearningDtos.cs
@@ -8,24 +8,24 @@ using Tiku.Domain.Content;
namespace Tiku.Api.Contracts;
///
-/// 学习Limit查询参数。
+/// 学习Limit查询参数。
///
public sealed class LearningLimitQueryDto
{
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int? Limit { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 单元 ID。
+ /// 单元 ID。
///
public Guid? UnitId { get; set; }
@@ -36,34 +36,34 @@ public sealed class LearningLimitQueryDto
}
///
-/// 练习会话查询参数。
+/// 练习会话查询参数。
///
public sealed class PracticeSessionQueryDto
{
///
- /// 练习会话 ID。
+ /// 练习会话 ID。
///
public Guid? PracticeSessionId { get; set; }
///
- /// 练习蓝图 ID。
+ /// 练习蓝图 ID。
///
public Guid? BlueprintId { get; set; }
///
- /// 模式。
+ /// 模式。
///
[StringLength(50)]
public string? Mode { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 200)]
public int? Limit { get; set; }
@@ -80,67 +80,67 @@ public sealed class PracticeSessionQueryDto
}
///
-/// 创建练习会话请求 DTO。
+/// 创建练习会话请求 DTO。
///
public sealed class CreatePracticeSessionDto
{
///
- /// 模式。
+ /// 模式。
///
[StringLength(50)]
public string? Mode { get; set; }
///
- /// 目标类型。
+ /// 目标类型。
///
[StringLength(50)]
public string? TargetType { get; set; }
///
- /// 目标 ID。
+ /// 目标 ID。
///
public Guid? TargetId { get; set; }
///
- /// 练习蓝图 ID。
+ /// 练习蓝图 ID。
///
public Guid? BlueprintId { get; set; }
///
- /// 题集 ID。
+ /// 题集 ID。
///
public Guid? CollectionId { get; set; }
///
- /// 内容入口 ID。
+ /// 内容入口 ID。
///
public Guid? EntryId { get; set; }
///
- /// 内容节点 ID。
+ /// 内容节点 ID。
///
public Guid? ContentNodeId { get; set; }
///
- /// 题目数量上限。
+ /// 题目数量上限。
///
[Range(1, 500)]
public int? QuestionLimit { get; set; }
///
- /// 时长,单位为分钟。
+ /// 时长,单位为分钟。
///
[Range(1, 1440)]
public int? DurationMinutes { get; set; }
///
- /// 总分。
+ /// 总分。
///
[Range(typeof(decimal), "0", "99999")]
public decimal? TotalScore { get; set; }
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
@@ -162,62 +162,67 @@ public sealed class CreatePracticeSessionDto
}
///
-/// 提交练习会话请求 DTO。
+/// 提交练习会话请求 DTO。
///
public sealed class SubmitPracticeSessionDto
{
///
- /// 练习会话 ID。
+ /// 练习会话 ID。
///
[Required]
public Guid PracticeSessionId { get; set; }
- [Required, Range(1, long.MaxValue)]
- public long ExpectedSessionVersion { get; set; }
+ [Required] [Range(1, long.MaxValue)] public long ExpectedSessionVersion { get; set; }
- [Required, StringLength(200, MinimumLength = 1)]
+ [Required]
+ [StringLength(200, MinimumLength = 1)]
public string IdempotencyKey { get; set; } = string.Empty;
- public SubmitPracticeSessionCommand ToCommand() =>
- new(PracticeSessionId, ExpectedSessionVersion, IdempotencyKey);
+ public SubmitPracticeSessionCommand ToCommand()
+ {
+ return new SubmitPracticeSessionCommand(PracticeSessionId, ExpectedSessionVersion, IdempotencyKey);
+ }
}
///
-/// 提交答案请求 DTO。
+/// 提交答案请求 DTO。
///
public sealed class SubmitAnswerDto
{
///
- /// 会话题目 ID。
+ /// 会话题目 ID。
///
[Required]
public Guid SessionQuestionId { get; set; }
///
- /// 客户端读取会话时获得的版本。
+ /// 客户端读取会话时获得的版本。
///
- [Required, Range(1, long.MaxValue)]
+ [Required]
+ [Range(1, long.MaxValue)]
public long ExpectedSessionVersion { get; set; }
///
- /// 客户端在本会话内单调递增的序列。
+ /// 客户端在本会话内单调递增的序列。
///
- [Required, Range(1, long.MaxValue)]
+ [Required]
+ [Range(1, long.MaxValue)]
public long ClientSequence { get; set; }
///
- /// 网络重试幂等键。
+ /// 网络重试幂等键。
///
- [Required, StringLength(200, MinimumLength = 1)]
+ [Required]
+ [StringLength(200, MinimumLength = 1)]
public string IdempotencyKey { get; set; } = string.Empty;
///
- /// 已选选项的零基索引。
+ /// 已选选项的零基索引。
///
public IReadOnlyCollection? SelectedOptionIndices { get; set; }
///
- /// 文字答案。
+ /// 文字答案。
///
[StringLength(10000)]
public string? AnswerText { get; set; }
@@ -235,24 +240,24 @@ public sealed class SubmitAnswerDto
}
///
-/// 题目Action请求 DTO。
+/// 题目Action请求 DTO。
///
public sealed class QuestionActionDto
{
///
- /// 题目 ID。
+ /// 题目 ID。
///
[Required]
public Guid QuestionId { get; set; }
///
- /// 来源。
+ /// 来源。
///
[Required]
public QuestionSource Source { get; set; } = QuestionSource.Tenant;
///
- /// 是否收藏。
+ /// 是否收藏。
///
public bool? Favorite { get; set; }
@@ -263,36 +268,36 @@ public sealed class QuestionActionDto
}
///
-/// 单词Progress请求 DTO。
+/// 单词Progress请求 DTO。
///
public sealed class WordProgressDto
{
///
- /// 单词 ID。
+ /// 单词 ID。
///
[Required]
public Guid WordId { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
///
- /// 答对数量变化。
+ /// 答对数量变化。
///
[Range(0, 100)]
public int? CorrectDelta { get; set; }
///
- /// 答错数量变化。
+ /// 答错数量变化。
///
[Range(0, 100)]
public int? WrongDelta { get; set; }
///
- /// 下次复习时间。
+ /// 下次复习时间。
///
public DateTimeOffset? NextReviewAt { get; set; }
@@ -308,23 +313,23 @@ public sealed class WordProgressDto
}
///
-/// 收藏单词请求 DTO。
+/// 收藏单词请求 DTO。
///
public sealed class FavoriteWordDto
{
///
- /// 单词 ID。
+ /// 单词 ID。
///
[Required]
public Guid WordId { get; set; }
///
- /// 是否收藏。
+ /// 是否收藏。
///
public bool? Favorite { get; set; }
///
- /// 备注。
+ /// 备注。
///
[StringLength(1000)]
public string? Note { get; set; }
@@ -336,24 +341,24 @@ public sealed class FavoriteWordDto
}
///
-/// 单词Review请求 DTO。
+/// 单词Review请求 DTO。
///
public sealed class WordReviewDto
{
///
- /// 单词 ID。
+ /// 单词 ID。
///
[Required]
public Guid WordId { get; set; }
///
- /// 结果。
+ /// 结果。
///
[StringLength(50)]
public string? Result { get; set; }
///
- /// 下次复习时间。
+ /// 下次复习时间。
///
public DateTimeOffset? NextReviewAt { get; set; }
@@ -361,4 +366,4 @@ public sealed class WordReviewDto
{
return new WordReviewCommand(WordId, Result, NextReviewAt);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/PlatformAdminDtos.cs b/Tiku.Api/Contracts/PlatformAdminDtos.cs
index 836169e..edf5f25 100644
--- a/Tiku.Api/Contracts/PlatformAdminDtos.cs
+++ b/Tiku.Api/Contracts/PlatformAdminDtos.cs
@@ -2,7 +2,6 @@ using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Tiku.Application.PlatformAdmin;
using Tiku.Domain.Common;
-using Tiku.Domain.Commerce;
using Tiku.Domain.Identity;
using Tiku.Domain.Platform;
using Tiku.Domain.Tenancy;
@@ -10,89 +9,98 @@ using Tiku.Domain.Tenancy;
namespace Tiku.Api.Contracts;
///
-/// 平台管理端查询参数。
+/// 平台管理端查询参数。
///
public sealed class PlatformAdminQueryDto
{
///
- /// 状态。
+ /// 状态。
///
[StringLength(32)]
public string? Status { get; set; }
///
- /// 搜索关键字。
+ /// 搜索关键字。
///
[StringLength(200)]
public string? Search { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 200)]
public int? Limit { get; set; }
- public PlatformAdminQuery ToQuery() => new(Status, Search, Limit);
+ public PlatformAdminQuery ToQuery()
+ {
+ return new PlatformAdminQuery(Status, Search, Limit);
+ }
}
///
-/// 创建平台租户请求 DTO。
+/// 创建平台租户请求 DTO。
///
public sealed class CreatePlatformTenantDto
{
///
- /// 短编码。
+ /// 短编码。
///
[Required]
[StringLength(100)]
public string Slug { get; set; } = string.Empty;
///
- /// 名称。
+ /// 名称。
///
[Required]
[StringLength(200)]
public string Name { get; set; } = string.Empty;
///
- /// 法定名称。
+ /// 法定名称。
///
[StringLength(300)]
public string? LegalName { get; set; }
///
- /// 状态。
+ /// 状态。
///
public TenantStatus Status { get; set; } = TenantStatus.Active;
+
///
- /// 账务状态。
+ /// 账务状态。
///
public BillingStatus BillingStatus { get; set; } = BillingStatus.Trial;
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
/// 租户首次开通使用的自定义主域名。
- [Required, StringLength(253, MinimumLength = 4)]
+ [Required]
+ [StringLength(253, MinimumLength = 4)]
public string PrimaryDomainHost { get; set; } = string.Empty;
///
- /// 租户负责人邮箱。
+ /// 租户负责人邮箱。
///
- [EmailAddress, StringLength(320)]
+ [EmailAddress]
+ [StringLength(320)]
public string? OwnerEmail { get; set; }
///
- /// 租户负责人手机号。
+ /// 租户负责人手机号。
///
- [Phone, StringLength(32)]
+ [Phone]
+ [StringLength(32)]
public string? OwnerPhone { get; set; }
///
- /// 租户负责人姓名。
+ /// 租户负责人姓名。
///
- [Required, StringLength(100)]
+ [Required]
+ [StringLength(100)]
public string OwnerName { get; set; } = string.Empty;
/// 初始试用套餐版本;为空时使用平台配置的默认基础套餐。
@@ -106,7 +114,8 @@ public sealed class CreatePlatformTenantDto
public TenantBillingCollectionMode CollectionMode { get; set; } = TenantBillingCollectionMode.Online;
/// 默认支付 Provider。
- [Required, StringLength(50)]
+ [Required]
+ [StringLength(50)]
public string DefaultPaymentProvider { get; set; } = "manual";
/// 是否自动生成续费应收。
@@ -116,408 +125,456 @@ public sealed class CreatePlatformTenantDto
[Range(1, 90)]
public int RenewalLeadDays { get; set; } = 14;
- public CreatePlatformTenantCommand ToCommand(string idempotencyKey) => new(
- Slug, Name, LegalName, Status, BillingStatus, Metadata, PrimaryDomainHost,
- OwnerEmail, OwnerPhone, OwnerName,
- InitialOfferingVersionId, TrialDays, CollectionMode, DefaultPaymentProvider,
- AutoGenerateRenewal, RenewalLeadDays, idempotencyKey);
+ public CreatePlatformTenantCommand ToCommand(string idempotencyKey)
+ {
+ return new CreatePlatformTenantCommand(
+ Slug, Name, LegalName, Status, BillingStatus, Metadata, PrimaryDomainHost,
+ OwnerEmail, OwnerPhone, OwnerName,
+ InitialOfferingVersionId, TrialDays, CollectionMode, DefaultPaymentProvider,
+ AutoGenerateRenewal, RenewalLeadDays, idempotencyKey);
+ }
}
public sealed class ReplacePlatformPrimaryDomainDto
{
- [Required, StringLength(253, MinimumLength = 4)]
+ [Required]
+ [StringLength(253, MinimumLength = 4)]
public string Host { get; set; } = string.Empty;
- [Required, StringLength(1000, MinimumLength = 3)]
+ [Required]
+ [StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
- public ReplacePlatformPrimaryDomainCommand ToCommand(Guid tenantId) => new(tenantId, Host, Reason);
+ public ReplacePlatformPrimaryDomainCommand ToCommand(Guid tenantId)
+ {
+ return new ReplacePlatformPrimaryDomainCommand(tenantId, Host, Reason);
+ }
}
public sealed class IssuePlatformOwnerActivationLinkDto
{
- [Required, StringLength(1000, MinimumLength = 3)]
+ [Required]
+ [StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
public bool ReplaceExisting { get; set; }
- public IssuePlatformOwnerActivationLinkCommand ToCommand(Guid tenantId, string idempotencyKey) =>
- new(tenantId, idempotencyKey, Reason, ReplaceExisting);
+ public IssuePlatformOwnerActivationLinkCommand ToCommand(Guid tenantId, string idempotencyKey)
+ {
+ return new IssuePlatformOwnerActivationLinkCommand(tenantId, idempotencyKey, Reason, ReplaceExisting);
+ }
}
/// 更新租户收款策略。
public sealed class UpsertTenantBillingPolicyDto
{
public TenantBillingCollectionMode CollectionMode { get; set; } = TenantBillingCollectionMode.Online;
- [Required, StringLength(50)]
- public string DefaultPaymentProvider { get; set; } = "manual";
+
+ [Required] [StringLength(50)] public string DefaultPaymentProvider { get; set; } = "manual";
+
public bool AutoGenerateRenewal { get; set; } = true;
- [Range(1, 90)]
- public int RenewalLeadDays { get; set; } = 14;
- [Required, StringLength(1000, MinimumLength = 3)]
+
+ [Range(1, 90)] public int RenewalLeadDays { get; set; } = 14;
+
+ [Required]
+ [StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
- public UpsertTenantBillingPolicyCommand ToCommand(Guid tenantId) => new(
- tenantId,
- CollectionMode,
- DefaultPaymentProvider,
- AutoGenerateRenewal,
- RenewalLeadDays,
- Reason);
+ public UpsertTenantBillingPolicyCommand ToCommand(Guid tenantId)
+ {
+ return new UpsertTenantBillingPolicyCommand(
+ tenantId,
+ CollectionMode,
+ DefaultPaymentProvider,
+ AutoGenerateRenewal,
+ RenewalLeadDays,
+ Reason);
+ }
}
///
-/// 更新平台租户状态请求 DTO。
+/// 更新平台租户状态请求 DTO。
///
public sealed class UpdatePlatformTenantStatusDto
{
///
- /// 租户 ID。
+ /// 租户 ID。
///
[Required]
public Guid TenantId { get; set; }
///
- /// 状态。
+ /// 状态。
///
public TenantStatus Status { get; set; } = TenantStatus.Active;
+
///
- /// 原因。
+ /// 原因。
///
[StringLength(1000)]
public string? Reason { get; set; }
- public UpdatePlatformTenantStatusCommand ToCommand() => new(TenantId, Status, Reason);
+ public UpdatePlatformTenantStatusCommand ToCommand()
+ {
+ return new UpdatePlatformTenantStatusCommand(TenantId, Status, Reason);
+ }
}
///
-/// 新增或更新平台租户账务资料请求 DTO。
+/// 新增或更新平台租户账务资料请求 DTO。
///
public sealed class UpsertPlatformTenantBillingProfileDto
{
///
- /// 租户 ID。
+ /// 租户 ID。
///
[Required]
public Guid TenantId { get; set; }
///
- /// 账务名称。
+ /// 账务名称。
///
[StringLength(300)]
public string? BillingName { get; set; }
///
- /// 税号。
+ /// 税号。
///
[StringLength(100)]
public string? TaxId { get; set; }
///
- /// 联系人姓名。
+ /// 联系人姓名。
///
[StringLength(100)]
public string? ContactName { get; set; }
///
- /// 联系人手机号。
+ /// 联系人手机号。
///
[StringLength(32)]
public string? ContactPhone { get; set; }
///
- /// 联系人邮箱。
+ /// 联系人邮箱。
///
[StringLength(320)]
public string? ContactEmail { get; set; }
///
- /// 账务地址。
+ /// 账务地址。
///
[StringLength(1000)]
public string? BillingAddress { get; set; }
///
- /// 发票抬头。
+ /// 发票抬头。
///
[StringLength(300)]
public string? InvoiceTitle { get; set; }
///
- /// 发票类型。
+ /// 发票类型。
///
public TenantBillingInvoiceTitleType? InvoiceType { get; set; }
///
- /// 开户银行。
+ /// 开户银行。
///
[StringLength(300)]
public string? BankName { get; set; }
///
- /// 脱敏银行账号。
+ /// 脱敏银行账号。
///
[StringLength(100)]
public string? BankAccountMasked { get; set; }
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
- public UpsertPlatformTenantBillingProfileCommand ToCommand() => new(
- TenantId,
- BillingName,
- TaxId,
- ContactName,
- ContactPhone,
- ContactEmail,
- BillingAddress,
- InvoiceTitle,
- InvoiceType,
- BankName,
- BankAccountMasked,
- Metadata);
+ public UpsertPlatformTenantBillingProfileCommand ToCommand()
+ {
+ return new UpsertPlatformTenantBillingProfileCommand(
+ TenantId,
+ BillingName,
+ TaxId,
+ ContactName,
+ ContactPhone,
+ ContactEmail,
+ BillingAddress,
+ InvoiceTitle,
+ InvoiceType,
+ BankName,
+ BankAccountMasked,
+ Metadata);
+ }
}
///
-/// 新增或更新平台Staff请求 DTO。
+/// 新增或更新平台Staff请求 DTO。
///
public sealed class UpsertPlatformStaffDto
{
///
- /// 用户 ID。
+ /// 用户 ID。
///
public Guid? UserId { get; set; }
///
- /// 邮箱。
+ /// 邮箱。
///
[StringLength(320)]
public string? Email { get; set; }
///
- /// 手机号。
+ /// 手机号。
///
[StringLength(32)]
public string? Phone { get; set; }
///
- /// 名称。
+ /// 名称。
///
[StringLength(200)]
public string? Name { get; set; }
///
- /// 状态。
+ /// 状态。
///
public UserStatus Status { get; set; } = UserStatus.Active;
+
///
- /// 角色 ID 列表。
+ /// 角色 ID 列表。
///
public IReadOnlyCollection RoleIds { get; set; } = [];
- public UpsertPlatformStaffCommand ToCommand() => new(UserId, Email, Phone, Name, Status, RoleIds);
+ public UpsertPlatformStaffCommand ToCommand()
+ {
+ return new UpsertPlatformStaffCommand(UserId, Email, Phone, Name, Status, RoleIds);
+ }
}
///
-/// 更新平台Staff状态请求 DTO。
+/// 更新平台Staff状态请求 DTO。
///
public sealed class UpdatePlatformStaffStatusDto
{
///
- /// 用户 ID。
+ /// 用户 ID。
///
[Required]
public Guid UserId { get; set; }
///
- /// 状态。
+ /// 状态。
///
public UserStatus Status { get; set; } = UserStatus.Active;
///
- /// 原因。
+ /// 原因。
///
[StringLength(1000)]
public string? Reason { get; set; }
- public UpdatePlatformStaffStatusCommand ToCommand() => new(UserId, Status, Reason);
+ public UpdatePlatformStaffStatusCommand ToCommand()
+ {
+ return new UpdatePlatformStaffStatusCommand(UserId, Status, Reason);
+ }
}
///
-/// 更新平台审计Alert状态请求 DTO。
+/// 更新平台审计Alert状态请求 DTO。
///
public sealed class UpdatePlatformAuditAlertStatusDto
{
///
- /// 告警 ID。
+ /// 告警 ID。
///
[Required]
public Guid AlertId { get; set; }
///
- /// 状态。
+ /// 状态。
///
public PlatformAuditAlertStatus Status { get; set; } = PlatformAuditAlertStatus.Acknowledged;
///
- /// 处理备注。
+ /// 处理备注。
///
[StringLength(1000)]
public string? ResolutionNote { get; set; }
- public UpdatePlatformAuditAlertStatusCommand ToCommand() => new(AlertId, Status, ResolutionNote);
+ public UpdatePlatformAuditAlertStatusCommand ToCommand()
+ {
+ return new UpdatePlatformAuditAlertStatusCommand(AlertId, Status, ResolutionNote);
+ }
}
///
-/// 新增或更新平台DunningChannel请求 DTO。
+/// 新增或更新平台DunningChannel请求 DTO。
///
public sealed class UpsertPlatformBillingDunningChannelDto
{
///
- /// 通知渠道 ID。
+ /// 通知渠道 ID。
///
public Guid? ChannelId { get; set; }
///
- /// 渠道编码。
+ /// 渠道编码。
///
[Required]
[StringLength(100)]
public string ChannelCode { get; set; } = string.Empty;
///
- /// 名称。
+ /// 名称。
///
[Required]
[StringLength(200)]
public string Name { get; set; } = string.Empty;
///
- /// 说明。
+ /// 说明。
///
[StringLength(1000)]
public string? Description { get; set; }
///
- /// 是否启用。
+ /// 是否启用。
///
public bool Enabled { get; set; } = true;
+
///
- /// 服务提供方。
+ /// 服务提供方。
///
public PlatformBillingDunningProvider Provider { get; set; } = PlatformBillingDunningProvider.Generic;
///
- /// Webhook 地址。
+ /// Webhook 地址。
///
[Required]
[StringLength(2048)]
public string WebhookUrl { get; set; } = string.Empty;
///
- /// 密钥引用。
+ /// 密钥引用。
///
[StringLength(300)]
public string? SecretRef { get; set; }
///
- /// 提醒类型列表。
+ /// 提醒类型列表。
///
public IReadOnlyCollection ReminderTypes { get; set; } = ["overdue", "final_notice"];
+
///
- /// 提醒渠道列表。
+ /// 提醒渠道列表。
///
public IReadOnlyCollection ReminderChannels { get; set; } = ["internal"];
///
- /// 最低提醒级别。
+ /// 最低提醒级别。
///
[Range(1, 20)]
public int MinReminderLevel { get; set; } = 1;
///
- /// 租户 ID 列表。
+ /// 租户 ID 列表。
///
public IReadOnlyCollection TenantIds { get; set; } = [];
///
- /// 超时时长,单位为秒。
+ /// 超时时长,单位为秒。
///
[Range(1, 60)]
public int TimeoutSeconds { get; set; } = 10;
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
- public UpsertPlatformBillingDunningChannelCommand ToCommand() => new(
- ChannelId,
- ChannelCode,
- Name,
- Description,
- Enabled,
- Provider,
- WebhookUrl,
- SecretRef,
- ReminderTypes,
- ReminderChannels,
- MinReminderLevel,
- TenantIds,
- TimeoutSeconds,
- Metadata);
+ public UpsertPlatformBillingDunningChannelCommand ToCommand()
+ {
+ return new UpsertPlatformBillingDunningChannelCommand(
+ ChannelId,
+ ChannelCode,
+ Name,
+ Description,
+ Enabled,
+ Provider,
+ WebhookUrl,
+ SecretRef,
+ ReminderTypes,
+ ReminderChannels,
+ MinReminderLevel,
+ TenantIds,
+ TimeoutSeconds,
+ Metadata);
+ }
}
///
-/// 禁用平台DunningChannel请求 DTO。
+/// 禁用平台DunningChannel请求 DTO。
///
public sealed class DisablePlatformBillingDunningChannelDto
{
///
- /// 通知渠道 ID。
+ /// 通知渠道 ID。
///
[Required]
public Guid ChannelId { get; set; }
///
- /// 原因。
+ /// 原因。
///
[StringLength(1000)]
public string? Reason { get; set; }
- public DisablePlatformBillingDunningChannelCommand ToCommand() => new(ChannelId, Reason);
+ public DisablePlatformBillingDunningChannelCommand ToCommand()
+ {
+ return new DisablePlatformBillingDunningChannelCommand(ChannelId, Reason);
+ }
}
///
-/// 重试平台Dunning事件请求 DTO。
+/// 重试平台Dunning事件请求 DTO。
///
public sealed class RetryPlatformBillingDunningEventDto
{
///
- /// 事件 ID。
+ /// 事件 ID。
///
[Required]
public Guid EventId { get; set; }
///
- /// 原因。
+ /// 原因。
///
[StringLength(1000)]
public string? Reason { get; set; }
- public RetryPlatformBillingDunningEventCommand ToCommand() => new(EventId, Reason);
+ public RetryPlatformBillingDunningEventCommand ToCommand()
+ {
+ return new RetryPlatformBillingDunningEventCommand(EventId, Reason);
+ }
}
/// 人工确认或忽略催缴投递事件。
public sealed class ResolvePlatformBillingDunningEventDto
{
- [Required]
- public Guid EventId { get; set; }
+ [Required] public Guid EventId { get; set; }
- [Required, StringLength(1000, MinimumLength = 3)]
+ [Required]
+ [StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
- public ResolvePlatformBillingDunningEventCommand ToCommand() => new(EventId, Reason);
-}
+ public ResolvePlatformBillingDunningEventCommand ToCommand()
+ {
+ return new ResolvePlatformBillingDunningEventCommand(EventId, Reason);
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/PlatformApprovalDtos.cs b/Tiku.Api/Contracts/PlatformApprovalDtos.cs
index b5ff866..ecdf42e 100644
--- a/Tiku.Api/Contracts/PlatformApprovalDtos.cs
+++ b/Tiku.Api/Contracts/PlatformApprovalDtos.cs
@@ -5,7 +5,7 @@ using Tiku.Domain.Common;
namespace Tiku.Api.Contracts;
-public sealed record PlatformApprovalDecisionDto([Required, MaxLength(1000)] string Reason);
+public sealed record PlatformApprovalDecisionDto([Required] [MaxLength(1000)] string Reason);
public sealed record UpdatePlatformApprovalPolicyDto(
bool Enabled,
@@ -14,11 +14,14 @@ public sealed record UpdatePlatformApprovalPolicyDto(
[Range(1, 720)] int ExpiresAfterHours,
JsonElement? Conditions)
{
- public UpdatePlatformApprovalPolicyCommand ToCommand(string code) => new(
- code,
- Enabled,
- AlwaysRequireApproval,
- AmountThresholdCents,
- ExpiresAfterHours,
- Conditions?.Clone() ?? JsonDefaults.Object());
-}
+ public UpdatePlatformApprovalPolicyCommand ToCommand(string code)
+ {
+ return new UpdatePlatformApprovalPolicyCommand(
+ code,
+ Enabled,
+ AlwaysRequireApproval,
+ AmountThresholdCents,
+ ExpiresAfterHours,
+ Conditions?.Clone() ?? JsonDefaults.Object());
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/PlatformGovernanceDtos.cs b/Tiku.Api/Contracts/PlatformGovernanceDtos.cs
index 00b941c..e47183c 100644
--- a/Tiku.Api/Contracts/PlatformGovernanceDtos.cs
+++ b/Tiku.Api/Contracts/PlatformGovernanceDtos.cs
@@ -7,25 +7,47 @@ using Tiku.Domain.Platform;
namespace Tiku.Api.Contracts;
public sealed record SavePlatformConfigurationDraftDto(
- [Required, MaxLength(120)] string DefinitionCode,
- [Required, MaxLength(80)] string Environment,
+ [Required] [MaxLength(120)] string DefinitionCode,
+ [Required] [MaxLength(80)] string Environment,
JsonElement? Value,
[MaxLength(300)] string? SecretRef,
- [Required, MaxLength(1000)] string Reason)
+ [Required] [MaxLength(1000)] string Reason)
{
- public SavePlatformConfigurationDraftCommand ToCommand() => new(DefinitionCode, Environment, Value, SecretRef, Reason);
+ public SavePlatformConfigurationDraftCommand ToCommand()
+ {
+ return new SavePlatformConfigurationDraftCommand(DefinitionCode, Environment, Value, SecretRef, Reason);
+ }
}
-public sealed record PlatformRollbackDto([Required, MaxLength(1000)] string Reason);
-public sealed record UpsertPlatformNotificationTemplateDto(Guid? Id, [Required, MaxLength(120)] string Code,
- [Required, MaxLength(200)] string Name, PlatformNotificationChannel Channel,
- [Required, MaxLength(500)] string SubjectTemplate, [Required, MaxLength(8000)] string BodyTemplate,
- bool Enabled, JsonElement? Variables)
+
+public sealed record PlatformRollbackDto([Required] [MaxLength(1000)] string Reason);
+
+public sealed record UpsertPlatformNotificationTemplateDto(
+ Guid? Id,
+ [Required] [MaxLength(120)] string Code,
+ [Required] [MaxLength(200)] string Name,
+ PlatformNotificationChannel Channel,
+ [Required] [MaxLength(500)] string SubjectTemplate,
+ [Required] [MaxLength(8000)] string BodyTemplate,
+ bool Enabled,
+ JsonElement? Variables)
{
- public UpsertPlatformNotificationTemplateCommand ToCommand() => new(Id, Code, Name, Channel, SubjectTemplate, BodyTemplate, Enabled, Variables?.Clone() ?? JsonDefaults.Array());
+ public UpsertPlatformNotificationTemplateCommand ToCommand()
+ {
+ return new UpsertPlatformNotificationTemplateCommand(Id, Code, Name, Channel, SubjectTemplate, BodyTemplate,
+ Enabled,
+ Variables?.Clone() ?? JsonDefaults.Array());
+ }
}
-public sealed record SendPlatformNotificationDto(Guid TemplateId, [MinLength(1)] IReadOnlyCollection RoleCodes,
+
+public sealed record SendPlatformNotificationDto(
+ Guid TemplateId,
+ [MinLength(1)] IReadOnlyCollection RoleCodes,
IReadOnlyDictionary? Variables,
- [Required, MaxLength(200)] string IdempotencyKey)
+ [Required] [MaxLength(200)] string IdempotencyKey)
{
- public SendPlatformNotificationCommand ToCommand() => new(TemplateId, RoleCodes, Variables ?? new Dictionary(), IdempotencyKey);
-}
+ public SendPlatformNotificationCommand ToCommand()
+ {
+ return new SendPlatformNotificationCommand(TemplateId, RoleCodes, Variables ?? new Dictionary(),
+ IdempotencyKey);
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/PlatformTenantCapabilitiesDtos.cs b/Tiku.Api/Contracts/PlatformTenantCapabilitiesDtos.cs
index 4e77481..44df51a 100644
--- a/Tiku.Api/Contracts/PlatformTenantCapabilitiesDtos.cs
+++ b/Tiku.Api/Contracts/PlatformTenantCapabilitiesDtos.cs
@@ -9,398 +9,497 @@ using Tiku.Domain.Tenancy;
namespace Tiku.Api.Contracts;
///
-/// 平台租户能力通用查询参数。
+/// 平台租户能力通用查询参数。
///
public class PlatformCapabilityQueryDto
{
///
- /// 租户 ID。
+ /// 租户 ID。
///
public Guid? TenantId { get; set; }
+
///
- /// 状态。
+ /// 状态。
///
[StringLength(50)]
public string? Status { get; set; }
+
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 500)]
public int Limit { get; set; } = 100;
- public PlatformCapabilityQuery ToQuery() => new(TenantId, Status, Limit);
+ public PlatformCapabilityQuery ToQuery()
+ {
+ return new PlatformCapabilityQuery(TenantId, Status, Limit);
+ }
}
///
-/// 新增或更新租户 CRM 配置请求。
+/// 新增或更新租户 CRM 配置请求。
///
public sealed class UpsertPlatformCrmConfigDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 租户 ID。
+ /// 租户 ID。
///
[Required]
public Guid TenantId { get; set; }
+
///
- /// 是否启用。
+ /// 是否启用。
///
public bool Enabled { get; set; }
+
///
- /// 回调地址。
+ /// 回调地址。
///
[StringLength(2048)]
public string? Url { get; set; }
+
///
- /// 密钥引用。
+ /// 密钥引用。
///
[StringLength(300)]
public string? SecretRef { get; set; }
+
///
- /// 表单名称。
+ /// 表单名称。
///
[StringLength(200)]
public string? FormName { get; set; }
+
///
- /// 考试类型。
+ /// 考试类型。
///
[StringLength(100)]
public string? ExamType { get; set; }
+
///
- /// 超时时长,单位为秒。
+ /// 超时时长,单位为秒。
///
[Range(1, 120)]
public int? TimeoutSeconds { get; set; }
+
///
- /// 延迟秒数。
+ /// 延迟秒数。
///
[Range(0, 86400)]
public int? DelaySeconds { get; set; }
+
///
- /// 分配模式。
+ /// 分配模式。
///
[StringLength(50)]
public string? AssignmentMode { get; set; }
+
///
- /// 分配池。
+ /// 分配池。
///
public JsonElement? AssignmentPool { get; set; }
+
///
- /// 分配配置。
+ /// 分配配置。
///
public JsonElement? AssignmentConfig { get; set; }
- public UpsertPlatformCrmConfigCommand ToCommand() =>
- new(Id, TenantId, Enabled, Url, SecretRef, FormName, ExamType, TimeoutSeconds, DelaySeconds, AssignmentMode, AssignmentPool, AssignmentConfig);
+ public UpsertPlatformCrmConfigCommand ToCommand()
+ {
+ return new UpsertPlatformCrmConfigCommand(Id, TenantId, Enabled, Url, SecretRef, FormName, ExamType,
+ TimeoutSeconds, DelaySeconds,
+ AssignmentMode, AssignmentPool, AssignmentConfig);
+ }
}
///
-/// 重试租户 CRM 线索推送请求。
+/// 重试租户 CRM 线索推送请求。
///
public sealed class RetryPlatformCrmLeadDto
{
///
- /// 队列任务 ID。
+ /// 队列任务 ID。
///
[Required]
public Guid QueueId { get; set; }
+
///
- /// 备注。
+ /// 备注。
///
[StringLength(500)]
public string? Note { get; set; }
- public PlatformCrmLeadRetryCommand ToCommand() => new(QueueId, Note);
+ public PlatformCrmLeadRetryCommand ToCommand()
+ {
+ return new PlatformCrmLeadRetryCommand(QueueId, Note);
+ }
}
///
-/// 平台租户 CRM 日志查询参数。
+/// 平台租户 CRM 日志查询参数。
///
public sealed class PlatformCrmLogQueryDto : PlatformCapabilityQueryDto
{
///
- /// 队列任务 ID。
+ /// 队列任务 ID。
///
public Guid? QueueId { get; set; }
}
///
-/// 新增或更新租户短信渠道请求。
+/// 新增或更新租户短信渠道请求。
///
public sealed class UpsertPlatformSmsChannelDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 租户 ID。
+ /// 租户 ID。
///
[Required]
public Guid TenantId { get; set; }
+
///
- /// 服务提供方。
+ /// 服务提供方。
///
- [Required, StringLength(80)]
+ [Required]
+ [StringLength(80)]
public string Provider { get; set; } = "generic";
+
///
- /// 名称。
+ /// 名称。
///
- [Required, StringLength(200)]
+ [Required]
+ [StringLength(200)]
public string Name { get; set; } = string.Empty;
+
///
- /// 短信签名。
+ /// 短信签名。
///
- [Required, StringLength(100)]
+ [Required]
+ [StringLength(100)]
public string Signature { get; set; } = string.Empty;
+
///
- /// 使用场景。
+ /// 使用场景。
///
- [Required, StringLength(100)]
+ [Required]
+ [StringLength(100)]
public string Scene { get; set; } = "login";
+
///
- /// 状态。
+ /// 状态。
///
public TenantExternalProviderStatus Status { get; set; } = TenantExternalProviderStatus.Disabled;
+
///
- /// 密钥引用。
+ /// 密钥引用。
///
[StringLength(300)]
public string? SecretRef { get; set; }
+
///
- /// 优先级。
+ /// 优先级。
///
public int? Priority { get; set; }
+
///
- /// 月度配额。
+ /// 月度配额。
///
[Range(0, int.MaxValue)]
public int? MonthlyQuota { get; set; }
+
///
- /// 公开配置内容。
+ /// 公开配置内容。
///
public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
- public UpsertPlatformSmsChannelCommand ToCommand() =>
- new(Id, TenantId, Provider, Name, Signature, Scene, Status, SecretRef, Priority, MonthlyQuota, ConfigPublic, Metadata);
+ public UpsertPlatformSmsChannelCommand ToCommand()
+ {
+ return new UpsertPlatformSmsChannelCommand(Id, TenantId, Provider, Name, Signature, Scene, Status, SecretRef,
+ Priority, MonthlyQuota,
+ ConfigPublic, Metadata);
+ }
}
///
-/// 新增或更新租户短信模板请求。
+/// 新增或更新租户短信模板请求。
///
public sealed class UpsertPlatformSmsTemplateDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 租户 ID。
+ /// 租户 ID。
///
[Required]
public Guid TenantId { get; set; }
+
///
- /// 短信渠道 ID。
+ /// 短信渠道 ID。
///
[Required]
public Guid ChannelId { get; set; }
+
///
- /// 编码。
+ /// 编码。
///
- [Required, StringLength(120)]
+ [Required]
+ [StringLength(120)]
public string Code { get; set; } = string.Empty;
+
///
- /// 名称。
+ /// 名称。
///
- [Required, StringLength(200)]
+ [Required]
+ [StringLength(200)]
public string Name { get; set; } = string.Empty;
+
///
- /// 类型。
+ /// 类型。
///
public SmsTemplateType Type { get; set; } = SmsTemplateType.Notification;
+
///
- /// 审核状态。
+ /// 审核状态。
///
public SmsTemplateAuditStatus AuditStatus { get; set; } = SmsTemplateAuditStatus.Draft;
+
///
- /// 状态。
+ /// 状态。
///
public SmsTemplateStatus Status { get; set; } = SmsTemplateStatus.Active;
+
///
- /// 渠道模板编码。
+ /// 渠道模板编码。
///
[StringLength(120)]
public string? ProviderTemplateCode { get; set; }
+
///
- /// 模板内容。
+ /// 模板内容。
///
- [Required, StringLength(1000)]
+ [Required]
+ [StringLength(1000)]
public string Content { get; set; } = string.Empty;
+
///
- /// Remark。
+ /// Remark。
///
[StringLength(500)]
public string? Remark { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
- public UpsertPlatformSmsTemplateCommand ToCommand() =>
- new(Id, TenantId, ChannelId, Code, Name, Type, AuditStatus, Status, ProviderTemplateCode, Content, Remark, Metadata);
+ public UpsertPlatformSmsTemplateCommand ToCommand()
+ {
+ return new UpsertPlatformSmsTemplateCommand(Id, TenantId, ChannelId, Code, Name, Type, AuditStatus, Status,
+ ProviderTemplateCode, Content,
+ Remark, Metadata);
+ }
}
///
-/// 新增或更新平台支付应用请求。
+/// 新增或更新平台支付应用请求。
///
public sealed class UpsertPlatformPaymentAppDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 支付应用编码。
+ /// 支付应用编码。
///
- [Required, StringLength(100)]
+ [Required]
+ [StringLength(100)]
public string AppCode { get; set; } = string.Empty;
+
///
- /// 支付应用名称。
+ /// 支付应用名称。
///
- [Required, StringLength(200)]
+ [Required]
+ [StringLength(200)]
public string AppName { get; set; } = string.Empty;
+
///
- /// 状态。
+ /// 状态。
///
public PlatformPaymentAppStatus Status { get; set; } = PlatformPaymentAppStatus.Disabled;
+
///
- /// 结算模式。
+ /// 结算模式。
///
[StringLength(100)]
public string SettlementMode { get; set; } = "PlatformCollect";
+
///
- /// 说明。
+ /// 说明。
///
[StringLength(500)]
public string? Description { get; set; }
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
- public UpsertPlatformPaymentAppCommand ToCommand() =>
- new(Id, AppCode, AppName, Status, SettlementMode, Description, Metadata);
+ public UpsertPlatformPaymentAppCommand ToCommand()
+ {
+ return new UpsertPlatformPaymentAppCommand(Id, AppCode, AppName, Status, SettlementMode, Description, Metadata);
+ }
}
///
-/// 新增或更新平台支付渠道请求。
+/// 新增或更新平台支付渠道请求。
///
public sealed class UpsertPlatformPaymentChannelDto
{
///
- /// ID。
+ /// ID。
///
public Guid? Id { get; set; }
+
///
- /// 支付应用 ID。
+ /// 支付应用 ID。
///
[Required]
public Guid AppId { get; set; }
+
///
- /// 服务提供方。
+ /// 服务提供方。
///
- [Required, StringLength(80)]
+ [Required]
+ [StringLength(80)]
public string Provider { get; set; } = "manual";
+
///
- /// 模式。
+ /// 模式。
///
[StringLength(100)]
public string Mode { get; set; } = "PlatformCollect";
+
///
- /// 状态。
+ /// 状态。
///
public PlatformPaymentChannelStatus Status { get; set; } = PlatformPaymentChannelStatus.Disabled;
+
///
- /// 显示名称。
+ /// 显示名称。
///
- [Required, StringLength(200)]
+ [Required]
+ [StringLength(200)]
public string DisplayName { get; set; } = string.Empty;
+
///
- /// 密钥引用。
+ /// 密钥引用。
///
[StringLength(300)]
public string? SecretRef { get; set; }
+
///
- /// 回调路径。
+ /// 回调路径。
///
[StringLength(500)]
public string? CallbackPath { get; set; }
+
///
- /// 优先级。
+ /// 优先级。
///
public int? Priority { get; set; }
+
///
- /// 公开配置内容。
+ /// 公开配置内容。
///
public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
- public UpsertPlatformPaymentChannelCommand ToCommand() =>
- new(Id, AppId, Provider, Mode, Status, DisplayName, SecretRef, CallbackPath, Priority, ConfigPublic, Metadata);
+ public UpsertPlatformPaymentChannelCommand ToCommand()
+ {
+ return new UpsertPlatformPaymentChannelCommand(Id, AppId, Provider, Mode, Status, DisplayName, SecretRef,
+ CallbackPath, Priority, ConfigPublic,
+ Metadata);
+ }
}
///
-/// 新增或更新租户支付应用请求。
+/// 新增或更新租户支付应用请求。
///
public sealed class UpsertPlatformTenantPaymentAppDto
{
///
- /// 租户 ID。
+ /// 租户 ID。
///
[Required]
public Guid TenantId { get; set; }
+
///
- /// 服务提供方。
+ /// 服务提供方。
///
- [Required, StringLength(80)]
+ [Required]
+ [StringLength(80)]
public string Provider { get; set; } = "manual";
+
///
- /// 状态。
+ /// 状态。
///
public TenantExternalProviderStatus Status { get; set; } = TenantExternalProviderStatus.Disabled;
+
///
- /// 显示名称。
+ /// 显示名称。
///
[StringLength(200)]
public string? DisplayName { get; set; }
+
///
- /// 密钥引用。
+ /// 密钥引用。
///
[StringLength(300)]
public string? SecretRef { get; set; }
+
///
- /// 优先级。
+ /// 优先级。
///
public int? Priority { get; set; }
+
///
- /// 公开配置内容。
+ /// 公开配置内容。
///
public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();
+
///
- /// 扩展元数据。
+ /// 扩展元数据。
///
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
- public UpsertTenantExternalProviderCommand ToCommand() =>
- new(TenantExternalProviderCapability.Payment, Provider, Status, DisplayName, SecretRef, Priority, ConfigPublic, Metadata);
-}
+ public UpsertTenantExternalProviderCommand ToCommand()
+ {
+ return new UpsertTenantExternalProviderCommand(TenantExternalProviderCapability.Payment, Provider, Status,
+ DisplayName, SecretRef, Priority,
+ ConfigPublic, Metadata);
+ }
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/PointDtos.cs b/Tiku.Api/Contracts/PointDtos.cs
index 5a1ddd1..7aef5fd 100644
--- a/Tiku.Api/Contracts/PointDtos.cs
+++ b/Tiku.Api/Contracts/PointDtos.cs
@@ -4,24 +4,24 @@ using Tiku.Application.Points;
namespace Tiku.Api.Contracts;
///
-/// 积分查询参数。
+/// 积分查询参数。
///
public sealed class PointQueryDto
{
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 200)]
public int? Limit { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(32)]
public string? Status { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
@@ -32,25 +32,25 @@ public sealed class PointQueryDto
}
///
-/// 领取积分任务请求 DTO。
+/// 领取积分任务请求 DTO。
///
public sealed class ClaimPointTaskDto
{
///
- /// 任务键。
+ /// 任务键。
///
[Required]
[StringLength(100)]
public string TaskKey { get; set; } = string.Empty;
///
- /// 来源类型。
+ /// 来源类型。
///
[StringLength(100)]
public string? SourceType { get; set; }
///
- /// 来源 ID。
+ /// 来源 ID。
///
public Guid? SourceId { get; set; }
@@ -61,12 +61,12 @@ public sealed class ClaimPointTaskDto
}
///
-/// 创建积分兑换订单请求 DTO。
+/// 创建积分兑换订单请求 DTO。
///
public sealed class CreatePointExchangeOrderDto
{
///
- /// 兑换项 ID。
+ /// 兑换项 ID。
///
[Required]
public Guid ItemId { get; set; }
@@ -75,4 +75,4 @@ public sealed class CreatePointExchangeOrderDto
{
return new CreatePointExchangeOrderCommand(ItemId);
}
-}
+}
\ No newline at end of file
diff --git a/Tiku.Api/Contracts/ProfileDtos.cs b/Tiku.Api/Contracts/ProfileDtos.cs
index 45c3c9c..f0a620f 100644
--- a/Tiku.Api/Contracts/ProfileDtos.cs
+++ b/Tiku.Api/Contracts/ProfileDtos.cs
@@ -5,105 +5,111 @@ using Tiku.Application.Profile;
namespace Tiku.Api.Contracts;
///
-/// 资料查询参数。
+/// 资料查询参数。
///
public sealed class ProfileQueryDto
{
///
- /// 最近记录数量上限。
+ /// 最近记录数量上限。
///
[Range(1, 50)]
public int? RecentLimit { get; set; }
///
- /// 返回数量上限。
+ /// 返回数量上限。
///
[Range(1, 20)]
public int? Limit { get; set; }
///
- /// 状态。
+ /// 状态。
///
[StringLength(32)]
public string? Status { get; set; }
///
- /// 类型。
+ /// 类型。
///
[StringLength(50)]
public string? Type { get; set; }
///
- /// 分类。
+ /// 分类。
///
[StringLength(50)]
public string? Category { get; set; }
///
- /// 是否包含锁定资源。
+ /// 是否包含锁定资源。
///
public bool IncludeLocked { get; set; }
///
- /// 来源类型。
+ /// 来源类型。
///
[StringLength(100)]
public string? SourceType { get; set; }
///
- /// 开始时间。
+ /// 开始时间。
///
public DateTimeOffset? From { get; set; }
///
- /// 结束时间。
+ /// 结束时间。
///
public DateTimeOffset? To { get; set; }
}
///
-/// 更新资料请求 DTO。
+/// 更新资料请求 DTO。
///
public sealed class UpdateProfileDto
{
///
- /// 名称。
+ /// 名称。
///
[StringLength(100)]
public string? Name { get; set; }
///
- /// 头像预设。
+ /// 头像预设。
///
[StringLength(32)]
public string? AvatarPreset { get; set; }
///
- /// 地区 ID。
+ /// 地区 ID。
///
public Guid? RegionId { get; set; }
+
///
- /// 已选择院校 ID。
+ /// 已选择院校 ID。
///
public Guid? SelectedSchoolId { get; set; }
+
///
- /// 已选择专业 ID。
+ /// 已选择专业 ID。
///
public Guid? SelectedMajorId { get; set; }
+
///
- /// 统计数据。
+ /// 统计数据。
///
public JsonElement? Stats { get; set; }
+
///
- /// 进度数据。
+ /// 进度数据。
///
public JsonElement? Progress { get; set; }
+
///
- /// 模块选择数据。
+ /// 模块选择数据。
///
public JsonElement? ModuleSelections { get; set; }
+
///
- /// 最近活动数据。
+ /// 最近活动数据。
///
public JsonElement? RecentActivities { get; set; }
@@ -123,12 +129,12 @@ public sealed class UpdateProfileDto
}
///
-/// 通知状态请求 DTO。
+/// 通知状态请求 DTO。
///
public sealed class NotificationStatusDto
{
///
- /// 通知 ID 列表。
+ /// 通知 ID 列表。
///
[Required]
[MinLength(1)]
@@ -136,7 +142,7 @@ public sealed class NotificationStatusDto
public IReadOnlyCollection NotificationIds { get; set; } = [];
///
- /// 状态。
+ /// 状态。
///
[StringLength(32)]
public string? Status { get; set; }
@@ -148,58 +154,59 @@ public sealed class NotificationStatusDto
}
///
-/// 提交反馈请求 DTO。
+/// 提交反馈请求 DTO。
///
public sealed class SubmitFeedbackDto
{
///
- /// 题目 ID。
+ /// 题目 ID。
///
public Guid? QuestionId { get; set; }
///
- /// 类型。
+ /// 类型。
///
[StringLength(50)]
public string? Type { get; set; }
///
- /// 分类。
+ /// 分类。
///
[StringLength(100)]
public string? Category { get; set; }
///
- /// 标题。
+ /// 标题。
///
[StringLength(200)]
public string? Title { get; set; }
///
- /// 说明。
+ /// 说明。
///
[Required]
[StringLength(5000)]
public string Description { get; set; } = string.Empty;
///
- /// 优先级。
+ /// 优先级。
///
[StringLength(32)]
public string? Priority { get; set; }
///
- /// 联系方式。
+ /// 联系方式。
///
[StringLength(200)]
public string? Contact { get; set; }
///
- /// 附件列表。
+ /// 附件列表。
///
public JsonElement Attachments { get; set; } = JsonSerializer.SerializeToElement(Array.Empty