From 94ad631d316da04c46266ddb1fc6e63e6f8f2fae Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期二, 17 三月 2026 17:34:15 +0800
Subject: [PATCH] feat: 同步协议处理、前端交互与业务联调改动

---
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue |  524 +++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 297 insertions(+), 227 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue
index 183c71c..88b6545 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue
@@ -1,218 +1,220 @@
-<template>
+锘�<template>
   <div>
-    <div class="d-flex justify-content-between align-items-center mb-4">
-      <div>
-        <h2 class="mb-0">
-          <i class="bi bi-plus-circle me-2"></i>鍒涘缓瀹炰緥
+    <div class="page-header">
+      <div class="header-left">
+        <h2>
+          <el-icon :size="24"><Plus /></el-icon>
+          鍒涘缓瀹炰緥
         </h2>
-        <p class="text-muted mb-0 mt-1">鍒涘缓鏂扮殑 S7 PLC 浠跨湡鍣ㄥ疄渚�</p>
+        <p class="text-muted">鍒涘缓鏂扮殑 S7 PLC 浠跨湡瀹炰緥</p>
       </div>
-      <router-link to="/" class="btn btn-outline-secondary">
-        <i class="bi bi-arrow-left me-1"></i>杩斿洖鍒楄〃
-      </router-link>
+      <el-button @click="$router.push('/')">
+        <el-icon><Back /></el-icon>
+        杩斿洖鍒楄〃
+      </el-button>
     </div>
 
-    <div class="row justify-content-center">
-      <div class="col-lg-8">
-        <div class="card">
-          <div class="card-body">
-            <form @submit.prevent="handleSubmit">
-              <!-- 鍩烘湰淇℃伅 -->
-              <h5 class="card-title mb-3">鍩烘湰淇℃伅</h5>
-              <div class="row mb-3">
-                <div class="col-md-6">
-                  <label for="id" class="form-label">瀹炰緥ID *</label>
-                  <input
-                    type="text"
-                    class="form-control"
-                    id="id"
+    <el-row justify="center">
+      <el-col :lg="24">
+        <el-card shadow="never">
+          <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+            <!-- 鍩烘湰淇℃伅 -->
+            <el-divider content-position="left">
+              <h3>鍩烘湰淇℃伅</h3>
+            </el-divider>
+
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="瀹炰緥ID" prop="id">
+                  <el-input
                     v-model="form.id"
                     pattern="[a-zA-Z0-9_-]+"
-                    required
                     placeholder="渚嬪: PLC_001"
                   >
-                  <div class="form-text">鍙兘鍖呭惈瀛楁瘝銆佹暟瀛椼�佷笅鍒掔嚎鍜岃繛瀛楃</div>
-                </div>
-                <div class="col-md-6">
-                  <label for="name" class="form-label">瀹炰緥鍚嶇О *</label>
-                  <input
-                    type="text"
-                    class="form-control"
-                    id="name"
-                    v-model="form.name"
-                    required
-                    placeholder="渚嬪: 1鍙稰LC"
-                  >
-                </div>
-              </div>
+                    <template #append>
+                      <el-tooltip content="鍙兘鍖呭惈瀛楁瘝銆佹暟瀛椼�佷笅鍒掔嚎鍜岃繛瀛楃" placement="top">
+                        <el-icon><QuestionFilled /></el-icon>
+                      </el-tooltip>
+                    </template>
+                  </el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="瀹炰緥鍚嶇О" prop="name">
+                  <el-input v-model="form.name" placeholder="渚嬪: 1鍙稰LC" />
+                </el-form-item>
+              </el-col>
+            </el-row>
 
-              <div class="row mb-3">
-                <div class="col-md-6">
-                  <label for="plcType" class="form-label">PLC鍨嬪彿 *</label>
-                  <select class="form-select" id="plcType" v-model="form.plcType" required>
-                    <option value="S7200Smart">S7-200 Smart</option>
-                    <option value="S71200">S7-1200</option>
-                    <option value="S71500">S7-1500</option>
-                    <option value="S7300">S7-300</option>
-                    <option value="S7400">S7-400</option>
-                  </select>
-                </div>
-                <div class="col-md-6">
-                  <label for="port" class="form-label">鐩戝惉绔彛 *</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="port"
-                    v-model.number="form.port"
-                    min="1"
-                    max="65535"
-                    required
-                    placeholder="102"
-                  >
-                </div>
-              </div>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="PLC鍨嬪彿" prop="plcType">
+                  <el-select v-model="form.plcType" style="width: 100%">
+                    <el-option label="S7-200 Smart" value="S7200Smart" />
+                    <el-option label="S7-1200" value="S71200" />
+                    <el-option label="S7-1500" value="S71500" />
+                    <el-option label="S7-300" value="S7300" />
+                    <el-option label="S7-400" value="S7400" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="鐩戝惉绔彛" prop="port">
+                  <el-input-number
+                    v-model="form.port"
+                    :min="1"
+                    :max="65535"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
 
-              <div class="row mb-3">
-                <div class="col-md-6">
-                  <label for="activationKey" class="form-label">HSL婵�娲荤爜</label>
-                  <input
-                    type="text"
-                    class="form-control"
-                    id="activationKey"
-                    v-model="form.activationKey"
-                    placeholder="鍙�夛紝鐣欑┖浣跨敤榛樿"
-                  >
-                </div>
-                <div class="col-md-6 d-flex align-items-center">
-                  <div class="form-check">
-                    <input class="form-check-input" type="checkbox" id="autoStart" v-model="form.autoStart">
-                    <label class="form-check-label" for="autoStart">
-                      鑷姩鍚姩
-                    </label>
-                  </div>
-                </div>
-              </div>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="HSL婵�娲荤爜">
+                  <el-input v-model="form.activationKey" placeholder="鍙�夛紝鐣欑┖浣跨敤榛樿" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="鑷姩鍚姩">
+                  <el-switch v-model="form.autoStart" />
+                </el-form-item>
+              </el-col>
+            </el-row>
 
-              <!-- 鍐呭瓨閰嶇疆 -->
-              <h5 class="card-title mb-3 mt-4">鍐呭瓨閰嶇疆</h5>
-              <div class="row mb-3">
-                <div class="col-md-4">
-                  <label for="mRegionSize" class="form-label">M鍖哄煙澶у皬</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="mRegionSize"
-                    v-model.number="form.mRegionSize"
-                    min="0"
-                    placeholder="1024"
-                  >
-                </div>
-                <div class="col-md-4">
-                  <label for="iRegionSize" class="form-label">I鍖哄煙澶у皬</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="iRegionSize"
-                    v-model.number="form.iRegionSize"
-                    min="0"
-                    placeholder="256"
-                  >
-                </div>
-                <div class="col-md-4">
-                  <label for="qRegionSize" class="form-label">Q鍖哄煙澶у皬</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="qRegionSize"
-                    v-model.number="form.qRegionSize"
-                    min="0"
-                    placeholder="256"
-                  >
-                </div>
-              </div>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="鍗忚妯℃澘" prop="protocolTemplateId">
+                  <el-select v-model="form.protocolTemplateId" style="width: 100%">
+                    <el-option
+                      v-for="tpl in protocolTemplates"
+                      :key="tpl.id"
+                      :label="`${tpl.name} (${tpl.id})`"
+                      :value="tpl.id"
+                    />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
 
-              <div class="row mb-3">
-                <div class="col-md-4">
-                  <label for="dbBlockCount" class="form-label">DB鍧楁暟閲�</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="dbBlockCount"
-                    v-model.number="form.dbBlockCount"
-                    min="0"
-                    placeholder="100"
-                  >
-                </div>
-                <div class="col-md-4">
-                  <label for="dbBlockSize" class="form-label">DB鍧楀ぇ灏�</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="dbBlockSize"
-                    v-model.number="form.dbBlockSize"
-                    min="0"
-                    placeholder="1024"
-                  >
-                </div>
-                <div class="col-md-2">
-                  <label for="tRegionCount" class="form-label">瀹氭椂鍣ㄦ暟閲�</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="tRegionCount"
-                    v-model.number="form.tRegionCount"
-                    min="0"
-                    placeholder="64"
-                  >
-                </div>
-                <div class="col-md-2">
-                  <label for="cRegionCount" class="form-label">璁℃暟鍣ㄦ暟閲�</label>
-                  <input
-                    type="number"
-                    class="form-control"
-                    id="cRegionCount"
-                    v-model.number="form.cRegionCount"
-                    min="0"
-                    placeholder="64"
-                  >
-                </div>
-              </div>
+            <!-- 鍐呭瓨閰嶇疆 -->
+            <el-divider content-position="left">
+              <h3>鍐呭瓨閰嶇疆</h3>
+            </el-divider>
 
-              <!-- 鎻愪氦鎸夐挳 -->
-              <div class="d-flex gap-2 mt-4">
-                <button type="submit" class="btn btn-primary" :disabled="submitting">
-                  <span v-if="submitting" class="spinner-border spinner-border-sm me-1"></span>
-                  <i v-else class="bi bi-check-lg me-1"></i>
-                  {{ submitting ? '鍒涘缓涓�...' : '鍒涘缓瀹炰緥' }}
-                </button>
-                <router-link to="/" class="btn btn-outline-secondary">鍙栨秷</router-link>
-              </div>
-            </form>
-          </div>
-        </div>
-      </div>
-    </div>
+            <el-row :gutter="20">
+              <el-col :span="8">
+                <el-form-item label="M鍖哄ぇ灏�">
+                  <el-input-number
+                    v-model="form.mRegionSize"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="I鍖哄ぇ灏�">
+                  <el-input-number
+                    v-model="form.iRegionSize"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="Q鍖哄ぇ灏�">
+                  <el-input-number
+                    v-model="form.qRegionSize"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+              <el-col :span="8">
+                <el-form-item label="DB鍧楀垪琛�">
+                  <el-select
+                    v-model="form.dbBlockNumbers"
+                    multiple
+                    filterable
+                    allow-create
+                    default-first-option
+                    :reserve-keyword="false"
+                    style="width: 100%"
+                    placeholder="杈撳叆鍧楀彿鍚庡洖杞︼紝渚嬪 50銆�900銆�901"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="DB鍧楀ぇ灏�">
+                  <el-input-number
+                    v-model="form.dbBlockSize"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item label="瀹氭椂鍣ㄦ暟閲�">
+                  <el-input-number
+                    v-model="form.tRegionCount"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item label="璁℃暟鍣ㄦ暟閲�">
+                  <el-input-number
+                    v-model="form.cRegionCount"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <!-- 鎻愪氦鎸夐挳 -->
+            <el-form-item>
+              <el-button type="primary" @click="handleSubmit" :loading="submitting">
+                {{ submitting ? '鍒涘缓涓�...' : '鍒涘缓瀹炰緥' }}
+              </el-button>
+              <el-button @click="$router.push('/')">鍙栨秷</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </el-col>
+    </el-row>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue'
+import { onMounted, ref } from 'vue'
 import { useRouter } from 'vue-router'
+import { ElMessage } from 'element-plus'
+import type { FormInstance, FormRules } from 'element-plus'
+import { Plus, Back, QuestionFilled } from '@element-plus/icons-vue'
 import * as api from '../api'
-import type { InstanceConfig, MemoryRegionConfig, SiemensPLCType } from '../types'
+import type { InstanceConfig, MemoryRegionConfig, ProtocolTemplate, SiemensPLCType } from '../types'
 
 const router = useRouter()
+const formRef = ref<FormInstance>()
 
 const form = ref({
-  id: '',
-  name: '',
+  id: 'GWSC1',
+  name: '楂樻俯1鍙峰爢鍨涙満',
   plcType: 'S71200' as SiemensPLCType,
   port: 102,
-  activationKey: '',
+  activationKey: '4b86f3fc-f650-3b08-5924-b0f8278d6ed2',
   autoStart: false,
+  protocolTemplateId: '',
   mRegionSize: 1024,
-  dbBlockCount: 100,
-  dbBlockSize: 1024,
+  dbBlockCount: 0,
+  dbBlockNumbers: [] as Array<number | string>,
+  dbBlockSize: 65536,
   iRegionSize: 256,
   qRegionSize: 256,
   tRegionCount: 64,
@@ -220,56 +222,124 @@
 })
 
 const submitting = ref(false)
+const protocolTemplates = ref<ProtocolTemplate[]>([])
+
+const rules: FormRules = {
+  id: [
+    { required: true, message: '璇疯緭鍏ュ疄渚婭D', trigger: 'blur' },
+    { pattern: /^[a-zA-Z0-9_-]+$/, message: '鍙兘鍖呭惈瀛楁瘝銆佹暟瀛椼�佷笅鍒掔嚎鍜岃繛瀛楃', trigger: 'blur' }
+  ],
+  name: [
+    { required: true, message: '璇疯緭鍏ュ疄渚嬪悕绉�', trigger: 'blur' }
+  ],
+  plcType: [
+    { required: true, message: '璇烽�夋嫨PLC鍨嬪彿', trigger: 'change' }
+  ],
+  port: [
+    { required: true, message: '璇疯緭鍏ョ洃鍚鍙�', trigger: 'blur' },
+    { type: 'number', min: 1, max: 65535, message: '绔彛蹇呴』鍦� 1-65535 涔嬮棿', trigger: 'blur' }
+  ],
+  protocolTemplateId: [
+    { required: true, message: '璇烽�夋嫨鍗忚妯℃澘', trigger: 'change' }
+  ]
+}
+
+onMounted(async () => {
+  protocolTemplates.value = await api.getProtocolTemplates()
+  if (protocolTemplates.value.length > 0) {
+    form.value.protocolTemplateId = protocolTemplates.value[0].id
+  }
+})
 
 async function handleSubmit() {
-  submitting.value = true
+  if (!formRef.value) return
 
-  try {
-    const memoryConfig: MemoryRegionConfig = {
-      mRegionSize: form.value.mRegionSize > 0 ? form.value.mRegionSize : 1024,
-      dBBBlockCount: form.value.dbBlockCount > 0 ? form.value.dbBlockCount : 100,
-      dBBBlockSize: form.value.dbBlockSize > 0 ? form.value.dbBlockSize : 1024,
-      iRegionSize: form.value.iRegionSize > 0 ? form.value.iRegionSize : 256,
-      qRegionSize: form.value.qRegionSize > 0 ? form.value.qRegionSize : 256,
-      tRegionCount: form.value.tRegionCount > 0 ? form.value.tRegionCount : 64,
-      cRegionCount: form.value.cRegionCount > 0 ? form.value.cRegionCount : 64
+  await formRef.value.validate(async (valid) => {
+    if (!valid) return
+
+    submitting.value = true
+
+    try {
+      const dbBlockNumbers = normalizeDbBlockNumbers(form.value.dbBlockNumbers)
+      if (dbBlockNumbers.length === 0) {
+        ElMessage.error('璇疯嚦灏戦厤缃竴涓狣B鍧楀彿锛屼緥濡� 50,900,901')
+        return
+      }
+
+      const memoryConfig: MemoryRegionConfig = {
+        mRegionSize: form.value.mRegionSize > 0 ? form.value.mRegionSize : 1024,
+        dbBlockCount: 0,
+        dbBlockNumbers,
+        dbBlockSize: form.value.dbBlockSize > 0 ? form.value.dbBlockSize : 1024,
+        iRegionSize: form.value.iRegionSize > 0 ? form.value.iRegionSize : 256,
+        qRegionSize: form.value.qRegionSize > 0 ? form.value.qRegionSize : 256,
+        tRegionCount: form.value.tRegionCount > 0 ? form.value.tRegionCount : 64,
+        cRegionCount: form.value.cRegionCount > 0 ? form.value.cRegionCount : 64
+      }
+
+      const config: InstanceConfig = {
+        id: form.value.id,
+        name: form.value.name,
+        plcType: form.value.plcType,
+        port: form.value.port,
+        activationKey: form.value.activationKey || '',
+        autoStart: form.value.autoStart,
+        protocolTemplateId: form.value.protocolTemplateId,
+        memoryConfig
+      }
+
+      const result = await api.createInstance(config)
+
+      if (result) {
+        ElMessage.success(`瀹炰緥 "${form.value.id}" 鍒涘缓鎴愬姛!`)
+        router.push('/')
+      } else {
+        ElMessage.error('鍒涘缓瀹炰緥澶辫触锛岃妫�鏌ヨ緭鍏�')
+      }
+    } catch (err) {
+      console.error('鍒涘缓瀹炰緥澶辫触:', err)
+      ElMessage.error('鍒涘缓瀹炰緥澶辫触锛岃鏌ョ湅鎺у埗鍙�')
+    } finally {
+      submitting.value = false
     }
+  })
+}
 
-    const config: InstanceConfig = {
-      id: form.value.id,
-      name: form.value.name,
-      plcType: form.value.plcType,
-      port: form.value.port,
-      activationKey: form.value.activationKey || '',
-      autoStart: form.value.autoStart,
-      memoryConfig
-    }
-
-    const result = await api.createInstance(config)
-
-    if (result) {
-      alert(`瀹炰緥 "${form.value.id}" 鍒涘缓鎴愬姛!`)
-      router.push('/')
-    } else {
-      alert('鍒涘缓瀹炰緥澶辫触锛岃妫�鏌ヨ緭鍏�')
-    }
-  } catch (err) {
-    console.error('鍒涘缓瀹炰緥澶辫触:', err)
-    alert('鍒涘缓瀹炰緥澶辫触锛岃鏌ョ湅鎺у埗鍙�')
-  } finally {
-    submitting.value = false
-  }
+function normalizeDbBlockNumbers(input: Array<number | string>): number[] {
+  return Array.from(new Set(
+    input
+      .map(x => Number(String(x).trim()))
+      .filter(x => Number.isInteger(x) && x > 0)
+  )).sort((a, b) => a - b)
 }
 </script>
 
 <style scoped>
-.card-title {
-  color: #495057;
-  font-weight: 600;
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  margin-bottom: 20px;
+  flex-wrap: wrap;
+  gap: 16px;
 }
 
-.form-label {
-  font-weight: 500;
-  color: #495057;
+.header-left h2 {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin: 0 0 8px 0;
+}
+
+.text-muted {
+  color: #909399;
+  margin: 0;
+}
+
+.el-divider h3 {
+  margin: 0;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
 }
 </style>

--
Gitblit v1.9.3