52 changed files with 1764 additions and 9 deletions
@ -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 |
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"version": 1, |
||||
|
"isRoot": true, |
||||
|
"tools": { |
||||
|
"dotnet-ef": { |
||||
|
"version": "7.0.4", |
||||
|
"commands": [ |
||||
|
"dotnet-ef" |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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"); |
||||
|
} |
||||
|
} |
@ -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"); |
||||
|
} |
||||
|
} |
@ -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"); |
||||
|
} |
||||
|
} |
@ -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"; |
||||
|
} |
||||
|
} |
@ -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 }); |
||||
|
} |
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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>(); |
||||
|
} |
@ -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>(); |
||||
|
} |
@ -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>>(); |
||||
|
} |
@ -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; } |
||||
|
} |
@ -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; } |
||||
|
} |
@ -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; } |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
namespace Web.Gateway.Models; |
||||
|
|
||||
|
public class RenderingModel |
||||
|
{ |
||||
|
public string Format { get; set; } = null!; |
||||
|
public string Rendering { get; set; } = null!; |
||||
|
} |
@ -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(); |
||||
|
} |
@ -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> |
@ -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 |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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> |
||||
|
|
@ -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> |
@ -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> |
||||
|
|
@ -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> |
@ -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> |
||||
|
|
@ -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> |
||||
|
|
||||
|
|
@ -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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
@using Web.Gateway |
||||
|
@using Web.Gateway.Models |
||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
@ -0,0 +1,3 @@ |
|||||
|
@{ |
||||
|
Layout = "_Layout"; |
||||
|
} |
@ -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> |
@ -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/" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,2 @@ |
|||||
|
{ |
||||
|
} |
@ -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/" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
@ -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…
Reference in new issue