Просмотр исходного кода

init: 删除不必要的代码

louhangfei 1 год назад
Родитель
Сommit
cc7e57b88b
100 измененных файлов с 0 добавлено и 16786 удалено
  1. 0 16
      package.json
  2. 0 89
      src/views/about/index.vue
  3. 0 199
      src/views/alarm-push/PushAlarm.vue
  4. 0 144
      src/views/alarm-push/component/AddRobot.vue
  5. 0 42
      src/views/alarm-push/constant.ts
  6. 0 62
      src/views/alarm-push/usePush.ts
  7. 0 117
      src/views/cameras/algo-management/algoManagement.vue
  8. 0 388
      src/views/cameras/algo-management/components/AlgoParamEdit.vue
  9. 0 40
      src/views/cameras/algo-management/useAlgoData.ts
  10. 0 37
      src/views/cameras/algo-params-setting/AlgoParamsSetting.vue
  11. 0 41
      src/views/cameras/camera-group-setting/CamerGroupSetting.vue
  12. 0 65
      src/views/cameras/camera-group-setting/components/CameraTreeList.vue
  13. 0 246
      src/views/cameras/nvrlist/NvrList.vue
  14. 0 260
      src/views/cameras/nvrlist/components/CreateDrawer.vue
  15. 0 56
      src/views/cameras/nvrlist/constant.ts
  16. 0 39
      src/views/cameras/nvrlist/overviewColumns.ts
  17. 0 603
      src/views/cameras/overview/CamerasOverview.vue
  18. 0 222
      src/views/cameras/overview/components/AddCameraByIP.vue
  19. 0 211
      src/views/cameras/overview/components/AddCameraByNVR.vue
  20. 0 285
      src/views/cameras/overview/components/AddCameraByRange.vue
  21. 0 208
      src/views/cameras/overview/components/AddCameraBySRS.vue
  22. 0 272
      src/views/cameras/overview/components/BatchEditCamera.vue
  23. 0 333
      src/views/cameras/overview/components/BatchImportCamera.vue
  24. 0 147
      src/views/cameras/overview/components/CameraAddPopover.vue
  25. 0 122
      src/views/cameras/overview/components/CameraEditNVRPopover.vue
  26. 0 125
      src/views/cameras/overview/components/CameraEditPopover.vue
  27. 0 144
      src/views/cameras/overview/components/CameraEditSRSPopover.vue
  28. 0 85
      src/views/cameras/overview/components/CameraEditshared.vue
  29. 0 382
      src/views/cameras/overview/components/CameraOverviewPopover.vue
  30. 0 103
      src/views/cameras/overview/components/CameraSharePopover.vue
  31. 0 109
      src/views/cameras/overview/components/CameraSharedEdit.vue
  32. 0 141
      src/views/cameras/overview/components/ConditionQuery.vue
  33. 0 137
      src/views/cameras/overview/components/EditSharedCamera.vue
  34. 0 61
      src/views/cameras/overview/components/SearchCamerasAction.vue
  35. 0 297
      src/views/cameras/overview/components/ShareCameraDetail.vue
  36. 0 226
      src/views/cameras/overview/components/SharedTable.vue
  37. 0 114
      src/views/cameras/overview/components/sysConfigItemOfAddCamera.vue
  38. 0 166
      src/views/cameras/overview/hooks/overviewColumns.ts
  39. 0 53
      src/views/cameras/overview/hooks/searchRangeColumns.ts
  40. 0 166
      src/views/cameras/overview/hooks/sharedColumns.ts
  41. 0 92
      src/views/cameras/overview/hooks/useCameraShare.ts
  42. 0 33
      src/views/cameras/overview/hooks/useNvrDevice.ts
  43. 0 80
      src/views/cameras/overview/hooks/useTreeWorkspaceInfo.ts
  44. 0 167
      src/views/cameras/overview/stores/useCameraOverview.ts
  45. 0 38
      src/views/cameras/overview/stores/useSceneTemplateList.ts
  46. 0 108
      src/views/cameras/overview/stores/useSharedCamera.ts
  47. 0 65
      src/views/cameras/preview/CameraPreview.vue
  48. 0 316
      src/views/cameras/preview/components/CameraConfigGroup/CameraConfigGroup.vue
  49. 0 492
      src/views/cameras/preview/components/CameraConfigGroup/components/SettingCamera.vue
  50. 0 51
      src/views/cameras/preview/components/CameraConfigGroup/hooks/useCameraGroupQuery.ts
  51. 0 258
      src/views/cameras/preview/components/CameraConfigSingle/BatchOperationDialog.vue
  52. 0 412
      src/views/cameras/preview/components/CameraConfigSingle/CameraConfigSingle.vue
  53. 0 176
      src/views/cameras/preview/components/CameraConfigSingle/QueryForm.vue
  54. 0 389
      src/views/cameras/preview/components/CameraConfigSingle/SingleCameraTable.vue
  55. 0 31
      src/views/datamanager/alertformdata/AlertformData.vue
  56. 0 73
      src/views/datamanager/alertformdata/AlertformDataComplex.vue
  57. 0 22
      src/views/datamanager/alertformdata/components/common/AddDrawer.vue
  58. 0 350
      src/views/datamanager/alertformdata/components/common/AlertTable.vue
  59. 0 265
      src/views/datamanager/alertformdata/components/common/AlertTableSimple.vue
  60. 0 146
      src/views/datamanager/alertformdata/components/common/DetailDialog.vue
  61. 0 22
      src/views/datamanager/alertformdata/components/common/EditDrawer.vue
  62. 0 298
      src/views/datamanager/alertformdata/components/common/Prequalification.vue
  63. 0 309
      src/views/datamanager/alertformdata/components/common/QueryForm.vue
  64. 0 187
      src/views/datamanager/alertformdata/components/common/QueryFormSimple.vue
  65. 0 453
      src/views/datamanager/alertformdata/components/common/QuestionFormBase.vue
  66. 0 131
      src/views/datamanager/alertformdata/components/common/SwiperThumbsGallery.vue
  67. 0 115
      src/views/datamanager/alertformdata/components/common/constant.question.ts
  68. 0 342
      src/views/datamanager/alertformdata/components/default-simple/Default.vue
  69. 0 585
      src/views/datamanager/alertformdata/components/default/Default.vue
  70. 0 427
      src/views/datamanager/alertformdata/components/show/Show.vue
  71. 0 67
      src/views/datamanager/alertformdata/hooks/useIssueMainType.ts
  72. 0 45
      src/views/datamanager/alertformdata/hooks/useIssueType.ts
  73. 0 67
      src/views/datamanager/alertformdata/hooks/useWorkLocation.ts
  74. 0 28
      src/views/datamanager/alertformdata/store/useCurImgVideoUrl.ts
  75. 0 74
      src/views/datamanager/platformdata/PlatformData.vue
  76. 0 120
      src/views/datamanager/platformdata/charts/BarChart.vue
  77. 0 138
      src/views/datamanager/platformdata/charts/LineChart.vue
  78. 0 130
      src/views/datamanager/platformdata/charts/ScoreLineChart.vue
  79. 0 175
      src/views/datamanager/platformdata/components/common/DialogNavBar.vue
  80. 0 298
      src/views/datamanager/platformdata/components/common/QueryTable.vue
  81. 0 171
      src/views/datamanager/platformdata/components/common/ScoreTable.vue
  82. 0 142
      src/views/datamanager/platformdata/components/query/Query.vue
  83. 0 162
      src/views/datamanager/platformdata/components/score/Score.vue
  84. 0 57
      src/views/datamanager/platformdata/config.ts
  85. 0 216
      src/views/datamanager/playback/Playback.vue
  86. 0 316
      src/views/datamanager/playback/components/NvrCameraView.vue
  87. 0 77
      src/views/datamanager/playback/components/NvrCheckbox.vue
  88. 0 274
      src/views/datamanager/playback/components/NvrSlider.vue
  89. 0 178
      src/views/datamanager/playback/components/NvrTimeSelect.vue
  90. 0 146
      src/views/feedback/component/singleProblem.vue
  91. 0 18
      src/views/feedback/constant.ts
  92. 0 114
      src/views/feedback/feedback.vue
  93. 0 130
      src/views/feedback/handleFeedback.vue
  94. 0 46
      src/views/feedback/use-feedback.ts
  95. 0 11
      src/views/feedback/useHandleStore.ts
  96. 0 72
      src/views/list/basicList/columns.ts
  97. 0 336
      src/views/list/basicList/index.vue
  98. 0 37
      src/views/list/basicList/info.vue
  99. 0 155
      src/views/login/LoginForm.vue
  100. 0 0
      src/views/login/LoginForm2.vue

+ 0 - 16
package.json

@@ -27,20 +27,13 @@
   },
   "dependencies": {
     "@element-plus/icons-vue": "2.0.9",
-    "@originjs/vite-plugin-commonjs": "^1.0.3",
-    "@types/fabric": "5.3.6",
     "@vicons/antd": "0.12.0",
     "@vicons/ionicons5": "0.12.0",
-    "@vueup/vue-quill": "1.0.0-beta.8",
     "@vueuse/core": "8.9.4",
     "@vueuse/router": "10.6.1",
-    "@wangeditor/editor": "5.1.23",
     "@wangeditor/editor-for-vue": "5.1.12",
     "animate.css": "4.1.1",
-    "archiver": "^7.0.1",
     "axios": "0.27.2",
-    "blueimp-md5": "2.19.0",
-    "canvg": "4.0.1",
     "cropperjs": "1.5.12",
     "dayjs": "1.11.4",
     "echarts": "5.4.2",
@@ -48,29 +41,20 @@
     "element-resize-detector": "1.2.4",
     "form-data": "^4.0.0",
     "html2canvas": "1.0.0",
-    "json-editor-vue3": "^1.1.1",
-    "konva": "9.3.0",
     "lodash-es": "4.17.21",
     "mockjs": "1.1.0",
     "mpegts.js": "1.7.3",
     "nprogress": "0.2.0",
-    "number-precision": "1.6.0",
     "perfect-scrollbar": "1.5.5",
     "pinia": "2.0.16",
-    "print-js": "1.6.0",
-    "qrcode": "1.5.1",
     "qs": "6.11.0",
-    "swiper": "^11.2.5",
     "uid": "2.0.2",
     "url-join": "5.0.0",
-    "v-viewer": "^3.0.21",
     "vue": "3.3.4",
     "vue-echarts": "^6.7.3",
     "vue-hooks-plus": "1.8.6",
-    "vue-konva": "3.0.2",
     "vue-router": "4.1.2",
     "vue-types": "4.1.1",
-    "vuedraggable": "4.1.0",
     "xlsx": "0.18.5"
   },
   "devDependencies": {

+ 0 - 89
src/views/about/index.vue

@@ -1,89 +0,0 @@
-<template>
-  <PageWrapper
-    title="关于我们"
-    :content="`${name}是一个基于 vue3,vite2,TypeScript
-        的中后台解决方案,它可以帮助你快速搭建企业级中后台项目,相信不管是从新技术使用还是其他方面,都能帮助到你,持续更新中。`"
-  >
-    <el-card shadow="never" title="项目信息" class="mt-3 proCard" size="small">
-      <el-descriptions border label-placement="left" class="py-2">
-        <el-descriptions-item label="版本">
-          <el-tag type="info"> {{ version }} </el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="最后编译时间">
-          <el-tag type="info"> {{ lastBuildTime }} </el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="文档地址">
-          <div class="flex items-center">
-            <a href="https://www.naiveadmin.com" class="py-2" target="_blank">查看文档地址</a>
-          </div>
-        </el-descriptions-item>
-        <el-descriptions-item label="预览地址">
-          <div class="flex items-center">
-            <a href="https://pro.naiveadmin.com" class="py-2" target="_blank">查看预览地址</a>
-          </div>
-        </el-descriptions-item>
-        <el-descriptions-item label="Github">
-          <div class="flex items-center">
-            <a href="https://github.com/jekip/naive-ui-admin" class="py-2" target="_blank"
-              >查看Github地址</a
-            >
-          </div>
-        </el-descriptions-item>
-        <el-descriptions-item label="QQ交流群">
-          <div class="flex items-center">
-            <a href="https://jq.qq.com/?_wv=1027&k=xib9dU4C" class="py-2" target="_blank"
-              >点击链接加入群聊【Cloud Admin】</a
-            >
-          </div>
-        </el-descriptions-item>
-      </el-descriptions>
-    </el-card>
-
-    <el-card shadow="never" class="mt-3 proCard" size="small">
-      <template #header>
-        <div class="card-header">
-          <span>开发环境依赖</span>
-        </div>
-      </template>
-      <el-descriptions border label-placement="left" class="py-2">
-        <el-descriptions-item v-for="item in devSchema" :key="item.field" :label="item.field">
-          {{ item.label }}
-        </el-descriptions-item>
-      </el-descriptions>
-    </el-card>
-
-    <el-card shadow="never" class="mt-3 proCard" size="small">
-      <template #header>
-        <div class="card-header">
-          <span>生产环境依赖</span>
-        </div>
-      </template>
-      <el-descriptions border label-placement="left" class="py-2">
-        <el-descriptions-item v-for="item in schema" :key="item.field" :label="item.field">
-          {{ item.label }}
-        </el-descriptions-item>
-      </el-descriptions>
-    </el-card>
-  </PageWrapper>
-</template>
-
-<script lang="ts" setup>
-  export interface schemaItem {
-    field: string;
-    label: string;
-  }
-
-  const { pkg, lastBuildTime } = __APP_INFO__;
-  const { dependencies, devDependencies, name, version } = pkg;
-
-  const schema: schemaItem[] = [];
-  const devSchema: schemaItem[] = [];
-
-  Object.keys(dependencies).forEach((key) => {
-    schema.push({ field: key, label: dependencies[key] });
-  });
-
-  Object.keys(devDependencies).forEach((key) => {
-    devSchema.push({ field: key, label: devDependencies[key] });
-  });
-</script>

+ 0 - 199
src/views/alarm-push/PushAlarm.vue

@@ -1,199 +0,0 @@
-<template>
-  <div class="push-page">
-    <el-card :bordered="false" class="proCard" style="position: relative">
-      <BasicTable
-        :columns="columns"
-        :data-source="robotPushList"
-        :row-key="(row) => row.id"
-        :action-column="actionColumn"
-        :loading="loading"
-        :pagination="{ total: total, pageSize: size, hideOnSinglePage: !robotPushList.length }"
-        :tableSetting="{
-          size: false,
-          redo: false,
-          fullscreen: false,
-          striped: false,
-          setting: false,
-        }"
-        :striped="true"
-        ref="tableRef"
-        @order-change="orderByItem"
-        @page-num-change="handlePageNumChange"
-        @page-size-change="handlePageSizeChange"
-      >
-        <template #tableTitle>
-          <el-button type="primary" :icon="Plus" @click="addDrawer">添加</el-button>
-        </template>
-      </BasicTable>
-    </el-card>
-    <AddRobot
-      v-if="showDrawer"
-      :robot-list="robotList"
-      @on-close="closeDrawer"
-      @sub-add="addSubRobot"
-      @sub-edit="editSubRobot"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { h, onMounted, reactive, ref } from 'vue';
-  import { BasicTable, TableActionIcons } from '@/components/Table';
-  import { BasicColumn } from '@/components/Table';
-  import { columns } from './constant';
-  import { Plus } from '@element-plus/icons-vue';
-  import editIcon from '@/assets/images/table/table-edit.png';
-  import deleteIcon from '@/assets/images/table/table-delete.png';
-  import AddRobot from './component/AddRobot.vue';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import { RobotType } from '@/api/push/push';
-  import usePush from './usePush';
-
-  const usePushRobot = usePush();
-  const { robotPushList, total, page, size, loading, getRobotList, robotAdd, robotDel, robotEdit } =
-    usePushRobot;
-
-  onMounted(() => {
-    getRobotList();
-  });
-
-  // 添加弹窗相关
-  const showDrawer = ref(false);
-  const robotList = ref<RobotType | null>({});
-
-  //关闭drawer
-  const closeDrawer = () => {
-    showDrawer.value = false;
-  };
-
-  const addDrawer = () => {
-    robotList.value = null;
-    showDrawer.value = true;
-  };
-
-  const addSubRobot = (data) => {
-    robotAdd(data).then(() => {
-      ElMessage.success('添加成功');
-    });
-    showDrawer.value = false;
-  };
-
-  const editSubRobot = (data) => {
-    robotEdit(data).then(() => {
-      ElMessage.success('编辑成功');
-    });
-    showDrawer.value = false;
-  };
-
-  //操作列
-  const actionColumn: BasicColumn = reactive({
-    width: 200,
-    title: '操作',
-    prop: 'action',
-    key: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(TableActionIcons as any, {
-        space: 20,
-        color: '#629bf9',
-        iconStyle: 'img',
-        size: 16,
-        actionIcons: [
-          {
-            label: '编辑',
-            icon: editIcon,
-            onClick: handleEdit.bind(null, record.row),
-          },
-          {
-            label: '删除',
-            icon: deleteIcon,
-            onClick: handleDelete.bind(null, record.row),
-          },
-        ],
-      });
-    },
-  });
-
-  // 列排序操作
-  const orderByItem = () => {};
-
-  const handlePageNumChange = (pageNum) => {
-    page.value = pageNum;
-    getRobotList();
-  };
-
-  const handlePageSizeChange = (pageSize) => {
-    size.value = pageSize;
-    getRobotList();
-  };
-
-  const handleDelete = (row) => {
-    ElMessageBox.confirm(`您想删除机器人${row.robotName}`, '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      draggable: true,
-    })
-      .then(() => {
-        robotDel(row.id).then(() => {
-          ElMessage.success('删除成功');
-        });
-      })
-      .catch(() => {});
-  };
-
-  //编辑
-  const handleEdit = (row) => {
-    robotList.value = row;
-    showDrawer.value = true;
-  };
-</script>
-
-<style scoped>
-  .push-page {
-    position: relative;
-    height: calc(100vh - 64px - 12px);
-    background-color: #ffffff;
-  }
-
-  .camera-list {
-    padding: 0 21px;
-  }
-
-  .empty-content {
-    margin: auto;
-    padding: 125px 0;
-  }
-
-  .empty-img {
-    width: 396px;
-  }
-
-  .empty-text {
-    font-size: 22px;
-    color: #8e8e8e;
-    line-height: 30px;
-    text-align: center;
-  }
-
-  .add-tip {
-    position: absolute;
-    left: 187px;
-    top: 64px;
-    font-size: 16px;
-    color: red;
-  }
-  .add-popover {
-    position: absolute;
-    width: calc(100% - 21px);
-    height: 622px;
-    top: 0;
-    bottom: 0;
-    margin: auto;
-    z-index: 99;
-  }
-
-  .item {
-    margin: 0px 40px 0px 15px;
-  }
-</style>

+ 0 - 144
src/views/alarm-push/component/AddRobot.vue

@@ -1,144 +0,0 @@
-<template>
-  <div>
-    <el-drawer
-      ref="companyDrawerRef"
-      class="test"
-      :model-value="true"
-      @close="() => emits('onClose')"
-      with-header="true"
-      size="30%"
-    >
-      <template #header="{ titleId }">
-        <p :id="titleId">{{ title }}</p>
-      </template>
-      <el-form
-        ref="ruleFormRef"
-        :model="ruleForm"
-        :rules="rules"
-        label-width="120px"
-        class="demo-ruleForm"
-        size="default"
-        status-icon
-      >
-        <el-form-item label="机器人名称" prop="robotName">
-          <el-input v-model="ruleForm.robotName" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="机器人地址" prop="robotUrl">
-          <el-input v-model="ruleForm.robotUrl" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="场景" prop="workshopName">
-          <el-tree-select
-            v-model="ruleForm.workshopName"
-            :data="scenesTree"
-            :render-after-expand="false"
-            :default-expand-all="true"
-            check-strictly
-            multiple
-            placeholder="请选择场景"
-            style="width: 200px"
-            @change="handleTreeSelect"
-          />
-        </el-form-item>
-        <el-form-item label="状态">
-          <el-switch
-            v-model="ruleForm.isPush"
-            :active-value="true"
-            :inactive-value="false"
-            class="switchUse"
-          />
-        </el-form-item>
-      </el-form>
-      <div style="position: absolute; left: 108px; bottom: 67px">
-        <el-button @click="resetDrawer">重置</el-button>
-        <el-button type="primary" @click="subDrawer"> 提交 </el-button>
-      </div>
-    </el-drawer></div
-  >
-</template>
-
-<script setup lang="ts">
-  import { computed, reactive, ref, defineProps, defineEmits, onBeforeMount } from 'vue';
-  import type { FormInstance, FormRules } from 'element-plus';
-  import { RobotType } from '@/api/push/push';
-  import useSceneInfos from '@/hooks/useSceneInfos';
-  import { cloneDeep } from 'lodash-es';
-
-  const sceneInfos = useSceneInfos();
-  const { scenesTree, flattenedWorkshops, getScenesTree } = sceneInfos;
-
-  const props = defineProps<{
-    robotList: RobotType | null;
-  }>();
-
-  const title = computed(() => {
-    if (props.robotList) {
-      return '编辑机器人';
-    }
-    return '添加机器人';
-  });
-
-  const emits = defineEmits(['onClose', 'subAdd', 'subEdit']);
-
-  //表格中的规则
-  const ruleFormRef = ref<FormInstance>();
-
-  const ruleForm = ref<RobotType>({
-    robotName: '',
-    robotUrl: '',
-    workshopCodes: [],
-    workshopName: [],
-    isPush: true,
-  });
-
-  const rules = reactive<FormRules>({
-    robotName: [{ required: true, message: '请输入机器人名称', trigger: 'blur' }],
-    robotUrl: [{ required: true, message: '请输入机器人地址', trigger: 'blur' }],
-    workshopName: [{ required: true, message: '请选择场景', trigger: 'blur' }],
-  });
-
-  //重置编辑框
-  const resetDrawer = () => {
-    ruleForm.value.robotName = '';
-    ruleForm.value.robotUrl = '';
-    ruleForm.value.workshopCodes = [];
-    ruleForm.value.workshopName = [];
-    ruleForm.value.isPush = true;
-  };
-  //提交
-  const subDrawer = () => {
-    if (props.robotList) {
-      const data = {
-        id: props.robotList.id,
-        robotName: ruleForm.value.robotName,
-        robotUrl: ruleForm.value.robotUrl,
-        workshopCodes: ruleForm.value.workshopCodes,
-        isPush: ruleForm.value.isPush,
-      };
-      emits('subEdit', data);
-    } else {
-      const data = {
-        robotName: ruleForm.value.robotName,
-        robotUrl: ruleForm.value.robotUrl,
-        workshopCodes: ruleForm.value.workshopCodes,
-        isPush: ruleForm.value.isPush,
-      };
-      emits('subAdd', data);
-    }
-  };
-
-  const handleTreeSelect = (code: string) => {
-    ruleForm.value.workshopCodes = flattenedWorkshops.value
-      .filter((item) => code.includes(item.code))
-      .map(({ code, name }) => ({ code, name }));
-  };
-
-  onBeforeMount(() => {
-    getScenesTree({ level: 2, valueKey: 'code', labelKey: 'name', disabled: true });
-    if (props.robotList) {
-      ruleForm.value = cloneDeep(props.robotList);
-      ruleForm.value.workshopName = ruleForm.value.workshopCodes!.map((item) => item.code);
-    }
-  });
-</script>
-
-<style scoped></style>

+ 0 - 42
src/views/alarm-push/constant.ts

@@ -1,42 +0,0 @@
-import { BasicColumn } from '@/components/Table';
-import { h } from 'vue';
-
-export const columns: BasicColumn[] = [
-  {
-    label: '序号',
-    minWidth: 60,
-    type: 'index',
-    fixed: 'left',
-  },
-  {
-    label: '机器人名称',
-    prop: 'robotName',
-    minWidth: 100,
-  },
-  {
-    label: '机器人地址',
-    prop: 'robotUrl',
-    minWidth: 140,
-  },
-  {
-    label: '场景',
-    prop: 'workshopCodes',
-    minWidth: 120,
-    render(record) {
-      return h(
-        'span',
-        {},
-        {
-          default: () => {
-            return record.row.workshopCodes.map((item) => item.name).join(' , ');
-          },
-        },
-      );
-    },
-  },
-];
-
-export enum ENABLED {
-  FALSE = '0',
-  TRUE = '1',
-}

+ 0 - 62
src/views/alarm-push/usePush.ts

@@ -1,62 +0,0 @@
-import { ref } from 'vue';
-import { RobotType, getRobot, addRobot, editRobot, delRobot } from '@/api/push/push';
-import { useRequest } from 'vue-hooks-plus';
-
-export const usePush = () => {
-  const robotPushList = ref<RobotType[]>([]);
-  const total = ref(0);
-  const page = ref(1);
-  const size = ref(10);
-
-  // 查询
-  const robotSearch = () => {
-    const params = {
-      pageNumber: page.value,
-      pageSize: size.value,
-    };
-    return getRobot(params).then((res) => {
-      return res;
-    });
-  };
-
-  const { loading, run: getRobotList } = useRequest(robotSearch, {
-    manual: true,
-    onSuccess: (res) => {
-      robotPushList.value = [...res.records];
-      total.value = res.totalRow;
-    },
-  });
-
-  const robotAdd = (data: RobotType) => {
-    return addRobot(data).then(() => {
-      getRobotList();
-    });
-  };
-
-  const robotDel = (id: number) => {
-    return delRobot(id).then(() => {
-      getRobotList();
-    });
-  };
-
-  const robotEdit = (data: RobotType) => {
-    return editRobot(data).then(() => {
-      getRobotList();
-    });
-  };
-
-  return {
-    robotPushList,
-    total,
-    page,
-    size,
-    loading,
-    robotSearch,
-    getRobotList,
-    robotAdd,
-    robotDel,
-    robotEdit,
-  };
-};
-
-export default usePush;

+ 0 - 117
src/views/cameras/algo-management/algoManagement.vue

@@ -1,117 +0,0 @@
-<template>
-  <PageWrapper>
-    <div class="background">
-      <div class="left">
-        <el-input
-          class="search-input"
-          v-model="keyWord"
-          placeholder="请输入算法信息搜索"
-          :suffix-icon="Search"
-          @change="searchItem"
-        />
-        <div class="algo-table">
-          <el-table
-            :data="algoList"
-            stripe
-            height="100%"
-            highlight-current-row
-            :row-style="{ height: '54px' }"
-            :header-row-style="{ height: '54px' }"
-            @row-click="handleRowClick"
-          >
-            <el-table-column property="id" label="序号" width="80" align="center" />
-            <el-table-column property="code" label="算法编号" width="120" align="center" />
-            <el-table-column property="name" label="算法名称" />
-          </el-table>
-        </div>
-        <el-pagination
-          class="algo-pagination"
-          background
-          layout="prev, pager, next"
-          :total="total"
-          v-model:current-page="page"
-          :page-size="pageSize"
-          @current-change="getAlgoDatas"
-        />
-      </div>
-      <div class="right">
-        <div class="no-algo-choose" v-if="!curRow">
-          <img src="@/assets/images/algo/no-algo-choose.png" alt="" />
-          <div>请在左侧列表中选择算法</div>
-        </div>
-        <AlgoParamEdit v-else style="height: 100%" />
-      </div>
-    </div>
-  </PageWrapper>
-</template>
-
-<script lang="ts" setup>
-  import { onMounted } from 'vue';
-  import { storeToRefs } from 'pinia';
-  import { Search } from '@element-plus/icons-vue';
-  import { useAlgoDataStore } from './useAlgoData';
-  import { PageWrapper } from '../../../components/Page';
-  import AlgoParamEdit from './components/AlgoParamEdit.vue';
-
-  const algoDataStore = useAlgoDataStore();
-  const { keyWord, page, pageSize, total, algoList, curRow } = storeToRefs(algoDataStore);
-  const { getAlgoDatas } = algoDataStore;
-
-  const searchItem = () => {
-    page.value = 1;
-    getAlgoDatas();
-  };
-
-  const handleRowClick = (row) => {
-    curRow.value = row;
-  };
-
-  onMounted(() => {
-    getAlgoDatas();
-  });
-</script>
-
-<style lang="scss" scoped>
-  .background {
-    height: calc(100vh - 86px);
-    background-color: #ffffff;
-    display: flex;
-  }
-
-  .left {
-    height: 100%;
-    width: 31%;
-    padding-left: 1.66%;
-    padding-right: 1.33%;
-    border-right: 1px solid #dddddd;
-
-    .search-input {
-      height: 32px;
-      margin: 24px 0 16px 0;
-    }
-
-    .algo-table {
-      width: 100%;
-      height: calc(100% - 132px);
-    }
-
-    .algo-pagination {
-      float: right;
-      margin-top: 15px;
-    }
-  }
-
-  .right {
-    width: 69%;
-    height: 100%;
-
-    .no-algo-choose {
-      height: 100%;
-      display: flex;
-      flex-direction: column;
-      justify-content: center;
-      align-items: center;
-      font-weight: 600;
-    }
-  }
-</style>

+ 0 - 388
src/views/cameras/algo-management/components/AlgoParamEdit.vue

@@ -1,388 +0,0 @@
-<template>
-  <div>
-    <div class="algorithm-detail" v-loading="loading">
-      <div class="algo-name">
-        <div>【{{ curRow?.name }}】</div>
-        <div class="algo-set" @click="isParamSetVisible = true" v-if="hasSetParamPermission()">
-          <el-icon><Setting /></el-icon>
-          设置默认参数
-        </div>
-      </div>
-      <div class="algo-title">
-        <div class="title">算法介绍</div>
-        <el-icon class="edit-icon" :size="16" @click="changeEditStatus" v-if="hasAlgoEditPermission()"
-          ><EditPen
-        /></el-icon>
-      </div>
-      <div class="media-section">
-        <template v-if="editParam.url">
-          <el-image
-            v-if="isImage(editParam.url)"
-            class="media-img"
-            :src="editParam.url"
-            :preview-src-list="[editParam.url]"
-            :preview-teleported="true"
-            fit="cover"
-          />
-          <video class="media-video" v-else :src="editParam.url" controls />
-          <div class="media-set" v-if="isEditing">
-            <el-upload
-              :action="actionUrl"
-              :show-file-list="false"
-              :on-success="handleUpload"
-              :headers="getHeaders()"
-              :data="{ bizType: 'ALGO' }"
-            >
-              <el-icon class="icon-upload" :size="20"><Upload /></el-icon>
-            </el-upload>
-            <el-icon class="icon-delete" :size="20" @click="handleDelete"><Delete /></el-icon>
-          </div>
-        </template>
-        <template v-else>
-          <div class="empty-media">
-            <img src="@/assets/images/algo/no-algo-url.png" alt="" width="200" height="200" />
-            <el-upload
-              v-if="isEditing"
-              :action="actionUrl"
-              :show-file-list="false"
-              :on-success="handleUpload"
-              :headers="getHeaders()"
-              :data="{ bizType: 'ALGO' }"
-            >
-              <div class="empty-media-text">请点击上传算法介绍图片或视频</div>
-            </el-upload>
-          </div>
-        </template>
-      </div>
-      <div class="remark-card">
-        <template v-if="!isEditing">
-          <div v-for="(line, idx) in remarkLines" :key="idx">{{ line }}</div>
-        </template>
-        <template v-else>
-          <el-input
-            v-model="editParam.remark"
-            type="textarea"
-            :autosize="{ minRows: 4, maxRows: 8 }"
-            placeholder="请输入算法描述"
-          />
-        </template>
-      </div>
-      <div class="btn-group" v-if="isEditing">
-        <el-button @click="cancelEdit">取消</el-button>
-        <el-button type="primary" @click="saveChanges">保存</el-button>
-      </div>
-    </div>
-    <el-dialog
-      v-model="isParamSetVisible"
-      title="请输入代码修改算法参数,提交后生效"
-      width="60%"
-      align-center
-      @close="cancelAlgoParamsEdit"
-    >
-      <json-editor-vue
-        class="json-editor"
-        v-model="extraJson"
-        :language="'zh-CN'"
-        @update:modelValue="handleUpdateAlgoParam"
-        @validationError="editError"
-      />
-      <template #footer>
-        <div class="dialog-footer">
-          <div class="warning-text"
-            ><el-icon><Warning /></el-icon>请务必确保参数字段正确,谨慎提交!</div
-          >
-          <div>
-            <el-button @click="cancelAlgoParamsEdit">取消</el-button>
-            <el-button type="primary" @click="saveAlgoParamsChanges"> 提交 </el-button>
-          </div>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import urlJoin from 'url-join';
-  import { storeToRefs } from 'pinia';
-  import { ref, computed, watch, nextTick } from 'vue';
-  import { ElButton, ElIcon, ElMessage, ElUpload, ElDialog, ElInput } from 'element-plus';
-  import { EditPen, Upload, Delete, Setting, Warning } from '@element-plus/icons-vue';
-  import { useGlobSetting } from '@/hooks/setting';
-  import { useUserStore } from '@/store/modules/user';
-  import { getHeaders } from '@/utils/http/axios';
-  import { useAlgoDataStore } from '../useAlgoData';
-  import { PERM_ALGO } from '@/types/permission/constants';
-  import { UpdateAlgoParamParams, updateAlgoParam } from '@/api/algo/algo';
-  import JsonEditorVue from 'json-editor-vue3';
-
-  const { urlPrefix } = useGlobSetting();
-  const userStore = useUserStore();
-
-  const algoDataStore = useAlgoDataStore();
-  const { curRow } = storeToRefs(algoDataStore);
-  const { updateCurRow } = algoDataStore;
-
-  const loading = ref(false);
-  const isParamSetVisible = ref(false);
-  const isEditing = ref(false);
-  const editParam = ref<UpdateAlgoParamParams>({});
-  const extraJson = ref({});
-
-  const remarkLines = computed(() => (curRow.value?.remark ? curRow.value?.remark.split(/\r?\n/) : []));
-
-  const actionUrl = computed(() => {
-    return urlJoin(urlPrefix!, `/admin/minio/uploadFile`);
-  });
-
-  function initEditParam() {
-    editParam.value.algoId = curRow.value?.id;
-    editParam.value.algoParam = curRow.value?.extra;
-    editParam.value.remark = curRow.value?.remark;
-    editParam.value.url = curRow.value?.url;
-    extraJson.value = JSON.parse(curRow.value?.extra || '{}');
-  }
-
-  function isImage(url: string) {
-    return /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(url);
-  }
-
-  watch(
-    curRow,
-    () => {
-      if (curRow.value) {
-        initEditParam();
-        loading.value = false;
-      }
-    },
-    { immediate: true, deep: true },
-  );
-
-  // 默认参数设置权限
-  const hasSetParamPermission = () => {
-    return userStore.checkPermission(PERM_ALGO.PREVIEW_PARAM_DEFAULT);
-  };
-  // 算法介绍设置权限
-  const hasAlgoEditPermission = () => {
-    return userStore.checkPermission(PERM_ALGO.PREVIEW_DESCRIPTION);
-  };
-
-  const handleUpload = (res) => {
-    editParam.value.url = res.data.url;
-  };
-
-  const handleDelete = () => {
-    editParam.value.url = '';
-  };
-
-  const changeEditStatus = () => {
-    isEditing.value = !isEditing.value;
-    initEditParam();
-  };
-
-  const saveChanges = () => {
-    if (!editParam.value.remark) {
-      ElMessage({
-        message: '算法描述不可为空',
-        type: 'warning',
-      });
-      return;
-    }
-    loading.value = true;
-    updateAlgoParam(editParam.value).then(() => {
-      updateCurRow(curRow.value!);
-      ElMessage({
-        message: '保存成功',
-        type: 'success',
-      });
-      nextTick(() => {
-        isEditing.value = false;
-        loading.value = false;
-      });
-    });
-  };
-
-  const cancelEdit = () => {
-    isEditing.value = false;
-    initEditParam();
-  };
-
-  const handleUpdateAlgoParam = (newJsonData) => {
-    editParam.value.algoParam = newJsonData;
-  };
-
-  const cancelAlgoParamsEdit = () => {
-    isParamSetVisible.value = false;
-    initEditParam();
-  };
-
-  const saveAlgoParamsChanges = () => {
-    updateAlgoParam(editParam.value).then(() => {
-      updateCurRow(curRow.value!);
-      ElMessage({
-        message: '算法参数设置成功',
-        type: 'success',
-      });
-      isParamSetVisible.value = false;
-    });
-  };
-
-  const editError = (_editor: any, errors: any[]) => {
-    if (errors.length > 0) {
-      ElMessage({
-        message: 'JSON 格式错误,请检查',
-        type: 'error',
-      });
-    }
-  };
-</script>
-
-<style scoped lang="scss">
-  .algorithm-detail {
-    height: 100%;
-    padding: 20px 8px;
-
-    .algo-name {
-      font-size: 20px;
-      font-weight: bold;
-      margin-bottom: 16px;
-      display: flex;
-      align-items: center;
-
-      .algo-set {
-        font-size: 14px;
-        color: #409eff;
-        cursor: pointer;
-        display: flex;
-        align-items: center;
-        margin-left: 10px;
-
-        .el-icon {
-          margin-right: 5px;
-        }
-      }
-    }
-
-    .algo-title {
-      height: 22px;
-      display: flex;
-      align-items: center;
-      margin: 16px 0 8px 12px;
-      font-weight: 600;
-
-      .title {
-        line-height: 22px;
-        margin-left: 10px;
-        position: relative;
-      }
-
-      .title::before {
-        content: '';
-        display: inline-block;
-        width: 3px;
-        height: 14px;
-        background-color: #409eff;
-        border-radius: 1px;
-        position: absolute;
-        left: -10px;
-        top: 50%;
-        transform: translateY(-50%);
-      }
-
-      .edit-icon {
-        margin-left: 8px;
-        color: #409eff;
-        cursor: pointer;
-      }
-    }
-  }
-
-  .media-section {
-    height: 40%;
-    margin: 20px 22px;
-    position: relative;
-
-    .media-img,
-    .media-video {
-      height: 100%;
-    }
-
-    .media-set {
-      padding: 10px 5px;
-      border-radius: 50px;
-      position: absolute;
-      top: 30%;
-      right: 0;
-      background: #fefefe;
-      box-shadow: #cdcdcda3 2px 2px 4px 2px;
-    }
-
-    .icon-upload,
-    .icon-delete {
-      margin: 5px 0;
-      cursor: pointer;
-    }
-
-    .icon-upload:hover,
-    .icon-delete:hover {
-      color: #409eff;
-    }
-
-    .icon-upload {
-      margin-bottom: 20px;
-    }
-  }
-
-  .empty-media {
-    height: 100%;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-
-    .empty-media-text {
-      color: #409eff;
-      cursor: pointer;
-    }
-  }
-
-  .remark-card {
-    height: calc(60% - 145px);
-    margin: 10px 20px;
-    line-height: 35px;
-    overflow: auto;
-    font-size: 14px;
-  }
-
-  .btn-group {
-    display: flex;
-    justify-content: flex-end;
-    gap: 12px;
-  }
-
-  :deep(.el-dialog__body) {
-    height: 500px;
-    overflow: auto;
-  }
-
-  .json-editor {
-    width: 100%;
-    height: 100%;
-  }
-
-  .dialog-footer {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-
-    .warning-text {
-      color: #f56c6c;
-      font-size: 14px;
-      display: flex;
-      align-items: center;
-
-      .el-icon {
-        margin-right: 5px;
-      }
-    }
-  }
-</style>

+ 0 - 40
src/views/cameras/algo-management/useAlgoData.ts

@@ -1,40 +0,0 @@
-import { ref } from 'vue';
-import { defineStore } from 'pinia';
-import { queryAlgoInfoPage, AlgoDetail } from '@/api/algo/algo';
-
-export const useAlgoDataStore = defineStore('algoData', () => {
-  const page = ref(1);
-  const pageSize = ref(12);
-  const total = ref(0);
-  const keyWord = ref('');
-  const algoList = ref<AlgoDetail[]>();
-  // 当前选中行数据
-  const curRow = ref<AlgoDetail>();
-
-  const getAlgoDatas = () => {
-    return queryAlgoInfoPage({
-      pageNumber: page.value,
-      pageSize: pageSize.value,
-      queryParam: { name: keyWord.value },
-    }).then((res) => {
-      algoList.value = res.records;
-      total.value = res.totalRow;
-    });
-  };
-
-  const updateCurRow = async (row: AlgoDetail) => {
-    await getAlgoDatas();
-    curRow.value = algoList.value?.find((item) => item.id === row.id);
-  };
-
-  return {
-    keyWord,
-    page,
-    pageSize,
-    total,
-    curRow,
-    algoList,
-    getAlgoDatas,
-    updateCurRow,
-  };
-});

+ 0 - 37
src/views/cameras/algo-params-setting/AlgoParamsSetting.vue

@@ -1,37 +0,0 @@
-<!-- 算法参数配置页面 -->
-<template>
-  <AlgoParamsSettingBase
-    :cameraAllAlgoList="cameraAllAlgoList"
-    :isCameraGroup="false"
-    :getCameraAlgoList="getCameraAlgoListApi"
-  >
-    <template #cameraTree>
-      <CameraTree />
-    </template>
-  </AlgoParamsSettingBase>
-</template>
-
-<script lang="ts" setup>
-  import AlgoParamsSettingBase from '@/modules/algo-params-setting-base/AlgoParamsSettingBase.vue';
-  import CameraTree from '@/modules/algo-params-setting-base/components/CameraTree/CameraTree.vue';
-  import { AlgoDetail, queryAlgoInfoAllByCameraId } from '@/api/algo/algo';
-
-  import { watch, ref } from 'vue';
-  import { useRoute } from 'vue-router';
-  import { getCameraAlgoListApi } from '@/api/camera/camera-preview';
-  const cameraAllAlgoList = ref<AlgoDetail[]>([]);
-  const route = useRoute();
-
-  watch(
-    () => route.query.cameraId,
-    (nextCameraId) => {
-      if (!nextCameraId) return;
-      queryAlgoInfoAllByCameraId(nextCameraId).then((res) => {
-        cameraAllAlgoList.value = res;
-      });
-    },
-    { immediate: true },
-  );
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 41
src/views/cameras/camera-group-setting/CamerGroupSetting.vue

@@ -1,41 +0,0 @@
-<!-- 算法参数配置页面 -->
-<template>
-  <AlgoParamsSettingBase 
-  :cameraAllAlgoList="cameraAllAlgoList" 
-  :isCameraGroup="true" 
-  :getCameraAlgoList="queryGroupAlgoInfoByCameraId">
-    <template #cameraTree>
-      <CameraTreeList ref="CameraTreeRef"/>
-    </template>
-  </AlgoParamsSettingBase>
-</template>
-
-<script lang="ts" setup>
-  import { watch, ref } from 'vue';
-  import { useRoute } from 'vue-router';
-  import AlgoParamsSettingBase from '@/modules/algo-params-setting-base/AlgoParamsSettingBase.vue';
-  import CameraTreeList from './components/CameraTreeList.vue';
-  import { AlgoDetail } from '@/api/algo/algo';
-  import { queryGroupAlgoInfoByCameraId } from '@/api/camera/camera-preview-group'
-  
-  const cameraAllAlgoList = ref<AlgoDetail[]>([]);
-  const route = useRoute();
-  const CameraTreeRef = ref<InstanceType<typeof CameraTreeList>>();
-
-  watch(
-    () => route.query.cameraId,
-    (nextCameraId) => {
-      if (nextCameraId) {
-        queryGroupAlgoInfoByCameraId(Number(nextCameraId)).then((res) => {
-          if (res.length > 0 && res[0].algoInfo) {
-            cameraAllAlgoList.value = [res[0].algoInfo];
-          }
-        });
-      }
-    },
-    { immediate: true },
-  );
-
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 65
src/views/cameras/camera-group-setting/components/CameraTreeList.vue

@@ -1,65 +0,0 @@
-<template>
-  <div class="camera-tree-list">
-    <div class="camera-tree-list__title"> 相机列表 </div>
-    <div class="camera-tree-list__content">
-      <CameraTreeCom
-        ref="cameraTreeRef"
-        :tree-data="treeData"
-        :is-show-checkbox="false"
-        @node-click="handleNodeClick"
-      />
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ref, onMounted } from 'vue';
-  import { useRoute } from 'vue-router';
-  import CameraTreeCom from '@/modules/camera-tree/CameraTree.vue';
-  import { CameraTree, CameraTreeNodeType } from '@/api/camera/camera-preview';
-  import { queryCameraTreeByGroupId } from '@/api/camera/camera-preview-group';
-  import { ElMessage } from 'element-plus';
-  import { useRouteQuery } from '@vueuse/router';
-  const cameraId = useRouteQuery('cameraId');
-
-  interface CameraTreeTempType extends CameraTree {
-    tempCode?: string;
-  }
-
-  const route = useRoute();
-  const cameraTreeRef = ref<InstanceType<typeof CameraTreeCom>>();
-  const treeData = ref<CameraTreeTempType[]>([]);
-  const handleNodeClick = (e: CameraTree) => {
-    if (e.integrationState === 1) {
-      ElMessage.error('该相机未进入平台');
-    } else {
-      if (e.nodeType === CameraTreeNodeType.camera) {
-        cameraId.value = String(e.id);
-      }
-    }
-  };
-
-  onMounted(() => {
-    if (!route.query.groupId) return;
-    queryCameraTreeByGroupId(Number(route.query.groupId)).then((res) => {
-      treeData.value = res;
-    });
-  });
-
-</script>
-
-<style scoped lang="scss">
-  .camera-tree-list {
-    min-width: 270px;
-    max-width: 600px;
-    flex-shrink: 0;
-    border: 1px solid #f0f2f5;
-    margin: 5px;
-
-    .camera-tree-list__title {
-      background: #f0f2f5;
-      padding: 12px;
-      display: flex;
-    }
-  }
-</style>

+ 0 - 246
src/views/cameras/nvrlist/NvrList.vue

@@ -1,246 +0,0 @@
-<template>
-  <div class="nvr-page">
-    <div class="nvr-list">
-      <BasicTable :columns="columns" :data-source="nvrList" :row-key="(row) => row.code" :action-column="actionColumn"
-        :pagination="{
-          total: total,
-          pageSize: pagesize,
-          currentPage: page,
-          hideOnSinglePage: !nvrList.length,
-        }" :tableSetting="{
-          size: false,
-          redo: false,
-          fullscreen: false,
-          striped: false,
-          setting: false,
-        }" :striped="true" ref="tableRef" @page-num-change="handlePageNumChange"
-        @page-size-change="handlePageSizeChange">
-        <template #tableTitle>
-          <el-button type="primary" @click="openCreateDrawer" :icon="Plus" v-permission="{ action: [PERM_DEVICE.NVR_ADD] }">添加</el-button>
-        </template>
-        <template #empty>
-          <div class="empty-content flex flex-col items-center">
-            <img :src="emptyImg" class="empty-img" />
-            <span class="empty-text">暂未添加NVR设备</span>
-          </div>
-        </template>
-      </BasicTable>
-    </div>
-    <CreateDrawer ref="createDrawerRef" :title="drawerTitle" @form-submit="handleFormSubmit"
-      @form-edit="handleFormEdit" />
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { h, ref, reactive, onMounted } from 'vue';
-import { Plus } from '@element-plus/icons-vue';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import editIcon from '@/assets/images/table/table-edit.png';
-import deleteIcon from '@/assets/images/table/table-delete.png';
-import emptyImg from '@/assets/images/table/table-empty.png';
-import { columns } from './overviewColumns';
-import { BasicTable, TableActionIcons, BasicColumn } from '@/components/Table';
-import CreateDrawer from './components/CreateDrawer.vue';
-import { deleteNVRListItem, getNVRList, NVRListItemAll } from '@/api/camera/camera-nvr';
-import { PERM_DEVICE } from '@/types/permission/constants';
-import { useUserStore } from '@/store/modules/user';
-
-const nvrList = ref<NVRListItemAll[]>([]);
-const total = ref(0);
-const page = ref(1);
-const pagesize = ref(10);
-
-const getNvrList = () => {
-  const queryForm = {
-    pageNumber: page.value,
-    pageSize: pagesize.value,
-  };
-  getNVRList(queryForm).then((res) => {
-    total.value = res.totalRow;
-    nvrList.value = res.records;
-  });
-}
-
-const drawerTitle = ref('添加NVR');
-const createDrawerRef = ref();
-//添加数据
-const openCreateDrawer = () => {
-  drawerTitle.value = '添加NVR';
-  const { openDrawer } = createDrawerRef.value;
-  openDrawer();
-};
-// 编辑
-const handleEdit = (row) => {
-  drawerTitle.value = '编辑NVR';
-  const { openDrawer } = createDrawerRef.value;
-  openDrawer(row);
-};
-// 删除
-const handleDelete = (row) => {
-  ElMessageBox.confirm(
-    '删除后使用该NVR设备的车间内相关相机历史视频内容将无法查看',
-    '请确认是否删除NVR设备信息?',
-    {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true
-    }
-  )
-    .then(() => {
-      deleteNVRListItem(row.id).then(() => {
-        ElMessage({
-          message: '删除NVR设备成功.',
-          type: 'success',
-        });
-        getNvrList();
-      })
-    })
-    .catch(() => {
-      ElMessage({
-        type: 'info',
-        message: '取消删除',
-      })
-    })
-};
-
-const userStore = useUserStore();
-
-//操作列
-const actionColumn: BasicColumn = reactive({
-  width: 200,
-  title: '操作',
-  prop: 'action',
-  key: 'action',
-  fixed: 'right',
-  render(record) {
-    const actions: any[] = [];
-
-    if (userStore.checkPermission(PERM_DEVICE.NVR_EDIT)) {
-      actions.push({
-        label: '修改',
-        icon: editIcon,
-        onClick: handleEdit.bind(null, record.row),
-      });
-    }
-
-    if (userStore.checkPermission(PERM_DEVICE.NVR_DELETE)) {
-      actions.push({
-        label: '删除',
-        icon: deleteIcon,
-        onClick: handleDelete.bind(null, record.row),
-      });
-    }
-
-    return h(TableActionIcons as any, {
-      space: 20,
-      color: '#629bf9',
-      iconStyle: 'img',
-      size: 16,
-      actionIcons: [
-        {
-          label: '修改',
-          icon: editIcon,
-          onClick: handleEdit.bind(null, record.row),
-          ifShow: userStore.checkPermission(PERM_DEVICE.NVR_EDIT)
-        },
-        {
-          label: '删除',
-          icon: deleteIcon,
-          onClick: handleDelete.bind(null, record.row),
-          ifShow: userStore.checkPermission(PERM_DEVICE.NVR_DELETE)
-        }
-      ]
-    });
-  },
-});
-
-const handleFormSubmit = () => {
-  ElMessage({
-    message: '添加NVR设备成功.',
-    type: 'success',
-  });
-  getNvrList();
-};
-
-const handleFormEdit = () => {
-  ElMessage({
-    message: '修改NVR设备成功.',
-    type: 'success',
-  });
-  getNvrList();
-};
-
-const handlePageNumChange = (pageNum) => {
-  page.value = pageNum;
-  getNvrList();
-};
-
-const handlePageSizeChange = (size) => {
-  page.value = 1;
-  pagesize.value = size;
-  getNvrList();
-};
-
-onMounted(() => {
-  getNvrList();
-});
-</script>
-
-<style lang="scss" scoped>
-.nvr-page {
-  position: relative;
-  height: calc(100vh - 64px - 12px);
-  background-color: #ffffff;
-
-  .nvr-list {
-    padding: 35px 21px;
-  }
-}
-
-.empty-content {
-  margin: auto;
-  padding: 125px 0;
-}
-
-.empty-img {
-  width: 396px;
-}
-
-.empty-text {
-  font-size: 22px;
-  color: #8e8e8e;
-  line-height: 30px;
-  text-align: center;
-}
-</style>
-<style lang="scss">
-.deleteMessage {
-  padding: 20px 24px;
-  box-shadow: 0px 12px 48px 16px rgba(0, 0, 0, 0.03), 0px 9px 28px 0px rgba(0, 0, 0, 0.05), 0px 6px 16px -8px rgba(0, 0, 0, 0.08);
-  border-radius: 8px;
-
-  .el-message-box__headerbtn {
-    margin-top: 12px;
-    margin-right: 12px;
-  }
-
-  .el-message-box__title {
-    justify-content: start;
-    color: rgba(0, 0, 0, 0.88);
-    font-size: 16px;
-    font-weight: 500;
-  }
-
-  .el-message-box__container {
-    justify-content: start;
-    margin-left: 23px;
-  }
-
-  .el-message-box__btns {
-    display: block;
-    float: right;
-  }
-}
-</style>

+ 0 - 260
src/views/cameras/nvrlist/components/CreateDrawer.vue

@@ -1,260 +0,0 @@
-<template>
-  <div>
-    <el-drawer v-model="isDrawer" :size="350" :title="title" @close="closeDrawer">
-      <el-form
-        :model="formParams"
-        :rules="rules"
-        ref="formRef"
-        label-position="left"
-        :label-width="85"
-      >
-        <el-form-item label="设备名称:" prop="name">
-          <el-input v-model="formParams.name" placeholder="请输入设备名称" />
-        </el-form-item>
-        <el-form-item label="设备编号:" prop="code" :error="codeError">
-          <el-input v-model="formParams.code" placeholder="自定义编码,不可重复" />
-        </el-form-item>
-        <el-form-item label="设备品牌:" prop="nvrType">
-          <el-select v-model="formParams.nvrType" placeholder="请选择设备品牌">
-            <el-option
-              v-for="item in brands"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="IP地址:" prop="nvrIp" :error="ipError">
-          <el-input v-model="formParams.nvrIp" placeholder="请输入设备IP地址,不可重复" />
-        </el-form-item>
-        <el-form-item label="端口:" prop="nvrPort">
-          <el-input v-model="formParams.nvrPort" placeholder="请输入设备端口" />
-        </el-form-item>
-        <el-form-item label="用户名:" prop="username">
-          <el-input v-model="formParams.username" placeholder="请输入设备用户名" />
-        </el-form-item>
-        <el-form-item label="密码:" prop="password">
-          <el-input
-            v-model="formParams.password"
-            placeholder="请输入设备密码"
-            type="password"
-            show-password
-          />
-        </el-form-item>
-        <!-- <el-form-item label="使用场景:" prop="workshopList">
-          <el-tree-select class="temp" v-model="workLocations" :data="locationOptions" multiple
-            :render-after-expand="false" placeholder="请选择使用该NVR的车间" @change="handleCascaderChange" />
-        </el-form-item> -->
-        <el-form-item label="负责人:" prop="principalName">
-          <el-input v-model="formParams.principalName" placeholder="请输入设备安装负责人" />
-        </el-form-item>
-        <el-form-item label="备注:" prop="remark">
-          <el-input
-            v-model="formParams.remark"
-            type="textarea"
-            maxlength="200"
-            :autosize="{ minRows: 3 }"
-            show-word-limit
-            placeholder="请输入该设备相关备注"
-          />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="btn-box">
-          <el-button @click="closeDrawer">取消</el-button>
-          <el-button type="primary" @click="formSubmit">提交</el-button>
-        </div>
-      </template>
-    </el-drawer>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { ref, computed, onMounted } from 'vue';
-  import { brands, useWorkLocation } from '../constant';
-  import { FormRules } from 'element-plus';
-  import {
-    NVRListItem,
-    NVRListItemAll,
-    addNVRListItem,
-    updateNVRListItem,
-  } from '@/api/camera/camera-nvr';
-
-  interface Props {
-    title: String;
-  }
-  const props = defineProps<Props>();
-  const emit = defineEmits(['form-submit', 'form-edit']);
-
-  const isDrawer = ref(false);
-  const formRef: any = ref(null);
-  // const ismultiple = { multiple: true };
-
-  const { getLocationOptions } = useWorkLocation();
-  // const workLocations = ref<[number | undefined, number | undefined] | []>([]);
-  const workLocations = ref<number[]>([]);
-
-  const codeError = ref('');
-  const ipError = ref('');
-
-  const initFormNvr = () => ({
-    name: '',
-    code: '',
-    nvrIp: '',
-    nvrType: '',
-    nvrPort: '',
-    username: '',
-    password: '',
-    principalName: '',
-    remark: '',
-  });
-  const formParams = ref<NVRListItem>(initFormNvr());
-
-  const deleteKey = (obj, ...args) => {
-    args.forEach((v) => {
-      delete obj[v];
-    });
-    return obj;
-  };
-  const openDrawer = (row: NVRListItemAll) => {
-    isDrawer.value = true;
-    if (row) {
-      formParams.value = Object.assign(formParams.value, row);
-      deleteKey(formParams.value, 'createdAt', 'isDeleted', 'tenantId', 'updatedAt');
-      return;
-    }
-  };
-
-  const closeDrawer = () => {
-    isDrawer.value = false;
-    formRef.value.resetFields();
-    formParams.value = Object.assign(formParams.value, initFormNvr());
-    workLocations.value = [];
-  };
-
-  const isAddUser = computed(() => {
-    return props.title === '添加NVR';
-  });
-
-  const rules: FormRules = {
-    name: { required: true, message: '设备名称不能为空', trigger: 'blur' },
-    code: [
-      { required: true, message: '设备编号不能为空', trigger: 'change' },
-      {
-        pattern: /^[a-zA-Z0-9-_]+$/,
-        message: '请输入大小写字母、数字、-、_的组合',
-        trigger: 'change',
-      },
-    ],
-    nvrType: { required: true, message: '设备品牌不能为空', trigger: 'change' },
-    nvrIp: { required: true, message: '设备IP不能为空', trigger: 'change' },
-    nvrPort: { required: true, message: '端口不能为空', trigger: 'blur' },
-    username: { required: true, message: '用户名不能为空', trigger: 'blur' },
-    password: { required: true, message: '密码不能为空', trigger: 'blur' },
-    workshopList: { required: true, message: '使用场景不能为空', trigger: 'change' },
-  };
-
-  const formSubmit = () => {
-    const errorText = ref('');
-    // 捕获当前表单中是否有el-form-item__error即错误信息
-    const errorTipElements = document.querySelectorAll('.el-form-item__error');
-    errorTipElements.forEach((element) => {
-      if (element.textContent) errorText.value = element.textContent;
-    });
-
-    if (errorText.value === '') {
-      // codeError.value = '';
-      // ipError.value = '';
-      formRef.value.validate((valid) => {
-        if (valid) {
-          const nvrData = {
-            name: formParams.value.name,
-            code: formParams.value.code,
-            nvrIp: formParams.value.nvrIp,
-            nvrType: formParams.value.nvrType,
-            nvrPort: formParams.value.nvrPort,
-            username: formParams.value.username,
-            password: formParams.value.password,
-            principalName: formParams.value.principalName,
-            remark: formParams.value.remark,
-          };
-
-          if (isAddUser.value) {
-            addNVRListItem(nvrData).then(() => {
-              emit('form-submit');
-              closeDrawer();
-              // if (Object.getOwnPropertyNames(res).length != 0) {
-              //   codeError.value = res.code;
-              //   ipError.value = res.nvrIp;
-              // } else {
-              // }
-            });
-          } else {
-            updateNVRListItem(formParams.value).then(() => {
-              emit('form-edit');
-              closeDrawer();
-              // if (Object.getOwnPropertyNames(res).length != 0) {
-              //   codeError.value = res.code;
-              //   ipError.value = res.nvrIp;
-              // } else {
-              // }
-            });
-          }
-        }
-      });
-    }
-  };
-
-  defineExpose({
-    openDrawer,
-    closeDrawer,
-  });
-
-  onMounted(() => {
-    getLocationOptions();
-  });
-</script>
-
-<style lang="scss" scoped>
-  :deep(.el-drawer__header) {
-    position: relative;
-
-    > :first-child {
-      margin-left: 32px;
-      font-weight: 600;
-      font-size: 16px;
-      color: rgba(0, 0, 0, 0.88);
-    }
-
-    .el-drawer__close-btn {
-      position: absolute;
-      color: #000;
-    }
-  }
-
-  :deep(.el-drawer__body) {
-    border-top: 1px solid #0000000f;
-  }
-
-  :deep(.el-form-item__label) {
-    padding-right: 0;
-  }
-
-  :deep(.el-cascader) {
-    width: 230px;
-  }
-
-  .btn-box {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    width: 100%;
-    margin-top: 10px;
-  }
-
-  :deep(.temp .el-select__selection) {
-    min-height: 24px;
-    max-height: 55px;
-    overflow: auto;
-  }
-</style>

+ 0 - 56
src/views/cameras/nvrlist/constant.ts

@@ -1,56 +0,0 @@
-import { ref } from 'vue';
-import { getShopSpaceList } from '@/api/scene/scene';
-
-// nvrType 可选项
-export const brands = [
-  { value: "dahua", label: "大华" },
-  { value: "haikang", label: "海康" },
-  { value: "anxunshi", label: "安讯士" },
-  { value: "huawei", label: "华为" },
-];
-
-// 公司-车间 级联可选项
-type Location = {
-  value: string;
-  label: string;
-  children: {
-    value: number;
-    label: string;
-  }[];
-};
-
-export function useWorkLocation() {
-  const locationOptions = ref<Location[]>([]);
-
-  const getLocationOptions = () => {
-    getShopSpaceList().then((res) => {
-      locationOptions.value =
-        res?.map((item) => {
-          const newChildren =
-            item.children?.map((x) => {
-              return { value: x.id, label: x.name };
-            }) || [];
-          return {
-            value: `${item.id}+${item.name}`,
-            label: item.name,
-            children: newChildren,
-          };
-        }) || [];
-    });
-  };
-
-  // 入参一个children里的value,根据这个value找到其父亲的value,返回[父value,子value]
-  const getWorkLocation = (workshopId: number, array) => {
-    const company: Location = array.find((item) =>
-      item.children.find((subItem) => {
-        subItem.value === workshopId;
-      }));
-    return company?.value, workshopId;
-  };
-
-  return {
-    locationOptions,
-    getLocationOptions,
-    getWorkLocation
-  };
-}

+ 0 - 39
src/views/cameras/nvrlist/overviewColumns.ts

@@ -1,39 +0,0 @@
-import type { BasicColumn } from '@/components/Table';
-import { brands } from './constant';
-import { h } from 'vue';
-
-export const columns: BasicColumn[] = [
-  {
-    label: '序号',
-    minWidth: 60,
-    type: 'index',
-  },
-  {
-    label: '名称',
-    prop: 'name',
-    minWidth: 100,
-  },
-  {
-    label: '设备品牌',
-    prop: 'nvrType',
-    minWidth: 140,
-    render(record) {
-      return h('span', {}, brands.find((item) => item.value === record.row.nvrType)?.label);
-    },
-  },
-  {
-    label: '设备编号',
-    prop: 'code',
-    minWidth: 100,
-  },
-  {
-    label: 'IP地址',
-    prop: 'nvrIp',
-    minWidth: 140,
-  },
-  {
-    label: '负责人',
-    prop: 'principalName',
-    minWidth: 140,
-  },
-];

+ 0 - 603
src/views/cameras/overview/CamerasOverview.vue

@@ -1,603 +0,0 @@
-<template>
-  <div class="camera-page">
-    <ConditionQuery />
-    <div class="camera-list">
-      <div v-if="showActionBar" class="action-bar">
-        <span class="num-text">已选{{ chooseNum }}项</span>
-        <el-button
-          :class="isActiveExport ? 'btn-active' : 'btn-normal'"
-          @click="handleBatchExport"
-          v-if="hasCameraViewPermission()"
-          >导出</el-button
-        >
-        <el-button
-          :class="isActiveDelete ? 'btn-active' : 'btn-normal'"
-          @click="handleBatchDelete"
-          v-if="hasCameraDeletePermission()"
-          >删除</el-button
-        >
-        <span class="close-btn" @click="handleSelectNone"></span>
-      </div>
-      <BasicTable
-        :columns="columns"
-        :data-source="cameraItems"
-        :row-key="(row) => row.code"
-        :action-column="actionColumn"
-        :pagination="{
-          total: total,
-          currentPage: page,
-          pageSize: size,
-          hideOnSinglePage: !cameraItems.length,
-        }"
-        :loading="loading"
-        :tableSetting="{
-          size: false,
-          redo: false,
-          fullscreen: false,
-          striped: false,
-          setting: false,
-        }"
-        :striped="true"
-        ref="tableRef"
-        @order-change="orderByItem"
-        @selection-change="handleSelectionChange"
-        @page-num-change="handlePageNumChange"
-        @page-size-change="handlePageSizeChange"
-      >
-        <template #tableTitle>
-          <el-button
-            v-if="hasCameraAddPermission()"
-            type="primary"
-            :icon="Plus"
-            @click="showAddPopover = true"
-            style="margin-right: 18px"
-            >添加</el-button
-          >
-          <el-button
-            v-if="hasCameraAddPermission()"
-            plain
-            color="#1890FF"
-            @click="showBatchImportPopover = true"
-            style="margin: 0 18px 0 0"
-          >
-            <template #icon>
-              <el-icon>
-                <DocumentAdd />
-              </el-icon>
-            </template>
-            批量添加
-          </el-button>
-          <el-button
-            v-if="hasCameraEditPermission()"
-            plain
-            color="#1890FF"
-            @click="showBatchEditPopover = true"
-            style="margin: 0 18px 0 0"
-          >
-            <template #icon>
-              <el-icon>
-                <Edit />
-              </el-icon>
-            </template>
-            批量修改
-          </el-button>
-          <!-- <el-badge :value="totalRow" :hidden="totalRow < 1" class="item">
-            <el-button
-              plain
-              color="#1890FF"
-              @click="showSharedPopover = true"
-              style="margin: 0 18px 0 0"
-              >共享相机</el-button
-            >
-          </el-badge> -->
-          <el-button
-            v-if="hasCameraViewPermission()"
-            plain
-            color="#1890FF"
-            style="margin: 0 18px 0 0"
-            @click="handleExportALl"
-          >
-            <template #icon>
-              <el-icon>
-                <Tickets />
-              </el-icon>
-            </template>
-            全部相机信息导出
-          </el-button>
-        </template>
-        <template #empty>
-          <div class="empty-content flex flex-col items-center">
-            <img :src="emptyImg" class="empty-img" />
-            <span class="empty-text">目前无内容,请先添加相机</span>
-          </div>
-        </template>
-      </BasicTable>
-    </div>
-    <AddCamera v-model="showAddPopover" />
-    <BatchImportCamera
-      class="batch-import"
-      v-if="showBatchImportPopover"
-      @update="handleUpdateBatchImport"
-      @close="handleCloseBatchImport"
-    />
-    <BatchEditCamera
-      class="batch-import"
-      v-if="showBatchEditPopover"
-      @update="handleUpdateBatchEdit"
-      @close="handleCloseBatchEdit"
-    />
-    <EditCamera v-model="showEditPopover" :edit-data="editCameraData" />
-    <EditSRSCamera v-model="showEditSRSPopover" :edit-data="editCameraData" />
-    <EditNVRCamera v-model="showEditNVRPopover" :edit-data="editCameraData" />
-    <ShareCamera v-model="addSharedPopover" :share-data="shareCameraData" />
-    <EditSharedCamera v-model="showSharedPopover" @update-unadd="updateUnaddAmount" />
-    <CameraOverviewPopover
-      v-if="showCameraOverviewPopover"
-      :dialog-visible="showCameraOverviewPopover"
-      :overview-camera-data="overviewCameraData!"
-      @update:dialogVisible="showCameraOverviewPopover = false"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { h, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
-  import { BasicTable, TableActionIcons } from '@/components/Table';
-  import { BasicColumn } from '@/components/Table';
-  import { columns } from './hooks/overviewColumns';
-  import ConditionQuery from './components/ConditionQuery.vue';
-  import AddCamera from './components/CameraAddPopover.vue';
-  import BatchImportCamera from './components/BatchImportCamera.vue';
-  import BatchEditCamera from './components/BatchEditCamera.vue';
-  import ShareCamera from './components/CameraSharePopover.vue';
-  import EditCamera from './components/CameraEditPopover.vue';
-  import EditSRSCamera from './components/CameraEditSRSPopover.vue';
-  import EditNVRCamera from './components/CameraEditNVRPopover.vue';
-  import EditSharedCamera from './components/CameraSharedEdit.vue';
-  import CameraOverviewPopover from './components/CameraOverviewPopover.vue';
-  import emptyImg from '@/assets/images/table/table-empty.png';
-  import { Plus, DocumentAdd, Edit, Tickets } from '@element-plus/icons-vue';
-  import shareIcon from '@/assets/images/table/table-share.png';
-  import previewIcon from '@/assets/images/table/table-preview.png';
-  import editIcon from '@/assets/images/table/table-edit.png';
-  import deleteIcon from '@/assets/images/table/table-delete.png';
-  import useCameraOverview from './stores/useCameraOverview';
-  import { storeToRefs } from 'pinia';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import { deleteCameraItem, deleteCameraItems } from '@/api/camera/camera-overview';
-  import { getCameraDeatilById } from '@/api/camera/camera-preview';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import useCameraShare from './hooks/useCameraShare';
-  import { AddType } from '@/types/camera/constant';
-  import axios, { AxiosRequestConfig } from 'axios';
-  import { getHeaders } from '@/utils/http/axios';
-  import { useGlobSetting } from '@/hooks/setting';
-  import { useSceneTemplateList } from './stores/useSceneTemplateList';
-  import { useUserStore } from '@/store/modules/user';
-  import { PERM_DEVICE } from '@/types/permission/constants';
-  import useCameraDetailStore from '@/modules/algo-params-setting-base/store/useCameraDetailStore';
-  const cameraDetailStore = useCameraDetailStore();
-
-  const userStore = useUserStore();
-  const hasCameraAddPermission = () => {
-    return userStore.checkPermission(PERM_DEVICE.CAMERA_ADD);
-  };
-  const hasCameraEditPermission = () => {
-    return userStore.checkPermission(PERM_DEVICE.CAMERA_EDIT);
-  };
-  const hasCameraDeletePermission = () => {
-    return userStore.checkPermission(PERM_DEVICE.CAMERA_DELETE);
-  };
-  const hasCameraViewPermission = () => {
-    return userStore.checkPermission(PERM_DEVICE.CAMERA_VIEW);
-  };
-
-  const sceneTemplateListInfo = useSceneTemplateList();
-  const { getSceneTemplateList } = sceneTemplateListInfo;
-
-  const { urlPrefix } = useGlobSetting();
-
-  const useShare = useCameraShare();
-  const { totalRow, queryToTenantId, isAddState, conditionSearch } = useShare;
-  const showCameraOverviewPopover = ref(false);
-
-  onMounted(() => {
-    isAddState.value = false;
-    console.log('isAddState', isAddState.value);
-    queryToTenantId.value = -10;
-    conditionSearch();
-  });
-
-  const cameraOverview = useCameraOverview();
-  const { cameraItems, loading, total, page, size } = storeToRefs(cameraOverview);
-  const { getCameraItems, openInterval, closeInterval, reset } = cameraOverview;
-
-  const tableRef = ref();
-  // 添加弹窗相关
-  const showAddPopover = ref(false);
-  // 批量添加弹窗
-  const showBatchImportPopover = ref(false);
-  // 批量删除弹窗
-  const showBatchEditPopover = ref(false);
-  const showSharedPopover = ref(false);
-  const addSharedPopover = ref(false);
-  const showEditPopover = ref(false);
-  const showEditSRSPopover = ref(false);
-  const showEditNVRPopover = ref(false);
-  const editCameraData = ref<CameraDetailServer>();
-  const overviewCameraData = ref<CameraDetailServer>();
-  const shareCameraData = ref<CameraDetailServer | null>();
-  // 多选操作
-  const showActionBar = ref(false);
-  const chooseNum = ref(0);
-  const chooseId = ref<number[]>([]);
-  const isActiveExport = ref(false);
-  const isActiveDelete = ref(false);
-
-  const updateUnaddAmount = () => {
-    isAddState.value = false;
-    console.log('isAddState', isAddState.value);
-    queryToTenantId.value = -10;
-    conditionSearch();
-  };
-
-  //操作列
-  const actionColumn: BasicColumn = reactive({
-    width: 200,
-    title: '操作',
-    prop: 'action',
-    key: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(TableActionIcons as any, {
-        space: 20,
-        color: '#629bf9',
-        iconStyle: 'img',
-        size: 16,
-        actionIcons: [
-          {
-            label: '分享',
-            icon: shareIcon,
-            onClick: handleShare.bind(null, record.row),
-            ifShow: false,
-          },
-          {
-            label: '编辑',
-            icon: editIcon,
-            onClick: handleEdit.bind(null, record.row),
-            auth: hasCameraEditPermission,
-          },
-          {
-            label: '预览',
-            icon: previewIcon,
-            onClick: handlePreview.bind(null, record.row),
-            disabled: record.row.networkingState !== 0 || record.row.integrationState !== 0,
-          },
-          {
-            label: '删除',
-            icon: deleteIcon,
-            onClick: handleDelete.bind(null, record.row),
-            auth: hasCameraDeletePermission,
-          },
-        ].filter((x) => {
-          if (!x.auth) return true;
-          return x.auth();
-        }),
-      });
-    },
-  });
-
-  // 列排序操作
-  const orderByItem = () => {};
-
-  // 多选操作
-  const handleSelectionChange = (selection) => {
-    chooseNum.value = selection.length;
-    showActionBar.value = chooseNum.value > 0 ? true : false;
-    chooseId.value = [];
-    selection.forEach((item) => {
-      if (chooseId.value.indexOf(item.id) === -1) chooseId.value.push(item.id);
-    });
-  };
-
-  const handleExportALl = async () => {
-    const requestBody = {};
-
-    const config: AxiosRequestConfig = {
-      headers: getHeaders(),
-      responseType: 'blob',
-    };
-
-    const response = await axios.post(urlPrefix + '/admin/cameraConfig/exportAllCameraList', requestBody, config);
-
-    const blob = new Blob([response.data], {
-      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-    });
-
-    // 创建下载链接
-    let downloadLink: HTMLAnchorElement | null = document.createElement('a');
-    const url = window.URL.createObjectURL(blob);
-    downloadLink.href = url;
-    downloadLink.download = '全量相机导出信息.xlsx';
-    downloadLink.click();
-    // 移除下载链接
-    window.URL.revokeObjectURL(url);
-    downloadLink = null;
-  };
-
-  const handleBatchExport = async () => {
-    try {
-      const requestBody = {
-        cameraIdList: chooseId.value,
-      };
-
-      const config: AxiosRequestConfig = {
-        headers: getHeaders(),
-        responseType: 'blob',
-      };
-      const response = await axios.post(urlPrefix + '/admin/cameraConfig/exportCameraList', requestBody, config);
-      const blob = new Blob([response.data], {
-        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-      });
-      // 创建下载链接
-      let downloadLink: HTMLAnchorElement | null = document.createElement('a');
-      const url = window.URL.createObjectURL(blob);
-      downloadLink.href = url;
-      downloadLink.download = '相机导出信息.xlsx';
-      downloadLink.click();
-      // 移除下载链接
-      window.URL.revokeObjectURL(url);
-      downloadLink = null;
-    } catch (error) {
-      console.error('Error downloading file:', error);
-    }
-  };
-
-  const handleBatchDelete = () => {
-    if (showActionBar.value) isActiveDelete.value = !isActiveDelete.value;
-    ElMessageBox.confirm('删除后,相机数据无法恢复', '请确认是否删除相机数据', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true,
-    })
-      .then(() => {
-        deleteCameraItems(chooseId.value).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '删除成功',
-          });
-          page.value = 1;
-          getCameraItems();
-          handleSelectNone();
-          isActiveDelete.value = !isActiveDelete.value;
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消删除',
-        });
-        isActiveDelete.value = !isActiveDelete.value;
-      });
-  };
-
-  // 清除多选
-  const handleSelectNone = () => {
-    chooseId.value = [];
-    chooseNum.value = 0;
-    tableRef.value?.clearAll();
-    showActionBar.value = false;
-  };
-
-  const handlePageNumChange = (pageNum) => {
-    page.value = pageNum;
-    getCameraItems();
-  };
-
-  const handlePageSizeChange = (pageSize) => {
-    page.value = 1;
-    size.value = pageSize;
-    getCameraItems();
-  };
-
-  const handleShare = (row) => {
-    addSharedPopover.value = true;
-    shareCameraData.value = row;
-  };
-
-  const handlePreview = (_row) => {
-    console.log('handlePreview', _row);
-    showCameraOverviewPopover.value = true;
-    overviewCameraData.value = _row;
-    cameraDetailStore.cameraId = _row.id;
-    getCameraDeatilById(_row.id).then((res) => {
-      cameraDetailStore.setDetail(res);
-    });
-  };
-
-  const handleDelete = (row) => {
-    ElMessageBox.confirm(`是否删除相机${row.code}`, '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      draggable: true,
-    })
-      .then(() => {
-        deleteCameraItem({ cameraId: row.id }).then(() => {
-          ElMessage.success('删除成功');
-
-          getCameraItems();
-        });
-      })
-      .catch(() => {});
-  };
-
-  const handleEdit = (row) => {
-    if (row.sourceType === AddType.srs) {
-      showEditSRSPopover.value = true;
-    } else if (row.sourceType === AddType.ip) {
-      showEditPopover.value = true;
-    } else {
-      showEditNVRPopover.value = true;
-    }
-    editCameraData.value = row;
-  };
-
-  // 批量导入相关事件
-  const handleUpdateBatchImport = () => {
-    showBatchImportPopover.value = false;
-    page.value = 1;
-    size.value = 10;
-    getCameraItems();
-  };
-  const handleCloseBatchImport = () => {
-    showBatchImportPopover.value = false;
-  };
-
-  // 批量修改相关事件
-  const handleUpdateBatchEdit = () => {
-    showBatchEditPopover.value = false;
-    page.value = 1;
-    size.value = 10;
-    getCameraItems();
-  };
-  const handleCloseBatchEdit = () => {
-    showBatchEditPopover.value = false;
-  };
-
-  onMounted(() => {
-    getCameraItems();
-    openInterval();
-    getSceneTemplateList();
-  });
-
-  onBeforeUnmount(() => {
-    closeInterval();
-    reset();
-  });
-</script>
-
-<style scoped lang="less">
-  .action-bar {
-    display: flex;
-    align-items: center;
-    position: absolute;
-    top: 48px;
-    min-width: calc(100vw - 266px);
-    height: 50px;
-    border-radius: 4px 4px 0px 0px;
-    background-color: #ddefff;
-    z-index: 10;
-
-    .num-text {
-      margin: 0 34px 0 25px;
-      color: rgba(0, 0, 0, 0.85);
-      font-weight: 500;
-    }
-
-    .btn-normal {
-      color: #1890ff;
-      background: transparent;
-      border: 1px solid #1890ff;
-      border-radius: 2px;
-    }
-
-    .btn-active {
-      color: #ffffff;
-      background-color: #1890ff;
-    }
-
-    .close-btn {
-      margin-left: auto;
-      margin-right: 20px;
-    }
-
-    .close-btn:before {
-      content: '\2716';
-      color: #000;
-      cursor: pointer;
-    }
-  }
-
-  .camera-page {
-    position: relative;
-    height: calc(100vh - 64px - 12px);
-    background-color: #ffffff;
-  }
-
-  .camera-list {
-    padding: 0 21px;
-    position: relative;
-  }
-
-  .empty-content {
-    margin: auto;
-    padding: 125px 0;
-  }
-
-  .empty-img {
-    width: 396px;
-  }
-
-  .empty-text {
-    font-size: 22px;
-    color: #8e8e8e;
-    line-height: 30px;
-    text-align: center;
-  }
-
-  .add-tip {
-    position: absolute;
-    left: 187px;
-    top: 64px;
-    font-size: 16px;
-    color: red;
-  }
-
-  .batch-import {
-    position: absolute;
-    width: 593px;
-    height: 435px;
-    left: 50%;
-    top: 50%;
-    margin-top: -218px;
-    margin-left: -297px;
-    z-index: 99;
-  }
-
-  .item {
-    margin: 0px 40px 0px 0px;
-  }
-</style>
-<style lang="less">
-  .deleteMessage {
-    padding: 20px 24px;
-    box-shadow: 0px 12px 48px 16px rgba(0, 0, 0, 0.03), 0px 9px 28px 0px rgba(0, 0, 0, 0.05),
-      0px 6px 16px -8px rgba(0, 0, 0, 0.08);
-    border-radius: 8px;
-
-    .el-message-box__headerbtn {
-      margin-top: 12px;
-      margin-right: 12px;
-    }
-
-    .el-message-box__title {
-      justify-content: start;
-      color: rgba(0, 0, 0, 0.88);
-      font-size: 16px;
-      font-weight: 500;
-    }
-
-    .el-message-box__container {
-      justify-content: start;
-      margin-left: 23px;
-    }
-
-    .el-message-box__btns {
-      display: block;
-      float: right;
-    }
-  }
-</style>

+ 0 - 222
src/views/cameras/overview/components/AddCameraByIP.vue

@@ -1,222 +0,0 @@
-<template>
-  <div>
-    <div>
-      <el-form
-        ref="IPFormRef"
-        class="ip-form"
-        :inline="true"
-        :model="cameraIPData"
-        :rules="rules"
-        label-width="114px"
-        label-position="left"
-      >
-        <el-form-item label="名称:" prop="name">
-          <el-input v-model="cameraIPData.name" placeholder="请输入名称" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="设备ID:" prop="code">
-          <el-input v-model="cameraIPData.code" placeholder="自定义ID,不能重复" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="IP地址:" prop="cameraIp">
-          <el-input v-model="cameraIPData.cameraIp" placeholder="请输入IP地址" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="端口:" prop="cameraPort">
-          <el-input v-model="cameraIPData.cameraPort" placeholder="请输入端口号" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="用户名:" prop="username">
-          <el-input v-model="cameraIPData.username" placeholder="请输入用户名" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="密码:" prop="password">
-          <el-input v-model="cameraIPData.password" placeholder="请输入用户名密码" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="视频编码标准:" prop="videoStandard">
-          <el-select v-model="cameraIPData.videoStandard" placeholder="请选择视频编码标准" style="width: 200px">
-            <el-option
-              v-for="protocal in standardTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="服务类型:" prop="videoServiceType">
-          <el-select v-model="cameraIPData.videoServiceType" placeholder="请选择服务类型" style="width: 200px">
-            <el-option
-              v-for="protocal in serviceTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="NVR设备:" prop="nvrId">
-          <el-select v-model="cameraIPData.nvrId" placeholder="请选择NVR设备" style="width: 200px">
-            <el-option v-for="item in nvrDevice" :key="item.id" :label="item.label" :value="item.id" />
-          </el-select>
-          <div style="margin-left: 10px; position: relative; width: 20px; height: 32px">
-            <el-tooltip content="选择已添加在【NVR设备管理】中的设备编号">
-              <el-icon :size="16" style="position: absolute; top: 8px"><InfoFilled /></el-icon>
-            </el-tooltip>
-          </div>
-        </el-form-item>
-        <el-form-item label="协议类型:" prop="cameraType">
-          <el-select v-model="cameraIPData.cameraType" placeholder="请选择协议类型" style="width: 200px">
-            <el-option
-              v-for="protocal in protocalTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="所属工位:" prop="workspaceIdStr">
-          <el-tree-select
-            v-model="cameraIPData.workspaceIdStr"
-            :data="workspaceInfo"
-            :render-after-expand="false"
-            :default-expand-all="true"
-            placeholder="请选择工位"
-            style="width: 200px"
-            @node-click="handleTreeSelect"
-          />
-        </el-form-item>
-        <el-form-item label="工位负责人:" prop="principal">
-          <el-input
-            v-model="cameraIPData.principal"
-            placeholder="请选择工位,该项自动填充"
-            disabled
-            style="width: 200px"
-          />
-        </el-form-item>
-        <el-form-item label="业务场景:" prop="sceneTemplateList" style="width: 766px">
-          <sysConfigItemOfAddCamera
-            :origin-scene-checked-list="cameraIPData.sceneTemplateList"
-            @update:scene-checked-list="handleUpdateSceneTemplateList"
-          />
-        </el-form-item>
-        <el-form-item label="备注:" prop="remark" style="width: 766px">
-          <el-input v-model="cameraIPData.remark" placeholder="请输入备注" style="width: 655px" />
-        </el-form-item>
-      </el-form>
-    </div>
-    <span class="pop-footer">
-      <el-button @click="handleCancel">取消</el-button>
-      <el-button type="primary" @click="handleConfirm">确定</el-button>
-    </span>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { onBeforeMount, ref } from 'vue';
-  import { ElIcon } from 'element-plus';
-  import { InfoFilled } from '@element-plus/icons-vue';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import { protocalTypeSelect, serviceTypeSelect, standardTypeSelect } from '@/types/camera/constant';
-  import useNvrDevice from '../hooks/useNvrDevice';
-  import useTreeWorkspaceInfo from '../hooks/useTreeWorkspaceInfo';
-  import { cloneDeep } from 'lodash-es';
-  import sysConfigItemOfAddCamera, { getSceneCheckedValues } from './sysConfigItemOfAddCamera.vue';
-
-  const props = defineProps<{ formData?: CameraDetailServer | null }>();
-  const emits = defineEmits(['cancel-execute', 'confirm-execute']);
-
-  const treeWorkspaceInfo = useTreeWorkspaceInfo();
-  const { workspaceInfo, getWorkspaceFromTreeInfo, getWorkspaceIdFromTreeNode } = treeWorkspaceInfo;
-
-  const nvrDeviceInfo = useNvrDevice();
-  const { nvrDevice, getNvrDevice } = nvrDeviceInfo;
-
-  const IPFormRef = ref();
-
-  type CameraDetailForm = CameraDetailServer & { workspaceIdStr?: string };
-  const cameraIPData = ref<CameraDetailForm>({} as CameraDetailForm);
-
-  const validateSceneTemplate = (_rule, value, callback) => {
-    if (Object.keys(sceneCheckedDataRef.value).length === 0)
-      callback(new Error('请至少选择一个业务场景及对应应用模版'));
-    else if (value && Object.keys(sceneCheckedDataRef.value).length > value.length)
-      callback(new Error('请完成已选业务场景中的应用模版选择'));
-    else callback();
-  };
-
-  const rules = {
-    name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
-    code: [{ required: true, message: '请输入设备ID', trigger: 'blur' }],
-    cameraIp: [{ required: true, message: '请输入IP地址', trigger: 'blur' }],
-    cameraPort: [{ required: true, message: '请输入端口号', trigger: 'blur' }],
-    username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
-    password: [{ required: true, message: '请输入用户名密码', trigger: 'blur' }],
-    videoStandard: [{ required: true, message: '请选择视频编码标准', trigger: 'blur' }],
-    cameraType: [{ required: true, message: '请选择协议类型', trigger: 'blur' }],
-    workspaceIdStr: [{ required: true, message: '请选择工位', trigger: 'blur' }],
-    sceneTemplateList: [{ required: true, validator: validateSceneTemplate, trigger: 'blur' }],
-  };
-
-  const sceneCheckedDataRef = ref({} as Record<number, boolean>);
-  const handleUpdateSceneTemplateList = (sceneTemplateData, sceneCheckedData) => {
-    sceneCheckedDataRef.value = sceneCheckedData;
-    cameraIPData.value.sceneTemplateList = sceneTemplateData;
-  };
-
-  const handleCancel = () => {
-    emits('cancel-execute');
-  };
-
-  const handleConfirm = () => {
-    IPFormRef.value.validate((valid) => {
-      if (valid) {
-        const copyData = cloneDeep(cameraIPData.value);
-        if (cameraIPData.value.workspaceIdStr)
-          copyData.workspaceId = Number(getWorkspaceIdFromTreeNode(cameraIPData.value.workspaceIdStr));
-        delete (copyData as any).principal;
-        copyData.sourceType = 'IP';
-        emits('confirm-execute', copyData);
-      }
-    });
-  };
-
-  const handleTreeSelect = (node) => {
-    if (node.disabled) return;
-    cameraIPData.value.principal = node.principalName ? node.principalName : '该工位暂无负责人';
-    cameraIPData.value.workshopId = node.workshopId;
-  };
-
-  onBeforeMount(() => {
-    getNvrDevice();
-    getWorkspaceFromTreeInfo();
-    if (props.formData) {
-      cameraIPData.value = props.formData;
-      cameraIPData.value.workspaceIdStr = `workspace-${props.formData.workspaceId}`;
-      sceneCheckedDataRef.value = getSceneCheckedValues(props.formData.sceneTemplateList);
-    }
-  });
-</script>
-
-<style scoped>
-  .ip-form {
-    width: 768px;
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    align-content: space-around;
-  }
-
-  .pop-footer {
-    position: absolute;
-    right: 24px;
-    bottom: 27px;
-    display: flex;
-    justify-content: flex-end;
-  }
-
-  :deep(.el-form-item__label) {
-    font-size: 14px;
-    color: #363636;
-    padding: 0;
-  }
-  :deep(.el-form--inline .el-form-item) {
-    display: flex;
-    margin-right: 0;
-    margin-bottom: 28px;
-  }
-</style>

+ 0 - 211
src/views/cameras/overview/components/AddCameraByNVR.vue

@@ -1,211 +0,0 @@
-<template>
-  <div>
-    <div>
-      <el-form
-        ref="NVRFormRef"
-        class="ip-form"
-        :inline="true"
-        :model="cameraNVRData"
-        :rules="rules"
-        label-width="124px"
-        label-position="left"
-      >
-        <el-form-item label="名称:" prop="name">
-          <el-input v-model="cameraNVRData.name" placeholder="请输入名称" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="设备ID:" prop="code">
-          <el-input v-model="cameraNVRData.code" placeholder="自定义ID,不能重复" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="视频编码标准:" prop="videoStandard">
-          <el-select v-model="cameraNVRData.videoStandard" placeholder="请选择视频编码标准" style="width: 200px">
-            <el-option
-              v-for="protocal in standardTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="服务类型:" prop="videoServiceType">
-          <el-select v-model="cameraNVRData.videoServiceType" placeholder="请选择服务类型" style="width: 200px">
-            <el-option
-              v-for="protocal in serviceTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="NVR设备:" prop="nvrId">
-          <el-select v-model="cameraNVRData.nvrId" placeholder="请选择NVR设备" style="width: 200px">
-            <el-option v-for="item in nvrDevice" :key="item.id" :label="item.label" :value="item.id" />
-          </el-select>
-          <div style="margin-left: 10px; position: relative; width: 20px; height: 32px">
-            <el-tooltip content="选择已添加在【NVR设备管理】中的设备编号">
-              <el-icon :size="16" style="position: absolute; top: 8px"><InfoFilled /></el-icon>
-            </el-tooltip>
-          </div>
-        </el-form-item>
-        <el-form-item label="NVR平台通道号:" prop="nvrChannel">
-          <el-input v-model="cameraNVRData.nvrChannel" placeholder="请输入NVR平台通道号" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="所属工位:" prop="workspaceIdStr">
-          <el-tree-select
-            v-model="cameraNVRData.workspaceIdStr"
-            :data="workspaceInfo"
-            :render-after-expand="false"
-            :default-expand-all="true"
-            placeholder="请选择工位"
-            style="width: 200px"
-            @node-click="handleTreeSelect"
-          />
-        </el-form-item>
-        <el-form-item label="工位负责人:" prop="principal">
-          <el-input
-            v-model="cameraNVRData.principal"
-            placeholder="请选择工位,该项自动填充"
-            disabled
-            style="width: 200px"
-          />
-        </el-form-item>
-
-        <el-form-item label="业务场景:" prop="sceneTemplateList" style="width: 766px">
-          <sysConfigItemOfAddCamera
-            :origin-scene-checked-list="cameraNVRData.sceneTemplateList"
-            @update:scene-checked-list="handleUpdateSceneTemplateList"
-          />
-        </el-form-item>
-        <el-form-item label="协议类型:" prop="cameraType">
-          <el-select v-model="cameraNVRData.cameraType" placeholder="请选择协议类型" style="width: 200px">
-            <el-option
-              v-for="protocal in protocalTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="备注:" prop="remark">
-          <el-input v-model="cameraNVRData.remark" placeholder="请输入备注" style="width: 200px" />
-        </el-form-item>
-      </el-form>
-    </div>
-    <span class="pop-footer">
-      <el-button @click="handleCancel">取消</el-button>
-      <el-button type="primary" @click="handleConfirm">确定</el-button>
-    </span>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { onBeforeMount, ref } from 'vue';
-  import { cloneDeep } from 'lodash-es';
-  import { ElIcon, ElTooltip } from 'element-plus';
-  import { InfoFilled } from '@element-plus/icons-vue';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import { protocalTypeSelect, serviceTypeSelect, standardTypeSelect } from '@/types/camera/constant';
-  import useNvrDevice from '../hooks/useNvrDevice';
-  import useTreeWorkspaceInfo from '../hooks/useTreeWorkspaceInfo';
-  import sysConfigItemOfAddCamera, { getSceneCheckedValues } from './sysConfigItemOfAddCamera.vue';
-
-  const props = defineProps<{ formData?: CameraDetailServer | null }>();
-  const emits = defineEmits(['cancel-execute', 'confirm-execute']);
-
-  const nvrDeviceInfo = useNvrDevice();
-  const { nvrDevice, getNvrDevice } = nvrDeviceInfo;
-
-  const treeWorkspaceInfo = useTreeWorkspaceInfo();
-  const { workspaceInfo, getWorkspaceFromTreeInfo, getWorkspaceIdFromTreeNode } = treeWorkspaceInfo;
-
-  const NVRFormRef = ref();
-
-  type CameraDetailForm = CameraDetailServer & { workspaceIdStr?: string };
-  const cameraNVRData = ref<CameraDetailForm>({} as CameraDetailForm);
-
-  const validateSceneTemplate = (_rule, value, callback) => {
-    if (Object.keys(sceneCheckedDataRef.value).length === 0)
-      callback(new Error('请至少选择一个业务场景及对应应用模版'));
-    else if (value && Object.keys(sceneCheckedDataRef.value).length > value.length)
-      callback(new Error('请完成已选业务场景中的应用模版选择'));
-    else callback();
-  };
-
-  const rules = {
-    nvrId: [{ required: true, message: '请选择NVR设备', trigger: 'blur' }],
-    name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
-    code: [{ required: true, message: '请输入设备ID', trigger: 'blur' }],
-    nvrChannel: [{ required: true, message: '请输入NVR平台通道号', trigger: 'blur' }],
-    sceneTemplateList: [{ required: true, validator: validateSceneTemplate, trigger: 'blur' }],
-    workspaceIdStr: [{ required: true, message: '请选择工位', trigger: 'blur' }],
-    cameraType: [{ required: true, message: '请选择协议类型', trigger: 'blur' }],
-    videoStandard: [{ required: true, message: '请选择视频编码标准', trigger: 'blur' }],
-  };
-
-  const sceneCheckedDataRef = ref({} as Record<number, boolean>);
-  const handleUpdateSceneTemplateList = (sceneTemplateData, sceneCheckedData) => {
-    sceneCheckedDataRef.value = sceneCheckedData;
-    cameraNVRData.value.sceneTemplateList = sceneTemplateData;
-  };
-
-  const handleCancel = () => {
-    emits('cancel-execute');
-  };
-
-  const handleConfirm = () => {
-    NVRFormRef.value.validate((valid) => {
-      if (valid) {
-        const copyData = cloneDeep(cameraNVRData.value);
-        if (cameraNVRData.value.workspaceIdStr)
-          copyData.workspaceId = Number(getWorkspaceIdFromTreeNode(cameraNVRData.value.workspaceIdStr));
-        delete (copyData as any).principal;
-        copyData.sourceType = 'NVR';
-        emits('confirm-execute', copyData);
-      }
-    });
-  };
-
-  const handleTreeSelect = (node) => {
-    if (node.disabled) return;
-    cameraNVRData.value.principal = node.principalName ? node.principalName : '该工位暂无负责人';
-    cameraNVRData.value.workshopId = node.workshopId;
-  };
-
-  onBeforeMount(() => {
-    getNvrDevice();
-    getWorkspaceFromTreeInfo();
-    if (props.formData) {
-      cameraNVRData.value = props.formData;
-      cameraNVRData.value.workspaceIdStr = `workspace-${props.formData.workspaceId}`;
-      sceneCheckedDataRef.value = getSceneCheckedValues(props.formData.sceneTemplateList);
-    }
-  });
-</script>
-
-<style scoped>
-  .ip-form {
-    width: 768px;
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    align-content: space-around;
-  }
-
-  .pop-footer {
-    position: absolute;
-    right: 24px;
-    bottom: 27px;
-    display: flex;
-    justify-content: flex-end;
-  }
-
-  :deep(.el-form-item__label) {
-    font-size: 14px;
-    color: #363636;
-    padding: 0;
-  }
-  :deep(.el-form--inline .el-form-item) {
-    display: flex;
-    margin-right: 0;
-    margin-bottom: 28px;
-  }
-</style>

+ 0 - 285
src/views/cameras/overview/components/AddCameraByRange.vue

@@ -1,285 +0,0 @@
-<template>
-  <div style="width: 100%">
-    <div class="flex flex-col items-center add-body">
-      <el-form
-        class="range-form"
-        :inline="true"
-        :model="cameraRangeData"
-        :rules="rules"
-        label-width="84px"
-        label-position="left"
-      >
-        <el-form-item
-          v-for="item in cameraRangeAddForm"
-          :key="item.prop"
-          :label="item.label"
-          :prop="item.prop"
-          :label-width="item.labelWidth"
-        >
-          <el-input
-            v-if="item.type === 'input'"
-            v-model="cameraRangeData[item.prop]"
-            :placeholder="item.placeholder"
-            style="width: 200px"
-          />
-          <el-select
-            v-if="item.type === 'select'"
-            v-model="cameraRangeData[item.prop]"
-            :placeholder="item.placeholder"
-            style="width: 200px"
-          >
-            <el-option
-              v-for="protocal in item.option"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-      </el-form>
-      <div class="flex justify-end" style="width: 100%">
-        <el-button type="primary" class="btn-r" @click="searchRangeCamera">搜索</el-button>
-      </div>
-      <div class="search-list">
-        <BasicTable
-          style="height: 274px"
-          :columns="columns"
-          :data-source="cameraItems"
-          :row-key="(row) => row.name"
-          :action-column="actionColumn"
-          :pagination="false"
-          :tableSetting="{
-            size: false,
-            redo: false,
-            fullscreen: false,
-            striped: false,
-            setting: false,
-          }"
-          :row-class-name="getRowClassName"
-          ref="tableRef"
-          @order-change="orderByItem"
-          @selection-change="handleSelectionChange"
-        >
-          <template #empty>
-            <div class="empty-content flex flex-col items-center">
-              <img :src="emptyImg" class="empty-img" />
-              <span class="empty-text">目前无内容,请先添加相机</span>
-            </div>
-          </template>
-        </BasicTable>
-      </div>
-      <EditCamera v-model="showEditPop" style="z-index: 9" :edit-data="editRow" />
-    </div>
-    <span class="pop-footer">
-      <el-button @click="handleCancel">取消</el-button>
-      <el-button type="primary" @click="handleConfirm">确定</el-button>
-    </span>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed, h, reactive, ref } from 'vue';
-  import { CameraRangeItem, CameraDetailServer } from '../../../../types/camera/type';
-  import { cameraRangeAddForm } from '../../../../types/camera/constant';
-  import SearchCamerasAction from './SearchCamerasAction.vue';
-  import { BasicTable } from '@/components/Table';
-  import { BasicColumn } from '@/components/Table';
-  import { columns } from '../hooks/searchRangeColumns';
-  import emptyImg from '@/assets/images/table/table-empty.png';
-  import editIcon from '@/assets/images/table/table-edit.png';
-  import deleteIcon from '@/assets/images/table/table-delete.png';
-  import EditCamera from './CameraEditPopover.vue';
-
-  const emits = defineEmits(['cancel-execute', 'confirm-execute']);
-
-  const cameraRangeData = ref<CameraRangeItem>({} as CameraRangeItem);
-
-  const showEditPop = ref(false);
-  const editRow = ref<CameraDetailServer | null>(null);
-
-  const rules = computed(() => {
-    const newRule = {};
-    cameraRangeAddForm.forEach((item) => {
-      if (item.required) {
-        newRule[item.prop] = item.rule;
-      }
-    });
-    return newRule;
-  });
-
-  //操作列
-  const actionColumn: BasicColumn = reactive({
-    width: 150,
-    title: '操作',
-    prop: 'action',
-    key: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(SearchCamerasAction as any, {
-        activeColor: '#629bf9',
-        unactiveColor: 'rgba(0,0,0,0.4)',
-        tableTextActions: [
-          {
-            label: '添加',
-            disabled: false,
-            onclick: handleAdd.bind(null, record.row),
-          },
-        ],
-        tableIconActions: {
-          space: 10,
-          color: '#629bf9',
-          style: 'img',
-          size: 16,
-          actionIcons: [
-            {
-              label: '编辑',
-              icon: editIcon,
-              onClick: handleEdit.bind(null, record.row),
-            },
-            {
-              label: '删除',
-              icon: deleteIcon,
-              onClick: handleDelete.bind(null, record.row),
-            },
-          ],
-        },
-      });
-    },
-  });
-
-  const getRowClassName = (record) => {
-    return record.row.name !== 'SHGD-XDJS-0003' ? 'warm-row' : '';
-  };
-
-  const cameraItems = reactive([
-    {
-      cameraIp: '10.10.10.10',
-      protocal: '海康威视',
-      cameraPort: '8080',
-      mac: '255.255.255.255',
-      name: 'SHGD-XDJS-0001',
-      workshopId: 'ARJ21部装车间',
-      workspaceId: '200工位',
-      networkState: 1,
-      status: 1,
-    },
-    {
-      cameraIp: '10.10.10.10',
-      protocal: '海康威视',
-      cameraPort: '8080',
-      mac: '255.255.255.255',
-      name: 'SHGD-XDJS-0002',
-      workshopId: 'ARJ21部装车间',
-      workspaceId: '200工位',
-      networkState: 1,
-      status: 1,
-    },
-    {
-      cameraIp: '10.10.10.10',
-      protocal: '海康威视',
-      cameraPort: '8080',
-      mac: '255.255.255.255',
-      name: 'SHGD-XDJS-0003',
-      workshopId: 'ARJ21部装车间',
-      workspaceId: '200工位',
-      networkState: 1,
-      status: 1,
-    },
-    {
-      cameraIp: '10.10.10.10',
-      protocal: '海康威视',
-      cameraPort: '8080',
-      mac: '255.255.255.255',
-      name: 'SHGD-XDJS-0004',
-      workshopId: 'ARJ21部装车间',
-      workspaceId: '200工位',
-      networkState: 1,
-      status: 1,
-    },
-    {
-      cameraIp: '10.10.10.10',
-      protocal: '海康威视',
-      cameraPort: '8080',
-      mac: '255.255.255.255',
-      name: 'SHGD-XDJS-0005',
-      workshopId: 'ARJ21部装车间',
-      workspaceId: '200工位',
-      networkState: 1,
-      status: 1,
-    },
-  ]);
-
-  const searchRangeCamera = () => {};
-
-  // 列排序操作
-  const orderByItem = () => {};
-
-  const handleSelectionChange = (val: any[]) => {
-    console.log(val);
-  };
-
-  const handleAdd = () => {};
-
-  const handleDelete = () => {};
-
-  const handleEdit = (row) => {
-    showEditPop.value = true;
-    editRow.value = row;
-  };
-
-  const handleCancel = () => {
-    emits('cancel-execute');
-  };
-
-  const handleConfirm = () => {};
-</script>
-
-<style scoped>
-  .add-body {
-    width: 100%;
-  }
-
-  .range-form {
-    width: 1082px;
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    align-content: space-around;
-    margin-bottom: -12px;
-  }
-
-  .btn-r {
-    margin-right: 24px;
-  }
-
-  .search-list {
-    width: 100%;
-    height: 300px;
-    padding: 0 28px;
-    margin-bottom: 40px;
-  }
-
-  .pop-footer {
-    position: absolute;
-    right: 24px;
-    bottom: 27px;
-    display: flex;
-    justify-content: flex-end;
-  }
-
-  :deep(.el-form-item__label) {
-    font-size: 14px;
-    color: #363636;
-    padding: 0;
-  }
-  :deep(.el-form--inline .el-form-item) {
-    display: flex;
-    margin-right: 0;
-    margin-bottom: 28px;
-  }
-  :deep(.el-table .warm-row) {
-    background: #f9e6e5 !important;
-    --el-table-row-hover-bg-color: none;
-    --el-bg-color: none;
-  }
-</style>

+ 0 - 208
src/views/cameras/overview/components/AddCameraBySRS.vue

@@ -1,208 +0,0 @@
-<template>
-  <div>
-    <div>
-      <el-form
-        ref="IPFormRef"
-        class="ip-form"
-        :inline="true"
-        :model="CameraSRSData"
-        :rules="rules"
-        label-width="114px"
-        label-position="left"
-      >
-        <el-form-item label="名称:" prop="name">
-          <el-input v-model="CameraSRSData.name" placeholder="请输入名称" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="设备ID:" prop="code">
-          <el-input v-model="CameraSRSData.code" placeholder="自定义ID,不能重复" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="rtsp地址:" prop="rtspUrl">
-          <el-input
-            v-model="CameraSRSData.rtspUrl"
-            placeholder="rtsp://192.168.0.249:557/34020000000_00000000000001"
-            style="width: 655px"
-          />
-        </el-form-item>
-        <el-form-item label="NVR设备:" prop="nvrId">
-          <el-select v-model="CameraSRSData.nvrId" placeholder="请选择NVR设备" style="width: 200px">
-            <el-option v-for="item in nvrDevice" :key="item.id" :label="item.label" :value="item.id" />
-          </el-select>
-          <div style="margin-left: 10px; position: relative; width: 20px; height: 32px">
-            <el-tooltip content="选择已添加在【NVR设备管理】中的设备编号">
-              <el-icon :size="16" style="position: absolute; top: 8px"><InfoFilled /></el-icon>
-            </el-tooltip>
-          </div>
-        </el-form-item>
-        <el-form-item label="相机IP地址:" prop="cameraIp">
-          <el-input v-model="CameraSRSData.cameraIp" placeholder="请输入IP地址" style="width: 200px" />
-        </el-form-item>
-
-        <el-form-item label="视频编码标准:" prop="videoStandard">
-          <el-select v-model="CameraSRSData.videoStandard" placeholder="请选择视频编码标准" style="width: 200px">
-            <el-option
-              v-for="protocal in standardTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="服务类型:" prop="videoServiceType">
-          <el-select v-model="CameraSRSData.videoServiceType" placeholder="请选择服务类型" style="width: 200px">
-            <el-option
-              v-for="protocal in serviceTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="所属工位:" prop="workspaceIdStr">
-          <el-tree-select
-            v-model="CameraSRSData.workspaceIdStr"
-            :data="workspaceInfo"
-            :render-after-expand="false"
-            :default-expand-all="true"
-            placeholder="请选择工位"
-            style="width: 200px"
-            @node-click="handleTreeSelect"
-          />
-        </el-form-item>
-        <el-form-item label="工位负责人:" prop="principal">
-          <el-input
-            v-model="CameraSRSData.principal"
-            placeholder="请选择工位,该项自动填充"
-            style="width: 200px"
-            :disabled="true"
-          />
-        </el-form-item>
-        <el-form-item label="业务场景:" prop="sceneTemplateList" style="width: 766px">
-          <sysConfigItemOfAddCamera
-            :origin-scene-checked-list="CameraSRSData.sceneTemplateList"
-            @update:scene-checked-list="handleUpdateSceneTemplateList"
-          />
-        </el-form-item>
-        <el-form-item label="备注:" prop="remark" style="width: 766px">
-          <el-input v-model="CameraSRSData.remark" placeholder="请输入备注" style="width: 655px" />
-        </el-form-item>
-      </el-form>
-    </div>
-    <span class="pop-footer">
-      <el-button @click="handleCancel">取消</el-button>
-      <el-button type="primary" @click="handleConfirm">确定</el-button>
-    </span>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { onBeforeMount, ref } from 'vue';
-  import { cloneDeep } from 'lodash-es';
-  import { ElIcon, ElTooltip } from 'element-plus';
-  import { InfoFilled } from '@element-plus/icons-vue';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import { serviceTypeSelect, standardTypeSelect } from '@/types/camera/constant';
-  import useNvrDevice from '../hooks/useNvrDevice';
-  import useTreeWorkspaceInfo from '../hooks/useTreeWorkspaceInfo';
-  import sysConfigItemOfAddCamera, { getSceneCheckedValues } from './sysConfigItemOfAddCamera.vue';
-
-  const props = defineProps<{ formData?: CameraDetailServer | null }>();
-  const emits = defineEmits(['cancel-execute', 'confirm-execute']);
-
-  const treeWorkspaceInfo = useTreeWorkspaceInfo();
-  const { workspaceInfo, getWorkspaceFromTreeInfo, getWorkspaceIdFromTreeNode } = treeWorkspaceInfo;
-
-  const nvrDeviceInfo = useNvrDevice();
-  const { nvrDevice, getNvrDevice } = nvrDeviceInfo;
-
-  const IPFormRef = ref();
-
-  type CameraDetailForm = CameraDetailServer & { workspaceIdStr?: string };
-  const CameraSRSData = ref<CameraDetailForm>({} as CameraDetailForm);
-
-  const validateSceneTemplate = (_rule, value, callback) => {
-    if (Object.keys(sceneCheckedDataRef.value).length === 0)
-      callback(new Error('请至少选择一个业务场景及对应应用模版'));
-    else if (value && Object.keys(sceneCheckedDataRef.value).length > value.length)
-      callback(new Error('请完成已选业务场景中的应用模版选择'));
-    else callback();
-  };
-
-  const rules = {
-    name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
-    code: [{ required: true, message: '请输入设备ID', trigger: 'blur' }],
-    cameraIp: [{ required: true, message: '请输入IP地址', trigger: 'blur' }],
-    rtspUrl: [{ required: true, message: '请输入流媒体地址', trigger: 'blur' }],
-    sceneTemplateList: [{ required: true, validator: validateSceneTemplate, trigger: 'blur' }],
-    workspaceIdStr: [{ required: true, message: '请选择工位', trigger: 'blur' }],
-    videoStandard: [{ required: true, message: '请选择视频编码标准', trigger: 'blur' }],
-  };
-
-  const sceneCheckedDataRef = ref({} as Record<number, boolean>);
-  const handleUpdateSceneTemplateList = (sceneTemplateData, sceneCheckedData) => {
-    sceneCheckedDataRef.value = sceneCheckedData;
-    CameraSRSData.value.sceneTemplateList = sceneTemplateData;
-  };
-
-  const handleCancel = () => {
-    emits('cancel-execute');
-  };
-
-  const handleConfirm = () => {
-    IPFormRef.value.validate((valid) => {
-      if (valid) {
-        const copyData = cloneDeep(CameraSRSData.value);
-        if (CameraSRSData.value.workspaceIdStr)
-          copyData.workspaceId = Number(getWorkspaceIdFromTreeNode(CameraSRSData.value.workspaceIdStr));
-        delete (copyData as any).principal;
-        copyData.sourceType = 'RTSP';
-        emits('confirm-execute', copyData);
-      }
-    });
-  };
-
-  const handleTreeSelect = (node) => {
-    if (node.disabled) return;
-    CameraSRSData.value.principal = node.principalName ? node.principalName : '该工位暂无负责人';
-    CameraSRSData.value.workshopId = node.workshopId;
-  };
-
-  onBeforeMount(() => {
-    getNvrDevice();
-    getWorkspaceFromTreeInfo();
-    if (props.formData) {
-      CameraSRSData.value = props.formData;
-      CameraSRSData.value.workspaceIdStr = `workspace-${props.formData.workspaceId}`;
-      sceneCheckedDataRef.value = getSceneCheckedValues(props.formData.sceneTemplateList);
-    }
-  });
-</script>
-
-<style scoped>
-  .ip-form {
-    width: 768px;
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    align-content: space-around;
-  }
-
-  .pop-footer {
-    position: absolute;
-    right: 24px;
-    bottom: 27px;
-    display: flex;
-    justify-content: flex-end;
-  }
-
-  :deep(.el-form-item__label) {
-    font-size: 14px;
-    color: #363636;
-    padding: 0;
-  }
-
-  :deep(.el-form--inline .el-form-item) {
-    display: flex;
-    margin-right: 0;
-    margin-bottom: 28px;
-  }
-</style>

+ 0 - 272
src/views/cameras/overview/components/BatchEditCamera.vue

@@ -1,272 +0,0 @@
-<template>
-  <div>
-    <div class="overlay" v-if="cardVisible"></div>
-    <el-card v-if="cardVisible" class="pop-card">
-      <template #header>
-        <div class="flex justify-between items-center pop-head">
-          <div style="font-size: 16px; font-weight: 600">批量修改</div>
-          <el-icon
-            :size="18"
-            class="mr-3"
-            @click="
-              () => {
-                emits('close');
-              }
-            "
-            style="cursor: pointer"
-          >
-            <Close />
-          </el-icon>
-        </div>
-      </template>
-      <div class="upload-content">
-        <el-upload
-          ref="upload"
-          style="width: 384px; height: 192px; border-radius: 8px"
-          :headers="getHeaders()"
-          :multiple="false"
-          :limit="1"
-          drag
-          :action="actionUrl"
-          :with-credentials="true"
-          :auto-upload="false"
-          :before-upload="beforeUpload"
-          :on-success="handleUploadSuccess"
-          :on-exceed="handleExceed"
-          :on-change="handleChange"
-          :on-remove="handleRemove"
-        >
-          <el-icon class="el-icon--upload" style="width: 33px; height: 42px; color: #409efc">
-            <Document />
-          </el-icon>
-          <div class="el-upload__text">
-            <div style="font-size: 12px; color: red; margin-bottom: 5px"
-              >请先导出需要修改的相机信息,并在原模版上修改后在此导入文件</div
-            >
-            <div style="font-size: 16px">点击或将文件拖拽到这里上传</div>
-            <div style="font-size: 12px; color: rgba(0, 0, 0, 0.45); margin-top: 5px"
-              >文件支持.xlsx .xls格式,仅支持上传一个文件</div
-            >
-          </div>
-        </el-upload>
-        <div style="margin-top: 72px; margin-left: 380px; display: flex">
-          <el-button type="primary" @click="handleImport" :disabled="isImportEnable">导入</el-button>
-        </div>
-      </div>
-    </el-card>
-
-    <el-dialog
-      v-model="DialogVisibleErr"
-      title="Warning"
-      width="50%"
-      align-center
-      @close="
-        () => {
-          emits('update');
-        }
-      "
-    >
-      <template #header>
-        <el-icon :size="24" color="#f2b20a" style="margin: 0 5px 2px">
-          <WarnTriangleFilled />
-        </el-icon>
-        <div class="header-text">批量修改</div>
-      </template>
-      <div class="sum-count">
-        <div
-          >修改成功:<span class="succ-sum">{{ sucCount }}</span> 条</div
-        >
-        <div
-          >修改失败:<span class="err-sum">{{ errCount }}</span> 条</div
-        >
-      </div>
-      <div class="err-info">
-        <ul v-for="(item, index) in errDetail" :key="index">
-          <li v-html="item"></li>
-        </ul>
-      </div>
-      <template #footer>
-        <el-button type="primary" @click="handleErrComfirm"> 确定 </el-button>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed, ref } from 'vue';
-  import { genFileId, ElMessage } from 'element-plus';
-  import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
-  import { Close, Document, WarnTriangleFilled } from '@element-plus/icons-vue';
-  import { useGlobSetting } from '@/hooks/setting';
-  import urlJoin from 'url-join';
-  import { getHeaders } from '@/utils/http/axios';
-
-  const emits = defineEmits(['close', 'update']);
-
-  const upload = ref<UploadInstance>();
-  const cardVisible = ref<boolean>(true);
-  const isImportEnable = ref<boolean>(true);
-  const DialogVisibleErr = ref<boolean>(false);
-  const sucCount = ref<number>(0);
-  const errCount = ref<number>(0);
-  const errDetail = ref<string[]>([]);
-
-  const { urlPrefix } = useGlobSetting();
-
-  const actionUrl = computed(() => {
-    return urlJoin(urlPrefix, `/admin/cameraConfig/updateCameraList`);
-  });
-
-  // 导入
-  const handleImport = async () => {
-    upload.value!.submit();
-  };
-
-  // 上传文件之前的钩子,参数为上传的文件。即上传之前验证文件类型/后缀
-  const beforeUpload = (file) => {
-    const isExcel = /\.(xlsx|xls)$/.test(file.name.toLowerCase());
-    if (!isExcel) {
-      // 提示用户选择正确的文件类型
-      ElMessage({
-        message: '仅支持上传.xlsx .xls格式文件',
-        type: 'error',
-      });
-      return false; // 阻止上传
-    }
-    return true; // 允许上传
-  };
-
-  const handleUploadSuccess = (response, _file, _fileList) => {
-    console.log(response);
-    sucCount.value = response.data.successCount;
-    errCount.value = response.data.failCount;
-    errDetail.value = response.data.resultList;
-
-    try {
-      if (errDetail.value.length > 0) {
-        errDetail.value.forEach((item, index) => {
-          if (item.indexOf('【修改失败】') >= 0) {
-            errDetail.value[index] = item.replace('【修改失败】', '<span style="color: #ff4d4f">【修改失败】</span>');
-          } else if (item.indexOf('【修改成功】') >= 0) {
-            errDetail.value[index] = item.replace('【修改成功】', '<span style="color: #52c41a">【修改成功】</span>');
-          }
-        });
-      }
-
-      if (sucCount.value != 0 && errCount.value === 0 && errDetail.value.length === 0) {
-        ElMessage({
-          message: '批量修改成功', // 1.全部修改成功 —— failCount === 0
-          type: 'success',
-        });
-        emits('update');
-      } else {
-        DialogVisibleErr.value = true; // 2.有错误 —— 显示错误dialog
-      }
-      cardVisible.value = false;
-    } catch (error) {
-      ElMessage({
-        message: '系统错误',
-        type: 'error',
-      });
-      emits('update');
-    }
-  };
-
-  const handleErrComfirm = () => {
-    DialogVisibleErr.value = false;
-    emits('update');
-  };
-
-  // 当超出只能上传一个文件的限制时,自动替换上一个文件
-  const handleExceed: UploadProps['onExceed'] = (files) => {
-    upload.value!.clearFiles();
-    const file = files[0] as UploadRawFile;
-    file.uid = genFileId();
-    upload.value!.handleStart(file);
-  };
-
-  const handleChange = () => {
-    isImportEnable.value = false;
-  };
-
-  const handleRemove = () => {
-    isImportEnable.value = true;
-  };
-</script>
-
-<style scoped>
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    z-index: 1000;
-  }
-
-  :deep(.el-dialog) {
-    padding: 0px;
-    border-radius: 5px;
-
-    .el-dialog__header {
-      display: flex;
-      align-items: flex-end;
-      height: 70px;
-      padding: 0px 0px 10px 10px;
-      border-bottom: 1px solid #e7e7e7;
-
-      .header-text {
-        font-size: 20px;
-      }
-    }
-
-    .el-dialog__headerbtn {
-      top: 22px;
-
-      .el-dialog__close {
-        color: black;
-      }
-    }
-
-    .el-dialog__body {
-      padding: 20px;
-
-      .sum-count {
-        margin: 10px 0 20px 20px;
-        font-size: 20px;
-        font-weight: 600;
-
-        .succ-sum {
-          color: #52c41a;
-        }
-
-        .err-sum {
-          color: #ff4d4f;
-        }
-      }
-
-      .err-info {
-        height: 200px;
-        margin-left: 20px;
-        overflow: auto;
-      }
-    }
-
-    .el-dialog__footer {
-      margin: 0 20px 20px 0;
-    }
-  }
-
-  li {
-    font-size: 14px;
-    margin-bottom: 2px;
-  }
-</style>

+ 0 - 333
src/views/cameras/overview/components/BatchImportCamera.vue

@@ -1,333 +0,0 @@
-<template>
-  <div>
-    <div class="overlay" v-if="cardVisible"></div>
-    <el-card v-if="cardVisible" class="pop-card">
-      <template #header>
-        <div class="flex justify-between items-center pop-head">
-          <div style="font-size: 16px; font-weight: 600">批量导入</div>
-          <el-icon
-            :size="18"
-            class="mr-3"
-            @click="
-              () => {
-                emits('close');
-              }
-            "
-            style="cursor: pointer"
-          >
-            <Close />
-          </el-icon>
-        </div>
-      </template>
-      <div class="upload-content">
-        <el-upload
-          ref="upload"
-          style="width: 384px; height: 192px; border-radius: 8px"
-          :headers="getHeaders()"
-          :multiple="false"
-          :limit="1"
-          drag
-          :action="actionUrl"
-          :with-credentials="true"
-          :auto-upload="false"
-          :before-upload="beforeUpload"
-          :on-success="handleUploadSuccess"
-          :on-exceed="handleExceed"
-          :on-change="handleChange"
-          :on-remove="handleRemove"
-        >
-          <el-icon class="el-icon--upload" style="width: 33px; height: 42px; color: #409efc">
-            <Document />
-          </el-icon>
-          <div class="el-upload__text">
-            <div style="font-size: 12px; color: red; margin-bottom: 5px">请下载模板并按要求填写后上传</div>
-            <div style="font-size: 16px">点击或将文件拖拽到这里上传</div>
-            <div style="font-size: 12px; color: rgba(0, 0, 0, 0.45); margin-top: 5px"
-              >文件支持.xlsx .xls格式,仅支持上传一个文件</div
-            >
-          </div>
-        </el-upload>
-        <div style="margin-top: 72px; margin-left: 128px; display: flex">
-          <el-icon :size="18" style="margin-top: 7px">
-            <Download />
-          </el-icon>
-          <el-tooltip content="点击下载场景字段对应的code信息" placement="top" effect="light">
-            <span
-              style="color: #409efc; margin-top: 6px; margin-right: 12px; cursor: pointer"
-              @click="handleDownloadSceneCode"
-              >场景code信息查询</span
-            >
-          </el-tooltip>
-          <el-button @click="handleDownloadTemplate">下载模板</el-button>
-          <el-button type="primary" @click="handleImport" :disabled="isImportEnable">导入</el-button>
-        </div>
-      </div>
-    </el-card>
-
-    <el-dialog
-      v-model="DialogVisibleErr"
-      title="Warning"
-      width="50%"
-      align-center
-      @close="
-        () => {
-          emits('update');
-        }
-      "
-    >
-      <template #header>
-        <el-icon :size="24" color="#f2b20a" style="margin: 0 5px 2px">
-          <WarnTriangleFilled />
-        </el-icon>
-        <div class="header-text">添加提示</div>
-      </template>
-      <div class="sum-count">
-        成功上传 <span class="succ-sum">{{ sucCount }}</span> 条, 失败 <span class="err-sum">{{ errCount }}</span> 条
-      </div>
-      <div class="err-info">
-        <ul v-for="(item, index) in errDetail" :key="index">
-          <li v-html="item"></li>
-        </ul>
-      </div>
-      <template #footer>
-        <el-button type="primary" @click="handleErrComfirm"> 确定 </el-button>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed, ref } from 'vue';
-  import axios, { AxiosRequestConfig } from 'axios';
-  import { genFileId, ElMessage } from 'element-plus';
-  import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
-  import { Close, Document, WarnTriangleFilled, Download } from '@element-plus/icons-vue';
-  import { useGlobSetting } from '@/hooks/setting';
-  import urlJoin from 'url-join';
-  import { getHeaders } from '@/utils/http/axios';
-
-  const emits = defineEmits(['close', 'update']);
-
-  const upload = ref<UploadInstance>();
-  const cardVisible = ref<boolean>(true);
-  const isImportEnable = ref<boolean>(true);
-  const DialogVisibleErr = ref<boolean>(false);
-  const sucCount = ref<number>(0);
-  const errCount = ref<number>(0);
-  const errDetail = ref<string[]>([]);
-
-  const { urlPrefix } = useGlobSetting();
-
-  const actionUrl = computed(() => {
-    return urlJoin(urlPrefix, `/admin/cameraConfig/uploadCameraList`);
-  });
-
-  // 下载场景code信息查询表
-  const handleDownloadSceneCode = async () => {
-    try {
-      const config: AxiosRequestConfig = {
-        headers: getHeaders(),
-        responseType: 'blob',
-      };
-      const response = await axios.post(urlPrefix + '/admin/cameraConfig/exportSceneCodeInfo', null, config);
-      const blob = new Blob([response.data], {
-        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-      });
-      // 创建下载链接
-      let downloadLink: HTMLAnchorElement | null = document.createElement('a');
-      const url = window.URL.createObjectURL(blob);
-      downloadLink.href = url;
-      downloadLink.download = '场景code信息查询.xlsx';
-      downloadLink.click();
-      // 移除下载链接
-      window.URL.revokeObjectURL(url);
-      downloadLink = null;
-    } catch (error) {
-      console.error('Error downloading file:', error);
-    }
-  };
-
-  // 下载模板
-  const handleDownloadTemplate = async () => {
-    try {
-      const config: AxiosRequestConfig = {
-        headers: getHeaders(),
-        responseType: 'blob',
-      };
-      const response = await axios.get(
-        './skyeye-file-upload/skyeye-v4/CAMERALIST_TEMPLATE/camera-upload-template.xlsx',
-        config,
-      );
-      const blob = new Blob([response.data], {
-        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-      });
-      // 创建下载链接
-      let downloadLink: HTMLAnchorElement | null = document.createElement('a');
-      const url = window.URL.createObjectURL(blob);
-      downloadLink.href = url;
-      downloadLink.download = '相机批量添加.xlsx';
-      downloadLink.click();
-      // 移除下载链接
-      window.URL.revokeObjectURL(url);
-      downloadLink = null;
-    } catch (error) {
-      console.error('Error downloading file:', error);
-    }
-  };
-
-  // 导入
-  const handleImport = async () => {
-    upload.value!.submit();
-  };
-
-  // 上传文件之前的钩子,参数为上传的文件。即上传之前验证文件类型/后缀
-  const beforeUpload = (file) => {
-    const isExcel = /\.(xlsx|xls)$/.test(file.name.toLowerCase());
-    if (!isExcel) {
-      // 提示用户选择正确的文件类型
-      ElMessage({
-        message: '仅支持上传.xlsx .xls格式文件',
-        type: 'error',
-      });
-      return false; // 阻止上传
-    }
-    return true; // 允许上传
-  };
-
-  const handleUploadSuccess = (response, _file, _fileList) => {
-    console.log(response);
-    sucCount.value = response.data.successCount;
-    errCount.value = response.data.failCount;
-    errDetail.value = response.data.errorList;
-
-    try {
-      if (errDetail.value.length > 0) {
-        errDetail.value.forEach((item, index) => {
-          if (item.indexOf('【添加失败】') >= 0) {
-            errDetail.value[index] = item.replace('【添加失败】', '<span style="color: #ff4d4f">【添加失败】</span>');
-          } else if (item.indexOf('【添加成功】') >= 0) {
-            errDetail.value[index] = item.replace('【添加成功】', '<span style="color: #52c41a">【添加成功】</span>');
-          }
-        });
-      }
-
-      if (sucCount.value != 0 && errCount.value === 0 && errDetail.value.length === 0) {
-        ElMessage({
-          message: '添加成功', // 1.全部添加成功 —— failCount === 0
-          type: 'success',
-        });
-        emits('update');
-      } else {
-        DialogVisibleErr.value = true; // 2.有错误 —— 显示错误dialog
-      }
-      cardVisible.value = false;
-    } catch (error) {
-      ElMessage({
-        message: response.message,
-        type: 'error',
-      });
-      emits('update');
-    }
-  };
-
-  const handleErrComfirm = () => {
-    DialogVisibleErr.value = false;
-    emits('update');
-  };
-
-  // 当超出只能上传一个文件的限制时,自动替换上一个文件
-  const handleExceed: UploadProps['onExceed'] = (files) => {
-    upload.value!.clearFiles();
-    const file = files[0] as UploadRawFile;
-    file.uid = genFileId();
-    upload.value!.handleStart(file);
-  };
-
-  const handleChange = () => {
-    isImportEnable.value = false;
-  };
-
-  const handleRemove = () => {
-    isImportEnable.value = true;
-  };
-</script>
-
-<style scoped>
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    z-index: 1000;
-  }
-  .upload-content {
-    margin-left: 90px;
-    margin-top: 36px;
-  }
-
-  :deep(.el-dialog) {
-    padding: 0px;
-    border-radius: 5px;
-
-    .el-dialog__header {
-      display: flex;
-      align-items: flex-end;
-      height: 70px;
-      padding: 0px 0px 10px 10px;
-      border-bottom: 1px solid #e7e7e7;
-
-      .header-text {
-        font-size: 20px;
-      }
-    }
-
-    .el-dialog__headerbtn {
-      top: 22px;
-
-      .el-dialog__close {
-        color: black;
-      }
-    }
-
-    .el-dialog__body {
-      padding: 20px;
-
-      .sum-count {
-        margin: 10px 0 20px 20px;
-        font-size: 20px;
-
-        .succ-sum {
-          color: #52c41a;
-        }
-
-        .err-sum {
-          color: #ff4d4f;
-        }
-      }
-
-      .err-info {
-        height: 200px;
-        margin-left: 20px;
-        overflow: auto;
-      }
-    }
-
-    .el-dialog__footer {
-      margin: 0 20px 20px 0;
-    }
-  }
-
-  li {
-    font-size: 14px;
-    margin-bottom: 2px;
-  }
-</style>

+ 0 - 147
src/views/cameras/overview/components/CameraAddPopover.vue

@@ -1,147 +0,0 @@
-<template>
-  <div class="overlay" v-if="props.modelValue"></div>
-  <el-card v-if="props.modelValue" class="pop-card">
-    <template #header>
-      <div class="flex justify-between items-center pop-head">
-        <span class="pop-head-name">添加相机</span>
-        <div class="flex pop-head-tabs">
-          <div
-            v-for="item in cameraAddType"
-            :key="item.value"
-            class="flex justify-center items-center tab-item"
-            :class="{ 'tab-item-active': item.value === addType }"
-            @click="addType = item.value"
-          >
-            {{ item.label }}
-          </div>
-        </div>
-        <el-icon :size="16" class="mr-5" @click="updateValue(false)" style="cursor: pointer"><Close /></el-icon>
-      </div>
-    </template>
-    <div class="pop-content">
-      <IPAddCamera v-if="addType === 'ip'" @cancel-execute="updateValue(false)" @confirm-execute="onAddCamera" />
-      <NVRAddCamera v-if="addType === 'nvr'" @cancel-execute="updateValue(false)" @confirm-execute="onAddNVRCamera" />
-      <SRSAddCamera v-if="addType === 'srs'" @cancel-execute="updateValue(false)" @confirm-execute="onAddSRSCamera" />
-      <RangeAddCamera v-if="addType === 'ipRange'" @cancel-execute="updateValue(false)" />
-    </div>
-  </el-card>
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  import { cameraAddType } from '@/types/camera/constant';
-  import { Close } from '@element-plus/icons-vue';
-  import { ElMessage } from 'element-plus';
-  import IPAddCamera from './AddCameraByIP.vue';
-  import SRSAddCamera from './AddCameraBySRS.vue';
-  import RangeAddCamera from './AddCameraByRange.vue';
-  import NVRAddCamera from './AddCameraByNVR.vue';
-  import useCameraOverview from '../stores/useCameraOverview';
-
-  const props = defineProps<{ modelValue: boolean }>();
-
-  const emits = defineEmits(['update:modelValue']);
-
-  const cameraOverview = useCameraOverview();
-  const { addCamera, addNVRCamera, addSRSCamera } = cameraOverview;
-
-  const addType = ref(cameraAddType[0].value);
-
-  const updateValue = (value) => {
-    addType.value = cameraAddType[0].value;
-    emits('update:modelValue', value);
-  };
-
-  const onAddCamera = (data) => {
-    addCamera(data).then(() => {
-      ElMessage.success('添加成功');
-      updateValue(false);
-    });
-  };
-
-  const onAddNVRCamera = (data) => {
-    addNVRCamera(data).then(() => {
-      ElMessage.success('添加成功');
-      updateValue(false);
-    });
-  };
-
-  const onAddSRSCamera = (data) => {
-    addSRSCamera(data).then(() => {
-      ElMessage.success('添加成功');
-      updateValue(false);
-    });
-  };
-</script>
-
-<style scoped lang="scss">
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    z-index: 1000;
-    width: calc(100% - 800px);
-    height: 622px;
-  }
-
-  .pop-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-
-    &-tabs {
-      margin-top: 18px;
-
-      :first-child {
-        border-radius: 8px 0px 0px 0px;
-      }
-
-      :last-child {
-        border-radius: 0px 8px 0px 0px;
-      }
-    }
-  }
-
-  .tab-item {
-    width: 188px;
-    height: 38px;
-    background: #fafafa;
-    border: 1px solid #d9d9d9;
-    cursor: pointer;
-
-    &-active {
-      background: #e2eefe;
-      border: 1px solid #1890ff;
-    }
-  }
-
-  .pop-content {
-    height: 480px;
-    display: flex;
-    justify-content: center;
-    padding: 35px;
-    overflow: auto;
-  }
-
-  :deep(.el-card__header) {
-    padding: 0;
-  }
-  :deep(.el-card__body) {
-    padding: 0;
-  }
-</style>

+ 0 - 122
src/views/cameras/overview/components/CameraEditNVRPopover.vue

@@ -1,122 +0,0 @@
-<template>
-  <div class="overlay" v-if="props.modelValue"></div>
-  <el-card v-if="props.modelValue" class="pop-card">
-    <template #header>
-      <div class="flex justify-between items-center pop-head">
-        <span class="pop-head-name">编辑相机</span>
-        <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
-      </div>
-    </template>
-    <div class="pop-content">
-      <NVRAddCamera
-        :form-data="props.editData"
-        @cancel-execute="updateValue(false)"
-        @confirm-execute="onEditCamera"
-      />
-    </div>
-  </el-card>
-</template>
-
-<script setup lang="ts">
-  import { ElMessage } from 'element-plus';
-  import { Close } from '@element-plus/icons-vue';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import useCameraOverview from '../stores/useCameraOverview';
-  import NVRAddCamera from './AddCameraByNVR.vue';
-
-  const props = defineProps<{
-    modelValue: boolean;
-    editData?: CameraDetailServer | null;
-    confirmEvent?: (data) => any;
-  }>();
-
-  const emits = defineEmits(['update:modelValue']);
-
-  const cameraOverview = useCameraOverview();
-  const { editCamera, getCameraItems } = cameraOverview;
-
-  const updateValue = (value) => {
-    emits('update:modelValue', value);
-  };
-
-  const onEditCamera = (data) => {
-    const temp = {
-      id: data.id,
-      nvrId: data.nvrId,
-      name: data.name,
-      code: data.code,
-      nvrChannel: data.nvrChannel,
-      videoServiceType: data.videoServiceType,
-      sceneTemplateList: data.sceneTemplateList,
-      workshopId: data.workshopId,
-      workspaceId: data.workspaceId,
-      cameraType: data.cameraType,
-      videoStandard: data.videoStandard,
-      remark: data.remark,
-      sourceType: data.sourceType,
-    };
-    editCamera(temp)
-      .then((res) => {
-        if (res.code === 200) {
-          updateValue(false);
-          ElMessage({
-            message: '修改成功',
-            type: 'success',
-          });
-          getCameraItems();
-        } else {
-          return Promise.reject(res.msg || res.message);
-        }
-      })
-      .catch((error) => {
-        ElMessage.error(error);
-      });
-  };
-</script>
-
-<style scoped lang="scss">
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    z-index: 1000;
-    width: calc(100% - 800px);
-    height: 622px;
-  }
-
-  .pop-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-  }
-
-  .pop-content {
-    height: 480px;
-    display: flex;
-    justify-content: center;
-    padding: 35px;
-    overflow: auto;
-  }
-
-  :deep(.el-card__header) {
-    padding: 0;
-  }
-  :deep(.el-card__body) {
-    padding: 0;
-  }
-</style>

+ 0 - 125
src/views/cameras/overview/components/CameraEditPopover.vue

@@ -1,125 +0,0 @@
-<template>
-  <div class="overlay" v-if="props.modelValue"></div>
-  <el-card v-if="props.modelValue" class="pop-card">
-    <template #header>
-      <div class="flex justify-between items-center pop-head">
-        <span class="pop-head-name">编辑相机</span>
-        <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
-      </div>
-    </template>
-    <div class="pop-content">
-      <IPAddCamera
-        :form-data="props.editData"
-        @cancel-execute="updateValue(false)"
-        @confirm-execute="onEditCamera"
-      />
-    </div>
-  </el-card>
-</template>
-
-<script setup lang="ts">
-  import { ElMessage } from 'element-plus';
-  import { Close } from '@element-plus/icons-vue';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import useCameraOverview from '../stores/useCameraOverview';
-  import IPAddCamera from './AddCameraByIP.vue';
-
-  const props = defineProps<{
-    modelValue: boolean;
-    editData?: CameraDetailServer | null;
-    confirmEvent?: (data) => any;
-  }>();
-
-  const emits = defineEmits(['update:modelValue']);
-
-  const cameraOverview = useCameraOverview();
-  const { editCamera, getCameraItems } = cameraOverview;
-
-  const updateValue = (value) => {
-    emits('update:modelValue', value);
-  };
-
-  const onEditCamera = (data) => {
-    const temp = {
-      id: data.id,
-      name: data.name,
-      code: data.code,
-      cameraIp: data.cameraIp,
-      cameraPort: data.cameraPort,
-      username: data.username,
-      password: data.password,
-      cameraType: data.cameraType,
-      videoServiceType: data.videoServiceType,
-      sceneTemplateList: data.sceneTemplateList,
-      workshopId: data.workshopId,
-      workspaceId: data.workspaceId,
-      videoStandard: data.videoStandard,
-      remark: data.remark,
-      sourceType: data.sourceType,
-      nvrId: data.nvrId,
-    };
-    editCamera(temp)
-      .then((res) => {
-        if (res.code === 200) {
-          updateValue(false);
-          ElMessage({
-            message: '修改成功',
-            type: 'success',
-          });
-          getCameraItems();
-        } else {
-          return Promise.reject(res.msg || res.message);
-        }
-      })
-      .catch((error) => {
-        ElMessage.error(error);
-      });
-  };
-</script>
-
-<style scoped lang="scss">
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    z-index: 1000;
-    width: calc(100% - 800px);
-    height: 622px;
-  }
-
-  .pop-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-  }
-
-  .pop-content {
-    height: 480px;
-    display: flex;
-    justify-content: center;
-    padding: 35px;
-    overflow: auto;
-  }
-
-  :deep(.el-card__header) {
-    padding: 0;
-  }
-  :deep(.el-card__body) {
-    padding: 0;
-  }
-</style>

+ 0 - 144
src/views/cameras/overview/components/CameraEditSRSPopover.vue

@@ -1,144 +0,0 @@
-<template>
-  <div class="overlay" v-if="props.modelValue"></div>
-  <el-card v-if="props.modelValue" class="pop-card">
-    <template #header>
-      <div class="flex justify-between items-center pop-head">
-        <span class="pop-head-name">编辑相机(通过rtsp添加)</span>
-
-        <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
-      </div>
-    </template>
-    <div class="pop-content">
-      <SRSAddCamera
-        :form-data="props.editData!"
-        @cancel-execute="updateValue(false)"
-        @confirm-execute="onUpdateSRSCamera"
-      />
-    </div>
-  </el-card>
-</template>
-
-<script setup lang="ts">
-  import { Close } from '@element-plus/icons-vue';
-  import SRSAddCamera from './AddCameraBySRS.vue';
-  import useCameraOverview from '../stores/useCameraOverview';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import { ElMessage } from 'element-plus';
-
-  const props = defineProps<{ modelValue: boolean; editData?: CameraDetailServer }>();
-
-  const emits = defineEmits(['update:modelValue']);
-
-  const cameraOverview = useCameraOverview();
-  const { editCamera, getCameraItems } = cameraOverview;
-
-  const updateValue = (value) => {
-    emits('update:modelValue', value);
-  };
-
-  const onUpdateSRSCamera = (data) => {
-    const temp = {
-      id: data.id,
-      name: data.name,
-      code: data.code,
-      rtspUrl: data.rtspUrl,
-      cameraIp: data.cameraIp,
-      videoServiceType: data.videoServiceType,
-      sceneTemplateList: data.sceneTemplateList,
-      workshopId: data.workshopId,
-      workspaceId: data.workspaceId,
-      videoStandard: data.videoStandard,
-      remark: data.remark,
-      sourceType: data.sourceType,
-      nvrId: data.nvrId,
-    };
-    editCamera(temp)
-      .then((res) => {
-        if (res.code === 200) {
-          updateValue(false);
-          ElMessage({
-            message: '修改成功',
-            type: 'success',
-          });
-          getCameraItems();
-        } else {
-          return Promise.reject(res.msg || res.message);
-        }
-      })
-      .catch((error) => {
-        ElMessage.error(error);
-      });
-  };
-</script>
-
-<style scoped lang="scss">
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    z-index: 1000;
-    width: calc(100% - 800px);
-    height: 622px;
-  }
-
-  .pop-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-
-    &-tabs {
-      margin-top: 18px;
-
-      :first-child {
-        border-radius: 8px 0px 0px 0px;
-      }
-
-      :last-child {
-        border-radius: 0px 8px 0px 0px;
-      }
-    }
-  }
-
-  .tab-item {
-    width: 188px;
-    height: 38px;
-    background: #fafafa;
-    border: 1px solid #d9d9d9;
-    cursor: pointer;
-
-    &-active {
-      background: #e2eefe;
-      border: 1px solid #1890ff;
-    }
-  }
-
-  .pop-content {
-    height: 480px;
-    display: flex;
-    justify-content: center;
-    padding: 35px;
-    overflow: auto;
-  }
-
-  :deep(.el-card__header) {
-    padding: 0;
-  }
-  :deep(.el-card__body) {
-    padding: 0;
-  }
-</style>

+ 0 - 85
src/views/cameras/overview/components/CameraEditshared.vue

@@ -1,85 +0,0 @@
-<template>
-  <el-card v-if="props.modelValue" class="pop-card">
-    <template #header>
-      <div class="flex justify-between items-center pop-head">
-        <span class="pop-head-name">编辑相机</span>
-        <el-icon :size="16" class="mr-3" @click="updateValue"><Close /></el-icon>
-      </div>
-    </template>
-    <div class="pop-content">
-      <EditSharedCamera @close-edit="updateValue" :form-data="props.editData" />
-    </div>
-  </el-card>
-</template>
-
-<script setup lang="ts">
-  import { Close } from '@element-plus/icons-vue';
-  import EditSharedCamera from './EditSharedCamera.vue';
-  import { CameraShareType } from '@/api/camera/camera-share';
-
-  const props = defineProps<{ modelValue: boolean; editData: CameraShareType }>();
-
-  const emits = defineEmits(['update:modelValue']);
-
-  const updateValue = () => {
-    emits('update:modelValue', false as boolean);
-  };
-</script>
-
-<style scoped lang="scss">
-  .pop-card {
-    position: relative;
-    margin-left: 21px !important;
-  }
-
-  .pop-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-
-    &-tabs {
-      margin-top: 18px;
-
-      :first-child {
-        border-radius: 8px 0px 0px 0px;
-      }
-
-      :last-child {
-        border-radius: 0px 8px 0px 0px;
-      }
-    }
-  }
-
-  .tab-item {
-    width: 188px;
-    height: 38px;
-    background: #fafafa;
-    border: 1px solid #d9d9d9;
-    cursor: pointer;
-
-    &-active {
-      background: #e2eefe;
-      border: 1px solid #1890ff;
-    }
-  }
-
-  .pop-content {
-    height: 480px;
-    display: flex;
-    justify-content: center;
-    padding: 35px;
-    overflow: auto;
-  }
-
-  :deep(.el-card__header) {
-    padding: 0;
-  }
-  :deep(.el-card__body) {
-    padding: 0;
-  }
-</style>

+ 0 - 382
src/views/cameras/overview/components/CameraOverviewPopover.vue

@@ -1,382 +0,0 @@
-<template>
-  <el-dialog
-    v-model="dialogVisible"
-    width="719"
-    center
-    align-center
-    class="camera-overview-popover--custom"
-    :close-on-click-modal="false"
-    @close="emits('update:dialogVisible', false)"
-  >
-    <template #title>
-      <div class="camera-overview-popover--custom__title">
-        <span>预览-{{ overviewCameraData.name }}</span>
-        <img :src="FullScreenIcon" alt="全屏" @click="toggle" />
-      </div>
-    </template>
-    <div class="camera-overview-popover--custom__content">
-      <main class="main" ref="videoContainerRef">
-        <div class="cameraVideo" ref="cameraVideoRef">
-          <CameraLiveVideo ref="cameraLiveVideoRef" />
-        </div>
-        <div class="presetAddWrapper" v-if="!!overviewCameraData.isPtz">
-          <CameraViewScale @update:ControlPerspective="activePresetToken = ''" />
-          <CameraDirectionControl @update:ControlPerspective="activePresetToken = ''" />
-          <ElButton
-            type="primary"
-            style="margin-top: 20px; width: 100px"
-            @click="handleAddPreset"
-            v-show="displayPresetList.length < 10"
-            >添加预置位</ElButton
-          >
-        </div>
-      </main>
-      <footer class="footer" v-if="!!overviewCameraData.isPtz && presetList.length > 0">
-        <div class="footer-header">
-          <div class="edit-preset-position-icon-wrapper" @click="toggleEditMode">
-            <img :src="isEditMode ? EditPresetPositionFocusIcon : EditPresetPositionIcon" alt="编辑预置位" />
-            <span v-show="isEditMode">退出编辑</span>
-          </div>
-          <div class="pagination-control" v-if="displayPresetList.length > 0">
-            <el-button type="text" :disabled="currentPage === 1" @click="prevPage" :icon="ArrowLeft" />
-            <span>{{ currentPage }}/{{ totalPages }}</span>
-            <el-button type="text" :disabled="currentPage === totalPages" @click="nextPage" :icon="ArrowRight" />
-          </div>
-        </div>
-        <div class="preset-position-list">
-          <div
-            class="preset-position-item"
-            v-for="item in currentPageItems"
-            :key="item.presetToken"
-            :class="{ 'active-preset': activePresetToken === item.presetToken }"
-          >
-            <img
-              :src="item.imageUrl || PresetPositionItem"
-              alt="预置位"
-              style="cursor: pointer"
-              @click="handleGoToPreset(item)"
-            />
-            <img
-              v-if="isEditMode"
-              :src="DeletePresetPositionIcon"
-              alt="删除预置位"
-              class="delete-preset-position-icon"
-              @click="handleDeletePreset(item)"
-            />
-            <span class="preset-position-name" v-if="item.presetName.length < 8">{{ item.presetName }}</span>
-            <el-tooltip :content="item.presetName" placement="bottom" v-else>
-              <span class="preset-position-name">{{ item.presetName }}</span>
-            </el-tooltip>
-          </div>
-        </div>
-      </footer>
-    </div>
-  </el-dialog>
-</template>
-
-<script lang="ts" setup>
-  import { ref, watch, computed, onMounted } from 'vue';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
-  import EditPresetPositionIcon from '@/assets/icons/edit-preset-position.svg';
-  import DeletePresetPositionIcon from '@/assets/icons/delete-preset-position.svg';
-  import PresetPositionItem from '@/assets/icons/preset-placeholder-img.svg';
-  import EditPresetPositionFocusIcon from '@/assets/icons/edit-preset-position-focus.svg';
-  import FullScreenIcon from '@/assets/icons/fullscreen.svg';
-  import { dataURLtoBlob } from '@/utils/file/base64Conver';
-  import {
-    getPresetListApi,
-    PresetListResp,
-    deletePresetApi,
-    createPresetApi,
-    goToPresetApi,
-    uploadPresetImageApi,
-  } from '@/api/camera/camera-preview';
-  import CameraLiveVideo from '@/modules/algo-params-setting-base/components/CameraLiveVideo/CameraLiveVideo.vue';
-  import CameraViewScale from '@/modules/algo-params-setting-base/components/CameraViewSetting/CameraViewScale.vue';
-  import CameraDirectionControl from '@/modules/algo-params-setting-base/components/CameraDirectionControl/CameraDirectionControl.vue';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import { useFullscreen } from '@vueuse/core';
-
-  const emits = defineEmits(['update:dialogVisible']);
-  const dialogVisible = ref(false);
-  const presetList = ref<PresetListResp[]>([]);
-  const displayPresetList = ref<PresetListResp[]>([]);
-  const isEditMode = ref(false);
-  const activePresetToken = ref<string>(''); // 当前激活的预置位token
-  const cameraLiveVideoRef = ref<InstanceType<typeof CameraLiveVideo> | null>(null);
-  const cameraVideoRef = ref<HTMLElement>();
-  const { toggle } = useFullscreen(cameraVideoRef);
-
-  const props = defineProps<{
-    dialogVisible: boolean;
-    overviewCameraData: CameraDetailServer;
-  }>();
-  const currentPage = ref(1);
-  const pageSize = 5;
-  const presetPositionCount = computed(() => displayPresetList.value.length); // 总预置位数量
-
-  const totalPages = computed(() => Math.ceil(presetPositionCount.value / pageSize));
-
-  const currentPageItems = computed(() => {
-    const startIdx = (currentPage.value - 1) * pageSize;
-    const endIdx = Math.min(startIdx + pageSize, presetPositionCount.value);
-    return displayPresetList.value.slice(startIdx, endIdx);
-  });
-
-  const prevPage = () => {
-    if (currentPage.value > 1) {
-      currentPage.value--;
-    }
-  };
-
-  const nextPage = () => {
-    if (currentPage.value < totalPages.value) {
-      currentPage.value++;
-    }
-  };
-
-  const toggleEditMode = () => {
-    isEditMode.value = !isEditMode.value;
-  };
-
-  const handleGoToPreset = (item: PresetListResp) => {
-    const cameraId = props.overviewCameraData.id;
-    if (!cameraId) return;
-
-    // 设置当前激活的预置位
-    activePresetToken.value = item.presetToken;
-
-    // 调用前往预置位的API
-    goToPresetApi({ presetToken: item.presetToken, cameraId });
-  };
-
-  const handleDeletePreset = (item: PresetListResp) => {
-    const cameraId = props.overviewCameraData.id;
-    if (!cameraId) return;
-    const index = displayPresetList.value.findIndex((preset) => preset.presetToken === item.presetToken);
-    if (index !== -1) {
-      ElMessageBox.confirm(
-        '该预置位可能存在关联的电子围栏。删除该预置位将会删除对应的电子围栏信息,请确认是否删除?',
-        '删除确认',
-        {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-        },
-      ).then(async () => {
-        await deletePresetApi(item.presetToken, String(cameraId));
-        ElMessage.success('删除成功');
-        await getPresetList();
-        const currentPageStartIdx = (currentPage.value - 1) * pageSize;
-        if (currentPageStartIdx >= displayPresetList.value.length && currentPage.value > 1) {
-          currentPage.value--;
-        }
-      });
-    }
-  };
-
-  const handleAddPreset = () => {
-    ElMessageBox.prompt('', '添加预置位', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      inputPlaceholder: '请输入预置位名称',
-      inputValidator: (value) => {
-        if (!value) {
-          return '预置位名称不能为空';
-        }
-        const isExist = presetList.value.find((item) => item.presetName === value);
-        if (isExist) {
-          return '预置位名称已存在';
-        }
-        return true;
-      },
-    }).then(async ({ value }) => {
-      const cameraId = props.overviewCameraData.id;
-      if (!cameraId) return;
-
-      let imageBase64 = '';
-      if (cameraLiveVideoRef.value) {
-        imageBase64 = cameraLiveVideoRef.value.captureImage();
-      }
-
-      // 未来可以在这里把imageBase64传给后端
-      const blob = dataURLtoBlob(imageBase64);
-      const url = await uploadPresetImageApi(blob, 'CAMERA_IMAGE');
-      if (!url) {
-        ElMessage.error('上传预置位图片失败');
-        return;
-      }
-      const res = await createPresetApi({ presetName: value, cameraId, imageUrl: url.url });
-      if (res) {
-        activePresetToken.value = res;
-        ElMessage.success('添加预置位成功');
-        await getPresetList();
-      }
-    });
-  };
-
-  const getPresetList = async () => {
-    const cameraId = props.overviewCameraData.id;
-    if (!cameraId) return;
-    presetList.value = await getPresetListApi(cameraId);
-    displayPresetList.value = [...presetList.value];
-  };
-
-  onMounted(async () => {
-    await getPresetList();
-  });
-
-  watch(
-    () => props.dialogVisible,
-    (newVal) => {
-      dialogVisible.value = newVal;
-      if (newVal) {
-        // 每次对话框打开时,重置编辑状态
-        isEditMode.value = false;
-      }
-    },
-    { immediate: true },
-  );
-</script>
-
-<style lang="scss">
-  .camera-overview-popover--custom {
-    padding: 20px 24px;
-    border-radius: 8px;
-    box-shadow: 0px 9px 28px 8px rgba(0, 0, 0, 0.05), 0px 6px 16px 0px rgba(0, 0, 0, 0.08),
-      0px 3px 6px -4px rgba(0, 0, 0, 0.12);
-    .el-dialog__header {
-      text-align: left;
-      color: rgba(0, 0, 0, 0.88);
-      font-weight: bold;
-      font-size: 16px;
-    }
-    &__title {
-      display: flex;
-      align-items: center;
-      gap: 10px;
-      img {
-        cursor: pointer;
-      }
-    }
-    &__content {
-      display: flex;
-      flex-direction: column;
-      gap: 12px;
-      width: 100%;
-      height: 100%;
-
-      .main {
-        position: relative;
-        flex-shrink: 0;
-        flex-grow: 0;
-        width: 100%;
-        height: 377px;
-      }
-      .footer {
-        display: flex;
-        flex-direction: column;
-        gap: 9px;
-
-        .footer-header {
-          display: flex;
-          justify-content: space-between;
-          align-items: center;
-          cursor: pointer;
-          .edit-preset-position-icon-wrapper {
-            display: flex;
-            align-items: center;
-            gap: 8px;
-            span {
-              font-size: 12px;
-              color: #1777ff;
-              font-weight: 500;
-            }
-          }
-
-          .pagination-control {
-            display: flex;
-            align-items: center;
-            gap: 8px;
-            font-size: 14px;
-            color: rgba(0, 0, 0, 0.88);
-          }
-        }
-
-        .preset-position-list {
-          display: flex;
-          width: 100%;
-          gap: 12px;
-
-          .preset-position-item {
-            text-align: center;
-            width: 120px;
-            position: relative;
-            transition: all 0.3s ease;
-            box-sizing: border-box;
-
-            &.active-preset {
-              transform: scale(1.05);
-              border: 2px solid #1890ff;
-              border-radius: 4px;
-            }
-
-            .delete-preset-position-icon {
-              position: absolute;
-              top: -4px;
-              right: -4px;
-              width: 16px;
-              height: 16px;
-              cursor: pointer;
-              transition: all 0.3s ease;
-              &:hover {
-                scale: 1.2;
-              }
-            }
-
-            img {
-              width: 120px;
-              height: 68px;
-              object-fit: cover;
-            }
-
-            .preset-position-name {
-              display: block;
-              width: 100%;
-              margin-top: 4px;
-              color: rgba(0, 0, 0, 0.88);
-              font-size: 12px;
-              padding: 2px 4px;
-              border-radius: 2px;
-              white-space: nowrap;
-              overflow: hidden;
-              text-overflow: ellipsis;
-            }
-          }
-        }
-      }
-      .cameraVideo {
-        position: absolute;
-        top: 0;
-        left: 0;
-        z-index: 8;
-        background: #ccc;
-        width: 100%;
-        height: 100%;
-      }
-      .presetAddWrapper {
-        position: absolute;
-        bottom: -50px;
-        right: -30px;
-        flex-direction: column;
-        display: flex;
-        align-items: center;
-        z-index: 10;
-        transform: scale(0.6);
-        .el-button {
-          transform: scale(1.5);
-        }
-      }
-    }
-  }
-</style>

+ 0 - 103
src/views/cameras/overview/components/CameraSharePopover.vue

@@ -1,103 +0,0 @@
-<template>
-  <div class="overlay" v-if="props.modelValue"></div>
-  <el-card v-if="props.modelValue" class="pop-card">
-    <template #header>
-      <div class="flex justify-between items-center pop-head">
-        <span class="pop-head-name">共享相机</span>
-        <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
-      </div>
-    </template>
-    <div class="pop-content">
-      <ShareCameraDetail :form-data="props.shareData" />
-    </div>
-  </el-card>
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  import { cameraAddType } from '@/types/camera/constant';
-  import { Close } from '@element-plus/icons-vue';
-  import ShareCameraDetail from './ShareCameraDetail.vue';
-  import { CameraDetailServer } from '@/types/camera/type';
-
-  const props = defineProps<{ modelValue: boolean; shareData?: CameraDetailServer | null }>();
-
-  const emits = defineEmits(['update:modelValue']);
-
-  const addType = ref(cameraAddType[0].value);
-
-  const updateValue = (value) => {
-    addType.value = cameraAddType[0].value;
-    emits('update:modelValue', value);
-  };
-</script>
-
-<style scoped lang="scss">
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-    z-index: 1000;
-  }
-
-  .pop-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-
-    &-tabs {
-      margin-top: 18px;
-
-      :first-child {
-        border-radius: 8px 0px 0px 0px;
-      }
-
-      :last-child {
-        border-radius: 0px 8px 0px 0px;
-      }
-    }
-  }
-
-  .tab-item {
-    width: 188px;
-    height: 38px;
-    background: #fafafa;
-    border: 1px solid #d9d9d9;
-    cursor: pointer;
-
-    &-active {
-      background: #e2eefe;
-      border: 1px solid #1890ff;
-    }
-  }
-
-  .pop-content {
-    height: 480px;
-    display: flex;
-    justify-content: center;
-    padding: 35px;
-    overflow: auto;
-  }
-
-  :deep(.el-card__header) {
-    padding: 0;
-  }
-  :deep(.el-card__body) {
-    padding: 0;
-  }
-</style>

+ 0 - 109
src/views/cameras/overview/components/CameraSharedEdit.vue

@@ -1,109 +0,0 @@
-<template>
-  <div class="overlay" v-if="props.modelValue"></div>
-  <el-card v-if="props.modelValue" class="pop-card">
-    <template #header>
-      <div class="flex justify-between items-center pop-head">
-        <span class="pop-head-name">添加相机</span>
-        <div class="flex pop-head-tabs">
-          <div
-            v-for="item in sharedCaremaType"
-            :key="item.value"
-            class="flex justify-center items-center tab-item"
-            :class="{ 'tab-item-active': item.value === addType }"
-            @click="addType = item.value"
-          >
-            {{ item.label }}
-          </div>
-        </div>
-        <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
-      </div>
-    </template>
-    <div><SharedTable :addCameraType="addType" @update="updateUnAdd" /></div>
-  </el-card>
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  import { sharedCaremaType } from '../../../../types/camera/constant';
-  import { Close } from '@element-plus/icons-vue';
-  import SharedTable from './SharedTable.vue';
-
-  const props = defineProps<{ modelValue: boolean }>();
-
-  const emits = defineEmits(['update:modelValue', 'updateUnadd']);
-
-  const addType = ref(sharedCaremaType[0].value);
-
-  const updateValue = (value) => {
-    addType.value = sharedCaremaType[0].value;
-    emits('update:modelValue', value);
-  };
-
-  const updateUnAdd = () => {
-    emits('updateUnadd');
-  };
-</script>
-
-<style lang="scss" scoped>
-  .overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.5);
-    z-index: 999;
-  }
-  .pop-card {
-    position: fixed;
-    top: 50%;
-    left: 55%;
-    transform: translate(-50%, -50%);
-    width: calc(100% - 300px);
-    height: 622px;
-    z-index: 1000;
-  }
-
-  .pop-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-
-    &-tabs {
-      margin-top: 18px;
-
-      :first-child {
-        border-radius: 8px 0px 0px 0px;
-      }
-
-      :last-child {
-        border-radius: 0px 8px 0px 0px;
-      }
-    }
-  }
-
-  .tab-item {
-    width: 188px;
-    height: 38px;
-    background: #fafafa;
-    border: 1px solid #d9d9d9;
-    cursor: pointer;
-
-    &-active {
-      background: #e2eefe;
-      border: 1px solid #1890ff;
-    }
-  }
-
-  :deep(.el-card__header) {
-    padding: 0;
-  }
-  :deep(.el-card__body) {
-    padding: 0;
-  }
-</style>

+ 0 - 141
src/views/cameras/overview/components/ConditionQuery.vue

@@ -1,141 +0,0 @@
-<template>
-  <div class="flex items-center query-head">
-    <el-space alignment="center" :size="50">
-      <div>
-        <el-select v-model="queryType" placeholder="选择类型" class="type-select">
-          <el-option v-for="item in queryTypeSelect" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-        <el-input
-          :style="{ width: '180px' }"
-          v-model="queryTypeContent"
-          clearable
-          placeholder="请输入查找内容"
-          :disabled="!Boolean(queryType)"
-        />
-      </div>
-      <div>
-        <span>添加方式:</span>
-        <el-select v-model="querySourceType" placeholder="请选择添加方式" class="protocal-select">
-          <el-option v-for="item in cameraAddType" :key="item.value" :label="item.label" :value="AddType[item.value]" />
-        </el-select>
-      </div>
-      <div>
-        <span>工位:</span>
-        <el-cascader
-          class="protocal-select"
-          v-model="tempWorkSpaces"
-          :options="workspaceInfo"
-          :props="locationProp"
-          clearable
-          collapse-tags
-          :show-all-levels="false"
-          popper-class="special-cascader"
-          placeholder="请选择工位"
-          @change="handleCascaderChange"
-        />
-      </div>
-      <div>
-        <span>联网状态:</span>
-        <el-select v-model="networkingState" placeholder="请选择添加方式" class="simple-select">
-          <el-option :value="-1" label="全部" />
-          <el-option :value="0" label="已联网" />
-          <el-option :value="1" label="未联网" />
-        </el-select>
-      </div>
-      <div>
-        <span>进入平台:</span>
-        <el-select v-model="integrationState" placeholder="请选择添加方式" class="simple-select">
-          <el-option :value="-1" label="全部" />
-          <el-option :value="0" label="是" />
-          <el-option :value="1" label="否" />
-        </el-select>
-      </div>
-      <div>
-        <span>鹰眼追踪:</span>
-        <el-select v-model="openEagle" placeholder="请选择添加方式" class="simple-select">
-          <el-option :value="-1" label="全部" />
-          <el-option :value="1" label="是" />
-          <el-option :value="0" label="否" />
-        </el-select>
-      </div>
-    </el-space>
-    <div class="flex-1 flex justify-end">
-      <el-button type="primary" @click="getCameraItems"> 查询 </el-button>
-      <el-button @click="resetSearch"> 重置 </el-button>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { onMounted, ref } from 'vue';
-  import { storeToRefs } from 'pinia';
-  import { queryTypeSelect, cameraAddType, AddType } from '@/types/camera/constant';
-  import useCameraOverview from '../stores/useCameraOverview';
-  import useTreeWorkspaceInfo from '../hooks/useTreeWorkspaceInfo';
-
-  const treeWorkspaceInfo = useTreeWorkspaceInfo();
-  const { workspaceInfo, getWorkspaceFromTreeInfo, getWorkspaceIdFromTreeNode } = treeWorkspaceInfo;
-
-  const cameraOverview = useCameraOverview();
-  const {
-    queryType,
-    queryTypeContent,
-    querySourceType,
-    queryWorkSpaces,
-    integrationState,
-    networkingState,
-    openEagle,
-  } = storeToRefs(cameraOverview);
-  const { getCameraItems, reset } = cameraOverview;
-
-  const tempWorkSpaces = ref([]);
-  const locationProp = { multiple: true, expandTrigger: 'hover' as const }; // 级联选择器(打开多选)
-
-  const handleCascaderChange = () => {
-    const tempArr = [] as number[];
-    queryWorkSpaces.value = [];
-    if (tempWorkSpaces.value.length !== 0) {
-      tempWorkSpaces.value.forEach((item) => {
-        const workspaceId = getWorkspaceIdFromTreeNode(item[2]);
-        tempArr.push(Number(workspaceId));
-      });
-      queryWorkSpaces.value = tempArr;
-    }
-  };
-
-  // 重置查询条件
-  const resetSearch = () => {
-    tempWorkSpaces.value = [];
-    queryType.value = '';
-    queryTypeContent.value = '';
-    querySourceType.value = '';
-    queryWorkSpaces.value = [];
-    integrationState.value = -1;
-    networkingState.value = -1;
-    openEagle.value = -1;
-    reset();
-    getCameraItems();
-  };
-
-  onMounted(() => {
-    getWorkspaceFromTreeInfo();
-  });
-</script>
-
-<style scoped>
-  .type-select {
-    width: 100px;
-  }
-
-  .protocal-select {
-    width: 160px;
-  }
-
-  .simple-select {
-    width: 80px;
-  }
-
-  .query-head {
-    padding: 24px 57px 18px 21px;
-  }
-</style>

+ 0 - 137
src/views/cameras/overview/components/EditSharedCamera.vue

@@ -1,137 +0,0 @@
-<template>
-  <div>
-    <div style="margin-bottom: 120px">
-      <el-form
-        class="ip-form"
-        :inline="true"
-        :model="cameraEditData"
-        :rules="rules"
-        label-width="84px"
-        label-position="left"
-      >
-        <el-form-item
-          v-for="item in cameraSharedForm"
-          :key="item.prop"
-          :label="item.label"
-          :prop="item.prop"
-        >
-          <el-input
-            v-if="item.type === 'input'"
-            v-model="cameraEditData[item.prop]"
-            :placeholder="item.placeholder"
-            style="width: 200px"
-            :type="item.prop === 'password' ? 'password' : ''"
-            :show-password="item.prop === 'password'"
-            :disabled="item.disabled"
-          />
-          <el-tree-select
-            v-if="item.type === 'tree-select'"
-            v-model="cameraEditData[item.prop]"
-            :data="scenesTree"
-            :render-after-expand="false"
-            :default-expand-all="true"
-            check-strictly
-            :placeholder="item.placeholder"
-            style="width: 200px"
-            @change="handleTreeSelect"
-          />
-        </el-form-item>
-      </el-form>
-    </div>
-    <span class="pop-footer">
-      <el-button @click="handleCancel">取消</el-button>
-      <el-button type="primary" @click="handleConfirm">确定</el-button>
-    </span>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed, onBeforeMount, ref } from 'vue';
-  import { cameraSharedForm } from '../../../../types/camera/constant';
-
-  import useSceneInfos from '@/hooks/useSceneInfos';
-  import useCameraShare from '../hooks/useCameraShare';
-  import { CameraShareType } from '@/api/camera/camera-share';
-
-  const useShare = useCameraShare();
-  const { handleEdit } = useShare;
-
-  const sceneInfos = useSceneInfos();
-  const { scenesTree, flattendWorkspaces, getScenesTree } = sceneInfos;
-
-  const props = defineProps<{ formData?: CameraShareType | null }>();
-
-  const emits = defineEmits(['closeEdit']);
-
-  const cameraEditData = ref<CameraShareType>({} as CameraShareType);
-
-  const rules = computed(() => {
-    const newRule = {};
-    cameraSharedForm.forEach((item) => {
-      if (item.required) {
-        newRule[item.prop] = item.rule;
-      }
-    });
-    return newRule;
-  });
-
-  const handleTreeSelect = (code: string) => {
-    console.log('code', code);
-    console.log('flattendWorkspaces', flattendWorkspaces.value);
-
-    cameraEditData.value.cameraWorkspace = flattendWorkspaces.value.find(
-      (item) => item.code === code,
-    ).id;
-  };
-
-  const handleCancel = () => {
-    emits('closeEdit');
-  };
-
-  const handleConfirm = () => {
-    const updateData = {
-      id: cameraEditData.value.id,
-      cameraName: cameraEditData.value.cameraName,
-      cameraWorkspace: cameraEditData.value.cameraWorkspace,
-      cameraCode: cameraEditData.value.cameraCode,
-    };
-    handleEdit(updateData);
-    emits('closeEdit');
-  };
-
-  onBeforeMount(() => {
-    getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
-    if (props.formData) {
-      cameraEditData.value = props.formData;
-    }
-  });
-</script>
-
-<style scoped>
-  .ip-form {
-    width: 768px;
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    align-content: space-around;
-  }
-
-  .pop-footer {
-    position: absolute;
-    right: 24px;
-    bottom: 27px;
-    display: flex;
-    justify-content: flex-end;
-  }
-
-  :deep(.el-form-item__label) {
-    font-size: 14px;
-    color: #363636;
-    padding: 0;
-  }
-  :deep(.el-form--inline .el-form-item) {
-    display: flex;
-    margin-right: 0;
-    margin-bottom: 28px;
-  }
-</style>

+ 0 - 61
src/views/cameras/overview/components/SearchCamerasAction.vue

@@ -1,61 +0,0 @@
-<template>
-  <div class="flex items-center">
-    <el-space :size="space">
-      <span
-        v-for="(item, index) in props.tableTextActions"
-        :key="item.label"
-        @click="item.onClick"
-        :style="{
-          pointerEvents: disList[index] ? 'none' : 'auto',
-          textDecoration: 'underline',
-          fontSize: '14px',
-          width: '28px',
-          color: disList[index] ? props.unactiveColor : props.activeColor,
-        }"
-      >
-        {{ item.label }}
-      </span>
-    </el-space>
-    <div class="divide"></div>
-    <TableActionIcons v-bind="props.tableIconActions" />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed } from 'vue';
-  import { ActionItem } from '@/components/Table';
-  import { TableActionIcons } from '@/components/Table';
-
-  type TableIconActionProp = {
-    space: number;
-    size: number;
-    color: string;
-    iconStyle: 'img' | 'icon';
-    actionIcons: ActionItem[];
-  };
-
-  type TextBtnItem = {
-    label: string;
-    disabled: boolean;
-    onClick?: Fn;
-  };
-
-  const props = defineProps<{
-    space?: number;
-    activeColor: string;
-    unactiveColor: string;
-    tableTextActions: TextBtnItem[];
-    tableIconActions: TableIconActionProp;
-  }>();
-
-  const disList = computed(() => props.tableTextActions.map((item) => item.disabled));
-</script>
-
-<style scoped>
-  .divide {
-    width: 1px;
-    height: 14px;
-    background: #e9e9e9;
-    margin: 0 14px;
-  }
-</style>

+ 0 - 297
src/views/cameras/overview/components/ShareCameraDetail.vue

@@ -1,297 +0,0 @@
-<template>
-  <div>
-    <div style="margin-top: 28px">
-      <el-form
-        ref="ruleFormRef"
-        class="ip-form"
-        :inline="true"
-        :model="shareData"
-        :rules="rules"
-        label-width="84px"
-        label-position="left"
-      >
-        <el-form-item label="企业账号:" prop="tenantCode" style="margin-right: 100px">
-          <el-input
-            v-model="shareData.tenantCode"
-            placeholder="请输入企业账号"
-            class="company-input"
-          />
-          <el-button
-            type="primary"
-            size="small"
-            plain
-            style="margin-left: 10px"
-            @click="verifyAccount"
-            >验证</el-button
-          >
-        </el-form-item>
-        <el-form-item label="权限设置:" prop="permission">
-          <el-radio-group v-model="shareData.permission" class="ml-4">
-            <el-radio v-for="item in authorityTypeSelect" :label="item.value" :key="item.value">{{
-              item.label
-            }}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item
-          label="企业名称:"
-          prop="tenantName"
-          class="company-name"
-          style="margin-right: 160px"
-        >
-          <el-input
-            v-model="shareData.tenantName"
-            disabled
-            placeholder=""
-            readonly
-            style="width: 200px; height: 32px"
-          />
-          <div v-if="shareData.tenantName" class="verify-success">账号验证成功</div>
-        </el-form-item>
-        <el-form-item label="分享时间:" prop="time">
-          <el-radio-group v-model="shareData.time" class="ml-4" @change="changeTime">
-            <el-radio v-for="item in timeTypeSelect" :label="item.value" :key="item.value"
-              >{{ item.label }}
-            </el-radio>
-          </el-radio-group>
-          <div
-            ><el-input
-              v-model="shareData.days"
-              placeholder="请输入"
-              :readonly="shareData.time === 'Indefinite'"
-              class="day-input"
-            />
-            <span>/天</span></div
-          >
-        </el-form-item>
-        <el-form-item label="备注:" prop="notes">
-          <el-input v-model="shareData.remark" placeholder="请输入备注" style="width: 765px" />
-        </el-form-item>
-        <el-button type="primary" @click="handleConfirm" class="confirm">确定</el-button>
-        <el-form-item label="分享企业:" prop="shareList" class="company-table">
-          <BasicTable
-            :columns="getColumns(handleEditState)"
-            :data-source="cameraShareList"
-            :row-key="(row) => row.code"
-            :action-column="actionColumn"
-            :showHeader="false"
-            :tableSetting="{
-              size: false,
-              redo: false,
-              fullscreen: false,
-              striped: false,
-              setting: false,
-            }"
-            :striped="true"
-            ref="tableRef"
-            style="height: 200px"
-          />
-        </el-form-item>
-      </el-form>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { h, reactive, ref, onMounted } from 'vue';
-  import { BasicColumn, BasicTable, TableActionIcons } from '@/components/Table';
-  import { CameraShareItem, CameraDetailServer } from '../../../../types/camera/type';
-  import deleteIcon from '@/assets/images/table/table-delete.png';
-  import {
-    authorityTypeSelect,
-    timeTypeSelect,
-    getColumns,
-  } from '../../../../types/camera/constant';
-  import useCameraShare from '../hooks/useCameraShare';
-  import { getVerify } from '@/api/camera/camera-share';
-  import dayjs from 'dayjs';
-  import { ElMessage, FormInstance, FormRules } from 'element-plus';
-
-  const useShare = useCameraShare();
-  const { cameraShareList, queryCameraId, conditionSearch, handleDel, handleAdd, handleEdit } =
-    useShare;
-
-  const props = defineProps<{ formData?: CameraDetailServer | null }>();
-
-  const rules = reactive<FormRules>({
-    tenantCode: [{ required: true, message: '请输入企业账号', trigger: 'blur' }],
-    permission: [{ required: true, message: '', trigger: 'change' }],
-    tenantName: [{ required: true, message: '请验证企业账号', trigger: 'change' }],
-    time: [{ required: true, message: '', trigger: 'change' }],
-    shareList: [{ required: true, message: '', trigger: 'blur' }],
-  });
-
-  // onMounted(() => {});
-  onMounted(() => {
-    //获取数据
-    queryCameraId.value = props.formData?.id;
-    console.log('queryCameraId', props.formData?.code);
-    conditionSearch();
-  });
-
-  const ruleFormRef = ref<FormInstance>();
-
-  const shareData = ref<CameraShareItem>({
-    tenantCode: undefined,
-    toTenantId: undefined,
-    permission: '0',
-    tenantName: '',
-    time: 'Indefinite',
-    days: undefined,
-    remark: '',
-    endTime: '',
-  });
-
-  // 将修改列表中的
-  const handleEditState = (row) => {
-    const editData = {
-      id: row.id as number,
-      connected: row.connected ? false : true,
-    };
-    handleEdit(editData);
-  };
-
-  const handleDelete = (row) => {
-    handleDel(row.id);
-  };
-
-  //操作列
-  const actionColumn: BasicColumn = reactive({
-    width: 200,
-    title: '操作',
-    prop: 'action',
-    key: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(TableActionIcons as any, {
-        space: 20,
-        color: '#629bf9',
-        iconStyle: 'img',
-        size: 16,
-        actionIcons: [
-          {
-            label: '删除',
-            icon: deleteIcon,
-            onClick: handleDelete.bind(null, record.row),
-          },
-        ],
-      });
-    },
-  });
-
-  const verifyAccount = () => {
-    // shareData.value.name = 'C' + shareData.value.account;
-    getVerify(shareData.value.tenantCode!).then((res) => {
-      if (res) {
-        shareData.value.tenantName = res.tenantName;
-        shareData.value.toTenantId = res.tenantId;
-      } else {
-        shareData.value.tenantName = '';
-        shareData.value.toTenantId = undefined;
-        ElMessage.error('企业账号验证失败');
-      }
-    });
-  };
-
-  const changeTime = () => {
-    if (shareData.value.time === 'Indefinite') {
-      shareData.value.days = undefined;
-    }
-  };
-
-  const resetData = () => {
-    shareData.value.tenantCode = undefined;
-    shareData.value.toTenantId = undefined;
-    shareData.value.tenantName = '';
-    shareData.value.permission = '0';
-    shareData.value.time = 'Indefinite';
-    shareData.value.days = undefined;
-    shareData.value.remark = '';
-    shareData.value.endTime = '';
-  };
-
-  const handleConfirm = () => {
-    if (!ruleFormRef.value) return;
-
-    ruleFormRef.value.validate((valid) => {
-      if (!valid) {
-        return;
-      }
-      if (shareData.value.time === 'Indefinite') {
-        shareData.value.endTime = dayjs().add(-1, 'day').format('YYYY-MM-DD HH:mm:ss');
-      } else {
-        shareData.value.endTime = dayjs()
-          .add(shareData.value.days!, 'day')
-          .format('YYYY-MM-DD HH:mm:ss');
-      }
-
-      //接口
-      const currentDate = new Date();
-      console.log('currentDate', currentDate);
-      const addShareItem = {
-        cameraId: props.formData?.id,
-        toTenantId: shareData.value.toTenantId,
-        permission: shareData.value.permission,
-        endTime: shareData.value.endTime,
-        isAdd: false,
-        remark: shareData.value.remark,
-      };
-      queryCameraId.value = props.formData?.id;
-      handleAdd(addShareItem); //数据未调整
-      resetData();
-    });
-  };
-</script>
-
-<style scoped>
-  .ip-form {
-    width: 900px;
-    display: flex;
-    flex-wrap: wrap;
-    align-content: space-around;
-  }
-
-  :deep(.el-form-item__label) {
-    font-size: 14px;
-    color: #363636;
-    padding: 0;
-  }
-  :deep(.el-form--inline .el-form-item) {
-    display: flex;
-    margin-right: 0;
-    margin-bottom: 28px;
-  }
-
-  .company-input {
-    width: 200px;
-    height: 32px;
-  }
-
-  .day-input {
-    width: 64px;
-    height: 32px;
-    margin-left: 10px;
-    margin-right: 4px;
-  }
-  .verify-success {
-    position: absolute;
-    right: -100px;
-
-    /* margin-right: 100px; */
-    color: rgb(142, 215, 33);
-  }
-
-  .confirm {
-    position: relative;
-    left: 800px;
-  }
-
-  .company-table {
-    margin-top: 70px;
-    margin-left: -60px;
-  }
-
-  .company-name {
-    margin-right: 160px;
-    position: relative;
-  }
-</style>

+ 0 - 226
src/views/cameras/overview/components/SharedTable.vue

@@ -1,226 +0,0 @@
-<template>
-  <div class="camera-share">
-    <div class="flex items-center query-head">
-      <el-space alignment="center" :size="50">
-        <div style="display: flex">
-          <div>公司名称:</div>
-          <el-input
-            v-model="queryName"
-            clearable
-            placeholder="请输入公司名称"
-            class="query-content"
-          />
-        </div>
-        <div>
-          <span>公司账号:</span>
-          <el-input
-            v-model="queryAccount"
-            clearable
-            placeholder="请输入公司账号"
-            class="query-content"
-          />
-        </div>
-      </el-space>
-      <div class="flex-1 flex justify-end">
-        <el-button type="primary" @click="queryCameraItems"> 查询 </el-button>
-        <el-button @click="resetSearch"> 重置 </el-button>
-      </div>
-    </div>
-    <div class="camera-list">
-      <BasicTable
-        :columns="getColumns(flattendWorkspaces)"
-        :data-source="cameraShareList"
-        :row-key="(row) => row.cameraIp"
-        :action-column="actionColumn"
-        :tableSetting="{
-          size: false,
-          redo: false,
-          fullscreen: false,
-          striped: false,
-          setting: false,
-        }"
-        :striped="true"
-        ref="tableRef"
-      />
-    </div>
-    <CameraEditshared
-      class="add-popover"
-      v-model="shareEditedPopover"
-      :edit-data="handleEditData"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { h, reactive, ref, onMounted, watch, onBeforeMount } from 'vue';
-  import { getColumns } from '../hooks/sharedColumns';
-  import editIcon from '@/assets/images/table/table-edit.png';
-  import deleteIcon from '@/assets/images/table/table-delete.png';
-  import { BasicColumn, TableActionIconsWords, BasicTable } from '@/components/Table';
-  import CameraEditshared from '../components/CameraEditshared.vue';
-  import useCameraShare from '../hooks/useCameraShare';
-  import useSceneInfos from '@/hooks/useSceneInfos';
-  import { CameraShareType } from '@/api/camera/camera-share';
-  import { ElMessageBox } from 'element-plus';
-
-  const useShare = useCameraShare();
-  const {
-    cameraShareList,
-    queryName,
-    queryAccount,
-    isAddState,
-    queryToTenantId,
-    conditionSearch,
-    handleEdit,
-    handleDel,
-  } = useShare;
-
-  const sceneInfos = useSceneInfos();
-  const { flattendWorkspaces, getScenesTree } = sceneInfos;
-
-  const props = defineProps<{ addCameraType: string }>();
-  const emits = defineEmits(['update']);
-  onMounted(() => {
-    isAddState.value = props.addCameraType === 'incomplete' ? false : true;
-    console.log('isAddState', isAddState.value);
-    queryToTenantId.value = -10;
-    conditionSearch();
-    console.log(cameraShareList.value);
-  });
-
-  const shareEditedPopover = ref<boolean>(false);
-
-  const handleEditData = ref<CameraShareType>({} as CameraShareType);
-
-  const handleEditDetail = (row) => {
-    shareEditedPopover.value = true;
-    row.cameraWorkspaceName = flattendWorkspaces.value?.find(
-      (item) => item.id === Number(row.cameraWorkspace),
-    )?.code;
-    handleEditData.value = row;
-  };
-
-  //添加按钮
-  const handleChangeAdd = (row) => {
-    if (!row.cameraWorkspaceName) {
-      ElMessageBox.alert('该共享相机未添加场景,请先添加相机场景', 'Warning', {
-        confirmButtonText: 'OK',
-        type: 'warning',
-      });
-      return;
-    }
-    const changeAddData = {
-      id: row.id,
-      isAdd: row.isAdd ? false : true,
-    };
-    emits('update');
-    handleEdit(changeAddData);
-  };
-
-  const handleDelete = (row) => {
-    // console.log('row', row);
-    emits('update');
-    handleDel(row.id);
-  };
-
-  //操作列
-  const actionColumn: BasicColumn = reactive({
-    width: 200,
-    title: '操作',
-    prop: 'action',
-    key: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(TableActionIconsWords as any, {
-        space: 20,
-        color: '#629bf9',
-        iconStyle: 'img',
-        size: 16,
-        actionIcons: [
-          {
-            label: '添加',
-            type: 'words' + props.addCameraType,
-            onClick: handleChangeAdd.bind(null, record.row),
-          },
-          {
-            label: '编辑',
-            type: 'img',
-            icon: editIcon,
-            onClick: handleEditDetail.bind(null, record.row),
-          },
-          {
-            label: '删除',
-            type: 'img',
-            icon: deleteIcon,
-            onClick: handleDelete.bind(null, record.row),
-          },
-        ],
-      });
-    },
-  });
-
-  //查询
-  const queryCameraItems = () => {
-    isAddState.value = props.addCameraType === 'incomplete' ? false : true;
-    conditionSearch();
-  };
-  //重置
-  const resetSearch = () => {
-    queryName.value = '';
-    queryAccount.value = '';
-    queryCameraItems();
-  };
-
-  watch(
-    () => props.addCameraType,
-    (_val) => {
-      resetSearch();
-      isAddState.value = props.addCameraType === 'incomplete' ? false : true;
-      console.log('isAddState', isAddState.value);
-      conditionSearch();
-    },
-  );
-
-  onBeforeMount(() => {
-    getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
-  });
-</script>
-
-<style scoped>
-  .type-select {
-    width: 100px;
-  }
-
-  .query-content {
-    width: 160px;
-    margin-top: -6px;
-  }
-
-  .protocal-select {
-    width: 160px;
-  }
-
-  .query-head {
-    padding: 24px 57px 18px 21px;
-  }
-
-  .camera-share {
-    position: relative;
-    height: calc(100vh - 64px - 12px);
-    background-color: #ffffff;
-  }
-
-  .camera-list {
-    padding: 0 21px;
-  }
-
-  .add-popover {
-    position: absolute;
-    width: calc(100%);
-    height: 622px;
-    top: -57px;
-    left: -20px;
-    margin: auto;
-    z-index: 99;
-  }
-</style>

+ 0 - 114
src/views/cameras/overview/components/sysConfigItemOfAddCamera.vue

@@ -1,114 +0,0 @@
-<template>
-  <div class="scene-template-item" v-for="item in sceneTemplateList" :key="item.id">
-    <el-checkbox v-model="sceneCheckedValues[item.id!]" :label="item.name" @change="handleSceneIdChange(item.id)" />
-    <div class="template-item">
-      <div class="template-item-tip"><span style="color: red"> * </span> 应用模版:</div>
-      <el-radio-group
-        class="template-item-list"
-        v-model="templateCheckedValues[item.id!]"
-        @change="handleTemplateIdChange"
-      >
-        <el-radio
-          v-for="subItem in item.viewTemplateList"
-          :key="subItem.id"
-          :value="subItem.id"
-          :disabled="!sceneCheckedValues[item.id!]"
-          >{{ subItem.name }}</el-radio
-        >
-      </el-radio-group>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { onMounted, ref } from 'vue';
-  import { CheckedSceneTemplate } from '@/types/camera/type';
-  import { useSceneTemplateList } from '../stores/useSceneTemplateList';
-  import { storeToRefs } from 'pinia';
-
-  const sceneTemplateListInfo = useSceneTemplateList();
-  const { sceneTemplateList } = storeToRefs(sceneTemplateListInfo);
-
-  const props = defineProps<{ originSceneCheckedList: CheckedSceneTemplate[] }>();
-  const emits = defineEmits(['update:sceneCheckedList']);
-
-  const sceneCheckedValues = ref({} as Record<number, boolean>);
-  const templateCheckedValues = ref({} as Record<number, number | null>);
-  const sceneCheckedList = ref<CheckedSceneTemplate[]>([]);
-
-  // Object 转换为 CheckedSceneTemplate
-  function getSceneCheckedList(obj: Record<number, number | null>): CheckedSceneTemplate[] {
-    return Object.entries(obj).map(([sceneId, templateId]) => ({
-      sceneId: Number(sceneId),
-      templateId: Number(templateId),
-    }));
-  }
-
-  function getTemplateCheckedValues(arr: CheckedSceneTemplate[]): Record<number, number | null> {
-    const result: Record<number, number | null> = {};
-    arr.forEach(({ sceneId, templateId }) => {
-      result[sceneId] = templateId;
-    });
-    return result;
-  }
-
-  function updateSceneCheckedList() {
-    sceneCheckedList.value = getSceneCheckedList(templateCheckedValues.value);
-    emits('update:sceneCheckedList', sceneCheckedList.value, sceneCheckedValues.value);
-  }
-
-  const handleSceneIdChange = (id) => {
-    if (!sceneCheckedValues.value[id]) delete templateCheckedValues.value[id];
-    updateSceneCheckedList();
-    for (let key in sceneCheckedValues.value) {
-      if (sceneCheckedValues.value.hasOwnProperty(key) && sceneCheckedValues.value[Number(key)] === false) {
-        delete sceneCheckedValues.value[Number(key)];
-      }
-    }
-  };
-
-  const handleTemplateIdChange = () => {
-    updateSceneCheckedList();
-  };
-
-  onMounted(() => {
-    if (props.originSceneCheckedList?.length) {
-      sceneCheckedValues.value = getSceneCheckedValues(props.originSceneCheckedList);
-      templateCheckedValues.value = getTemplateCheckedValues(props.originSceneCheckedList);
-    }
-  });
-</script>
-<script lang="ts">
-  export function getSceneCheckedValues(arr: CheckedSceneTemplate[]): Record<number, boolean> {
-    const result: Record<number, boolean> = {};
-    arr.forEach(({ sceneId }) => {
-      result[sceneId] = true;
-    });
-    return result;
-  }
-</script>
-
-<style scoped lang="less">
-  .scene-template-item {
-    width: 100%;
-    display: flex;
-    flex-direction: column;
-    margin-bottom: 10px;
-  }
-
-  .template-item {
-    padding: 5px 20px;
-    border-radius: 5px;
-    background: rgba(170, 170, 170, 0.1);
-    display: flex;
-
-    .template-item-tip {
-      width: 100px;
-      color: rgba(0, 0, 0, 0.4);
-    }
-
-    .template-item-list {
-      flex: 1;
-    }
-  }
-</style>

+ 0 - 166
src/views/cameras/overview/hooks/overviewColumns.ts

@@ -1,166 +0,0 @@
-import { h } from 'vue';
-import { ElSwitch, ElTag } from 'element-plus';
-import type { BasicColumn } from '@/components/Table';
-import connectedIcon from '@/assets/images/table/camera-netConnect.png';
-import unConnectedIcon from '@/assets/images/table/camera-netUnconnect.png';
-// import { protocalTypeSelect } from '@/types/camera/constant';
-import useCameraOverview from '../stores/useCameraOverview';
-import { updateCameraIntState } from '@/api/camera/camera-overview';
-import { useSceneTemplateList } from '../stores/useSceneTemplateList';
-import { storeToRefs } from 'pinia';
-
-const sceneTemplateListInfo = useSceneTemplateList();
-const { sceneTemplateList } = storeToRefs(sceneTemplateListInfo);
-
-const { getLabelById } = sceneTemplateListInfo;
-
-const cameraOverview = useCameraOverview();
-const { getState, getCameraItems } = cameraOverview;
-
-export const columns: BasicColumn[] = [
-  {
-    minWidth: 30,
-    type: 'selection',
-    // fixed: 'left',
-    align: 'center',
-  },
-  {
-    label: '序号',
-    minWidth: 60,
-    type: 'index',
-    // fixed: 'left',
-    align: 'center',
-  },
-  {
-    label: '设备ID',
-    prop: 'code',
-    minWidth: 100,
-    align: 'center',
-  },
-  {
-    label: '名称',
-    prop: 'name',
-    minWidth: 140,
-    align: 'center',
-  },
-  {
-    label: '业务场景',
-    prop: 'sceneTemplateList',
-    minWidth: 160,
-    align: 'center',
-    render(record) {
-      const tags = getLabelById(record.row.sceneTemplateList, sceneTemplateList.value);
-      const tag = tags.map((item) => h(ElTag, item));
-      return h(
-        'span',
-        {
-          style: 'display: flex; justify-content: center; flex-wrap: wrap; gap: 5px;',
-        },
-        tag,
-      );
-    },
-  },
-  {
-    label: '公司',
-    prop: 'companyName',
-    minWidth: 100,
-    align: 'center',
-  },
-  {
-    label: '车间',
-    prop: 'workshopName',
-    minWidth: 140,
-    align: 'center',
-  },
-  {
-    label: '工位',
-    prop: 'workspaceName',
-    minWidth: 140,
-    align: 'center',
-  },
-  {
-    label: '添加方式',
-    prop: 'sourceType',
-    minWidth: 100,
-    align: 'center',
-  },
-  // {
-  //   label: 'IP地址',
-  //   prop: 'cameraIp',
-  //   minWidth: 140,
-  // },
-  // {
-  //   label: '协议类型',
-  //   prop: 'cameraType',
-  //   minWidth: 120,
-  //   render(record) {
-  //     return h(
-  //       'span',
-  //       {},
-  //       {
-  //         default: () =>
-  //           protocalTypeSelect.find((item) => item.value === record.row.cameraType)?.label,
-  //       },
-  //     );
-  //   },
-  // },
-  // {
-  //   label: '端口地址',
-  //   prop: 'cameraPort',
-  //   minWidth: 120,
-  // },
-  // {
-  //   label: 'MAC地址',
-  //   prop: 'cameraMac',
-  //   minWidth: 140,
-  // },
-  {
-    label: '联网状态',
-    prop: 'networkingState',
-    render(record) {
-      return h(
-        'img',
-        {
-          src: record.row.networkingState === 0 ? connectedIcon : unConnectedIcon,
-          style:
-            'width: 20px; height: 20px; object-fit: fill; display: inline-block; line-height: 20px; vertical-align: middle;',
-        },
-        {},
-      );
-    },
-    minWidth: 120,
-    align: 'center',
-    sortable: 'custom',
-  },
-  {
-    label: '是否进入平台',
-    prop: 'integrationState',
-    render(record) {
-      return h(
-        ElSwitch,
-        {
-          modelValue: record.row.integrationState,
-          onChange: (val) => {
-            record.row.status = val;
-            updateCameraIntState({ cameraId: record.row.id, intState: val as number }).then(() => {
-              getState();
-              getCameraItems();
-            });
-          },
-          activeValue: 0,
-          inactiveValue: 1,
-        },
-        {},
-      );
-    },
-    minWidth: 140,
-    align: 'center',
-    sortable: 'custom',
-  },
-  {
-    label: '备注',
-    prop: 'remark',
-    minWidth: 140,
-    align: 'center',
-  },
-];

+ 0 - 53
src/views/cameras/overview/hooks/searchRangeColumns.ts

@@ -1,53 +0,0 @@
-import type { BasicColumn } from '@/components/Table';
-
-export const columns: BasicColumn[] = [
-  {
-    minWidth: 30,
-    type: 'selection',
-    fixed: 'left',
-    selectable(row, _) {
-      return row.name === 'SHGD-XDJS-0003';
-    },
-  },
-  {
-    label: '序号',
-    minWidth: 40,
-    type: 'index',
-    fixed: 'left',
-  },
-  {
-    label: 'IP地址',
-    prop: 'cameraIp',
-    minWidth: 80,
-  },
-  {
-    label: '协议类型',
-    prop: 'protocal',
-    minWidth: 60,
-  },
-  {
-    label: '端口地址',
-    prop: 'cameraPort',
-    minWidth: 60,
-  },
-  {
-    label: 'MAC地址',
-    prop: 'mac',
-    minWidth: 100,
-  },
-  {
-    label: '设备ID',
-    prop: 'name',
-    minWidth: 110,
-  },
-  {
-    label: '车间场景',
-    prop: 'workshopId',
-    minWidth: 100,
-  },
-  {
-    label: '工位场景',
-    prop: 'workspaceId',
-    minWidth: 60,
-  },
-];

+ 0 - 166
src/views/cameras/overview/hooks/sharedColumns.ts

@@ -1,166 +0,0 @@
-import { h } from 'vue';
-import type { BasicColumn } from '@/components/Table';
-import { protocalTypeSelect } from '@/types/camera/constant';
-import useSceneInfos from '@/hooks/useSceneInfos';
-
-// export const columns: BasicColumn[] = [
-//   {
-//     label: '序号',
-//     minWidth: 60,
-//     type: 'index',
-//     fixed: 'left',
-//   },
-//   {
-//     label: 'IP地址',
-//     prop: 'cameraIp',
-//     minWidth: 140,
-//   },
-//   {
-//     label: '协议类型',
-//     prop: 'cameraType',
-//     minWidth: 120,
-//     render(record) {
-//       return h(
-//         'span',
-//         {},
-//         {
-//           default: () => {
-//             return protocalTypeSelect.find((item) => item.value === record.row.cameraType)?.label;
-//           },
-//         },
-//       );
-//     },
-//   },
-//   {
-//     label: '端口地址',
-//     prop: 'cameraPort',
-//     minWidth: 120,
-//   },
-//   {
-//     label: '企业账号',
-//     prop: 'tenantCode',
-//     minWidth: 140,
-//   },
-//   {
-//     label: '企业名称',
-//     prop: 'tenantName',
-//     minWidth: 140,
-//   },
-//   {
-//     label: '设备ID',
-//     prop: 'cameraCode',
-//     minWidth: 150,
-//   },
-//   {
-//     label: '车间场景',
-//     prop: 'workspaceName',
-//     minWidth: 140,
-//   },
-//   {
-//     label: '工位场景',
-//     prop: 'cameraWorkspace',
-//     minWidth: 140,
-//     render(record) {
-//       const sceneInfos = useSceneInfos();
-//       const { flattendWorkspaces } = sceneInfos;
-//       return h(
-//         'span',
-//         {},
-//         {
-//           default: () => {
-//             const code = flattendWorkspaces.value.find(
-//               (item) => item.code === record.row.cameraWorkspace,
-//             );
-//             console.log('flattendWorkspaces', flattendWorkspaces.value);
-
-//             console.log('record.row.cameraWorkspace', code);
-//             return record.row.cameraWorkspace;
-//             return flattendWorkspaces.value.find((item) => item.code === record.row.cameraWorkspace)
-//               ?.id;
-
-//             // return protocalTypeSelect.find((item) => item.value === record.row.cameraType)?.label;
-//           },
-//         },
-//       );
-//     },
-//   },
-// ];
-
-export const getColumns = (flattendWorkspaces): BasicColumn[] => {
-  return [
-    {
-      label: '序号',
-      minWidth: 60,
-      type: 'index',
-      fixed: 'left',
-    },
-    {
-      label: 'IP地址',
-      prop: 'cameraIp',
-      minWidth: 140,
-    },
-    {
-      label: '协议类型',
-      prop: 'cameraType',
-      minWidth: 120,
-      render(record) {
-        return h(
-          'span',
-          {},
-          {
-            default: () => {
-              return protocalTypeSelect.find((item) => item.value === record.row.cameraType)?.label;
-            },
-          },
-        );
-      },
-    },
-    {
-      label: '端口地址',
-      prop: 'cameraPort',
-      minWidth: 120,
-    },
-    {
-      label: '企业账号',
-      prop: 'tenantCode',
-      minWidth: 140,
-    },
-    {
-      label: '企业名称',
-      prop: 'tenantName',
-      minWidth: 140,
-    },
-    {
-      label: '设备ID',
-      prop: 'code',
-      minWidth: 150,
-    },
-    {
-      label: '车间场景',
-      prop: 'workspaceName',
-      minWidth: 140,
-    },
-    {
-      label: '工位场景',
-      prop: 'cameraWorkspace',
-      minWidth: 140,
-      render(record) {
-        // const sceneInfos = useSceneInfos();
-        // const { flattendWorkspaces } = sceneInfos;
-        return h(
-          'span',
-          {},
-          {
-            default: () => {
-              return flattendWorkspaces?.find(
-                (item) => item.id === Number(record.row.cameraWorkspace),
-              )?.name;
-
-              // return protocalTypeSelect.find((item) => item.value === record.row.cameraType)?.label;
-            },
-          },
-        );
-      },
-    },
-  ];
-};

+ 0 - 92
src/views/cameras/overview/hooks/useCameraShare.ts

@@ -1,92 +0,0 @@
-import { ref } from 'vue';
-import {
-  CameraShareType,
-  CameraShareQueryType,
-  getShareCameraList,
-  editShareCameraList,
-  delShareCameraList,
-  addShareCameraList,
-} from '@/api/camera/camera-share';
-
-export const useCameraShared = () => {
-  const cameraShareList = ref<CameraShareType[]>([]);
-  const queryName = ref<string>();
-  const queryAccount = ref<string>('');
-  const isAddState = ref<boolean | number>(-1);
-  const queryCameraId = ref<number | undefined>(-1);
-  const queryToTenantId = ref<number>(-1);
-  const totalRow = ref(0);
-  const page = ref(1);
-  const size = ref(100);
-
-  // 条件查询事件
-  const conditionSearch = () => {
-    const param = {
-      pageNumber: page.value,
-      pageSize: size.value === 0 ? 1 : size.value,
-      cameraId: -1,
-      isAdd: -1,
-      toTenantId: -1,
-    };
-    //先获取总数作为
-    getShareCameraList(param).then((res) => {
-      size.value = res.totalRow === 0 ? 1 : res.totalRow;
-      const params: CameraShareQueryType = {
-        pageNumber: page.value,
-        pageSize: size.value,
-        isAdd: isAddState.value,
-      };
-      if (queryName.value) {
-        params.tenantName = queryName.value;
-      }
-
-      if (queryAccount.value) {
-        params.tenantCode = queryAccount.value;
-      }
-      if (queryCameraId.value) {
-        params.cameraId = queryCameraId.value;
-      }
-      if (queryToTenantId.value) {
-        params.toTenantId = queryToTenantId.value;
-      }
-      getShareCameraList(params).then((res) => {
-        cameraShareList.value = res.records;
-        totalRow.value = res.totalRow;
-      });
-    });
-  };
-
-  const handleAdd = (data: CameraShareType) => {
-    addShareCameraList(data).then(() => {
-      conditionSearch();
-    });
-  };
-
-  const handleDel = (id: number) => {
-    delShareCameraList(id).then(() => {
-      conditionSearch();
-    });
-  };
-
-  const handleEdit = (data: CameraShareType) => {
-    editShareCameraList(data).then(() => {
-      conditionSearch();
-    });
-  };
-
-  return {
-    cameraShareList,
-    totalRow,
-    queryName,
-    queryAccount,
-    isAddState,
-    queryCameraId,
-    queryToTenantId,
-    conditionSearch,
-    handleDel,
-    handleAdd,
-    handleEdit,
-  };
-};
-
-export default useCameraShared;

+ 0 - 33
src/views/cameras/overview/hooks/useNvrDevice.ts

@@ -1,33 +0,0 @@
-/**
- * description: NVR方式添加相机时,选择的NVR设备列表
- */
-
-import { ref } from 'vue';
-import { getAllNVRList } from '@/api/camera/camera-nvr';
-
-interface NvrDevice {
-  id: number; // nvrId
-  label: string; // Nvr展示格式
-}
-
-export function useNvrDevice() {
-  const nvrDevice = ref<NvrDevice[]>([]);
-
-  const getNvrDevice = async () => {
-    await getAllNVRList().then((res) => {
-      nvrDevice.value = res.map((item) => {
-        return {
-          id: item.id,
-          label: `${item.name}(${item.code})`,
-        };
-      });
-    });
-  };
-
-  return {
-    nvrDevice,
-    getNvrDevice,
-  };
-}
-
-export default useNvrDevice;

+ 0 - 80
src/views/cameras/overview/hooks/useTreeWorkspaceInfo.ts

@@ -1,80 +0,0 @@
-/**
- * description:
- * 获取公司-车间-工位(树结构)信息,适用于添加相机(三种方式)- 所属工位下拉框选项
- */
-import { ref } from 'vue';
-import { getTreeWorkspaceInfo } from '@/api/camera/camera-overview';
-
-interface TreeWorkspaceInfoType {
-  id: number; // 自增主键
-  name: string; // 公司名称
-  code?: string; // 公司编号
-  nodeType: 'company' | 'workshop' | 'workspace'; // 节点类型
-  workshopId?: number; // nodeType=workspace时携带车间Id
-  principalName?: string; // nodeType=workspace时携带负责人name
-  children?: TreeWorkspaceInfoType[];
-}
-
-interface ElTreeItem {
-  value: string;
-  label: string;
-  children?: ElTreeItem[];
-  // disabled?: boolean;
-  workshopId?: number;
-  principalName?: string;
-}
-
-export function useTreeWorkspaceInfo() {
-  const workspaceInfo = ref<ElTreeItem[]>([]);
-
-  function setTreeWorkspaceInfo(infos: TreeWorkspaceInfoType[], currentDepth = 1) {
-    const result = [] as ElTreeItem[];
-    if (!Array.isArray(infos)) {
-      return result;
-    }
-    for (const item of infos) {
-      const newItem = {
-        value: `${item.nodeType}-${item.id}`,
-        label: item.name,
-        workshopId: item.workshopId,
-        principalName: item.principalName,
-        // disabled: item.nodeType === 'workspace' ? false : true,
-        children: [] as ElTreeItem[],
-      };
-      if (currentDepth === 3) {
-        result.push(newItem);
-      } else if (item.children && item.children.length > 0) {
-        const childResults = setTreeWorkspaceInfo(item.children, currentDepth + 1);
-        if (childResults.length > 0) {
-          // 如果子节点中有深度为 3 的节点,保留当前节点并添加子结果
-          newItem.children = childResults;
-          result.push(newItem);
-        }
-      }
-    }
-    return result;
-  }
-
-  const getWorkspaceIdFromTreeNode = (inputStr: string) => {
-    let dashIndex = inputStr.indexOf('-');
-    if (dashIndex !== -1 && dashIndex < inputStr.length - 1) {
-      return inputStr.slice(dashIndex + 1);
-    } else {
-      return '';
-    }
-  };
-
-  const getWorkspaceFromTreeInfo = async () => {
-    await getTreeWorkspaceInfo().then((res) => {
-      workspaceInfo.value = setTreeWorkspaceInfo(res);
-    });
-  };
-
-  return {
-    workspaceInfo,
-    getWorkspaceFromTreeInfo,
-    getWorkspaceIdFromTreeNode,
-  };
-}
-
-export default useTreeWorkspaceInfo;

+ 0 - 167
src/views/cameras/overview/stores/useCameraOverview.ts

@@ -1,167 +0,0 @@
-import { ref } from 'vue';
-import { defineStore } from 'pinia';
-import {
-  CameraQueryParamDetails,
-  CameraQueryParams,
-  getCameraList,
-  addCameraItem,
-  updateCameraItem,
-  getCameraStateByCodes,
-} from '@/api/camera/camera-overview';
-import { CameraAddItem, CameraDetailServer } from '@/types/camera/type';
-import { useRequest } from 'vue-hooks-plus';
-
-const ALL = -1;
-
-export const useCameraOverview = defineStore('camera-overview', () => {
-  const queryType = ref('');
-  const queryTypeContent = ref('');
-  const queryCameraType = ref('');
-  const queryWorkSpaces = ref<number[]>([]);
-  const querySourceType = ref('');
-  const networkingState = ref<number>(ALL);
-  const integrationState = ref<number>(ALL);
-  const openEagle = ref<number>(ALL);
-  const total = ref(0);
-  const page = ref(1);
-  const size = ref(10);
-
-  let interval;
-
-  const cameraItems = ref<CameraDetailServer[]>([]);
-
-  // 条件查询事件
-  const conditionSearch = () => {
-    const paramDetails = ref({} as CameraQueryParamDetails);
-    const params: CameraQueryParams = {
-      pageNumber: page.value,
-      pageSize: size.value,
-      queryParam: paramDetails.value,
-    };
-    if (queryType.value) {
-      switch (queryType.value) {
-        case 'cameraIp':
-          paramDetails.value.ip = queryTypeContent.value;
-          break;
-
-        case 'name':
-          paramDetails.value.code = queryTypeContent.value;
-          break;
-      }
-    }
-    if (queryCameraType.value) {
-      paramDetails.value.cameraType = queryCameraType.value;
-    }
-    if (queryWorkSpaces.value) {
-      paramDetails.value.workspaceIdList = queryWorkSpaces.value;
-    }
-    if (querySourceType.value) {
-      paramDetails.value.sourceType = querySourceType.value;
-    }
-    if (networkingState.value != ALL) {
-      paramDetails.value.networkingState = networkingState.value;
-    }
-    if (integrationState.value != ALL) {
-      paramDetails.value.integrationState = integrationState.value;
-    }
-    if (openEagle.value != ALL) {
-      paramDetails.value.openEagle = openEagle.value;
-    }
-    return getCameraList(params).then((res) => {
-      return res;
-    });
-  };
-
-  const { loading, run: getCameraItems } = useRequest(conditionSearch, {
-    manual: true,
-    onSuccess: (res) => {
-      cameraItems.value = [...res.records];
-      total.value = res.totalRow;
-    },
-  });
-
-  const addCamera = (data: CameraAddItem) => {
-    return addCameraItem(data).then(() => {
-      getCameraItems();
-    });
-  };
-
-  const addSRSCamera = (data) => {
-    return addCameraItem(data).then(() => {
-      getCameraItems();
-    });
-  };
-
-  const addNVRCamera = (data) => {
-    return addCameraItem(data).then(() => {
-      getCameraItems();
-    });
-  };
-
-  const editCamera = (data) => {
-    return updateCameraItem(data);
-    // .then(() => {
-    //   getCameraItems();
-    // });
-  };
-
-  const getState = () => {
-    getCameraStateByCodes({ cameraCodeList: cameraItems.value.map((camera) => camera.code) }).then((res) => {
-      res.forEach((item) => {
-        const targetObj = cameraItems.value.find((camera) => camera.code === item.cameraCode);
-        if (targetObj) targetObj.networkingState = Number(item.networkingState);
-      });
-    });
-  };
-
-  const openInterval = () => {
-    setTimeout(() => {
-      getState();
-    }, 500);
-    interval = setInterval(() => {
-      getState();
-    }, 30000);
-  };
-
-  const closeInterval = () => {
-    clearInterval(interval);
-  };
-
-  const reset = () => {
-    queryType.value = '';
-    queryTypeContent.value = '';
-    queryCameraType.value = '';
-    queryWorkSpaces.value = [];
-    total.value = 0;
-    page.value = 1;
-    size.value = 10;
-    cameraItems.value = [];
-  };
-
-  return {
-    queryType,
-    queryTypeContent,
-    queryCameraType,
-    querySourceType,
-    queryWorkSpaces,
-    integrationState,
-    openEagle,
-    networkingState,
-    cameraItems,
-    loading,
-    total,
-    size,
-    page,
-    getCameraItems,
-    addCamera,
-    editCamera,
-    openInterval,
-    closeInterval,
-    getState,
-    addSRSCamera,
-    addNVRCamera,
-    reset,
-  };
-});
-
-export default useCameraOverview;

+ 0 - 38
src/views/cameras/overview/stores/useSceneTemplateList.ts

@@ -1,38 +0,0 @@
-/**
- * description:
- * 1. 获取业务场景模版信息
- * 2. 反显列表显示信息
- */
-
-import { ref } from 'vue';
-import { SceneListInfo } from '@/types/business-scene/type';
-import { CheckedSceneTemplate } from '@/types/camera/type';
-import { getSceneList } from '@/api/sys-config/business-scene';
-import { defineStore } from 'pinia';
-
-export const useSceneTemplateList = defineStore('scene-template', () => {
-  const sceneTemplateList = ref<SceneListInfo[]>([]);
-
-  const getSceneTemplateList = async () => {
-    await getSceneList().then((res) => {
-      sceneTemplateList.value = res;
-    });
-  };
-
-  const getLabelById = (arr: CheckedSceneTemplate[], list: SceneListInfo[]): string[] => {
-    const result = [] as string[];
-    arr.forEach((item) => {
-      const targetObj = list.find((obj) => obj.id === item.sceneId);
-      if (targetObj) result.push(targetObj.name);
-    });
-    return result;
-  };
-
-  return {
-    sceneTemplateList,
-    getSceneTemplateList,
-    getLabelById,
-  };
-});
-
-export default useSceneTemplateList;

+ 0 - 108
src/views/cameras/overview/stores/useSharedCamera.ts

@@ -1,108 +0,0 @@
-import { computed, ref } from 'vue';
-import { defineStore } from 'pinia';
-import { CameraSharedItem } from '../../../../types/camera/constant';
-import { ElMessage } from 'element-plus';
-
-export const useCameraShare = defineStore('camera-share', () => {
-  const cameraCompleted = ref<CameraSharedItem[]>([
-    {
-      cameraIp: '172.13.25.0000',
-      cameraType: 'haikang',
-      cameraPort: '11',
-      companyAccount: 111,
-      companyName: '1111',
-      code: 'C919-140',
-      workshopName: 'C919车间',
-      workspaceName: '东侧',
-      shareState: 'complete',
-      password: '11',
-      username: '22',
-    },
-  ]);
-
-  const cameraIncompleted = ref<CameraSharedItem[]>([
-    {
-      cameraIp: '172.13.25.0011',
-      cameraType: 'haikang',
-      cameraPort: '11',
-      companyAccount: 111,
-      companyName: '1111',
-      code: 'C919-141',
-      workshopName: 'C919车间',
-      workspaceName: '西侧',
-      shareState: 'incomplete',
-      password: '11',
-      username: '22',
-    },
-    {
-      cameraIp: '172.13.25.0009',
-      cameraType: 'haikang',
-      cameraPort: '11',
-      companyAccount: 111,
-      companyName: '1111',
-      code: 'C919-142',
-      workshopName: 'C919车间',
-      workspaceName: '北侧',
-      shareState: 'incomplete',
-      password: '11',
-      username: '22',
-    },
-  ]);
-
-  const queryName = ref<string>();
-  const queryAccount = ref<string>();
-
-  const unAddlength = computed(() => {
-    return cameraIncompleted.value.length;
-  });
-
-  const handleAdd = (row, addCameraType) => {
-    if (addCameraType === 'complete') return;
-    const currentData = cameraIncompleted.value.find((item) => (item.cameraIp = row.cameraIp));
-    const indexToRemove = cameraIncompleted.value.findIndex(
-      (item) => item.cameraIp === row.cameraIp,
-    );
-    if (indexToRemove !== -1) {
-      cameraIncompleted.value.splice(indexToRemove, 1);
-    }
-    if (currentData) {
-      cameraCompleted.value.push(currentData!);
-    }
-    ElMessage({
-      message: '添加成功',
-      type: 'success',
-    });
-  };
-
-  const handleDelete = (row, addCameraType) => {
-    if (addCameraType === 'complete') {
-      const indexToRemove = cameraCompleted.value.findIndex(
-        (item) => item.cameraIp === row.cameraIp,
-      );
-      cameraCompleted.value.splice(indexToRemove, 1);
-    } else {
-      const indexToRemove = cameraIncompleted.value.findIndex(
-        (item) => item.cameraIp === row.cameraIp,
-      );
-      cameraIncompleted.value.splice(indexToRemove, 1);
-    }
-  };
-
-  const resetSearch = () => {
-    queryName.value = '';
-    queryAccount.value = '';
-  };
-
-  return {
-    queryName,
-    queryAccount,
-    cameraCompleted,
-    cameraIncompleted,
-    unAddlength,
-    handleAdd,
-    handleDelete,
-    resetSearch,
-  };
-});
-
-export default useCameraShare;

+ 0 - 65
src/views/cameras/preview/CameraPreview.vue

@@ -1,65 +0,0 @@
-<template>
-  <div class="container-box">
-    <div class="tabs">
-      <div class="tab" :class="{ active: activeName === 'single' }" @click="handleChangeTab('single')"> 单相机配置 </div>
-      <div class="tab" :class="{ active: activeName === 'group' }" @click="handleChangeTab('group')"> 组相机配置 </div>
-    </div>
-    <component :is="currentComponent" />
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { computed, ref } from 'vue';
-  import { useRouter, useRoute } from 'vue-router';
-  import CameraConfigSingle from './components/CameraConfigSingle/CameraConfigSingle.vue';
-  import CameraConfigGroup from './components/CameraConfigGroup/CameraConfigGroup.vue';
-
-  const router = useRouter();
-  const route = useRoute();
-  const activeName = ref(route.query.type || 'single');
-  const handleChangeTab = (name: string) => {
-    activeName.value = name;
-    router.push({ path: '/algorithm/config', query: { type: name }})
-  }
-  const currentComponent = computed(() => {
-    return activeName.value === 'single' ? CameraConfigSingle : CameraConfigGroup;
-  });
-</script>
-
-<style lang="scss" scoped>
-  .container-box {
-    width: 100%;
-    height: 100%;
-    min-height: calc(100vh - 90px);
-    padding: 20px 20px 10px 20px;
-    background-color: rgba(255, 255, 255, 1);
-    border-radius: 10px;
-  }
-
-  .tabs {
-    display: flex;
-    margin-bottom: 20px;
-
-    .tab {
-      width: 125px;
-      height: 40px;
-      border: 1px solid #d9dce3;
-      border-radius: 5px;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      margin-right: 20px;
-      font-size: 15px;
-      letter-spacing: 1px;
-      cursor: pointer;
-    }
-
-    .tab.active,
-    .tab:hover {
-      color: #fff;
-      background-color: #409eff;
-      border: none;
-      font-weight: bold;
-    }
-  }
-</style>

+ 0 - 316
src/views/cameras/preview/components/CameraConfigGroup/CameraConfigGroup.vue

@@ -1,316 +0,0 @@
-<template>
-  <div class="cameraConfigGroup">
-    <el-button
-      type="primary"
-      @click="createGroupDialog = true"
-      style="margin: 10px 0;"
-      v-permission="{ action: [PERM_ALGO.CONFIG_ADD_GROUP] }"
-    >
-      <img src="@/assets/images/create.png" style="margin-top: -1px; margin-right: 5px" />新建相机分组
-    </el-button>
-    <el-table
-      :data="cameraGroupList"
-      :span-method="objectSpanMethod"
-      height="calc(100vh - 300px)"
-      style="width: 100%; margin-top: 16px; --el-table-border-color: none"
-      v-loading="loading"
-      :row-class-name="tableRowClassName"
-    >
-      <el-table-column prop="id" label="组序号"  width="70"/>
-      <el-table-column prop="cameraName" label="相机名称" align="center">
-        <template #default="scope">
-          <div class="cameraName-text" v-if="scope.row.isMainCamera === IsMainCamera.YES">
-            <el-icon><Star color="Gold" /></el-icon>
-            {{ scope.row.cameraName }}
-          </div>
-        </template>  
-      </el-table-column>
-      <el-table-column prop="cameraCode" label="设备ID"/>
-      <el-table-column prop="location" label="地点"/>
-      <el-table-column prop="algoName" label="算法">
-        <template #default="scope">
-          <div class="algoId-text" @click="handleView(scope.row)">
-            {{ scope.row.algoName }}
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" fixed="right" width="120px">
-        <template #default="scope">
-          <div class="operation">
-            <el-tooltip effect="light" content="关闭/开启" placement="bottom">
-              <el-switch 
-                :model-value="scope.row.status" 
-                :inactive-value="CameraGroupStatus.CLOSE"
-                :active-value="CameraGroupStatus.OPEN"
-                @update:model-value="(val) => handleSwitch(val, scope.row)"/>
-            </el-tooltip>
-            
-            <el-tooltip effect="light" content="删除" placement="bottom">
-              <img src="@/views/message/alarmMessages/img/delete.png" 
-              @click="handleDelete(scope.row)" 
-                v-permission="{ action: [PERM_ALGO.CONFIG_DELETE_GROUP] }"
-              />
-            </el-tooltip>
-          </div>
-        </template>
-      </el-table-column>
-
-      <template #empty>
-        <div class="emptyDiv">
-          <img src="@/assets/images/empty.png" class="emptyImg" />
-          <span class="emptySpan">暂无数据</span>
-        </div>
-      </template>
-    </el-table>
-    <section class="mt-4 flex justify-end">
-      <el-pagination
-        background
-        layout="total, sizes, prev, pager, next"
-        :page-sizes="[10, 30, 50]"
-        :total="total"
-        v-model:page-size="requestParams.pageSize"
-        v-model:current-page="requestParams.pageNumber"
-        @change="queryCameraGroupPage"
-      />
-    </section>
-    <!-- </el-card> -->
-
-    <!--删除弹窗 -->
-    <el-dialog v-model="deleteDialog" width="424px" top="20%" class="deleteDialog">
-      <template #header="">
-        <div class="deleteDialogHeader">
-          <img src="@/assets/images/deleteTip.png" class="deleteTip" />
-          <span class="titleSpan">请确认删除该相机分组吗?</span>
-        </div>
-      </template>
-      <span style="margin-left: 37px">删除之后,该组多相机检测将失效!</span>
-      <div class="dialogBottom">
-        <el-button class="dialogBtn" @click="deleteDialog = false">取消</el-button>
-        <el-button class="dialogBtn" type="primary" @click="confirmDelete">确定</el-button>
-      </div>
-    </el-dialog>
-
-    <!-- 新增相机分组弹窗 -->
-    <el-dialog v-model="createGroupDialog" width="70%" top="15%" left="25%" class="deleteDialog" title="设置相机组" @close="handleCancle">
-    <SettingCamera ref="settingCameraRef"/>
-      <div class="dialogBottom">
-        <el-button class="dialogBtn" @click="handleCancle">取消</el-button>
-        <el-button class="dialogBtn" type="primary" @click="handleCreateGroup">确定</el-button>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { onMounted, ref } from 'vue';
-import { useRouter } from 'vue-router';
-import { ElMessage } from 'element-plus';
-import { Star } from '@element-plus/icons-vue';
-import useCameraGroupQuery from './hooks/useCameraGroupQuery';
-import { CameraGroupTableItem, CameraGroupStatus, IsMainCamera } from '@/types/camera/camera-preview';
-import { deleteDetectionGroup, updateGroupStatus, saveDetectionGroup } from '@/api/camera/camera-preview-group';
-import SettingCamera from './components/SettingCamera.vue'
-import { PERM_ALGO } from '@/types/permission/constants';
-
-const router = useRouter();
-const { requestParams, total, queryCameraGroupPage, cameraGroupList, loading } = useCameraGroupQuery();
-const createGroupDialog = ref(false);
-const deleteDialog = ref(false);
-const cameraDetectionGroupId = ref();
-
-const tableRowClassName = ({
-  row,
-}: {
-  row: CameraGroupTableItem
-}) => {
-  // 根据分组ID计算颜色索引(使用模运算实现颜色循环)
-  const groupColors = ['normal', 'active'];
-  const groupId = row.cameraDetectionGroupId;
-  return groupColors[groupId % 3];
-}
-
-const objectSpanMethod = ({
-  row,
-  rowIndex,
-  columnIndex,
-}) => {
-  // 合并组序列和操作列
-  if (columnIndex === 0 || columnIndex === 5) {
-    const list = cameraGroupList.value;
-    const groupId = row.cameraDetectionGroupId;
-    const firstIndex = list.findIndex(item => item.cameraDetectionGroupId === groupId);
-    
-    if (rowIndex !== firstIndex) {
-      return { rowspan: 0, colspan: 0 };
-    }
-    
-    let rowCount = 0;
-    for (let i = firstIndex; i < list.length; i++) {
-      if (list[i].cameraDetectionGroupId === groupId) rowCount++;
-      else break;
-    }
-    
-    return {
-      rowspan: rowCount,
-      colspan: 1
-    };
-  }
-};
-
-const handleDelete = (row: CameraGroupTableItem) => {
-  if (row.status === CameraGroupStatus.OPEN) {
-    ElMessage({
-      message: '开启状态的分组不可删除',
-      type: 'warning',
-      plain: true,
-    });
-  } else {
-    deleteDialog.value = true;
-    cameraDetectionGroupId.value = row.cameraDetectionGroupId;
-  }
-}
-
-const handleSwitch = (newStatus: number, row: CameraGroupTableItem) => {
-  const data = {
-    cameraDetectionGroupId: row.cameraDetectionGroupId,
-    status: newStatus,
-  }
-  updateGroupStatus(data).then(res => {
-    ElMessage.success('操作成功')
-    queryCameraGroupPage();
-  })
-}
-
-const confirmDelete = () => {
-  deleteDetectionGroup([Number(cameraDetectionGroupId.value)]).then(() => {
-    ElMessage({
-      message: '删除成功',
-      type: 'success',
-      plain: true,
-    });
-    deleteDialog.value = false;
-    queryCameraGroupPage();
-  })
-  
-}
-
-const settingCameraRef = ref<InstanceType<typeof SettingCamera>>();
-const handleCreateGroup = () => {
-  const { valid, data } = settingCameraRef.value?.isValidate();
- 
-  if(valid) {
-    // 执行提交逻辑
-    const saveData = data.map(item => {
-      return {
-        cameraId: Number(item.code),
-        algoId: Number(item.algoCode),
-        isMainCamera: item.isMainCamera,
-      }
-    })
-    
-    saveDetectionGroup(saveData).then(() => {
-      ElMessage({
-        message: '相机组添加成功',
-        type:'success',
-        plain: true,
-      });
-      createGroupDialog.value = false;
-      settingCameraRef.value?.clearForm();
-      queryCameraGroupPage();
-    })
-  }
-}
-
-const handleCancle = () => {
-  createGroupDialog.value = false
-  settingCameraRef.value?.clearForm();
-}
-
-const handleView = (row: CameraGroupTableItem) => {
-  router.push({
-    path: '/algorithm/camera-group',
-    query: {
-      groupId: row.cameraDetectionGroupId,
-      cameraId: row.cameraId
-    }
-  })
-}
-
-onMounted(() => {
-  queryCameraGroupPage();
-})
-</script>
-
-<style lang="scss" scoped>
-  .emptyDiv {
-    margin-top: 78px;
-    margin: auto;
-    width: 396px;
-    .emptyImg {
-      height: 257px;
-    }
-    .emptySpan {
-      font-family: PingFangSC, PingFang SC;
-      font-weight: 400;
-      font-size: 18px;
-      color: rgba(0, 0, 0, 0.45);
-      text-align: left;
-      font-style: normal;
-    }
-  }
-
-  .algoId-text {
-    cursor: pointer;
-    color: #409eff;
-  }
-
-    .deleteDialog {
-    .deleteDialogHeader {
-      display: flex;
-      .deleteTip {
-        height: 24px;
-        width: 24px;
-      }
-      
-      .titleSpan {
-        height: 24px;
-        font-size: 16px;
-        color: rgba(0, 0, 0, 0.88);
-        line-height: 24px;
-        text-align: center;
-        margin-left: 12px;
-      }
-    }
-    .dialogBottom {
-      display: flex;
-      justify-content: flex-end;
-      margin-top: 12px;
-    }
-  }
-
-  .operation {
-    display: flex;
-    align-items: center;
-
-    img {
-      margin-left: 20px;
-    }
-    
-  }
-
- .el-table {
-    :deep(.normal) {
-      --el-table-tr-bg-color: #fff;
-      &:hover {
-        --el-table-tr-bg-color: #fff;
-      }
-    }
-    :deep(.active) {
-      --el-table-tr-bg-color: #fafafa;
-      &:hover {
-        --el-table-tr-bg-color: #fafafa;
-      }
-    }
-  }
-
-</style>

+ 0 - 492
src/views/cameras/preview/components/CameraConfigGroup/components/SettingCamera.vue

@@ -1,492 +0,0 @@
-<template>
-  <div class="setting-camera-page">
-    <div class="camera-item">
-      <p class="camera-header">
-        <el-input
-          placeholder="请输入相机名称或设备ID"
-          :prefix-icon="Search"
-          v-model="queryForm.queryString"
-          @keyup.enter="getCameraData"
-          clearable
-          @clear="getCameraData"
-        />
-      </p>
-      <div class="camera-content">
-        <el-scrollbar class="tree-scroll">
-          <CameraTreeCom
-            ref="treeRef"
-            :treeData="cameraTreeTemp"
-            :isShowCheckbox="true"
-            :enablePreview="true"
-            @node-click="handleNodeClick"
-            @check="handleTreeCheck"
-          />
-        </el-scrollbar>
-      </div>
-    </div>
-    <div class="camera-item">
-      <p class="camera-header"> 已选相机 </p>
-      <div class="camera-content">
-        <div class="select-item"  :class="item.isActive ? 'active' : ''" v-for="item in selectedCameraList" :key="item.code">
-          <div class="select-botton">
-            <el-icon @click="handleSelectIcon(item)"
-              ><Star :color="item.isMainCamera === IsMainCamera.YES ? 'Gold' : 'gray'"
-            /></el-icon>
-          </div>
-          <div class="select-content">
-            <div class="content-main" @click="handleSelect(item)">
-              <p class="name"  :class="item.algoName !== '' ? 'seleced-algo': ''">{{ item.name }}</p>
-              <p class="message">{{ item.algoName }}</p>
-            </div>
-            <el-icon class="delete-icon" @click="handleDelete(item)"><Close color="#333" /></el-icon>
-          </div>
-        </div>
-      </div>
-    </div>
-    <div class="camera-item">
-      <p class="camera-header"> 联合算法列表</p>
-      <div class="camera-content">
-        <div class="mb-2 ml-4">
-          <el-radio-group :model-value="selectedAlgo" @change="handleRiadoChange" v-if="groupAlgoData.length > 0">
-            <el-radio :value="item.code" size="large" v-for="item in groupAlgoData" :key="item.id">
-              {{ item.name }}</el-radio
-            >
-          </el-radio-group>
-          <p class="empty-data" v-else> 暂无数据</p>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { onMounted, ref } from 'vue';
-  import { Search, Star, Close } from '@element-plus/icons-vue';
-  import { ElMessage } from 'element-plus';
-  import { uid } from 'uid';
-  import { CameraTree, CameraTreeNodeType, CameraQueryForm } from '@/api/camera/camera-preview';
-  import { queryCameraTreeByCondition, getDetectionGroupLAlgoList } from '@/api/camera/camera-preview-group';
-  import { GropAlgoProps, SelectOption, IsMainCamera } from '@/types/camera/camera-preview';
-  import CameraTreeCom from '@/modules/camera-tree/CameraTree.vue';
-  import { IntegrationState } from '@/modules/camera-tree/types/constant';
-
-  interface CameraTreeTempType extends CameraTree {
-    tempCode?: string;
-  }
-
-  const queryForm = ref<CameraQueryForm>({
-    isEnableAlgo: false,
-    isEnableRender: false,
-    queryString: '',
-  });
-
-  const cameraTreeTemp = ref<CameraTreeTempType[]>([]); // 保存修改name之后的树
-  const selectedCameraList = ref<SelectOption[]>([]); // 保存选中的算法列表
-  const handleNodeClick = (e: CameraTreeTempType) => {
-    selectedAlgo.value = '';
-    if (e.nodeType === CameraTreeNodeType.camera) {
-      if (selectedCameraList.value.some((item) => item.code === e.id)) {
-        ElMessage({
-          message: '该相机已被选中',
-          type: 'warning',
-          plain: true,
-        });
-        return;
-      }
-
-      if (e.integrationState === IntegrationState.DISABLED) {
-        ElMessage({
-          message: '该相机未开启',
-          type: 'warning',
-          plain: true,
-        });
-        return;
-      }
-
-      selectedCameraList.value.push({
-        code: e.id,
-        name: e.name,
-        isMainCamera: IsMainCamera.NO,
-        algoName: '',
-        algoCode: '',
-        isActive: false,
-      });
-
-      // 获取当前节点在树中的完整节点对象
-      const treeNode = treeRef.value?.getCheckedNodes(e.tempCode);
-      // 勾选当前节点
-      treeRef.value?.setChecked(treeNode, true, false);
-      // 递归勾选所有父节点
-      const checkParentNodes = (node: Node) => {
-        if (node.parent) {
-          treeRef.value?.setChecked(node.parent, true, false);
-          checkParentNodes(node.parent);
-        }
-      };
-
-      if (treeNode.parent) {
-        checkParentNodes(treeNode.parent);
-      }
-      updateMainCamera(); 
-    }
-  };
-
-  const handleTreeCheck = (node: CameraTreeTempType, checked: { checkedNodes: CameraTreeTempType[] }) => {
-    selectedAlgo.value = '';
-    // 获取当前所有选中节点中的相机节点
-    const currentCameraNodes = checked.checkedNodes.filter(
-      (n) => n.nodeType === CameraTreeNodeType.camera && n.integrationState !== IntegrationState.DISABLED,
-    );
-
-    // 检查并过滤禁用节点
-    const disabledNodes = checked.checkedNodes.filter(
-      (n) => n.nodeType === CameraTreeNodeType.camera && n.integrationState === IntegrationState.DISABLED,
-    );
-    disabledNodes.forEach((n) => {
-      treeRef.value?.setChecked(n.tempCode as string, false, true);
-    });
-
-    // 生成当前选中的code集合
-    const currentCodes = new Set(currentCameraNodes.map((n) => n.id));
-
-    // 精确同步选中列表:移除不在当前选中列表中的项
-    selectedCameraList.value = selectedCameraList.value.filter((item) => currentCodes.has(item.code));
-
-    // 添加新选中的项
-    currentCameraNodes.forEach((camera) => {
-      if (!selectedCameraList.value.some((item) => item.code === camera.id)) {
-        selectedCameraList.value.push({
-          code: camera.id,
-          name: camera.name.replace(/ \[\w+\] $/, ''),
-          isMainCamera: IsMainCamera.NO,
-          algoName: '',
-          algoCode: '',
-          isActive: false,
-        });
-      }
-    });
-    updateMainCamera(); 
-  };
-
-  const checkMainCameraExists = () => {
-    return selectedCameraList.value.some((item) => item.isMainCamera === IsMainCamera.YES);
-  };
-
-  // 更新主相机方法
-  const updateMainCamera = () => {
-    if (selectedCameraList.value.length === 0) return;
-    
-    // 如果没有主相机,设置第一个为主相机
-    if (!checkMainCameraExists()) {
-      selectedCameraList.value[0].isMainCamera = IsMainCamera.YES;
-    }
-  };
-
-  const getCameraData = async () => {
-    await queryCameraTreeByCondition(queryForm.value).then((res) => {
-      cameraTreeTemp.value = getCameraNameCode(res);
-    });
-  };
-
-  // 把树节点中所有 nodeType = camera 的 name 替换成 name + code
-  function getCameraNameCode(data) {
-    const cameraNameCode = data;
-    for (let i = 0; i < data.length; i++) {
-      const node = cameraNameCode[i];
-      node.tempCode = uid(); // 为相机树节点创建唯一code
-      if (node.nodeType === 'camera') {
-        node.name = node.name + ` [${node.code}] `;
-      }
-      if (node.children && node.children.length > 0) {
-        getCameraNameCode(node.children);
-      }
-    }
-    return cameraNameCode;
-  }
-
-  const groupAlgoData = ref<GropAlgoProps[]>([]);
-  const getGroupLAlgoList = () => {
-    getDetectionGroupLAlgoList().then((res) => {
-      groupAlgoData.value = res;
-    });
-  };
-
-  const handleSelect = (row: SelectOption) => {
-    if (groupAlgoData.value.length === 0) {
-      getGroupLAlgoList();
-    }
-    
-    selectedCameraList.value.map((item) => {
-      if (item.code === row.code) {
-        item.isActive = true;
-      } else {
-        item.isActive = false;
-      }
-    });
-    selectedAlgo.value = '';
-  };
-
-  const handleSelectIcon = (row: SelectOption) => {
-   
-    selectedCameraList.value.map((item) => {
-      if (item.code === row.code) {
-        item.isMainCamera = item.isMainCamera === IsMainCamera.YES ? IsMainCamera.NO : IsMainCamera.YES;
-      } else {
-        item.isMainCamera = IsMainCamera.NO;
-      }
-    });
-  };
-
-  const treeRef = ref<InstanceType<typeof CameraTreeCom>>();
-  const handleDelete = (row: SelectOption) => {
-    // 从已选列表删除
-    selectedCameraList.value = selectedCameraList.value.filter((item) => item.code !== row.code);
-
-    // 同步取消树节点的选中状态
-    const findNode = (nodes: CameraTreeTempType[]): CameraTreeTempType | undefined => {
-      for (const node of nodes) {
-        if (node.id === row.code && node.nodeType === CameraTreeNodeType.camera) return node;
-        if (node.children) {
-          const found = findNode(node.children);
-          if (found) return found;
-        }
-      }
-    };
-
-    const targetNode = findNode(cameraTreeTemp.value);
-    if (targetNode?.tempCode) {
-      treeRef.value?.setChecked(targetNode.tempCode, false, false);
-    }
-
-    updateMainCamera();
-    selectedAlgo.value = '';
-  };
-
-  const selectedAlgo = ref();
-  const handleRiadoChange = (value) => {
-    const selectedCameraItem = selectedCameraList.value.filter((item) => item.isActive);
-    if (selectedCameraItem.length === 0) {
-      ElMessage({
-        message: '请先选中的相机',
-        type: 'warning',
-        plain: true,
-      });
-      return;
-    }
-    const selectedAlgoItem = groupAlgoData.value.find((item) => item.code === value);
-
-    selectedCameraItem.forEach((item) => {
-      item.algoName = selectedAlgoItem?.name as unknown as string;
-      item.algoCode = selectedAlgoItem?.code as unknown as string;
-    });
-
-    selectedAlgo.value = value;
-  };
-
-
-
-
-  const isValidate = () => {
-    // 校验至少选择两个相机
-    if (selectedCameraList.value.length < 2) {
-      ElMessage.error('请至少选择两个相机');
-      return { valid: false, message: '相机数量不足' };
-    }
-
-    // 校验所有选中相机都已配置算法
-    const unsetAlgoCameras = selectedCameraList.value.filter((item) => !item.algoCode || item.algoCode === '');
-
-    if (unsetAlgoCameras.length > 0) {
-      ElMessage.error('存在未选择算法的相机');
-      return { valid: false, message: '算法未配置完整' };
-    }
-
-    return { valid: true, data: selectedCameraList.value };
-  };
-
-  // 重置设置相机组
-  const clearForm = () => {
-    selectedCameraList.value = [];
-    selectedAlgo.value = '';
-    queryForm.value = {
-      isEnableAlgo: false,
-      isEnableRender: false,
-      queryString: '',
-    };
-    //  清除树组件的所有选中状态
-    if (treeRef.value) {
-      treeRef.value.setCheckedKeys([]);
-    }
-  };
-
-  // 暴露校验方法给父组件
-  defineExpose({
-    isValidate,
-    clearForm,
-  });
-
-  onMounted(() => {
-    getCameraData();
-    // getGroupLAlgoList();
-  });
-</script>
-
-<style scoped lang="scss">
-  .setting-camera-page {
-    width: 100%;
-    height: 100%;
-    display: flex;
-    justify-content: center;
-    gap: 20px;
-
-    .camera-item {
-      flex: 1;
-
-      &:first-child {
-        .camera-header {
-          padding-left: 0;
-        }
-      }
-
-      .camera-header {
-        width: 100%;
-        height: 40px;
-        border-radius: 2px;
-        font-size: 15px;
-        line-height: 40px;
-        color: #333;
-        cursor: pointer;
-        background-color: #e6e0dc;
-        padding-left: 20px;
-        display: flex;
-        align-items: center;
-
-        :deep(.el-input--default) {
-          width: 95%;
-          margin: 0 auto;
-        }
-
-        :deep(.el-input__wrapper) {
-          border-radius: 50px;
-        }
-      }
-
-      .camera-content {
-        width: 100%;
-        height: 400px;
-        background-color: #fff;
-        overflow-y: auto;
-        border: 1px solid #dcdfe6;
-        padding: 10px 10px;
-
-        .select-item {
-          display: flex;
-          justify-content: center;
-          align-items: center;
-          margin-bottom: 10px;
-          padding: 2px 5px ;
-         
-          &:hover {
-            background-color: #f5f7fa;
-            
-            .delete-icon {
-              display: block;
-            }
-          }
-           
-
-          &:last-child {
-            margin-bottom: 0;
-          }
-
-          .select-botton {
-            cursor: pointer;
-            display: flex;
-            align-items: center;
-          }
-
-          .select-content {
-            position: relative; 
-            margin-left: 5px;
-            width: 100%;
-
-            .name {
-              color: #333;
-              padding-left: 5px;
-            }
-
-            .message {
-              color: #dcdfe6;
-              padding-left: 5px;
-            }
-
-            .seleced-algo {
-              color: #0052d9;
-            }
-
-            &:hover {
-              .delete-icon {
-                display: block;
-              }
-            }
-           
-            .delete-icon {
-              // 新增删除图标样式
-              display: none;
-              position: absolute;
-              right: 5px;
-              top: 50%;
-              transform: translateY(-45%);
-              width: 16px;
-              height: 16px;
-              cursor: pointer;
-            }
-
-            .content-main {
-              // 新增内容容器
-              flex: 1;
-              cursor: pointer;
-            }
-
-           
-          }
-        }
-        .active {
-          // color: #0052d9;
-          background-color: #f5f7fa;
-        }
-        
-        .empty-data {
-          text-align: center;
-          height: 60px;
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          color: #909399;
-        }
-      }
-    }
-  }
-
-  .el-input__icon {
-    cursor: pointer;
-  }
-
-  .el-input__icon:hover {
-    color: #0052d9;
-  }
-
-  .cameraTreeCheckboxWrapper {
-    display: flex;
-    justify-content: space-between;
-
-    .el-checkbox {
-      margin-right: 0;
-    }
-  }
-
-  :deep(.el-radio-group) {
-    flex-direction: column;
-    align-items: flex-start;
-  }
-</style>

+ 0 - 51
src/views/cameras/preview/components/CameraConfigGroup/hooks/useCameraGroupQuery.ts

@@ -1,51 +0,0 @@
-import { reactive, ref, shallowRef } from 'vue';
-import { cloneDeep } from 'lodash-es';
-import { DEFAULT_PAGE_SIZE } from '@/types/common/constants';
-import { CameraPreviewRequest, CameraGroupTableItem, CameraGroupItem } from '@/types/camera/camera-preview';
-import { queryDetectionGroupList } from '@/api/camera/camera-preview-group';
-
-const defaultLoginLogRequest: CameraPreviewRequest = {
-  pageNumber: 1,
-  pageSize: DEFAULT_PAGE_SIZE,
-};
-
-export default function useLoginLogRequest() {
-  const requestParams = reactive<CameraPreviewRequest>(cloneDeep(defaultLoginLogRequest));
-  const cameraGroupList = shallowRef<CameraGroupTableItem[]>([]);
-  const total = ref(0);
-  const loading = ref(false);
-
-  const queryCameraGroupPage = async () => {
-    try {
-      loading.value = true;
-      const data = await queryDetectionGroupList(requestParams);
-      cameraGroupList.value = transformCameraGroupList(data.records);
-      total.value = data.totalRow;
-    } catch (error) {
-      console.log(error);
-    } finally {
-      loading.value = false;
-    }
-  };
-
-  const transformCameraGroupList = (data: CameraGroupItem[]) => {
-    let groupId = 0;
-    return data.flatMap(group => {
-      groupId++;
-      return group.groupDetailList.map(detail => ({
-        id: groupId,  // 添加自增ID
-        cameraDetectionGroupId: group.cameraDetectionGroupId,
-        status: group.status,
-        ...detail
-      }));
-    });
-  }
-
-  return {
-    requestParams,
-    total,
-    loading,
-    cameraGroupList,
-    queryCameraGroupPage,
-  };
-}

+ 0 - 258
src/views/cameras/preview/components/CameraConfigSingle/BatchOperationDialog.vue

@@ -1,258 +0,0 @@
-<template>
-  <el-dialog v-model="batchDialogVisible" width="50%" align-center :close-on-click-modal="false" @close="handleClose">
-    <template #header>
-      <div class="header-text">请选择需要{{ getOperationNameByType }}的算法:</div>
-    </template>
-    <div class="tips" v-if="type === 'set' && hasAlgosOfType">
-      <el-icon :size="15"><InfoFilled /></el-icon>
-      <div class="tip">以下为所选相机已添加的共同算法</div>
-    </div>
-    <div class="algos-list" v-if="hasAlgosOfType">
-      <div
-        v-for="(item, index) in algosList"
-        :key="index"
-        class="algo-item"
-        :class="{
-          'active-item': chooseAlgos.find((obj) => obj.algoId === item.algoId),
-          'added-item':
-            type === 'add' && algoStatusList?.savedAlgoJiaojiList?.find((obj) => obj.algoId === item.algoId),
-        }"
-        @click="
-          type === 'add' && algoStatusList?.savedAlgoJiaojiList?.find((obj) => obj.algoId === item.algoId)
-            ? null
-            : handleChangeChooseAlgos(item)
-        "
-      >
-        {{ item.algoName }}
-      </div>
-    </div>
-    <div v-else class="no-algo">
-      <img src="@/assets/images/no-algo.png" alt="" />
-      <div class="no-algo-tip">{{ getNoAlgoTip }}</div>
-    </div>
-    <template #footer v-if="hasAlgosOfType">
-      <div class="dialog-footer">
-        <el-button v-if="type === 'open' || type === 'close' || type === 'delete'" @click="handleChooseAllAlgos"
-          >全选</el-button
-        >
-        <el-button @click="resetChooseAlgos">重置</el-button>
-        <el-button type="primary" :disabled="chooseAlgos.length === 0" @click="handleConfirmOperation">
-          确认
-          <span v-if="chooseAlgos.length > 0">({{ chooseAlgos.length }}个算法)</span>
-        </el-button>
-      </div>
-    </template>
-  </el-dialog>
-</template>
-
-<script lang="ts" setup>
-  import { computed, onMounted, ref, watch } from 'vue';
-  import { ElDialog, ElButton, ElIcon } from 'element-plus';
-  import { InfoFilled } from '@element-plus/icons-vue';
-  import {
-    AlgoStruct,
-    QueryAlgoInfoRes,
-    QueryAlgoStatusByCameraIdRes,
-    getAlgoStatusByCameraIds,
-  } from '@/api/camera/camera-config';
-
-  const props = defineProps<{
-    type: string;
-    cameraIds: number[];
-    allAlgoList: QueryAlgoInfoRes[];
-  }>();
-  const emits = defineEmits(['onConfirm', 'onClose']);
-
-  const batchDialogVisible = ref(true);
-  const algoStatusList = ref<QueryAlgoStatusByCameraIdRes>(); // 当前选择的相机组的算法状态列表
-  const algosList = ref<AlgoStruct[] | undefined>([]); // 可选的算法列表
-  const chooseAlgos = ref<AlgoStruct[]>([]); // 选中的算法列表
-
-  const getOperationNameByType = computed(() => {
-    switch (props.type) {
-      case 'add':
-        return '添加';
-      case 'set':
-        return '设置参数';
-      case 'open':
-        return '开启';
-      case 'close':
-        return '关闭';
-      case 'delete':
-        return '删除';
-      default:
-        return '';
-    }
-  });
-
-  const hasAlgosOfType = computed(() => {
-    switch (props.type) {
-      case 'set':
-        if (algoStatusList.value) return algoStatusList.value?.savedAlgoJiaojiList?.length > 0;
-      case 'open':
-        if (algoStatusList.value) return algoStatusList.value?.notEnabledAlgoBingjiList?.length > 0;
-      case 'close':
-        if (algoStatusList.value) return algoStatusList.value?.enabledAlgoBingjiList?.length > 0;
-      case 'delete':
-        if (algoStatusList.value) return algoStatusList.value?.savedAlgoBingjiList?.length > 0;
-      default:
-        return true;
-    }
-  });
-
-  const getNoAlgoTip = computed(() => {
-    switch (props.type) {
-      case 'set':
-        return '所选中的相机不存在共同算法,无法批量设置算法参数';
-      case 'open':
-        return '所选中的相机不存在未开启的算法';
-      case 'close':
-        return '所选中的相机不存在已开启的算法';
-      case 'delete':
-        return '所选中的相机无已添加的算法';
-      default:
-        return '';
-    }
-  });
-
-  const getAlgoListByType = () => {
-    if (props.type === 'set') {
-      algosList.value = algoStatusList.value?.savedAlgoJiaojiList.map((item) => ({
-        algoName: item.algoName,
-        algoId: item.algoId,
-      }));
-    }
-    if (props.type === 'open') {
-      algosList.value = algoStatusList.value?.notEnabledAlgoBingjiList.map((item) => ({
-        algoName: item.algoName,
-        algoId: item.algoId,
-      }));
-    }
-    if (props.type === 'close') {
-      algosList.value = algoStatusList.value?.enabledAlgoBingjiList.map((item) => ({
-        algoName: item.algoName,
-        algoId: item.algoId,
-      }));
-    }
-    if (props.type === 'delete') {
-      algosList.value = algoStatusList.value?.savedAlgoBingjiList.map((item) => ({
-        algoName: item.algoName,
-        algoId: item.algoId,
-      }));
-    }
-    if (props.type === 'add') {
-      algosList.value = props.allAlgoList.map((item) => ({ algoName: item.name, algoId: item.id }));
-    }
-  };
-
-  watch(
-    [() => algoStatusList.value, () => props.allAlgoList],
-    () => {
-      getAlgoListByType();
-    },
-    { immediate: true },
-  );
-
-  // 切换选中状态
-  const handleChangeChooseAlgos = (algo: AlgoStruct) => {
-    const index = chooseAlgos.value.findIndex((item) => item.algoId === algo.algoId);
-    if (index === -1) {
-      if (props.type === 'set') {
-        chooseAlgos.value = [];
-      }
-      chooseAlgos.value.push(algo);
-    } else {
-      chooseAlgos.value.splice(index, 1);
-    }
-  };
-
-  // 全选
-  const handleChooseAllAlgos = () => {
-    chooseAlgos.value = algosList.value || [];
-  };
-  // 重置
-  const resetChooseAlgos = () => {
-    chooseAlgos.value = [];
-  };
-  // 确认
-  const handleConfirmOperation = () => {
-    const algoIdList = chooseAlgos.value.map((item) => item.algoId);
-    emits('onConfirm', algoIdList);
-  };
-
-  const handleClose = () => {
-    emits('onClose');
-  };
-
-  onMounted(() => {
-    getAlgoStatusByCameraIds({ cameraIdList: props.cameraIds }).then((res) => {
-      algoStatusList.value = res;
-    });
-  });
-</script>
-
-<style scoped lang="less">
-  .header-text {
-    font-size: 18px;
-  }
-
-  .tips {
-    height: 21px;
-    margin-bottom: 10px;
-    display: flex;
-    align-items: center;
-    color: #909399;
-
-    .tip {
-      margin-left: 4px;
-    }
-  }
-
-  .algos-list {
-    height: 280px;
-    overflow: auto;
-    display: flex;
-    flex-wrap: wrap;
-    align-content: flex-start;
-    margin-top: 10px;
-
-    .algo-item {
-      margin: 0 20px 15px 0;
-      padding: 4px 16px;
-      cursor: pointer;
-      font-size: 16px;
-    }
-
-    .algo-item:hover {
-      background-color: #f5f7fa;
-    }
-
-    .active-item {
-      color: #409eff;
-      background-color: #e6f7ff;
-    }
-
-    .added-item {
-      color: #88bcff;
-      cursor: not-allowed;
-    }
-
-    .added-item:hover {
-      background-color: transparent;
-    }
-  }
-
-  .no-algo {
-    height: 340px;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    padding-top: 35px;
-
-    .no-algo-tip {
-      margin-top: 20px;
-      font-size: 14px;
-      color: #606266;
-    }
-  }
-</style>

+ 0 - 412
src/views/cameras/preview/components/CameraConfigSingle/CameraConfigSingle.vue

@@ -1,412 +0,0 @@
-<template>
-  <div>
-    <QueryForm :algos-info="algosInfo" @on-search="handleQueryTableData" @on-reset="handleResetTableData" />
-    <div v-if="showActionBar" class="action-bar">
-      <span class="num-text">已选{{ chooseNum }}项</span>
-      <el-button :class="isAlgoAdd ? 'btn-active' : 'btn-normal'" @click="handleAlgosAdd" v-if="hasAddPermission()"
-        >算法添加</el-button
-      >
-      <el-button
-        :class="isParamsSet ? 'btn-active' : 'btn-normal'"
-        @click="handleParamsSet"
-        v-if="hasParamSetPermission()"
-        >参数设置</el-button
-      >
-      <el-button :class="isAlgoOpen ? 'btn-active' : 'btn-normal'" @click="handleAlgosOpen">算法开启</el-button>
-      <el-button :class="isAlgoClose ? 'btn-active' : 'btn-normal'" @click="handleAlgosClose">算法关闭</el-button>
-      <el-button
-        :class="isAlgoDelete ? 'btn-active' : 'btn-normal'"
-        @click="handleAlgosDel"
-        v-if="hasDeletePermission()"
-        >算法删除</el-button
-      >
-      <span class="close-btn" @click="handleSelectNone"></span>
-    </div>
-    <SingleCameraTable
-      ref="singleCameraTableRef"
-      class="table-bar"
-      :table-data="tableData"
-      @on-filter="handleFilterTable"
-      @on-reset="handleResetTable"
-      @on-refresh="getTableData"
-      @update:selection="handlePop"
-    />
-    <Pagination
-      v-model:page="tableQueryParams.pageNumber"
-      v-model:size="tableQueryParams.pageSize"
-      :total="total"
-      @update:page="handlePageChange"
-      @update:size="handleSizeChange"
-      style="margin-bottom: 0"
-    />
-    <BatchOperationDialog
-      v-if="batchOperationVisible"
-      :type="batchOperationType"
-      :camera-ids="chooseId"
-      :all-algo-list="algosInfo"
-      @on-confirm="handleConfirmBatchOperation"
-      @on-close="handleCloseBatchOperation"
-    />
-    <el-dialog
-      v-model="isBatchParamSetVisible"
-      width="1022"
-      align-center
-      :close-on-click-modal="false"
-      @close="handleCancel"
-    >
-      <template #header>
-        <div class="batch-param-set-header">
-          <div class="algo-title">{{ selectedAlgoDetail?.name }}</div>
-          <div class="set-tips">
-            <el-icon :size="15"><InfoFilled /></el-icon>
-            <div class="tip"
-              >当前显示默认参数值,请选择具体参数进行修改,提交后新参数值将对所选全部相机生效,覆盖原有参数值</div
-            >
-          </div>
-        </div>
-      </template>
-      <AlgoParamsSetting
-        v-if="selectedAlgoDetail"
-        :algo-detail="selectedAlgoDetail"
-        @on-submit="handleSubmit"
-        @on-cancel="handleCancel"
-      />
-    </el-dialog>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { onMounted, ref } from 'vue';
-  import { ElButton, ElIcon, ElMessage, ElDialog } from 'element-plus';
-  import { InfoFilled } from '@element-plus/icons-vue';
-  import {
-    QueryCameraPageByAlgoParams,
-    QueryCameraPageByAlgoRes,
-    getCameraListByAlgo,
-    QueryAlgoInfoRes,
-    getAlgosInfo,
-    addAlgosByBatch,
-    deleteAlgosByBatch,
-    updateAlgosStatusByBatch,
-    updateAlgosByBatch,
-  } from '@/api/camera/camera-config';
-  import QueryForm from './QueryForm.vue';
-  import SingleCameraTable from './SingleCameraTable.vue';
-  import Pagination from '@/components/Pagination/Pagination.vue';
-  import BatchOperationDialog from './BatchOperationDialog.vue';
-  import AlgoParamsSetting from '@/modules/algo/algo-params-edit/index.vue';
-  import { CameraAlgoItemInCard } from '@/modules/algo/algo-params-edit/types';
-  import { createAlgoSubmitParams, algoDetailToJSON, algoMetaToJSON } from '@/modules/algo/algo-params-edit/utils';
-  import { useUserStore } from '@/store/modules/user';
-  import { PERM_ALGO } from '@/types/permission/constants';
-
-  const userStore = useUserStore();
-
-  // 权限设置
-  const hasAddPermission = () => {
-    return userStore.checkPermission(PERM_ALGO.CONFIG_ADD);
-  };
-  const hasDeletePermission = () => {
-    return userStore.checkPermission(PERM_ALGO.CONFIG_DELETE);
-  };
-  const hasParamSetPermission = () => {
-    return userStore.checkPermission(PERM_ALGO.CONFIG_PARAM);
-  };
-
-  const tableQueryParams = ref<QueryCameraPageByAlgoParams>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-  });
-
-  const algosInfo = ref<QueryAlgoInfoRes[]>([]);
-  const singleCameraTableRef = ref<typeof SingleCameraTable>();
-  const tableData = ref<QueryCameraPageByAlgoRes[]>([]);
-  const total = ref(0);
-  // 多选相机 批量操作
-  const showActionBar = ref(false);
-  const chooseNum = ref(0);
-  const chooseRow = ref<QueryCameraPageByAlgoRes[]>([]); // 被选中的数据行
-  const chooseId = ref<number[]>([]);
-  // 按钮点击激活状态
-  const isAlgoAdd = ref(false);
-  const isParamsSet = ref(false);
-  const isAlgoClose = ref(false);
-  const isAlgoOpen = ref(false);
-  const isAlgoDelete = ref(false);
-  const batchOperationType = ref('');
-  const batchOperationVisible = ref(false);
-  // 批量参数设置
-  const isBatchParamSetVisible = ref(false);
-  const selectedAlgoDetail = ref<CameraAlgoItemInCard>(); // 批量参数设置组件的参数
-
-  // 查询
-  const handleQueryTableData = (queryParams) => {
-    tableQueryParams.value.queryParam.cameraName = queryParams.queryParam.cameraName;
-    tableQueryParams.value.queryParam.cameraCode = queryParams.queryParam.cameraCode;
-    tableQueryParams.value.queryParam.workspaceIdList = queryParams.queryParam.workspaceIdList;
-    tableQueryParams.value.queryParam.algoId = queryParams.queryParam.algoId;
-    tableQueryParams.value.pageNumber = 1;
-    tableQueryParams.value.pageSize = 10;
-    getTableData();
-  };
-  // 重置 (清空查询条件, 不清空筛选条件)
-  const handleResetTableData = () => {
-    Reflect.deleteProperty(tableQueryParams.value.queryParam, 'cameraName');
-    Reflect.deleteProperty(tableQueryParams.value.queryParam, 'cameraCode');
-    Reflect.deleteProperty(tableQueryParams.value.queryParam, 'workspaceIdList');
-    Reflect.deleteProperty(tableQueryParams.value.queryParam, 'algoId');
-    tableQueryParams.value.pageNumber = 1;
-    tableQueryParams.value.pageSize = 10;
-    getTableData();
-  };
-
-  // 筛选
-  const handleFilterTable = (type: string, opened: boolean, closed: boolean) => {
-    // 为了在筛选时 保留 查询条件,将筛选处理放在此处
-    if (type === 'algo') {
-      if (opened && !closed) {
-        tableQueryParams.value.queryParam.isAlgoDisabled = false;
-      } else if (!opened && closed) {
-        tableQueryParams.value.queryParam.isAlgoDisabled = true;
-      } else {
-        Reflect.deleteProperty(tableQueryParams.value.queryParam, 'isAlgoDisabled');
-      }
-    }
-    if (type === 'render') {
-      if (opened && !closed) {
-        tableQueryParams.value.queryParam.isRenderDisabled = false;
-      } else if (!opened && closed) {
-        tableQueryParams.value.queryParam.isRenderDisabled = true;
-      } else {
-        Reflect.deleteProperty(tableQueryParams.value.queryParam, 'isRenderDisabled');
-      }
-    }
-    tableQueryParams.value.pageNumber = 1;
-    tableQueryParams.value.pageSize = 10;
-    getTableData();
-  };
-  // 清空筛选 (不清空查询条件)
-  const handleResetTable = (type: string) => {
-    if (type === 'algo') {
-      Reflect.deleteProperty(tableQueryParams.value.queryParam, 'isAlgoDisabled');
-    }
-    if (type === 'render') {
-      Reflect.deleteProperty(tableQueryParams.value.queryParam, 'isRenderDisabled');
-    }
-    tableQueryParams.value.pageNumber = 1;
-    tableQueryParams.value.pageSize = 10;
-    getTableData();
-  };
-
-  // 多选
-  const handlePop = (selection) => {
-    chooseRow.value = selection;
-    chooseId.value = [];
-    selection.forEach((item) => {
-      if (chooseId.value.indexOf(item.cameraId) === -1) chooseId.value.push(item.cameraId);
-    });
-    chooseNum.value = selection.length;
-    showActionBar.value = chooseNum.value > 0 ? true : false;
-  };
-  // 取消多选
-  const handleSelectNone = () => {
-    chooseId.value = [];
-    chooseNum.value = 0;
-    singleCameraTableRef.value?.clearAll();
-    showActionBar.value = false;
-    handleResetBtnStatus();
-  };
-  // 重置按钮点击状态
-  function handleResetBtnStatus() {
-    isAlgoAdd.value = false;
-    isParamsSet.value = false;
-    isAlgoClose.value = false;
-    isAlgoOpen.value = false;
-    isAlgoDelete.value = false;
-  }
-
-  // 批量操作
-  const handleAlgosAdd = () => {
-    isAlgoAdd.value = true;
-    batchOperationType.value = 'add';
-    batchOperationVisible.value = true;
-  };
-  const handleParamsSet = () => {
-    isParamsSet.value = true;
-    batchOperationType.value = 'set';
-    batchOperationVisible.value = true;
-  };
-  const handleAlgosOpen = () => {
-    isAlgoOpen.value = true;
-    batchOperationType.value = 'open';
-    batchOperationVisible.value = true;
-  };
-  const handleAlgosClose = () => {
-    isAlgoClose.value = true;
-    batchOperationType.value = 'close';
-    batchOperationVisible.value = true;
-  };
-  const handleAlgosDel = () => {
-    isAlgoDelete.value = true;
-    batchOperationType.value = 'delete';
-    batchOperationVisible.value = true;
-  };
-  // 批量操作弹窗
-  const handleConfirmBatchOperation = (algoIds) => {
-    if (batchOperationType.value === 'add') {
-      addAlgosByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds }).then(() => {
-        ElMessage({ type: 'success', message: '算法添加成功' });
-        handleCloseBatchOperation();
-        getTableData();
-      });
-    }
-    if (batchOperationType.value === 'set') {
-      isBatchParamSetVisible.value = true;
-      const algoDetail = algosInfo.value.find((item) => item.id === algoIds[0]);
-      if (algoDetail) {
-        selectedAlgoDetail.value = algoMetaToJSON(algoDetail);
-      }
-    }
-    if (batchOperationType.value === 'open') {
-      updateAlgosStatusByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds, isEnabled: true }).then(() => {
-        ElMessage({ type: 'success', message: '算法开启成功' });
-        handleCloseBatchOperation();
-        getTableData();
-      });
-    }
-    if (batchOperationType.value === 'close') {
-      updateAlgosStatusByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds, isEnabled: false }).then(() => {
-        ElMessage({ type: 'success', message: '算法关闭成功' });
-        handleCloseBatchOperation();
-        getTableData();
-      });
-    }
-    if (batchOperationType.value === 'delete') {
-      deleteAlgosByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds }).then(() => {
-        ElMessage({ type: 'success', message: '算法删除成功' });
-        handleCloseBatchOperation();
-        getTableData();
-      });
-    }
-  };
-  const handleCloseBatchOperation = () => {
-    batchOperationType.value = '';
-    batchOperationVisible.value = false;
-    handleResetBtnStatus();
-  };
-
-  // 批量参数设置提交
-  const handleSubmit = (param) => {
-    const newParam = createAlgoSubmitParams(param, selectedAlgoDetail.value);
-    updateAlgosByBatch({
-      cameraIdList: chooseId.value,
-      ...newParam,
-    }).then(() => {
-      ElMessage({ type: 'success', message: '参数设置成功' });
-      isBatchParamSetVisible.value = false;
-    });
-  };
-  const handleCancel = () => {
-    isBatchParamSetVisible.value = false;
-  };
-
-  // 换页,重新获取表格
-  const handlePageChange = (val) => {
-    tableQueryParams.value.pageNumber = val;
-    getTableData();
-  };
-  const handleSizeChange = (val) => {
-    tableQueryParams.value.pageSize = val;
-    getTableData();
-  };
-
-  const getTableData = async () => {
-    await getCameraListByAlgo(tableQueryParams.value).then((res) => {
-      tableData.value = res.records;
-      total.value = res.totalRow;
-    });
-  };
-
-  onMounted(() => {
-    getTableData();
-    getAlgosInfo().then((res) => {
-      algosInfo.value = res;
-    });
-  });
-</script>
-
-<style lang="scss" scoped>
-  .action-bar {
-    display: flex;
-    align-items: center;
-    position: absolute;
-    min-width: calc(100vw - 266px);
-    height: 50px;
-    border-radius: 4px 4px 0px 0px;
-    background-color: #ddefff;
-    z-index: 10;
-
-    .num-text {
-      margin: 0 34px 0 25px;
-      color: rgba(0, 0, 0, 0.85);
-      font-weight: 500;
-    }
-
-    .btn-normal {
-      color: #1890ff;
-      background: transparent;
-      border: 1px solid #1890ff;
-      border-radius: 2px;
-    }
-
-    .btn-active,
-    .btn-normal:hover {
-      color: #ffffff;
-      background-color: #1890ff;
-    }
-
-    .close-btn {
-      margin-left: auto;
-      margin-right: 20px;
-    }
-
-    .close-btn:before {
-      content: '\2716';
-      color: #000;
-      cursor: pointer;
-    }
-  }
-
-  .table-bar {
-    position: relative;
-  }
-
-  .batch-param-set-header {
-    width: 100%;
-    height: 80px;
-    border-bottom: 1px solid #e4e7ec;
-    position: relative;
-
-    .algo-title {
-      font-size: 20px;
-      font-weight: 600;
-      color: #000000;
-    }
-
-    .set-tips {
-      display: flex;
-      align-items: center;
-      margin-top: 10px;
-      color: #66abeb;
-
-      .tip {
-        margin-left: 2px;
-      }
-    }
-  }
-
-  :deep(.el-dialog__header) {
-    padding-right: 0px;
-  }
-</style>

+ 0 - 176
src/views/cameras/preview/components/CameraConfigSingle/QueryForm.vue

@@ -1,176 +0,0 @@
-<template>
-  <div class="query-box">
-    <div class="query-param">
-      <el-input
-        v-model="tableQueryTypeContent"
-        style="width: 300px; height: 32px; margin-right: 40px; margin-bottom: 10px"
-        :placeholder="tableQueryType ? '请输入' + tableQueryType : '请输入查找内容'"
-        clearable
-        :disabled="!tableQueryType"
-        @input="handleTableQueryTypeContentChange"
-      >
-        <template #prepend>
-          <el-select
-            v-model="tableQueryType"
-            placeholder="选择类型"
-            style="width: 110px"
-            @change="handleTableQueryTypeChange"
-            clearable
-          >
-            <el-option v-for="item in tableQueryTypeOptions" :key="item.value" :label="item.name" :value="item.value" />
-          </el-select>
-        </template>
-      </el-input>
-      <div class="locations-query">
-        <div>地点:</div>
-        <el-cascader
-          v-model="workLocation"
-          :options="locationOptions"
-          :props="locationProp"
-          clearable
-          collapse-tags
-          :show-all-levels="false"
-          placeholder="请选择地点"
-          popper-class="special-cascader"
-          @change="handleCascaderChange"
-        />
-      </div>
-      <div class="algo-query">
-        <div>算法:</div>
-        <el-select v-model="queryParams.queryParam.algoId" placeholder="请选择算法" clearable style="width: 200px">
-          <el-option v-for="item in algoOptions" :key="item.value" :label="item.name" :value="item.value" />
-        </el-select>
-      </div>
-    </div>
-    <div class="query-btn">
-      <el-button type="primary" @click="submitTableQuery">查询</el-button>
-      <el-button @click="resetTable">重置</el-button>
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { onMounted, reactive, ref, watch } from 'vue';
-  import { ElSelect, ElOption, ElInput, ElCascader, ElButton } from 'element-plus';
-  import { useWorkLocation } from '@/views/datamanager/alertformdata/hooks/useWorkLocation';
-  import { QueryCameraPageByAlgoParams, QueryAlgoInfoRes } from '@/api/camera/camera-config';
-
-  const { locationOptions, getLocationOptions } = useWorkLocation();
-
-  const props = defineProps<{
-    algosInfo: QueryAlgoInfoRes[];
-  }>();
-  const emits = defineEmits(['onSearch', 'onReset']);
-
-  const queryParams = reactive<QueryCameraPageByAlgoParams>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-  });
-
-  // 查询参数选项
-  const tableQueryTypeOptions = [
-    { name: '相机名称', value: '相机名称' },
-    { name: '相机ID', value: '相机ID' },
-  ];
-  // 算法选择器选项
-  const algoOptions = ref<{ name: string; value: number }[]>([]);
-
-  const tableQueryType = ref<string>('');
-  const tableQueryTypeContent = ref<string>('');
-  const workLocation = ref([]);
-  const locationProp = { multiple: true, expandTrigger: 'hover' as const };
-
-  const handleTableQueryTypeChange = () => {
-    if (tableQueryType.value === '相机名称') {
-      delete queryParams.queryParam.cameraCode;
-    } else if (tableQueryType.value === '相机ID') {
-      delete queryParams.queryParam.cameraName;
-    } else {
-      delete queryParams.queryParam.cameraCode;
-      delete queryParams.queryParam.cameraName;
-    }
-    tableQueryTypeContent.value = '';
-  };
-
-  const handleTableQueryTypeContentChange = () => {
-    if (tableQueryType.value === '相机名称') {
-      queryParams.queryParam.cameraName = tableQueryTypeContent.value;
-    } else if (tableQueryType.value === '相机ID') {
-      queryParams.queryParam.cameraCode = tableQueryTypeContent.value;
-    }
-  };
-
-  const handleCascaderChange = () => {
-    if (workLocation.value.length !== 0) {
-      const arr = [];
-      workLocation.value.forEach((item) => {
-        arr.push(item[1]);
-      });
-      queryParams.queryParam.workspaceIdList = arr;
-    } else {
-      Reflect.deleteProperty(queryParams.queryParam, 'workspaceIdList');
-    }
-  };
-
-  const submitTableQuery = () => {
-    emits('onSearch', queryParams);
-  };
-
-  const resetTable = () => {
-    tableQueryType.value = '';
-    tableQueryTypeContent.value = '';
-    workLocation.value = [];
-    queryParams.pageNumber = 1;
-    queryParams.pageSize = 10;
-    queryParams.queryParam = {};
-    emits('onReset');
-  };
-
-  // 获取所有算法信息
-  const getAllAlgosInfo = () => {
-    algoOptions.value = props.algosInfo.map((item) => ({ name: item.name, value: item.id }));
-  };
-
-  watch(
-    () => props.algosInfo,
-    (newVal) => {
-      if (newVal.length > 0) {
-        getAllAlgosInfo();
-      }
-    },
-    { immediate: true },
-  );
-
-  onMounted(() => {
-    getLocationOptions();
-  });
-</script>
-
-<style lang="scss" scoped>
-  .query-box {
-    margin-bottom: 10px;
-    display: flex;
-
-    .query-param {
-      display: flex;
-      flex-wrap: wrap;
-      flex-direction: row;
-      align-items: center;
-      flex: 1;
-    }
-
-    .locations-query,
-    .algo-query {
-      display: flex;
-      align-items: center;
-      margin-right: 40px;
-      margin-bottom: 10px;
-    }
-
-    .query-btn {
-      margin-left: auto;
-      margin-bottom: 10px;
-    }
-  }
-</style>

+ 0 - 389
src/views/cameras/preview/components/CameraConfigSingle/SingleCameraTable.vue

@@ -1,389 +0,0 @@
-<template>
-  <div class="table-box">
-    <el-table
-      ref="multipleTableRef"
-      :data="tableData"
-      style="width: 100%"
-      height="100%"
-      :row-class-name="colorOfRow"
-      @select="handleShiftSelect"
-      @selection-change="handleSelectionChange"
-      @row-click="handleRowClick"
-    >
-      <el-table-column type="selection" width="30" />
-      <el-table-column label="相机名称" prop="cameraName" width="150">
-        <template #default="{ row }">
-          <el-popover placement="right" :width="300" trigger="hover" effect="dark" popper-style="padding: 0;">
-            <template #reference>
-              <span
-                :class="[row.integrationState ? 'notconnect-camera' : '', row.networkingState ? 'offline-camera' : '']"
-                >{{ row.cameraName }}</span
-              >
-            </template>
-            <img v-if="row.cameraImgUrl" :src="row.cameraImgUrl" alt="" />
-            <div v-else style="display: flex; flex-direction: column; align-items: center">
-              <img src="@/assets/icons/no-content.png" alt="" width="200" />
-              <div>暂无相机预览图</div>
-            </div>
-          </el-popover>
-        </template>
-      </el-table-column>
-      <el-table-column label="设备ID" prop="cameraCode" width="150" />
-      <el-table-column label="地点" prop="location" width="300">
-        <template #default="{ row }">
-          {{ row.workshopName + ' - ' + row.workspaceName }}
-        </template>
-      </el-table-column>
-      <el-table-column label="算法" prop="algoStatusList" min-width="200">
-        <template #header>
-          <span>算法</span>
-          <el-popover
-            placement="bottom-start"
-            :width="100"
-            trigger="click"
-            popper-class="filter-popper"
-            :popper-style="{ minWidth: '100px' }"
-          >
-            <template #reference>
-              <SvgIcon class="filter-btn" icon-name="filter" :color="algoOpened || algoClosed ? '#409EFF' : ''" />
-            </template>
-            <el-checkbox v-model="algoOpened" label="开启" />
-            <el-checkbox v-model="algoClosed" label="未开启" />
-            <div class="filter-btns">
-              <span class="filter-apply" @click="applyFilter('algo')">应用</span>
-              <span class="filter-clear" @click="clearFilter('algo')">清空</span>
-            </div>
-          </el-popover>
-        </template>
-        <template #default="{ row }">
-          <el-tag v-if="row.algoStatusList.length === 0" type="info" effect="dark">未添加</el-tag>
-          <div v-for="item in row.algoStatusList" :class="item.isDisabled ? 'close-algo' : ''">{{ item.algoName }}</div>
-        </template>
-      </el-table-column>
-      <el-table-column label="渲染" prop="isRenderDisabled" width="100">
-        <template #header>
-          <span>渲染</span>
-          <el-popover
-            placement="bottom-start"
-            :width="100"
-            trigger="click"
-            popper-class="filter-popper"
-            :popper-style="{ minWidth: '100px' }"
-          >
-            <template #reference>
-              <SvgIcon class="filter-btn" icon-name="filter" :color="renderOpened || renderClosed ? '#409EFF' : ''" />
-            </template>
-            <el-checkbox v-model="renderOpened" label="开启" />
-            <el-checkbox v-model="renderClosed" label="未开启" />
-            <div class="filter-btns">
-              <span class="filter-apply" @click="applyFilter('render')">应用</span>
-              <span class="filter-clear" @click="clearFilter('render')">清空</span>
-            </div>
-          </el-popover>
-        </template>
-        <template #default="{ row }">
-          <el-switch :model-value="!row.isRenderDisabled" @change="handleChangeRenderStatus(row)" @click.stop />
-        </template>
-      </el-table-column>
-      <el-table-column label="算法操作" fixed="right" width="280">
-        <template #default="{ row }">
-          <el-button
-            type="primary"
-            text
-            @click="
-              handleSettingConfig(row);
-              $event.stopPropagation();
-            "
-            >配置</el-button
-          >
-          <el-button
-            v-if="row.algoStatusList.find((item) => item.isDisabled === true)"
-            type="primary"
-            text
-            @click="
-              batchOpenAlgos(row);
-              $event.stopPropagation();
-            "
-            >一键开启</el-button
-          >
-          <el-button
-            v-if="row.algoStatusList.find((item) => item.isDisabled === false)"
-            type="primary"
-            text
-            @click="
-              batchCloseAlgos(row);
-              $event.stopPropagation();
-            "
-            >一键关闭</el-button
-          >
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { onMounted, ref } from 'vue';
-  import router from '@/router';
-  import {
-    ElButton,
-    ElTable,
-    ElTableColumn,
-    ElPopover,
-    ElTag,
-    ElSwitch,
-    ElMessage,
-    ElMessageBox,
-    ElCheckbox,
-  } from 'element-plus';
-  import { QueryCameraPageByAlgoRes, updateAlgosStatusByCameraId } from '@/api/camera/camera-config';
-  import { renderCamera } from '@/api/camera/camera-preview';
-  import { SvgIcon } from '@/components/SvgIcon';
-
-  const props = defineProps<{ tableData: QueryCameraPageByAlgoRes[] }>();
-  const emits = defineEmits(['onFilter', 'onReset', 'onRefresh', 'update:selection']);
-
-  const multipleTableRef = ref<InstanceType<typeof ElTable>>();
-  // shift多选操作
-  const startPoint = ref<number | undefined>();
-  const endPoint = ref<number | undefined>();
-  const shiftKeyBoard = ref(false); // shift按钮按住/松开
-  const selections = ref<QueryCameraPageByAlgoRes[]>([]);
-  const rowClickSelections = ref<QueryCameraPageByAlgoRes[]>([]);
-
-  const algoOpened = ref(false); // 算法开启 勾选状态
-  const algoClosed = ref(false); // 算法未开启 勾选状态
-  const renderOpened = ref(false); // 渲染开启 勾选状态
-  const renderClosed = ref(false); // 渲染未开启 勾选状态
-
-  // 渲染/算法 开启/未开启状态筛选
-  const applyFilter = (type) => {
-    if (type === 'algo') {
-      emits('onFilter', type, algoOpened.value, algoClosed.value);
-    } else if (type === 'render') {
-      emits('onFilter', type, renderOpened.value, renderClosed.value);
-    }
-  };
-  const clearFilter = (type) => {
-    if (type === 'algo') {
-      algoOpened.value = false;
-      algoClosed.value = false;
-    }
-    if (type === 'render') {
-      renderOpened.value = false;
-      renderClosed.value = false;
-    }
-    emits('onReset', type);
-  };
-
-  // 切换渲染状态
-  const handleChangeRenderStatus = (row) => {
-    const tempRenderStatus = row.isRenderDisabled ? 'demo' : null;
-    renderCamera({
-      render: tempRenderStatus,
-      cameraId: row.cameraId,
-    })
-      .then(() => {
-        ElMessage({
-          message: '渲染状态切换成功',
-          type: 'success',
-        });
-        emits('onRefresh');
-      })
-      .catch(() => {
-        ElMessage({
-          message: '开启数量已达上限,可关闭其他相机渲染后再开启',
-          type: 'error',
-        });
-      });
-  };
-
-  // 配置算法(单相机配置)
-  const handleSettingConfig = (row) => {
-    router.push({ path: '/algorithm/params', query: { cameraId: row.cameraId } });
-  };
-  // 一键开启算法(单相机一键开启)
-  const batchOpenAlgos = (row) => {
-    ElMessageBox.confirm('开启后,所选相机已配置的算法将全部生效。', '确认开启算法吗?', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-    })
-      .then(() => {
-        updateAlgosStatusByCameraId({ cameraId: row.cameraId, isDisabled: false }).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '算法开启成功',
-          });
-          emits('onRefresh');
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消开启',
-        });
-      });
-  };
-  // 一键关闭算法(单相机一键关闭)
-  const batchCloseAlgos = (row) => {
-    ElMessageBox.confirm('关闭后,所选相机已配置的算法将不再生效。', '确认关闭算法吗?', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-    })
-      .then(() => {
-        updateAlgosStatusByCameraId({ cameraId: row.cameraId, isDisabled: true }).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '算法关闭成功',
-          });
-          emits('onRefresh');
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消关闭',
-        });
-      });
-  };
-
-  // 选中行
-  const colorOfRow = ({ row }) => {
-    if (selections.value.includes(row)) {
-      return 'selected-row';
-    }
-    return '';
-  };
-
-  const handleSelectionChange = (selection: any[]) => {
-    selections.value = selection;
-    emits('update:selection', selections.value);
-  };
-
-  const handleShiftSelect = (_, row) => {
-    props.tableData.forEach((item, index) => {
-      item.index = index;
-    });
-    // 按住shift
-    if (shiftKeyBoard.value) {
-      // 有起点startPoint
-      if (startPoint.value !== undefined) {
-        endPoint.value = row.index as number;
-        if (startPoint.value > endPoint.value) {
-          let temp = startPoint.value;
-          startPoint.value = endPoint.value;
-          endPoint.value = temp;
-        }
-        setTimeout(() => {
-          for (let i = startPoint.value as number; i < (endPoint.value as number); i++) {
-            multipleTableRef.value!.toggleRowSelection(props.tableData[i], true);
-          }
-        }, 100);
-      }
-      // 没有起点startPoint
-      else {
-        startPoint.value = row.index;
-        endPoint.value = undefined;
-      }
-    }
-    // 没按住shift
-    else {
-      startPoint.value = row.index;
-      endPoint.value = undefined;
-    }
-  };
-
-  const handleRowClick = (row) => {
-    if (rowClickSelections.value.find((item) => item.cameraId === row.cameraId)) {
-      let index = rowClickSelections.value.findIndex((item) => item.cameraId === row.cameraId);
-      rowClickSelections.value.splice(index, 1);
-      multipleTableRef.value!.toggleRowSelection(row, false);
-    } else {
-      rowClickSelections.value.push(row);
-      multipleTableRef.value!.toggleRowSelection(row, true);
-    }
-  };
-
-  const clearAll = () => {
-    multipleTableRef.value!.clearSelection();
-  };
-
-  defineExpose({ clearAll });
-
-  onMounted(() => {
-    window.addEventListener('keydown', (code) => {
-      if (code.shiftKey) {
-        shiftKeyBoard.value = true;
-      }
-    });
-    window.addEventListener('keyup', (code) => {
-      if (!code.shiftKey) {
-        shiftKeyBoard.value = false;
-        startPoint.value = -1;
-        endPoint.value = -1;
-      }
-    });
-  });
-</script>
-
-<style lang="scss" scoped>
-  .table-box {
-    height: calc(100vh - 280px);
-
-    .filter-btn {
-      display: inline-block;
-      margin-left: 3px;
-      cursor: pointer;
-    }
-
-    .notconnect-camera {
-      color: #cccccc;
-    }
-    .offline-camera::before {
-      content: '!';
-      color: red;
-      font-weight: bold;
-      margin-right: 4px;
-    }
-
-    .close-algo {
-      color: #cccccc;
-    }
-  }
-
-  :deep(.el-table) {
-    ::before {
-      height: 0px;
-    }
-
-    .selected-row {
-      background: #f3f8ff;
-    }
-  }
-</style>
-<style lang="scss">
-  .el-checkbox {
-    margin-right: 0;
-  }
-
-  .el-popover.filter-popper {
-    display: flex;
-    flex-direction: column;
-
-    .filter-btns {
-      margin-top: 20px;
-
-      .filter-apply {
-        color: #409eff;
-        margin-right: 16px;
-        cursor: pointer;
-      }
-
-      .filter-clear {
-        cursor: pointer;
-      }
-    }
-  }
-</style>

+ 0 - 31
src/views/datamanager/alertformdata/AlertformData.vue

@@ -1,31 +0,0 @@
-<template>
-  <div class="container-box">
-    <component :is="com" />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed } from 'vue';
-  import { useGlobSetting } from '@/hooks/setting';
-  import SimpleDefault from './components/default-simple/Default.vue';
-  import AlertformDataComplex from './AlertformDataComplex.vue';
-
-  const { questionListVersion } = useGlobSetting();
-
-  const com = computed(() => {
-    return questionListVersion === 'simple' ? SimpleDefault : AlertformDataComplex;
-  });
-</script>
-
-<style scoped lang="scss">
-  .container-box {
-    width: 100%;
-    height: 100%;
-    display: flex;
-    flex-direction: column;
-    min-height: calc(100vh - 90px);
-    padding: 21px;
-    background-color: rgba(255, 255, 255, 1);
-    border-radius: 10px;
-  }
-</style>

+ 0 - 73
src/views/datamanager/alertformdata/AlertformDataComplex.vue

@@ -1,73 +0,0 @@
-<template>
-  <div class="control-btn" v-if="hasFakeDataViewPermission()">
-    <div
-      class="btn"
-      :class="{ 'btn-active': activeName === 'default' }"
-      @click="activeName = 'default'"
-      >默认数据</div
-    >
-    <div class="btn" :class="{ 'btn-active': activeName === 'show' }" @click="activeName = 'show'"
-      >展示数据</div
-    >
-  </div>
-  <Default class="content-box" v-if="activeName === 'default'" />
-  <Show class="content-box" v-else />
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  import Default from './components/default/Default.vue';
-  import Show from './components/show/Show.vue';
-  import { useUserStore } from '@/store/modules/user';
-  import { PERM_DATA } from '@/types/permission/constants';
-
-  const activeName = ref('default');
-
-  const userStore = useUserStore();
-  const hasFakeDataViewPermission = () => {
-    return (
-      userStore.checkPermission(PERM_DATA.VIOLATION_FAKE_ADD) ||
-      userStore.checkPermission(PERM_DATA.VIOLATION_FAKE_DELETE)
-    );
-  };
-</script>
-
-<style scoped lang="scss">
-  .control-btn {
-    display: flex;
-    margin-bottom: 20px;
-
-    .btn {
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      width: 188px;
-      height: 38px;
-      font-size: 14px;
-      font-weight: 400;
-      color: rgba(0, 0, 0, 0.88);
-      border: 1px solid #d9d9d9;
-      background: rgba(0, 0, 0, 0.02);
-      cursor: pointer;
-    }
-
-    :first-child {
-      border-radius: 8px 0px 0px 8px;
-    }
-
-    :last-child {
-      border-radius: 0px 8px 8px 0px;
-    }
-
-    .btn-active {
-      font-weight: 500;
-      color: #1890ff;
-      border: 1px solid #1890ff;
-      background-color: rgba(24, 144, 255, 0.15);
-    }
-  }
-
-  .content-box {
-    flex: 1;
-  }
-</style>

+ 0 - 22
src/views/datamanager/alertformdata/components/common/AddDrawer.vue

@@ -1,22 +0,0 @@
-<template>
-  <QuestionFormBase @save-form="handleAdd" @close-form="handleClose" />
-</template>
-
-<script setup lang="ts">
-import QuestionFormBase from './QuestionFormBase.vue';
-import { addShowTableData } from '@/api/datamanagement/alert-show'
-
-const emits = defineEmits(['close']);
-
-const handleAdd = (formData) => {
-  addShowTableData(formData).then(() => {
-    emits('close');
-  })
-};
-
-const handleClose = () => {
-  emits('close');
-}
-</script>
-
-<style scoped></style>

+ 0 - 350
src/views/datamanager/alertformdata/components/common/AlertTable.vue

@@ -1,350 +0,0 @@
-<template>
-  <div class="alert-table-box">
-    <el-table
-      ref="multipleTableRef"
-      :data="tableData"
-      style="width: 100%"
-      height="100%"
-      :cell-style="colorOfState"
-      :row-class-name="colorOfRow"
-      @select="handleShiftSelect"
-      @selection-change="handleSelectionChange"
-      @row-click="handleRowClick"
-      @sort-change="handleTimeSort"
-      :default-sort="{ prop: 'createdAt', order: 'descending' }"
-    >
-      <el-table-column type="selection" width="55" />
-      <el-table-column label="问题来源" prop="source" width="150">
-        <template #default="{ row }">
-          {{ getNameBySource(row.source) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="类型" prop="issueType" width="150">
-        <template #default="{ row }">
-          {{ getNameByType(row.source, row.issueMainType, row.issueType) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="问题描述" prop="description" width="280" show-overflow-tooltip>
-        <template #default="{ row }">
-          <span>{{ getSplicedDes(row.description) }}</span>
-          <span
-            class="detail-text"
-            @click="
-              handleDetailClick(row);
-              $event.stopPropagation();
-            "
-          >
-            详情</span
-          >
-        </template>
-      </el-table-column>
-      <el-table-column label="地点" prop="workspaceId" width="300">
-        <template #default="{ row }">
-          {{ getNameByWorkid(row.workshopId, row.workspaceId, locationOptions) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="时间" prop="createdAt" width="180" sortable="custom" />
-      <el-table-column label="负责人" prop="personNameInCharge" width="100" />
-      <el-table-column label="处理状态" prop="issueState">
-        <template #default="{ row }">
-          {{ getNameByState(row.issueState) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" width="160" fixed="right">
-        <template #default="{ row }">
-          <el-tooltip
-            v-if="row.issueState != IssueState.hasRevoke"
-            effect="dark"
-            :content="row.isHide ? '点此设置为生效问题' : '点此设置为无效问题'"
-            placement="top"
-          >
-            <el-switch :model-value="!row.isHide" @change="handleShow(row)" @click.stop />
-          </el-tooltip>
-          <el-tooltip
-            v-if="row.issueState != IssueState.hasRevoke"
-            effect="dark"
-            content="点击标记为加急问题"
-            placement="top"
-          >
-            <img
-              src="/src/assets/images/alert/urgent.png"
-              alt=""
-              v-if="!isShowTab && !row.priority"
-              @click="
-                handleUrgent(row);
-                $event.stopPropagation();
-              "
-            />
-          </el-tooltip>
-          <el-tooltip
-            v-if="row.issueState != IssueState.hasRevoke"
-            effect="dark"
-            content="点击取消问题加急"
-            placement="top"
-          >
-            <img
-              src="/src/assets/images/alert/urgent-active.png"
-              alt=""
-              v-if="!isShowTab && row.priority"
-              @click="
-                handleUrgent(row);
-                $event.stopPropagation();
-              "
-            />
-          </el-tooltip>
-          <el-tooltip effect="dark" content="点击编辑问题" placement="top">
-            <img
-              src="/src/assets/images/alert/edit.png"
-              alt=""
-              v-if="isShowTab"
-              @click="
-                handleEdit(row);
-                $event.stopPropagation();
-              "
-            />
-          </el-tooltip>
-          <el-tooltip effect="dark" content="点击删除问题数据" placement="top" v-if="hasDataDeletePermisson()">
-            <img
-              src="/src/assets/images/alert/delete.png"
-              alt=""
-              @click="
-                handleDelete(row);
-                $event.stopPropagation();
-              "
-            />
-          </el-tooltip>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ElTable } from 'element-plus';
-  import { onBeforeMount, onMounted, ref } from 'vue';
-  import { IssueState, getNameBySource, getNameByState } from './constant.question';
-  import { useIssueMainType } from '../../hooks/useIssueMainType';
-  import { useWorkLocation } from '../../hooks/useWorkLocation';
-  import { useUserStore } from '@/store/modules/user';
-  import { PERM_DATA } from '@/types/permission/constants';
-
-  const userStore = useUserStore();
-  const hasDataDeletePermisson = () => {
-    // isShowTab = true 展示数据
-    if (props.isShowTab) return userStore.checkPermission(PERM_DATA.VIOLATION_FAKE_DELETE);
-    // isShowTab = false 默认数据
-    else return userStore.checkPermission(PERM_DATA.VIOLATION_DELETE);
-  };
-
-  const { getAIMainOptions, getManualMainOptions, getNameByType } = useIssueMainType();
-  const { locationOptions, getLocationOptions, getNameByWorkid } = useWorkLocation();
-
-  const multipleTableRef = ref<InstanceType<typeof ElTable>>();
-
-  export interface DataSourceItem {
-    index: Number;
-    id: Number;
-    source: Number; // 问题单来源:1-AI检测、2-人工上报
-    issueType: Number; // 问题单类型
-    description: String; // 问题描述
-    workspaceId: Number[]; // 工位id(地点=车间+工位?)
-    createdAt: String;
-    personNameInCharge: String;
-    issueState: Number; // 问题单状态:1-待审核、2-待处理、3-待复核、4-已退回、5-已处理
-  }
-
-  interface Props {
-    tableData: Array<DataSourceItem>;
-    isShowTab: boolean; // true展示数据,false默认数据
-    onDetail: (_row: DataSourceItem) => unknown; // 详情事件
-    onUrgent?: (_row: DataSourceItem) => unknown; // isShowTab=false时,加急按钮事件
-    onEdit?: (_row: DataSourceItem) => unknown; // isShowTab=true时,编辑按钮事件
-    onShow: (_row: DataSourceItem) => unknown; // 显示/隐藏按钮事件
-    onDelete: (_row: DataSourceItem) => unknown; // 删除按钮事件
-  }
-
-  const props = defineProps<Props>();
-
-  const emits = defineEmits(['update:selection', 'update:timeSort']);
-
-  const startPoint = ref<number | undefined>();
-  const endPoint = ref<number | undefined>();
-  const shiftKeyBoard = ref(false); // shift按钮按住/松开
-
-  const selections = ref<DataSourceItem[]>([]);
-  const handleSelectionChange = (selection: any[]) => {
-    selections.value = selection;
-    emits('update:selection', selections.value);
-  };
-
-  const handleShiftSelect = (_, row) => {
-    props.tableData.forEach((item, index) => {
-      item.index = index;
-    });
-    // 按住shift
-    if (shiftKeyBoard.value) {
-      // 有起点startPoint
-      if (startPoint.value !== undefined) {
-        endPoint.value = row.index as number;
-        if (startPoint.value > endPoint.value) {
-          let temp = startPoint.value;
-          startPoint.value = endPoint.value;
-          endPoint.value = temp;
-        }
-        setTimeout(() => {
-          for (let i = startPoint.value as number; i < (endPoint.value as number); i++) {
-            multipleTableRef.value!.toggleRowSelection(props.tableData[i], true);
-          }
-        }, 100);
-      }
-      // 没有起点startPoint
-      else {
-        startPoint.value = row.index;
-        endPoint.value = undefined;
-      }
-    }
-    // 没按住shift
-    else {
-      startPoint.value = row.index;
-      endPoint.value = undefined;
-    }
-  };
-
-  const rowClickSelections = ref<DataSourceItem[]>([]);
-  const handleRowClick = (row) => {
-    if (rowClickSelections.value.find((item) => item.id === row.id)) {
-      let index = rowClickSelections.value.findIndex((item) => item.id === row.id);
-      rowClickSelections.value.splice(index, 1);
-      multipleTableRef.value!.toggleRowSelection(row, false);
-    } else {
-      rowClickSelections.value.push(row);
-      multipleTableRef.value!.toggleRowSelection(row, true);
-    }
-  };
-
-  const handleDetailClick = (row) => {
-    props.onDetail(row);
-  };
-  const handleUrgent = (row) => {
-    props.onUrgent?.(row);
-  };
-  const handleEdit = (row) => {
-    props.onEdit?.(row);
-  };
-  const handleShow = (row) => {
-    props.onShow(row);
-  };
-  const handleDelete = (row) => {
-    props.onDelete(row);
-  };
-
-  const handleTimeSort = (column) => {
-    let curTimeSort = '';
-    if (column.order === 'ascending') curTimeSort = 'asc';
-    if (column.order === 'descending') curTimeSort = 'desc';
-    emits('update:timeSort', curTimeSort);
-  };
-
-  const getSplicedDes = (val) => {
-    if (val.length < 15) return val;
-    else {
-      const temp = val.substring(0, 14);
-      return temp + '…';
-    }
-  };
-
-  const colorOfState = ({ row, columnIndex }) => {
-    if (columnIndex === 7) {
-      if (row.issueState === 4 || row.issueState === 6) return { color: '#FF4D4F' }; // 待处理
-      else if (row.issueState === 7 || row.issueState === 8) return { color: '#52C41A ' }; // 已处理
-      else if (row.issueState === 3) return { color: '#cdca00' }; // 已撤销
-      else return { color: '#1890FF ' }; // 待审核,待复核
-    }
-    if (row.isHide) {
-      return { color: '#A8ABB2' };
-    }
-  };
-
-  const colorOfRow = ({ row }) => {
-    if (selections.value.includes(row)) {
-      return 'selected-row';
-    }
-    return '';
-  };
-
-  const clearAll = () => {
-    multipleTableRef.value!.clearSelection();
-  };
-
-  // 改变当前打开详情的表格行的选中状态
-  const updateCurRowChosen = (row, status: boolean) => {
-    multipleTableRef.value!.toggleRowSelection(row, status);
-  };
-
-  defineExpose({ clearAll, updateCurRowChosen });
-
-  onBeforeMount(() => {
-    getAIMainOptions();
-    getManualMainOptions();
-    getLocationOptions();
-  });
-
-  onMounted(() => {
-    window.addEventListener('keydown', (code) => {
-      if (code.shiftKey) {
-        shiftKeyBoard.value = true;
-      }
-    });
-    window.addEventListener('keyup', (code) => {
-      if (!code.shiftKey) {
-        shiftKeyBoard.value = false;
-        startPoint.value = -1;
-        endPoint.value = -1;
-      }
-    });
-  });
-</script>
-
-<style scoped lang="less">
-  .alert-table-box {
-    display: flex;
-    flex-direction: column;
-    height: calc(100vh - 350px);
-  }
-
-  .detail-text {
-    color: #1890ff;
-    font-weight: 500;
-    cursor: pointer;
-  }
-
-  :deep(.el-table-fixed-column--right) {
-    .cell {
-      display: flex;
-      align-items: center;
-      display: flex;
-      justify-content: center;
-    }
-
-    .el-switch {
-      margin-right: 20px;
-    }
-
-    img {
-      width: 20px;
-      height: 20px;
-      margin-right: 20px;
-      cursor: pointer;
-    }
-  }
-
-  :deep(.el-table) {
-    ::before {
-      height: 0px;
-    }
-
-    .selected-row {
-      background: #f3f8ff;
-    }
-  }
-</style>

+ 0 - 265
src/views/datamanager/alertformdata/components/common/AlertTableSimple.vue

@@ -1,265 +0,0 @@
-<template>
-  <div class="alert-table-box">
-    <el-table
-      ref="multipleTableRef"
-      :data="tableData"
-      style="width: 100%"
-      height="100%"
-      :cell-style="colorOfState"
-      :row-class-name="colorOfRow"
-      @select="handleShiftSelect"
-      @selection-change="handleSelectionChange"
-      @row-click="handleRowClick"
-      @sort-change="handleTimeSort"
-      :default-sort="{ prop: 'createdAt', order: 'descending' }"
-    >
-      <el-table-column type="selection" width="55"></el-table-column>
-      <el-table-column label="类型" prop="issueType" width="180">
-        <template #default="{ row }">
-          {{ getNameByType(row.source, row.issueMainType, row.issueType) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="问题描述" prop="description" width="280" show-overflow-tooltip>
-        <template #default="{ row }">
-          <span>{{ getSplicedDes(row.description) }}</span>
-          <span
-            class="detail-text"
-            @click="
-              handleDetailClick(row);
-              $event.stopPropagation();
-            "
-          >
-            详情</span
-          >
-        </template>
-      </el-table-column>
-      <el-table-column label="地点" prop="workspaceId" width="300">
-        <template #default="{ row }">
-          {{ getNameByWorkid(row.workshopId, row.workspaceId, locationOptions) }}
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="时间"
-        prop="createdAt"
-        width="180"
-        sortable="custom"
-      ></el-table-column>
-      <el-table-column label="负责人" prop="personNameInCharge" width="100"></el-table-column>
-      <el-table-column label="处理状态" prop="issueState">
-        <template #default="{ row }">
-          {{ getNameByStateZJC(row.issueState) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" width="60" fixed="right">
-        <template #default="{ row }">
-          <el-tooltip effect="dark" content="点击删除问题数据" placement="top">
-            <img
-              src="/src/assets/images/alert/delete.png"
-              alt=""
-              @click="
-                handleDelete(row);
-                $event.stopPropagation();
-              "
-            />
-          </el-tooltip>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ElTable } from 'element-plus';
-  import { onBeforeMount, onMounted, ref } from 'vue';
-  import { getNameByStateZJC } from './constant.question';
-  import { useIssueMainType } from '../../hooks/useIssueMainType';
-  import { useWorkLocation } from '../../hooks/useWorkLocation';
-
-  const { getAIMainOptions, getManualMainOptions, getNameByType } = useIssueMainType();
-  const { locationOptions, getLocationOptions, getNameByWorkid } = useWorkLocation();
-
-  const multipleTableRef = ref<InstanceType<typeof ElTable>>();
-
-  export interface DataSourceItem {
-    index: Number;
-    id: Number;
-    source: Number; // 问题单来源:1-AI检测、2-人工上报
-    issueType: Number; // 问题单类型
-    description: String; // 问题描述
-    workspaceId: Number[]; // 工位id(地点=车间+工位?)
-    createdAt: String;
-    personNameInCharge: String;
-    issueState: Number; // 问题单状态:1-待审核、2-待处理、3-待复核、4-已退回、5-已处理
-  }
-
-  interface Props {
-    tableData: Array<DataSourceItem>;
-    onDetail: (row: DataSourceItem) => unknown; // 详情事件
-    onDelete: (row: DataSourceItem) => unknown; // 删除按钮事件
-  }
-
-  const props = defineProps<Props>();
-
-  const emits = defineEmits(['update:selection', 'update:timeSort']);
-
-  const startPoint = ref<number | undefined>();
-  const endPoint = ref<number | undefined>();
-  const shiftKeyBoard = ref(false); // shift按钮按住/松开
-
-  const selections = ref<DataSourceItem[]>([]);
-  const handleSelectionChange = (selection: any[]) => {
-    selections.value = selection;
-    emits('update:selection', selection);
-  };
-
-  const handleShiftSelect = (_, row) => {
-    props.tableData.forEach((item, index) => {
-      item.index = index;
-    });
-    // 按住shift
-    if (shiftKeyBoard.value) {
-      // 有起点startPoint
-      if (startPoint.value !== undefined) {
-        endPoint.value = row.index as number;
-        if (startPoint.value > endPoint.value) {
-          let temp = startPoint.value;
-          startPoint.value = endPoint.value;
-          endPoint.value = temp;
-        }
-        setTimeout(() => {
-          for (let i = startPoint.value as number; i < (endPoint.value as number); i++) {
-            multipleTableRef.value!.toggleRowSelection(props.tableData[i], true);
-          }
-        }, 100);
-      }
-      // 没有起点startPoint
-      else {
-        startPoint.value = row.index;
-        endPoint.value = undefined;
-      }
-    }
-    // 没按住shift
-    else {
-      startPoint.value = row.index;
-      endPoint.value = undefined;
-    }
-  };
-
-  const rowClickSelections = ref<DataSourceItem[]>([]);
-  const handleRowClick = (row) => {
-    if (rowClickSelections.value.find((item) => item.id === row.id)) {
-      let index = rowClickSelections.value.findIndex((item) => item.id === row.id);
-      rowClickSelections.value.splice(index, 1);
-      multipleTableRef.value!.toggleRowSelection(row, false);
-    } else {
-      rowClickSelections.value.push(row);
-      multipleTableRef.value!.toggleRowSelection(row, true);
-    }
-  };
-
-  const handleDetailClick = (row) => {
-    props.onDetail(row);
-  };
-  const handleDelete = (row) => {
-    props.onDelete(row);
-  };
-
-  const handleTimeSort = (column) => {
-    let curTimeSort = '';
-    if (column.order === 'ascending') curTimeSort = 'asc';
-    if (column.order === 'descending') curTimeSort = 'desc';
-    emits('update:timeSort', curTimeSort);
-  };
-
-  const getSplicedDes = (val) => {
-    if (val.length < 15) return val;
-    else {
-      const temp = val.substring(0, 14);
-      return temp + '…';
-    }
-  };
-
-  const colorOfState = ({ row, columnIndex }) => {
-    if (columnIndex === 6) {
-      if (row.issueState === 7 || row.issueState === 8) return { color: '#52C41A ' };
-      else return { color: '#FF4D4F' };
-    }
-    if (row.isHide) {
-      return { color: '#A8ABB2' };
-    }
-  };
-
-  const colorOfRow = ({ row }) => {
-    if (selections.value.includes(row)) {
-      return 'selected-row';
-    }
-    return '';
-  };
-
-  const clearAll = () => {
-    multipleTableRef.value!.clearSelection();
-  };
-
-  // 改变当前打开详情的表格行的选中状态
-  const updateCurRowChosen = (row, status: boolean) => {
-    multipleTableRef.value!.toggleRowSelection(row, status);
-  };
-
-  defineExpose({ clearAll, updateCurRowChosen });
-
-  onBeforeMount(() => {
-    getAIMainOptions();
-    getManualMainOptions();
-    getLocationOptions();
-  });
-
-  onMounted(() => {
-    window.addEventListener('keydown', (code) => {
-      if (code.shiftKey) {
-        shiftKeyBoard.value = true;
-      }
-    });
-    window.addEventListener('keyup', (code) => {
-      if (!code.shiftKey) {
-        shiftKeyBoard.value = false;
-        startPoint.value = -1;
-        endPoint.value = -1;
-      }
-    });
-  });
-</script>
-
-<style scoped lang="less">
-  .alert-table-box {
-    display: flex;
-    flex-direction: column;
-    height: calc(100vh - 290px);
-  }
-
-  .detail-text {
-    color: #1890ff;
-    font-weight: 500;
-    cursor: pointer;
-  }
-
-  :deep(.el-table-fixed-column--right) {
-    .cell {
-      display: flex;
-    }
-
-    img {
-      margin-right: 20px;
-      cursor: pointer;
-    }
-  }
-
-  :deep(.el-table) {
-    ::before {
-      height: 0px;
-    }
-
-    .selected-row {
-      background: #f3f8ff;
-    }
-  }
-</style>

+ 0 - 146
src/views/datamanager/alertformdata/components/common/DetailDialog.vue

@@ -1,146 +0,0 @@
-<template>
-  <div>
-    <el-dialog
-      v-model="visible"
-      title="问题详情"
-      width="80%"
-      align-center
-      :close-on-click-modal="false"
-      @close="handleClose"
-    >
-      <div class="description-box">
-        <div class="title">问题描述</div>
-        <p>{{ detailDescription }}</p>
-      </div>
-      <div>
-        <div class="title">问题图片/视频</div>
-        <SwiperThumbsGallery v-if="updateSwiper" />
-      </div>
-      <template #footer>
-        <div class="dialog-footer">
-          <span class="footer-tip">提示:可切换查看问题列表当前分页内数据</span>
-          <el-button @click="handlePrevious" :disabled="!hasPreviousRow">上一个</el-button>
-          <el-button type="primary" @click="handleNext" :disabled="!hasNextRow">下一个</el-button>
-          <el-checkbox
-            class="footer-checkbox"
-            v-model="curHasBeenChosen"
-            label="是否选中"
-            @change="handleChooseStatus"
-          />
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed, nextTick, ref } from 'vue';
-  import { storeToRefs } from 'pinia';
-  import { useCurImgVideoUrlStore } from '../../store/useCurImgVideoUrl';
-  import SwiperThumbsGallery from './SwiperThumbsGallery.vue';
-
-  const curImgVideoUrl = useCurImgVideoUrlStore();
-  const { detailRowChosen, hasPreviousRow, hasNextRow, detailDescription } = storeToRefs(curImgVideoUrl);
-
-  const emits = defineEmits(['close', 'update:previous', 'update:next', 'update:choose']);
-
-  const visible = ref(true);
-  const updateSwiper = ref(true);
-
-  const curHasBeenChosen = computed(() => {
-    return detailRowChosen.value;
-  });
-
-  const handleClose = () => {
-    emits('close');
-  };
-
-  const handlePrevious = () => {
-    emits('update:previous');
-  };
-
-  const handleNext = () => {
-    emits('update:next');
-    updateSwiper.value = false;
-    nextTick(() => {
-      updateSwiper.value = true;
-    });
-  };
-
-  const handleChooseStatus = () => {
-    emits('update:choose', curHasBeenChosen.value);
-    updateSwiper.value = false;
-    nextTick(() => {
-      updateSwiper.value = true;
-    });
-  };
-</script>
-
-<style scoped lang="less">
-  :deep(.el-dialog) {
-    padding: 0;
-    background: #ffffff;
-    box-shadow: 0px 9px 28px 8px rgba(0, 0, 0, 0.05), 0px 6px 16px 0px rgba(0, 0, 0, 0.08),
-      0px 3px 6px -4px rgba(0, 0, 0, 0.12);
-
-    .el-dialog__header {
-      display: flex;
-      align-items: center;
-      height: 56px;
-      padding-left: 24px;
-      padding-bottom: 0;
-      border-bottom: 1px solid rgba(0, 0, 0, 0.06);
-    }
-
-    .el-dialog__title {
-      color: rgba(0, 0, 0, 0.88);
-      font-size: 16px;
-      font-weight: 500;
-    }
-
-    .el-dialog__headerbtn .el-dialog__close {
-      color: #000;
-    }
-
-    .el-dialog__body {
-      height: 690px;
-      padding: 20px 40px 0 40px;
-      overflow: auto;
-    }
-
-    .el-dialog__footer {
-      height: 92px;
-      padding: 28px 48px;
-
-      .footer-tip {
-        margin-right: 40px;
-        color: rgba(0, 0, 0, 0.3);
-      }
-
-      .footer-checkbox {
-        margin-left: 40px;
-      }
-    }
-  }
-
-  .title {
-    margin-bottom: 20px;
-    color: #303133;
-    font-size: 16px;
-    font-weight: 500;
-  }
-
-  .title:before {
-    margin-right: 8px;
-    content: '';
-    border-left: 3px solid #1777ff;
-  }
-
-  .description-box {
-    margin-bottom: 20px;
-
-    p {
-      color: #606266;
-    }
-  }
-</style>

+ 0 - 22
src/views/datamanager/alertformdata/components/common/EditDrawer.vue

@@ -1,22 +0,0 @@
-<template>
-  <QuestionFormBase @save-form="handleEdit" @close-form="handleClose" v-bind="$attrs" />
-</template>
-
-<script setup lang="ts">
-import QuestionFormBase from './QuestionFormBase.vue';
-import { EditShowTableData } from '@/api/datamanagement/alert-show'
-
-const emits = defineEmits(['close']);
-
-const handleEdit = (formData) => {
-  EditShowTableData(formData).then(() => {
-    emits('close');
-  })
-};
-
-const handleClose = () => {
-  emits('close');
-};
-</script>
-
-<style scoped></style>

+ 0 - 298
src/views/datamanager/alertformdata/components/common/Prequalification.vue

@@ -1,298 +0,0 @@
-<template>
-  <div class="main-container" v-if="hasDevModePermisson() || hasVideoCutPermisson()">
-    <div class="switch-container">
-      <div class="prequal-container" v-if="hasDevModePermisson()">
-        <el-tooltip
-          effect="light"
-          placement="bottom-start"
-          content="预审模式开启,违规问题在设置生效后,进行前台展示"
-        >
-          <el-icon :size="20" style="margin: 6px 4px"><QuestionFilled /></el-icon>
-        </el-tooltip>
-        <span>预审模式:</span>
-        <el-switch :model-value="devMode" @change="handelSwitchDevMode" />
-      </div>
-      <div style="display: flex" v-if="hasVideoCutPermisson()">
-        <div>报警视频截取时长:</div>
-        <el-select
-          v-model="videoLength"
-          style="width: 80px; margin: 0 10px"
-          @change="updateNewVideoLength"
-        >
-          <el-option v-for="item in videoLengthOptions" :key="item" :label="item" :value="item" />
-        </el-select>
-        <div>s</div>
-      </div>
-    </div>
-    <div class="options-container" v-if="hasDevModePermisson() && devMode">
-      <el-tooltip effect="light" placement="bottom-start" content="选择直接生效的问题类型">
-        <el-icon :size="20" style="margin: 6px 4px"><WarningFilled /></el-icon>
-      </el-tooltip>
-      <div class="option-title">白名单问题类型:</div>
-      <div class="option-tags" :class="expandAll ? 'hide-style' : ''" id="option-id">
-        <el-popover
-          placement="bottom-start"
-          trigger="click"
-          :width="240"
-          popper-style="height: 400px; overflow: auto;"
-        >
-          <template #reference>
-            <div class="add-options">+</div>
-          </template>
-          <template #default>
-            <div
-              v-for="item in options"
-              :key="item.id"
-              class="common-option"
-              :class="isOptionInTags(item.id) ? 'chosen-option' : ''"
-              @click="handleChangeTagStatus(item.id)"
-            >
-              {{ item.name }}
-            </div>
-          </template>
-        </el-popover>
-
-        <el-tag
-          class="option-tag"
-          v-for="item in tags"
-          :key="item.id"
-          :hit="true"
-          color="#fff"
-          type="primary"
-          closable
-          @close="handleDeleteTag(item)"
-          >{{ item.algoName }}</el-tag
-        >
-      </div>
-      <div v-if="isExpandAllExist" class="option-expand" @click="expandAll = !expandAll">
-        <div v-if="expandAll"
-          ><el-icon><ArrowDown /></el-icon>展开</div
-        >
-        <div v-if="!expandAll"
-          ><el-icon><ArrowUp /></el-icon>收起</div
-        >
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { nextTick, onMounted, ref, watch } from 'vue';
-  import {
-    ElMessage,
-    ElSwitch,
-    ElSelect,
-    ElOption,
-    ElTooltip,
-    ElTag,
-    ElPopover,
-    ElIcon,
-  } from 'element-plus';
-  import { QuestionFilled, WarningFilled, ArrowDown, ArrowUp } from '@element-plus/icons-vue';
-  import { useUserStore } from '@/store/modules/user';
-  import {
-    getDevMode,
-    switchDevMode,
-    getVideoLength,
-    updateVideoLength,
-    DirectPushIssueType,
-    getCurIssueTypeList,
-    addCurIssueTypeList,
-    deleteCurIssueTypeList,
-  } from '@/api/datamanagement/getDevMode';
-  import { AlgoItem, getAllAlgosApi } from '@/api/camera/camera-preview';
-  import { PERM_DATA } from '@/types/permission/constants';
-
-  const userStore = useUserStore();
-  const hasDevModePermisson = () => {
-    return userStore.checkPermission(PERM_DATA.VIOLATION_PERVIEW);
-  };
-  const hasVideoCutPermisson = () => {
-    return userStore.checkPermission(PERM_DATA.VIOLATION_VIDEO_SETTING);
-  };
-
-  const devMode = ref(true);
-  const videoLength = ref(10);
-  const videoLengthOptions = [10, 20, 40, 60];
-  const tags = ref<DirectPushIssueType[]>([]);
-  const isExpandAllExist = ref(false);
-  const expandAll = ref(false);
-  const options = ref<AlgoItem[]>([]);
-
-  const handelSwitchDevMode = () => {
-    switchDevMode();
-    devMode.value = !devMode.value;
-  };
-
-  const updateNewVideoLength = () => {
-    updateVideoLength(videoLength.value).then(() => {
-      ElMessage({
-        message: '报警视频截取长度设置成功',
-        type: 'success',
-      });
-    });
-  };
-
-  const isOptionInTags = (val) => {
-    if (tags.value) return tags.value.find((item) => item.algoInfoId === val);
-    else return false;
-  };
-
-  const handleChangeTagStatus = async (val) => {
-    if (tags.value && tags.value.find((item) => item.algoInfoId === val)) {
-      const targetTag = tags.value.find((item) => item.algoInfoId === val);
-      handleDeleteTag(targetTag);
-    } else {
-      await addCurIssueTypeList({ algoInfoIdList: [val] });
-      getCurOptions();
-    }
-  };
-
-  const handleDeleteTag = async (tag) => {
-    await deleteCurIssueTypeList(tag.id);
-    getCurOptions();
-  };
-
-  const getCurDevMode = () => {
-    getDevMode().then((res) => {
-      devMode.value = res;
-    });
-  };
-
-  const getCurVideoLength = () => {
-    getVideoLength().then((res) => {
-      videoLength.value = res;
-    });
-  };
-
-  const getCurOptions = async () => {
-    await getCurIssueTypeList().then((res) => {
-      tags.value = res;
-    });
-  };
-
-  const getAllOptions = () => {
-    getAllAlgosApi().then((res) => {
-      options.value = res;
-    });
-  };
-
-  watch(
-    () => tags.value,
-    () => {
-      nextTick(() => {
-        const objDivID = document.getElementById('option-id');
-        if (objDivID && objDivID.clientHeight > 35) {
-          isExpandAllExist.value = true;
-        } else {
-          isExpandAllExist.value = false;
-        }
-      });
-    },
-    { immediate: true },
-  );
-
-  onMounted(() => {
-    getCurDevMode();
-    getCurVideoLength();
-    getAllOptions();
-    getCurOptions();
-  });
-</script>
-
-<style scoped lang="less">
-  .main-container {
-    margin-bottom: 20px;
-    padding-bottom: 5px;
-    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
-  }
-
-  .switch-container {
-    display: flex;
-    line-height: 33px;
-    margin-bottom: 10px;
-
-    .prequal-container {
-      display: flex;
-      margin-right: 30px;
-    }
-  }
-
-  .options-container {
-    display: flex;
-    padding: 10px;
-    border-radius: 4px;
-    background-color: rgba(55, 55, 55, 0.05);
-
-    .option-title {
-      width: 130px;
-      padding-top: 7px;
-    }
-
-    .option-tags {
-      height: 100%;
-      flex: 1;
-
-      .option-tag {
-        height: 28px;
-        border: none;
-        border-radius: 5px;
-        margin: 3px 5px 4px 0;
-      }
-    }
-
-    .hide-style {
-      height: 35px;
-      overflow: hidden;
-    }
-
-    .option-expand {
-      padding-top: 7px;
-      color: #1890ff;
-      cursor: pointer;
-    }
-  }
-
-  .add-options {
-    width: 100px;
-    height: 28px;
-    border-radius: 5px;
-    background: rgba(0, 0, 0, 0.05);
-    color: rgba(0, 0, 0, 0.5);
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
-    margin-right: 5px;
-    cursor: pointer;
-    transition: all 0.4s;
-  }
-
-  .add-options:hover {
-    background: rgba(0, 0, 0, 0.15);
-    transform: scale(1.05);
-  }
-
-  .common-option {
-    padding: 5px;
-    font-size: 16px;
-    cursor: pointer;
-  }
-
-  .chosen-option {
-    position: relative;
-    color: #1890ff;
-    font-weight: 600;
-  }
-
-  .chosen-option::after {
-    content: '';
-    position: absolute;
-    right: 4px;
-    top: 7px;
-    width: 8px;
-    height: 12px;
-    border: solid #1890ff;
-    border-width: 0 2px 2px 0;
-    transform: rotate(45deg);
-  }
-</style>

+ 0 - 309
src/views/datamanager/alertformdata/components/common/QueryForm.vue

@@ -1,309 +0,0 @@
-<template>
-  <div>
-    <el-form :model="queryForm" label-width="auto" :inline="true" ref="formRef">
-      <div class="select-group">
-        <el-form-item label="问题来源:" prop="queryParam.source">
-          <el-select
-            v-model="queryForm.queryParam.source"
-            placeholder="全部"
-            clearable
-            @change="handleSelectChange"
-          >
-            <el-option
-              v-for="item in sourceOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="类型:" prop="queryParam.issueTypeList">
-          <el-cascader
-            v-model="issueTypeValue"
-            :options="options"
-            :props="issueMainTypeProp"
-            clearable
-            collapse-tags
-            :show-all-levels="false"
-            popper-class="special-cascader"
-            :disabled="typeDisable"
-            @change="handleIssueMainTypeChange"
-          />
-        </el-form-item>
-        <el-form-item label="地点:" prop="queryParam.workspaceId">
-          <el-cascader
-            v-model="workLocation"
-            :options="locationOptions"
-            :props="locationProp"
-            clearable
-            collapse-tags
-            :show-all-levels="false"
-            popper-class="special-cascader"
-            @change="handleCascaderChange"
-          />
-        </el-form-item>
-        <el-form-item label="处理状态:" prop="queryParam.issueState">
-          <el-select v-model="tempState" clearable @change="handleIssueStateChange">
-            <el-option
-              v-for="item in issueStateOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="生效状态:" prop="queryParam.hide">
-          <el-select v-model="queryForm.queryParam.hide" clearable>
-            <el-option
-              v-for="item in hideStateOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="日期:">
-          <el-date-picker
-            v-model="dateRange"
-            type="daterange"
-            range-separator="~"
-            start-placeholder="开始时间"
-            end-placeholder="结束时间"
-            clearable
-            unlink-panels
-            value-format="YYYY-MM-DD HH:mm:ss"
-            :default-time="defaultTime"
-            @change="handleDateChange"
-          />
-        </el-form-item>
-      </div>
-      <div class="btn-group">
-        <el-form-item>
-          <el-button class="search-btn" type="primary" @click="handleSearch">查询</el-button>
-          <el-button class="reset-btn" @click="handleReset">重置</el-button>
-          <el-button class="reset-btn" @click="handleExport" v-if="!isShowTab">导出</el-button>
-        </el-form-item>
-      </div>
-    </el-form>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import type { FormInstance } from 'element-plus';
-  import { reactive, ref } from 'vue';
-  import { sourceOptions, hideStateOptions, issueStateOptions } from './constant.question';
-  import { TableQueryForm } from '@/api/datamanagement/alert-default';
-
-  interface Props {
-    isShowTab: boolean; // true展示数据,false默认数据
-    aiOptions: Array<any>;
-    manualOptions: Array<any>;
-    locationOptions: Array<any>;
-  }
-  const props = defineProps<Props>();
-  const emits = defineEmits(['onSearch', 'onReset', 'onExport']);
-
-  const formRef = ref<FormInstance>();
-  const queryForm = reactive<TableQueryForm>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-  });
-
-  type MainOption = {
-    value: number;
-    label: string;
-    children: {
-      value: number;
-      label: string;
-    }[];
-  };
-
-  const options = ref<MainOption[]>([]);
-  const typeDisable = ref(true);
-  const issueTypeValue = ref([]); // 问题类型,级联选择器
-  const issueMainTypeProp = { multiple: true, expandTrigger: 'hover' as const };
-  const workShopIds = ref([]);
-  const workLocation = ref([]); // 级联选择器,为二维数组(提取workspaceId)
-  const locationProp = { multiple: true, expandTrigger: 'hover' as const }; // 级联选择器(打开多选)
-  const tempState = ref(''); // 状态,字符串转number[]
-  const dateRange = ref([]); // 时间段,拆分成startTime/endTime
-  const defaultTime = ref<[Date, Date]>([
-    new Date(2000, 1, 1, 0, 0, 0),
-    new Date(2000, 2, 1, 23, 59, 59),
-  ]);
-
-  const handleSearch = () => {
-    emits('onSearch', queryForm);
-  };
-
-  const handleReset = () => {
-    workShopIds.value = [];
-    issueTypeValue.value = [];
-    typeDisable.value = true;
-    workLocation.value = [];
-    tempState.value = '';
-    dateRange.value = [];
-    Reflect.deleteProperty(queryForm.queryParam, 'startTime');
-    Reflect.deleteProperty(queryForm.queryParam, 'endTime');
-    Reflect.deleteProperty(queryForm.queryParam, 'issueMainTypeList');
-    Reflect.deleteProperty(queryForm.queryParam, 'issueTypeList');
-    formRef.value?.resetFields();
-    emits('onReset', queryForm);
-  };
-
-  const handleExport = () => {
-    emits('onExport', queryForm, workShopIds.value);
-  };
-
-  const handleSelectChange = () => {
-    if (Number(queryForm.queryParam.source) === 1) {
-      typeDisable.value = false;
-      options.value = props.aiOptions;
-    } else if (Number(queryForm.queryParam.source) === 2) {
-      typeDisable.value = false;
-      options.value = props.manualOptions;
-    } else {
-      typeDisable.value = true;
-      options.value = [];
-      queryForm.queryParam.issueMainTypeList = undefined;
-      queryForm.queryParam.issueTypeList = undefined;
-    }
-  };
-
-  const handleIssueMainTypeChange = () => {
-    if (issueTypeValue.value.length !== 0) {
-      const arrMain = [];
-      const arrSub = [];
-      issueTypeValue.value.forEach((item) => {
-        arrMain.push(item[0]);
-        arrSub.push(item[1]);
-      });
-      queryForm.queryParam.issueMainTypeList = [...new Set(arrMain)];
-      queryForm.queryParam.issueTypeList = arrSub;
-    } else {
-      Reflect.deleteProperty(queryForm.queryParam, 'issueMainTypeList');
-      Reflect.deleteProperty(queryForm.queryParam, 'issueTypeList');
-    }
-  };
-
-  const handleCascaderChange = () => {
-    if (workLocation.value.length !== 0) {
-      const arr = [];
-      workShopIds.value = [];
-      workLocation.value.forEach((item) => {
-        arr.push(item[1]);
-        workShopIds.value.push(item[0]);
-      });
-      queryForm.queryParam.workspaceId = arr;
-      workShopIds.value = [...new Set(workShopIds.value)];
-    } else {
-      Reflect.deleteProperty(queryForm.queryParam, 'workspaceId');
-    }
-  };
-
-  const handleIssueStateChange = () => {
-    if (tempState.value) queryForm.queryParam.issueState = JSON.parse(tempState.value);
-    else Reflect.deleteProperty(queryForm.queryParam, 'issueState');
-  };
-
-  const handleDateChange = () => {
-    if (dateRange.value != null) {
-      queryForm.queryParam.startTime = dateRange.value[0];
-      queryForm.queryParam.endTime = dateRange.value[1];
-    } else {
-      Reflect.deleteProperty(queryForm.queryParam, 'startTime');
-      Reflect.deleteProperty(queryForm.queryParam, 'endTime');
-    }
-  };
-
-  // TODO: cascader点击任意位置选中,DOM方式实现一级,CSS方式无法穿透
-  // TODO: el-cascader组件需添加 @expand-change="handleLocationExpandChange"(当前暂时删除)
-  // const curLocationLevel = ref(0);
-  // const handleLocationExpandChange = (event) => {
-  //   curLocationLevel.value = event.length;
-  //   nextTick(() => {
-  //     setCascaderDomEvent();
-  //   });
-  // };
-
-  // const setCascaderDomEvent = () => {
-  //   const cascaderDom = document.querySelectorAll('.special-cascader .el-cascader-menu__list');
-
-  //   if (cascaderDom.length >= curLocationLevel.value - 1) {
-  //     const optionDom = cascaderDom[curLocationLevel.value] as Element;
-  //     optionDom.querySelectorAll('.el-cascader-node__label').forEach((label: Element) => {
-  //       const nextDom = label.nextElementSibling;
-  //       label.addEventListener('click', cascaderCheckEvent);
-  //       if (!nextDom) {
-  //         (label as HTMLElement).style.cursor = 'pointer';
-  //       }
-  //     });
-  //   }
-  //   if (curLocationLevel.value) {
-  //     const optionDom = cascaderDom[curLocationLevel.value - 1] as Element;
-  //     optionDom.querySelectorAll('.el-cascader-node__label').forEach((label: Element) => {
-  //       const nextDom = label.nextElementSibling;
-  //       label.addEventListener('click', cascaderCheckEvent);
-  //       if (!nextDom) {
-  //         (label as HTMLElement).style.cursor = 'pointer';
-  //       }
-  //     });
-  //   }
-  // };
-
-  // const cascaderCheckEvent = (event: MouseEvent) => {
-  //   // 查找对应的输入框
-  //   let brother = (event.target as HTMLElement).previousElementSibling; // 获取前一个兄弟元素
-  //   const input = brother?.querySelector('input[type="checkbox"], input[type="radio"]'); // 支持复选框和单选框
-  //   if (input) {
-  //     (input as HTMLInputElement).click(); // 模拟点击复选框
-  //   }
-
-  //   // 如果有子菜单,展开/收起子菜单
-  //   const childMenu = (event.target as HTMLElement).nextElementSibling;
-  //   if (childMenu && childMenu.classList.contains('el-cascader-menu__list')) {
-  //     // 这里可以根据需求添加展开/收起的逻辑
-  //   }
-  // };
-</script>
-
-<style scoped lang="less">
-  .el-form {
-    display: flex;
-    justify-content: space-between;
-  }
-
-  :deep(.el-form--inline .el-form-item) {
-    margin-right: 10px;
-  }
-
-  :deep(.el-form-item__label) {
-    padding-left: 10px;
-  }
-
-  .select-group {
-    flex: 1;
-  }
-
-  .btn-group {
-    .search-btn {
-      width: 65px;
-      height: 32px;
-      background: #1890ff;
-      border-radius: 2px;
-    }
-
-    .reset-btn {
-      width: 65px;
-      height: 32px;
-      border-radius: 2px;
-      border: 1px solid #1890ff;
-      color: #1890ff;
-    }
-  }
-
-  .el-select {
-    --el-select-width: 215px;
-  }
-</style>

+ 0 - 187
src/views/datamanager/alertformdata/components/common/QueryFormSimple.vue

@@ -1,187 +0,0 @@
-<template>
-  <div>
-    <el-form :model="queryForm" label-width="auto" :inline="true" ref="formRef">
-      <div class="select-group">
-        <el-form-item label="类型:" prop="issueTypeList">
-          <el-cascader
-            v-model="issueTypeValue"
-            :options="props.aiOptions"
-            :props="issueMainTypeProp"
-            clearable
-            collapse-tags
-            :show-all-levels="false"
-            @change="handleIssueMainTypeChange"
-          />
-        </el-form-item>
-        <el-form-item label="地点:" prop="workspaceId">
-          <el-cascader
-            v-model="workLocation"
-            :options="props.locationOptions"
-            :props="locationProp"
-            clearable
-            collapse-tags
-            :show-all-levels="false"
-            @change="handleCascaderChange"
-          />
-        </el-form-item>
-        <el-form-item label="处理状态:" prop="issueState">
-          <el-select v-model="tempState" clearable @change="handleIssueStateChange">
-            <el-option
-              v-for="item in issueStateOptionsZJC"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="日期:">
-          <el-date-picker
-            v-model="dateRange"
-            type="daterange"
-            range-separator="~"
-            start-placeholder="开始时间"
-            end-placeholder="结束时间"
-            clearable
-            unlink-panels
-            value-format="YYYY-MM-DD HH:mm:ss"
-            :default-time="defaultTime"
-            @change="handleDateChange"
-          />
-        </el-form-item>
-      </div>
-      <div class="btn-group">
-        <el-form-item>
-          <el-button class="search-btn" type="primary" @click="handleSearch">查询</el-button>
-          <el-button class="reset-btn" @click="handleReset">重置</el-button>
-        </el-form-item>
-      </div>
-    </el-form>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import type { FormInstance } from 'element-plus';
-  import { reactive, ref } from 'vue';
-  import { issueStateOptionsZJC } from './constant.question';
-  import { TableQueryForm } from '@/api/datamanagement/alert-default';
-
-  const props = defineProps({
-    aiOptions: Array<any>,
-    locationOptions: Array<any>,
-  });
-  const emits = defineEmits(['onSearch', 'onReset']);
-
-  const formRef = ref<FormInstance>();
-  const queryForm = reactive<TableQueryForm>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-  });
-
-  const issueTypeValue = ref([]);
-  const issueMainTypeProp = { multiple: true, expandTrigger: 'hover' as const };
-  const workLocation = ref([]); // 级联选择器,为二维数组(提取workspaceId)
-  const locationProp = { multiple: true, expandTrigger: 'hover' as const }; // 级联选择器(打开多选)
-  const tempState = ref(''); // 状态,字符串转number[]
-  const dateRange = ref([]); // 时间段,拆分成startTime/endTime
-  const defaultTime = ref<[Date, Date]>([
-    new Date(2000, 1, 1, 0, 0, 0),
-    new Date(2000, 2, 1, 23, 59, 59),
-  ]);
-
-  const handleSearch = () => {
-    emits('onSearch', queryForm);
-  };
-
-  const handleReset = () => {
-    issueTypeValue.value = [];
-    workLocation.value = [];
-    tempState.value = '';
-    dateRange.value = [];
-    Reflect.deleteProperty(queryForm.queryParam, 'startTime');
-    Reflect.deleteProperty(queryForm.queryParam, 'endTime');
-    Reflect.deleteProperty(queryForm.queryParam, 'issueMainTypeList');
-    Reflect.deleteProperty(queryForm.queryParam, 'issueTypeList');
-    formRef.value?.resetFields();
-    emits('onReset', queryForm);
-  };
-
-  const handleIssueMainTypeChange = () => {
-    if (issueTypeValue.value.length !== 0) {
-      const arrMain = [];
-      const arrSub = [];
-      issueTypeValue.value.forEach((item) => {
-        arrMain.push(item[0]);
-        arrSub.push(item[1]);
-      });
-      queryForm.queryParam.issueMainTypeList = [...new Set(arrMain)];
-      queryForm.queryParam.issueTypeList = arrSub;
-    } else {
-      Reflect.deleteProperty(queryForm.queryParam, 'issueMainTypeList');
-      Reflect.deleteProperty(queryForm.queryParam, 'issueTypeList');
-    }
-  };
-
-  const handleCascaderChange = () => {
-    if (workLocation.value.length !== 0) {
-      const arr = [];
-      workLocation.value.forEach((item) => {
-        arr.push(item[1]);
-      });
-      queryForm.queryParam.workspaceId = arr;
-    } else {
-      Reflect.deleteProperty(queryForm.queryParam, 'workspaceId');
-    }
-  };
-
-  const handleIssueStateChange = () => {
-    if (tempState.value) queryForm.queryParam.issueState = JSON.parse(tempState.value);
-    else Reflect.deleteProperty(queryForm.queryParam, 'issueState');
-  };
-
-  const handleDateChange = () => {
-    if (dateRange.value != null) {
-      queryForm.queryParam.startTime = dateRange.value[0];
-      queryForm.queryParam.endTime = dateRange.value[1];
-    } else {
-      Reflect.deleteProperty(queryForm.queryParam, 'startTime');
-      Reflect.deleteProperty(queryForm.queryParam, 'endTime');
-    }
-  };
-</script>
-
-<style scoped lang="less">
-  .el-form {
-    display: flex;
-    justify-content: space-between;
-  }
-
-  :deep(.el-form-item__label) {
-    padding: 0;
-  }
-
-  .select-group {
-    flex: 1;
-  }
-
-  .btn-group {
-    .search-btn {
-      width: 65px;
-      height: 32px;
-      background: #1890ff;
-      border-radius: 2px;
-    }
-
-    .reset-btn {
-      width: 65px;
-      height: 32px;
-      border-radius: 2px;
-      border: 1px solid #1890ff;
-      color: #1890ff;
-    }
-  }
-
-  .el-select {
-    --el-select-width: 215px;
-  }
-</style>

+ 0 - 453
src/views/datamanager/alertformdata/components/common/QuestionFormBase.vue

@@ -1,453 +0,0 @@
-<template>
-  <div>
-    <el-drawer
-      v-model="visible"
-      title="问题编辑"
-      direction="rtl"
-      size="30%"
-      :close-on-click-modal="false"
-      @close="handleCancel"
-    >
-      <el-form ref="formRef" :model="formData">
-        <el-form-item
-          label="问题来源:"
-          prop="source"
-          :rules="{ required: true, message: '请完成必填项' }"
-        >
-          <el-select
-            v-model="formData.source"
-            placeholder="请选择问题来源"
-            clearable
-            @change="handleSelectChange"
-          >
-            <el-option
-              v-for="item in sourceOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item
-          label="问题类型:"
-          prop="issueType"
-          :rules="{ required: true, message: '请完成必填项' }"
-        >
-          <el-select v-model="formData.issueType" placeholder="请选择问题类型" clearable>
-            <el-option v-for="item in options" :label="item.name" :value="item.id" />
-          </el-select>
-        </el-form-item>
-        <el-form-item
-          label="问题描述:"
-          prop="description"
-          :rules="{ required: true, message: '请完成必填项' }"
-        >
-          <el-input
-            v-model="formData.description"
-            type="textarea"
-            maxlength="100"
-            autosize
-            show-word-limit
-            placeholder="请输入问题描述,不超过100个字"
-          ></el-input>
-        </el-form-item>
-        <el-form-item
-          class="pic-form-item"
-          label="问题图片:"
-          prop="pictures"
-          :rules="{ required: true, message: '请完成必填项' }"
-        >
-          <p>(建议尺寸192*108,大小10M以下)</p>
-          <el-upload
-            v-model:file-list="fileList"
-            :action="actionUrl"
-            list-type="picture-card"
-            :on-preview="handlePictureCardPreview"
-            :on-remove="handleRemove"
-            :on-success="handleAvatarSuccess"
-            :headers="getHeaders()"
-            :data="{ bizType: 'PROBLEM_REPORT' }"
-          >
-            <el-icon>
-              <Plus />
-            </el-icon>
-          </el-upload>
-          <el-dialog v-model="dialogVisible">
-            <img w-full :src="dialogImageUrl" alt="Preview Image" />
-          </el-dialog>
-        </el-form-item>
-        <el-form-item class="pic-form-item" label="问题视频:" prop="videos">
-          <p>(仅支持上传1条视频,大小50M以内)</p>
-          <el-upload
-            v-if="
-              formData.videos === undefined ||
-              formData.videos === null ||
-              (formData.videos && formData.videos.length === 0)
-            "
-            class="avatar-uploader"
-            :action="actionUrl"
-            :show-file-list="false"
-            :on-success="handleUploadVideo"
-            :headers="getHeaders()"
-            :data="{ bizType: 'PROBLEM_REPORT' }"
-            :before-upload="beforeUploadVideo"
-          >
-            <el-icon class="avatar-uploader-icon">
-              <Plus />
-            </el-icon>
-          </el-upload>
-          <div class="upload-success" v-else>
-            <img
-              src="@/assets/images/alert/video-play.png"
-              @click="videoDialogVisible = true"
-              style="cursor: pointer"
-            />
-            <el-icon class="clear-video" @click="handleDeleteVideo" :size="15" color="#fff">
-              <CloseBold />
-            </el-icon>
-            <el-dialog v-model="videoDialogVisible">
-              <video
-                type="video/mp4"
-                muted="true"
-                preload="auto"
-                :controls="true"
-                autoplay
-                style="height: 500px; object-fit: fill"
-              >
-                <source :src="formData.videos![0]" />
-              </video>
-            </el-dialog>
-          </div>
-        </el-form-item>
-        <el-form-item
-          label="问题地点:"
-          prop="workspaceId"
-          :rules="{ required: true, message: '请完成必填项' }"
-        >
-          <el-cascader
-            v-model="workLocation"
-            :options="locationOptions"
-            :props="location"
-            placeholder="请选择问题地点"
-            clearable
-            @change="handleCascaderChange"
-          />
-        </el-form-item>
-        <el-form-item
-          label="问题时间:"
-          prop="createdAt"
-          :rules="{ required: true, message: '请完成必填项' }"
-        >
-          <el-date-picker
-            v-model="formData.createdAt"
-            type="datetime"
-            value-format="YYYY-MM-DD HH:mm:ss"
-            placeholder="请选择问题时间"
-          />
-        </el-form-item>
-        <el-form-item
-          label="问题状态:"
-          prop="issueState"
-          :rules="{ required: true, message: '请完成必填项' }"
-        >
-          <el-select v-model="formData.issueState" placeholder="请选择问题状态" clearable>
-            <el-option
-              v-for="item in issueStateOptionsAdd"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item>
-          <div class="btn-box">
-            <el-button @click="handleCancel">取消</el-button>
-            <el-button type="primary" @click="handleSubmit(formRef)">保存</el-button>
-          </div>
-        </el-form-item>
-      </el-form>
-    </el-drawer>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { computed, onBeforeMount, onMounted, reactive, ref } from 'vue';
-  import {
-    ElMessage,
-    type FormInstance,
-    type UploadProps,
-    type UploadUserFile,
-  } from 'element-plus';
-  import { Plus, CloseBold } from '@element-plus/icons-vue';
-  import { Source, IssueState, sourceOptions, issueStateOptionsAdd } from './constant.question';
-  import { useIssueType } from '../../hooks/useIssueType';
-  import { useWorkLocation } from '../../hooks/useWorkLocation';
-  import { getHeaders } from '@/utils/http/axios';
-  import urlJoin from 'url-join';
-  import { useGlobSetting } from '@/hooks/setting';
-
-  interface Props {
-    initialData?: FormModel;
-  }
-
-  interface FormModel {
-    id?: number;
-    source?: number; // 来源
-    issueType?: number; // 类型
-    description?: string; // 描述
-    pictures?: string[]; // 图片
-    videos?: string[];
-    workshopId?: number; // 车间id
-    workshopName?: string;
-    workspaceId?: number; // 工位id
-    workspaceName?: string;
-    createdAt?: string; // 时间
-    issueState?: number; // 状态
-  }
-
-  const visible = ref(true);
-  const { aiOptions, manualOptions, getAIOptions, getManualOptions } = useIssueType();
-  const { locationOptions, getLocationOptions, getNameByWorkid } = useWorkLocation();
-
-  const props = defineProps<Props>();
-  const emits = defineEmits(['saveForm', 'closeForm']);
-
-  const formRef = ref<FormInstance>();
-  const formData = reactive<FormModel>({
-    id: undefined,
-    source: undefined,
-    issueType: undefined,
-    description: '',
-    pictures: [],
-    videos: [],
-    workshopId: undefined,
-    workspaceId: undefined,
-    createdAt: '',
-    issueState: undefined,
-  });
-
-  const location = { expandTrigger: 'hover' as const };
-  const workLocation = ref<[number | undefined, number | undefined] | []>([]);
-
-  const { urlPrefix } = useGlobSetting();
-
-  const handleSelectChange = () => {
-    formData.issueType = undefined;
-  };
-  const options = computed(() => {
-    if (Number(formData.source) === Source.ai && aiOptions.value.length > 0) {
-      return aiOptions.value;
-    }
-    if (Number(formData.source) === Source.manual && manualOptions.value.length > 0) {
-      return manualOptions.value;
-    }
-    return [];
-  });
-  const handleCascaderChange = () => {
-    if (workLocation.value != null) {
-      formData.workshopId = workLocation.value[0];
-      formData.workspaceId = workLocation.value[1];
-      const tempString = getNameByWorkid(
-        formData.workshopId,
-        formData.workspaceId,
-        locationOptions.value,
-      );
-      const strFlag = tempString?.indexOf('-');
-      formData.workshopName = tempString?.slice(0, strFlag);
-      formData.workspaceName = tempString?.slice(strFlag! + 1);
-    } else {
-      Reflect.deleteProperty(formData, 'workshopId');
-      Reflect.deleteProperty(formData, 'workspaceId');
-    }
-  };
-
-  const handleCopyData = () => {
-    formData.id = props.initialData?.id;
-    formData.source = props.initialData?.source;
-    formData.issueType = props.initialData?.issueType;
-    formData.description = props.initialData?.description;
-    formData.pictures = props.initialData?.pictures;
-    formData.videos = props.initialData?.videos;
-    formData.workshopId = props.initialData?.workshopId;
-    formData.workspaceId = props.initialData?.workspaceId;
-    formData.createdAt = props.initialData?.createdAt;
-
-    switch (props.initialData?.issueState) {
-      case IssueState.toAuth0:
-        formData.issueState = 2;
-        break;
-      case IssueState.toAuth1:
-        formData.issueState = 2;
-        break;
-      case IssueState.toDeal6:
-        formData.issueState = 4;
-        break;
-      case IssueState.hasDone7:
-        formData.issueState = 8;
-        break;
-      default:
-        formData.issueState = props.initialData?.issueState;
-        break;
-    }
-
-    workLocation.value = [props.initialData?.workshopId, props.initialData?.workspaceId!];
-    fileList.value = props.initialData?.pictures?.map((str) => ({ name: str, url: str })) || [];
-  };
-
-  // 取消
-  const handleCancel = () => {
-    emits('closeForm');
-  };
-
-  const actionUrl = computed(() => {
-    return urlJoin(urlPrefix!, `/admin/minio/uploadFile`);
-  });
-
-  // 保存
-  const handleSubmit = async (formEl: FormInstance | undefined) => {
-    if (!formEl) return;
-    await formEl.validate((valid, fields) => {
-      if (valid) {
-        console.log('submit!', formData);
-        emits('saveForm', formData);
-      } else {
-        console.log('error submit!', fields);
-      }
-    });
-  };
-
-  const handleAvatarSuccess = (res) => {
-    if (!formData.pictures) formData.pictures = [];
-    formData.pictures.push(res.data.url);
-  };
-  const fileList = ref<UploadUserFile[]>([]);
-  const dialogImageUrl = ref('');
-  const dialogVisible = ref(false);
-  const handleRemove: UploadProps['onRemove'] = (uploadFile) => {
-    const index = formData.pictures?.indexOf(uploadFile.url || '')!;
-    if (index !== -1) formData.pictures?.splice(index, 1);
-  };
-  const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
-    dialogImageUrl.value = uploadFile.url!;
-    dialogVisible.value = true;
-  };
-
-  // 视频上传
-  const videoDialogVisible = ref(false);
-  const handleUploadVideo = (res) => {
-    if (!formData.videos) formData.videos = [];
-    formData.videos.push(res.data.url);
-  };
-  const handleDeleteVideo = () => {
-    formData.videos = [];
-  };
-  const beforeUploadVideo: UploadProps['beforeUpload'] = (rawFile) => {
-    if (rawFile.type !== 'video/mp4') {
-      ElMessage.error('上传视频仅支持mp4格式');
-      return false;
-    } else if (rawFile.size / 1024 / 1024 > 50) {
-      ElMessage.error('上传视频大小不能超过50MB');
-      return false;
-    }
-    return true;
-  };
-
-  onMounted(() => {
-    handleCopyData();
-  });
-
-  onBeforeMount(() => {
-    getAIOptions();
-    getManualOptions();
-    getLocationOptions();
-  });
-</script>
-
-<style scoped lang="less">
-  :deep(.el-drawer__header) {
-    position: relative;
-
-    > :first-child {
-      margin-left: 32px;
-      font-weight: 600;
-      font-size: 16px;
-      color: rgba(0, 0, 0, 0.88);
-    }
-
-    .el-drawer__close-btn {
-      position: absolute;
-      color: #000;
-    }
-  }
-
-  .btn-box {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    width: 100%;
-    margin-top: 10px;
-  }
-
-  .pic-form-item {
-    :deep(.el-form-item__content) {
-      display: block;
-    }
-  }
-
-  p {
-    font-size: 10px;
-    color: #a8abb2;
-  }
-
-  :deep(.avatar-uploader .el-upload) {
-    border: 1px dashed #cdd0d6;
-    border-radius: 6px;
-    cursor: pointer;
-    position: relative;
-    overflow: hidden;
-    transition: var(--el-transition-duration-fast);
-    background-color: #fafafa;
-  }
-
-  :deep(.avatar-uploader .el-upload:hover) {
-    border-color: var(--el-color-primary);
-  }
-
-  .el-icon.avatar-uploader-icon {
-    font-size: 28px;
-    color: #909399;
-    width: 148px;
-    height: 148px;
-    text-align: center;
-  }
-
-  .upload-success {
-    position: relative;
-
-    .clear-video {
-      width: 25px;
-      height: 25px;
-      position: absolute;
-      top: 0;
-      left: 129px;
-      cursor: pointer;
-      background-color: #000;
-      border-radius: 0 0 0 25px;
-      opacity: 0.7;
-    }
-
-    :deep(.el-dialog) {
-      width: 960px;
-      height: 540px;
-      padding: 0;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background-color: #000;
-    }
-
-    :deep(.el-dialog__header) {
-      display: none;
-    }
-  }
-</style>

+ 0 - 131
src/views/datamanager/alertformdata/components/common/SwiperThumbsGallery.vue

@@ -1,131 +0,0 @@
-<template>
-  <div class="thumb-example">
-    <swiper
-      class="top-swiper"
-      :style="{
-        '--swiper-navigation-color': '#fff',
-        '--swiper-pagination-color': '#fff',
-      }"
-      :space-between="10"
-      :navigation="true"
-      :thumbs="{ swiper: thumbsSwiper }"
-      :modules="modules"
-    >
-      <swiper-slide class="slide" v-for="(item, index) in fileList" :key="index">
-        <template v-if="item.type === 'image'">
-          <img :src="item.url" alt="" @click="handleOpenPicViewer(index)" />
-        </template>
-        <template v-else-if="item.type === 'video'">
-          <VideoPlayer :video-url="item.url" />
-        </template>
-      </swiper-slide>
-    </swiper>
-
-    <swiper
-      class="thumbs-swiper"
-      :space-between="10"
-      :slides-per-view="10"
-      :watch-slides-progress="true"
-      :modules="modules"
-      @swiper="setThumbsSwiper"
-    >
-      <swiper-slide class="slide" v-for="(item, index) in fileList" :key="index">
-        <img :src="item.url" alt="" v-if="item.type === 'image'" />
-        <div v-else-if="item.type === 'video'" style="pointer-events: none; position: relative; height: 100%">
-          <VideoPlayer :video-url="item.url" :icon-size="40" :controls="false" :video-height="88" />
-        </div>
-      </swiper-slide>
-    </swiper>
-  </div>
-  <el-image-viewer
-    v-if="imgViewerVisible"
-    :url-list="detailPictures"
-    :initial-index="imgSrcIndex"
-    @close="handleClosePicViewer"
-  />
-</template>
-
-<script setup>
-  import { ref, computed } from 'vue';
-  import { storeToRefs } from 'pinia';
-  import { ElImageViewer } from 'element-plus';
-  import { Swiper, SwiperSlide } from 'swiper/vue';
-  import { Navigation, Thumbs } from 'swiper/modules';
-  import 'swiper/css';
-  import 'swiper/css/navigation';
-  import 'swiper/css/thumbs';
-  import { useCurImgVideoUrlStore } from '../../store/useCurImgVideoUrl';
-  import VideoPlayer from '@/components/VideoPlayer/VideoPlayer.vue';
-
-  const curImgVideoUrl = useCurImgVideoUrlStore();
-  const { detailPictures, detailVideos } = storeToRefs(curImgVideoUrl);
-
-  const modules = [Navigation, Thumbs];
-
-  const fileList = computed(() => {
-    const images = detailPictures.value.map((url) => ({ type: 'image', url }));
-    const videos = detailVideos.value.map((url) => ({ type: 'video', url, poster: ref('') }));
-    return [...images, ...videos];
-  });
-
-  const thumbsSwiper = ref(null);
-
-  const imgSrcIndex = ref(0);
-  const imgViewerVisible = ref(false);
-
-  const handleOpenPicViewer = (curImgIndex) => {
-    imgSrcIndex.value = curImgIndex;
-    imgViewerVisible.value = true;
-  };
-
-  const handleClosePicViewer = () => {
-    imgViewerVisible.value = false;
-  };
-
-  const setThumbsSwiper = (swiper) => {
-    thumbsSwiper.value = swiper;
-  };
-</script>
-
-<style lang="scss" scoped>
-  .thumb-example {
-    height: 540px;
-    background-color: rgba(0, 0, 0);
-  }
-
-  .top-swiper,
-  .thumbs-swiper {
-    .slide {
-      img {
-        display: block;
-        width: 100%;
-        height: 100%;
-        object-fit: contain;
-      }
-    }
-  }
-
-  .top-swiper {
-    height: 80%;
-    width: 100%;
-  }
-
-  .thumbs-swiper {
-    height: 20%;
-    box-sizing: border-box;
-    padding: 10px;
-
-    .slide {
-      width: 25%;
-      height: 100%;
-      opacity: 1;
-      border: 1px solid #fff;
-      overflow: hidden;
-
-      &:not(.swiper-slide-thumb-active) {
-        opacity: 0.8;
-        border: none;
-      }
-    }
-  }
-</style>

+ 0 - 115
src/views/datamanager/alertformdata/components/common/constant.question.ts

@@ -1,115 +0,0 @@
-// 问题来源
-export enum Source {
-  ai = 1,
-  manual = 2,
-}
-export const sourceNameMap = {
-  [Source.ai]: 'AI检测',
-  [Source.manual]: '人工上报',
-};
-// 问题来源下拉框选项
-export const sourceOptions = [
-  { label: sourceNameMap[Source.ai], value: Source.ai },
-  { label: sourceNameMap[Source.manual], value: Source.manual },
-];
-// 表格数据-转换value为label
-export const getNameBySource = (source: Source) => {
-  return sourceNameMap[source] || '-';
-};
-
-// 问题生效状态
-export const hideStateOptions = [
-  { label: '已生效', value: false },
-  { label: '未生效', value: true },
-];
-
-// 问题状态
-export enum IssueState {
-  toAuth0 = 0,
-  toAuth1 = 1,
-  toAuth2 = 2, // 待审核
-  hasRevoke = 3, // 已撤销
-  toDeal4 = 4, // 待处理
-  toDeal6 = 6,
-  toReview = 5, // 待复核
-  hasDone7 = 7,
-  hasDone8 = 8, // 已处理
-  canceling = 9, // 撤销中
-}
-export const issueStateNameMap = {
-  [IssueState.toAuth0]: '待审核',
-  [IssueState.toAuth1]: '待审核',
-  [IssueState.toAuth2]: '待审核',
-  [IssueState.hasRevoke]: '已撤销',
-  [IssueState.toDeal4]: '待处理',
-  [IssueState.toDeal6]: '待处理',
-  [IssueState.toReview]: '待复核',
-  [IssueState.hasDone7]: '已处理',
-  [IssueState.hasDone8]: '已处理',
-};
-// 问题状态下拉框选项(默认数据——待审核(012) 待处理(46) 待复核(5) 已处理(78) 已撤销(3))
-export const issueStateOptions = [
-  { label: issueStateNameMap[IssueState.toAuth0], value: '[0, 1, 2]' },
-  { label: issueStateNameMap[IssueState.toDeal4], value: '[4, 6]' },
-  { label: issueStateNameMap[IssueState.toReview], value: '[5]' },
-  { label: issueStateNameMap[IssueState.hasDone7], value: '[7,8]' },
-  { label: issueStateNameMap[IssueState.hasRevoke], value: '[3]' },
-];
-
-export const issueStateOptionsAdd = [
-  { label: issueStateNameMap[IssueState.toAuth2], value: IssueState.toAuth2 },
-  { label: issueStateNameMap[IssueState.toDeal4], value: IssueState.toDeal4 },
-  { label: issueStateNameMap[IssueState.toReview], value: IssueState.toReview },
-  { label: issueStateNameMap[IssueState.hasDone8], value: IssueState.hasDone8 },
-];
-
-// 表格数据-转换value为label
-export const getNameByState = (issueState: IssueState) => {
-  return issueStateNameMap[issueState] || '-';
-};
-
-// 中建材 —— 待处理(0123456),已处理(78)
-export enum IssueStateZJC {
-  toDeal0 = 0,
-  toDeal1 = 1,
-  toDeal2 = 2,
-  toDeal3 = 3,
-  toDeal4 = 4,
-  toDeal5 = 5,
-  toDeal6 = 6,
-  hasDone7 = 7,
-  hasDone8 = 8,
-}
-export const issueStateNameMapZJC = {
-  [IssueStateZJC.toDeal0]: '待处理',
-  [IssueStateZJC.toDeal1]: '待处理',
-  [IssueStateZJC.toDeal2]: '待处理',
-  [IssueStateZJC.toDeal3]: '待处理',
-  [IssueStateZJC.toDeal4]: '待处理',
-  [IssueStateZJC.toDeal5]: '待处理',
-  [IssueStateZJC.toDeal6]: '待处理',
-  [IssueStateZJC.hasDone7]: '已处理',
-  [IssueStateZJC.hasDone8]: '已处理',
-};
-export const issueStateOptionsZJC = [
-  { label: issueStateNameMapZJC[IssueStateZJC.toDeal0], value: '[0, 1, 2, 3, 4, 5, 6]' },
-  { label: issueStateNameMapZJC[IssueStateZJC.hasDone7], value: '[7, 8]' },
-];
-export const getNameByStateZJC = (issueState: IssueStateZJC) => {
-  return issueStateNameMapZJC[issueState] || '-';
-};
-
-// 问题四大类
-export enum QUESTION_TYPE_MAIN {
-  fromHuman = 1, //人的不安全行为
-  fromThing = 2, //物的不安全状态
-  fromEnvir = 3, //环境的不安全因素
-  fromManage = 4, //管理措施的不规范
-}
-
-export const questionMainTypeNameMap = {
-  [QUESTION_TYPE_MAIN.fromHuman]: '人的不安全行为',
-  [QUESTION_TYPE_MAIN.fromThing]: '物的不安全状态',
-  [QUESTION_TYPE_MAIN.fromEnvir]: '环境的不安全因素',
-  [QUESTION_TYPE_MAIN.fromManage]: '管理措施的不规范',
-};

+ 0 - 342
src/views/datamanager/alertformdata/components/default-simple/Default.vue

@@ -1,342 +0,0 @@
-<template>
-  <div class="box">
-    <Prequalification />
-    <div class="search-form">
-      <QueryFormSimple
-        :ai-options="aiMainOptions"
-        :location-options="locationOptions"
-        @on-search="handleSearch"
-        @on-reset="handleReset"
-      />
-    </div>
-    <div class="table-list">
-      <div v-if="showActionBar" class="action-bar">
-        <span class="num-text">已选{{ chooseNum }}项</span>
-        <el-button :class="isActiveDelete ? 'btn-active' : 'btn-normal'" @click="handleDeleteAll">删除</el-button>
-        <span class="close-btn" @click="handleSelectNone"></span>
-      </div>
-      <AlertTableSimple
-        ref="alertTableRef"
-        class="table-bar"
-        :table-data="tableData"
-        :on-detail="handleDetail"
-        :on-delete="handleDelete"
-        @update:selection="handlePop"
-        @update:time-sort="handleChangeTimeSort"
-      />
-    </div>
-    <div class="pagination-box">
-      <Pagination
-        v-model:page="query.pageNumber"
-        v-model:size="query.pageSize"
-        :total="total"
-        @update:page="handlePageChange"
-        @update:size="handleSizeChange"
-      />
-    </div>
-    <DetailDialog
-      v-if="isDetailDialogShow"
-      @close="closeDetailDialog"
-      @update:previous="handleChangePrevious"
-      @update:next="handleChangeNext"
-      @update:choose="handleChangeChoose"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { storeToRefs } from 'pinia';
-  import { ref, onMounted, onBeforeMount } from 'vue';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import { TableQueryForm, getDefaultTableData, deleteDefaultTableData } from '@/api/datamanagement/alert-default';
-  import { useWorkLocation } from '../../hooks/useWorkLocation';
-  import { useIssueMainType } from '../../hooks/useIssueMainType';
-  import { useCurImgVideoUrlStore } from '../../store/useCurImgVideoUrl';
-  import Prequalification from '../common/Prequalification.vue';
-  import QueryFormSimple from '../common/QueryFormSimple.vue';
-  import AlertTableSimple, { DataSourceItem } from '../common/AlertTableSimple.vue';
-  import DetailDialog from '../common/DetailDialog.vue';
-  import Pagination from '@/components/Pagination/Pagination.vue';
-
-  const { locationOptions, getLocationOptions } = useWorkLocation();
-  const { aiMainOptions, getAIMainOptions } = useIssueMainType();
-
-  const curImgVideoUrl = useCurImgVideoUrlStore();
-  const {
-    detailRowChosen,
-    detailRow,
-    detailCurRowIndex,
-    detailPreviousRow,
-    detailNextRow,
-    hasPreviousRow,
-    hasNextRow,
-    detailDescription,
-    detailPictures,
-    detailVideos,
-  } = storeToRefs(curImgVideoUrl);
-
-  const alertTableRef = ref<typeof AlertTableSimple>();
-  const tableData = ref<DataSourceItem[]>([]);
-  const showActionBar = ref(false);
-  const chooseNum = ref(0);
-  const chooseRow = ref<DataSourceItem[]>([]); // 被选中的数据行
-  const chooseId = ref<number[]>([]);
-  const isActiveDelete = ref(false);
-  // 详情
-  const isDetailDialogShow = ref(false);
-  // 分页
-  const total = ref(0);
-
-  const query = ref<TableQueryForm>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-  });
-  // 查询
-  const handleSearch = (queryForm) => {
-    query.value = queryForm;
-    getTableData();
-  };
-  // 重置
-  const handleReset = (queryForm) => {
-    query.value = queryForm;
-    getTableData();
-  };
-
-  // 表格排序切换
-  const handleChangeTimeSort = (curTimeSort) => {
-    query.value.queryParam.order = curTimeSort;
-    getTableData();
-  };
-
-  // 多选
-  const handlePop = (selection) => {
-    chooseRow.value = selection;
-    chooseId.value = [];
-    selection.forEach((item) => {
-      if (chooseId.value.indexOf(item.id) === -1) chooseId.value.push(item.id);
-    });
-    chooseNum.value = selection.length;
-    showActionBar.value = chooseNum.value > 0 ? true : false;
-  };
-  // 取消多选
-  const handleSelectNone = () => {
-    chooseId.value = [];
-    chooseNum.value = 0;
-    alertTableRef.value?.clearAll();
-    showActionBar.value = false;
-  };
-  // 改变该行的选中状态
-  const handleChangeChoose = (status) => {
-    alertTableRef.value?.updateCurRowChosen(detailRow.value, !status);
-    updateDetailDialog(detailRow.value);
-  };
-
-  // 批量删除
-  const handleDeleteAll = () => {
-    if (showActionBar.value) isActiveDelete.value = !isActiveDelete.value;
-    ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true,
-    })
-      .then(() => {
-        deleteDefaultTableData(chooseId.value).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '删除成功',
-          });
-          getTableData();
-          handleSelectNone();
-          isActiveDelete.value = !isActiveDelete.value;
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消删除',
-        });
-        isActiveDelete.value = !isActiveDelete.value;
-      });
-  };
-
-  // 详情
-  const closeDetailDialog = () => {
-    isDetailDialogShow.value = false;
-  };
-  // 更新detailCurRowIndex、detailPreviousRow、detailNextRow、hasPreviousRow、hasNextRow
-  const updateDetailDialog = (curRow) => {
-    detailDescription.value = curRow.description;
-    detailPictures.value = curRow.pictures;
-    detailVideos.value = curRow.videos;
-    detailCurRowIndex.value = tableData.value.findIndex((item) => item.id === curRow.id);
-    detailPreviousRow.value = tableData.value[detailCurRowIndex.value - 1];
-    detailNextRow.value = tableData.value[detailCurRowIndex.value + 1];
-    if (detailPreviousRow.value) hasPreviousRow.value = true;
-    else hasPreviousRow.value = false;
-    if (detailNextRow.value) hasNextRow.value = true;
-    else hasNextRow.value = false;
-    if (chooseRow.value.findIndex((item) => item.id === curRow.id) !== -1) detailRowChosen.value = true;
-    else detailRowChosen.value = false;
-  };
-  const handleDetail = (row) => {
-    isDetailDialogShow.value = true;
-    detailRow.value = row;
-    updateDetailDialog(detailRow.value);
-  };
-  // 上一个
-  const handleChangePrevious = () => {
-    detailRow.value = detailPreviousRow.value;
-    updateDetailDialog(detailRow.value);
-  };
-  // 下一个
-  const handleChangeNext = () => {
-    detailRow.value = detailNextRow.value;
-    updateDetailDialog(detailRow.value);
-  };
-
-  // 删除
-  const handleDelete = (row) => {
-    ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true,
-    })
-      .then(() => {
-        deleteDefaultTableData([row.id]).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '删除成功',
-          });
-          getTableData();
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消删除',
-        });
-      });
-  };
-
-  // 换页,重新获取表格
-  const handlePageChange = (val) => {
-    query.value.pageNumber = val;
-    getTableData();
-  };
-  const handleSizeChange = (val) => {
-    query.value.pageSize = val;
-    getTableData();
-  };
-
-  const getTableData = () => {
-    getDefaultTableData(query.value).then((res) => {
-      console.log(res);
-      tableData.value = res.records;
-      total.value = res.totalRow;
-    });
-  };
-
-  onMounted(() => {
-    getTableData();
-  });
-
-  onBeforeMount(() => {
-    getAIMainOptions();
-    getLocationOptions();
-  });
-</script>
-
-<style scoped lang="scss">
-  .box {
-    display: flex;
-    flex-direction: column;
-  }
-
-  .table-list {
-    flex: 1;
-
-    .action-bar {
-      display: flex;
-      align-items: center;
-      position: absolute;
-      min-width: calc(100vw - 266px);
-      height: 50px;
-      border-radius: 4px 4px 0px 0px;
-      background-color: #ddefff;
-      z-index: 10;
-
-      .num-text {
-        margin: 0 34px 0 25px;
-        color: rgba(0, 0, 0, 0.85);
-        font-weight: 500;
-      }
-
-      .btn-normal {
-        color: #1890ff;
-        background: transparent;
-        border: 1px solid #1890ff;
-        border-radius: 2px;
-      }
-
-      .btn-active {
-        color: #ffffff;
-        background-color: #1890ff;
-      }
-
-      .close-btn {
-        margin-left: auto;
-        margin-right: 20px;
-      }
-
-      .close-btn:before {
-        content: '\2716';
-        color: #000;
-        cursor: pointer;
-      }
-    }
-
-    .table-bar {
-      position: relative;
-    }
-  }
-
-  .pagination-box {
-    height: 50px;
-    margin-top: 10px;
-  }
-</style>
-<style lang="scss">
-  .deleteMessage {
-    padding: 20px 24px;
-    box-shadow: 0px 12px 48px 16px rgba(0, 0, 0, 0.03), 0px 9px 28px 0px rgba(0, 0, 0, 0.05),
-      0px 6px 16px -8px rgba(0, 0, 0, 0.08);
-    border-radius: 8px;
-
-    .el-message-box__headerbtn {
-      margin-top: 12px;
-      margin-right: 12px;
-    }
-
-    .el-message-box__title {
-      justify-content: start;
-      color: rgba(0, 0, 0, 0.88);
-      font-size: 16px;
-      font-weight: 500;
-    }
-
-    .el-message-box__container {
-      justify-content: start;
-      margin-left: 23px;
-    }
-
-    .el-message-box__btns {
-      display: block;
-      float: right;
-    }
-  }
-</style>

+ 0 - 585
src/views/datamanager/alertformdata/components/default/Default.vue

@@ -1,585 +0,0 @@
-<template>
-  <div class="box">
-    <Prequalification />
-    <div class="search-form">
-      <QueryForm
-        :is-show-tab="false"
-        :ai-options="aiMainOptions"
-        :manual-options="manualMainOptions"
-        :location-options="locationOptions"
-        @on-search="handleSearch"
-        @on-reset="handleReset"
-        @on-export="handleExport"
-      />
-    </div>
-    <div class="table-list">
-      <div v-if="showActionBar" class="action-bar">
-        <span class="num-text">已选{{ chooseNum }}项</span>
-        <el-button :class="isActiveCancelHide ? 'btn-active' : 'btn-normal'" @click="handleCancelHideAll"
-          >全部生效</el-button
-        >
-        <el-button :class="isActiveHide ? 'btn-active' : 'btn-normal'" @click="handleHideAll">全部失效</el-button>
-        <el-button
-          v-if="hasDeletePermission()"
-          :class="isActiveDelete ? 'btn-active' : 'btn-normal'"
-          @click="handleDeleteAll"
-          >删除</el-button
-        >
-        <el-button
-          v-if="!cancelUrgentFlag"
-          :class="isActiveUrgent ? 'btn-active' : 'btn-normal'"
-          @click="handleUrgentAll"
-          >标记加急</el-button
-        >
-        <el-button
-          v-if="cancelUrgentFlag"
-          :class="isActiveCancelUrgent ? 'btn-active' : 'btn-normal'"
-          @click="handleCancelUrgentAll"
-          >取消加急</el-button
-        >
-        <el-button v-if="hasPermisson()" :class="isActiveCopy ? 'btn-active' : 'btn-normal'" @click="handleCopyToShow"
-          >复制到展示数据</el-button
-        >
-        <span class="close-btn" @click="handleSelectNone"></span>
-      </div>
-      <AlertTable
-        ref="alertTableRef"
-        class="table-bar"
-        :is-show-tab="false"
-        :table-data="tableData"
-        :on-detail="handleDetail"
-        :on-urgent="handleUrgent"
-        :on-show="handleShow"
-        :on-delete="handleDelete"
-        @update:selection="handlePop"
-        @update:time-sort="handleChangeTimeSort"
-      />
-    </div>
-    <div class="pagination-box">
-      <Pagination
-        v-model:page="query.pageNumber"
-        v-model:size="query.pageSize"
-        :total="total"
-        @update:page="handlePageChange"
-        @update:size="handleSizeChange"
-      />
-    </div>
-    <DetailDialog
-      v-if="isDetailDialogShow"
-      @close="closeDetailDialog"
-      @update:previous="handleChangePrevious"
-      @update:next="handleChangeNext"
-      @update:choose="handleChangeChoose"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import urlJoin from 'url-join';
-  import { storeToRefs } from 'pinia';
-  import { ref, onMounted, onBeforeMount } from 'vue';
-  import axios, { AxiosRequestConfig } from 'axios';
-  import { getHeaders } from '@/utils/http/axios';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import {
-    TableQueryForm,
-    getDefaultTableData,
-    deleteDefaultTableData,
-    copyToShowTableData,
-    updateDefaultHide,
-    updateDefaultHideAll,
-    updateDefaultPriority,
-    updateDefaultPriorityAll,
-  } from '@/api/datamanagement/alert-default';
-  import { PERM_DATA } from '@/types/permission/constants';
-  import { useGlobSetting } from '@/hooks/setting';
-  import { useWorkLocation } from '../../hooks/useWorkLocation';
-  import { useIssueMainType } from '../../hooks/useIssueMainType';
-  import { useUserStore } from '@/store/modules/user';
-  import { useCurImgVideoUrlStore } from '../../store/useCurImgVideoUrl';
-  import Prequalification from '../common/Prequalification.vue';
-  import QueryForm from '../common/QueryForm.vue';
-  import AlertTable, { DataSourceItem } from '../common/AlertTable.vue';
-  import DetailDialog from '../common/DetailDialog.vue';
-  import Pagination from '@/components/Pagination/Pagination.vue';
-
-  const { urlPrefix } = useGlobSetting();
-
-  const userStore = useUserStore();
-  const { locationOptions, getLocationOptions } = useWorkLocation();
-  const { aiMainOptions, manualMainOptions, getAIMainOptions, getManualMainOptions } = useIssueMainType();
-
-  const curImgVideoUrl = useCurImgVideoUrlStore();
-  const {
-    detailRowChosen,
-    detailRow,
-    detailCurRowIndex,
-    detailPreviousRow,
-    detailNextRow,
-    hasPreviousRow,
-    hasNextRow,
-    detailDescription,
-    detailPictures,
-    detailVideos,
-  } = storeToRefs(curImgVideoUrl);
-
-  const alertTableRef = ref<typeof AlertTable>();
-  const tableData = ref<DataSourceItem[]>([]);
-  const showActionBar = ref(false);
-  const chooseNum = ref(0);
-  const chooseRow = ref<DataSourceItem[]>([]); // 被选中的数据行
-  const chooseId = ref<number[]>([]);
-  const cancelUrgentFlag = ref(true); // true取消加急 / false全部加急
-  const isActiveHide = ref(false);
-  const isActiveCancelHide = ref(false);
-  const isActiveDelete = ref(false);
-  const isActiveUrgent = ref(false);
-  const isActiveCancelUrgent = ref(false);
-  const isActiveCopy = ref(false);
-  // 详情
-  const isDetailDialogShow = ref(false);
-  // 分页
-  const total = ref(0);
-
-  const query = ref<TableQueryForm>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-  });
-  // 查询
-  const handleSearch = (queryForm) => {
-    query.value = queryForm;
-    getTableData();
-  };
-  // 重置
-  const handleReset = (queryForm) => {
-    query.value = queryForm;
-    getTableData();
-  };
-  // 导出
-  const handleExport = async (queryForm, workShop) => {
-    const tempWorkShopIds = ref<number[]>([]);
-    if (workShop.length === 0) {
-      locationOptions.value.forEach((item) => {
-        tempWorkShopIds.value.push(item.value);
-      });
-    } else {
-      tempWorkShopIds.value = workShop;
-    }
-
-    try {
-      const now = new Date();
-      const year = now.getFullYear();
-      const month = String(now.getMonth() + 1).padStart(2, '0');
-      const day = String(now.getDate()).padStart(2, '0');
-      const currentDate = `${year}${month}${day}`;
-      const currentUrl = urlJoin(window.location.origin, window.location.pathname);
-
-      const requestBody = {
-        imageBaseUrl: currentUrl,
-        queryDisplayIssueReq: {
-          issueMainTypeList: queryForm.queryParam.issueMainTypeList,
-          issueTypeList: queryForm.queryParam.issueTypeList,
-          workspaceId: queryForm.queryParam.workspaceId,
-          workshopIds: tempWorkShopIds.value,
-          source: queryForm.queryParam.source,
-          issueState: queryForm.queryParam.issueState,
-          startTime: queryForm.queryParam.startTime,
-          endTime: queryForm.queryParam.endTime,
-          hide: queryForm.queryParam.hide,
-          order: queryForm.queryParam.order,
-        },
-      };
-
-      const config: AxiosRequestConfig = {
-        headers: getHeaders(),
-        responseType: 'blob',
-      };
-      const response = await axios.post(urlPrefix + '/admin/issueManage/exportIssueList', requestBody, config);
-      const blob = new Blob([response.data], {
-        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-      });
-      // 创建下载链接
-      let downloadLink: HTMLAnchorElement | null = document.createElement('a');
-      const url = window.URL.createObjectURL(blob);
-      downloadLink.href = url;
-      downloadLink.download = `安全违规问题数据统计表${currentDate}.xlsx`;
-      downloadLink.click();
-      // 移除下载链接
-      window.URL.revokeObjectURL(url);
-      downloadLink = null;
-    } catch (error) {
-      console.error('Error downloading file:', error);
-    }
-  };
-
-  // 表格排序切换
-  const handleChangeTimeSort = (curTimeSort) => {
-    query.value.queryParam.order = curTimeSort;
-    getTableData();
-  };
-
-  // 多选
-  const handlePop = (selection) => {
-    chooseRow.value = selection;
-    chooseId.value = [];
-    cancelUrgentFlag.value = true;
-    selection.forEach((item) => {
-      if (chooseId.value.indexOf(item.id) === -1) chooseId.value.push(item.id);
-      if (item.priority === 0) cancelUrgentFlag.value = false;
-    });
-    chooseNum.value = selection.length;
-    showActionBar.value = chooseNum.value > 0 ? true : false;
-  };
-  // 取消多选
-  const handleSelectNone = () => {
-    chooseId.value = [];
-    chooseNum.value = 0;
-    alertTableRef.value?.clearAll();
-    showActionBar.value = false;
-  };
-  // 改变该行的选中状态
-  const handleChangeChoose = (status) => {
-    alertTableRef.value?.updateCurRowChosen(detailRow.value, !status);
-    updateDetailDialog(detailRow.value);
-  };
-
-  // 全部隐藏
-  const handleHideAll = () => {
-    if (showActionBar.value) isActiveHide.value = !isActiveHide.value;
-    const updateList = {
-      ids: chooseId.value,
-      hide: true,
-    };
-    updateDefaultHideAll(updateList).then(() => {
-      handleSelectNone();
-      getTableData();
-      ElMessage({
-        message: '操作成功',
-        type: 'success',
-      });
-      setTimeout(function () {
-        isActiveHide.value = !isActiveHide.value;
-      }, 1000);
-    });
-  };
-
-  // 取消隐藏
-  const handleCancelHideAll = () => {
-    if (showActionBar.value) isActiveCancelHide.value = !isActiveCancelHide.value;
-    const updateList = {
-      ids: chooseId.value,
-      hide: false,
-    };
-    updateDefaultHideAll(updateList).then(() => {
-      handleSelectNone();
-      getTableData();
-      ElMessage({
-        message: '操作成功',
-        type: 'success',
-      });
-      setTimeout(function () {
-        isActiveCancelHide.value = !isActiveCancelHide.value;
-      }, 1000);
-    });
-  };
-
-  // 批量删除
-  const handleDeleteAll = () => {
-    if (showActionBar.value) isActiveDelete.value = !isActiveDelete.value;
-    ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true,
-    })
-      .then(() => {
-        deleteDefaultTableData(chooseId.value).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '删除成功',
-          });
-          getTableData();
-          handleSelectNone();
-          isActiveDelete.value = !isActiveDelete.value;
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消删除',
-        });
-        isActiveDelete.value = !isActiveDelete.value;
-      });
-  };
-
-  // 标记加急,设置priority = 1
-  const handleUrgentAll = () => {
-    if (showActionBar.value) isActiveUrgent.value = !isActiveUrgent.value;
-    const updateList = {
-      ids: chooseId.value,
-      priority: 1,
-    };
-    updateDefaultPriorityAll(updateList).then(() => {
-      handleSelectNone();
-      getTableData();
-      ElMessage({
-        message: '已加急',
-        type: 'success',
-      });
-      setTimeout(function () {
-        isActiveUrgent.value = !isActiveUrgent.value;
-      }, 1000);
-    });
-  };
-
-  // 取消加急
-  const handleCancelUrgentAll = () => {
-    if (showActionBar.value) isActiveCancelUrgent.value = !isActiveCancelUrgent.value;
-    const updateList = {
-      ids: chooseId.value,
-      priority: 0,
-    };
-    updateDefaultPriorityAll(updateList).then(() => {
-      handleSelectNone();
-      getTableData();
-      ElMessage({
-        message: '已取消加急',
-        type: 'success',
-      });
-      setTimeout(function () {
-        isActiveCancelUrgent.value = !isActiveCancelUrgent.value;
-      }, 1000);
-    });
-  };
-
-  // 复制到展示数据
-  const handleCopyToShow = () => {
-    if (showActionBar.value) isActiveCopy.value = !isActiveCopy.value;
-    copyToShowTableData(chooseId.value).then(() => {
-      ElMessage({
-        message: '复制成功',
-        type: 'success',
-      });
-      setTimeout(function () {
-        isActiveCopy.value = !isActiveCopy.value;
-      }, 1000);
-      handleSelectNone();
-    });
-  };
-
-  // 详情
-  const closeDetailDialog = () => {
-    isDetailDialogShow.value = false;
-  };
-  // 更新detailCurRowIndex、detailPreviousRow、detailNextRow、hasPreviousRow、hasNextRow
-  const updateDetailDialog = (curRow) => {
-    detailDescription.value = curRow.description;
-    detailPictures.value = curRow.pictures;
-    detailVideos.value = curRow.videos;
-    detailCurRowIndex.value = tableData.value.findIndex((item) => item.id === curRow.id);
-    detailPreviousRow.value = tableData.value[detailCurRowIndex.value - 1];
-    detailNextRow.value = tableData.value[detailCurRowIndex.value + 1];
-    if (detailPreviousRow.value) hasPreviousRow.value = true;
-    else hasPreviousRow.value = false;
-    if (detailNextRow.value) hasNextRow.value = true;
-    else hasNextRow.value = false;
-    if (chooseRow.value.findIndex((item) => item.id === curRow.id) !== -1) detailRowChosen.value = true;
-    else detailRowChosen.value = false;
-  };
-  const handleDetail = (row) => {
-    isDetailDialogShow.value = true;
-    detailRow.value = row;
-    updateDetailDialog(detailRow.value);
-  };
-  // 上一个
-  const handleChangePrevious = () => {
-    detailRow.value = detailPreviousRow.value;
-    updateDetailDialog(detailRow.value);
-  };
-  // 下一个
-  const handleChangeNext = () => {
-    detailRow.value = detailNextRow.value;
-    updateDetailDialog(detailRow.value);
-  };
-
-  // 单个加急priority=1/取消加急priority=0
-  const handleUrgent = (row) => {
-    const tempPriority = row.priority === 0 ? 1 : 0;
-    const updateList = {
-      id: row.id,
-      priority: tempPriority,
-    };
-    updateDefaultPriority(updateList).then(() => {
-      getTableData();
-    });
-  };
-
-  // 单个显示hide=false/隐藏hide=true
-  const handleShow = (row) => {
-    const tempHide = row.isHide === false ? true : false;
-    const updateList = {
-      id: row.id,
-      hide: tempHide,
-    };
-    updateDefaultHide(updateList).then(() => {
-      getTableData();
-    });
-  };
-
-  // 删除
-  const handleDelete = (row) => {
-    ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true,
-    })
-      .then(() => {
-        deleteDefaultTableData([row.id]).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '删除成功',
-          });
-          getTableData();
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消删除',
-        });
-      });
-  };
-
-  // 换页,重新获取表格
-  const handlePageChange = (val) => {
-    query.value.pageNumber = val;
-    getTableData();
-  };
-  const handleSizeChange = (val) => {
-    query.value.pageSize = val;
-    getTableData();
-  };
-
-  const getTableData = () => {
-    getDefaultTableData(query.value).then((res) => {
-      console.log(res);
-      tableData.value = res.records;
-      total.value = res.totalRow;
-    });
-  };
-
-  const hasDeletePermission = () => {
-    return userStore.checkPermission(PERM_DATA.VIOLATION_DELETE);
-  };
-
-  const hasPermisson = () => {
-    return (
-      userStore.checkPermission(PERM_DATA.VIOLATION_FAKE_ADD) ||
-      userStore.checkPermission(PERM_DATA.VIOLATION_FAKE_DELETE)
-    );
-  };
-
-  onMounted(() => {
-    getTableData();
-  });
-
-  onBeforeMount(() => {
-    getAIMainOptions();
-    getManualMainOptions();
-    getLocationOptions();
-  });
-</script>
-
-<style scoped lang="less">
-  .box {
-    display: flex;
-    flex-direction: column;
-  }
-
-  .table-list {
-    flex: 1;
-
-    .action-bar {
-      display: flex;
-      align-items: center;
-      position: absolute;
-      min-width: calc(100vw - 266px);
-      height: 50px;
-      border-radius: 4px 4px 0px 0px;
-      background-color: #ddefff;
-      z-index: 10;
-
-      .num-text {
-        margin: 0 34px 0 25px;
-        color: rgba(0, 0, 0, 0.85);
-        font-weight: 500;
-      }
-
-      .btn-normal {
-        color: #1890ff;
-        background: transparent;
-        border: 1px solid #1890ff;
-        border-radius: 2px;
-      }
-
-      .btn-active {
-        color: #ffffff;
-        background-color: #1890ff;
-      }
-
-      .close-btn {
-        margin-left: auto;
-        margin-right: 20px;
-      }
-
-      .close-btn:before {
-        content: '\2716';
-        color: #000;
-        cursor: pointer;
-      }
-    }
-
-    .table-bar {
-      position: relative;
-    }
-  }
-
-  .pagination-box {
-    height: 50px;
-    margin-top: 10px;
-  }
-</style>
-<style lang="less">
-  .deleteMessage {
-    padding: 20px 24px;
-    box-shadow: 0px 12px 48px 16px rgba(0, 0, 0, 0.03), 0px 9px 28px 0px rgba(0, 0, 0, 0.05),
-      0px 6px 16px -8px rgba(0, 0, 0, 0.08);
-    border-radius: 8px;
-
-    .el-message-box__headerbtn {
-      margin-top: 12px;
-      margin-right: 12px;
-    }
-
-    .el-message-box__title {
-      justify-content: start;
-      color: rgba(0, 0, 0, 0.88);
-      font-size: 16px;
-      font-weight: 500;
-    }
-
-    .el-message-box__container {
-      justify-content: start;
-      margin-left: 23px;
-    }
-
-    .el-message-box__btns {
-      display: block;
-      float: right;
-    }
-  }
-</style>

+ 0 - 427
src/views/datamanager/alertformdata/components/show/Show.vue

@@ -1,427 +0,0 @@
-<template>
-  <div class="box">
-    <div class="search-form">
-      <QueryForm
-        :is-show-tab="true"
-        :ai-options="aiMainOptions"
-        :manual-options="manualMainOptions"
-        :location-options="locationOptions"
-        @on-search="handleSearch"
-        @on-reset="handleReset"
-      />
-      <el-button v-if="hasAddPermission()" type="primary" :icon="Plus" @click="handleAdd">添加</el-button>
-    </div>
-    <div class="table-list">
-      <div v-if="showActionBar" class="action-bar">
-        <span class="num-text">已选{{ chooseNum }}项</span>
-        <el-button :class="isActiveCancelHide ? 'btn-active' : 'btn-normal'" @click="handleCancelHideAll"
-          >全部生效</el-button
-        >
-        <el-button :class="isActiveHide ? 'btn-active' : 'btn-normal'" @click="handleHideAll">全部失效</el-button>
-        <el-button
-          v-if="hasDeletePermission()"
-          :class="isActiveDelete ? 'btn-active' : 'btn-normal'"
-          @click="handleDeleteAll"
-          >删除</el-button
-        >
-        <span class="close-btn" @click="handleSelectNone"></span>
-      </div>
-      <AlertTable
-        ref="alertTableRef"
-        class="table-bar"
-        :is-show-tab="true"
-        :table-data="tableData"
-        :on-detail="handleDetail"
-        :on-edit="handleEdit"
-        :on-show="handleShow"
-        :on-delete="handleDelete"
-        @update:selection="handlePop"
-        @update:time-sort="handleChangeTimeSort"
-      />
-    </div>
-    <div class="pagination-box">
-      <Pagination
-        v-model:page="query.pageNumber"
-        v-model:size="query.pageSize"
-        :total="total"
-        @update:page="handlePageChange"
-        @update:size="handleSizeChange"
-      />
-    </div>
-    <DetailDialog
-      v-if="isDetailDialogShow"
-      @close="closeDetailDialog"
-      @update:previous="handleChangePrevious"
-      @update:next="handleChangeNext"
-      @update:choose="handleChangeChoose"
-    />
-    <AddDrawer v-if="isAddDrawer" @close="handleAddDrawerClose" />
-    <EditDrawer v-if="isEditDrawer" :initial-data="rowData" @close="handleEditDrawerClose" />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { storeToRefs } from 'pinia';
-  import { ref, onMounted, onBeforeMount } from 'vue';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import { Plus } from '@element-plus/icons-vue';
-  import { PERM_DATA } from '@/types/permission/constants';
-  import { useWorkLocation } from '../../hooks/useWorkLocation';
-  import { useIssueMainType } from '../../hooks/useIssueMainType';
-  import { useUserStore } from '@/store/modules/user';
-  import { useCurImgVideoUrlStore } from '../../store/useCurImgVideoUrl';
-  import { TableQueryForm } from '@/api/datamanagement/alert-default';
-  import { getShowTableData, updateShowTableData, deleteShowTableData } from '@/api/datamanagement/alert-show';
-  import QueryForm from '../common/QueryForm.vue';
-  import AlertTable, { DataSourceItem } from '../common/AlertTable.vue';
-  import DetailDialog from '../common/DetailDialog.vue';
-  import Pagination from '@/components/Pagination/Pagination.vue';
-  import AddDrawer from '../common/AddDrawer.vue';
-  import EditDrawer from '../common/EditDrawer.vue';
-
-  const userStore = useUserStore();
-
-  const { locationOptions, getLocationOptions } = useWorkLocation();
-  const { aiMainOptions, manualMainOptions, getAIMainOptions, getManualMainOptions } = useIssueMainType();
-
-  const curImgVideoUrl = useCurImgVideoUrlStore();
-  const {
-    detailRowChosen,
-    detailRow,
-    detailCurRowIndex,
-    detailPreviousRow,
-    detailNextRow,
-    hasPreviousRow,
-    hasNextRow,
-    detailDescription,
-    detailPictures,
-    detailVideos,
-  } = storeToRefs(curImgVideoUrl);
-
-  const alertTableRef = ref<typeof AlertTable>();
-  const tableData = ref<DataSourceItem[]>([]);
-  const showActionBar = ref(false);
-  const chooseNum = ref(0);
-  const chooseRow = ref<DataSourceItem[]>([]); // 被选中的数据行
-  const chooseId = ref<number[]>([]);
-  const isActiveHide = ref(false);
-  const isActiveCancelHide = ref(false);
-  const isActiveDelete = ref(false);
-  // 详情
-  const isDetailDialogShow = ref(false);
-  // 添加
-  const isAddDrawer = ref(false);
-  const isEditDrawer = ref(false);
-  const rowData = ref(); // 编辑时填充row的tableData
-  // 分页
-  const total = ref(0);
-
-  const query = ref<TableQueryForm>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-  });
-  // 查询
-  const handleSearch = (queryForm) => {
-    query.value = queryForm;
-    getTableData();
-  };
-  // 重置
-  const handleReset = (queryForm) => {
-    query.value = queryForm;
-    getTableData();
-  };
-
-  // 表格排序切换
-  const handleChangeTimeSort = (curTimeSort) => {
-    query.value.queryParam.order = curTimeSort;
-    getTableData();
-  };
-
-  // 多选
-  const handlePop = (selection) => {
-    chooseRow.value = selection;
-    chooseId.value = [];
-    selection.forEach((item) => {
-      if (chooseId.value.indexOf(item.id) === -1) chooseId.value.push(item.id);
-    });
-    chooseNum.value = selection.length;
-    showActionBar.value = chooseNum.value > 0 ? true : false;
-  };
-  // 取消多选
-  const handleSelectNone = () => {
-    chooseId.value = [];
-    chooseNum.value = 0;
-    alertTableRef.value?.clearAll();
-    showActionBar.value = false;
-  };
-  // 改变该行的选中状态
-  const handleChangeChoose = (status) => {
-    alertTableRef.value?.updateCurRowChosen(detailRow.value, !status);
-    updateDetailDialog(detailRow.value);
-  };
-
-  // 全部隐藏
-  const handleHideAll = () => {
-    if (showActionBar.value) isActiveHide.value = !isActiveHide.value;
-    const updateList = {
-      ids: chooseId.value,
-      hide: true,
-    };
-    updateShowTableData(updateList).then(() => {
-      handleSelectNone();
-      getTableData();
-      ElMessage({
-        message: '操作成功',
-        type: 'success',
-      });
-      setTimeout(function () {
-        isActiveHide.value = !isActiveHide.value;
-      }, 1000);
-    });
-  };
-
-  // 取消隐藏
-  const handleCancelHideAll = () => {
-    if (showActionBar.value) isActiveCancelHide.value = !isActiveCancelHide.value;
-    const updateList = {
-      ids: chooseId.value,
-      hide: false,
-    };
-    updateShowTableData(updateList).then(() => {
-      handleSelectNone();
-      getTableData();
-      ElMessage({
-        message: '操作成功',
-        type: 'success',
-      });
-      setTimeout(function () {
-        isActiveCancelHide.value = !isActiveCancelHide.value;
-      }, 1000);
-    });
-  };
-
-  // 批量删除
-  const handleDeleteAll = () => {
-    if (showActionBar.value) isActiveDelete.value = !isActiveDelete.value;
-    ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true,
-    })
-      .then(() => {
-        deleteShowTableData(chooseId.value).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '删除成功',
-          });
-          getTableData();
-          handleSelectNone();
-          isActiveDelete.value = !isActiveDelete.value;
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消删除',
-        });
-        isActiveDelete.value = !isActiveDelete.value;
-      });
-  };
-
-  // 详情
-  const closeDetailDialog = () => {
-    isDetailDialogShow.value = false;
-  };
-  // 更新detailCurRowIndex、detailPreviousRow、detailNextRow、hasPreviousRow、hasNextRow
-  const updateDetailDialog = (curRow) => {
-    detailDescription.value = curRow.description;
-    detailPictures.value = curRow.pictures;
-    detailVideos.value = curRow.videos;
-    detailCurRowIndex.value = tableData.value.findIndex((item) => item.id === curRow.id);
-    detailPreviousRow.value = tableData.value[detailCurRowIndex.value - 1];
-    detailNextRow.value = tableData.value[detailCurRowIndex.value + 1];
-    if (detailPreviousRow.value) hasPreviousRow.value = true;
-    else hasPreviousRow.value = false;
-    if (detailNextRow.value) hasNextRow.value = true;
-    else hasNextRow.value = false;
-    if (chooseRow.value.findIndex((item) => item.id === curRow.id) !== -1) detailRowChosen.value = true;
-    else detailRowChosen.value = false;
-  };
-  const handleDetail = (row) => {
-    isDetailDialogShow.value = true;
-    detailRow.value = row;
-    updateDetailDialog(detailRow.value);
-  };
-  // 上一个
-  const handleChangePrevious = () => {
-    detailRow.value = detailPreviousRow.value;
-    updateDetailDialog(detailRow.value);
-  };
-  // 下一个
-  const handleChangeNext = () => {
-    detailRow.value = detailNextRow.value;
-    updateDetailDialog(detailRow.value);
-  };
-
-  // 添加
-  const handleAdd = () => {
-    isAddDrawer.value = true;
-  };
-  // 编辑
-  const handleEdit = (row) => {
-    isEditDrawer.value = true;
-    rowData.value = { ...row };
-  };
-
-  const handleAddDrawerClose = () => {
-    isAddDrawer.value = false;
-    getTableData();
-  };
-
-  const handleEditDrawerClose = () => {
-    isEditDrawer.value = false;
-    getTableData();
-  };
-
-  // 单个显示hide=false/隐藏hide=true
-  const handleShow = (row) => {
-    const tempHide = row.isHide === false ? true : false;
-    const updateList = {
-      ids: [row.id],
-      hide: tempHide,
-    };
-    updateShowTableData(updateList).then(() => {
-      getTableData();
-    });
-  };
-
-  // 删除
-  const handleDelete = (row) => {
-    ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-      customClass: 'deleteMessage',
-      center: true,
-    })
-      .then(() => {
-        deleteShowTableData([row.id]).then(() => {
-          ElMessage({
-            type: 'success',
-            message: '删除成功',
-          });
-          getTableData();
-        });
-      })
-      .catch(() => {
-        ElMessage({
-          type: 'info',
-          message: '取消删除',
-        });
-      });
-  };
-
-  // 换页,重新获取表格
-  const handlePageChange = (val) => {
-    query.value.pageNumber = val;
-    getTableData();
-  };
-  const handleSizeChange = (val) => {
-    query.value.pageSize = val;
-    getTableData();
-  };
-
-  const getTableData = () => {
-    getShowTableData(query.value).then((res) => {
-      console.log(res);
-      tableData.value = res.records;
-      total.value = res.totalRow;
-    });
-  };
-
-  const hasAddPermission = () => {
-    return userStore.checkPermission(PERM_DATA.VIOLATION_FAKE_ADD);
-  };
-
-  const hasDeletePermission = () => {
-    return userStore.checkPermission(PERM_DATA.VIOLATION_FAKE_DELETE);
-  };
-
-  onMounted(() => {
-    getTableData();
-  });
-
-  onBeforeMount(() => {
-    getLocationOptions();
-    getAIMainOptions();
-    getManualMainOptions();
-  });
-</script>
-
-<style scoped lang="scss">
-  .box {
-    display: flex;
-    flex-direction: column;
-  }
-
-  .search-form {
-    margin-bottom: 20px;
-  }
-
-  .table-list {
-    height: calc(100vh - 350px);
-    overflow-y: scroll;
-
-    .action-bar {
-      display: flex;
-      align-items: center;
-      position: absolute;
-      min-width: calc(100vw - 266px);
-      height: 50px;
-      border-radius: 4px 4px 0px 0px;
-      background-color: #ddefff;
-      z-index: 10;
-
-      .num-text {
-        margin: 0 34px 0 25px;
-        color: rgba(0, 0, 0, 0.85);
-        font-weight: 500;
-      }
-
-      .btn-normal {
-        color: #1890ff;
-        background: transparent;
-        border: 1px solid #1890ff;
-        border-radius: 2px;
-      }
-
-      .btn-active {
-        color: #ffffff;
-        background-color: #1890ff;
-      }
-
-      .close-btn {
-        margin-left: auto;
-        margin-right: 20px;
-      }
-
-      .close-btn:before {
-        content: '\2716';
-        color: #000;
-        cursor: pointer;
-      }
-    }
-
-    .table-bar {
-      position: relative;
-    }
-  }
-
-  .pagination-box {
-    height: 50px;
-    margin-top: 10px;
-  }
-</style>

+ 0 - 67
src/views/datamanager/alertformdata/hooks/useIssueMainType.ts

@@ -1,67 +0,0 @@
-import { ref } from 'vue';
-import { getIssueTypeListWithMainType } from '@/api/datamanagement/alert';
-import { Source } from '@/views/datamanager/alertformdata/components/common/constant.question';
-
-type IssueMainTypeOption = {
-  value: number;
-  label: string;
-  children: {
-    value: number;
-    label: string;
-  }[];
-};
-
-export function useIssueMainType() {
-  const aiMainOptions = ref<IssueMainTypeOption[]>([]); // AI检测
-  const manualMainOptions = ref<IssueMainTypeOption[]>([]); // 人工上报
-
-  const processBackendData = (data): IssueMainTypeOption[] => {
-    return data.map((item) => ({
-      value: item.issueMainTypeId,
-      label: item.issueMainTypeName,
-      children: item.issueTypeList.map((child) => ({
-        value: child.issueTypeId,
-        label: child.issueTypeName,
-      })),
-    }));
-  };
-
-  const getAIMainOptions = async () => {
-    await getIssueTypeListWithMainType(Source.ai).then((res) => {
-      aiMainOptions.value = processBackendData(res);
-    });
-  };
-
-  const getManualMainOptions = async () => {
-    await getIssueTypeListWithMainType(Source.manual).then((res) => {
-      manualMainOptions.value = processBackendData(res);
-    });
-  };
-
-  // 根据 问题来源id + 问题类型id 决定表格类型栏展示文字
-  const getNameByType = (source, mainType, subType) => {
-    const sourceTypeMap = {
-      [Source.ai]: aiMainOptions,
-      [Source.manual]: manualMainOptions,
-    };
-    const targetArray = sourceTypeMap[source];
-    if (targetArray) {
-      const foundObject = targetArray.value.find((obj) => obj.value === mainType);
-      if (foundObject) {
-        const subObj = foundObject.children.find((sub) => sub.value === subType);
-        if (subObj) return subObj.label;
-        return '-';
-      }
-      return '-';
-    }
-    return '-';
-  };
-
-  return {
-    aiMainOptions,
-    manualMainOptions,
-    getAIMainOptions,
-    getManualMainOptions,
-    getNameByType,
-  };
-}

+ 0 - 45
src/views/datamanager/alertformdata/hooks/useIssueType.ts

@@ -1,45 +0,0 @@
-/**
- * @description: 用于展示数据-添加-问题类型选择-可选项
- */
-import { ref } from 'vue';
-import { getIssueSubTypeList } from '@/api/datamanagement/alert';
-import { Source } from '../components/common/constant.question';
-
-type IssueOptionType = {
-  id: number;
-  name: string;
-};
-
-export function useIssueType() {
-  const aiOptions = ref<IssueOptionType[]>([]); // AI检测
-  const manualOptions = ref<IssueOptionType[]>([]); // 人工上报
-
-  const getAIOptions = () => {
-    getIssueSubTypeList(Source.ai).then((res) => {
-      res.forEach((item) => {
-        aiOptions.value.push({
-          id: item.issueTypeId,
-          name: item.issueTypeName,
-        });
-      });
-    });
-  };
-
-  const getManualOptions = () => {
-    getIssueSubTypeList(Source.manual).then((res) => {
-      res.forEach((item) => {
-        manualOptions.value.push({
-          id: item.issueTypeId,
-          name: item.issueTypeName,
-        });
-      });
-    });
-  };
-
-  return {
-    aiOptions,
-    manualOptions,
-    getAIOptions,
-    getManualOptions,
-  };
-}

+ 0 - 67
src/views/datamanager/alertformdata/hooks/useWorkLocation.ts

@@ -1,67 +0,0 @@
-import { ref } from 'vue';
-import { getWorkLocationList } from '@/api/datamanagement/alert';
-
-type Location = {
-  value: number;
-  label: string;
-  children: {
-    value: number;
-    label: string;
-  }[];
-};
-
-export function useWorkLocation() {
-  const locationOptions = ref<Location[]>([]);
-
-  const result = ref<Location[]>([]);
-  const getWorkLocationTree = (cameraTree) => {
-    cameraTree.forEach((item) => {
-      if (item.nodeType === 'workshop') {
-        if (item.children && item.children.length > 0) {
-          const newChildren =
-            item.children.map((x) => {
-              return { value: x.id, label: x.name };
-            }) || [];
-          const newNode = {
-            value: item.id,
-            label: item.name,
-            children: newChildren,
-          };
-          result.value.push(newNode);
-          return result.value;
-        }
-        return result.value;
-      } else if (item.nodeType === 'company') {
-        getWorkLocationTree(item.children);
-      }
-    });
-    return result.value;
-  };
-
-  const getLocationOptions = () => {
-    getWorkLocationList().then((res) => {
-      locationOptions.value = getWorkLocationTree(res);
-    });
-  };
-
-  const getNameByWorkid = (workshopId, workspaceId, array) => {
-    const shop = array.find((item) => item.value === workshopId);
-    if (!shop) {
-      return '-';
-    }
-
-    if (!shop.children || !Array.isArray(shop.children)) return '-';
-    const space = shop.children.find((item) => item.value === workspaceId);
-    let str = shop.label;
-    if (space?.label) {
-      str += ' - ' + space?.label;
-    }
-    return str;
-  };
-
-  return {
-    locationOptions,
-    getLocationOptions,
-    getNameByWorkid,
-  };
-}

+ 0 - 28
src/views/datamanager/alertformdata/store/useCurImgVideoUrl.ts

@@ -1,28 +0,0 @@
-import { ref } from 'vue';
-import { defineStore } from 'pinia';
-
-export const useCurImgVideoUrlStore = defineStore('curImgVideoUrl', () => {
-  const detailRowChosen = ref(false); // 当前行是否被选中
-  const detailRow = ref(); // 当前行
-  const detailCurRowIndex = ref(0); // 当前行index
-  const detailPreviousRow = ref(); // 上一行
-  const detailNextRow = ref(); // 下一行
-  const hasPreviousRow = ref(false); // 是否有上一行
-  const hasNextRow = ref(false); // 是否有下一行
-  const detailDescription = ref('');
-  const detailPictures = ref<string[]>([]);
-  const detailVideos = ref<string[]>([]);
-
-  return {
-    detailRowChosen,
-    detailRow,
-    detailCurRowIndex,
-    detailPreviousRow,
-    detailNextRow,
-    hasPreviousRow,
-    hasNextRow,
-    detailDescription,
-    detailPictures,
-    detailVideos,
-  };
-});

+ 0 - 74
src/views/datamanager/platformdata/PlatformData.vue

@@ -1,74 +0,0 @@
-<template>
-  <div class="platform-content">
-    <div class="flex platform-head-tabs">
-      <div
-        class="flex justify-center items-center tab-item"
-        :class="{ 'tab-item-active': activeName === 'count' }"
-        @click="activeName = 'count'"
-      >
-        访问次数统计
-      </div>
-      <div
-        class="flex justify-center items-center tab-item"
-        :class="{ 'tab-item-active': activeName === 'score' }"
-        @click="activeName = 'score'"
-      >
-        积分统计
-      </div>
-    </div>
-    <Query v-if="activeName === 'count'" />
-    <Score v-else />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  import Query from './components/query/Query.vue';
-  import Score from './components/score/Score.vue';
-
-  const activeName = ref('count');
-</script>
-
-<style scoped lang="scss">
-  .platform-content {
-    height: calc(100vh - 64px - 18px);
-    background-color: rgba(255, 255, 255, 1);
-    padding: 21px;
-  }
-  .platform-head {
-    height: 56px;
-
-    &-name {
-      margin-left: 24px;
-      font-size: 16px;
-      font-weight: 500;
-      color: #252525;
-    }
-
-    &-tabs {
-      margin: 18px 0;
-
-      .tab-item {
-        width: 188px;
-        height: 38px;
-        background: #fafafa;
-        border: 1px solid #d9d9d9;
-        cursor: pointer;
-
-        &-active {
-          color: rgba(22, 119, 255, 1);
-          background: #e2eefe;
-          border: 1px solid #1890ff;
-        }
-      }
-
-      :first-child {
-        border-radius: 8px 0px 0px 8px;
-      }
-
-      :last-child {
-        border-radius: 0px 8px 8px 0px;
-      }
-    }
-  }
-</style>

+ 0 - 120
src/views/datamanager/platformdata/charts/BarChart.vue

@@ -1,120 +0,0 @@
-<template>
-  <div id="bar-chart" ref="barChart" class="chart" :style="{ height: props.height }"></div>
-</template>
-
-<script setup lang="ts">
-  import * as echarts from 'echarts/core';
-  import {
-    TooltipComponent,
-    TooltipComponentOption,
-    GridComponent,
-    GridComponentOption,
-    DataZoomComponent,
-    DataZoomComponentOption,
-  } from 'echarts/components';
-  import { BarChart, BarSeriesOption } from 'echarts/charts';
-  import { CanvasRenderer } from 'echarts/renderers';
-  import { onMounted, watch } from 'vue';
-
-  echarts.use([TooltipComponent, GridComponent, BarChart, CanvasRenderer, DataZoomComponent]);
-  type EChartsOption = echarts.ComposeOption<
-    TooltipComponentOption | GridComponentOption | BarSeriesOption | DataZoomComponentOption
-  >;
-
-  const props = withDefaults(
-    defineProps<{
-      chartData: number[];
-      chartLable: string[];
-      height?: string;
-    }>(),
-    {
-      height: '372px',
-    },
-  );
-
-  onMounted(() => {
-    const bar: echarts.ECharts = echarts.init(document.getElementById('bar-chart')!);
-
-    initBarChart(bar);
-
-    watch(
-      () => props.chartData,
-      () => {
-        drawBarChart(bar);
-      },
-    );
-  });
-
-  const initBarChart = (bar: echarts.ECharts) => {
-    const barOption: EChartsOption = {
-      tooltip: {
-        trigger: 'axis',
-        axisPointer: {
-          type: 'shadow',
-        },
-      },
-      grid: {
-        left: '3%',
-        right: '4%',
-        bottom: '3%',
-        containLabel: true,
-      },
-      dataZoom: [
-        {
-          startValue: 0,
-          endValue: 13,
-          type: 'inside',
-        },
-      ],
-      xAxis: [
-        {
-          type: 'category',
-          data: props.chartLable,
-          axisTick: {
-            alignWithLabel: true,
-          },
-          axisLabel: {
-            rotate: 45,
-          },
-        },
-      ],
-      yAxis: [
-        {
-          name: '访问次数',
-          type: 'value',
-        },
-      ],
-      series: [
-        {
-          // name: props.chartCategory,
-          type: 'bar',
-          barWidth: '60%',
-          data: props.chartData,
-        },
-      ],
-    };
-    bar.setOption(barOption);
-  };
-
-  const drawBarChart = (bar: echarts.ECharts) => {
-    const barOption: EChartsOption = {
-      xAxis: [
-        {
-          data: props.chartLable,
-        },
-      ],
-      series: [
-        {
-          data: props.chartData,
-        },
-      ],
-    };
-    bar.setOption(barOption);
-  };
-</script>
-
-<style scoped lang="scss">
-  #bar-chart {
-    width: 968px;
-  }
-</style>

+ 0 - 138
src/views/datamanager/platformdata/charts/LineChart.vue

@@ -1,138 +0,0 @@
-<template>
-  <div id="line-chart" ref="lineChart" class="chart" :style="{ height: props.height }"></div>
-</template>
-
-<script setup lang="ts">
-  import * as echarts from 'echarts/core';
-  import {
-    GridComponent,
-    GridComponentOption,
-    DataZoomComponent,
-    DataZoomComponentOption,
-    TooltipComponent,
-  } from 'echarts/components';
-  import { LineChart, LineSeriesOption } from 'echarts/charts';
-  import { UniversalTransition } from 'echarts/features';
-  import { CanvasRenderer } from 'echarts/renderers';
-  import { onMounted, watch } from 'vue';
-
-  echarts.use([
-    GridComponent,
-    LineChart,
-    CanvasRenderer,
-    UniversalTransition,
-    DataZoomComponent,
-    TooltipComponent,
-  ]);
-  type EChartsOption = echarts.ComposeOption<
-    GridComponentOption | LineSeriesOption | DataZoomComponentOption
-  >;
-  const props = withDefaults(
-    defineProps<{
-      chartData: any[];
-      chartLable: string[];
-      height?: string;
-    }>(),
-    {
-      height: '372px',
-    },
-  );
-
-  let lineOption: EChartsOption = {} as EChartsOption;
-
-  onMounted(() => {
-    const line: echarts.ECharts = echarts.init(document.getElementById('line-chart')!);
-
-    initLineChart(line);
-  });
-
-  watch(
-    () => props.chartData,
-    () => {
-      const line: echarts.ECharts = echarts.init(document.getElementById('line-chart')!);
-      drawLineChart(line);
-    },
-    {
-      deep: true,
-    },
-  );
-
-  const initLineChart = (line: echarts.ECharts) => {
-    lineOption = {
-      tooltip: {
-        trigger: 'axis',
-        axisPointer: {
-          type: 'shadow',
-        },
-      },
-      grid: {
-        left: '3%',
-        right: '4%',
-        bottom: '3%',
-        containLabel: true,
-      },
-      dataZoom: [
-        {
-          startValue: 0,
-          endValue: 13,
-          type: 'inside',
-        },
-      ],
-      xAxis: [
-        {
-          type: 'category',
-          data: props.chartLable,
-          axisLabel: {
-            rotate: 45,
-          },
-        },
-      ],
-      yAxis: [
-        {
-          name: '访问次数',
-          type: 'value',
-        },
-      ],
-      series: props.chartData.map((item) => {
-        return {
-          name: item.workshopName,
-          type: 'line',
-          showSymbol: false,
-          data: item.counts,
-        };
-      }),
-    };
-    console.log(lineOption);
-
-    line.setOption(lineOption);
-  };
-
-  const drawLineChart = (line: echarts.ECharts) => {
-    line.clear();
-    lineOption.xAxis = [
-      {
-        type: 'category',
-        data: props.chartLable,
-        axisLabel: {
-          rotate: 45,
-        },
-      },
-    ];
-    lineOption.series = props.chartData.map((item) => {
-      return {
-        name: item.workshopName,
-        type: 'line',
-        showSymbol: false,
-        data: item.counts,
-      };
-    });
-    line.setOption(lineOption);
-  };
-</script>
-
-<style scoped lang="scss">
-  #line-chart {
-    width: 968px;
-    height: 372px;
-  }
-</style>

+ 0 - 130
src/views/datamanager/platformdata/charts/ScoreLineChart.vue

@@ -1,130 +0,0 @@
-<template>
-  <div id="line-chart" ref="lineChart" class="chart" :style="{ height: props.height }"></div>
-</template>
-
-<script setup lang="ts">
-  import * as echarts from 'echarts/core';
-  import {
-    GridComponent,
-    GridComponentOption,
-    DataZoomComponent,
-    DataZoomComponentOption,
-    TooltipComponent,
-  } from 'echarts/components';
-  import { LineChart, LineSeriesOption } from 'echarts/charts';
-  import { UniversalTransition } from 'echarts/features';
-  import { CanvasRenderer } from 'echarts/renderers';
-  import { onMounted, watch } from 'vue';
-
-  echarts.use([
-    GridComponent,
-    LineChart,
-    CanvasRenderer,
-    UniversalTransition,
-    DataZoomComponent,
-    TooltipComponent,
-  ]);
-  type EChartsOption = echarts.ComposeOption<
-    GridComponentOption | LineSeriesOption | DataZoomComponentOption
-  >;
-  const props = withDefaults(
-    defineProps<{
-      chartData: any[];
-      chartLable: any[];
-      height?: string;
-    }>(),
-    {
-      height: '372px',
-    },
-  );
-
-  let lineOption: EChartsOption = {} as EChartsOption;
-
-  onMounted(() => {
-    const line: echarts.ECharts = echarts.init(document.getElementById('line-chart')!);
-
-    initLineChart(line);
-  });
-
-  watch(
-    () => props.chartData,
-    () => {
-      const line: echarts.ECharts = echarts.init(document.getElementById('line-chart')!);
-      drawLineChart(line);
-    },
-    {
-      deep: true,
-    },
-  );
-
-  const initLineChart = (line: echarts.ECharts) => {
-    lineOption = {
-      tooltip: {
-        trigger: 'axis',
-        axisPointer: {
-          type: 'shadow',
-        },
-      },
-      grid: {
-        left: '3%',
-        right: '4%',
-        bottom: '3%',
-        containLabel: true,
-      },
-      dataZoom: [
-        {
-          startValue: 0,
-          endValue: 13,
-          type: 'inside',
-        },
-      ],
-      xAxis: [
-        {
-          type: 'category',
-          data: props.chartLable,
-        },
-      ],
-      yAxis: [
-        {
-          name: '人数',
-          type: 'value',
-        },
-      ],
-      series: [
-        {
-          type: 'line',
-          showSymbol: false,
-          data: props.chartData,
-        },
-      ],
-    };
-    console.log(lineOption);
-
-    line.setOption(lineOption);
-  };
-
-  const drawLineChart = (line: echarts.ECharts) => {
-    line.clear();
-    lineOption.xAxis = [
-      {
-        type: 'category',
-        data: props.chartLable,
-      },
-    ];
-    lineOption.series = [
-      {
-        type: 'line',
-        showSymbol: false,
-        data: props.chartData,
-      },
-    ];
-    line.setOption(lineOption);
-  };
-</script>
-
-<style scoped lang="scss">
-  #line-chart {
-    width: 968px;
-    height: 372px;
-  }
-</style>

+ 0 - 175
src/views/datamanager/platformdata/components/common/DialogNavBar.vue

@@ -1,175 +0,0 @@
-<template>
-  <div class="dialog-nav-bar">
-    <div v-if="workshopList !== undefined" class="workshop-select">
-      <el-select
-        v-model="selectedWorkshop"
-        multiple
-        clearable
-        collapse-tags
-        placeholder="请添加车间"
-        :max-collapse-tags="1"
-        style="width: 240px"
-      >
-        <el-checkbox v-model="checkAll" :indeterminate="false" @change="handleCheckAll">
-          全选
-        </el-checkbox>
-        <el-option v-for="shop in workshopList" :key="shop.id" :label="shop.name" :value="shop.id">
-          <!-- <el-checkbox :label="shop.label"> </el-checkbox> -->
-        </el-option>
-      </el-select>
-    </div>
-    <el-date-picker
-      class="date-picker"
-      v-model="dateRange"
-      type="daterange"
-      range-separator="至"
-      start-placeholder="开始日期"
-      end-placeholder="结束日期"
-      :shortcuts="shortcuts"
-      :default-time="[new Date().setHours(0, 0, 0, 0), new Date().setHours(23, 59, 59, 999)]"
-      style="max-width: 299px"
-    ></el-date-picker>
-    <el-button @click="onSearch" type="primary" style="width: 65px; height: 32px; margin-left: 16px"
-      >搜 索
-    </el-button>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { onMounted, ref, watch } from 'vue';
-  import { ChartQuery } from '@/api/datamanagement/dataplatform';
-  import { formatDate } from '@/utils/platformUtils';
-
-  const checkAll = ref();
-  const selectedWorkshop = ref<number[]>();
-  const dateRange = ref<Date[]>();
-
-  const props = withDefaults(
-    defineProps<{
-      chartType?: string;
-      workshopList?: any[] | undefined;
-    }>(),
-    {
-      chartType: 'bar',
-    },
-  );
-
-  // 参数改变事件
-  const emits = defineEmits<{
-    (e: 'chartParamsChanged', parmas: ChartQuery);
-  }>();
-
-  const serchParams = ref<ChartQuery>({});
-
-  const onSearch = () => {
-    if (
-      !dateRange.value ||
-      dateRange.value[0].toString() === 'Invalid Date' ||
-      dateRange.value[1].toString() === 'Invalid Date'
-    ) {
-      delete serchParams.value.startTime;
-      delete serchParams.value.endTime;
-    } else {
-      serchParams.value.startTime = formatDate(dateRange.value[0]);
-      serchParams.value.endTime = formatDate(dateRange.value[1]);
-    }
-    serchParams.value.workshopList = selectedWorkshop.value;
-    // if (props.workshopList !== undefined) {
-    //   if (!selectedWorkshop.value || !selectedWorkshop.value.length) {
-    //     ElMessage.error('请至少选择一个车间');
-    //     return;
-    //   }
-    //   serchParams.value.workshopList = selectedWorkshop.value;
-    // }
-    emits('chartParamsChanged', serchParams.value);
-  };
-
-  // select全选事件
-  const handleCheckAll = (val: boolean) => {
-    if (val) {
-      selectedWorkshop.value = props.workshopList!.map((item) => item.id);
-    } else {
-      selectedWorkshop.value = [];
-    }
-  };
-  watch(
-    () => selectedWorkshop.value,
-    (val) => {
-      if (val !== undefined) {
-        if (val.length === props.workshopList!.length) {
-          checkAll.value = true;
-        } else {
-          checkAll.value = false;
-        }
-      }
-    },
-    { immediate: true },
-  );
-
-  // 初始化全选
-  onMounted(() => {
-    if (props.workshopList !== undefined) {
-      selectedWorkshop.value = props.workshopList!.map((item) => item.id);
-    }
-    onSearch();
-  });
-
-  const shortcuts = [
-    {
-      text: props.chartType === 'bar' ? '今天' : '本周',
-      value: () => {
-        return props.chartType === 'bar'
-          ? [new Date().setHours(0, 0, 0, 0), new Date()]
-          : [
-              new Date(new Date().getTime() - 3600 * 1000 * 24 * new Date().getDay()).setHours(
-                0,
-                0,
-                0,
-                0,
-              ),
-              new Date(),
-            ];
-      },
-    },
-    {
-      text: '本月',
-      value: () => {
-        const start = new Date(
-          new Date().getTime() - 3600 * 1000 * 24 * (new Date().getDate() - 1),
-        ).setHours(0, 0, 0, 0);
-        return [start, new Date()];
-      },
-    },
-    {
-      text: '累计',
-      value: () => {
-        return [null, null];
-      },
-    },
-  ];
-</script>
-
-<style lang="scss" scoped>
-  .workshop-select {
-    width: 250px;
-  }
-  .dialog-nav-bar {
-    padding-right: 25px;
-    width: 100%;
-    display: flex;
-    justify-content: flex-start;
-    align-items: center;
-  }
-  .el-select-dropdown.is-multiple .el-select-dropdown__item.is-selected:after {
-    left: 5px;
-  }
-  .el-select-dropdown__item.is-selected {
-    font-weight: inherit;
-  }
-  :deep(.el-checkbox__label) {
-    padding-left: 2px;
-  }
-  :deep(.el-checkbox__input) {
-    margin-left: 4px;
-  }
-</style>

+ 0 - 298
src/views/datamanager/platformdata/components/common/QueryTable.vue

@@ -1,298 +0,0 @@
-<template>
-  <div class="form">
-    <div class="table-query-form">
-      <el-input
-        v-model="tableQueryTypeContent"
-        style="max-width: 251px; margin-right: 50px"
-        :placeholder="'请输入' + tableQueryType"
-      >
-        <template #prepend>
-          <el-select
-            v-model="tableQueryType"
-            style="width: 74px"
-            @change="handleTableQueryTypeChange"
-          >
-            <el-option value="姓名" />
-            <el-option value="工号" />
-          </el-select>
-        </template>
-      </el-input>
-      <div class="dept-select">
-        <span>请选择组织:</span>
-        <el-tree-select
-          v-model="tableQueryDept"
-          :data="props.departmentList"
-          :render-after-expand="false"
-          :default-expand-all="true"
-          @change="handleDeptChange"
-          style="width: 200px"
-          check-strictly
-          placeholder="请选择组织"
-          class="protocal-select"
-        />
-      </div>
-      <div style="min-width: 150px; float: right">
-        <el-button type="primary" @click="submitTableQuery" style="width: 65px; height: 32px"
-          >搜 索</el-button
-        >
-        <el-button @click="resetTable" style="width: 65px; height: 32px">重 置</el-button>
-      </div>
-    </div>
-    <el-table
-      ref="queryTableRef"
-      max-height="calc(100vh - 350px)"
-      style="width: 100%; margin-top: 18px"
-      stripe
-      :data="tableData.list"
-      highlight-current-row
-      @sort-change="handleSortChange"
-    >
-      <el-table-column label="姓名" prop="nickname" align="center"></el-table-column>
-      <el-table-column label="工号" prop="username" align="center"></el-table-column>
-      <el-table-column label="部门" prop="deptName" align="center"></el-table-column>
-      <el-table-column
-        v-if="tableLabel === '访问次数'"
-        :label="'当日' + props.tableLabel"
-        prop="statisticDay"
-        sortable="custom"
-        align="right"
-      ></el-table-column>
-      <el-table-column
-        v-if="tableLabel === '访问次数'"
-        :label="'本月' + tableLabel"
-        prop="statisticMonth"
-        sortable="custom"
-        align="right"
-      ></el-table-column>
-      <el-table-column
-        :label="'累计' + tableLabel"
-        prop="statisticAll"
-        sortable="custom"
-        :align="tableLabel === '访问次数' ? 'right' : 'center'"
-      ></el-table-column>
-      <el-table-column v-if="tableLabel === '访问次数'" label="访问次数统计图" align="center">
-        <template #default="scope">
-          <img
-            style="display: inline-block; margin-right: 20px; cursor: pointer"
-            src="@/assets/icons/chart-bar.png"
-            alt=""
-            @click="showBargraph(scope.row)"
-          />
-          <img
-            style="display: inline-block; cursor: pointer"
-            src="@/assets/icons/chart-line.png"
-            alt=""
-            @click="showLinechart(scope.row)"
-          />
-        </template>
-      </el-table-column>
-    </el-table>
-    <el-pagination
-      v-model:current-page="tableQueryParams.pageNumber"
-      v-model:currentPageSize="tableQueryParams.pageSize"
-      :total="tableData.total"
-      :page-sizes="[10, 20, 50, 100, 200]"
-      layout="->, total,sizes,prev,pager,next,jumper"
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentPageChange"
-    />
-  </div>
-  <el-dialog
-    v-model="bargraphVisible"
-    :title="chartTitle"
-    :close-on-click-modal="true"
-    :destroy-on-close="true"
-    width="1000px"
-    center
-  >
-    <DialogNavBar @chart-params-changed="onDialogParamsChanged" />
-    <BarChart :chart-data="chartData.val" :chart-lable="chartData.label" />
-  </el-dialog>
-  <el-dialog
-    v-model="linechartVisible"
-    :title="chartTitle"
-    :close-on-click-modal="true"
-    :destroy-on-close="true"
-    width="1000px"
-    center
-  >
-    <DialogNavBar
-      chart-type="line"
-      :workshop-list="workshopList"
-      @chart-params-changed="onDialogParamsChanged"
-    />
-    <LineChart :chart-data="chartData.val" :chart-lable="chartData.label" />
-  </el-dialog>
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  import { defineProps } from 'vue';
-  import DialogNavBar from '../common/DialogNavBar.vue';
-  import BarChart from '../../charts/BarChart.vue';
-  import LineChart from '../../charts/LineChart.vue';
-  import {
-    type ChartQuery,
-    type UserAccessRecordList,
-    type UserAccessRecordQueryParams,
-    getUserVisitTimes,
-    getUserDailyVisitTimes,
-  } from '@/api/datamanagement/dataplatform';
-  import { formatWorkshopChart, formatTimeChart } from '@/utils/platformUtils';
-  import { PaginationRequest } from '@/types/common/type';
-
-  const queryTableRef = ref();
-
-  // 获取下拉菜单数据和表格数据
-  const props = defineProps<{
-    departmentList: any[];
-    workshopList: any[];
-    tableData: UserAccessRecordList;
-    tableLabel: string;
-  }>();
-
-  // 表格查询参数和修改事件
-  const tableQueryParams = ref<PaginationRequest & { queryParam: UserAccessRecordQueryParams }>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-    // nickname: "",
-    // username: "",
-    // sortKey: "",
-    // sortType: "",
-  });
-  const emits = defineEmits<{
-    (
-      e: 'tableParamsChanged',
-      parmas: PaginationRequest & { queryParam: UserAccessRecordQueryParams },
-    );
-  }>();
-
-  // 页码导航栏修改事件
-  const handleSizeChange = (v: number) => {
-    tableQueryParams.value.pageSize = v;
-    emits('tableParamsChanged', tableQueryParams.value);
-  };
-  const handleCurrentPageChange = (v: number) => {
-    tableQueryParams.value.pageNumber = v;
-    emits('tableParamsChanged', tableQueryParams.value);
-  };
-
-  // 表格排序事件
-  const handleSortChange = (data: any) => {
-    if (data.order !== null) {
-      tableQueryParams.value.queryParam.sortKey = data.prop;
-      tableQueryParams.value.queryParam.sortType = data.order.includes('a') ? 'asc' : 'desc';
-    } else {
-      delete tableQueryParams.value.queryParam.sortKey;
-      delete tableQueryParams.value.queryParam.sortType;
-    }
-    tableQueryParams.value.pageNumber = 1;
-    emits('tableParamsChanged', tableQueryParams.value);
-  };
-
-  // 复用输入框类型和变化事件
-  const tableQueryType = ref<string>('姓名');
-  const handleTableQueryTypeChange = (v: string) => {
-    if (v === '姓名') {
-      delete tableQueryParams.value.queryParam.staffNo;
-    } else {
-      delete tableQueryParams.value.queryParam.nickname;
-    }
-    tableQueryTypeContent.value = '';
-  };
-
-  // 部门筛选框变化
-  const handleDeptChange = (v: string) => {
-    tableQueryParams.value.queryParam.deptId = v;
-  };
-
-  // 复用输入框绑定内容、提交事件、重置事件
-  const tableQueryTypeContent = ref<string>();
-  function submitTableQuery() {
-    if (tableQueryType.value === '姓名') {
-      tableQueryParams.value.queryParam.nickname = tableQueryTypeContent.value;
-    } else {
-      tableQueryParams.value.queryParam.staffNo = tableQueryTypeContent.value;
-    }
-    emits('tableParamsChanged', tableQueryParams.value);
-  }
-  function resetTable() {
-    queryTableRef.value.clearSort();
-    tableQueryTypeContent.value = '';
-    tableQueryDept.value = undefined;
-    tableQueryParams.value = {
-      pageNumber: 1,
-      pageSize: 10,
-      queryParam: {},
-    };
-    emits('tableParamsChanged', tableQueryParams.value);
-  }
-  // 组织列表筛选数据
-  const tableQueryDept = ref<string>();
-
-  // dialog显示和画图
-  const chartTitle = ref('');
-  const ChartQueryUserId = ref('');
-  const bargraphVisible = ref(false);
-  const showBargraph = (rowData) => {
-    bargraphVisible.value = true;
-    chartTitle.value = rowData.nickname + '访问车间统计柱状图';
-    ChartQueryUserId.value = rowData.userId;
-  };
-  const linechartVisible = ref(false);
-  const showLinechart = (rowData) => {
-    linechartVisible.value = true;
-    chartTitle.value = rowData.nickname + '访问车间统计折线图';
-    ChartQueryUserId.value = rowData.userId;
-  };
-
-  // 请求画图数据
-  const getChartData = async (cp: ChartQuery) => {
-    if (chartTitle.value.includes('柱状')) {
-      const data = await getUserVisitTimes(cp);
-      chartData.value = formatWorkshopChart(data);
-    } else {
-      const data = await getUserDailyVisitTimes(cp);
-      chartData.value = formatTimeChart(data);
-    }
-  };
-  const chartData = ref<{
-    label: string[];
-    val: any[];
-  }>({
-    label: [],
-    val: [],
-  });
-  const onDialogParamsChanged = async (v: ChartQuery) => {
-    v.userId = ChartQueryUserId.value;
-    await getChartData(v);
-  };
-</script>
-
-<style scoped lang="scss">
-  .testbox {
-    width: 930px;
-    height: 480px;
-  }
-  .form {
-    /* width: 1100px; */
-    margin-top: 18px;
-  }
-
-  .el-pagination {
-    margin-top: 30px;
-  }
-
-  .table-query-form {
-    padding-right: 25px;
-    width: 100%;
-    display: flex;
-    justify-content: flex-start;
-    align-items: center;
-    .dept-select {
-      min-width: 300px;
-      margin-right: 50px;
-    }
-  }
-</style>

+ 0 - 171
src/views/datamanager/platformdata/components/common/ScoreTable.vue

@@ -1,171 +0,0 @@
-<template>
-  <div class="form">
-    <div class="table-query-form">
-      <el-input
-        v-model="tableQueryTypeContent"
-        style="max-width: 251px; margin-right: 50px"
-        :placeholder="'请输入' + tableQueryType"
-      >
-        <template #prepend>
-          <el-select v-model="tableQueryType" style="width: 74px" @change="handleTableQueryTypeChange">
-            <el-option value="姓名" />
-            <el-option value="工号" />
-          </el-select>
-        </template>
-      </el-input>
-      <div class="dept-select">
-        <span>请选择组织:</span>
-        <el-tree-select
-          v-model="tableQueryDept"
-          :data="props.departmentList"
-          :render-after-expand="false"
-          :default-expand-all="true"
-          @change="handleDeptChange"
-          style="width: 200px"
-          check-strictly
-          placeholder="请选择组织"
-          class="protocal-select"
-        />
-      </div>
-      <div style="float: right">
-        <el-button type="primary" @click="submitTableQuery" style="width: 65px; height: 32px">搜 索</el-button>
-        <el-button @click="resetTable" style="width: 65px; height: 32px">重 置</el-button>
-      </div>
-    </div>
-    <el-table
-      ref="scoreTableRef"
-      max-height="calc(100vh - 350px)"
-      style="width: 100%; margin-top: 18px"
-      stripe
-      :data="tableData.records"
-      highlight-current-row
-      @sort-change="handleSortChange"
-    >
-      <el-table-column label="姓名" prop="realname" align="center"></el-table-column>
-      <el-table-column label="工号" prop="staffNo" align="center"></el-table-column>
-      <el-table-column label="部门" prop="deptName" align="center"></el-table-column>
-      <el-table-column label="累计积分" prop="score" sortable="custom" align="center"></el-table-column>
-    </el-table>
-    <el-pagination
-      v-model:current-page="tableQueryParams.pageNumber"
-      v-model:currentPageSize="tableQueryParams.pageSize"
-      :total="tableData.totalRow"
-      :page-sizes="[10, 20, 50, 100, 200]"
-      layout="->, total,sizes,prev,pager,next,jumper"
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentPageChange"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  import { defineProps } from 'vue';
-  import { type ScoreTableRecord, type ScoreTableQueryBody } from '@/api/datamanagement/dataplatform';
-
-  const scoreTableRef = ref();
-
-  // 获取下拉菜单数据和表格数据
-  const props = defineProps<{
-    departmentList: any[];
-    tableData: ScoreTableRecord;
-  }>();
-
-  // 组织列表筛选数据
-  const tableQueryDept = ref<number>();
-
-  // 表格查询参数和修改事件
-  const tableQueryParams = ref<ScoreTableQueryBody>({
-    pageNumber: 1,
-    pageSize: 10,
-    deptId: '',
-    // realname: "",
-    // staffNo: "",
-    // order: "",
-  });
-  const emits = defineEmits<{
-    (e: 'tableParamsChanged', parmas: ScoreTableQueryBody);
-  }>();
-
-  // 页码导航栏修改事件
-  const handleSizeChange = (v: number) => {
-    tableQueryParams.value.pageSize = v;
-    emits('tableParamsChanged', tableQueryParams.value);
-  };
-  const handleCurrentPageChange = (v: number) => {
-    tableQueryParams.value.pageNumber = v;
-    emits('tableParamsChanged', tableQueryParams.value);
-  };
-  // 表格排序事件
-  const handleSortChange = (data: any) => {
-    if (data.order !== null) {
-      tableQueryParams.value.order = data.order.includes('a') ? 1 : 2;
-    } else {
-      delete tableQueryParams.value.order;
-    }
-    tableQueryParams.value.pageNumber = 1;
-    emits('tableParamsChanged', tableQueryParams.value);
-  };
-
-  // 复用输入框类型和变化事件
-  const tableQueryType = ref<string>('姓名');
-  const handleTableQueryTypeChange = (v: string) => {
-    if (v === '姓名') {
-      delete tableQueryParams.value.staffNo;
-    } else {
-      delete tableQueryParams.value.realname;
-    }
-    tableQueryTypeContent.value = '';
-  };
-  // 部门筛选框变化
-  const handleDeptChange = (v: string) => {
-    tableQueryParams.value.deptId = v;
-  };
-  // 复用输入框绑定内容、提交事件、重置事件
-  const tableQueryTypeContent = ref<string>();
-  function submitTableQuery() {
-    if (tableQueryType.value === '姓名') {
-      tableQueryParams.value.realname = tableQueryTypeContent.value;
-    } else {
-      tableQueryParams.value.staffNo = tableQueryTypeContent.value;
-    }
-    emits('tableParamsChanged', tableQueryParams.value);
-  }
-  function resetTable() {
-    scoreTableRef.value.clearSort();
-    tableQueryTypeContent.value = '';
-    tableQueryDept.value = undefined;
-    tableQueryParams.value = {
-      pageNumber: 1,
-      pageSize: 10,
-    };
-    emits('tableParamsChanged', tableQueryParams.value);
-  }
-</script>
-
-<style scoped lang="scss">
-  .testbox {
-    width: 930px;
-    height: 480px;
-  }
-  .form {
-    /* width: 1100px; */
-    margin-top: 18px;
-  }
-
-  .el-pagination {
-    margin-top: 30px;
-  }
-
-  .table-query-form {
-    padding-right: 25px;
-    width: 100%;
-    display: flex;
-    justify-content: flex-start;
-    align-items: center;
-    .dept-select {
-      min-width: 300px;
-      margin-right: 50px;
-    }
-  }
-</style>

+ 0 - 142
src/views/datamanager/platformdata/components/query/Query.vue

@@ -1,142 +0,0 @@
-<template>
-  <div>
-    <el-button type="primary" @click="showWorkshopData()">车间统计数据</el-button>
-    <el-button type="primary" @click="showCameraData()">相机统计数据</el-button>
-    <QueryTable
-      v-if="tableData !== undefined"
-      :department-list="departmentList"
-      :workshop-list="flattenedWorkshops"
-      :table-data="tableData"
-      table-label="访问次数"
-      @table-params-changed="
-        (v) => {
-          tableQueryParams = _.cloneDeep(v);
-        }
-      "
-    />
-    <el-dialog
-      v-model="dialogVisible"
-      width="1000px"
-      :title="dialogTitle"
-      :close-on-click-modal="true"
-      :destroy-on-close="true"
-      center
-    >
-      <DialogNavBar
-        :workshop-list="dialogTitle === '相机统计数据' ? flattenedWorkshops : undefined"
-        @chart-params-changed="
-          async (v) => {
-            await getChartData(v);
-          }
-        "
-      />
-      <BarChart :chart-data="chartData.val" :chart-lable="chartData.label" />
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import QueryTable from '../common/QueryTable.vue';
-  import DialogNavBar from '../common/DialogNavBar.vue';
-  import BarChart from '../../charts/BarChart.vue';
-  import { ref, onMounted, watch } from 'vue';
-  import { useSceneInfos } from '@/hooks/useSceneInfos';
-  import {
-    type UserAccessRecordQueryParams,
-    type UserAccessRecordList,
-    type ChartQuery,
-    getUserAccessRecords,
-    getCameraVisitedTimes,
-    getWorkshopVisitedTimes,
-  } from '@/api/datamanagement/dataplatform';
-  import { formatWorkshopChart, formatCameraChart } from '@/utils/platformUtils';
-  import { getAllDepartments } from '@/api/auth/dept';
-  import _ from 'lodash-es';
-  import { PaginationRequest } from '@/types/common/type';
-
-  const departmentList = ref<any[]>([]);
-
-  // 下拉菜单车间列表数据
-  const sceneInfos = useSceneInfos();
-  const { flattenedWorkshops, getScenesTree, calculateTreeData } = sceneInfos;
-  onMounted(() => {
-    getScenesTree({ level: 1, valueKey: 'code', labelKey: 'name', disabled: true });
-    getAllDepartments().then((res) => {
-      departmentList.value = calculateTreeData(res, { level: 3, valueKey: 'id', labelKey: 'deptName' }, 1);
-    });
-  });
-
-  // dialog显示
-  const dialogVisible = ref(false);
-  const dialogTitle = ref('');
-  const showWorkshopData = () => {
-    dialogVisible.value = true;
-    dialogTitle.value = '车间统计数据';
-  };
-  const showCameraData = () => {
-    dialogVisible.value = true;
-    dialogTitle.value = '相机统计数据';
-  };
-
-  // 请求画图数据
-  const getChartData = async (cp: ChartQuery) => {
-    if (dialogTitle.value.includes('车间')) {
-      const data = await getWorkshopVisitedTimes(cp);
-      chartData.value = formatWorkshopChart(data);
-    } else {
-      const data = await getCameraVisitedTimes(cp);
-      chartData.value = formatCameraChart(data);
-    }
-  };
-  const chartData = ref<{
-    label: string[];
-    val: number[];
-  }>({
-    label: [],
-    val: [],
-  });
-
-  // 请求表格数据
-  const tableQueryParams = ref<PaginationRequest & { queryParam: UserAccessRecordQueryParams }>({
-    pageNumber: 1,
-    pageSize: 10,
-    queryParam: {},
-    // nickname: '',
-    // username: '',
-    // sortKey: 'statisticAll',
-    // sortType: 'asc',
-  });
-  const tableData = ref<UserAccessRecordList>();
-  watch(
-    () => tableQueryParams.value,
-    async () => {
-      const data = await getUserAccessRecords(tableQueryParams.value);
-      tableData.value = {
-        list: data.records,
-        pageNumber: data.pageNumber,
-        pageSize: data.pageSize,
-        total: data.totalRow,
-      };
-    },
-    {
-      immediate: true,
-      deep: true,
-    },
-  );
-</script>
-
-<style scoped lang="scss">
-  :deep(.el-dialog__header) {
-    text-align: left;
-    border-bottom: 1px solid rgba(232, 232, 232, 1);
-    padding-bottom: 16px;
-    margin-bottom: 16px;
-  }
-
-  :deep(.el-dialog__title) {
-    font-weight: 600;
-    font-size: 16px;
-    color: rgba(0, 0, 0, 0.88);
-    line-height: 24px;
-  }
-</style>

+ 0 - 162
src/views/datamanager/platformdata/components/score/Score.vue

@@ -1,162 +0,0 @@
-<template>
-  <div>
-    <el-button type="primary" @click="onOpenScoreChart">数据总表</el-button>
-    <ScoreTable
-      v-if="tableData !== undefined"
-      :department-list="departmentList"
-      :table-data="tableData"
-      @table-params-changed="
-        (v) => {
-          tableQueryParams = _.cloneDeep(v);
-        }
-      "
-    />
-    <el-dialog
-      v-model="dialogVisible"
-      width="1000px"
-      title="各分数段所对应人数折线图"
-      :close-on-click-modal="true"
-      :destroy-on-close="true"
-      @open="handleDialogOpen"
-      center
-    >
-      <div class="dialog-header">
-        <div class="dept-select">
-          <el-tree-select
-            v-model="dept"
-            :data="departmentList"
-            :render-after-expand="false"
-            :default-expand-all="true"
-            style="width: 240px"
-            multiple
-            clearable
-            collapse-tags
-            show-checkbox
-            check-strictly
-            placeholder="请选择组织"
-            class="protocal-select"
-          />
-        </div>
-        <el-button
-          @click="onSearch"
-          type="primary"
-          style="width: 95px; height: 32px; margin-left: 16px"
-          >生成折线图
-        </el-button>
-      </div>
-      <ScoreLineChart :chart-data="chartData.val" :chart-lable="chartData.label" />
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import {
-    type ScoreTableRecord,
-    type ScoreTableQueryBody,
-    getScoreTable,
-    getScoreChartData,
-  } from '@/api/datamanagement/dataplatform';
-  import { ref, onMounted, watch } from 'vue';
-  import { useSceneInfos } from '@/hooks/useSceneInfos';
-  import ScoreTable from '../common/ScoreTable.vue';
-  import ScoreLineChart from '../../charts/ScoreLineChart.vue';
-  import { getAllDepartments } from '@/api/auth/dept';
-  import _ from 'lodash-es';
-
-  const departmentList = ref<any[]>([]);
-
-  // 下拉菜单车间列表数据
-  const sceneInfos = useSceneInfos();
-  const { getScenesTree, calculateTreeData } = sceneInfos;
-  onMounted(() => {
-    getScenesTree({ level: 1, valueKey: 'code', labelKey: 'name', disabled: true });
-    getAllDepartments().then((res) => {
-      departmentList.value = calculateTreeData(
-        res,
-        { level: 3, valueKey: 'id', labelKey: 'deptName' },
-        1,
-      );
-    });
-  });
-
-  // 请求表格数据
-  const tableQueryParams = ref<ScoreTableQueryBody>({
-    pageNumber: 1,
-    pageSize: 10,
-  });
-  const tableData = ref<ScoreTableRecord>();
-
-  watch(
-    () => tableQueryParams.value,
-    async () => {
-      getScoreTable(tableQueryParams.value).then((res) => {
-        tableData.value = res;
-      });
-    },
-    {
-      immediate: true,
-      deep: true,
-    },
-  );
-
-  // dialog显示
-  const dialogVisible = ref(false);
-  const onOpenScoreChart = () => {
-    dialogVisible.value = true;
-  };
-
-  const handleDialogOpen = () => {
-    dept.value = getAllIds(departmentList.value as { value: number; children: [] }[]);
-    onSearch();
-  };
-
-  function getAllIds(list: { value: number; children: [] }[] = [], ids: number[] = []) {
-    for (let item of list) {
-      !ids.includes(item.value) && ids.push(item.value);
-      if (item.children && item.children.length) getAllIds(item.children, ids);
-    }
-    return ids;
-  }
-
-  // 折线图筛选
-  const dept = ref<number[]>([]);
-  const chartData = ref<{
-    label: number[];
-    val: any[];
-  }>({
-    label: [],
-    val: [],
-  });
-  const onSearch = () => {
-    // const deptIdList = dept.value.join(',');
-    getScoreChartData(dept.value).then((res) => {
-      chartData.value = {
-        label: res.map((item) => (item.scoreSection[0] + item.scoreSection[1]) / 2),
-        val: res.map((item) => item.num),
-      };
-    });
-  };
-</script>
-
-<style scoped lang="scss">
-  :deep(.el-dialog__header) {
-    text-align: left;
-    border-bottom: 1px solid rgba(232, 232, 232, 1);
-    padding-bottom: 16px;
-    margin-bottom: 16px;
-  }
-
-  :deep(.el-dialog__title) {
-    font-weight: 600;
-    font-size: 16px;
-    color: rgba(0, 0, 0, 0.88);
-    line-height: 24px;
-  }
-  .dialog-header {
-    padding-right: 25px;
-    width: 100%;
-    display: flex;
-    justify-content: flex-start;
-    align-items: center;
-  }
-</style>

+ 0 - 57
src/views/datamanager/platformdata/config.ts

@@ -1,57 +0,0 @@
-import { DepartMentModel, getDeptList } from "@/api/datamanagement/dataplatform";
-import { onMounted, ref } from "vue";
-
-
-export const BoardSelectList = [
-    {
-        label: '姓名',
-        value: 0,
-    },
-    {
-        label: '工号',
-        value: 1,
-    },
-
-]
-
-
-// export enum BoardDeptEnum {
-//     all = 100,
-//     '5g' = 0,
-//     'c02' = 1,
-//     'c12' = 2,
-//     'top' = 12,
-// }
-
-// export const BoardDeptList = [
-//     {
-//         label: '全部',
-//         value: BoardDeptEnum.all,
-//     },
-//     {
-//         label: '总部公司',
-//         value: BoardDeptEnum.top,
-//     },
-// ]
-
-
-export function getDepartmentList() {
-    
-  
-    const departmentList = ref<DepartMentModel[]>([]);
-    const getDepartmentList = () => {
-      getDeptList().then((res) => {
-        departmentList.value = res;
-      });
-    };
-  
-  
-    onMounted(() => {
-      getDepartmentList();
-    })
-  
-  
-    return {  departmentList, getDepartmentList }
-  }
-  
-  export default getDepartmentList;

+ 0 - 216
src/views/datamanager/playback/Playback.vue

@@ -1,216 +0,0 @@
-<template>
-  <div>
-    <div class="camera-main">
-      <div class="camera-tree" v-show="cameraTreeVisible">
-        <CameraTreeCom
-          :loading="presetListStore.loading"
-          :camera-tree="cameraTree || []"
-          :total="codeShowList.length"
-          :no-integration-num="noIntegrationNum"
-          :no-networking-num="noNetworkingNum"
-        />
-      </div>
-      <div v-if="cameraTreeVisible" class="arrow-icon" @click="cameraTreeVisible = false"
-        ><el-icon><DArrowLeft /></el-icon
-      ></div>
-      <div v-else class="arrow-icon" @click="cameraTreeVisible = true"
-        ><el-icon><DArrowRight /></el-icon
-      ></div>
-      <div class="camera-placeholder" v-if="!cameraDetailStore.cameraId">请选择左侧相机</div>
-      <div v-else class="camera-setting-wrapper">
-        <NvrCameraView ref="nvrCameraViewRef" :camera-id="cameraDetailStore.cameraId" />
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ElIcon } from 'element-plus';
-  import { DArrowLeft, DArrowRight } from '@element-plus/icons-vue';
-  import NvrCameraView from './components/NvrCameraView.vue';
-  import CameraTreeCom from '@/modules/algo-params-setting-base/components/CameraTree/CameraTreeOldVersion.vue';
-  import { onUnmounted, onBeforeUnmount, ref, watch } from 'vue';
-  import useCameraDetail from '@/modules/algo-params-setting-base/store/useCameraDetailStore';
-  import usePresetListStore from '@/modules/algo-params-setting-base/store/usePresetListStore';
-  import useFenceStore from '@/modules/algo-params-setting-base/store/useFenceStore';
-  import useCameraAlgoStore from '@/modules/algo-params-setting-base/store/useCameraAlgoStore';
-  import { onMounted } from 'vue';
-  // import { IsPtz } from '@/types/camera/constant';
-  import { CameraDetailServer } from '@/types/camera/type';
-  import { CameraTree, getFullCameraTree } from '@/api/camera/camera-preview';
-  import useCameraStatus from '@/modules/camera/hooks/useCameraStatus';
-
-  const cameraStatus = useCameraStatus();
-  const { noNetworkingNum, openInterval, closeInterval } = cameraStatus;
-
-  const cameraDetailStore = useCameraDetail();
-  const fenceStore = useFenceStore();
-  const presetListStore = usePresetListStore();
-  const cameraAlgoStore = useCameraAlgoStore();
-  const cameraTree = ref<CameraTree[]>([]);
-  const codeShowList = ref<string[]>([]);
-  const noIntegrationNum = ref<number>(0);
-  const nvrCameraViewRef = ref();
-
-  const cameraTreeVisible = ref(true);
-
-  // const { allAlgoList } = storeToRefs(cameraAlgoStore);
-
-  function updateNetworkingState(data, targetData) {
-    let integrationCount = 0;
-    for (let i = 0; i < data.length; i++) {
-      const node = data[i];
-      const matchedNode = targetData.find((item) => item.cameraCode === node.code);
-      if (matchedNode) {
-        node.networkingState = matchedNode.networkingState;
-        node.integrationState = matchedNode.integrationState;
-      }
-      if (node.integrationState === 1) {
-        integrationCount++;
-      }
-      if (node.children && node.children.length > 0) {
-        const childIntegrationCount = updateNetworkingState(node.children, targetData);
-        integrationCount += childIntegrationCount;
-      }
-    }
-    noIntegrationNum.value = integrationCount;
-    return integrationCount;
-  }
-
-  function getCameraList(data) {
-    let cameraList = [] as string[];
-    for (let i = 0; i < data.length; i++) {
-      const node = data[i];
-      if (node.nodeType === 'camera') {
-        cameraList.push(node.code);
-      }
-      if (node.children && node.children.length > 0) {
-        const childCameraList = getCameraList(node.children);
-        cameraList.push(...childCameraList);
-      }
-    }
-    return cameraList;
-  }
-
-  watch(
-    () => cameraDetailStore.cameraId,
-    async (cameraId) => {
-      fenceStore.clear();
-      if (cameraId) {
-        if (cameraTree.value.length === 0) {
-          /** 如果当前树为空,那么切换相机的时候,要重新请求树结构 */
-          const tree = await getFullCameraTree();
-          cameraTree.value = tree as unknown as CameraTree[];
-          codeShowList.value = getCameraList(tree);
-          closeInterval();
-          openInterval(codeShowList.value, (targetData) => {
-            updateNetworkingState(cameraTree.value, targetData);
-          });
-        }
-
-        const detail: CameraDetailServer = getCameraDetail(
-          cameraTree.value,
-          cameraDetailStore.cameraId,
-        ) as unknown as CameraDetailServer;
-        if (detail) {
-          cameraDetailStore.setDetail(detail);
-        }
-        // cameraAlgoStore.getCameraAlgoList(cameraId);
-        // cameraAlgoStore.selectedAlgoId = null;
-
-        cameraAlgoStore.selectedAlgoList = [];
-        cameraAlgoStore.getCameraAlgoList(cameraId).then();
-        nvrCameraViewRef.value.clearNvrUrl();
-      } else {
-        /** 没有相机的时候也要请求相机树 */
-        const tree = await getFullCameraTree();
-        cameraTree.value = tree as unknown as CameraTree[];
-      }
-    },
-    {
-      immediate: true,
-    },
-  );
-
-  onMounted(() => {
-    // getCameraTreeOldVersion().then((res) => {
-    //   cameraTree.value = res;
-    //   codeShowList.value = getCameraList(res);
-    //   openInterval(codeShowList.value, (targetData) => {
-    //     updateNetworkingState(cameraTree.value, targetData);
-    //   });
-    // });
-  });
-
-  onBeforeUnmount(() => {
-    if (nvrCameraViewRef.value) {
-      nvrCameraViewRef.value.clearNvrUrl();
-    }
-  });
-
-  onUnmounted(() => {
-    /** 离开页面要清理掉所有的store */
-    cameraDetailStore.clear();
-    cameraAlgoStore.clear();
-    fenceStore.clear();
-    presetListStore.clear();
-    closeInterval();
-  });
-
-  function getCameraDetail(tree: CameraTree[], cameraId: number): CameraTree | null {
-    let detail: CameraTree | null = null;
-
-    function getDetail(t: CameraTree[]) {
-      t.forEach((x) => {
-        if (x.nodeType === 'camera' && x.id === cameraId) {
-          detail = x;
-        } else if (x.children && x.children.length > 0) {
-          getDetail(x.children);
-        }
-      });
-    }
-
-    getDetail(tree);
-
-    return detail;
-  }
-</script>
-<style lang="scss" scoped>
-  .camera-main {
-    display: flex;
-    background: #fff;
-
-    .camera-tree {
-      // width: 250px;
-      flex-shrink: 0;
-      border: 1px solid #f0f2f5;
-      margin: 5px;
-    }
-    .camera-placeholder {
-      color: #333;
-      text-align: center;
-      margin-top: 100px;
-      margin-left: 100px;
-    }
-    .camera-setting-wrapper {
-      width: 960px;
-    }
-  }
-
-  .arrow-icon {
-    width: 16px;
-    height: 48px;
-    margin: 320px 0;
-    border-radius: 15px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    cursor: pointer;
-    background-color: #bee2ff;
-  }
-
-  .arrow-icon:hover {
-    color: #fff;
-    background-color: #0052d9;
-  }
-</style>

+ 0 - 316
src/views/datamanager/playback/components/NvrCameraView.vue

@@ -1,316 +0,0 @@
-<template>
-  <div class="nvr-camera-view">
-    <div class="nvr-tips">
-      <el-icon size="18" color="#409eff" style="margin: 11px 8px 11px 16px"><InfoFilled /></el-icon>
-      默认播放当前实时视频画面,可选择具体日期和时间进行回看,最长支持90天内视频内容回看</div
-    >
-    <div class="nvr-date-picker">
-      <el-date-picker
-        v-model="dateRange"
-        type="datetimerange"
-        start-placeholder="开始日期"
-        end-placeholder="结束日期"
-        range-separator="至"
-        format="YYYY-MM-DD HH:mm:ss"
-        :prefix-icon="Calendar"
-        :disabled-date="disableDate"
-        :clearable="false"
-        @change="judgeDate"
-      />
-      <el-button style="margin-left: 10px" type="primary" @click="handleNvrUrl(null)">查看回放</el-button>
-      <el-icon class="el-input__icon fullscreen-icon" :size="20" @click="enterFullscreen">
-        <FullscreenOutlined style="position: absolute; right: 0" />
-      </el-icon>
-    </div>
-    <div id="nvr-video" style="width: 960px; height: 540px">
-      <LiveVideo v-if="videoUrl" :url="videoUrl" @time-update="handleTimeUpdate" />
-    </div>
-    <div class="nvr-slider" v-if="confirmDate">
-      <NvrSlider
-        ref="nvrSliderRef"
-        :start-time="dateRange[0]"
-        :end-time="dateRange[1]"
-        :start-position="100"
-        :violations="violationsList"
-        @update-nvr="handleNvrUrl"
-      />
-    </div>
-    <div class="nvr-setting-bar">
-      <NvrVioCheckbox :available="confirmDate" :camera-id="cameraId" @check-tags="handleVioTags" />
-      <NvrTimeSelect
-        ref="nvrTimeSelectRef"
-        @set-Time="handleSetTime"
-        @download-nvr="handleDownloadNvr"
-        v-permission="{ action: [PERM_DATA.PLAYBACK_DOWNLOAD] }"
-      />
-    </div>
-    <a ref="downloadRef" style="display: none" href="" download />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import NvrVioCheckbox from './NvrCheckbox.vue';
-  import NvrTimeSelect from './NvrTimeSelect.vue';
-  import NvrSlider from './NvrSlider.vue';
-  // import CameraLiveVideo from '@/views/cameras/preview/components/CameraLiveVideo/CameraLiveVideo.vue';
-  import { ref } from 'vue';
-  import LiveVideo from '@/components/LiveVideo/LiveVideo.vue';
-  import useCameraDetailStore from '@/modules/algo-params-setting-base/store/useCameraDetailStore';
-  import { dayjs, ElMessage } from 'element-plus';
-  import { computed } from 'vue';
-  import { InfoFilled, Calendar } from '@element-plus/icons-vue';
-  import { FullscreenOutlined } from '@vicons/antd';
-  import {
-    getReplayNvr,
-    GetReplayNvrBody,
-    getRecordByTime,
-    GetRecordByTimeBody,
-    ViolationRecordItem,
-    getNvrDownloadUrl,
-  } from '@/api/datamanagement/playback';
-  import useCameraAlgoStore from '@/modules/algo-params-setting-base/store/useCameraAlgoStore';
-  import { useFullscreen } from 'vue-hooks-plus';
-  import { PERM_DATA } from '@/types/permission/constants';
-
-  const cameraAlgoStore = useCameraAlgoStore();
-  defineProps<{ cameraId: number }>();
-  const cameraDetailStore = useCameraDetailStore();
-
-  // 全屏参数和方法获取
-  const [, { enterFullscreen }] = useFullscreen(() => document.getElementById('nvr-video'));
-
-  // 日期范围
-  const dateRange = ref();
-  // 确认查看回放
-  const confirmDate = ref(false);
-  // 回放nvr地址
-  const nvrUrl = ref();
-  // 违例点列表
-  const violationsList = ref<ViolationRecordItem[]>([]);
-  // nvr滑动组件引用
-  const nvrSliderRef = ref();
-  // nvr下载组件引用
-  const nvrTimeSelectRef = ref();
-  // 下载
-  const downloadRef = ref();
-
-  const judgeDate = (date: Date[]) => {
-    confirmDate.value = false;
-    nvrUrl.value = undefined;
-    cameraAlgoStore.selectedAlgoList = [];
-
-    if (date && date.length === 2) {
-      const startTime = new Date(date[0]);
-      const endTime = new Date(date[1]);
-      if ((endTime.getTime() - startTime.getTime()) / 1000 < 1) {
-        ElMessage({
-          message: `选择回放时间范围需大于1秒`,
-          type: 'error',
-        });
-        dateRange.value = undefined;
-        return;
-      }
-      if (endTime > new Date()) {
-        ElMessage({
-          message: `结束时间不能在当前时间之后`,
-          type: 'error',
-        });
-        dateRange.value = undefined;
-        return;
-      }
-    }
-  };
-
-  // 播放时间变化前秒数
-  const secondMargin = ref<number>();
-  const handleNvrUrl = (nowTime?: Date | null) => {
-    if (!dateRange.value) {
-      return;
-    }
-    // if (cameraDetailStore.detail?.pushstreamIp) {
-    //   cameraDetailStore.clear();
-    // }
-    const nvrParams: GetReplayNvrBody = {
-      cameraId: cameraDetailStore.cameraId,
-      startTime: dayjs(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss'),
-      endTime: dayjs(dateRange.value[1]).format('YYYY-MM-DD HH:mm:ss'),
-    };
-    secondMargin.value = dateRange.value[0].getSeconds();
-    if (nowTime) {
-      const nowTimeMin = new Date(nowTime.setSeconds(0));
-      if (nowTimeMin < dateRange.value[0]) {
-        nvrParams.startTime = dayjs(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss');
-        // secondMargin.value = dateRange.value[0].getSeconds();
-      } else {
-        nvrParams.startTime = dayjs(nowTimeMin).format('YYYY-MM-DD HH:mm:ss');
-        secondMargin.value = nowTimeMin.getSeconds();
-      }
-    }
-    getReplayNvr(nvrParams)
-      .then((res) => {
-        confirmDate.value = true;
-
-        min = 0;
-        nvrUrl.value = res;
-      })
-      .catch(() => {
-        confirmDate.value = false;
-        min = 0;
-        nvrUrl.value = '';
-      });
-  };
-
-  const clearNvrUrl = () => {
-    nvrUrl.value = undefined;
-    confirmDate.value = false;
-    dateRange.value = undefined;
-    nvrTimeSelectRef.value.clearTime();
-  };
-
-  const handleVioTags = (tags: string[]) => {
-    if (tags.length === 0) {
-      violationsList.value = [];
-      return;
-    }
-    const violationsParams: GetRecordByTimeBody = {
-      algoList: tags.map((tag) => Number(tag)),
-      cameraId: cameraDetailStore.cameraId,
-      startTime: dayjs(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss'),
-      endTime: dayjs(dateRange.value[1]).format('YYYY-MM-DD HH:mm:ss'),
-    };
-    getRecordByTime(violationsParams).then((res) => {
-      violationsList.value = res;
-    });
-  };
-
-  const handleSetTime = (isStart: boolean) => {
-    if (!confirmDate.value) {
-      return;
-    }
-    const nowTimeMin = new Date(nvrSliderRef.value.onTime.setSeconds(0));
-    if (isStart) {
-      const end = nvrTimeSelectRef.value.endTime;
-      if (end.length > 0 && new Date(end) <= nowTimeMin) {
-        ElMessage({
-          message: `结束时间不早于开始时间`,
-          type: 'error',
-        });
-        return;
-      }
-      nvrTimeSelectRef.value.startTime = dayjs(
-        nowTimeMin < dateRange.value[0] ? dateRange.value[0] : nowTimeMin,
-      ).format('YYYY-MM-DD HH:mm:ss');
-    } else {
-      const start = nvrTimeSelectRef.value.startTime;
-      if (start.length > 0 && new Date(start) >= nowTimeMin) {
-        ElMessage({
-          message: `开始时间不晚于结束时间`,
-          type: 'error',
-        });
-        return;
-      }
-      nvrTimeSelectRef.value.endTime = dayjs(
-        new Date(nowTimeMin.setMinutes(nowTimeMin.getMinutes() + 1)) > dateRange.value[1]
-          ? dateRange.value[1]
-          : nowTimeMin.setMinutes(nowTimeMin.getMinutes() - 1),
-      ).format('YYYY-MM-DD HH:mm:ss');
-    }
-  };
-
-  let min = 0;
-  const handleTimeUpdate = (playSeconds: number) => {
-    if (dateRange.value && dateRange.value[0] && dateRange.value[1]) {
-      //计算时刻帧进给的间隔
-      const minuteLen = Math.ceil((dateRange.value[1].valueOf() - dateRange.value[0].valueOf()) / (1000 * 60));
-      const durMinute = minuteLen > 10 ? 60 : 6;
-      //时刻帧递进
-      if (secondMargin.value !== undefined) {
-        const currentTime = Math.floor(playSeconds) + secondMargin.value;
-        if (currentTime > min && currentTime % durMinute === 0) {
-          min = currentTime;
-          nvrSliderRef.value.pushTime();
-        }
-      }
-    }
-  };
-
-  const handleDownloadNvr = () => {
-    if (
-      // !confirmDate.value ||
-      nvrTimeSelectRef.value.startTime.length === 0 ||
-      nvrTimeSelectRef.value.endTime.length === 0
-    ) {
-      return;
-    }
-    nvrTimeSelectRef.value.isCallingDownload = true;
-    const nvrParams: GetReplayNvrBody = {
-      cameraId: cameraDetailStore.cameraId,
-      startTime: dayjs(nvrTimeSelectRef.value.startTime).format('YYYY-MM-DD HH:mm:ss'),
-      endTime: dayjs(nvrTimeSelectRef.value.endTime).format('YYYY-MM-DD HH:mm:ss'),
-    };
-    getNvrDownloadUrl(nvrParams).then((res) => {
-      downloadRef.value.href = res;
-      downloadRef.value.click();
-      nvrTimeSelectRef.value.isCallingDownload = false;
-    });
-  };
-
-  const disableDate = (time: Date) => {
-    const now = new Date();
-    return time > now || time < new Date(now.setDate(now.getDate() - 90));
-  };
-
-  const videoUrl = computed(() => {
-    return nvrUrl.value
-      ? nvrUrl.value
-      : cameraDetailStore.detail?.pushStreamDTO?.videoUrls?.pushstreamIp
-      ? cameraDetailStore.detail?.pushStreamDTO?.videoUrls?.pushstreamIp
-      : '';
-  });
-
-  defineExpose({
-    clearNvrUrl,
-  });
-</script>
-
-<style scoped lang="scss">
-  .nvr-tips {
-    margin: 5px 0;
-    width: 100%;
-    height: 40px;
-    background: #ecf5ff;
-    border-radius: 2px;
-    font-family: 'PingFangSC', 'PingFang SC';
-    font-weight: 400;
-    font-size: 13px;
-    color: #606266;
-    line-height: 40px;
-    text-align: left;
-    font-style: normal;
-    text-transform: none;
-    display: flex;
-    align-items: center;
-  }
-
-  .nvr-date-picker {
-    position: relative;
-    margin: 10px 0 10px 20px;
-  }
-
-  .nvr-slider {
-    height: 80px;
-    position: relative;
-  }
-
-  .nvr-setting-bar {
-    display: flex;
-    // justify-content: center;
-  }
-
-  .fullscreen-icon {
-    position: absolute;
-    right: 0;
-    top: 50%;
-    transform: translateY(-50%);
-  }
-</style>

+ 0 - 77
src/views/datamanager/playback/components/NvrCheckbox.vue

@@ -1,77 +0,0 @@
-<template>
-  <div class="nvr-checkbox">
-    <div class="head">
-      <div class="line"></div>
-      <div class="title">违规事件标记</div>
-    </div>
-
-    <div class="checkbox">
-      <el-checkbox-group v-if="cameraAlgoList?.length" v-model="selectedAlgoList">
-        <el-checkbox
-          v-for="tag in cameraAlgoList"
-          :disabled="!available"
-          :key="tag.algoInfo.id"
-          :label="tag.algoInfo.name"
-          :value="tag.algoInfo.id"
-          @change="sendCheckTag"
-        >
-        </el-checkbox>
-      </el-checkbox-group>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ElCheckboxGroup, ElCheckbox } from 'element-plus';
-  import { onMounted } from 'vue';
-  import { storeToRefs } from 'pinia';
-  import useCameraAlgoStore from '@/modules/algo-params-setting-base/store/useCameraAlgoStore';
-
-  const cameraAlgoStore = useCameraAlgoStore();
-  const { cameraAlgoList, selectedAlgoList } = storeToRefs(cameraAlgoStore);
-  // const checkedtags = ref<any[] | undefined>([]);
-  // const tags = ref<any>([]);
-
-  defineProps<{ available: boolean; cameraId?: number }>();
-
-  const emit = defineEmits(['checkTags']);
-  const sendCheckTag = () => {
-    emit('checkTags', selectedAlgoList.value);
-  };
-
-  onMounted(() => {
-    // cameraAlgoStore.getCameraAlgoList(props.cameraId).then(() => {
-    // checkedtags.value = cameraAlgoList.value?.map((item) => item.algoInfo.id); // 默认选中
-    // tags.value = cameraAlgoList.value;
-    // });
-  });
-</script>
-
-<style scoped lang="scss">
-  .nvr-checkbox {
-    width: 50%;
-    height: 100vh;
-    background-color: #ffffff;
-    .head {
-      display: flex;
-      align-items: center;
-      margin-left: 8px;
-      margin-top: 14px;
-      .line {
-        width: 4px;
-        height: 16px;
-        background: #1890ff;
-      }
-      .title {
-        font-size: 14px;
-        font-weight: 500;
-        color: rgba(0, 0, 0, 0.88);
-        line-height: 20px;
-        margin-left: 8px;
-      }
-    }
-    .checkbox {
-      padding: 12px 22px 0 22px;
-    }
-  }
-</style>

+ 0 - 274
src/views/datamanager/playback/components/NvrSlider.vue

@@ -1,274 +0,0 @@
-<template>
-  <div class="nvr-track" @mousedown="onDragStart">
-    <div class="run-line" :style="{ left: `${startPosition}px` }"></div>
-    <div class="run-time" :style="{ left: `${startPosition + 3}px` }">{{
-      dayjs(onTime).format('YYYY-MM-DD HH:mm')
-    }}</div>
-    <div id="timeline" class="nvr-slider" :style="{ transform: `translateX(${sliderPosition}px)` }">
-      <div id="violations"></div>
-      <div id="violationsLine" class="nvr-violations-line"> </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ref, onMounted, watch, computed } from 'vue';
-  import { dayjs } from 'element-plus';
-  import { ViolationRecordItem } from '@/api/datamanagement/playback';
-
-  const emit = defineEmits(['updateNvr']);
-
-  const minLength = 800;
-  const sliderScale = ref(1);
-  const sliderLength = ref(800);
-
-  // 定义长条的位置
-  const sliderPosition = ref(0);
-
-  // 记录鼠标按下时的信息
-  const isDragging = ref(false);
-  const initialMousePosition = ref(0);
-  const initialSliderPosition = ref(0);
-
-  // 鼠标按下时添加移动和抬起监听
-  const onDragStart = (event) => {
-    event.preventDefault();
-    isDragging.value = true;
-    initialMousePosition.value = event.clientX;
-    initialSliderPosition.value = sliderPosition.value;
-    document.addEventListener('mousemove', onDragging);
-    document.addEventListener('mouseup', onDragEnd);
-  };
-
-  // 鼠标移动时触发
-  const onDragging = (event) => {
-    if (!isDragging.value) return;
-    const delta = initialSliderPosition.value + (event.clientX - initialMousePosition.value);
-    sliderPosition.value =
-      delta > props.startPosition
-        ? props.startPosition
-        : delta < props.startPosition - sliderLength.value
-        ? props.startPosition - sliderLength.value
-        : delta;
-  };
-
-  // 鼠标抬起时去除监听器
-  const onDragEnd = () => {
-    isDragging.value = false;
-    document.removeEventListener('mousemove', onDragging);
-    document.removeEventListener('mouseup', onDragEnd);
-    emit('updateNvr', onTime.value);
-  };
-
-  onMounted(() => {
-    createTimeline(props.startTime, props.endTime, durationMins.value);
-    createViolationsLine([], props.startTime, props.endTime);
-    sliderPosition.value = props.startPosition;
-
-    watch([() => props.startTime, () => props.endTime], () => {
-      createTimeline(props.startTime, props.endTime, durationMins.value);
-      sliderPosition.value = props.startPosition;
-    });
-
-    watch(
-      () => props.violations,
-      () => {
-        createViolationsLine(props.violations!, props.startTime, props.endTime);
-      },
-    );
-  });
-
-  // 传入起止时间 传入违规点数组 违规点数组只需要时间点这个属性 画在拉动条上
-  const props = defineProps({
-    startTime: {
-      type: Date,
-      required: true,
-    },
-    endTime: {
-      type: Date,
-      required: true,
-    },
-    violations: {
-      type: Array<ViolationRecordItem>,
-      required: false,
-    },
-    startPosition: {
-      type: Number,
-      required: true,
-    },
-  });
-
-  // 时间条长度计算
-  const durationMins = computed(() => {
-    return Math.ceil((props.endTime.valueOf() - props.startTime.valueOf()) / (1000 * 60));
-  });
-
-  // 计算停驻时间
-  const onTime = computed(() => {
-    const res =
-      Number(props.startTime.valueOf()) +
-      ((props.startPosition - sliderPosition.value) / sliderScale.value) * 1000 * 60;
-    return new Date(res);
-  });
-
-  // 推动时间前进
-  const pushTime = () => {
-    const detaDistance = durationMins.value >= 10 ? 1 : 0.1;
-    const delta = sliderPosition.value - detaDistance * sliderScale.value;
-    sliderPosition.value =
-      delta > props.startPosition
-        ? props.startPosition
-        : delta < props.startPosition - sliderLength.value
-        ? props.startPosition - sliderLength.value
-        : delta;
-  };
-
-  const createTimeline = (startTime: Date, endTime: Date, durationMins: number) => {
-    const container = document.getElementById('timeline');
-    container!.innerHTML = '';
-
-    const startHours = startTime.getHours();
-    const marginMins = startTime.getMinutes();
-    const marginMinsRight = endTime.getMinutes();
-    // 拉动条的长度设置为分钟数
-    if (durationMins >= minLength) {
-      container!.style.width = `${durationMins}px`;
-    } else {
-      container!.style.width = `${minLength}px`;
-      sliderScale.value = minLength / durationMins;
-    }
-    sliderLength.value = durationMins >= 800 ? durationMins : 800;
-    // 计算持续小时数 向下取整
-    const duration = Math.floor(durationMins / 60) + (marginMins > marginMinsRight ? 1 : 0);
-    if (marginMins === 0) {
-      // 添加第一个小时
-      const mark = document.createElement('div');
-      mark.className = 'time-slider-mark';
-      mark.style.left = `${marginMins}px`;
-      container?.appendChild(mark);
-
-      // 添加第一个小时文本
-      const text = document.createElement('span');
-      text.className = 'time-slider-text';
-      text.textContent = `${startHours % 24}:00`;
-      text.style.left = `${marginMins}px`;
-      container?.appendChild(text);
-    }
-
-    for (let i = 1; i <= duration; i++) {
-      // 刻度元素
-      const mark = document.createElement('div');
-      mark.className = 'time-slider-mark';
-      mark.style.left = `${(i * 60 - marginMins) * sliderScale.value}px`;
-      container?.appendChild(mark);
-
-      // 刻度文本
-      const text = document.createElement('span');
-      text.className = 'time-slider-text';
-      text.textContent = `${(startHours + i) % 24}:00`;
-      text.style.left = `${(i * 60 - marginMins) * sliderScale.value - 12}px`;
-      container?.appendChild(text);
-    }
-  };
-
-  const createViolationsLine = (violations: ViolationRecordItem[], startTime: Date, endTime: Date) => {
-    const container = document.getElementById('timeline');
-    const remove = container!.querySelector('#violationsLine');
-
-    if (remove) {
-      container!.removeChild(remove);
-    }
-
-    // 创建违例时间条
-    const vLine = document.createElement('div');
-    vLine.id = 'violationsLine';
-
-    vLine.className = 'violations-line';
-    container!.appendChild(vLine);
-
-    violations.forEach((item) => {
-      const vTime = new Date(item.time);
-      if (vTime.valueOf() < startTime.valueOf() || vTime.valueOf() > endTime.valueOf()) {
-        return;
-      }
-      const vPoint = document.createElement('div');
-      vPoint.className = 'violations-point';
-      vPoint.style.left = `${((vTime.valueOf() - startTime.valueOf()) / (1000 * 60)) * sliderScale.value - 5}px`;
-      vLine.appendChild(vPoint);
-    });
-  };
-
-  defineExpose({
-    onTime,
-    pushTime,
-  });
-</script>
-
-<style scoped lang="scss">
-  .nvr-track {
-    width: 100%;
-    height: 80px;
-    position: absolute;
-    overflow: hidden;
-    background-color: #d8d8d8;
-
-    .run-line {
-      position: absolute;
-      width: 2px;
-      height: 80px;
-      background-color: #1890ff;
-      z-index: 3;
-    }
-    .run-time {
-      position: absolute;
-      background-color: #1890ff;
-      z-index: 3;
-      top: 50px;
-      font-size: 12px;
-      color: #ffffff;
-      line-height: 17px;
-      text-align: left;
-      background: #1890ff;
-      border-radius: 10px;
-      padding: 3px 6px;
-    }
-  }
-
-  #timeline {
-    cursor: pointer;
-    position: relative;
-    background-color: #f6f7f8;
-    height: 80px;
-    z-index: 1;
-  }
-</style>
-
-<style>
-  .time-slider-mark {
-    position: absolute;
-    width: 1px;
-    height: 8px;
-    background-color: #979797;
-  }
-  .time-slider-text {
-    position: absolute;
-    top: 10px;
-    color: #333333;
-  }
-  .violations-line {
-    overflow: hidden;
-    position: absolute;
-    width: 100%;
-    height: 8px;
-    top: 36px;
-    background-color: #d8d8d8;
-    z-index: 2;
-  }
-  .violations-point {
-    position: absolute;
-    width: 10px;
-    height: 8px;
-    background-color: #1890ff;
-    z-index: 3;
-  }
-</style>

+ 0 - 178
src/views/datamanager/playback/components/NvrTimeSelect.vue

@@ -1,178 +0,0 @@
-<template>
-  <div class="nvr-timeselect">
-    <div class="head">
-      <div class="line"></div>
-      <div class="title">视频下载</div>
-    </div>
-
-    <div class="timeselect">
-      <div class="time-picker">
-        开始时间:
-        <el-date-picker
-          v-model="startTime"
-          style="width: 160px; margin: 0 8px"
-          type="datetime"
-          format="YYYY-MM-DD HH:mm:ss"
-          value-format="YYYY-MM-DD HH:mm:ss"
-          :clearable="true"
-          placeholder="点击选择时间"
-          @change="changeStart"
-        />
-        <!-- <el-input
-          v-model="startTime"
-          style="width: 160px; margin: 0 8px"
-          disabled
-          placeholder="点击选择时间"
-        /> -->
-        <el-tooltip class="picker-tooltip" effect="dark" content="请先拖动进度条,再点击按钮选择时间" placement="top">
-          <img @click="callSetTime(true)" style="cursor: pointer" src="@\assets\icons\icon-picker.png" alt="" />
-        </el-tooltip>
-        <el-icon class="icon-refresh" :size="18">
-          <Refresh @click="startTime = ''" />
-        </el-icon>
-      </div>
-      <div class="time-picker">
-        结束时间:
-        <el-date-picker
-          v-model="endTime"
-          style="width: 160px; margin: 0 8px"
-          type="datetime"
-          format="YYYY-MM-DD HH:mm:ss"
-          value-format="YYYY-MM-DD HH:mm:ss"
-          :disabled="!startTime || !startTime.length"
-          :clearable="true"
-          placeholder="点击选择时间"
-          @change="judgeDate"
-        />
-        <!-- <el-input
-          v-model="endTime"
-          style="width: 160px; margin: 0 8px"
-          disabled
-          placeholder="点击选择时间"
-        /> -->
-        <el-tooltip class="picker-tooltip" effect="dark" content="请先拖动进度条,再点击按钮选择时间" placement="top">
-          <img @click="callSetTime(false)" style="cursor: pointer" src="@\assets\icons\icon-picker.png" alt="" />
-        </el-tooltip>
-        <el-icon class="icon-refresh" :size="18">
-          <Refresh @click="endTime = ''" />
-        </el-icon>
-      </div>
-
-      <el-button
-        type="primary"
-        :loading="isCallingDownload"
-        :disabled="!startTime || !endTime || !startTime.length || !endTime.length"
-        @click="nvrDownload"
-        >下 载</el-button
-      >
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ref } from 'vue';
-  // import { ElInput } from 'element-plus';
-  import { Refresh } from '@element-plus/icons-vue';
-  import { ElIcon, ElTooltip } from 'element-plus';
-  import { ElMessage } from 'element-plus';
-
-  const isCallingDownload = ref(false);
-  const startTime = ref('');
-  const endTime = ref('');
-
-  const emit = defineEmits(['setTime', 'downloadNvr']);
-
-  const callSetTime = (isStart: boolean) => {
-    emit('setTime', isStart);
-  };
-
-  const nvrDownload = () => {
-    emit('downloadNvr');
-  };
-
-  const changeStart = (val) => {
-    if (!val) {
-      endTime.value = '';
-    }
-  };
-  const clearTime = () => {
-    startTime.value = '';
-    endTime.value = '';
-  };
-
-  const judgeDate = (value) => {
-    if (!endTime.value) {
-      return;
-    }
-    const startTimeStamp = new Date(startTime.value).getTime();
-    const endTimeStamp = new Date(value).getTime();
-    if (endTimeStamp <= startTimeStamp) {
-      ElMessage.warning('结束时间不能小于开始时间');
-      endTime.value = '';
-    }
-    if (endTimeStamp - startTimeStamp > 10 * 60 * 1000) {
-      ElMessage.warning('视频下载时间不能超过10分钟');
-      endTime.value = '';
-    }
-  };
-
-  defineExpose({ isCallingDownload, startTime, endTime, clearTime });
-</script>
-
-<style scoped lang="scss">
-  .nvr-timeselect {
-    width: 50%;
-    height: 100vh;
-    background-color: #ffffff;
-    .head {
-      display: flex;
-      align-items: center;
-      margin-left: 8px;
-      margin-top: 14px;
-      .line {
-        width: 4px;
-        height: 16px;
-        background: #1890ff;
-      }
-      .title {
-        font-size: 14px;
-        font-weight: 500;
-        color: rgba(0, 0, 0, 0.88);
-        line-height: 20px;
-        margin-left: 8px;
-      }
-      .tips {
-        font-weight: 400;
-        font-size: 10px;
-        color: #909399;
-        line-height: 14px;
-      }
-    }
-    .timeselect {
-      padding: 12px 22px 0 22px;
-      .time-picker {
-        margin-bottom: 12px;
-        display: flex;
-        align-items: center;
-        .picker-tooltip {
-          width: 110px;
-          margin-top: 10px;
-
-          img {
-            display: inline;
-            margin-left: 20px;
-          }
-        }
-        .icon-refresh {
-          color: #1890ff;
-          margin: 0 8px;
-          cursor: pointer;
-        }
-      }
-    }
-  }
-
-  :deep(.el-input__prefix-inner) {
-    display: none;
-  }
-</style>

+ 0 - 146
src/views/feedback/component/singleProblem.vue

@@ -1,146 +0,0 @@
-<template>
-  <div
-    class="single-item"
-    :style="`padding-bottom:${props.problemData.problemStatus === STATUS.handled ? '0px' : '38px'}`"
-  >
-    <div style="display: flex; font-size: 12px">
-      <img src="@/assets/icons/phone.png" alt="" />
-      <div class="single-contact">联系方式:{{ props.problemData.mobile }}</div>
-      <div style="color: #00000073"
-        >人员:{{ props.problemData.submitterUsername }}-{{ props.problemData.submitterNickname }}
-      </div>
-      <div style="margin-left: 20px; color: #00000073">日期:{{ props.problemData.createdAt }}</div>
-    </div>
-    <el-button v-if="props.isHandle" type="primary" class="single-handle" @click="handleProblem"
-      >处理</el-button
-    >
-    <el-divider />
-    <div class="problem-type">
-      <div>问题类型:</div>
-      <div class="type-content">{{ problemTypeName[props.problemData.problemType] }}</div>
-    </div>
-    <div class="problem-describe">
-      <div>问题描述:</div>
-      <div class="problem-content">{{ props.problemData.problemDescription }}</div>
-    </div>
-    <div class="problem-picture">
-      <div class="picture-content" v-for="(item, index) in problemImageUrls" :key="index">
-        <el-image
-          style="width: 80px; height: 80px"
-          :src="item"
-          :zoom-rate="1.2"
-          :max-scale="7"
-          :min-scale="0.2"
-          :preview-src-list="problemImageUrls"
-          :initial-index="index"
-          fit="cover"
-        />
-      </div>
-    </div>
-
-    <el-collapse v-if="props.problemData.problemStatus === STATUS.handled" v-model="activeNames">
-      <el-collapse-item name="1">
-        <template #title>
-          <div class="problem-describe">
-            <div>处理人:</div>
-            <div class="problem-content">{{ props.problemData.processorName }}</div>
-          </div>
-        </template>
-        <div class="problem-describe">
-          <div>处理措施:</div>
-          <div class="problem-content">{{ props.problemData.dealMethod }}</div>
-        </div>
-      </el-collapse-item>
-    </el-collapse>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, computed } from 'vue';
-import { useRouter } from 'vue-router';
-import { Records, STATUS } from '@/api/feedback/feedback';
-import useHandleStore from '../useHandleStore';
-import { storeToRefs } from 'pinia';
-import { problemTypeName } from '../constant';
-
-const useSingle = useHandleStore();
-const { singleFeedback } = storeToRefs(useSingle);
-
-const router = useRouter();
-const props = defineProps<{
-  problemData: Records;
-  isHandle: boolean;
-}>();
-
-const activeNames = ref<string>('');
-const problemImageUrls = computed(() => {
-  const imageUrlString = props.problemData.problemImageUrl;
-  return imageUrlString ? imageUrlString.split(',') : [];
-});
-
-const handleProblem = () => {
-  singleFeedback.value = props.problemData;
-  router.push('/system/feedback-handle');
-};
-</script>
-
-<style scoped>
-.single-item {
-  background: #ffffff;
-  box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.09);
-  border-radius: 6px;
-  padding: 16px 12px 0px 12px;
-  position: relative;
-}
-
-.single-contact {
-  margin-left: 10px;
-  margin-right: 40px;
-}
-.single-handle {
-  position: absolute;
-  top: 11px;
-  right: 12px;
-}
-
-.el-divider--horizontal {
-  margin: 16px 0;
-}
-
-.problem-type,
-.problem-describe {
-  font-size: 14px;
-  white-space: nowrap;
-  word-break: break-word;
-  display: flex;
-  margin-bottom: 8px;
-}
-
-.type-content,
-.problem-content {
-  white-space: pre-wrap;
-  word-break: break-word;
-}
-.type-content {
-  font-weight: 600;
-}
-.problem-picture{
-  display: flex;
-  gap: 20px;
-}
-
-:deep(.el-collapse-item__header) {
-  border-bottom: none;
-}
-
-:deep(.el-collapse-item__wrap) {
-  border-bottom: none;
-}
-
-:deep(.el-collapse-item__content) {
-  padding-bottom: 0px;
-}
-:deep(.el-collapse) {
-  border-top: none;
-}
-</style>

+ 0 - 18
src/views/feedback/constant.ts

@@ -1,18 +0,0 @@
-import { STATUS } from '@/api/feedback/feedback';
-
-export const tabContent = [
-  { name: '未处理', value: STATUS.unhandled },
-  { name: '已处理', value: STATUS.handled },
-];
-
-enum ProblemType {
-  "system" = 1,
-  "product" = 2,
-  "other" = 3
-}
-
-export const problemTypeName = {
-  [ProblemType.system]:"系统操作问题",
-  [ProblemType.product]:"产品内容问题",
-  [ProblemType.other]:"其他"
-}

+ 0 - 114
src/views/feedback/feedback.vue

@@ -1,114 +0,0 @@
-<template>
-  <div class="feedback-page">
-    <div class="feedback-head">
-      <el-radio-group
-        v-model="problemStatus"
-        class="radio-button"
-        text-color="#1677FF"
-        fill="#1890FF26"
-        @change="handleClick"
-      >
-        <el-radio-button v-for="item in tabContent" :value="item.value" :key="item.value">{{
-          item.name
-        }}</el-radio-button>
-      </el-radio-group>
-      <div class="search-input">
-        <el-input
-          v-model="queryDescription"
-          style="width: 294px"
-          placeholder="请输入搜索内容"
-          :prefix-icon="Search"
-        />
-        <el-button type="primary" style="margin-left: 16px" @click="searchFeedback"
-          >搜索</el-button
-        ></div
-      ></div
-    >
-    <div class="problem-list"
-      ><singleProblem
-        v-for="(item, index) in feedbackList"
-        :key="index"
-        :problem-data="item"
-        :is-handle="item.problemStatus === STATUS.unhandled"
-        style="margin-top: 22px; margin-bottom: 2px"
-    /></div>
-
-    <el-pagination
-      v-model:current-page="pageNumber"
-      v-model:page-size="pageSize"
-      background
-      layout="prev, pager, next,sizes,jumper"
-      :page-sizes="[5, 10, 20, 40]"
-      :total="totalRow"
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentChange"
-      class="flex justify-end"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { Search } from '@element-plus/icons-vue';
-  import { tabContent } from './constant';
-  import singleProblem from './component/singleProblem.vue';
-  import useFeedback from './use-feedback.ts';
-  import { STATUS } from '@/api/feedback/feedback';
-
-  const useFeedbackList = useFeedback();
-  const { feedbackList, pageNumber, pageSize, problemStatus, queryDescription, totalRow, getList } =
-    useFeedbackList;
-
-  const handleClick = () => {
-    queryDescription.value = '';
-    getList();
-  };
-
-  const searchFeedback = () => {
-    pageNumber.value = 1;
-    getList();
-  };
-
-  const handleSizeChange = () => {
-    pageNumber.value = 1;
-    getList();
-  };
-  const handleCurrentChange = () => {
-    getList();
-  };
-</script>
-
-<style scoped>
-  .feedback-page {
-    position: relative;
-    height: calc(100vh - 64px - 12px);
-    background-color: #ffffff;
-    padding-top: 20px;
-    padding-left: 20px;
-    padding-right: 20px;
-  }
-
-  :deep(.el-radio-button .el-radio-button__inner) {
-    width: 188px;
-    background-color: #00000005;
-  }
-
-  .feedback-head {
-    display: flex;
-    flex-direction: column;
-  }
-
-  .search-input {
-    margin-top: 24px;
-  }
-
-  .problem-list {
-    height: calc(100vh - 270px);
-    overflow: auto;
-    margin-bottom: 4px;
-    padding: 0 2px;
-  }
-
-  :deep(.el-pagination .el-select) {
-    width: 92px;
-  }
-</style>

+ 0 - 130
src/views/feedback/handleFeedback.vue

@@ -1,130 +0,0 @@
-<template>
-  <div class="feedback-page">
-    <el-button :icon="Back" @click="backList">返回</el-button>
-    <div
-      ><singleProblem
-        :problem-data="singleFeedback"
-        :is-handle="false"
-        style="margin-top: 24px; margin-bottom: 40px"
-    /></div>
-    <el-form
-      ref="ruleFormRef"
-      :model="ruleForm"
-      :rules="rules"
-      label-position="left"
-      label-width="90px"
-      class="demo-ruleForm"
-      size="default"
-      status-icon
-    >
-      <el-form-item label="处理人:" prop="name">
-        <el-input v-model="ruleForm.name" placeholder="请输入" style="width: 160px" />
-      </el-form-item>
-      <el-form-item label="处理措施:" prop="solution">
-        <el-input
-          v-model="ruleForm.solution"
-          placeholder="请输入多行文字"
-          :autosize="{ minRows: 7, maxRows: 7 }"
-          type="textarea"
-          style="height: 160px"
-        />
-      </el-form-item>
-    </el-form>
-    <el-button type="primary" @click="subHandle" class="sub-btn" :disabled="!isFormValid"> 提交 </el-button>
-
-    <el-dialog
-      v-model="dialogVisible"
-      title="提交成功"
-      width="500"
-      align-center
-      @close="closeDialog"
-    >
-      <span>提交成功,可以在【已处理】中查看</span>
-      <template #footer>
-        <div class="dialog-footer">
-          <!-- <el-button @click="dialogVisible = false">Cancel</el-button> -->
-          <el-button type="primary" @click="closeDialog"> 确定 </el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { ref, reactive, watch,computed } from 'vue';
-  import { Back } from '@element-plus/icons-vue';
-  import { useRouter } from 'vue-router';
-  import singleProblem from './component/singleProblem.vue';
-  import type { FormInstance, FormRules } from 'element-plus';
-  import useHandleStore from './useHandleStore';
-  import { storeToRefs } from 'pinia';
-  import { STATUS, updateFeedback } from '@/api/feedback/feedback';
-
-  const useSingleStore = useHandleStore();
-  const { singleFeedback } = storeToRefs(useSingleStore);
-
-  const router = useRouter();
-
-  const ruleFormRef = ref<FormInstance>();
-  interface RuleForm {
-    name: string;
-    solution: string;
-  }
-  const ruleForm = reactive<RuleForm>({
-    name: '',
-    solution: '',
-  });
-
-  const rules = reactive<FormRules>({
-    name: [{ required: true, message: '处理人不能为空', trigger: 'blur' }],
-  });
-  const isFormValid = computed(()=>{
-    return Object.keys(rules).every(item => ruleForm[item].length>0)
-  })
-
-  const backList = () => {
-    router.push('/system/feedback');
-  };
-
-  const dialogVisible = ref<boolean>(false);
-
-  const subHandle = () => {
-    if (!ruleFormRef.value) return;
-    ruleFormRef.value.validate((valid) => {
-      if (!valid) {
-        return;
-      }
-
-      const subData = {
-        id: singleFeedback.value.id,
-        problemStatus: STATUS.handled,
-        processorName: ruleForm.name,
-        dealMethod: ruleForm.solution,
-      };
-      updateFeedback(subData).then(() => {
-        dialogVisible.value = true;
-      });
-    });
-  };
-
-  const closeDialog = () => {
-    dialogVisible.value = false;
-    backList();
-  };
-</script>
-
-<style scoped>
-  .feedback-page {
-    position: relative;
-    height: calc(100vh - 64px - 12px);
-    background-color: #ffffff;
-    padding-top: 20px;
-    padding-left: 20px;
-    padding-right: 20px;
-  }
-
-  .sub-btn {
-    margin-top: 6px;
-    margin-left: 88px;
-  }
-</style>

+ 0 - 46
src/views/feedback/use-feedback.ts

@@ -1,46 +0,0 @@
-import { STATUS, Records, QueryFeedback, getFeedbackList } from '@/api/feedback/feedback';
-import { onMounted, ref } from 'vue';
-
-export function useFeedbackList() {
-  const feedbackList = ref<Records[]>([]);
-  const pageNumber = ref<number>(1);
-  const pageSize = ref<number>(10);
-  const problemStatus = ref<STATUS>(STATUS.unhandled);
-  const queryDescription = ref<string>('');
-  const totalPage = ref<number>();
-  const totalRow = ref<number>();
-
-  const getList = () => {
-    const params: QueryFeedback = {
-      pageNumber: pageNumber.value,
-      pageSize: pageSize.value,
-      //problemDescription: queryDescription.value
-      problemStatus: problemStatus.value,
-    };
-    if (queryDescription.value) {
-      params.problemDescription = queryDescription.value;
-    }
-    getFeedbackList(params).then((res) => {
-      feedbackList.value = res.records;
-      totalPage.value = res.totalPage;
-      totalRow.value = res.totalRow;
-    });
-  };
-
-  onMounted(() => {
-    getList();
-  });
-
-  return {
-    feedbackList,
-    pageNumber,
-    pageSize,
-    problemStatus,
-    queryDescription,
-    totalPage,
-    totalRow,
-    getList,
-  };
-}
-
-export default useFeedbackList;

+ 0 - 11
src/views/feedback/useHandleStore.ts

@@ -1,11 +0,0 @@
-import { ref } from 'vue';
-import { defineStore } from 'pinia';
-import { Records } from '@/api/feedback/feedback';
-
-export const useFeedbackHandled = defineStore('handle-feedback', () => {
-  const singleFeedback = ref<Records>({} as Records);
-
-  return { singleFeedback };
-});
-
-export default useFeedbackHandled;

+ 0 - 72
src/views/list/basicList/columns.ts

@@ -1,72 +0,0 @@
-import { h } from 'vue';
-import { ElAvatar, ElTag } from 'element-plus';
-
-export const columns = [
-  {
-    type: 'selection',
-    width: 55,
-  },
-  {
-    label: 'id',
-    prop: 'id',
-    // width: 100,
-  },
-  {
-    label: '名称',
-    prop: 'name',
-    // width: 100,
-  },
-  {
-    label: '头像',
-    prop: 'avatar',
-    // width: 100,
-    render(record) {
-      return h(ElAvatar, {
-        size: 48,
-        src: record.row.avatar,
-        shape: 'square',
-        fit: 'fill',
-      });
-    },
-  },
-  {
-    label: '地址',
-    prop: 'address',
-    auth: ['basic_list'], // 同时根据权限控制是否显示
-    // width: 150,
-    ifShow: (_column) => {
-      return true; // 根据业务控制是否显示
-    },
-  },
-  {
-    label: '开始日期',
-    prop: 'beginTime',
-    width: 160,
-  },
-  {
-    label: '结束日期',
-    prop: 'endTime',
-    width: 160,
-  },
-  {
-    label: '状态',
-    prop: 'status',
-    // width: 100,
-    render(record) {
-      return h(
-        ElTag,
-        {
-          type: record.row.status ? 'success' : 'danger',
-        },
-        {
-          default: () => (record.row.status ? '启用' : '禁用'),
-        },
-      );
-    },
-  },
-  {
-    label: '创建时间',
-    prop: 'date',
-    width: 100,
-  },
-];

+ 0 - 336
src/views/list/basicList/index.vue

@@ -1,336 +0,0 @@
-<template>
-  <PageWrapper>
-    <el-card :bordered="false" class="pt-3 mb-3 proCard">
-      <BasicForm
-        @register="register"
-        @submit="handleSubmit"
-        @reset="handleReset"
-        @advanced="formAdvanced"
-      >
-        <template #statusSlot="{ model, field }">
-          <el-input v-model="model[field]" placeholder="请输入" />
-        </template>
-      </BasicForm>
-    </el-card>
-    <el-card :bordered="false" class="proCard">
-      <BasicTable
-        :columns="columns"
-        :request="loadDataTable"
-        :row-key="(row) => row.id"
-        ref="actionRef"
-        :actionColumn="actionColumn"
-        @checked-row-change="onCheckedRow"
-        :scroll-x="1090"
-      >
-        <template #tableTitle>
-          <el-button type="primary" @click="addTable">
-            <template #icon>
-              <el-icon class="el-input__icon">
-                <PlusOutlined />
-              </el-icon>
-            </template>
-            新建
-          </el-button>
-        </template>
-
-        <template #toolbar>
-          <el-button type="primary" @click="reloadTable">刷新数据</el-button>
-        </template>
-      </BasicTable>
-    </el-card>
-    <el-dialog v-model="showModal" title="新建" width="30%" draggable>
-      <el-form
-        :model="formParams"
-        :rules="rules"
-        ref="formRef"
-        label-placement="left"
-        :label-width="80"
-        class="py-4"
-      >
-        <el-form-item label="名称" prop="name">
-          <el-input placeholder="请输入名称" v-model="formParams.name" />
-        </el-form-item>
-        <el-form-item label="地址" prop="address">
-          <el-input type="textarea" placeholder="请输入地址" v-model="formParams.address" />
-        </el-form-item>
-        <el-form-item label="日期" prop="date">
-          <el-date-picker type="datetime" placeholder="请选择日期" v-model="formParams.date" />
-        </el-form-item>
-      </el-form>
-
-      <template #footer>
-        <el-space>
-          <el-button @click="() => (showModal = false)">取消</el-button>
-          <el-button type="primary" :loading="formBtnLoading" @click="confirmForm">确定</el-button>
-        </el-space>
-      </template>
-    </el-dialog>
-  </PageWrapper>
-</template>
-
-<script lang="ts" setup>
-  import { h, reactive, ref } from 'vue';
-  import { ColProps, ElMessage, FormRules } from 'element-plus';
-  import { BasicTable, TableAction } from '@/components/Table';
-  import { BasicForm, useForm, FormSchema } from '@/components/Form/index';
-  import { getTableList } from '@/api/table/list';
-  import { columns } from './columns';
-  import { PlusOutlined, DeleteOutlined, FormOutlined } from '@vicons/antd';
-  import { useRoute } from 'vue-router';
-  import { renderIcon } from '@/utils';
-
-  const rules: FormRules = {
-    name: [
-      {
-        required: true,
-        trigger: 'blur',
-        message: '请输入名称',
-      },
-    ],
-    address: [
-      {
-        required: true,
-        trigger: 'blur',
-        message: '请输入地址',
-      },
-    ],
-    date: [
-      {
-        required: true,
-        trigger: ['blur', 'change'],
-        message: '请选择日期',
-      },
-    ],
-  };
-
-  const schemas: FormSchema[] = [
-    {
-      field: 'name',
-      labelMessage: '这是一个提示',
-      component: 'Input',
-      label: '姓名',
-      componentProps: {
-        placeholder: '请输入姓名',
-        onInput: (e: any) => {
-          console.log(e);
-        },
-      },
-      // rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
-    },
-    {
-      field: 'mobile',
-      component: 'Input',
-      label: '手机',
-      componentProps: {
-        placeholder: '请输入手机号码',
-        onInput: (e: any) => {
-          console.log(e);
-        },
-      },
-    },
-    {
-      field: 'type',
-      component: 'Select',
-      label: '类型',
-      componentProps: {
-        placeholder: '请选择类型',
-        options: [
-          {
-            label: '舒适性',
-            value: 1,
-          },
-          {
-            label: '经济性',
-            value: 2,
-          },
-        ],
-        onChange: (e: any) => {
-          console.log(e);
-        },
-      },
-    },
-    {
-      field: 'makeDate',
-      component: 'DatePicker',
-      label: '预约时间',
-      defaultValue: 1183135260000,
-      componentProps: {
-        type: 'date',
-        onChange: (e: any) => {
-          console.log(e);
-        },
-      },
-    },
-    {
-      field: 'makeTime',
-      component: 'TimePicker',
-      label: '停留时间',
-      componentProps: {
-        clearable: true,
-        onChange: (e: any) => {
-          console.log(e);
-        },
-      },
-    },
-    {
-      field: 'status',
-      label: '状态',
-      //插槽
-      slot: 'statusSlot',
-    },
-  ];
-
-  const route = useRoute();
-  const formRef: any = ref(null);
-
-  const actionRef = ref();
-
-  const showModal = ref(false);
-  const formBtnLoading = ref(false);
-  const formParams = reactive({
-    name: '',
-    address: '',
-    date: '',
-  });
-
-  const params = ref({
-    name: '',
-    id: route.params.id,
-  });
-
-  const actionColumn = reactive({
-    width: 300,
-    label: '操作',
-    prop: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(TableAction as any, {
-        style: 'button',
-        actions: [
-          {
-            label: '删除',
-            type: 'danger',
-            size: 'default',
-            icon: renderIcon(DeleteOutlined),
-            //Popconfirm 气泡确认框 配置
-            isConfirm: true,
-            popConfirm: {
-              onConfirm: handleDelete.bind(null, record),
-              onCancel: handleNegative.bind(null, record),
-              title: '您真的,确定要删除吗?',
-              confirmButtonText: '确定',
-              cancelButtonText: '取消',
-            },
-          },
-          {
-            label: '编辑',
-            type: 'warning',
-            size: 'default',
-            icon: renderIcon(FormOutlined),
-            onClick: handleEdit.bind(null, record),
-          },
-        ],
-        dropDownProps: {
-          label: '更多',
-          type: 'primary',
-          size: 'default',
-          icon: renderIcon(DeleteOutlined),
-          // iconPlacement: 'left',
-        },
-        dropDownActions: [
-          {
-            label: '启用',
-            size: 'medium',
-            key: 'enabled',
-            // 根据业务控制是否显示: 非enable状态的不显示启用按钮
-            ifShow: () => {
-              return true;
-            },
-          },
-          {
-            label: '禁用',
-            key: 'disabled',
-            ifShow: () => {
-              return true;
-            },
-          },
-        ],
-        select: (key) => {
-          ElMessage.success(`您点击了,${key} 按钮`);
-        },
-      });
-    },
-  });
-
-  const [register, {}] = useForm({
-    layout: 'horizontal',
-    colProps: { span: 6 } as ColProps,
-    schemas,
-  });
-
-  function formAdvanced(status) {
-    console.log(status);
-    actionRef.value.redoHeight();
-  }
-
-  function addTable() {
-    showModal.value = true;
-  }
-
-  const loadDataTable = async (res) => {
-    return await getTableList({ ...formParams, ...params.value, ...res });
-  };
-
-  function onCheckedRow(rowKeys) {
-    console.log(rowKeys.value);
-  }
-
-  function reloadTable() {
-    actionRef.value.reload();
-  }
-
-  function confirmForm() {
-    if (!formRef.value) return;
-    formBtnLoading.value = true;
-    formRef.value.validate((valid) => {
-      if (valid) {
-        ElMessage.success('新建成功');
-        setTimeout(() => {
-          showModal.value = false;
-          reloadTable();
-        });
-      } else {
-        formBtnLoading.value = false;
-        ElMessage.error('请填写完整信息');
-      }
-    });
-  }
-
-  function handleEdit(record: Recordable) {
-    console.log('点击了编辑', record);
-    ElMessage.success('点击了编辑');
-    //router.push({ name: 'BasicInfo', params: { id: record.id } });
-  }
-
-  function handleDelete(record: Recordable) {
-    console.log('点击了删除', record);
-    ElMessage.success('点击了删除');
-  }
-
-  function handleNegative(record: Recordable) {
-    console.log('点击了取消', record);
-    ElMessage.success('点击了取消');
-  }
-
-  function handleSubmit(values: Recordable) {
-    console.log(values);
-    params.value = Object.assign(formParams, values) as any;
-    reloadTable();
-  }
-
-  function handleReset(values: Recordable) {
-    console.log(values);
-  }
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 37
src/views/list/basicList/info.vue

@@ -1,37 +0,0 @@
-<template>
-  <PageWrapper title="基础详情" content="基础详情,有时也用于显示只读信息。">
-    <el-card shadow="hover" class="mt-3 proCard" size="small">
-      <el-descriptions label-placement="left" class="py-2">
-        <el-descriptions-item>
-          <template #label>收款人姓名</template>
-          啊俊
-        </el-descriptions-item>
-        <el-descriptions-item label="收款账户">NaiveUiAdmin@qq.com</el-descriptions-item>
-        <el-descriptions-item label="付款类型">支付宝</el-descriptions-item>
-        <el-descriptions-item label="付款账户">NaiveUiAdmin@163.com</el-descriptions-item>
-        <el-descriptions-item label="转账金额">¥1980.00</el-descriptions-item>
-        <el-descriptions-item label="状态">
-          <el-tag type="success"> 已到账</el-tag>
-        </el-descriptions-item>
-      </el-descriptions>
-      <div class="w-full">
-        <el-space>
-          <label>测试页面缓存</label>
-          <el-input v-model="value" placeholder="输入点内容试试" />
-        </el-space>
-      </div>
-    </el-card>
-  </PageWrapper>
-</template>
-
-<script lang="ts">
-  export default {
-    name: 'BasicInfo',
-  };
-</script>
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  const value = ref();
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 155
src/views/login/LoginForm.vue

@@ -1,155 +0,0 @@
-<template>
-  <el-form
-    ref="formRef"
-    :show-label="false"
-    :show-require-mark="false"
-    size="large"
-    :model="formInline"
-    :rules="rules"
-  >
-    <el-form-item prop="username">
-      <el-input v-model="formInline.username" placeholder="请输入用户名">
-        <template #prefix>
-          <el-icon class="el-input__icon" size="18" color="#808695">
-            <PersonOutline />
-          </el-icon>
-        </template>
-      </el-input>
-    </el-form-item>
-    <el-form-item prop="password">
-      <el-input
-        v-model="formInline.password"
-        type="password"
-        show-password
-        placeholder="请输入密码"
-        @keyup.enter="handleSubmit"
-      >
-        <template #prefix>
-          <el-icon class="el-input__icon" size="18" color="#808695">
-            <LockClosedOutline />
-          </el-icon>
-        </template>
-      </el-input>
-    </el-form-item>
-    <div class="mb-6 default-color">
-      <div class="flex justify-between">
-        <div class="flex-initial">
-          <el-checkbox v-model:checked="autoLogin">自动登录</el-checkbox>
-        </div>
-        <div class="flex-initial order-last">
-          <a href="javascript:">忘记密码</a>
-        </div>
-      </div>
-    </div>
-    <el-form-item :show-label="false">
-      <el-button
-        class="w-full"
-        type="primary"
-        @click="handleSubmit"
-        size="large"
-        :loading="loading"
-      >
-        登录
-      </el-button>
-    </el-form-item>
-    <div class="mb-4 default-color">
-      <div class="flex view-account-other">
-        <div class="flex-initial">
-          <span>其它登录方式</span>
-        </div>
-        <div class="flex-initial mx-2">
-          <a href="javascript:">
-            <el-icon class="el-input__icon" size="24" color="#2d8cf0">
-              <LogoGithub />
-            </el-icon>
-          </a>
-        </div>
-        <div class="flex-initial mx-2">
-          <a href="javascript:">
-            <el-icon class="el-input__icon" size="24" color="#2d8cf0">
-              <LogoFacebook />
-            </el-icon>
-          </a>
-        </div>
-        <div class="flex-initial" style="margin-left: auto">
-          <a href="javascript:" @click="goRegister">注册账号</a>
-        </div>
-      </div>
-    </div>
-  </el-form>
-</template>
-
-<script lang="ts" setup>
-  import { reactive, ref } from 'vue';
-  import { useRoute, useRouter } from 'vue-router';
-  import { useUserStore } from '@/store/modules/user';
-  import { ElMessage } from 'element-plus';
-  import { ResultEnum } from '@/enums/httpEnum';
-  import { PersonOutline, LockClosedOutline, LogoGithub, LogoFacebook } from '@vicons/ionicons5';
-  import { PageEnum } from '@/enums/pageEnum';
-
-  interface FormState {
-    username: string;
-    password: string;
-  }
-
-  const formRef = ref();
-
-  const loading = ref(false);
-  const autoLogin = ref(true);
-  const LOGIN_NAME = PageEnum.BASE_LOGIN_NAME;
-
-  const formInline = reactive({
-    username: '',
-    password: '',
-  });
-
-  const rules = {
-    username: { required: true, message: '请输入用户名', trigger: 'blur' },
-    password: { required: true, message: '请输入密码', trigger: 'blur' },
-  };
-  const emit = defineEmits(['goRegister']);
-  const userStore = useUserStore();
-
-  const router = useRouter();
-  const route = useRoute();
-
-  const handleSubmit = () => {
-    if (!formRef.value) return;
-    formRef.value.validate(async (valid) => {
-      if (valid) {
-        const { username, password } = formInline;
-        loading.value = true;
-
-        const params: FormState = {
-          username,
-          password,
-        };
-
-        try {
-          const { code, message: msg } = await userStore.login(params);
-          if (code == ResultEnum.SUCCESS) {
-            const toPath = decodeURIComponent((route.query?.redirect || '/') as string);
-            ElMessage.success('登录成功,即将进入系统');
-            if (route.name === LOGIN_NAME) {
-              router.replace('/');
-            } else router.replace(toPath);
-          } else {
-            ElMessage.error(msg || '登录失败');
-          }
-        } finally {
-          loading.value = false;
-        }
-      } else {
-        ElMessage({
-          message: '请填写完整信息',
-          type: 'error',
-        });
-      }
-    });
-  };
-
-  function goRegister() {
-    emit('goRegister');
-  }
-</script>

+ 0 - 0
src/views/login/LoginForm2.vue


Некоторые файлы не были показаны из-за большого количества измененных файлов