Эх сурвалжийг харах

数据显示隐藏 / 自定义初始化参数部分 / 销毁修改对话框内容

Rmengdi 2 сар өмнө
parent
commit
e93b0be14b

+ 399 - 90
uavps-web/src/views/uavps/parameter/index.vue

@@ -188,7 +188,7 @@
         label="操作"
         align="center"
         class-name="small-padding fixed-width"
-        width="150"
+        width="200"
       >
         <template slot-scope="scope">
           <el-button
@@ -210,11 +210,19 @@
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-s-operation"
+            icon="el-icon-video-play"
             @click="handleRun(scope.row)"
             v-hasPermi="['uavps:parameter:run']"
             >运行</el-button
           >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handlePlayback(scope.row)"
+            v-hasPermi="['uavps:parameter:run']"
+            >回放</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
@@ -228,51 +236,145 @@
     />
 
     <!-- 添加或修改算法参数信息对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
-        <el-form-item label="目标ID" prop="targetId">
-          <el-input v-model="form.targetId" placeholder="请输入目标ID" />
-        </el-form-item>
-        <el-form-item label="目标集群类型" prop="formationType">
-          <el-select
-            v-model="form.formationType"
-            placeholder="请选择目标集群类型"
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="75%"
+      :close-on-click-modal="false"
+      append-to-body
+      destroy-on-close
+      :before-close="cancel"
+    >
+      <el-form
+        ref="form"
+        :inline="true"
+        :model="form"
+        :rules="rules"
+        label-width="110px"
+      >
+        <el-row>
+          <el-form-item label="目标ID" prop="targetId">
+            <el-input v-model="form.targetId" placeholder="请输入目标ID" />
+          </el-form-item>
+          <el-form-item label="目标集群类型" prop="formationType">
+            <el-select
+              v-model="form.formationType"
+              placeholder="请选择目标集群类型"
+            >
+              <el-option
+                v-for="dict in dict.type.uavps_target_formation_type"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="编队类型">
+            <el-select
+              v-model="formationType"
+              @change="typeChange"
+              placeholder="请选择"
+              :disabled="!form.formationType"
+            >
+              <el-option
+                v-for="item in formationTypeList"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </el-row>
+        <div v-show="formationType == '1'">
+          <el-form-item label="经度" prop="longitude">
+            <el-input v-model="form.longitude" placeholder="请输入经度" />
+          </el-form-item>
+          <el-form-item label="纬度" prop="latitude">
+            <el-input v-model="form.latitude" placeholder="请输入纬度" />
+          </el-form-item>
+          <el-form-item label="海拔" prop="altitude">
+            <el-input v-model="form.altitude" placeholder="请输入海拔" />
+          </el-form-item>
+          <el-form-item label="东向速度" prop="eastSpeed">
+            <el-input v-model="form.eastSpeed" placeholder="请输入东向速度" />
+          </el-form-item>
+          <el-form-item label="北向速度" prop="northSpeed">
+            <el-input v-model="form.northSpeed" placeholder="请输入北向速度" />
+          </el-form-item>
+          <el-form-item label="天向速度" prop="skySpeed">
+            <el-input v-model="form.skySpeed" placeholder="请输入天向速度" />
+          </el-form-item>
+          <el-form-item label="UTC时间" prop="utcTimes">
+            <el-input v-model="form.utcTimes" placeholder="请输入UTC时间" />
+          </el-form-item>
+          <el-form-item label="本次目标总数" prop="targetTotal">
+            <el-input
+              v-model="form.targetTotal"
+              placeholder="请输入本次目标总数"
+            />
+          </el-form-item>
+        </div>
+        <div v-show="formationType == '2'" style="width: 100%">
+          <div style="width: 100%">
+            <el-form
+              ref="canvasInfoFormRef"
+              :inline="true"
+              :model="canvasInfo"
+              :rules="infoRules"
+              class="demo-form-inline"
+              :disabled="submitInfoFlag"
+            >
+              <el-form-item label="中心点-经度" prop="centerLongitude">
+                <el-input
+                  v-model="canvasInfo.centerLongitude"
+                  placeholder="中心点-经度"
+                ></el-input>
+              </el-form-item>
+              <el-form-item label="中心点-纬度" prop="centerLatitude">
+                <el-input
+                  v-model="canvasInfo.centerLatitude"
+                  placeholder="中心点-纬度"
+                ></el-input>
+              </el-form-item>
+              <el-form-item label="长距离" prop="longSideDistance">
+                <el-input
+                  v-model="canvasInfo.longSideDistance"
+                  placeholder="长距离"
+                >
+                  <template slot="append">km</template>
+                </el-input>
+              </el-form-item>
+              <el-form-item label="宽距离" prop="wideSideDistance">
+                <el-input
+                  v-model="canvasInfo.wideSideDistance"
+                  placeholder="宽距离"
+                >
+                  <template slot="append">km</template>
+                </el-input>
+              </el-form-item>
+              <el-form-item>
+                <el-button type="primary" @click="canvasInfoSubmit"
+                  >确 定</el-button
+                >
+              </el-form-item>
+            </el-form>
+          </div>
+          <div
+            style="
+              width: 100%;
+              height: 600px;
+              display: flex;
+              justify-content: space-between;
+            "
           >
-            <el-option
-              v-for="dict in dict.type.uavps_target_formation_type"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="经度" prop="longitude">
-          <el-input v-model="form.longitude" placeholder="请输入经度" />
-        </el-form-item>
-        <el-form-item label="纬度" prop="latitude">
-          <el-input v-model="form.latitude" placeholder="请输入纬度" />
-        </el-form-item>
-        <el-form-item label="海拔" prop="altitude">
-          <el-input v-model="form.altitude" placeholder="请输入海拔" />
-        </el-form-item>
-        <el-form-item label="东向速度" prop="eastSpeed">
-          <el-input v-model="form.eastSpeed" placeholder="请输入东向速度" />
-        </el-form-item>
-        <el-form-item label="北向速度" prop="northSpeed">
-          <el-input v-model="form.northSpeed" placeholder="请输入北向速度" />
-        </el-form-item>
-        <el-form-item label="天向速度" prop="skySpeed">
-          <el-input v-model="form.skySpeed" placeholder="请输入天向速度" />
-        </el-form-item>
-        <el-form-item label="UTC时间" prop="utcTimes">
-          <el-input v-model="form.utcTimes" placeholder="请输入UTC时间" />
-        </el-form-item>
-        <el-form-item label="本次目标总数" prop="targetTotal">
-          <el-input
-            v-model="form.targetTotal"
-            placeholder="请输入本次目标总数"
-          />
-        </el-form-item>
+            <div ref="pixiCanvas" class="left" style="width: 80%"></div>
+            <div
+              class="right"
+              style="width: 19%; background-color: aquamarine"
+            ></div>
+          </div>
+        </div>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
@@ -281,27 +383,34 @@
     </el-dialog>
 
     <!-- 飞行轨迹展示对话框 -->
-    <!-- @closed="destroyTrajectory" -->
     <el-dialog
       :title="title"
       :visible.sync="showTrajectory"
       @opened="initTrajectory"
-      :before-close="destroyTrajectory"
+      :before-close="closeDialog"
       :fullscreen="true"
       append-to-body
       destroy-on-close
+      :close-on-click-modal="false"
     >
       <div class="container">
         <div>
           <el-row type="flex" align="middle" style="height: 40px">
-            <el-col :span="7">
-              <el-button @click="transFormation" type="danger"
+            <el-col :span="20">
+              <el-button
+                v-if="!isUpdateView"
+                @click="transFormation"
+                type="danger"
                 >转换队形</el-button
               >
-              <el-button @click="" type="success">回放</el-button>
-            </el-col>
-            <el-col :span="17">
-              <!--              <el-progress v-show="isShow" :percentage="percentage"></el-progress>-->
+              <el-progress
+                style="margin: 0 auto"
+                :text-inside="true"
+                :stroke-width="26"
+                v-if="isUpdateView"
+                :percentage="percentage"
+              ></el-progress>
+              <!-- <el-button @click="handlePlayback" type="success">回放</el-button> -->
             </el-col>
           </el-row>
           <el-row>
@@ -312,34 +421,60 @@
           <div style="float: right">
             <el-link type="primary" @click="showConfig">显示配置</el-link>
           </div>
+          <div>
+            <el-divider content-position="left">隐藏列表</el-divider>
+            <div style="margin-left: 10px" v-if="hideList.length !== 0">
+              <el-tag
+                v-for="item in hideList"
+                @click="showSprite(item)"
+                style="cursor: pointer; margin-left: 5px"
+                >{{ item }}</el-tag
+              >
+            </div>
+            <div style="margin-left: 10px" v-else>暂无</div>
+          </div>
           <el-divider content-position="left">目标无人机群</el-divider>
           <li v-for="(item, index) in targetLblAry" :key="index">
-            <div @click="showSprite(item.id)" style="cursor: pointer">
-              <span>编号:&nbsp;&nbsp;</span><label>{{ item.showNo }}</label>
-              <span style="margin-left: 10px" v-if="hideList.includes(item.id)"
+            <div
+              v-if="!hideList.includes(item.id)"
+              @click="showSprite(item.id)"
+              style="cursor: pointer"
+            >
+              <div>
+                <span>编号:&nbsp;&nbsp;</span><label>{{ item.showNo }}</label>
+                <!-- <span style="margin-left: 10px" v-if="hideList.includes(item.id)"
                 >( 隐 藏 )</span
-              >
-            </div>
-            <div v-if="configList.includes('经度')">
-              <span>经度:&nbsp;&nbsp;</span><label>{{ item.longitude }}</label>
+              > -->
+              </div>
+              <div v-if="configList.includes('经度')">
+                <span>经度:&nbsp;&nbsp;</span
+                ><label>{{ item.longitude }}</label>
+              </div>
+              <div v-if="configList.includes('纬度')">
+                <span>纬度:&nbsp;&nbsp;</span
+                ><label>{{ item.latitude }}</label>
+              </div>
+              <div v-if="configList.includes('海拔')">
+                <span>海拔:&nbsp;&nbsp;</span
+                ><label>{{ item.altitude }}</label>
+              </div>
+              <div v-if="configList.includes('东向速度')">
+                <span>东向速度:&nbsp;&nbsp;</span
+                ><label>{{ item.eastSpeed }}</label>
+              </div>
+              <div v-if="configList.includes('北向速度')">
+                <span>北向速度:&nbsp;&nbsp;</span
+                ><label>{{ item.northSpeed }}</label>
+              </div>
+              <div v-if="configList.includes('天向速度')">
+                <span>天向速度:&nbsp;&nbsp;</span
+                ><label>{{ item.skySpeed }}</label>
+              </div>
             </div>
-            <div v-if="configList.includes('纬度')">
-              <span>纬度:&nbsp;&nbsp;</span><label>{{ item.latitude }}</label>
-            </div>
-            <div v-if="configList.includes('海拔')">
-              <span>海拔:&nbsp;&nbsp;</span><label>{{ item.altitude }}</label>
-            </div>
-            <div v-if="configList.includes('东向速度')">
-              <span>东向速度:&nbsp;&nbsp;</span
-              ><label>{{ item.eastSpeed }}</label>
-            </div>
-            <div v-if="configList.includes('北向速度')">
-              <span>北向速度:&nbsp;&nbsp;</span
-              ><label>{{ item.northSpeed }}</label>
-            </div>
-            <div v-if="configList.includes('天向速度')">
-              <span>天向速度:&nbsp;&nbsp;</span
-              ><label>{{ item.skySpeed }}</label>
+            <div v-else>
+              <el-tag @click="showSprite(item.id)" style="cursor: pointer"
+                >隐藏</el-tag
+              >
             </div>
           </li>
         </div>
@@ -347,7 +482,12 @@
     </el-dialog>
 
     <!-- 显示配置对话框 -->
-    <el-dialog title="显示配置" :visible.sync="showConfigVisible" width="30%">
+    <el-dialog
+      title="显示配置"
+      :close-on-click-modal="false"
+      :visible.sync="showConfigVisible"
+      width="30%"
+    >
       <el-checkbox-group
         v-model="showConfigList"
         style="display: flex; flex-direction: column"
@@ -453,6 +593,20 @@ export default {
           { required: true, message: "本次目标总数不能为空", trigger: "blur" },
         ],
       },
+      infoRules: {
+        centerLongitude: [
+          { required: true, message: "经度不能为空", trigger: "blur" },
+        ],
+        centerLatitude: [
+          { required: true, message: "纬度不能为空", trigger: "blur" },
+        ],
+        longSideDistance: [
+          { required: true, message: "长距离不能为空", trigger: "blur" },
+        ],
+        wideSideDistance: [
+          { required: true, message: "宽距离不能为空", trigger: "blur" },
+        ],
+      },
       // 是否显示轨迹
       showTrajectory: false,
       pixiApp: null,
@@ -493,6 +647,30 @@ export default {
       // 多久更新一次轨迹
       updatePathFlag: 125,
       cycleCount: 0, // 循环计数
+      isUpdateView: false, // 是否开启实现追踪,在回放时开启
+      percentage: 50,
+      formationTypeList: [
+        {
+          value: "1",
+          label: "固定编队",
+        },
+        {
+          value: "2",
+          label: "自由编队",
+        },
+      ],
+      formationType: "1",
+      // 编辑编队信息的
+      formationAirPiXiApp: null,
+      // 设定的画布信息
+      canvasInfo: {
+        centerLongitude: null,
+        centerLatitude: null,
+        longSideDistance: null,
+        wideSideDistance: null,
+      },
+      // 是否提交了编队信息
+      submitInfoFlag: false,
     };
   },
   created() {
@@ -512,6 +690,7 @@ export default {
     cancel() {
       this.open = false;
       this.reset();
+      this.closeUpdataDialog();
     },
     // 表单重置
     reset() {
@@ -605,6 +784,86 @@ export default {
       this.showTrajectory = true;
       this.title = "飞行轨迹";
     },
+
+    handlePlayback(row) {
+      this.parameterId = row.id || this.ids;
+      this.showTrajectory = true;
+      this.isUpdateView = true;
+      this.title = "回放";
+    },
+
+    // 选择编队类型
+    typeChange(val) {
+      if (val == "2") {
+        this.$nextTick(() => {
+          this.$message.warning(`请先输入画布信息!`);
+          this.initFormationApp();
+        });
+      }
+    },
+
+    // 确定编队信息
+    canvasInfoSubmit() {
+      this.$refs["canvasInfoFormRef"].validate((valid) => {
+        if (valid) {
+          this.submitInfoFlag = true;
+          this.addAirSprite();
+        }
+      });
+    },
+
+    // 初始化编队的画布
+    initFormationApp() {
+      const pixiCanvas = this.$refs.pixiCanvas;
+      if (!pixiCanvas) return;
+      // 创建Pixi应用
+      this.formationAirPiXiApp = new PIXI.Application({
+        width: pixiCanvas.clientWidth,
+        height: pixiCanvas.clientHeight,
+        antialias: true,
+        transparent: false,
+        resolution: 1,
+        backgroundAlpha: 0,
+      });
+      this.formationAirPiXiApp.renderer.backgroundColor = 0x1099bb;
+      pixiCanvas.appendChild(this.formationAirPiXiApp.view);
+    },
+
+    // 增加飞机编队
+    addAirSprite() {
+      // 判断是哪个机型
+      let texture;
+      if (this.form && this.form.formationType == "1") {
+        texture = new PIXI.Texture.from("../../textures/uav-tar.png");
+      } else if (this.form && this.form.formationType == "2") {
+        // 旋翼机型
+      }
+      // 创建飞机
+      const airSprite = new PIXI.Sprite(texture);
+      airSprite.anchor.set(0.5, 0.5);
+      airSprite.scale.set(0.04);
+      airSprite.position.set(
+        this.formationAirPiXiApp.screen.width / 2,
+        this.formationAirPiXiApp.screen.height / 2
+      );
+      this.formationAirPiXiApp.stage.addChild(airSprite);
+      this.formationAirPiXiApp.stage.eventMode = "static";
+      this.formationAirPiXiApp.stage.hitArea = this.formationAirPiXiApp.screen;
+      this.formationAirPiXiApp.view.addEventListener("pointermove", (e) => {
+        airSprite.x = e.offsetX;
+        airSprite.y = e.offsetY;
+      });
+      this.formationAirPiXiApp.view.addEventListener("dblclick", (e) => {
+        // 创建新精灵
+        const newSprite = new PIXI.Sprite(texture);
+        newSprite.anchor.set(0.5, 0.5);
+        newSprite.scale.set(0.04);
+        newSprite.x = e.offsetX;
+        newSprite.y = e.offsetY;
+        this.formationAirPiXiApp.stage.addChild(newSprite);
+      });
+    },
+
     /** 导出按钮操作 */
     handleExport() {
       this.download(
@@ -785,20 +1044,35 @@ export default {
           text.y = cy;
 
           if (data.targetAircraft[0].aircrafts[i].piloted) {
-            // console.log(
-            //   "coordinateX",
-            //   data.targetAircraft[0].aircrafts[i].coordinateX
-            // );
-            // console.log(
-            //   "coordinateY",
-            //   data.targetAircraft[0].aircrafts[i].coordinateY
-            // );
             const point = { x: targetUav.x, y: targetUav.y };
-            // console.log("point", point);
             this.targetUavPath.push(point);
             this.curLongitude = data.targetAircraft[0].aircrafts[i].longitude;
             this.curLatitude = data.targetAircraft[0].aircrafts[i].latitude;
             this.curAltitude = data.targetAircraft[0].aircrafts[i].altitude;
+
+            const viewSprite = this.pixiApp.stage.children.find((item) => {
+              return (
+                item.id == data.targetAircraft[0].aircrafts[i].aircraftNumber
+              );
+            });
+            if (this.isUpdateView) {
+              // 获取精灵的边界
+              const spriteBounds = viewSprite.getBounds();
+              // 检测是否移出画布
+              if (spriteBounds.left < 0) {
+                // 触碰到了左边界
+                this.pixiApp.stage.x += this.container.clientWidth / 2;
+              } else if (spriteBounds.right > this.container.clientWidth) {
+                // 触碰到了右边
+                this.pixiApp.stage.x -= this.container.clientWidth / 2;
+              } else if (spriteBounds.top < 0) {
+                // 触碰到了上边
+                this.pixiApp.stage.y += this.container.clientHeight / 2;
+              } else if (spriteBounds.bottom > this.container.clientHeight) {
+                // 触碰到了下边
+                this.pixiApp.stage.y -= this.container.clientHeight / 2;
+              }
+            }
           }
         }
       }
@@ -931,6 +1205,7 @@ export default {
       //   });
       // }
     },
+
     // 更新位置
     updatePosition() {
       this.pixiApp.ticker.add(() => {
@@ -971,8 +1246,6 @@ export default {
       this.pixiApp.stage.interactive = true;
       // 拖曳状态变量
       let dragging = false;
-      let offsetX = 0;
-      let offsetY = 0;
 
       let lastPosition = null; // 上一次鼠标的位置
       // 鼠标按下事件
@@ -1052,7 +1325,43 @@ export default {
       }
 
       this.clearAllAry();
+    },
+    closeDialog() {
+      this.destroyTrajectory();
       this.showTrajectory = false;
+      this.isUpdateView = false;
+    },
+    closeUpdataDialog() {
+      this.destroyTormationInfo();
+      this.canvasInfo = {
+        centerLongitude: null,
+        centerLatitude: null,
+        longSideDistance: null,
+        wideSideDistance: null,
+      };
+      this.submitInfoFlag = false;
+      this.formationAirPiXiApp = null;
+      this.formationType = "1";
+      this.reset();
+    },
+    destroyTormationInfo() {
+      if (this.formationAirPiXiApp) {
+        const removedChildren = this.formationAirPiXiApp.stage.removeChildren(
+          0,
+          this.formationAirPiXiApp.stage.children.length
+        );
+        removedChildren.forEach((child) => {
+          child.destroy({
+            children: true,
+            texture: false,
+            baseTexture: false,
+          });
+        });
+        this.formationAirPiXiApp.stage.removeChildren();
+        this.formationAirPiXiApp.renderer.clear();
+        this.formationAirPiXiApp.destroy(true);
+        this.formationAirPiXiApp = null;
+      }
     },
     transFormation() {
       // debugger;