sd
2025-07-28 84f19ab0d37599400959e85e63cfda5df4869bc8
src/pages/cameraAccess/components/SceneRule.vue
@@ -1,34 +1,19 @@
<template>
  <div class="scene-edit-container">
    <div class="scene-title">
      <b style="font-size: 14px; line-height: 18px">场景</b>
      <el-button
        type="primary"
        size="mini"
        @click="handleCreate"
        style="margin-left: 90%"
        v-show="!editScene && TreeDataPool.selectedNode.type !== 'MENU'"
        >+ 添加场景</el-button
      >
      <b style="font-size: 14px; line-height: 18px">督查任务</b>
      <el-button type="primary" size="mini" @click="handleCreate" style="margin-left: 90%"
        v-show="!editScene && TreeDataPool.selectedNode.type !== 'MENU'">+ 添加任务</el-button>
    </div>
    <el-form ref="form" label-width="80px" v-show="editScene">
      <div class="flex-form">
        <div class="left">
          <el-form-item label="场景名称">
            <el-input
              v-model="sceneForm.scene_name"
              size="mini"
              maxlength="15"
            ></el-input>
          <el-form-item label="任务名称">
            <el-input v-model="sceneForm.scene_name" size="mini" maxlength="15"></el-input>
          </el-form-item>
          <el-form-item label="事件等级">
            <el-select
              v-model="sceneForm.alarm_level"
              placeholder="请选择"
              size="mini"
              style="width: 250px"
            >
            <el-select v-model="sceneForm.alarm_level" placeholder="请选择" size="mini" style="width: 250px">
              <el-option label="一级" :value="1"></el-option>
              <el-option label="二级" :value="2"></el-option>
              <el-option label="三级" :value="3"></el-option>
@@ -37,29 +22,38 @@
            </el-select>
          </el-form-item>
          <el-form-item label="时间段">
            <el-select
              v-model="sceneForm.time_rule_id"
              placeholder="请选择"
              size="mini"
            >
              <el-option
                v-for="item in VideoManageData.TimeRules"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              ></el-option>
            <el-select v-model="sceneForm.workTimeId" placeholder="请选择" size="mini">
              <el-option v-for="item in VideoManageData.TimeRules" :key="item.id" :label="item.name"
                :value="item.id"></el-option>
            </el-select>
          </el-form-item>
          <!-- 检测内容 -->
          <el-form-item label="检测内容">
            <el-select v-model="sceneForm.checkContents" multiple placeholder="请选择" size="mini">
              <el-option v-for="item in VideoManageData.checkOptions" :key="item.checkId" :label="item.fileName"
                :value="item.checkId"></el-option>
            </el-select>
          </el-form-item>
        </div>
        <div class="right">
          <el-form-item label="场景描述">
            <el-input
              v-model="sceneForm.desc"
              type="textarea"
              size="mini"
            ></el-input>
          <el-form-item label="任务描述">
            <el-input v-model="sceneForm.desc" type="textarea" size="mini"></el-input>
          </el-form-item>
          <el-form-item label="事件声音">
          <!-- 预警规则 -->
          <el-form-item label="预警规则">
            <el-select v-model="sceneForm.warningRules" placeholder="请选择" size="mini" multiple>
              <el-option v-for="item in VideoManageData.ruleOptions" :key="item.ruleId" :label="item.fileName"
                :value="item.ruleId"></el-option>
            </el-select>
          </el-form-item>
          <!-- 知识库 -->
          <el-form-item label="知识库" size="mini">
            <el-cascader v-model="sceneForm.knowsList" :options="VideoManageData.knowsList" :props="knowledgeProps"
              clearable filterable placeholder="请选择" class="knowledge-cascader" :show-all-levels="false"></el-cascader>
          </el-form-item>
          <!-- <el-form-item label="事件声音">
            <el-select
              v-model="sceneForm.voice"
              placeholder="空"
@@ -90,48 +84,38 @@
                style="font-size: 26px; vertical-align: middle; color: #409eff"
              ></i>
            </span>
          </el-form-item>
          </el-form-item> -->
        </div>
      </div>
      <scene-editor
      <!-- <scene-editor
        ref="sceneEditor"
        :isLinkRule="linkRule"
        :Cameras="seletedCameras"
        :ruleList="templateRules"
        @sdkNameChange="getSceneName"
      ></scene-editor>
      ></scene-editor> -->
      <el-form-item style="width: 60%; min-width: 1048px">
        <el-button size="mini" @click="editScene = false">取消</el-button>
        <el-button type="primary" size="mini" @click="saveSceneRule"
          >保存</el-button
        >
        <el-button type="primary" size="mini" @click="saveSceneRule">保存</el-button>
      </el-form-item>
    </el-form>
    <!-- 规则列表 -->
    <div class="edit-rule-table" v-show="!editScene">
      <div class="task-rules-table-box">
        <el-table
          :data="tableRuleList"
          border
          style="width: 100%"
          :cell-style="cellStyle"
          :header-cell-style="{ background: '#f8f8f8', color: '#222222' }"
        >
          <el-table-column
            label="序号"
            type="index"
            align="center"
          ></el-table-column>
          <el-table-column
            label="场景名称"
            prop="scene_name"
            align="center"
            show-overflow-tooltip
          ></el-table-column>
          <el-table-column
        <el-table :data="tableRuleList" border style="width: 100%" :cell-style="cellStyle"
          :header-cell-style="{ background: '#f8f8f8', color: '#222222' }">
          <el-table-column label="序号" type="index" align="center"></el-table-column>
          <el-table-column label="任务名称" prop="scene_name" align="center" show-overflow-tooltip></el-table-column>
          <el-table-column label="事件等级" align="center">
            <template slot-scope="scope">
              <span>{{ scope.row.alarm_level | alarmLevel }}</span>
            </template>
          </el-table-column>
          <!-- <el-table-column
            label="策略"
            prop="group_text"
            align="center"
@@ -140,58 +124,49 @@
            <template slot-scope="scope">
              <span v-html="scope.row.group_text"></span>
            </template>
          </el-table-column>workTimeId -->
          <el-table-column label="时间段" prop="time_name" align="center">
            <template slot-scope="scope">
              <!-- {{(scope.row.workingTime || []).map(r => r.labelName).join(' / ') || ''}} -->
              <span v-for="(tag, idx) in VideoManageData.TimeRules.filter(t => t.id === scope.row.workTimeId)"
                :key="idx">
                {{ tag.name }}</span>
            </template>
          </el-table-column>
          <el-table-column
            label="时间段"
            prop="time_name"
            align="center"
          ></el-table-column>
          <el-table-column
            label="描述"
            prop="desc"
            align="center"
            min-width="120"
          ></el-table-column>
          <el-table-column label="检测内容" prop="checkContent" align="center">
            <template slot-scope="scope">
              {{(scope.row.checkContent || []).map(r => r.fileName).join(' / ') || ''}}
            </template>
          </el-table-column>
          <el-table-column label="预警规则" prop="warningRule" align="center">
            <template slot-scope="scope">
              {{(scope.row.warningRule || []).map(r => r.fileName).join(' / ') || ''}}
            </template>
          </el-table-column>
          <el-table-column label="知识库" prop="knowledge" align="center">
            <template slot-scope="scope">
              {{(scope.row.knowledge || []).map(r => r.fileName).join(' / ') || ''}}
            </template>
          </el-table-column>
          <el-table-column label="描述" prop="desc" align="center" min-width="120"></el-table-column>
          <!-- <el-table-column label="状态" align="center" width="90">
            <template slot-scope="scope">
              <el-switch v-model="scope.row.defence_state" @change="updateDefence(scope.row)"></el-switch>
            </template>
          </el-table-column>-->
          <el-table-column label="事件声音" align="center">
          <!-- <el-table-column label="事件声音" align="center">
            <template slot-scope="scope">
              <span>{{ getSoundById(scope.row.voiceId) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="事件等级" align="center">
            <template slot-scope="scope">
              <span>{{ scope.row.alarm_level | alarmLevel }}</span>
            </template>
          </el-table-column>
          </el-table-column> -->
          <el-table-column label="操作" fixed="right" align="center">
            <template slot-scope="scope">
              <el-tooltip
                content="编辑"
                :hide-after="700"
                placement="top"
                popper-class="atooltip"
              >
                <i
                  class="iconfont iconbianji1 btn-icon"
                  style="font-size: 28px"
                  @click="handleEdit(scope.row)"
                ></i>
              <el-tooltip content="编辑" :hide-after="700" placement="top" popper-class="atooltip">
                <i class="iconfont iconbianji1 btn-icon" style="font-size: 28px" @click="handleEdit(scope.row)"></i>
              </el-tooltip>
              <el-tooltip
                content="删除"
                :hide-after="700"
                placement="top"
                popper-class="atooltipgroup_"
              >
                <i
                  class="iconfont iconshanchu4 btn-icon"
                  style="font-size: 28px; color: red"
                  @click="handleDelScene(scope.row)"
                ></i>
              <el-tooltip content="删除" :hide-after="700" placement="top" popper-class="atooltipgroup_">
                <i class="iconfont iconshanchu4 btn-icon" style="font-size: 28px; color: red"
                  @click="handleDelScene(scope.row)"></i>
              </el-tooltip>
            </template>
          </el-table-column>
@@ -202,10 +177,11 @@
</template>
<script>
import { saveCameraScene, deleteCameraScene } from "@/api/scene";
import { saveCameraScene, deleteCameraScene, deleteCameraSceneTwo } from "@/api/scene";
import RuleEditor from "@/components/subComponents/RuleEditor";
import SceneEditor from "./scene/Editor";
import { getSoundList } from "@/api/event";
import { forEach } from "jszip";
export default {
  name: "SceneRuleEditor",
@@ -264,6 +240,12 @@
  },
  data() {
    return {
      knowledgeProps: {
        multiple: true, // 支持多选
        value: 'id',    // 指定选项值字段
        label: 'title', // 指定选项标签字段
        children: 'files' // 指定子选项字段(文件列表)
      },
      editScene: false,
      sceneTemplates: [],
      sceneForm: {
@@ -420,6 +402,17 @@
    },
    handleEdit(scene) {
      this.sceneForm = JSON.parse(JSON.stringify(scene));
      // 修正知识库文件转换逻辑
      if (scene.knowledge) {
        const convertKnowledge = scene.knowledge.map(file => {
          const library = this.VideoManageData.knowsList.find(lib =>
            lib.files.some(f => f.id === file.id)
          )
          return library ? [library.id, file.id] : null
        }).filter(item => item !== null) || []
        this.sceneForm.knowsList = convertKnowledge
        // console.info("know:" + JSON.stringify(convertKnowledge))
      }
      // this.originSceneInfo = JSON.parse(JSON.stringify(scene));
      this.sceneForm.voice = this.soundList.find((o) => o.id === scene.voiceId);
@@ -433,14 +426,14 @@
      this.templateSdks = selectedTpl.sdks;
      this.templateRules = JSON.stringify(scene.rules);
      this.$refs.sceneEditor.editHandle(this.templateRules);
      // this.$refs.sceneEditor.editHandle(this.templateRules);//算法相关
    },
    validateForm() {
      if (!this.sceneForm.scene_name.trim()) {
        this.$notify({
          type: "warning",
          message: "场景名不能为空",
          message: "任务名不能为空",
        });
        return false;
      } else if (!this.sceneForm.alarm_level) {
@@ -449,40 +442,89 @@
          message: "事件等级不能为空",
        });
        return false;
      } else if (!this.sceneForm.time_rule_id) {
      } else if (!this.sceneForm.workTimeId) {
        this.$notify({
          type: "warning",
          message: "时间段不能为空",
        });
        return false;
      } else if (!this.sceneForm.checkContents) {
        this.$notify({
          type: "warning",
          message: "检测内容不能为空",
        });
        return false;
      } else if (!this.sceneForm.warningRules) {
        this.$notify({
          type: "warning",
          message: "预警规则不能为空",
        });
        return false;
      }
      //  else if (!this.sceneForm.knowsList) {
      //   this.$notify({
      //     type: "warning",
      //     message: "知识库不能为空",
      //   });
      //   return false;
      // }
      return true;
    },
    saveSceneRule() {
      if (!this.validateForm()) {
        return;
      }
      let editorResp = this.$refs.sceneEditor.submitRule();
      if (!editorResp) {
        return;
      // let editorResp = this.$refs.sceneEditor.submitRule();
      // if (!editorResp) {
      //   return;
      // }
      // this.sceneForm.rules = editorResp.rules;
      // this.sceneForm.id = editorResp.id;
      // this.sceneForm.group_text = editorResp.text;
      // const workTimes = [this.sceneForm.workingTimes].map(id => {
      //   const timeOption = this.VideoManageData.TimeRules.find(opt => opt.id === id)
      //   return {
      //     labelId: id,
      //     labelName: timeOption ? timeOption.name : ''
      //   }
      // })
      let fileIds = []
      if (this.sceneForm.knowsList) {
        fileIds = this.sceneForm.knowsList.map(
          path => {
            // 提取最后一级的文件ID并转换为数字
            const id = path[path.length - 1];
            return Number(id); // 或者使用 parseInt(id) 或 +id
          }
        )
      }
      this.sceneForm.rules = editorResp.rules;
      this.sceneForm.id = editorResp.id;
      this.sceneForm.group_text = editorResp.text;
      this.onSaveScene(this.sceneForm);
      this.sceneForm.taskName = this.sceneForm.scene_name
      this.sceneForm.eventLevel = this.sceneForm.alarm_level
      this.sceneForm.checks = this.sceneForm.checkContents
      this.sceneForm.rules = this.sceneForm.warningRules
      // this.sceneForm.workTimes = workTimes
      this.sceneForm.taskDescription = this.sceneForm.desc
      this.sceneForm.knows = fileIds,
        this.onSaveScene(this.sceneForm);
    },
    handleDelScene(groupRule) {
      let _this = this;
      this.$confirm("提示:删除后,该条规则将失效,是否删除?", {
      this.$confirm("提示:删除后,该条任务将失效,是否删除?", {
        center: true,
        cancelButtonClass: "comfirm-class-cancle",
        confirmButtonClass: "comfirm-class-sure",
      })
        .then(() => {
          deleteCameraScene(groupRule.id).then((res) => {
          // console.info("groupRule:"+JSON.stringify(groupRule))
          deleteCameraSceneTwo(
            {
              taskId: groupRule.taskId
            }
          ).then((res) => {
            this.$emit("delete-rule");
            if (res && res.success) {
            if (res && res.status === 200) {
              // console.info("删除成功")
              this.$notify({
                type: "success",
                message: "删除成功",
@@ -496,7 +538,7 @@
            }
          });
        })
        .catch(() => {});
        .catch(() => { });
    },
    cellStyle(obj) {
      if (obj.column.label == "策略" || obj.column.label == "事件声音") {
@@ -514,44 +556,55 @@
    text-align: left;
    margin: 10px 0px;
  }
  .flex-form {
    display: flex;
    width: 80%;
    padding-left: 25px;
    .left,
    .right {
      width: 43.3%;
      min-width: 550px;
      .el-form-item {
        margin-bottom: 16px;
      }
      .el-form-item__label {
        text-align: left;
      }
      .el-form-item__content {
        text-align: left;
        .el-input,
        .el-select {
          width: 400px !important;
        }
      }
      textarea {
        height: 92px;
      }
    }
    .right {
      padding-top: 6px;
    }
  }
  .edit-rule-table {
    .task-rules-table-box {
      width: 98%;
      padding: 0px;
      box-sizing: border-box;
    }
    .el-form-item {
      width: calc(100% - 30px);
    }
    .el-input__inner {
      border: 0px !important;
      border-radius: 2px;
@@ -562,17 +615,21 @@
    .el-input__suffix {
      right: 8px;
    }
    span {
      cursor: pointer;
    }
    .cell {
      padding-left: 0 !important;
      i {
        outline: none !important;
      }
    }
  }
  .el-table th.el-table__cell > .cell {
  .el-table th.el-table__cell>.cell {
    padding-right: 0;
  }
}