Browse Source

网关

集成Redis
郑勃旭 2 years ago
parent
commit
fb86bdc8c3
  1. 25
      be/Web.Gateway/Web.Gateway.sln
  2. 12
      be/Web.Gateway/Web.Gateway/.config/dotnet-tools.json
  3. 52
      be/Web.Gateway/Web.Gateway/Controllers/AccountController.cs
  4. 30
      be/Web.Gateway/Web.Gateway/Controllers/ConfigController.cs
  5. 30
      be/Web.Gateway/Web.Gateway/Controllers/GatewayController.cs
  6. 236
      be/Web.Gateway/Web.Gateway/Controllers/HomeController.cs
  7. 19
      be/Web.Gateway/Web.Gateway/Controllers/TestController.cs
  8. 37
      be/Web.Gateway/Web.Gateway/Hubs/PageHub.cs
  9. 11
      be/Web.Gateway/Web.Gateway/Models/InfluxResult.cs
  10. 9
      be/Web.Gateway/Web.Gateway/Models/InfluxResults.cs
  11. 13
      be/Web.Gateway/Web.Gateway/Models/InfluxSeries.cs
  12. 27
      be/Web.Gateway/Web.Gateway/Models/LogModel.cs
  13. 15
      be/Web.Gateway/Web.Gateway/Models/LoginModel.cs
  14. 17
      be/Web.Gateway/Web.Gateway/Models/QueryLogModel.cs
  15. 7
      be/Web.Gateway/Web.Gateway/Models/RenderingModel.cs
  16. 112
      be/Web.Gateway/Web.Gateway/Program.cs
  17. 21
      be/Web.Gateway/Web.Gateway/Properties/PublishProfiles/FolderProfile.pubxml
  18. 38
      be/Web.Gateway/Web.Gateway/Properties/launchSettings.json
  19. 20
      be/Web.Gateway/Web.Gateway/Views/Account/Login.cshtml
  20. 27
      be/Web.Gateway/Web.Gateway/Views/Config/Edit.cshtml
  21. 66
      be/Web.Gateway/Web.Gateway/Views/Config/Index.cshtml
  22. 27
      be/Web.Gateway/Web.Gateway/Views/Gateway/Edit.cshtml
  23. 66
      be/Web.Gateway/Web.Gateway/Views/Gateway/Index.cshtml
  24. 150
      be/Web.Gateway/Web.Gateway/Views/Home/Index.cshtml
  25. 77
      be/Web.Gateway/Web.Gateway/Views/Shared/_Layout.cshtml
  26. 3
      be/Web.Gateway/Web.Gateway/Views/_ViewImports.cshtml
  27. 3
      be/Web.Gateway/Web.Gateway/Views/_ViewStart.cshtml
  28. 28
      be/Web.Gateway/Web.Gateway/Web.Gateway.csproj
  29. 44
      be/Web.Gateway/Web.Gateway/appsettings.Development.json
  30. 2
      be/Web.Gateway/Web.Gateway/appsettings.Production.json
  31. 101
      be/Web.Gateway/Web.Gateway/appsettings.json
  32. 1
      be/Web.Gateway/Web.Gateway/wwwroot/lib/codeflask.min.js
  33. 2
      be/Web.Gateway/Web.Gateway/wwwroot/lib/fecha.min.js
  34. 1
      be/Web.Gateway/Web.Gateway/wwwroot/lib/micromodal.min.js
  35. 1
      be/Web.Gateway/Web.Gateway/wwwroot/lib/pubsub.min.js
  36. 11
      be/Web.Gateway/Web.Gateway/wwwroot/lib/pure-min.css
  37. 2
      be/Web.Gateway/Web.Gateway/wwwroot/lib/signalr.min.js
  38. 1
      be/Web.Gateway/Web.Gateway/wwwroot/lib/vue.global.prod.js
  39. 165
      be/Web.Gateway/Web.Gateway/wwwroot/settings/appsettings.Development.json
  40. 154
      be/Web.Gateway/Web.Gateway/wwwroot/settings/appsettings.json

25
be/Web.Gateway/Web.Gateway.sln

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33801.468
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web.Gateway", "Web.Gateway\Web.Gateway.csproj", "{F7D9A48F-16DD-4ED2-A7DD-93BFF6C51F72}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F7D9A48F-16DD-4ED2-A7DD-93BFF6C51F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7D9A48F-16DD-4ED2-A7DD-93BFF6C51F72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7D9A48F-16DD-4ED2-A7DD-93BFF6C51F72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7D9A48F-16DD-4ED2-A7DD-93BFF6C51F72}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {931AE41B-0CBC-4C24-965E-BC13FFA740B6}
EndGlobalSection
EndGlobal

12
be/Web.Gateway/Web.Gateway/.config/dotnet-tools.json

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "7.0.4",
"commands": [
"dotnet-ef"
]
}
}
}

52
be/Web.Gateway/Web.Gateway/Controllers/AccountController.cs

@ -0,0 +1,52 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Web.Gateway.Models;
namespace Web.Gateway.Controllers;
public class AccountController : Controller
{
[AllowAnonymous]
[HttpGet]
public IActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Login(LoginModel model, string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
if (ModelState.IsValid)
{
if (model.UserName == "admin" && model.Password == "aA123456!")
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.UserName),
new Claim(ClaimTypes.Role, "Administrator"),
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity)).ConfigureAwait(false);
return LocalRedirect(returnUrl ?? Url.Content("~/"));
}
ModelState.AddModelError("", "用户名或密码错误");
}
return View(model);
}
[Authorize]
[HttpPost]
public async Task<IActionResult> Logout(string returnUrl)
{
await HttpContext.SignOutAsync().ConfigureAwait(false);
return RedirectToAction("Index", "Home");
}
}

30
be/Web.Gateway/Web.Gateway/Controllers/ConfigController.cs

@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Web.Gateway.Controllers;
[Authorize]
public class ConfigController : Controller
{
public IActionResult Index()
{
var files = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "settings"), "*.json")
.Select(o => new { File = o, Content = System.IO.File.ReadAllText(o) })
.ToDictionary(o => o.File, o => o.Content);
return View(files);
}
[HttpGet]
public IActionResult Edit(string file)
{
return View(model:file);
}
[HttpPost]
public IActionResult Edit(string file, string content)
{
using var sw = new StreamWriter(file);
sw.Write(content);
return RedirectToAction("Index");
}
}

30
be/Web.Gateway/Web.Gateway/Controllers/GatewayController.cs

@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Web.Gateway.Controllers;
[Authorize]
public class GatewayController : Controller
{
public IActionResult Index()
{
var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "appsettings*.json")
.Select(o => new { File = o, Content = System.IO.File.ReadAllText(o) })
.ToDictionary(o => o.File, o => o.Content);
return View(files);
}
[HttpGet]
public IActionResult Edit(string file)
{
return View(model: file);
}
[HttpPost]
public IActionResult Edit(string file, string content)
{
using var sw = new StreamWriter(file);
sw.Write(content);
return RedirectToAction("Index");
}
}

236
be/Web.Gateway/Web.Gateway/Controllers/HomeController.cs

@ -0,0 +1,236 @@
using System.Globalization;
using System.Text;
using System.Text.Json;
using Flurl;
using Flurl.Util;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Web.Gateway.Models;
namespace Web.Gateway;
public class HomeController : Controller
{
private const string Table = "log";
private const string TagKey = "ApplicationName";
private const string TimeKey = "Time";
private readonly Dictionary<string, string> _connectionValues;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IHubContext<PageHub> _hubContext;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger,
IConfiguration configuration,
IHttpClientFactory httpClientFactory,
IHubContext<PageHub> hubContext)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
_hubContext = hubContext;
_connectionValues = configuration.GetConnectionString("InfluxDB")
.Split(';', StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.Split('=', StringSplitOptions.RemoveEmptyEntries))
.ToDictionary(o => o[0].ToLowerInvariant(), o => o[1]);
}
[HttpGet]
[Authorize]
public async Task<IActionResult> Index(QueryLogModel model)
{
try
{
if (!model.UseCustom || string.IsNullOrEmpty(model.Query))
{
if (!model.Start.HasValue)
{
model.Start = DateTime.Now.Date;
}
if (!model.End.HasValue)
{
model.End = DateTime.Now.Date.AddDays(1);
}
var start = model.Start.Value.ToUniversalTime().ToInvariantString();
var end = model.End.Value.ToUniversalTime().ToInvariantString();
var query = $"select * from {Table} where time>='{start}' and time<='{end}' ";
if (!string.IsNullOrEmpty(model.ApplicationName))
{
query += $"and {nameof(model.ApplicationName)}='{model.ApplicationName}' ";
}
else
{
model.ApplicationName = string.Empty;
}
if (!string.IsNullOrEmpty(model.Level))
{
query += $"and {nameof(model.Level)}='{model.Level}' ";
}
else
{
model.Level = string.Empty;
}
query += $"order by time desc ";
query += $"limit {model.PageSize} offset {(model.PageIndex - 1) * model.PageSize}";
model.Query = query;
}
var result = await QueryInfluxDB($"{model.Query}").ConfigureAwait(false);
if (result != null)
{
model.Items = result.Values.Select(o =>
{
var dict = new Dictionary<string, string>();
for (int i = 0; i < result.Columns.Count; i++)
{
dict.Add(result.Columns[i], o[i]);
}
return dict;
}).ToList();
}
// tags
var tagQuery = $"show tag values on {_connectionValues["database"]} with key={TagKey}";
var tagResult = await QueryInfluxDB(tagQuery).ConfigureAwait(false);
if (tagResult != null)
{
model.Tags = tagResult.Values.Select(o => o[1]).ToList();
}
}
catch (Exception ex)
{
_logger.LogError(ex, ex.ToString());
ModelState.AddModelError("", ex.Message);
}
return View(model);
}
[HttpPost]
public async Task<IActionResult> Index()
{
if (!Request.Body.CanSeek)
{
Request.EnableBuffering();
}
Request.Body.Position = 0;
var reader = new StreamReader(Request.Body, Encoding.UTF8);
var body = await reader.ReadToEndAsync().ConfigureAwait(false);
Request.Body.Position = 0;
var list = JsonSerializer.Deserialize<List<LogModel>>(body!)!;
using var client = new InfluxDBClient(_connectionValues["url"],
_connectionValues["usr"],
_connectionValues["pwd"],
_connectionValues["database"],
_connectionValues["retention-policy"]);
using var writeApi = client.GetWriteApi();
var dicts = list.Select(o =>
{
var dict = new Dictionary<string, string>
{
{ TimeKey,new DateTimeOffset(o.Timestamp).ToInvariantString()},
{ TagKey, o.Properties?[TagKey].ToString()! },
{ nameof(o.Level), o.Level },
};
if (o.Exception != null)
{
dict.Add(nameof(o.Exception), o.Exception);
}
if (o.MessageTemplate != null)
{
dict.Add(nameof(o.MessageTemplate), o.MessageTemplate);
}
if (o.RenderedMessage != null)
{
dict.Add(nameof(o.RenderedMessage), o.RenderedMessage);
}
if (o.Properties != null)
{
foreach (var item in o.Properties.Where(o => o.Key != TagKey && o.Value != null))
{
if (item.Key == "EventId")
{
var eventProperties = item.Value as JsonElement?;
if (eventProperties != null)
{
if (eventProperties.Value.TryGetProperty("Id", out JsonElement eventId))
{
dict.Add("EventId", eventId.ToString());
}
}
if (eventProperties != null)
{
if (eventProperties.Value.TryGetProperty("Name", out JsonElement eventName))
{
dict.Add("EventName", eventName.ToString());
}
}
}
else
{
dict.Add(item.Key, item.Value.ToString()!);
}
}
}
if (o.Renderings != null)
{
foreach (var item in o.Renderings)
{
foreach (var item2 in item.Value)
{
dict.Add($"{item.Key}_{item2.Format}", item2.Rendering);
}
}
}
return dict;
});
var points = dicts.Select(o =>
{
var point = PointData.Measurement(Table);
foreach (var key in o.Keys)
{
if (key == TimeKey)
{
point = point.Timestamp(DateTime.Parse(o[key], CultureInfo.InvariantCulture), WritePrecision.Ms);
}
else if (key == TagKey)
{
point = point.Tag(TagKey, o[key]);
}
else
{
point = point.Field(key, o[key]);
}
}
return point;
}).ToList();
writeApi.WritePoints(points);
await _hubContext.Clients.Group("tail").SendAsync("notify", dicts.Reverse()).ConfigureAwait(false);
return Ok();
}
private async Task<InfluxSeries?> QueryInfluxDB(string query)
{
var url = _connectionValues["url"]
.AppendPathSegment("query")
.SetQueryParam("db", _connectionValues["database"])
.SetQueryParam("q", query!)
.ToString();
var result = await _httpClientFactory.CreateClient().GetAsync(url).ConfigureAwait(false);
var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
var results = JsonSerializer.Deserialize<InfluxResults>(content)!;
if (results.Results.Count > 0 && results.Results[0].Series.Count > 0)
{
return results.Results[0].Series[0];
}
return null;
}
[HttpPost]
[Route("/test")]
public string UploadTest([FromForm] IFormFileCollection files,string test)
{
return "ok";
}
}

19
be/Web.Gateway/Web.Gateway/Controllers/TestController.cs

@ -0,0 +1,19 @@
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
namespace Web.Gateway.Controllers;
public class TestController : Controller
{
private readonly IConfiguration _configuration;
public TestController(IConfiguration configuration)
{
this._configuration = configuration;
}
public IActionResult Index()
{
return Json(this._configuration.AsEnumerable(),new JsonSerializerOptions { WriteIndented=true });
}
}

37
be/Web.Gateway/Web.Gateway/Hubs/PageHub.cs

@ -0,0 +1,37 @@
using Microsoft.AspNetCore.SignalR;
public class PageHub : Hub
{
private readonly ILogger<PageHub> _logger;
public PageHub(ILogger<PageHub> logger)
{
this._logger = logger;
}
public override Task OnConnectedAsync()
{
this._logger.LogInformation($"{Context.ConnectionId} has connected");
this.Groups.AddToGroupAsync(Context.ConnectionId, Context.ConnectionId);
this.Clients.Group(Context.ConnectionId).SendAsync("connected", Context.ConnectionId);
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception? exception)
{
this._logger.LogInformation($"{Context.ConnectionId} has disconnected: {exception}");
return base.OnDisconnectedAsync(exception);
}
public void SetTail(bool enabled, string connectionId)
{
var groupName = "tail";
if (enabled)
{
this.Groups.AddToGroupAsync(connectionId, groupName);
}
else
{
this.Groups.RemoveFromGroupAsync(connectionId, groupName);
}
}
}

11
be/Web.Gateway/Web.Gateway/Models/InfluxResult.cs

@ -0,0 +1,11 @@
using System.Text.Json.Serialization;
namespace Web.Gateway.Models;
public class InfluxResult
{
[JsonPropertyName("statement_id")]
public int StatementId { get; set; }
[JsonPropertyName("series")]
public List<InfluxSeries> Series { get; set; } = new List<InfluxSeries>();
}

9
be/Web.Gateway/Web.Gateway/Models/InfluxResults.cs

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Web.Gateway.Models;
public class InfluxResults
{
[JsonPropertyName("results")]
public List<InfluxResult> Results { get; set; } = new List<InfluxResult>();
}

13
be/Web.Gateway/Web.Gateway/Models/InfluxSeries.cs

@ -0,0 +1,13 @@
using System.Text.Json.Serialization;
namespace Web.Gateway.Models;
public class InfluxSeries
{
[JsonPropertyName("name")]
public string Name { get; set; } = null!;
[JsonPropertyName("columns")]
public List<string> Columns { get; set; }=new List<string>();
[JsonPropertyName("values")]
public List<List<string>> Values { get; set; } = new List<List<string>>();
}

27
be/Web.Gateway/Web.Gateway/Models/LogModel.cs

@ -0,0 +1,27 @@
using System.Text.Json.Serialization;
namespace Web.Gateway.Models;
public class LogModel
{
[JsonPropertyName("Timestamp")]
public DateTime Timestamp { get; set; }
[JsonPropertyName("Level")]
public string Level { get; set; } = "Information";
[JsonPropertyName("MessageTemplate")]
public string? MessageTemplate { get; set; }
[JsonPropertyName("RenderedMessage")]
public string? RenderedMessage { get; set; }
[JsonPropertyName("Properties")]
public Dictionary<string, object>? Properties { get; set; }
[JsonPropertyName("Renderings")]
public Dictionary<string, RenderingModel[]>? Renderings { get; set; }
[JsonPropertyName("Exception")]
public string? Exception { get; set; }
}

15
be/Web.Gateway/Web.Gateway/Models/LoginModel.cs

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace Web.Gateway.Models;
public class LoginModel
{
[Display(Name = "用户名")]
[Required(ErrorMessage = "必填项")]
public string? UserName { get; set; }
[Display(Name = "密码")]
[Required(ErrorMessage = "必填项")]
[DataType(DataType.Password)]
public string? Password { get; set; }
}

17
be/Web.Gateway/Web.Gateway/Models/QueryLogModel.cs

@ -0,0 +1,17 @@
namespace Web.Gateway.Models;
public class QueryLogModel
{
public string? ApplicationName { get; set; } = string.Empty;
public bool EnalbeTail { get; set; }
public List<Dictionary<string, string>> Items { get; set; } = new List<Dictionary<string, string>>();
public string? Level { get; set; } = string.Empty;
public List<string> Levels { get; set; } = new List<string>() { "Verbose", "Debug", "Information", "Warning", "Error", "Fatal" };
public int PageIndex { get; set; } = 1;
public int PageSize { get; set; } = 100;
public string? Query { get; set; }
public List<string> Tags { get; set; } = new List<string>();
public bool UseCustom { get; set; }
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
}

7
be/Web.Gateway/Web.Gateway/Models/RenderingModel.cs

@ -0,0 +1,7 @@
namespace Web.Gateway.Models;
public class RenderingModel
{
public string Format { get; set; } = null!;
public string Rendering { get; set; } = null!;
}

112
be/Web.Gateway/Web.Gateway/Program.cs

@ -0,0 +1,112 @@
using System.Globalization;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Serilog;
// log
var logFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "log.txt");
var loggerConfiguration = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithProcessName()
.Enrich.WithProcessId()
.Enrich.WithProperty("ApplicationName", Assembly.GetEntryAssembly().GetName().Name)
.Enrich.WithProperty("Version", Assembly.GetEntryAssembly()?.GetName().Version)
.WriteTo.Console(formatProvider: CultureInfo.InvariantCulture)
.WriteTo.File(logFile, rollOnFileSizeLimit: true, rollingInterval: RollingInterval.Infinite, fileSizeLimitBytes: 1024 * 1024 * 100, formatProvider: CultureInfo.InvariantCulture);
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
{
loggerConfiguration.WriteTo.Http("http://localhost:5001", null);
}
Log.Logger = loggerConfiguration.CreateLogger();
try
{
// builder
var builder = WebApplication.CreateBuilder(args);
// config
builder.Host.UseSerilog();
builder.Services.AddHttpClient();
builder.Services.Configure<KestrelServerOptions>(options => {
options.Limits.MaxRequestBodySize = long.MaxValue;
options.Limits.MaxRequestBufferSize = long.MaxValue;
options.Limits.MaxRequestLineSize = int.MaxValue;
options.Limits.KeepAliveTimeout = TimeSpan.MaxValue;
});
builder.Services.Configure<FormOptions>(options => {
options.ValueLengthLimit = int.MaxValue;
options.MultipartBodyLengthLimit=long.MaxValue;
});
builder.Services.AddSignalR(o => o.EnableDetailedErrors = true)
.AddJsonProtocol(o =>
{
o.PayloadSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
o.PayloadSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
o.PayloadSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
builder.Services.AddMvc().AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors(options =>
{
options.AddPolicy("default", builder =>
{
builder.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
});
builder.Configuration.GetSection("CORS").GetChildren().ToList().ForEach(o =>
{
options.AddPolicy(o.Key, builder =>
{
//
_ = o.GetValue(nameof(CorsPolicy.AllowAnyOrigin), true)
? builder.AllowAnyOrigin()
: builder.WithOrigins(o.GetSection(nameof(CorsPolicy.Origins)).Get<string[]>());
//
_ = o.GetValue(nameof(CorsPolicy.AllowAnyHeader), true)
? builder.AllowAnyHeader()
: builder.WithHeaders(o.GetSection(nameof(CorsPolicy.Headers)).Get<string[]>());
//
_ = o.GetValue(nameof(CorsPolicy.AllowAnyMethod), true) ?
builder.AllowAnyMethod()
: builder.WithMethods(o.GetSection(nameof(CorsPolicy.Methods)).Get<string[]>());
});
});
});
// build
var app = builder.Build();
// config
app.UseSwagger();
app.UseSwaggerUI();
app.UseSerilogRequestLogging();
app.MapReverseProxy();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapHub<PageHub>("/hub");
app.UseCors("default");
// run
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}

21
be/Web.Gateway/Web.Gateway/Properties/PublishProfiles/FolderProfile.pubxml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\net6.0\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>net6.0</TargetFramework>
<ProjectGuid>4a793e8c-f1be-4aa6-b058-a0a0af21719e</ProjectGuid>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>

38
be/Web.Gateway/Web.Gateway/Properties/launchSettings.json

@ -0,0 +1,38 @@
{
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5001"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL": {
"commandName": "WSL2",
"launchBrowser": true,
"launchUrl": "http://localhost:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5001"
},
"distributionName": ""
}
},
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5001",
"sslPort": 0
}
}
}

20
be/Web.Gateway/Web.Gateway/Views/Account/Login.cshtml

@ -0,0 +1,20 @@
@model LoginModel
@section styles{
<style>
.field-validation-valid, .field-validation-error {
display: block;
min-width: 1.5em;
height: 1.5em;
color: red;
}
</style>
}
<div style="display:inline-flex;justify-content:center;align-items: center;width:100%;height:100%;box-sizing:border-box;">
<form asp-controller="Account" asp-action="Login" method="post" class="pure-form pure-form-aligned" style="margin-bottom:10em;">
@Html.ValidationSummary(true)
@Html.EditorForModel()
@Html.Hidden("ReturnUrl",(ViewBag.ReturnUrl as string))
<input type="submit" class="pure-button pure-button-primary" value="登录">
</form>
</div>

27
be/Web.Gateway/Web.Gateway/Views/Config/Edit.cshtml

@ -0,0 +1,27 @@
@model string
@{
var content = System.IO.File.ReadAllText(Model);
}
@section scripts{
<script>
var app = {
setup() {
Vue.onMounted(() => {
const flask = new CodeFlask('#editor', { language: 'js' });
flask.onUpdate((value) => {
document.getElementById("content").setAttribute("value", value);
});
flask.updateCode(@Json.Serialize(content));
});
}
};
</script>
}
<div id="editor" style="width:100%;height:calc(100vh - 80px);position:relative;"></div>
<form asp-controller="Config" asp-action="Edit" method="post" class="pure-form pure-form-aligned" style="width:100%;height:40px;">
<input name="file" type="hidden" value="@Model" />
<input name="content" id="content" value="@content" type="hidden" />
<div style="text-align:center;">
<input type="submit" class="pure-button pure-button-primary" value="提交">
</div>
</form>

66
be/Web.Gateway/Web.Gateway/Views/Config/Index.cshtml

@ -0,0 +1,66 @@
@model Dictionary<string,string>
@section styles{
<style>
#close {
position: absolute;
top: 1em;
left: calc(100%/2 - 1em);
width: 2em;
line-height: 2em;
display: inline-block;
text-align: center;
color: #fff;
background-color: gray;
cursor: pointer;
z-index: 10;
}
</style>
}
@section scripts{
<script>
const model = Vue.reactive((@Json.Serialize(Model)));
var app = {
setup() {
const show = Vue.ref(false);
const detail = (key, value) => {
const flask = new CodeFlask('#editor', { language: 'js', readonly: true });
flask.updateCode(value);
show.value = true;
//
};
const close = () => {
show.value = false;
};
return {
model,
show,
close,
detail
}
}
};
</script>
}
<div style="display:inline-flex;justify-content:center;align-items:flex-start;width:100%;box-sizing:border-box;">
<table class="pure-table pure-table-striped">
<thead>
<tr>
<th>文件</th>
<th>详情</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(value,key) in model">
<td class="white-space-nowrap">{{key}}</td>
<td class="white-space-nowrap" v-on:click="detail(key,value)"><span style="cursor:pointer;">详情</span></td>
<td class="white-space-nowrap"><a :href="'@Url.Action("Edit")?file='+encodeURIComponent(key)">编辑</a></td>
</tr>
</tbody>
</table>
</div>
<div id="modal" style="width:100%;height:100vh;position:absolute;top:0;overflow:hidden;" v-show="show">
<div id="editor" style="width:100%;height:100%;overflow:scroll;"></div>
<span id="close" v-on:click="close">X</span>
</div>

27
be/Web.Gateway/Web.Gateway/Views/Gateway/Edit.cshtml

@ -0,0 +1,27 @@
@model string
@{
var content = System.IO.File.ReadAllText(Model);
}
@section scripts{
<script>
var app = {
setup() {
Vue.onMounted(() => {
const flask = new CodeFlask('#editor', { language: 'js' });
flask.onUpdate((value) => {
document.getElementById("content").setAttribute("value", value);
});
flask.updateCode(@Json.Serialize(content));
});
}
};
</script>
}
<div id="editor" style="width:100%;height:calc(100vh - 80px);position:relative;"></div>
<form asp-controller="Config" asp-action="Edit" method="post" class="pure-form pure-form-aligned" style="width:100%;height:40px;">
<input name="file" type="hidden" value="@Model" />
<input name="content" id="content" value="@content" type="hidden" />
<div style="text-align:center;">
<input type="submit" class="pure-button pure-button-primary" value="提交">
</div>
</form>

66
be/Web.Gateway/Web.Gateway/Views/Gateway/Index.cshtml

@ -0,0 +1,66 @@
@model Dictionary<string,string>
@section styles{
<style>
#close {
position: absolute;
top: 1em;
left: calc(100%/2 - 1em);
width: 2em;
line-height: 2em;
display: inline-block;
text-align: center;
color: #fff;
background-color: gray;
cursor: pointer;
z-index: 10;
}
</style>
}
@section scripts{
<script>
const model = Vue.reactive((@Json.Serialize(Model)));
var app = {
setup() {
const show = Vue.ref(false);
const detail = (key, value) => {
const flask = new CodeFlask('#editor', { language: 'js', readonly: true });
flask.updateCode(value);
show.value = true;
//
};
const close = () => {
show.value = false;
};
return {
model,
show,
close,
detail
}
}
};
</script>
}
<div style="display:inline-flex;justify-content:center;align-items:flex-start;width:100%;box-sizing:border-box;">
<table class="pure-table pure-table-striped">
<thead>
<tr>
<th>文件</th>
<th>详情</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(value,key) in model">
<td class="white-space-nowrap">{{key}}</td>
<td class="white-space-nowrap" v-on:click="detail(key,value)"><span style="cursor:pointer;">详情</span></td>
<td class="white-space-nowrap"><a :href="'@Url.Action("Edit")?file='+encodeURIComponent(key)">编辑</a></td>
</tr>
</tbody>
</table>
</div>
<div id="modal" style="width:100%;height:100vh;position:absolute;top:0;overflow:hidden;" v-show="show">
<div id="editor" style="width:100%;height:100%;overflow:scroll;"></div>
<span id="close" v-on:click="close">X</span>
</div>

150
be/Web.Gateway/Web.Gateway/Views/Home/Index.cshtml

@ -0,0 +1,150 @@
@model QueryLogModel
@section styles{
<style>
.white-space-nowrap {
white-space: nowrap;
}
.pure-form select {
padding-top: 0;
padding-bottom: 0;
}
label{
padding-left:1em;
}
</style>
}
@section scripts{
<script>
const model = Vue.reactive((@Json.Serialize(Model)));
var app = {
setup() {
const colorMap = new Map([
['Warning', 'darkred'],
['Error', 'red'],
['Debug', 'yellow']
]);
const toggle = (item) => {
item.show = !item.show;
};
const getColor = (item) => {
return colorMap.get(item) ?? 'green';
};
Vue.onMounted(() => {
PubSub.subscribe('notify', (method, data) => {
model.items = data.filter(o => model.level === '' || o.level === model.level).concat(model.items).slice(0, model.pageSize);
});
});
const start = Vue.ref(fecha.format(new Date(model.start), "YYYY-MM-DDTHH:mm"));
const end = Vue.ref(fecha.format(new Date(model.end), "YYYY-MM-DDTHH:mm"));
return {
model,
toggle,
getColor,
start,
end
}
}
};
</script>
<script>
var connectionId = null;
const connection = new signalR.HubConnectionBuilder().withUrl('@Url.Content("~/hub")').build();
const connect = () => {
if (connection.state === signalR.HubConnectionState.Disconnected) {
connection
.start()
.then(function () {
console.log('signalr connected');
})
.catch(function (error) {
console.error(error);
setTimeout(connect, 5000);
});
}
};
connection.onclose(function () {
connect();
});
connection.on('connected', function (id) {
connectionId = id;
connection.invoke('setTail', model.enalbeTail, connectionId);
});
connection.on('notify', function (results) {
PubSub.publish('notify', results);
});
connect();
</script>
}
<form asp-controller="Home" asp-action="Index" method="get" class="pure-form">
<input name="query" type="text" v-model="model.query" placeholder="InfluxQL" style="width:100%" />
<br />
<br />
<label>应用:</label>
<select id="applicationName" name="applicationName" v-model="model.applicationName">
<option value="">选择应用</option>
<option v-for="item in model.tags" :value="item">{{item}}</option>
</select>
<label>级别:</label>
<select id="levle" name="level" v-model="model.level">
<option value="">选择级别</option>
<option v-for="item in model.levels" :value="item">{{item}}</option>
</select>
<label for="start">
开始:
<input type="datetime-local" v-model="start" placeholder="开始" />
<input name="start" type="hidden" :value="start" />
</label>
<label for="end">
结束:
<input type="datetime-local" v-model="end" placeholder="结束" />
<input name="end" type="hidden" :value="new Date(end).toISOString()" />
</label>
<label for="enalbeTail">
数量:
<input name="pageSize" data-role="spinner" data-min-value="0" data-max-value="10000" type="number" v-model="model.pageSize" placeholder="数量" />
</label>
<label for="useCustom">
自定义查询:
<input name="useCustom" id="useCustom" type="checkbox" v-model="model.useCustom" :value="model.useCustom" />
</label>
<label for="enalbeTail">
实时刷新:
<input name="enalbeTail" id="enalbeTail" type="checkbox" v-model="model.enalbeTail" :value="model.enalbeTail" />
</label>
<input type="submit" class="pure-button pure-button-primary" value="查询" style="margin-left:1em;">
</form>
<br />
<table class="pure-table pure-table-striped" style="width:100%;">
<thead>
<tr>
<th>时间</th>
<th>应用</th>
<th>级别</th>
<th>日志</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in model.items">
<td class="white-space-nowrap">{{new Date(item.time).toLocaleString()}}</td>
<td class="white-space-nowrap">{{item.applicationName}}</td>
<td class="white-space-nowrap" :style="{color:getColor(item.level)}" >{{item.level}}</td>
<td>
<div style="cursor:pointer" v-on:click="toggle(item)">{{item.renderedMessage}}</div>
<div v-if="item.show">
<table class="pure-table pure-table-bordered" style="margin:.5em;">
<template v-for="(value,key) in item">
<tr v-if="value">
<td class="white-space-nowrap">{{key}}</td>
<td>{{value}}</td>
</tr>
</template>
</table>
</div>
</td>
</tr>
</tbody>
</table>

77
be/Web.Gateway/Web.Gateway/Views/Shared/_Layout.cshtml

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="~/lib/pure-min.css" />
<style>
.pure-menu-selected .pure-menu-link {
background: lightgray;
}
.editor-label{
margin-bottom:.5em;
}
</style>
@RenderSection("styles",false)
<title>网关</title>
</head>
<body style="padding:0;margin:0;width:100%;height:100vh;overflow:hidden;">
<div id="app" style="width:100%;height:100vh;">
<div class="header" style="height:40px;">
<div class="home-menu pure-menu pure-menu-horizontal" style="display:inline-flex;justify-content:space-between;">
<ul class="pure-menu-list">
<li class="@GetMenuClass("home")">
<a href="@Url.Content("~/")" class="pure-menu-link">日志</a>
</li>
<li class="@GetMenuClass("config")">
<a href="@Url.Action("Index","Config")" class="pure-menu-link">配置</a>
</li>
<li class="@GetMenuClass("gateway")">
<a href="@Url.Action("Index","Gateway")" class="pure-menu-link">网关</a>
</li>
</ul>
<ul class="pure-menu-list">
<li class="pure-menu-item">
@if (User.Identity!.IsAuthenticated)
{
<form method="post" action="@Url.Action("Logout","Account",new{ReturnUrl=this.Context.Request.Path})">
<button type="submit" class="pure-button">退出</button>
</form>
}
else
{
<a href="@Url.Action("Login","Account")" class="pure-button">登录</a>
}
</li>
</ul>
</div>
</div>
<div class="pure-g" style="height:calc(100vh - 40px);">
<div class="pure-u" style="width:100%;height:100%;overflow-y:scroll;">
@RenderBody()
</div>
</div>
</div>
<script src="~/lib/vue.global.prod.js"></script>
<script src="~/lib/signalr.min.js"></script>
<script src="~/lib/pubsub.min.js"></script>
<script src="~/lib/fecha.min.js"></script>
<script src="~/lib/micromodal.min.js"></script>
<script src="~/lib/codeflask.min.js"></script>
@RenderSection("scripts",false)
<script>
Vue.createApp(app ?? {}).mount('#app');
</script>
</body>
</html>
@functions {
string GetMenuClass(string controller)
{
var className = "pure-menu-item";
if (this.ViewContext.RouteData.Values["Controller"]?.ToString()?.ToLowerInvariant() == controller)
{
className += " pure-menu-selected";
}
return className;
}
}

3
be/Web.Gateway/Web.Gateway/Views/_ViewImports.cshtml

@ -0,0 +1,3 @@
@using Web.Gateway
@using Web.Gateway.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

3
be/Web.Gateway/Web.Gateway/Views/_ViewStart.cshtml

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

28
be/Web.Gateway/Web.Gateway/Web.Gateway.csproj

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>0.1.5</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Flurl" Version="3.0.7" />
<PackageReference Include="InfluxDB.Client" Version="4.11.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
<PackageReference Include="Serilog.Enrichers.Process" Version="2.0.2" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Http" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Yarp.ReverseProxy" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\PublishProfiles\" />
</ItemGroup>
</Project>

44
be/Web.Gateway/Web.Gateway/appsettings.Development.json

@ -0,0 +1,44 @@
{
"ConnectionStrings": {
"InfluxDB": "url=http://localhost:8086;database=logs;usr=admin;pwd=aA123456!;retention-policy=d30;"
},
"ReverseProxy": {
"Clusters": {
"abp": {
"Destinations": {
"dest": {
"Address": "http://localhost:59093/api/"
}
}
},
"auth": {
"Destinations": {
"dest": {
"Address": "http://localhost:59093/"
}
}
},
"core": {
"Destinations": {
"dest": {
"Address": "http://localhost:59092/"
}
}
},
"basedata": {
"Destinations": {
"dest": {
"Address": "http://localhost:59094/"
}
}
},
"wms": {
"Destinations": {
"dest": {
"Address": "http://localhost:59095/"
}
}
}
}
}
}

2
be/Web.Gateway/Web.Gateway/appsettings.Production.json

@ -0,0 +1,2 @@
{
}

101
be/Web.Gateway/Web.Gateway/appsettings.json

@ -0,0 +1,101 @@
{
"ConnectionStrings": {
"InfluxDB": "url=http://influxdb:8086;database=logs;usr=admin;pwd=aA123456!;retention-policy=d30;"
},
"CORS": {
"abp": {
"AllowAnyOrigin": false,
"Origins": [
"http://localhost:9527"
]
}
},
"ReverseProxy": {
"Routes": {
"abp": {
"ClusterId": "abp",
"CorsPolicy": "abp",
"Match": {
"Path": "/api/auth/{regex((abp|identity|base|multi-tenancy|permission-management))}/{**catch-all}"
},
"Transforms": [
{
"PathRemovePrefix": "/api/auth"
}
]
},
"ids4": {
"ClusterId": "auth",
"Match": {
"Path": "/api/auth/connect/{**catch-all}"
},
"Transforms": [
{
"PathRemovePrefix": "/api/auth"
}
]
},
"auth": {
"ClusterId": "auth",
"Match": {
"Path": "/api/auth/{**catch-all}"
}
},
"core": {
"ClusterId": "core",
"Match": {
"Path": "/api/{regex((label|filestore|reporting|message))}/{**catch-all}"
}
},
"basedata": {
"ClusterId": "basedata",
"Match": {
"Path": "/api/basedata/{**catch-all}"
}
},
"wms": {
"ClusterId": "wms",
"Match": {
"Path": "/api/wms/{**catch-all}"
}
}
},
"Clusters": {
"abp": {
"Destinations": {
"dest": {
"Address": "http://sfs-auth-web:59093/api/"
}
}
},
"auth": {
"Destinations": {
"dest": {
"Address": "http://sfs-auth-web:59093/"
}
}
},
"core": {
"Destinations": {
"dest": {
"Address": "http://sfs-core-host:59092/"
}
}
},
"basedata": {
"Destinations": {
"dest": {
"Address": "http://sfs-basedata-host:59094/"
}
}
},
"wms": {
"Destinations": {
"dest": {
"Address": "http://sfs-wms-host:59095/"
}
}
}
}
}
}

1
be/Web.Gateway/Web.Gateway/wwwroot/lib/codeflask.min.js

File diff suppressed because one or more lines are too long

2
be/Web.Gateway/Web.Gateway/wwwroot/lib/fecha.min.js

File diff suppressed because one or more lines are too long

1
be/Web.Gateway/Web.Gateway/wwwroot/lib/micromodal.min.js

File diff suppressed because one or more lines are too long

1
be/Web.Gateway/Web.Gateway/wwwroot/lib/pubsub.min.js

@ -0,0 +1 @@
!function (t) { "use strict"; var r = {}; t.PubSub ? (r = t.PubSub, console.warn("PubSub already loaded, using existing version")) : function (s) { "use strict"; var a = {}, n = -1, u = "*"; function o(t) { var r; for (r in t) if (Object.prototype.hasOwnProperty.call(t, r)) return true; return false } function i(r) { return function t() { throw r } } function c(t, r, e) { try { t(r, e) } catch (t) { setTimeout(i(t), 0) } } function f(t, r, e) { t(r, e) } function p(t, r, e, n) { var o = a[r], i = n ? f : c, u; if (!Object.prototype.hasOwnProperty.call(a, r)) return; for (u in o) if (Object.prototype.hasOwnProperty.call(o, u)) i(o[u], t, e) } function l(n, o, i) { return function t() { var r = String(n), e = r.lastIndexOf("."); p(n, n, o, i); while (e !== -1) { r = r.substr(0, e); e = r.lastIndexOf("."); p(n, r, o, i) } p(n, u, o, i) } } function b(t) { var r = String(t), e = Boolean(Object.prototype.hasOwnProperty.call(a, r) && o(a[r])); return e } function y(t) { var r = String(t), e = b(r) || b(u), n = r.lastIndexOf("."); while (!e && n !== -1) { r = r.substr(0, n); n = r.lastIndexOf("."); e = b(r) } return e } function e(t, r, e, n) { t = typeof t === "symbol" ? t.toString() : t; var o = l(t, r, n), i = y(t); if (!i) return false; if (e === true) o(); else setTimeout(o, 0); return true } s.publish = function (t, r) { return e(t, r, false, s.immediateExceptions) }, s.publishSync = function (t, r) { return e(t, r, true, s.immediateExceptions) }, s.subscribe = function (t, r) { if (typeof r !== "function") return false; t = typeof t === "symbol" ? t.toString() : t; if (!Object.prototype.hasOwnProperty.call(a, t)) a[t] = {}; var e = "uid_" + String(++n); a[t][e] = r; return e }, s.subscribeAll = function (t) { return s.subscribe(u, t) }, s.subscribeOnce = function (t, r) { var e = s.subscribe(t, function () { s.unsubscribe(e); r.apply(this, arguments) }); return s }, s.clearAllSubscriptions = function t() { a = {} }, s.clearSubscriptions = function t(r) { var e; for (e in a) if (Object.prototype.hasOwnProperty.call(a, e) && e.indexOf(r) === 0) delete a[e] }, s.countSubscriptions = function t(r) { var e; var n; var o = 0; for (e in a) if (Object.prototype.hasOwnProperty.call(a, e) && e.indexOf(r) === 0) { for (n in a[e]) o++; break } return o }, s.getSubscriptions = function t(r) { var e; var n = []; for (e in a) if (Object.prototype.hasOwnProperty.call(a, e) && e.indexOf(r) === 0) n.push(e); return n }, s.unsubscribe = function (t) { var r = function (t) { var r; for (r in a) if (Object.prototype.hasOwnProperty.call(a, r) && r.indexOf(t) === 0) return true; return false }, e = typeof t === "string" && (Object.prototype.hasOwnProperty.call(a, t) || r(t)), n = !e && typeof t === "string", o = typeof t === "function", i = false, u, c, f; if (e) { s.clearSubscriptions(t); return } for (u in a) if (Object.prototype.hasOwnProperty.call(a, u)) { c = a[u]; if (n && c[t]) { delete c[t]; i = t; break } if (o) for (f in c) if (Object.prototype.hasOwnProperty.call(c, f) && c[f] === t) { delete c[f]; i = true } } return i } }(t.PubSub = r), "object" == typeof exports ? ((exports = void 0 !== module && module.exports ? module.exports = r : exports).PubSub = r, module.exports = exports = r) : "function" == typeof define && define.amd && define(function () { return r }) }("object" == typeof window && window || this);

11
be/Web.Gateway/Web.Gateway/wwwroot/lib/pure-min.css

File diff suppressed because one or more lines are too long

2
be/Web.Gateway/Web.Gateway/wwwroot/lib/signalr.min.js

File diff suppressed because one or more lines are too long

1
be/Web.Gateway/Web.Gateway/wwwroot/lib/vue.global.prod.js

File diff suppressed because one or more lines are too long

165
be/Web.Gateway/Web.Gateway/wwwroot/settings/appsettings.Development.json

@ -0,0 +1,165 @@
{
"AlwaysAllowAuthorization": "False",
"App": {
"CorsOrigins": [
"http://localhost:59080",
"http://localhost:59081",
"http://localhost:59090",
"http://localhost:59091",
"http://localhost:59093",
"http://localhost:59094",
"http://localhost:59095",
"http://localhost:59096",
"http://localhost:59097",
"http://localhost:59098",
"http://localhost:59099",
"http://localhost:59090",
"http://localhost:59091",
"http://localhost:59093",
"http://localhost:59094",
"http://localhost:59095",
"http://localhost:59096",
"http://localhost:59097",
"http://localhost:59098",
"http://localhost:59099",
"https://localhost:59090",
"https://localhost:59091",
"https://localhost:59093",
"https://localhost:59094",
"https://localhost:59095",
"https://localhost:59096",
"https://localhost:59097",
"https://localhost:59098",
"https://localhost:59099",
"https://localhost:59090",
"https://localhost:59091",
"https://localhost:59093",
"https://localhost:59094",
"https://localhost:59095",
"https://localhost:59096",
"https://localhost:59097",
"https://localhost:59098",
"https://localhost:59099",
"http://localhost:9527"
]
},
"AuthServer": {
"Audience": "Auth",
"Authority": "http://localhost:59093/",
"ClientId": "Auth_App",
"ClientSecret": "1q2w3E*",
"RequireHttpsMetadata": "false",
"SwaggerClientId": "Auth_App",
"SwaggerClientSecret": "1q2w3e*",
"UseAuth": "true"
},
// "ConnectionStrings": {
// "AbpAuditLogging": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpBackgroundJobs": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpBlobStoring": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpFeatureManagement": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpIdentity": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpIdentityServer": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpPermissionManagement": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpSettingManagement": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "AbpTenantManagement": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "Auth": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "Basedata": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "DataExchange": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "FileStorage": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "Inventory": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "Job": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "Label": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "Message": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
// "Store": "Server=localhost,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;"
// },
"ConnectionStrings": {
"AbpAuditLogging": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpBackgroundJobs": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpBlobStoring": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpFeatureManagement": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpIdentity": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpIdentityServer": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpPermissionManagement": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpSettingManagement": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpTenantManagement": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Auth": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Basedata": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"DataExchange": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"FileStorage": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Inventory": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Job": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Label": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Message": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Store": "Server=dev.ccwin-in.com,21195;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;"
},
"IdentityClients": {
"Default": {
"Authority": "http://localhost:59093",
"ClientId": "Auth_App",
"ClientSecret": "1q2w3E*",
"GrantType": "client_credentials",
"RequireHttps": "false",
"Scope": "Auth"
}
},
"IsMultiTenancy": "True",
"Redis": {
"Configuration": "localhost:21194",
"KeyPrefix": "Wms:"
},
"RemoteServices": {
"Auth": {
"BaseUrl": "http://dev.ccwin-in.com:59093/"
},
"BaseData": {
"BaseUrl": "http://dev.ccwin-in.com:59094/"
},
"Default": {
"BaseUrl": "http://dev.ccwin-in.com:59093"
},
"FileStorage": {
"BaseUrl": "http://dev.ccwin-in.com:59092/"
},
"Inventory": {
"BaseUrl": "http://dev.ccwin-in.com:59095/"
},
"Job": {
"BaseUrl": "http://dev.ccwin-in.com:59095/"
},
"Label": {
"BaseUrl": "http://dev.ccwin-in.com:59092/"
},
"Message": {
"BaseUrl": "http://dev.ccwin-in.com:59092/"
},
"Store": {
"BaseUrl": "http://dev.ccwin-in.com:59095/"
}
},
"Serilog": {
"WriteTo": [
{
"Args": {
"configure": [
{
"Args": {
"path": "logs/log.txt",
"retainedFileCountLimit": "30",
"rollingInterval": "Day"
},
"Name": "File"
}
]
},
"Name": "Async"
},
{
"Args": {
"serverUrl": "http://localhost:5341"
},
"Name": "Seq"
}
]
}
}

154
be/Web.Gateway/Web.Gateway/wwwroot/settings/appsettings.json

@ -0,0 +1,154 @@
{
//
"AlwaysAllowAuthorization": "True",
//
"App": {
"CorsOrigins": [
"http://localhost:59080",
"http://localhost:59081",
"http://localhost:59090",
"http://localhost:59091",
"http://localhost:59093",
"http://localhost:59094",
"http://localhost:59095",
"http://localhost:59096",
"http://localhost:59097",
"http://localhost:59098",
"http://localhost:59099",
"http://localhost:59090",
"http://localhost:59091",
"http://localhost:59093",
"http://localhost:59094",
"http://localhost:59095",
"http://localhost:59096",
"http://localhost:59097",
"http://localhost:59098",
"http://localhost:59099",
"https://localhost:59090",
"https://localhost:59091",
"https://localhost:59093",
"https://localhost:59094",
"https://localhost:59095",
"https://localhost:59096",
"https://localhost:59097",
"https://localhost:59098",
"https://localhost:59099",
"https://localhost:59090",
"https://localhost:59091",
"https://localhost:59093",
"https://localhost:59094",
"https://localhost:59095",
"https://localhost:59096",
"https://localhost:59097",
"https://localhost:59098",
"https://localhost:59099",
"http://localhost:9527"
]
},
//ids4
"AuthServer": {
"Audience": "Auth",
"Authority": "http://localhost:21093/",
"ClientId": "Auth_App",
"ClientSecret": "1q2w3E*",
"RequireHttpsMetadata": "false",
"SwaggerClientId": "Auth_App",
"SwaggerClientSecret": "1q2w3e*",
"UseAuth": "true"
},
//ids4
"IdentityClients": {
"Default": {
"Authority": "http://localhost:59093",
"ClientId": "Auth_App",
"ClientSecret": "1q2w3E*",
"GrantType": "client_credentials",
"RequireHttps": "false",
"Scope": "Auth"
}
},
//
"Database": "SQLServer",
"ConnectionStrings": {
"AbpAuditLogging": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpBackgroundJobs": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpBlobStoring": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpFeatureManagement": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpIdentity": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpIdentityServer": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpPermissionManagement": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpSettingManagement": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"AbpTenantManagement": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Auth": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Basedata": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"DataExchange": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"FileStorage": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Inventory": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Job": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Label": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Message": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;",
"Store": "Server=database,1433;Database=Wms;Uid=sa;Pwd=aA123456!;timeout=6000;"
},
//
"IsMultiTenancy": "True",
//
"Redis": {
"Configuration": "redis:6379",
"KeyPrefix": "Wms:"
},
//
"RemoteServices": {
"Auth": {
"BaseUrl": "http://dev.ccwin-in.com:59093/"
},
"BaseData": {
"BaseUrl": "http://dev.ccwin-in.com:59094/"
},
"Default": {
"BaseUrl": "http://dev.ccwin-in.com:59093"
},
"FileStorage": {
"BaseUrl": "http://dev.ccwin-in.com:59092/"
},
"Inventory": {
"BaseUrl": "http://dev.ccwin-in.com:59095/"
},
"Job": {
"BaseUrl": "http://dev.ccwin-in.com:59095/"
},
"Label": {
"BaseUrl": "http://dev.ccwin-in.com:59092/"
},
"Message": {
"BaseUrl": "http://dev.ccwin-in.com:59092/"
},
"Store": {
"BaseUrl": "http://dev.ccwin-in.com:59095/"
}
},
"Serilog": {
"WriteTo": [
{
"Args": {
"configure": [
{
"Args": {
"path": "logs/log.txt",
"retainedFileCountLimit": "30",
"rollingInterval": "Day"
},
"Name": "File"
}
]
},
"Name": "Async"
},
{
"Args": {
"serverUrl": "http://seq:5341"
},
"Name": "Seq"
}
]
}
}
Loading…
Cancel
Save