From c493779a8504fe1eb548c865ff268a7f7436ec01 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期四, 19 三月 2026 11:43:36 +0800
Subject: [PATCH] feat: 集成机械手客户端并重构模拟器前端工作台

---
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue |  380 +++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 277 insertions(+), 103 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue
index e16d086..06cb505 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue
@@ -1,5 +1,6 @@
 锘�<template>
   <div
+    class="admin-page"
     v-loading.fullscreen.lock="startActionLoading"
     element-loading-text="姝e湪鍚姩瀹炰緥锛岃绋嶅��..."
   >
@@ -12,16 +13,43 @@
         <p class="text-muted">绠$悊鍜岀洃鎺� S7 PLC 妯℃嫙鍣ㄥ疄渚�</p>
       </div>
       <div class="header-right">
-        <div class="stats">
-          <span>杩愯涓�: {{ runningCount }} | 宸插仠姝�: {{ stoppedCount }}</span>
-          <span v-if="errorCount > 0" class="error-text">| 閿欒: {{ errorCount }}</span>
-        </div>
-        <el-button type="primary" @click="$router.push('/create')">
+        <el-button type="primary" class="create-btn" @click="$router.push('/create')">
           <el-icon><Plus /></el-icon>
           鍒涘缓瀹炰緥
         </el-button>
       </div>
     </div>
+
+    <section class="section-block">
+      <div class="section-head">
+        <div>
+          <h3 class="section-title">淇℃伅鍖�</h3>
+          <p class="section-desc">瀹炰緥杩愯鐘舵�佹�昏</p>
+        </div>
+      </div>
+      <div class="section-body">
+        <el-row :gutter="12" class="summary-row">
+          <el-col :xs="24" :sm="8">
+            <el-card shadow="hover" class="summary-card running-card">
+              <div class="summary-title">杩愯涓�</div>
+              <div class="summary-value">{{ runningCount }}</div>
+            </el-card>
+          </el-col>
+          <el-col :xs="24" :sm="8">
+            <el-card shadow="hover" class="summary-card stopped-card">
+              <div class="summary-title">宸插仠姝�</div>
+              <div class="summary-value">{{ stoppedCount }}</div>
+            </el-card>
+          </el-col>
+          <el-col :xs="24" :sm="8">
+            <el-card shadow="hover" class="summary-card error-card">
+              <div class="summary-title">閿欒瀹炰緥</div>
+              <div class="summary-value">{{ errorCount }}</div>
+            </el-card>
+          </el-col>
+        </el-row>
+      </div>
+    </section>
 
     <!-- Loading state -->
     <div v-if="loading && instances.length === 0" class="loading-container">
@@ -35,45 +63,75 @@
     </el-empty>
 
     <!-- Instances grid -->
-    <el-row v-else :gutter="20">
-      <el-col v-for="instance in instances" :key="instance.instanceId" :xs="24" :sm="12" :xl="8">
-        <el-card class="instance-card" :class="getStatusClass(instance.status)" shadow="hover">
-          <template #header>
-            <div class="card-header">
-              <span class="instance-id">{{ instance.instanceId }}</span>
-              <el-tag :type="getStatusTagType(instance.status)">
-                {{ getStatusText(instance.status) }}
-              </el-tag>
+    <section v-else class="section-block">
+      <div class="section-head">
+        <div>
+          <h3 class="section-title">鎿嶄綔鍖�</h3>
+          <p class="section-desc">瀹炰緥鍚姩銆佸仠姝€�佺紪杈戜笌璇︽儏鍏ュ彛</p>
+        </div>
+      </div>
+      <div class="section-body">
+        <el-row :gutter="14" class="instances-grid">
+          <el-col
+            v-for="instance in instances"
+            :key="instance.instanceId"
+            :xs="24"
+            :sm="12"
+            :md="12"
+            :lg="8"
+            :xl="6"
+          >
+            <el-card class="instance-card panel-card" :class="getStatusClass(instance.status)" shadow="hover">
+          <div class="card-glow"></div>
+
+          <div class="card-top">
+            <div class="card-title">
+              <div class="instance-id-line">
+                <span class="instance-id">{{ instance.instanceId }}</span>
+                <span class="instance-name">{{ instance.name || '鏈懡鍚嶅疄渚�' }}</span>
+                <span class="instance-sub">PLC</span>
+              </div>
             </div>
-          </template>
-
-          <div class="instance-info">
-            <el-descriptions :column="2" size="small">
-              <el-descriptions-item label="鍚嶇О">{{ instance.name || '-' }}</el-descriptions-item>
-              <el-descriptions-item label="PLC鍨嬪彿">{{ getPlcTypeText(instance.plcType) }}</el-descriptions-item>
-              <el-descriptions-item label="绔彛">{{ instance.port || '-' }}</el-descriptions-item>
-              <el-descriptions-item label="瀹㈡埛绔�">
-                <el-icon><User /></el-icon>
-                {{ instance.clientCount || 0 }}
-              </el-descriptions-item>
-              <el-descriptions-item v-if="instance.startTime" label="鍚姩鏃堕棿" :span="2">
-                {{ formatDate(instance.startTime) }}
-              </el-descriptions-item>
-            </el-descriptions>
-
-            <el-alert
-              v-if="instance.errorMessage"
-              type="error"
-              :closable="false"
-              class="mt-2"
-              show-icon
-            >
-              {{ instance.errorMessage }}
-            </el-alert>
+            <el-tag :type="getStatusTagType(instance.status)" effect="dark" round>
+              {{ getStatusText(instance.status) }}
+            </el-tag>
           </div>
 
-          <template #footer>
-            <div class="card-footer">
+          <div class="meta-row">
+              <div class="meta-chip">
+                <span class="chip-label">PLC</span>
+                <span class="chip-value">{{ getPlcTypeText(instance.plcType) }}</span>
+              </div>
+            <div class="meta-chip">
+              <span class="chip-label">绔彛</span>
+              <span class="chip-value">{{ instance.port || '-' }}</span>
+            </div>
+            <div class="meta-chip">
+              <span class="chip-label">瀹㈡埛绔�</span>
+              <span class="chip-value">
+                <el-icon><User /></el-icon>
+                {{ instance.clientCount || 0 }}
+              </span>
+            </div>
+          </div>
+
+          <div class="time-row">
+            <span class="time-label">鍚姩鏃堕棿</span>
+            <span class="time-value">{{ instance.startTime ? formatDate(instance.startTime) : '-' }}</span>
+          </div>
+
+          <el-alert
+            v-if="instance.errorMessage"
+            type="error"
+            :closable="false"
+            class="mt-2"
+            show-icon
+          >
+            {{ instance.errorMessage }}
+          </el-alert>
+
+          <div class="card-footer">
+            <div class="main-actions">
               <el-button
                 v-if="instance.status === 'Running'"
                 type="warning"
@@ -98,14 +156,16 @@
                 <el-icon><Edit /></el-icon>
                 缂栬緫
               </el-button>
-              <el-button type="danger" @click="handleDelete(instance.instanceId)">
-                <el-icon><Delete /></el-icon>
-              </el-button>
             </div>
-          </template>
-        </el-card>
-      </el-col>
-    </el-row>
+            <el-button class="delete-btn" type="danger" @click="handleDelete(instance.instanceId)">
+              <el-icon><Delete /></el-icon>
+            </el-button>
+          </div>
+            </el-card>
+          </el-col>
+        </el-row>
+      </div>
+    </section>
   </div>
 </template>
 
@@ -246,106 +306,220 @@
 </script>
 
 <style scoped>
-.page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: flex-start;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-  gap: 16px;
-}
-
 .header-left h2 {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  margin: 0 0 8px 0;
-}
-
-.text-muted {
-  color: #909399;
   margin: 0;
 }
 
 .header-right {
   display: flex;
   align-items: center;
-  gap: 16px;
+  gap: 10px;
   flex-wrap: wrap;
 }
 
-.stats {
-  color: #606266;
-  font-size: 14px;
+.create-btn {
+  padding-inline: 18px;
 }
 
-.error-text {
-  color: #f56c6c;
+.summary-row {
+  margin-top: -2px;
+  margin-bottom: 2px;
 }
 
-.loading-container {
-  text-align: center;
-  padding: 60px 0;
-  color: #909399;
+.instances-grid {
+  max-width: 1500px;
 }
 
-.loading-icon {
-  animation: spin 1s linear infinite;
+.summary-card {
+  border-radius: 12px;
+  border: 1px solid #dbe2ea;
+  overflow: hidden;
 }
 
-@keyframes spin {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
+.summary-title {
+  color: #64748b;
+  font-size: 13px;
+  margin-bottom: 6px;
+}
+
+.summary-value {
+  font-size: 28px;
+  font-weight: 700;
+  line-height: 1;
+}
+
+.running-card {
+  background: linear-gradient(180deg, #f0fdf4 0%, #ffffff 100%);
+}
+
+.running-card .summary-value {
+  color: #15803d;
+}
+
+.stopped-card {
+  background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
+}
+
+.stopped-card .summary-value {
+  color: #334155;
+}
+
+.error-card {
+  background: linear-gradient(180deg, #fef2f2 0%, #ffffff 100%);
+}
+
+.error-card .summary-value {
+  color: #b91c1c;
 }
 
 .instance-card {
-  margin-bottom: 20px;
-  transition: all 0.3s;
+  margin-bottom: 10px;
+  position: relative;
+  border-radius: 12px;
+  border: 1px solid #dbe2ea;
+  transition: all 0.25s;
+  overflow: hidden;
 }
 
 .instance-card:hover {
-  transform: translateY(-4px);
+  transform: translateY(-3px);
+  box-shadow: 0 14px 26px rgba(15, 23, 42, 0.1);
 }
 
-.card-header {
+.card-glow {
+  position: absolute;
+  top: -56px;
+  right: -56px;
+  width: 100px;
+  height: 100px;
+  border-radius: 50%;
+  background: radial-gradient(circle, rgba(14, 116, 244, 0.16), transparent 70%);
+  pointer-events: none;
+}
+
+.card-title {
   display: flex;
-  justify-content: space-between;
-  align-items: center;
+  flex-direction: column;
+  gap: 1px;
+  min-width: 0;
 }
 
 .instance-id {
   font-weight: 600;
-  font-size: 16px;
+  font-size: 15px;
+  color: #0f172a;
+  white-space: nowrap;
 }
 
-.instance-info {
-  margin-bottom: 16px;
+.instance-name {
+  color: #64748b;
+  font-size: 12px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
-.card-footer {
+.instance-id-line {
   display: flex;
+  align-items: baseline;
+  gap: 6px;
+  min-width: 0;
+}
+
+.instance-sub {
+  color: #94a3b8;
+  font-size: 10px;
+}
+
+.card-top {
+  margin-top: 2px;
+  display: flex;
+  justify-content: space-between;
   gap: 8px;
+  align-items: flex-start;
+}
+
+.meta-row {
+  margin-top: 8px;
+  display: flex;
+  gap: 6px;
   flex-wrap: wrap;
 }
 
-.card-footer .el-button {
-  flex: 1;
-  min-width: 60px;
+.meta-chip {
+  border: 1px solid #e2e8f0;
+  border-radius: 999px;
+  padding: 4px 8px;
+  background: #f8fafc;
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
 }
 
-.status-stopped { border-left: 4px solid #909399; }
-.status-starting { border-left: 4px solid #409eff; }
-.status-running { border-left: 4px solid #67c23a; }
-.status-stopping { border-left: 4px solid #e6a23c; }
-.status-error { border-left: 4px solid #f56c6c; }
+.chip-label {
+  font-size: 10px;
+  line-height: 1;
+  color: #64748b;
+  padding: 1px 5px;
+  border-radius: 999px;
+  background: #e2e8f0;
+}
+
+.chip-value {
+  font-size: 12px;
+  line-height: 1;
+  color: #0f172a;
+  display: inline-flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.time-row {
+  margin-top: 7px;
+  margin-bottom: 8px;
+  display: flex;
+  justify-content: space-between;
+  gap: 8px;
+  font-size: 11px;
+}
+
+.time-label {
+  color: #64748b;
+}
+
+.time-value {
+  color: #0f172a;
+}
+
+.card-footer {
+  border-top: 1px dashed #dbe2ea;
+  padding-top: 8px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  gap: 10px;
+}
+
+.main-actions {
+  display: flex;
+  gap: 6px;
+  flex-wrap: wrap;
+}
+
+.main-actions .el-button {
+  border-radius: 8px;
+  height: 28px;
+  padding: 0 10px;
+}
+
+.delete-btn {
+  border-radius: 8px;
+  height: 28px;
+  padding: 0 10px;
+}
 
 .mt-2 {
   margin-top: 8px;
 }
 </style>
-
 

--
Gitblit v1.9.3