From 0dbc8273bdfbcabcc4b770546245f6b17d787de9 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期五, 13 三月 2026 14:44:50 +0800
Subject: [PATCH] fix: 修复API控制器依赖注入和路由配置
---
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 220 insertions(+), 4 deletions(-)
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml
index b5f0c15..e86b444 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml
@@ -1,10 +1,226 @@
锘緻page
@model IndexModel
@{
- ViewData["Title"] = "Home page";
+ ViewData["Title"] = "瀹炰緥鍒楄〃";
}
-<div class="text-center">
- <h1 class="display-4">Welcome</h1>
- <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
+<div class="d-flex justify-content-between align-items-center mb-4">
+ <div>
+ <h2 class="mb-0">
+ <i class="bi bi-cpu-fill me-2"></i>S7 PLC 浠跨湡鍣ㄥ疄渚�
+ </h2>
+ <p class="text-muted mb-0 mt-1">绠$悊鍜岀洃鎺� S7 PLC 浠跨湡鍣ㄥ疄渚�</p>
+ </div>
+ <a asp-page="/Create" class="btn btn-primary">
+ <i class="bi bi-plus-lg me-1"></i>鍒涘缓瀹炰緥
+ </a>
</div>
+
+<div id="instancesContainer">
+ <!-- Loading state -->
+ <div id="loadingState" class="text-center py-5">
+ <div class="spinner-border text-primary" role="status">
+ <span class="visually-hidden">鍔犺浇涓�...</span>
+ </div>
+ <p class="mt-3 text-muted">姝e湪鍔犺浇瀹炰緥鍒楄〃...</p>
+ </div>
+
+ <!-- Empty state -->
+ <div id="emptyState" class="empty-state d-none">
+ <i class="bi bi-inbox"></i>
+ <h3>鏆傛棤瀹炰緥</h3>
+ <p>鐐瑰嚮涓婃柟"鍒涘缓瀹炰緥"鎸夐挳鏉ュ垱寤烘偍鐨勭涓�涓豢鐪熷櫒瀹炰緥</p>
+ </div>
+
+ <!-- Instances grid -->
+ <div id="instancesGrid" class="row row-cols-1 row-cols-md-2 row-cols-xl-3 g-4 d-none"></div>
+</div>
+
+@section Scripts {
+<script>
+ let autoRefreshInterval = null;
+
+ document.addEventListener('DOMContentLoaded', function () {
+ loadInstances();
+ startAutoRefresh(loadInstances, 5000);
+ });
+
+ async function loadInstances() {
+ try {
+ const instances = await apiCall(`${API_BASE_URL}/SimulatorInstances`);
+ renderInstances(instances);
+ } catch (error) {
+ console.error('Failed to load instances:', error);
+ document.getElementById('loadingState').classList.add('d-none');
+ document.getElementById('emptyState').classList.remove('d-none');
+ }
+ }
+
+ function renderInstances(instances) {
+ const loadingState = document.getElementById('loadingState');
+ const emptyState = document.getElementById('emptyState');
+ const grid = document.getElementById('instancesGrid');
+
+ loadingState.classList.add('d-none');
+ grid.classList.add('d-none');
+ emptyState.classList.add('d-none');
+
+ if (!instances || instances.length === 0) {
+ emptyState.classList.remove('d-none');
+ return;
+ }
+
+ grid.classList.remove('d-none');
+ grid.innerHTML = instances.map(instance => createInstanceCard(instance)).join('');
+ }
+
+ function createInstanceCard(instance) {
+ const statusClass = getStatusClass(instance.status);
+ const statusText = getStatusText(instance.status);
+ const plcTypeText = getPlcTypeText(instance.plcType);
+ const isRunning = instance.status === 'Running';
+ const isStopped = instance.status === 'Stopped';
+
+ return `
+ <div class="col">
+ <div class="card instance-card h-100 ${statusClass}">
+ <div class="card-header d-flex justify-content-between align-items-center">
+ <h5 class="card-title mb-0">${escapeHtml(instance.instanceId)}</h5>
+ <span class="badge ${statusClass}">${statusText}</span>
+ </div>
+ <div class="card-body">
+ <div class="instance-info mb-3">
+ <div class="row mb-2">
+ <div class="col-6">
+ <small class="instance-info-label">鍚嶇О</small>
+ <div class="instance-info-value">${escapeHtml(instance.name || '-')}</div>
+ </div>
+ <div class="col-6">
+ <small class="instance-info-label">PLC鍨嬪彿</small>
+ <div class="instance-info-value">${plcTypeText}</div>
+ </div>
+ </div>
+ <div class="row mb-2">
+ <div class="col-6">
+ <small class="instance-info-label">绔彛</small>
+ <div class="instance-info-value">${instance.port || '-'}</div>
+ </div>
+ <div class="col-6">
+ <small class="instance-info-label">瀹㈡埛绔�</small>
+ <div class="instance-info-value">
+ <i class="bi bi-people-fill me-1"></i>${instance.clientCount || 0}
+ </div>
+ </div>
+ </div>
+ ${instance.startTime ? `
+ <div class="row">
+ <div class="col-12">
+ <small class="instance-info-label">鍚姩鏃堕棿</small>
+ <div class="instance-info-value small">${formatDate(instance.startTime)}</div>
+ </div>
+ </div>
+ ` : ''}
+ ${instance.errorMessage ? `
+ <div class="alert alert-danger alert-sm mt-2 mb-0 py-2 small">
+ <i class="bi bi-exclamation-triangle-fill me-1"></i>${escapeHtml(instance.errorMessage)}
+ </div>
+ ` : ''}
+ </div>
+ </div>
+ <div class="card-footer bg-white">
+ <div class="action-buttons d-flex gap-2">
+ ${isRunning ? `
+ <button class="btn btn-warning btn-sm flex-fill" onclick="stopInstance('${instance.instanceId}')" ${instance.status === 'Stopping' ? 'disabled' : ''}>
+ <i class="bi bi-stop-fill me-1"></i>鍋滄
+ </button>
+ ` : ''}
+ ${isStopped ? `
+ <button class="btn btn-success btn-sm flex-fill" onclick="startInstance('${instance.instanceId}')" ${instance.status === 'Starting' ? 'disabled' : ''}>
+ <i class="bi bi-play-fill me-1"></i>鍚姩
+ </button>
+ ` : ''}
+ <a href="/Details?id=${encodeURIComponent(instance.instanceId)}" class="btn btn-info btn-sm text-white flex-fill">
+ <i class="bi bi-info-circle-fill me-1"></i>璇︽儏
+ </a>
+ <a href="/Edit?id=${encodeURIComponent(instance.instanceId)}" class="btn btn-primary btn-sm flex-fill">
+ <i class="bi bi-pencil-fill me-1"></i>缂栬緫
+ </a>
+ <button class="btn btn-danger btn-sm" onclick="deleteInstance('${instance.instanceId}')">
+ <i class="bi bi-trash-fill"></i>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ `;
+ }
+
+ function getStatusClass(status) {
+ const map = {
+ 'Stopped': 'status-stopped',
+ 'Starting': 'status-starting',
+ 'Running': 'status-running',
+ 'Stopping': 'status-stopping',
+ 'Error': 'status-error'
+ };
+ return map[status] || '';
+ }
+
+ async function startInstance(id) {
+ confirmAction(`纭畾瑕佸惎鍔ㄥ疄渚� "${id}" 鍚�?`, async () => {
+ try {
+ await apiCall(`${API_BASE_URL}/SimulatorInstances/${encodeURIComponent(id)}/start`, {
+ method: 'POST'
+ });
+ showToast(`瀹炰緥 "${id}" 鍚姩鍛戒护宸插彂閫乣, 'success');
+ setTimeout(() => loadInstances(), 1000);
+ } catch (error) {
+ console.error('Failed to start instance:', error);
+ }
+ });
+ }
+
+ async function stopInstance(id) {
+ confirmAction(`纭畾瑕佸仠姝㈠疄渚� "${id}" 鍚�?`, async () => {
+ try {
+ await apiCall(`${API_BASE_URL}/SimulatorInstances/${encodeURIComponent(id)}/stop`, {
+ method: 'POST'
+ });
+ showToast(`瀹炰緥 "${id}" 鍋滄鍛戒护宸插彂閫乣, 'success');
+ setTimeout(() => loadInstances(), 1000);
+ } catch (error) {
+ console.error('Failed to stop instance:', error);
+ }
+ });
+ }
+
+ async function deleteInstance(id) {
+ confirmAction(`纭畾瑕佸垹闄ゅ疄渚� "${id}" 鍚�?姝ゆ搷浣滀笉鍙挙閿�!`, async () => {
+ try {
+ await apiCall(`${API_BASE_URL}/SimulatorInstances/${encodeURIComponent(id)}?deleteConfig=true`, {
+ method: 'DELETE'
+ });
+ showToast(`瀹炰緥 "${id}" 宸插垹闄, 'success');
+ loadInstances();
+ } catch (error) {
+ console.error('Failed to delete instance:', error);
+ }
+ });
+ }
+
+ function escapeHtml(text) {
+ const div = document.createElement('div');
+ div.textContent = text;
+ return div.innerHTML;
+ }
+
+ // Stop auto-refresh when page is hidden
+ document.addEventListener('visibilitychange', function () {
+ if (document.hidden) {
+ stopAutoRefresh();
+ } else {
+ startAutoRefresh(loadInstances, 5000);
+ }
+ });
+</script>
+}
--
Gitblit v1.9.3