using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel.DataAnnotations; using WIDESEAWCS_S7Simulator.Core.Entities; using WIDESEAWCS_S7Simulator.Core.Enums; namespace WIDESEAWCS_S7Simulator.Web.Pages; /// /// 编辑实例页 /// public class EditModel : PageModel { private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; public EditModel(ILogger logger, IHttpClientFactory httpClientFactory) { _logger = logger; _httpClientFactory = httpClientFactory; } [BindProperty] public EditInstanceInputModel Input { get; set; } = new(); public InstanceState? CurrentInstance { get; private set; } public bool IsRunning { get; private set; } public async Task OnGetAsync(string id) { if (string.IsNullOrWhiteSpace(id)) { return BadRequest("实例ID不能为空"); } try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri($"{Request.Scheme}://{Request.Host}"); var response = await httpClient.GetAsync($"/api/SimulatorInstances/{Uri.EscapeDataString(id)}"); if (response.IsSuccessStatusCode) { CurrentInstance = await response.Content.ReadFromJsonAsync(); IsRunning = CurrentInstance?.Status == InstanceStatus.Running; // Load existing config var configResponse = await httpClient.GetAsync($"/api/SimulatorInstances"); if (configResponse.IsSuccessStatusCode) { var allInstances = await configResponse.Content.ReadFromJsonAsync>(); // For now, we'll initialize with defaults. In production, you'd have a separate endpoint to get instance config } // Initialize input with current values (default for now) Input.Id = id; Input.Name = CurrentInstance?.InstanceId ?? id; Input.Port = 102; // Default } else if (response.StatusCode == System.Net.HttpStatusCode.NotFound) { return NotFound($"实例 \"{id}\" 不存在"); } } catch (HttpRequestException ex) { _logger.LogError(ex, "Failed to load instance {InstanceId}", id); ModelState.AddModelError(string.Empty, "加载实例失败,请稍后重试"); } return Page(); } public async Task OnPostAsync() { if (!ModelState.IsValid) { // Reload instance state await LoadInstanceStateAsync(Input.Id); return Page(); } try { // 创建HttpClient并设置BaseAddress var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri($"{Request.Scheme}://{Request.Host}"); var config = new InstanceConfig { Id = Input.Id, Name = Input.Name, PLCType = Input.PLCType, Port = Input.Port, ActivationKey = Input.ActivationKey ?? string.Empty, AutoStart = Input.AutoStart, MemoryConfig = new MemoryRegionConfig { MRegionSize = Input.MRegionSize > 0 ? Input.MRegionSize : 1024, DBBlockCount = Input.DBBlockCount > 0 ? Input.DBBlockCount : 100, DBBlockSize = Input.DBBlockSize > 0 ? Input.DBBlockSize : 1024, IRegionSize = Input.IRegionSize > 0 ? Input.IRegionSize : 256, QRegionSize = Input.QRegionSize > 0 ? Input.QRegionSize : 256, TRegionCount = Input.TRegionCount > 0 ? Input.TRegionCount : 64, CRegionCount = Input.CRegionCount > 0 ? Input.CRegionCount : 64 } }; var response = await httpClient.PutAsJsonAsync($"/api/SimulatorInstances/{Uri.EscapeDataString(Input.Id)}", config); if (response.IsSuccessStatusCode) { _logger.LogInformation("Instance {InstanceId} updated successfully", Input.Id); TempData["SuccessMessage"] = $"实例 \"{Input.Id}\" 更新成功!"; return RedirectToPage("/Index"); } else if (response.StatusCode == System.Net.HttpStatusCode.NotFound) { ModelState.AddModelError(string.Empty, "实例不存在"); } else { var error = await response.Content.ReadFromJsonAsync(); ModelState.AddModelError(string.Empty, error?.ToString() ?? "更新实例失败"); } } catch (HttpRequestException ex) { _logger.LogError(ex, "Failed to update instance"); ModelState.AddModelError(string.Empty, "网络错误,请稍后重试"); } await LoadInstanceStateAsync(Input.Id); return Page(); } private async Task LoadInstanceStateAsync(string id) { try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri($"{Request.Scheme}://{Request.Host}"); var response = await httpClient.GetAsync($"/api/SimulatorInstances/{Uri.EscapeDataString(id)}"); if (response.IsSuccessStatusCode) { CurrentInstance = await response.Content.ReadFromJsonAsync(); IsRunning = CurrentInstance?.Status == InstanceStatus.Running; } } catch { // Ignore errors when reloading state } } /// /// 编辑实例输入模型 /// public class EditInstanceInputModel { public string Id { get; set; } = string.Empty; [Required(ErrorMessage = "实例名称不能为空")] [StringLength(100, ErrorMessage = "实例名称不能超过100个字符")] public string Name { get; set; } = string.Empty; [Required(ErrorMessage = "PLC型号不能为空")] public SiemensPLCType PLCType { get; set; } = SiemensPLCType.S71200; [Required(ErrorMessage = "端口不能为空")] [Range(1, 65535, ErrorMessage = "端口必须在1-65535之间")] public int Port { get; set; } = 102; [StringLength(200, ErrorMessage = "激活码不能超过200个字符")] public string? ActivationKey { get; set; } public bool AutoStart { get; set; } = false; // 内存配置 public int MRegionSize { get; set; } public int DBBlockCount { get; set; } public int DBBlockSize { get; set; } public int IRegionSize { get; set; } public int QRegionSize { get; set; } public int TRegionCount { get; set; } public int CRegionCount { get; set; } } }