1
wanshenmean
2026-03-16 689dd676fc0efb31236d989334122590b7198d61
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue
@@ -1,202 +1,188 @@
<template>
  <div>
    <div v-if="loading" class="text-center py-5">
      <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">加载中...</span>
      </div>
    <div v-if="loading" class="loading-container">
      <el-icon class="loading-icon" :size="40"><Loading /></el-icon>
      <p>加载中...</p>
    </div>
    <div v-else-if="errorMsg">
      <div class="alert alert-danger">{{ errorMsg }}</div>
      <router-link to="/" class="btn btn-primary">返回列表</router-link>
      <el-result icon="error" :title="errorMsg">
        <template #extra>
          <el-button type="primary" @click="$router.push('/')">返回列表</el-button>
        </template>
      </el-result>
    </div>
    <div v-else>
      <div class="d-flex justify-content-between align-items-center mb-4">
        <div>
          <h2 class="mb-0">
            <i class="bi bi-pencil me-2"></i>编辑实例
      <div class="page-header">
        <div class="header-left">
          <h2>
            <el-icon :size="24"><Edit /></el-icon>
            编辑实例
          </h2>
          <p class="text-muted mb-0 mt-1">编辑实例配置: {{ form.id }}</p>
          <p class="text-muted">编辑实例配置: {{ form.id }}</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 v-if="isRunning" class="alert alert-warning">
        <i class="bi bi-exclamation-triangle-fill me-2"></i>
      <el-alert
        v-if="isRunning"
        type="warning"
        :closable="false"
        class="mb-4"
        show-icon
      >
        实例正在运行中,修改配置后需要重启实例才能生效
      </div>
      </el-alert>
      <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"
                      v-model="form.id"
                      disabled
                    >
                    <div class="form-text">实例ID创建后不可修改</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
                    >
                  </div>
                </div>
      <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>
                <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
                    >
                  </div>
                </div>
              <el-row :gutter="20">
                <el-col :span="12">
                  <el-form-item label="实例ID">
                    <el-input v-model="form.id" disabled />
                    <div class="form-tip">实例ID创建后不可修改</div>
                  </el-form-item>
                </el-col>
                <el-col :span="12">
                  <el-form-item label="实例名称" prop="name">
                    <el-input v-model="form.name" />
                  </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"
                    >
                  </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="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>
                <!-- 内存配置 -->
                <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"
                    >
                  </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"
                    >
                  </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"
                    >
                  </div>
                </div>
              <el-row :gutter="20">
                <el-col :span="12">
                  <el-form-item label="HSL激活码">
                    <el-input v-model="form.activationKey" />
                  </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>
                <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"
                    >
                  </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"
                    >
                  </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"
                    >
                  </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"
                    >
                  </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-input-number
                      v-model="form.dbBlockCount"
                      :min="0"
                      style="width: 100%"
                    />
                  </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>
  </div>
</template>
@@ -204,11 +190,15 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { Edit, Back, Loading } from '@element-plus/icons-vue'
import * as api from '../api'
import type { InstanceConfig, MemoryRegionConfig, SiemensPLCType } from '../types'
const router = useRouter()
const route = useRoute()
const formRef = ref<FormInstance>()
const form = ref({
  id: '',
@@ -232,6 +222,19 @@
const isRunning = ref(false)
const id = route.params.id as string
const rules: FormRules = {
  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' }
  ]
}
onMounted(async () => {
  try {
@@ -261,8 +264,8 @@
      activationKey: config.activationKey,
      autoStart: config.autoStart,
      mRegionSize: config.memoryConfig.mRegionSize,
      dbBlockCount: config.memoryConfig.dBBBlockCount,
      dbBlockSize: config.memoryConfig.dBBBlockSize,
      dbBlockCount: config.memoryConfig.dbBlockCount,
      dbBlockSize: config.memoryConfig.dbBlockSize,
      iRegionSize: config.memoryConfig.iRegionSize,
      qRegionSize: config.memoryConfig.qRegionSize,
      tRegionCount: config.memoryConfig.tRegionCount,
@@ -277,54 +280,107 @@
})
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 memoryConfig: MemoryRegionConfig = {
        mRegionSize: form.value.mRegionSize > 0 ? form.value.mRegionSize : 1024,
        dbBlockCount: form.value.dbBlockCount > 0 ? form.value.dbBlockCount : 100,
        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,
        memoryConfig
      }
      const result = await api.updateInstance(form.value.id, 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.updateInstance(form.value.id, config)
    if (result) {
      alert(`实例 "${form.value.id}" 更新成功!`)
      router.push('/')
    } else {
      alert('更新实例失败')
    }
  } catch (err) {
    console.error('更新实例失败:', err)
    alert('更新实例失败,请查看控制台')
  } finally {
    submitting.value = false
  }
  })
}
</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;
}
.loading-container {
  text-align: center;
  padding: 60px 0;
  color: #909399;
}
.loading-icon {
  animation: spin 1s linear infinite;
}
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
.form-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}
.el-divider h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}
.mb-4 {
  margin-bottom: 16px;
}
</style>