From d216edd0e9931d71664f33e625cff6d8131a0fad Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期五, 13 三月 2026 16:00:40 +0800
Subject: [PATCH] 重构: 实现前后端分离架构

---
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml |  241 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 237 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..13cd2f0 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,243 @@
 锘緻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>
+    <div class="d-flex align-items-center gap-3">
+        <div id="refreshIndicator" class="text-muted small" style="display: none;">
+            <i class="bi bi-arrow-clockwise spin-icon me-1"></i>
+            <span>鏇存柊涓�...</span>
+        </div>
+        <a asp-page="/Create" class="btn btn-primary">
+            <i class="bi bi-plus-lg me-1"></i>鍒涘缓瀹炰緥
+        </a>
+    </div>
 </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(false); // 棣栨鍔犺浇鏄剧ず loading
+        startAutoRefresh(() => loadInstances(true), 2000); // 鑷姩鍒锋柊浣跨敤闈欓粯妯″紡锛屾瘡2绉掑埛鏂�
+    });
+
+    async function loadInstances(silent = false) {
+        const refreshIndicator = document.getElementById('refreshIndicator');
+        if (silent && refreshIndicator) {
+            refreshIndicator.style.display = 'block';
+        }
+
+        try {
+            const instances = await apiCall(`${API_BASE_URL}/SimulatorInstances`, { silent: silent });
+            renderInstances(instances);
+        } catch (error) {
+            console.error('Failed to load instances:', error);
+            if (!silent) {
+                document.getElementById('loadingState').classList.add('d-none');
+                document.getElementById('emptyState').classList.remove('d-none');
+            }
+        } finally {
+            if (silent && refreshIndicator) {
+                refreshIndicator.style.display = '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(false), 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(false), 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(false);
+            } 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