zhaoen 3 mesi fa
parent
commit
04d2179eae

+ 8 - 0
src/api/subPlanZb/index.js

@@ -40,6 +40,14 @@ export function getSubPlanZbTsList(params) {
     });
 }
 
+export function deleteSubPlanZbTsList(data) {
+    return request({
+        url: "/api/v1/simequipment-deployment/delete",
+        method: "post",
+        params:data,
+    });
+}
+
 
 
 export function getSubPlanZbStatistics(params) {

+ 1 - 1
src/views/Deduction/taskSetting/Scenarioediting.vue

@@ -639,7 +639,7 @@ export default {
         this.selectedSubTask = task;
         this.selectedTreeNode = null;
 
-        getListVer({}).then((res) => {
+        getListVer({subTaskId:task.id}).then((res) => {
           this.schemeTable = res.data;
           // 确保表格数据更新后重新渲染
           this.$nextTick(() => {

+ 34 - 35
src/views/Deduction/taskSetting/components/GanttChart.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="gantt-container">
     <div class="chart-wrapper">
-      <div ref="ganttChart" class="gantt-chart" :style="{width: '100%', height: '600px'}"></div>
+      <div ref="ganttChart" class="gantt-chart" :style="{width: '100%', height: chartHeight + 'px'}"></div>
     </div>
     <div class="legend-container">
       <div class="legend-items">
@@ -42,7 +42,7 @@ export default {
     },
     defaultDuration: {
       type: Number,
-      required: true, // 设为必填,确保有默认持续时间
+      required: true,
       default: 3600 // 默认1小时
     },
     timeMargin: {
@@ -58,6 +58,9 @@ export default {
     }
   },
   computed: {
+    chartHeight() {
+      return this.timeOrderedItems.length * 60 + 400
+    },
     legendData() {
       const legends = Object.keys(this.typeColorMap).map(type => ({
         name: type,
@@ -80,7 +83,6 @@ export default {
 
       const times = this.timelineData.flatMap(item => {
         const startTime = getTimeInSeconds(item.rawTime)
-        // 明确使用defaultDuration计算结束时间
         const endTime = startTime + (item.duration || this.defaultDuration);
         return [startTime, endTime];
       });
@@ -89,7 +91,7 @@ export default {
       const maxTime = Math.max(...times) + this.timeMargin;
       return {
         min: Math.max(0, minTime),
-        max: Math.max(this.defaultDuration, maxTime) // 确保至少能显示一个defaultDuration
+        max: Math.max(this.defaultDuration, maxTime)
       }
     },
 
@@ -104,25 +106,26 @@ export default {
 
       return this.timelineData.map(item => {
         const startTime = getTimeInSeconds(item.rawTime)
-        // 明确计算持续时间,优先使用item.duration,否则使用defaultDuration
         const duration = item.duration || this.defaultDuration;
         const endTime = startTime + duration;
 
+        // 根据id查找索引,确保唯一性
         const yAxisIndex = this.timeOrderedItems.findIndex(
-            orderedItem => orderedItem.rawTime === item.rawTime && orderedItem.name === item.name
+            orderedItem => orderedItem.id === item.id
         );
 
         const displayTime = item.rawTime.startsWith('T0+') ? item.rawTime : `T0+${item.rawTime}`;
-        const displayText = `${item.title || '无标题'}  ${displayTime}\n${item.desc || '无描述'}\n持续时间: ${this.formatDuration(duration)}`
+        const displayText = `${displayTime}\n${item.title || '无标题'} \n${item.desc || '无描述'}`
 
         return {
+          id: item.id, // 保留id用于标识
           name: item.name,
           zbType: item.zbType,
           value: [
             yAxisIndex,
             startTime,
             endTime,
-            duration, // 存储实际使用的持续时间
+            duration,
             item.title
           ],
           itemStyle: {
@@ -142,12 +145,11 @@ export default {
   watch: {
     timelineData: { deep: true, handler: 'updateChart' },
     typeColorMap: { deep: true, handler: 'updateChart' },
-    defaultDuration: { handler: 'updateChart' }, // 监听defaultDuration变化
+    defaultDuration: { handler: 'updateChart' },
     timeMargin: { handler: 'updateChart' },
     activeLegends: { deep: true, handler: 'updateChart' }
   },
   methods: {
-    // 格式化持续时间显示
     formatDuration(seconds) {
       const hours = Math.floor(seconds / 3600);
       const minutes = Math.floor((seconds % 3600) / 60);
@@ -155,6 +157,7 @@ export default {
       return `${hours}h${minutes}m${secs}s`;
     },
 
+    // 根据id获取唯一的时间线项目
     getOrderedTimelineItems() {
       const getTimeInSeconds = (timeStr) => {
         const cleanTimeStr = timeStr.startsWith('T0+') ? timeStr.slice(3) : timeStr;
@@ -162,12 +165,14 @@ export default {
         return hours * 3600 + minutes * 60 + seconds
       }
 
+      // 使用id作为唯一标识去重
       const uniqueItems = Array.from(
           new Map(this.timelineData.map(item =>
-              [`${item.rawTime}-${item.name}`, item]
+              [item.id, item] // 用id作为map的key确保唯一性
           )).values()
       );
 
+      // 按时间和名称排序
       return uniqueItems.sort((a, b) => {
         const timeA = getTimeInSeconds(a.rawTime);
         const timeB = getTimeInSeconds(b.rawTime);
@@ -213,6 +218,7 @@ export default {
     setChartOption() {
       if (!this.chart) return
 
+      // 使用id对应的项目作为Y轴数据
       const yAxisData = this.timeOrderedItems.map(item =>
           `${item.name} (${item.rawTime})`
       );
@@ -226,18 +232,18 @@ export default {
 
       const option = {
         tooltip: {
-          show: true,
-          formatter: (params) => {
-            const data = params.data;
-            return `
-              <div style="font-weight:bold">${data.name}</div>
-              <div>开始时间: ${formatTime(data.value[1])}</div>
-              <div>结束时间: ${formatTime(data.value[2])}</div>
-              <div>持续时间: ${this.formatDuration(data.value[3])}</div>
-            `;
-          }
+          show: false,
+          // formatter: (params) => {
+          //   const data = params.data;
+          //   return `
+          //     <div style="font-weight:bold">${data.name}</div>
+          //     <div>开始时间: ${formatTime(data.value[1])}</div>
+          //     <div>结束时间: ${formatTime(data.value[2])}</div>
+          //     <div>持续时间: ${this.formatDuration(data.value[3])}</div>
+          //   `;
+          // }
         },
-        grid: { left: '5%', right: '8%', top: '10%', bottom: '15%' },
+        grid: { left: '5%', right: '5%', top: '5%', bottom: '5%' },
         xAxis: {
           type: 'value',
           name: '时间',
@@ -259,34 +265,28 @@ export default {
             type: 'custom',
             data: this.processedData,
             renderItem: (params, api) => {
-              // 获取时间值和持续时间
               const startTime = api.value(1);
-              const duration = api.value(3); // 使用计算好的持续时间(含defaultDuration)
+              const duration = api.value(3);
               const endTime = startTime + duration;
               const categoryIndex = api.value(0);
 
-              // 计算X轴比例和实际宽度
               const xAxisScale = this.timeRange.max - this.timeRange.min;
-              const chartWidth = this.chart.getWidth() * 0.85; // 考虑网格边距
+              const chartWidth = this.chart.getWidth() * 0.85;
               const startX = ((startTime - this.timeRange.min) / xAxisScale) * chartWidth;
 
-              // 基于持续时间计算宽度,确保与defaultDuration正确关联
               let width = (duration / xAxisScale) * chartWidth;
-              // 最小宽度限制,确保可见性
               const minWidth = Math.max(50, (this.defaultDuration / xAxisScale) * chartWidth * 0.5);
               width = Math.max(width, minWidth);
 
-              // Y轴位置计算
               const yPos = api.coord([0, categoryIndex])[1];
               const height = 60;
 
               const dataItem = this.processedData[params.dataIndex]
 
-              // 创建矩形元素
               const rect = {
                 type: 'rect',
                 shape: {
-                  x: startX + (this.chart.getWidth() * 0.05), // 加上左网格偏移
+                  x: startX + (this.chart.getWidth() * 0.05),
                   y: yPos - height / 2,
                   width: width,
                   height: height,
@@ -296,7 +296,6 @@ export default {
                 z2: 0
               }
 
-              // 创建文本元素
               const text = {
                 type: 'text',
                 x: startX + (this.chart.getWidth() * 0.05) + 10,
@@ -323,6 +322,7 @@ export default {
     },
 
     updateChart() {
+      console.log(this.timelineData)
       this.chart ? this.setChartOption() : this.initChart()
     },
 
@@ -339,7 +339,7 @@ export default {
       const container = this.$refs.ganttChart
       if (!container.clientWidth || !container.clientHeight) {
         container.style.width = '100%'
-        container.style.height = '600px'
+        // container.style.height = '600px'
       }
       this.initChart()
     })
@@ -403,8 +403,7 @@ export default {
 }
 
 .legend-text {
-  color: #ffffff;
+  color: #FFF;
   font-size: 14px;
 }
 </style>
-

+ 166 - 166
src/views/Deduction/taskSetting/components/equipment/DynamicFormModal.vue

@@ -18,14 +18,35 @@
           v-for="(field, index) in formFields"
           :key="index"
           :label="field.label"
-          :prop="field.prop"
+          :prop="getFieldProp(field)"
           :required="isFieldRequired(field)"
           v-if="shouldShowField(field)"
       >
-        <!-- 输入框类型 (包含修改后的时间输入) -->
+        <!-- 处理ts特殊字段:拆分为分钟和秒两个输入框 -->
+        <div v-if="field.prop === 'ts'" class="ts-input-group">
+          <el-input
+              class="custom-input"
+              style="width:48%; display: inline-block; margin-right:4%"
+              v-model="tsMinutes"
+              placeholder="请输入分钟数(无上限)"
+              type="number"
+              @input="handleTsChange"
+          ></el-input>分
+          <el-input
+              class="custom-input"
+              style="width:48%; display: inline-block"
+              v-model="tsSeconds"
+              placeholder="请输入秒数(1-59)"
+              type="number"
+              max="59"
+              @input="handleTsChange"
+          ></el-input>秒
+        </div>
+
+        <!-- 其他表单字段... -->
         <el-input
             style="width:100%"
-            v-if="['string', 'number', 'decimal', 'time'].includes(field.dataType)"
+            v-else-if="['string', 'number', 'decimal', 'time'].includes(field.dataType)"
             v-model="formData[field.prop]"
             :placeholder="getFieldPlaceholder(field)"
             :type="getInputType(field.dataType)"
@@ -33,10 +54,9 @@
             @input="handleFieldChange(field.prop)"
         ></el-input>
 
-        <!-- 下拉选择框类型 -->
         <el-select
             style="width:100%"
-            v-if="field.dataType === 'select' && field.options"
+            v-else-if="field.dataType === 'select' && field.options"
             v-model="formData[field.prop]"
             :placeholder="field.placeholder || `请选择${field.label}`"
             clearable
@@ -60,44 +80,26 @@
 </template>
 
 <script>
-// 导入获取表单数据的接口
 import {getSimEquipmentDeploymentBySimulation} from "@/api/subPlanZb";
 
 export default {
   name: 'DynamicFormModal',
   props: {
-    zbId: {
-      type: String,
-      default: ''
-    },
-    planId: {
-      type: String,
-      default: ''
-    },
-    type: {
-      type: String,
-      default: ''
-    },
-    title: {
-      type: String,
-      default: '表单配置'
-    },
-    dialogWidth: {
-      type: String,
-      default: '600px'
-    },
-    formFields: {
-      type: Array,
-      required: true,
-      default: () => []
-    }
+    zbId: { type: String, default: '' },
+    planId: { type: String, default: '' },
+    type: { type: String, default: '' },
+    title: { type: String, default: '表单配置' },
+    dialogWidth: { type: String, default: '600px' },
+    formFields: { type: Array, required: true, default: () => [] }
   },
   data() {
     return {
       visible: false,
       formData: {},
       formRules: {},
-      loading: false
+      loading: false,
+      tsMinutes: '',
+      tsSeconds: ''
     };
   },
   watch: {
@@ -111,7 +113,10 @@ export default {
     },
     formData: {
       handler() {
-        // 不需要具体操作,因为shouldShowField是计算属性会自动更新
+        if (this.formData.ts !== undefined && !isNaN(this.formData.ts)) {
+          this.tsMinutes = Math.floor(this.formData.ts / 60);
+          this.tsSeconds = this.formData.ts % 60;
+        }
       },
       deep: true
     }
@@ -126,7 +131,11 @@ export default {
         if (this.formData[field.prop] !== undefined) {
           newFormData[field.prop] = this.formData[field.prop];
         } else {
-          if (field.dataType === 'select' && field.options && field.options.length) {
+          if (field.prop === 'ts') {
+            newFormData[field.prop] = 0;
+            this.tsMinutes = '';  // 初始化为空而不是0,强化非空约束
+            this.tsSeconds = '';
+          } else if (field.dataType === 'select' && field.options && field.options.length) {
             newFormData[field.prop] = '';
           } else if (field.dataType === 'number' || field.dataType === 'decimal') {
             newFormData[field.prop] = 0;
@@ -139,17 +148,21 @@ export default {
     },
 
     async loadFormData() {
+      // 保持原有逻辑不变
       if (!this.zbId) return;
-
       try {
         this.loading = true;
         const response = await getSimEquipmentDeploymentBySimulation({
           schemeEquId: this.zbId,
           simulationId: this.planId
         });
-
         if (response.code === 0 && response.data) {
-          this.formData = {...this.formData, ...JSON.parse(response.data.modelConfig)};
+          const modelConfig = JSON.parse(response.data.modelConfig);
+          this.formData = {...this.formData, ...modelConfig};
+          if (modelConfig.ts !== undefined) {
+            this.tsMinutes = Math.floor(modelConfig.ts / 60);
+            this.tsSeconds = modelConfig.ts % 60;
+          }
         } else {
           this.$message.warning('未找到相关数据,将使用默认值');
         }
@@ -161,196 +174,155 @@ export default {
       }
     },
 
-    // --- 新增/修改方法:获取字段占位符 ---
     getFieldPlaceholder(field) {
       if (field.placeholder) return field.placeholder;
       if (field.dataType === 'time') return `请输入时间 (如 01:30:00 或 25:15:45)`;
       return `请输入${field.label}`;
     },
-    // --- 新增/修改方法结束 ---
 
     initFormRules(fields) {
       this.formRules = {};
       fields.forEach(field => {
-        // --- 新增逻辑:为 'time' 类型字段添加自定义验证 ---
-        if (field.dataType === 'time') {
-          this.formRules[field.prop] = [{
+        // 强化ts字段的非空验证规则
+        if (field.prop === 'ts') {
+          this.formRules['ts'] = [{
             validator: (rule, value, callback) => {
-              if (rule.required && (!value || value.trim() === '')) {
-                callback(new Error(rule.message || `请输入${field.label}`));
+              // 检查是否两个输入框都为空
+              if (this.tsMinutes === '' && this.tsSeconds === '') {
+                callback(new Error(`请至少输入分钟或秒数`));
+                return;
+              }
+
+              // 验证分钟数有效性
+              if (this.tsMinutes !== '' && (isNaN(Number(this.tsMinutes)) || Number(this.tsMinutes) < 0)) {
+                callback(new Error(`请输入有效的分钟数(非负整数)`));
                 return;
               }
-              if (value) {
-                // 定义允许小时数大于24的时间格式正则 (HH:mm:ss)
-                const timeRegex = /^([0-9]{1,3}):([0-5]?[0-9]):([0-5]?[0-9])$/;
-                const matches = value.match(timeRegex);
-                if (!matches) {
-                  callback(new Error(rule.message || `${field.label}格式不正确,请输入如 01:30:00 或 25:15:45`));
-                  return;
-                }
-                // 可以在这里添加更具体的范围检查,例如小时不超过999等
-                const hours = parseInt(matches[1], 10);
-                const minutes = parseInt(matches[2], 10);
-                const seconds = parseInt(matches[3], 10);
-
-                // 检查分钟和秒是否有效 (虽然正则已经限制了,但再检查一次更安全)
-                if (minutes > 59) {
-                  callback(new Error(`${field.label}分钟数不能大于59`));
-                  return;
-                }
-                if (seconds > 59) {
-                  callback(new Error(`${field.label}秒数不能大于59`));
-                  return;
-                }
-
-                // 例如,限制小时不超过999
-                if (hours > 999) {
-                  callback(new Error(`${field.label}小时数不能大于999`));
-                  return;
-                }
+
+              // 验证秒数有效性
+              if (this.tsSeconds !== '' && (isNaN(Number(this.tsSeconds)) || Number(this.tsSeconds) < 0 || Number(this.tsSeconds) > 59)) {
+                callback(new Error(`请输入有效的秒数(0-59)`));
+                return;
+              }
+
+              // 验证总时长不能为0
+              const totalSeconds = (this.tsMinutes === '' ? 0 : Number(this.tsMinutes)) * 60 +
+                  (this.tsSeconds === '' ? 0 : Number(this.tsSeconds));
+              if (totalSeconds <= 0) {
+                callback(new Error(`总时长必须大于0`));
+                return;
               }
+
               callback();
             },
-            trigger: 'blur' // 或 'change'
+            trigger: ['change', 'blur']  // 增加blur触发,提升用户体验
           }];
-          // 如果原始字段定义了其他规则,也可以合并
-          if (field.rules && field.rules.length > 0) {
-            this.formRules[field.prop] = [...this.formRules[field.prop], ...field.rules];
-          }
+        }
+        // 其他字段验证规则保持不变
+        else if (field.dataType === 'time') {
+          // ... 保持原有逻辑
         } else if (field.rules && field.rules.length) {
-          // --- 原有逻辑处理其他类型的规则 ---
-          this.formRules[field.prop] = field.rules.map(rule => {
-            const formattedRule = {...rule};
-
-            if (rule.min !== undefined || rule.max !== undefined) {
-              formattedRule.validator = (rule, value, callback) => {
-                const numValue = Number(value);
-
-                if (rule.required && (value === '' || value === null || value === undefined)) {
-                  callback(new Error(rule.message || `请输入${field.label}`));
-                  return;
-                }
-
-                if (value !== '' && value !== null && value !== undefined) {
-                  if (isNaN(numValue)) {
-                    callback(new Error(`请输入有效的${field.label}`));
-                    return;
-                  }
-
-                  if (rule.min !== undefined && numValue < rule.min) {
-                    callback(new Error(rule.message || `${field.label}不能小于${rule.min}`));
-                    return;
-                  }
-
-                  if (rule.max !== undefined && numValue > rule.max) {
-                    callback(new Error(rule.message || `${field.label}不能大于${rule.max}`));
-                    return;
-                  }
-                }
-
-                callback();
-              };
-            }
-
-            return formattedRule;
-          });
+          // ... 保持原有逻辑
         }
-        // --- 新增/修改逻辑结束 ---
       });
     },
 
+    getFieldProp(field) {
+      return field.prop === 'ts' ? 'ts' : field.prop;
+    },
+
     isFieldRequired(field) {
+      if (field.prop === 'ts') return true;  // 强制ts字段为必填
       if (!field.rules || !field.rules.length) return false;
       return field.rules.some(rule => rule.required);
     },
 
+    // 处理ts字段的分钟和秒变化
+    handleTsChange() {
+      // 确保值为有效数字
+      const minutes = this.tsMinutes === '' ? 0 : Number(this.tsMinutes);
+      const seconds = this.tsSeconds === '' ? 0 : Number(this.tsSeconds);
+
+      // 秒数边界处理
+      const validSeconds = seconds < 0 ? 0 : (seconds > 59 ? 59 : seconds);
+      if (validSeconds !== seconds) {
+        this.tsSeconds = validSeconds;
+      }
+
+      // 分钟数边界处理(确保非负)
+      const validMinutes = Math.max(0, minutes);
+      if (validMinutes !== minutes) {
+        this.tsMinutes = validMinutes;
+      }
+
+      // 计算总秒数并更新
+      this.formData.ts = validMinutes * 60 + validSeconds;
+      this.handleFieldChange('ts');
+    },
+
+    // 其他方法保持不变...
     getInputType(dataType) {
       switch (dataType) {
         case 'number':
         case 'decimal':
           return 'number';
-          // --- 修改:'time' 类型也使用 'text' 输入框 ---
         case 'time':
           return 'text';
-          // --- 修改结束 ---
         default:
           return 'text';
       }
     },
 
     shouldShowField(field) {
+      // 保持原有逻辑
       if (!field.showWhen || !Array.isArray(field.showWhen) || field.showWhen.length === 0) {
         return true;
       }
-
       return field.showWhen.every(condition => {
         const {field: conditionField, operator, value} = condition;
         const currentValue = this.formData[conditionField];
-
         switch (operator) {
-          case 'eq':
-            return currentValue === value;
-          case 'neq':
-            return currentValue !== value;
-          case 'gt':
-            return Number(currentValue) > Number(value);
-          case 'lt':
-            return Number(currentValue) < Number(value);
-          case 'gte':
-            return Number(currentValue) >= Number(value);
-          case 'lte':
-            return Number(currentValue) <= Number(value);
-          case 'in':
-            return Array.isArray(value) && value.includes(currentValue);
-          case 'nin':
-            return Array.isArray(value) && !value.includes(currentValue);
-          case 'has':
-            return typeof currentValue === 'string' && currentValue.includes(value);
-          default:
-            return true;
+          case 'eq': return currentValue === value;
+          case 'neq': return currentValue !== value;
+          case 'gt': return Number(currentValue) > Number(value);
+          case 'lt': return Number(currentValue) < Number(value);
+          case 'gte': return Number(currentValue) >= Number(value);
+          case 'lte': return Number(currentValue) <= Number(value);
+          case 'in': return Array.isArray(value) && value.includes(currentValue);
+          case 'nin': return Array.isArray(value) && !value.includes(currentValue);
+          case 'has': return typeof currentValue === 'string' && currentValue.includes(value);
+          default: return true;
         }
       });
     },
 
     handleFieldChange(fieldProp) {
+      // 保持原有逻辑
       let dependentFields = this.formFields.filter(
           field => field.showWhen && field.showWhen.some(cond => cond.field === fieldProp)
       );
-
       const selectFieldsWithDependentOptions = this.formFields.filter(field => {
         if (field.dataType !== 'select' || !field.options) return false;
         return field.options.some(option =>
             option.showWhen && option.showWhen.some(cond => cond.field === fieldProp)
         );
       });
-
       if (selectFieldsWithDependentOptions.length > 0) {
         selectFieldsWithDependentOptions.forEach(selectField => {
           this.$set(this.formData, selectField.prop, '');
-          console.log(`Reset select field '${selectField.prop}' value due to dependency change on '${fieldProp}'`);
         });
       }
-
       dependentFields = [...new Set([...dependentFields, ...selectFieldsWithDependentOptions])];
-      console.log(dependentFields)
-      if (dependentFields.length > 0) {
-        dependentFields.forEach(field => {
-          if (this.$refs.dynamicForm) {
-            this.$refs.dynamicForm.clearValidate(field.prop);
-          }
-        });
+      if (dependentFields.length > 0 && this.$refs.dynamicForm) {
+        dependentFields.forEach(field => this.$refs.dynamicForm.clearValidate(field.prop));
       }
     },
 
     show() {
       this.visible = true;
       this.$nextTick(() => {
-        if (this.$refs.dynamicForm) {
-          this.$refs.dynamicForm.clearValidate();
-        }
-        if (this.type === 'init') {
-          this.loadFormData();
-        }
+        if (this.$refs.dynamicForm) this.$refs.dynamicForm.clearValidate();
+        if (this.type === 'init') this.loadFormData();
       });
     },
 
@@ -367,7 +339,15 @@ export default {
     handleSubmit() {
       this.$refs.dynamicForm.validate(valid => {
         if (valid) {
-          this.$emit('submit', this.formData);
+          let behavior = null;
+          if (this.type === 'add') {
+            behavior = this.formFields.find(field => field.prop === 'behaviorName')?.options
+                ?.find(item => item.value === this.formData['behaviorName'])?.label;
+          }
+          if (this.formData.ts !== undefined) {
+            this.formData.ts = Number(this.formData.ts);
+          }
+          this.$emit('submit', this.formData, behavior);
           this.handleClose();
         } else {
           this.$message.warning('请完善表单信息');
@@ -382,6 +362,8 @@ export default {
         this.$refs.dynamicForm.clearValidate();
         this.formData = {};
         this.formRules = {};
+        this.tsMinutes = '';
+        this.tsSeconds = '';
       }
     }
   }
@@ -397,16 +379,34 @@ export default {
   margin-bottom: 15px;
 }
 
-.loading-mask {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  background: rgba(255, 255, 255, 0.7);
+.ts-input-group {
   display: flex;
-  align-items: center;
-  justify-content: center;
-  z-index: 1000;
+  gap: 8px;
+  align-items: center; /* 垂直居中对齐输入框和文字 */
+}
+
+/* 增强必填项视觉提示 */
+::v-deep .el-form-item.is-required .el-form-item__label::before {
+  content: '*';
+  color: #ff4d4f;
+  margin-right: 4px;
+}
+
+/* 隐藏数字输入框的默认箭头 */
+::v-deep input::-webkit-inner-spin-button,
+::v-deep input::-webkit-outer-spin-button {
+  -webkit-appearance: none;
+  appearance: none;
+  margin: 0;
+}
+
+:v-deep input[type="number"] {
+  -moz-appearance: textfield;
+}
+
+/* 错误状态样式增强 */
+::v-deep .el-form-item.is-error .el-input__inner {
+  border-color: #ff4d4f;
 }
 </style>
+

+ 69 - 14
src/views/Deduction/taskSetting/components/equipment/EquipmentListWithTimeline.vue

@@ -55,8 +55,13 @@
               :type="getTimelineType(e.typeClass)"
               placement="top"
           >
-            <el-card :shadow="false" class="ui-card soft tl-card">
-              <div class="tl-title">{{ e.title }}</div>
+            <el-card shadow="never" class="ui-card soft tl-card">
+              <div class="tl-title">
+                <div>{{ e.title }}</div>
+                <div>
+                  <el-button v-if="e.time !== '0'" @click="deleteTs(e)" type="danger" icon="el-icon-delete" circle></el-button>
+                </div>
+              </div>
               <div class="tl-desc">
                 {{ e.desc }}
                 <el-tag :type="getTagType(e.badgeClass)" class="m-l-6" size="mini">
@@ -86,7 +91,13 @@
 </template>
 
 <script>
-import {getModelData, getSubPlanZbTsList, getSubPlanZbZbList, subPlanZbZbSaveData} from "@/api/subPlanZb";
+import {
+  deleteSubPlanZbTsList,
+  getModelData,
+  getSubPlanZbTsList,
+  getSubPlanZbZbList,
+  subPlanZbZbSaveData
+} from "@/api/subPlanZb";
 import DynamicFormModal from './DynamicFormModal.vue';
 
 export default {
@@ -133,10 +144,11 @@ export default {
       this.tsList.forEach(t => {
         if (!t.ts) return;
         list.push({
-          time: `T0+${t.ts}`,
+          id:t.id,
+          time: `T0+${this.formatSeconds(t.seconds)}`,
           rawTime: t.ts,
-          title: t.ts === '00:00:00' ? '装备准备' : '装备激活',
-          desc: `${t.zbName} ${t.ts === '00:00:00' ? '准备' : '激活'}`,
+          title: t.ts === '00:00:00' ? '初始化' : t.behavior,
+          desc: `${t.zbName}`,
           zbType: t.zbType,
           typeClass: t.type === '动态' ? 'tl-danger' : 'tl-warn',
           badgeClass: t.statusText === '可用'
@@ -162,11 +174,50 @@ export default {
     this.fetchTsList()
   },
   methods: {
+    formatSeconds(seconds) {
+      // 确保输入是有效的数字,并取整数部分
+      const totalSeconds = Math.max(0, Math.floor(seconds)); // 处理负数或无效输入
+
+      const minutes = Math.floor(totalSeconds / 60);
+      const secs = totalSeconds % 60;
+
+      // 使用 padStart 确保秒数始终显示为两位数 (e.g., 05, 09, 12)
+      const paddedSeconds = String(secs).padStart(2, '0');
+
+      // 返回
+      return `${minutes}分${paddedSeconds}秒`;
+    },
     fetchTsList() {
       getSubPlanZbTsList({simulationId: this.planId}).then((res) => {
         this.tsList = res.data
       })
     },
+    deleteTs(e) {
+      // 使用 Element UI 的 $confirm 方法显示确认弹窗
+      this.$confirm(`确定要删除 "${e.name || e.title || '该项'}" 吗?`, '删除确认', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning' // 设置弹窗类型为警告
+      }).then(() => {
+        // 用户点击了“确定”
+        deleteSubPlanZbTsList({ id: e.id }).then((res) => {
+          if (res.code === 0) {
+            this.$message.success('删除成功');
+            // 刷新列表
+            this.fetchTsList()
+          } else {
+            // 处理删除失败的情况
+            this.$message.error(res.msg || '删除失败');
+          }
+        }).catch((err) => {
+          // 处理请求异常
+          console.error('删除请求出错:', err);
+        });
+      }).catch(() => {
+        // 用户点击了“取消”或关闭了弹窗
+        this.$message.info('已取消删除');
+      });
+    },
     fetchZbList() {
       let zbType = null;
       if (this.typeKey === 'target') zbType = 1
@@ -179,11 +230,11 @@ export default {
     init(row) {
       this.selectRow = row
       this.selectType = 'init'
-      getModelData({id: row.id}).then(res => {
+      getModelData({id: row.id,isInit:0}).then(res => {
         console.log(res.data)
         if (res.code === 0 && res.data) {
           console.log(res.data)
-          this.formFields = res.data.modelConfigForm.filter(item => item.prop !== 'ts' && item.type === "STATIC");
+          this.formFields = res.data.modelConfigForm.filter(item => item.prop !== 'ts');
           this.$refs.myFormModal.show();
         } else {
           this.$message.error('获取表单配置失败');
@@ -195,10 +246,10 @@ export default {
     addTiming(row) {
       this.selectRow = row
       this.selectType = 'add'
-      getModelData({id: row.id}).then(res => {
+      getModelData({id: row.id,isInit:1}).then(res => {
         if (res.code === 0 && res.data ) {
           // 筛选出动态类型的字段
-          let dynamicFields = res.data.interactionConfigForm.filter(item => item.prop !== 'ts' && item.type === "DYNAMIC");
+          let dynamicFields = res.data.interactionConfigForm.filter(item => item.prop !== 'ts');
 
           // 创建时序时间字段 - 使用时间选择器
           const timingField = {
@@ -232,12 +283,12 @@ export default {
       });
     },
     // 处理表单提交
-    handleFormSubmit(formData) {
+    handleFormSubmit(formData,behavior) {
       console.log('表单提交数据:', formData);
       let submitTs = ''
       if (this.selectType === 'init') {
         submitTs = '00:00:00'
-        subPlanZbZbSaveData({id: this.selectRow.id, simulationId: this.planId,ts:submitTs, params: formData}).then((res) => {
+        subPlanZbZbSaveData({id: this.selectRow.id, isInit:0, simulationId: this.planId,ts:submitTs, params: formData}).then((res) => {
           if (res.code === 0) {
             this.fetchTsList()
             this.$message.success('配置已保存');
@@ -245,7 +296,8 @@ export default {
         })
       } else {
         submitTs = formData.ts
-        subPlanZbZbSaveData({id: this.selectRow.id, simulationId: this.planId,ts:submitTs, interactionConfigData: formData}).then((res) => {
+
+        subPlanZbZbSaveData({id: this.selectRow.id,isInit:1, simulationId: this.planId,ts:submitTs,behavior:behavior, interactionConfigData: formData}).then((res) => {
           if (res.code === 0) {
             this.fetchTsList()
             this.$message.success('配置已保存');
@@ -359,6 +411,9 @@ export default {
 }
 
 .tl-title {
+  display: flex;
+  width: 100%;
+  justify-content: space-between;
   font-weight: 800;
   color: #EAF2FF;
   margin-bottom: 4px;
@@ -366,7 +421,7 @@ export default {
 }
 
 .tl-desc {
-  font-size: 12px;
+  font-size: 14px;
   color: var(--text-2);
 }
 

+ 67 - 414
src/views/Deduction/taskSetting/dedOrderEdit.vue

@@ -141,7 +141,7 @@
           <!-- Step 1 装备配置 -->
           <template v-if="step===1">
             <div class="flex w-full justify-center">
-              <el-card class="ui-card fill-card" style="width:80%;justify-content:center" shadow="hover">
+              <el-card class="ui-card fill-card" style="width:100%;margin-bottom:20px;justify-content:center" shadow="never">
                 <div slot="header" class="card-header">
                   <div class="title-left">
                     <i class="fa fa-cogs icon-primary"></i><span>装备配置</span>
@@ -193,7 +193,7 @@
           <!-- Step 3 环境设置(保留) -->
           <template v-if="step===3">
             <el-main class="main-full">
-              <el-card class="ui-card fill-card" shadow="hover">
+              <el-card class="ui-card fill-card" shadow="never">
                 <div slot="header" class="card-header">
                   <div class="title-left">
                     <i class="fa fa-cloud icon-primary"></i><span>战场环境规划</span>
@@ -237,7 +237,7 @@
           <!-- Step 4 想定预览 -->
           <template v-if="step===4">
             <el-main class="main-full">
-              <el-card class="ui-card fill-card" shadow="hover">
+              <el-card class="ui-card fill-card" shadow="never">
                 <div slot="header" class="card-header">
                   <div class="title-left">
                     <i class="fa fa-file-text icon-primary"></i><span>想定预览(版本:{{ scenarioVersion }})</span>
@@ -272,52 +272,71 @@
                   <el-card body-style="padding:16px;" class="ui-card panel-card mb-16" shadow="never">
                     <div class="sub-title"><i class="el-icon-tickets"></i> 装备信息总览</div>
                     <el-row :gutter="12">
-                      <el-col :span="8" v-if="equTree.find(item=>item.name==='靶标方案')">
+                      <el-col :span="24" v-if="equTree.find(item=>item.name==='靶标方案')">
                         <el-card body-style="padding:10px;" class="ui-card soft" shadow="never">
                           <div class="module-title"><i class="el-icon-location-information"></i>
                             靶标装备({{ equTree.find(item=>item.name==='靶标方案').equList.length }})
                           </div>
                           <el-table :data="equTree.find(item=>item.name==='靶标方案').equList" border height="220" size="mini">
-                            <el-table-column label="名称" min-width="120" prop="name"/>
-                            <el-table-column label="类型" prop="type" width="70"/>
-                            <el-table-column label="状态" width="90">
+                            <el-table-column label="装备名称" min-width="120" prop="name"/>
+                            <el-table-column label="装备类型" prop="typeName"/>
+                            <el-table-column label="是否有准确位置" prop="isExactLocation">
                               <template slot-scope="scope">
-                                <el-tag
-                                    :type="scope.row.statusClass==='badge-success'?'success':(scope.row.statusClass==='badge-warn'?'warning':'info')"
-                                    size="mini">
-                                  {{ scope.row.statusText }}
-                                </el-tag>
+                                <el-tag v-if="scope.row.isExactLocation === '0'" type="success">是</el-tag>
+                                <el-tag v-if="scope.row.isExactLocation === '1'" type="warning">否</el-tag>
+                              </template>
+                            </el-table-column>
+                            <el-table-column label="位置" prop="positionDescription">
+                              <template slot-scope="scope">
+                                <div v-if="scope.row.isExactLocation === '0'" >{{ scope.row.equipPositionX }},{{ scope.row.equipPositionY }}</div>
+                                <div v-if="scope.row.isExactLocation === '1'" >{{ scope.row.positionDescription }}</div>
                               </template>
                             </el-table-column>
-                            <el-table-column label="激活" prop="time" width="90"/>
                           </el-table>
                         </el-card>
                       </el-col>
 
-                      <el-col :span="8" v-if="equTree.find(item=>item.name==='干扰方案')">
+                      <el-col :span="24" v-if="equTree.find(item=>item.name==='干扰方案')">
                         <el-card body-style="padding:10px;" class="ui-card soft" shadow="never">
                           <div class="module-title"><i class="el-icon-microphone"></i> 干扰装备({{ equTree.find(item=>item.name==='干扰方案').equList.length }})
                           </div>
                           <el-table :data="equTree.find(item=>item.name==='干扰方案').equList" border height="220" size="mini">
-                            <el-table-column label="名称" min-width="120" prop="name"/>
-                            <el-table-column label="类型" prop="type" width="70"/>
-                            <el-table-column label="频率(MHz)" width="100">
-                              <template slot-scope="scope">{{ scope.row.params && scope.row.params.freq }}</template>
+                            <el-table-column label="装备名称" min-width="120" prop="name"/>
+                            <el-table-column label="装备类型" prop="typeName"/>
+                            <el-table-column label="是否有准确位置" prop="isExactLocation">
+                              <template slot-scope="scope">
+                                <el-tag v-if="scope.row.isExactLocation === '0'" type="success">是</el-tag>
+                                <el-tag v-if="scope.row.isExactLocation === '1'" type="warning">否</el-tag>
+                              </template>
+                            </el-table-column>
+                            <el-table-column label="位置" prop="positionDescription">
+                              <template slot-scope="scope">
+                                <div v-if="scope.row.isExactLocation === '0'" >{{ scope.row.equipPositionX }},{{ scope.row.equipPositionY }}</div>
+                                <div v-if="scope.row.isExactLocation === '1'" >{{ scope.row.positionDescription }}</div>
+                              </template>
                             </el-table-column>
                           </el-table>
                         </el-card>
                       </el-col>
 
-                      <el-col :span="8" v-if="equTree.find(item=>item.name==='测量方案')">
+                      <el-col :span="24" v-if="equTree.find(item=>item.name==='测量方案')">
                         <el-card body-style="padding:10px;" class="ui-card soft" shadow="never">
                           <div class="module-title"><i class="el-icon-view"></i> 测量装备({{ equTree.find(item=>item.name==='测量方案').equList.length }})
                           </div>
                           <el-table :data="equTree.find(item=>item.name==='测量方案').equList" border height="220" size="mini">
-                            <el-table-column label="名称" min-width="120" prop="name"/>
-                            <el-table-column label="类型" prop="type" width="70"/>
-                            <el-table-column label="启动" prop="time" width="90"/>
-                            <el-table-column label="范围(km)" width="90">
-                              <template slot-scope="scope">{{ scope.row.params && scope.row.params.range }}</template>
+                            <el-table-column label="装备名称" min-width="120" prop="name"/>
+                            <el-table-column label="装备类型" prop="typeName"/>
+                            <el-table-column label="是否有准确位置" prop="isExactLocation">
+                              <template slot-scope="scope">
+                                <el-tag v-if="scope.row.isExactLocation === '0'" type="success">是</el-tag>
+                                <el-tag v-if="scope.row.isExactLocation === '1'" type="warning">否</el-tag>
+                              </template>
+                            </el-table-column>
+                            <el-table-column label="位置" prop="positionDescription">
+                              <template slot-scope="scope">
+                                <div v-if="scope.row.isExactLocation === '0'" >{{ scope.row.equipPositionX }},{{ scope.row.equipPositionY }}</div>
+                                <div v-if="scope.row.isExactLocation === '1'" >{{ scope.row.positionDescription }}</div>
+                              </template>
                             </el-table-column>
                           </el-table>
                         </el-card>
@@ -353,367 +372,6 @@
         </div>
       </el-container>
     </template>
-    <!-- 新增/编辑:靶标 -->
-    <el-dialog :close-on-click-modal="false" :title="editModeTarget ? '编辑靶标' : '添加靶标'"
-               :visible.sync="addTargetDialog" width="900px">
-      <el-form ref="targetFormRef" :model="newTargetForm" :rules="targetRules" class="dense-form" label-width="110px"
-               size="small">
-        <el-row :gutter="16">
-          <el-col :span="12">
-            <el-form-item label="靶标名称" prop="name">
-              <el-input v-model="newTargetForm.name" placeholder="请输入"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="靶标类型" prop="type">
-              <el-select v-model="newTargetForm.type" style="width:100%" @change="onTargetTypeChange">
-                <el-option label="静态" value="静态"/>
-                <el-option label="动态" value="动态"/>
-              </el-select>
-            </el-form-item>
-          </el-col>
-
-          <template v-if="newTargetForm.type==='静态'">
-            <el-col :span="12">
-              <el-form-item label="固定点位来源">
-                <el-switch v-model="newTargetForm.fixedFromPlan" active-text="使用方案固定点位"
-                           inactive-text="手动/地图选点"/>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item label="状态" prop="statusText">
-                <el-select v-model="newTargetForm.statusText" style="width:100%">
-                  <el-option label="可用" value="可用"/>
-                  <el-option label="维护中" value="维护中"/>
-                  <el-option label="停用" value="停用"/>
-                </el-select>
-              </el-form-item>
-            </el-col>
-          </template>
-
-          <el-col :span="12">
-            <el-form-item :prop="newTargetForm.fixedFromPlan ? '' : 'lon'" label="经度">
-              <el-input v-model="newTargetForm.lon" placeholder="116.320000"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item :prop="newTargetForm.fixedFromPlan ? '' : 'lat'" label="纬度">
-              <el-input v-model="newTargetForm.lat" placeholder="39.950000"/>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="12">
-            <el-form-item label="激活时间" prop="time">
-              <el-time-picker v-model="newTargetForm.time" format="HH:mm:ss" placeholder="选择时间"
-                              style="width:100%;" value-format="HH:mm:ss"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12"></el-col>
-
-          <template v-if="newTargetForm.type==='动态'">
-            <el-col :span="12">
-              <el-form-item label="运动模式">
-                <el-select v-model="targetForm.motion">
-                  <el-option label="直线" value="linear"/>
-                  <el-option label="圆周" value="circular"/>
-                  <el-option label="随机" value="random"/>
-                  <el-option label="自定义" value="custom"/>
-                </el-select>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item label="速度(km/h)">
-                <el-input v-model.number="targetForm.speed" :min="0" step="0.1" type="number"/>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item label="持续时间(s)">
-                <el-input v-model.number="targetForm.duration" :min="1" type="number"/>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item label="工作模式">
-                <el-select v-model="targetForm.mode">
-                  <el-option label="正常" value="normal"/>
-                  <el-option label="模拟" value="simulated"/>
-                  <el-option label="增强" value="enhanced"/>
-                </el-select>
-              </el-form-item>
-            </el-col>
-          </template>
-
-          <el-col v-if="!newTargetForm.fixedFromPlan" :span="24">
-            <!-- 地图选点 -->
-            <el-form-item label="地图选点">
-              <div class="map-container">
-                <div class="map-placeholder" @click.stop="selectMapPosition">
-                  <img alt="map" class="map-image" src="/img/banner.jpg"/>
-                  <div
-                      v-if="mapMarkerPosition"
-                      class="map-marker"
-                      :style="{left: mapMarkerPosition.x + 'px', top: mapMarkerPosition.y + 'px'}"
-                  >
-                    <i class="el-icon-location icon-marker"></i>
-                  </div>
-                </div>
-                <p class="map-hint">点击地图可快速带出经纬度</p>
-              </div>
-            </el-form-item>
-
-          </el-col>
-        </el-row>
-      </el-form>
-      <div slot="footer">
-        <el-button @click="addTargetDialog=false">取消</el-button>
-        <el-button type="primary" @click="confirmAddTarget">{{ editModeTarget ? '保存' : '确认添加' }}</el-button>
-      </div>
-    </el-dialog>
-
-    <!-- 新增/编辑:干扰 -->
-    <el-dialog :close-on-click-modal="false" :title="editModeJammer ? '编辑干扰装备' : '添加干扰装备'"
-               :visible.sync="addJammerDialog" size="40%">
-      <el-form ref="jammerFormRef" :model="newJammerForm" :rules="jammerRules" class="dense-form" label-width="110px"
-               size="small">
-        <el-row :gutter="16">
-          <el-col :span="12">
-            <el-form-item label="装备名称" prop="name">
-              <el-input v-model="newJammerForm.name"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="装备类型" prop="type">
-              <el-select v-model="newJammerForm.type" style="width:100%">
-                <el-option label="电磁" value="电磁"/>
-                <el-option label="雷达" value="雷达"/>
-              </el-select>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="12">
-            <el-form-item label="经度" prop="lon">
-              <el-input v-model="newJammerForm.lon"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="纬度" prop="lat">
-              <el-input v-model="newJammerForm.lat"/>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="12">
-            <el-form-item label="干扰频率(MHz)">
-              <el-input v-model.number="jammerForm.freq" type="number"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="干扰功率(W)">
-              <el-input v-model.number="jammerForm.power" type="number"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="持续时间(s)">
-              <el-input v-model.number="jammerForm.duration" :min="1" type="number"/>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="24">
-            <div class="subsection-header">
-              <span>激活计划</span>
-              <el-button icon="el-icon-plus" size="mini" type="primary" @click="addJammerSchedule">新增计划</el-button>
-            </div>
-            <el-table :data="newJammerForm.schedules" border size="small">
-              <el-table-column label="激活时间" width="140">
-                <template slot-scope="scope">
-                  <el-time-picker v-model="scope.row.time" format="HH:mm:ss" placeholder="HH:mm:ss" size="mini"
-                                  value-format="HH:mm:ss"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="触发类型" width="150">
-                <template slot-scope="scope">
-                  <el-select v-model="scope.row.triggerType" size="mini" style="width:140px;">
-                    <el-option label="导弹接近" value="导弹接近"/>
-                    <el-option label="雷达信号异常" value="雷达信号异常"/>
-                    <el-option label="目标激活" value="目标激活"/>
-                    <el-option label="手动触发" value="手动触发"/>
-                  </el-select>
-                </template>
-              </el-table-column>
-              <el-table-column label="阈值参数" width="140">
-                <template slot-scope="scope">
-                  <el-input v-model="scope.row.threshold" placeholder="如:距离<5km" size="mini"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="触发动作" width="160">
-                <template slot-scope="scope">
-                  <el-select v-model="scope.row.action" size="mini" style="width:150px;">
-                    <el-option label="立即启动干扰" value="立即启动干扰"/>
-                    <el-option label="进入准备状态" value="进入准备状态"/>
-                    <el-option label="发出警报" value="发出警报"/>
-                    <el-option label="执行预设序列" value="执行预设序列"/>
-                  </el-select>
-                </template>
-              </el-table-column>
-              <el-table-column label="说明">
-                <template slot-scope="scope">
-                  <el-input v-model="scope.row.triggerDesc" placeholder="补充说明(可选)" size="mini"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="延迟(s)" width="100">
-                <template slot-scope="scope">
-                  <el-input v-model.number="scope.row.delaySec" :min="0" size="mini" type="number"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="操作" width="90">
-                <template slot-scope="scope">
-                  <el-button class="danger-btn" size="mini" type="text" @click="removeJammerSchedule(scope.$index)">
-                    删除
-                  </el-button>
-                </template>
-              </el-table-column>
-            </el-table>
-          </el-col>
-        </el-row>
-      </el-form>
-      <div slot="footer">
-        <el-button @click="addJammerDialog=false">取消</el-button>
-        <el-button type="primary" @click="confirmAddJammer">{{ editModeJammer ? '保存' : '确认添加' }}</el-button>
-      </div>
-    </el-dialog>
-
-    <!-- 新增/编辑:测量 -->
-    <el-dialog :close-on-click-modal="false" :title="editModeMeasurement ? '编辑测量装备' : '添加测量装备'"
-               :visible.sync="addMeasurementDialog" size="40%">
-      <el-form ref="measureFormRef" :model="newMeasurementForm" :rules="measureRules" class="dense-form"
-               label-width="110px"
-               size="small">
-        <el-row :gutter="16">
-          <el-col :span="12">
-            <el-form-item label="装备名称" prop="name">
-              <el-input v-model="newMeasurementForm.name"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="装备类型" prop="type">
-              <el-select v-model="newMeasurementForm.type" style="width:100%">
-                <el-option label="雷达" value="雷达"/>
-                <el-option label="光学" value="光学"/>
-              </el-select>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="12">
-            <el-form-item label="经度" prop="lon">
-              <el-input v-model="newMeasurementForm.lon"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="纬度" prop="lat">
-              <el-input v-model="newMeasurementForm.lat"/>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="12">
-            <el-form-item label="启动时间" prop="time">
-              <el-time-picker v-model="newMeasurementForm.time" format="HH:mm:ss" placeholder="选择时间"
-                              style="width:100%;" value-format="HH:mm:ss"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12"></el-col>
-
-          <el-col :span="12">
-            <el-form-item label="测量范围(km)">
-              <el-input v-model.number="measureForm.range" type="number"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="测量精度(m)">
-              <el-input v-model.number="measureForm.precision" :min="0.1" step="0.1" type="number"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="俯仰角(°)">
-              <el-input v-model.number="measureForm.deg" type="number"/>
-            </el-form-item>
-          </el-col>
-          <el-col :spn="12">
-            <el-form-item label="离地高度(m)">
-              <el-input v-model.number="measureForm.height" type="number"/>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="24">
-            <el-form-item label="相对位置备注">
-              <el-input v-model="newMeasurementForm.posNote" placeholder="如:指挥所东南角 200m 高度20m"/>
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="24">
-            <div class="subsection-header">
-              <span>激活计划</span>
-              <el-button icon="el-icon-plus" size="mini" type="primary" @click="addMeasurementSchedule">新增计划
-              </el-button>
-            </div>
-            <el-table :data="newMeasurementForm.schedules" border size="small">
-              <el-table-column label="激活时间" width="140">
-                <template slot-scope="scope">
-                  <el-time-picker v-model="scope.row.time" format="HH:mm:ss" placeholder="HH:mm:ss" size="mini"
-                                  value-format="HH:mm:ss"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="触发类型" width="150">
-                <template slot-scope="scope">
-                  <el-select v-model="scope.row.triggerType" size="mini" style="width:140px;">
-                    <el-option label="导弹接近" value="导弹接近"/>
-                    <el-option label="雷达信号异常" value="雷达信号异常"/>
-                    <el-option label="目标激活" value="目标激活"/>
-                    <el-option label="手动触发" value="手动触发"/>
-                  </el-select>
-                </template>
-              </el-table-column>
-              <el-table-column label="阈值参数" width="140">
-                <template slot-scope="scope">
-                  <el-input v-model="scope.row.threshold" placeholder="如:距离<5km" size="mini"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="触发动作" width="160">
-                <template slot-scope="scope">
-                  <el-select v-model="scope.row.action" size="mini" style="width:150px;">
-                    <el-option label="立即启动干扰" value="立即启动干扰"/>
-                    <el-option label="进入准备状态" value="进入准备状态"/>
-                    <el-option label="发出警报" value="发出警报"/>
-                    <el-option label="执行预设序列" value="执行预设序列"/>
-                  </el-select>
-                </template>
-              </el-table-column>
-              <el-table-column label="说明">
-                <template slot-scope="scope">
-                  <el-input v-model="scope.row.triggerDesc" placeholder="补充说明(可选)" size="mini"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="延迟(s)" width="100">
-                <template slot-scope="scope">
-                  <el-input v-model.number="scope.row.delaySec" :min="0" size="mini" type="number"/>
-                </template>
-              </el-table-column>
-              <el-table-column label="操作" width="90">
-                <template slot-scope="scope">
-                  <el-button class="danger-btn" size="mini" type="text"
-                             @click="removeMeasurementSchedule(scope.$index)">删除
-                  </el-button>
-                </template>
-              </el-table-column>
-            </el-table>
-          </el-col>
-        </el-row>
-      </el-form>
-      <div slot="footer">
-        <el-button @click="addMeasurementDialog=false">取消</el-button>
-        <el-button type="primary" @click="confirmAddMeasurement">{{
-            editModeMeasurement ? '保存' : '确认添加'
-          }}
-        </el-button>
-      </div>
-    </el-dialog>
 
     <dd-upload ref="uploadDd" />
   </div>
@@ -843,27 +501,6 @@ export default {
 
       mapMarkerPosition: null,
 
-      targetRules: {
-        name: [{required: true, message: '填写名称', trigger: 'blur'}],
-        type: [{required: true, message: '选择类型', trigger: 'change'}],
-        lon: [{required: true, message: '填写经度', trigger: 'blur'}],
-        lat: [{required: true, message: '填写纬度', trigger: 'blur'}],
-        time: [{required: true, message: '选择时间', trigger: 'change'}]
-      },
-      jammerRules: {
-        name: [{required: true, message: '填写名称', trigger: 'blur'}],
-        type: [{required: true, message: '选择类型', trigger: 'change'}],
-        lon: [{required: true, message: '填写经度', trigger: 'blur'}],
-        lat: [{required: true, message: '填写纬度', trigger: 'blur'}]
-      },
-      measureRules: {
-        name: [{required: true, message: '填写名称', trigger: 'blur'}],
-        type: [{required: true, message: '选择类型', trigger: 'change'}],
-        lon: [{required: true, message: '填写经度', trigger: 'blur'}],
-        lat: [{required: true, message: '填写纬度', trigger: 'blur'}],
-        time: [{required: true, message: '选择时间', trigger: 'change'}]
-      },
-
       leftWidth: '58%',
       rightWidth: '42%',
 
@@ -881,16 +518,13 @@ export default {
       this.tsList.forEach(t => {
         if (!t.ts) return;
         list.push({
-          time: `T0+${t.ts}`,
+          id:t.id,
+          time: `T0+${this.formatSeconds(t.seconds)}`,
           name: t.zbName,
-          rawTime: t.ts,
-          title: t.ts === '00:00:00' ? '装备准备' : '装备激活',
-          desc: `${t.zbName} ${t.ts === '00:00:00' ? '准备' : '激活'}`,
+          rawTime: this.formatSeconds(t.seconds),
+          title: t.seconds === '0' ? '初始化' : t.behavior,
+          desc: `${t.zbName}`,
           zbType: this.$getDictNameByValue('zb_type', t.zbType),
-          typeClass: t.type === '动态' ? 'tl-danger' : 'tl-warn',
-          badgeClass: t.statusText === '可用'
-              ? 'badge-success'
-              : (t.statusText === '维护中' ? 'badge-warn' : 'badge-accent'),
         });
       });
 
@@ -941,6 +575,23 @@ export default {
     })
   },
   methods: {
+    formatSeconds(seconds) {
+      // 确保输入是有效的数字,并取整数部分
+      const totalSeconds = Math.max(0, Math.floor(seconds)); // 处理负数或无效输入
+
+      // 计算小时、分钟和秒
+      const hours = Math.floor(totalSeconds / 3600);
+      const minutes = Math.floor((totalSeconds % 3600) / 60);
+      const secs = totalSeconds % 60;
+
+      // 使用 padStart 确保分钟和秒始终显示为两位数 (e.g., 05, 09, 12)
+      const paddedMinutes = String(minutes).padStart(2, '0');
+      const paddedSeconds = String(secs).padStart(2, '0');
+
+      // 返回格式: "Hhmmss" 或 "HH:mm:ss"
+      // 这里采用更标准的 HH:mm:ss 格式
+      return `${hours}:${paddedMinutes}:${paddedSeconds}`;
+    },
     fetchTsList() {
       getSubPlanZbTsList({simulationId: this.plan.id}).then((res) => {
         this.tsList = res.data
@@ -1421,6 +1072,8 @@ html, body, #app, .page {
 
 /* ===== 布局与滚动 ===== */
 .workspace {
+  width: 80%;
+  margin: auto;
   height: calc(100% - var(--header-h) - var(--footer-h));
 }
 

+ 1 - 1
src/views/Deduction/taskSetting/index.vue

@@ -626,7 +626,7 @@ export default {
         this.selectedSubTask = task;
         this.selectedTreeNode = null;
 
-        getListVer({}).then((res) => {
+        getListVer({subTaskId:task.id}).then((res) => {
           this.schemeTable = res.data;
           // 确保表格数据更新后重新渲染
           this.$nextTick(() => {

+ 1 - 1
src/views/Deduction/taskSetting/processcontrol.vue

@@ -570,7 +570,7 @@ export default {
         this.selectedSubTask = task;
         this.selectedTreeNode = null;
 
-        getListVer({}).then((res) => {
+        getListVer({subTaskId:task.id}).then((res) => {
           this.schemeTable = res.data;
           // 确保表格数据更新后重新渲染
           this.$nextTick(() => {

+ 1 - 1
src/views/decision/testBuild/index.vue

@@ -720,7 +720,7 @@ export default {
         this.selectedSubTask = task;
         this.selectedTreeNode = null;
 
-        getListVer({}).then((res) => {
+        getListVer({subTaskId:task.id}).then((res) => {
           this.schemeTable = res.data;
           // 确保表格数据更新后重新渲染
           this.$nextTick(() => {

+ 16 - 5
src/views/planningSchem/comprehensive/components/semiPlanCreate.vue

@@ -340,13 +340,13 @@
           <el-col :span="12">
             <el-form-item label="是否精确位置" prop="isExactLocation">
               <el-radio-group v-model="addForm.isExactLocation" @change="locationChange">
-                <el-radio-button :label="0">非精确位置</el-radio-button>
-                <el-radio-button :label="1">精确位置</el-radio-button>
+                <el-radio-button :label="1">非精确位置</el-radio-button>
+                <el-radio-button :label="0">精确位置</el-radio-button>
               </el-radio-group>
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row :gutter="20" v-if="addForm.isExactLocation === 1">
+        <el-row :gutter="20" v-if="addForm.isExactLocation === 0">
           <el-col :span="12">
             <el-form-item label="X坐标" prop="equipPositionX">
               <el-input v-model="addForm.equipPositionX" placeholder="请输入X坐标"/>
@@ -358,7 +358,7 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row :gutter="20" v-if="addForm.isExactLocation === 0">
+        <el-row :gutter="20" v-if="addForm.isExactLocation === 1">
           <el-col :span="24">
             <el-form-item label="位置描述" prop="positionDescription">
               <el-input type="textarea" :rows="4" v-model="addForm.positionDescription" placeholder="请输入位置描述"/>
@@ -375,7 +375,7 @@
       </el-form>
 
       <div slot="footer" class="dialog-footer">
-        <el-button @click="addOrUpdateVisible = false">取 消</el-button>
+        <el-button @click="cancelSubmit">取 消</el-button>
         <el-button type="primary" @click="handleAddSubmit">确 定</el-button>
       </div>
     </el-dialog>
@@ -622,6 +622,17 @@ export default {
       }
       this.addOrUpdateVisible = true
     },
+    cancelSubmit(){
+      this.addForm = {
+        zbName: '',
+        isExactLocation: 0,
+        equipPositionX: '',
+        equipPositionY: '',
+        positionDescription: '',
+        taskRemark: '',
+      }
+      this.addOrUpdateVisible = false
+    },
     // 添加装备确认按钮
     handleAddSubmit() {
       console.log(this.addForm)