Procházet zdrojové kódy

Merge branch 'NVR-manage' into 'dev'

Nvr manage

See merge request skyeye/skyeye_frontend/skyeye-admin!68
航飞 楼 před 1 rokem
rodič
revize
e5d85ccafc

+ 69 - 0
src/api/camera/camera-nvr.ts

@@ -0,0 +1,69 @@
+import { http } from '@/utils/http/axios';
+
+export interface NVRListItem {
+  code: string;           // 编码
+  name: string;           // NVR名称
+  nvrIp: string;          // NVR的IP地址
+  nvrPort: string;        // NVR端口号
+  nvrType: string;        // NVR品牌
+  password: string;       // NVR登录密码
+  principal?: string;     // 设备安装负责人
+  remark?: string;        // 备注
+  username: string;       // NVR登录用户名
+  workshopList: number[]; // NVR使用车间列表
+};
+
+export interface NVRListItemAll extends NVRListItem {
+  id: number;
+  tenantId: number;     // 租户ID
+  createdAt: string;
+  updatedAt: string;
+  isDeleted: number;    // 0-未删除,>0-已删除
+  workshopName: string; // NVR绑定车间名称展示
+}
+
+export interface NVRQueryItem {
+  pageNumber: number;
+  pageSize: number;
+};
+
+// 添加NVR
+export const addNVRListItem = (data: NVRListItem) => {
+  return http.request({
+    url: '/nvrOption/saveNvr',
+    method: 'post',
+    data,
+  });
+};
+
+// 删除NVR
+export const deleteNVRListItem = (nvrId: number) => {
+  return http.request({
+    url: `/nvrOption/deleteNvr?nvrId=${nvrId}`,
+    method: 'delete',
+  });
+};
+
+// 编辑NVR
+export const updateNVRListItem = (data: NVRListItem) => {
+  return http.request({
+    url: '/nvrOption/updateNvr',
+    method: 'post',
+    data,
+  });
+};
+
+// 查询NVR
+export const getNVRList = (query: NVRQueryItem) => {
+  return http.request({
+    url: `/nvrOption/getNvr?pageNumber=${query.pageNumber}&pageSize=${query.pageSize}`,
+    method: 'get',
+  });
+};
+// export const getNVRList = (data: NVRQueryItem) => {
+//   return http.request({
+//     url: '/nvrOption/getNvr',
+//     method: 'get',
+//     data,
+//   });
+// };

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

@@ -0,0 +1,222 @@
+<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">添加</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';
+
+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 actionColumn: BasicColumn = reactive({
+  width: 200,
+  title: '操作',
+  prop: 'action',
+  key: 'action',
+  fixed: 'right',
+  render(record) {
+    return h(TableActionIcons as any, {
+      space: 20,
+      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 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>

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

@@ -0,0 +1,234 @@
+<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-cascader v-model="workLocations" :options="locationOptions" :props="ismultiple" collapse-tags
+            collapse-tags-tooltip clearable placeholder="请选择使用该NVR的车间" @change="handleCascaderChange" />
+        </el-form-item>
+        <el-form-item label="负责人:" prop="principal">
+          <el-input v-model="formParams.principal" 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 { locationOptions, getLocationOptions, getWorkLocation } = useWorkLocation();
+const workLocations = ref<[number | undefined, number | undefined] | []>([]);
+
+const codeError = ref('');
+const ipError = ref('');
+
+const initFormNvr = () => ({
+  name: '',
+  code: '',
+  nvrIp: '',
+  nvrType: '',
+  nvrPort: '',
+  username: '',
+  password: '',
+  workshopList: [],
+  principal: '',
+  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', 'workshopName');
+    formParams.value.workshopList.map((item, index) => {
+      workLocations.value[index] = getWorkLocation(item, locationOptions.value)
+    });
+    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' },
+  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 handleCascaderChange = () => {
+  formParams.value.workshopList = workLocations.value.map((item) => {
+    return item[1];
+  })
+};
+
+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,
+          workshopList: formParams.value.workshopList,
+          principal: formParams.value.principal,
+          remark: formParams.value.remark,
+        };
+
+        if (isAddUser.value) {
+          addNVRListItem(nvrData).then((res) => {
+            if (Object.getOwnPropertyNames(res).length != 0) {
+              codeError.value = res.code;
+              ipError.value = res.nvrIp;
+            } else {
+              emit('form-submit');
+              closeDrawer();
+            }
+          });
+        } else {
+          updateNVRListItem(formParams.value).then((res) => {
+            if (Object.getOwnPropertyNames(res).length != 0) {
+              codeError.value = res.code;
+              ipError.value = res.nvrIp;
+            } else {
+              emit('form-edit');
+              closeDrawer();
+            }
+          });
+        }
+      }
+    });
+  }
+};
+
+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;
+}
+</style>

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

@@ -0,0 +1,56 @@
+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: number;
+  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,
+            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
+  };
+}

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

@@ -0,0 +1,48 @@
+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: 'workshopName',
+    minWidth: 150,
+  },
+  {
+    label: '负责人',
+    prop: 'principal',
+    minWidth: 140,
+  }
+];

+ 108 - 146
src/views/cameras/overview/components/AddCameraBySRS.vue

@@ -1,83 +1,44 @@
 <template>
   <div>
     <div style="margin-bottom: 120px">
-      <el-form
-        ref="IPFormRef"
-        class="ip-form"
-        :inline="true"
-        :model="CameraSRSData"
-        :rules="rules"
-        label-width="114px"
-        label-position="left"
-      >
+      <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="场景:" prop="workspaceCode">
-          <el-tree-select
-            v-model="CameraSRSData.workspaceCode"
-            :data="scenesTree"
-            :render-after-expand="false"
-            :default-expand-all="props.formData ? true : false"
-            check-strictly
-            placeholder="请输入场景名称"
-            style="width: 200px"
-            @node-click="handleTreeSelect"
-          />
+          <el-tree-select v-model="CameraSRSData.workspaceCode" :data="scenesTree" :render-after-expand="false"
+            :default-expand-all="props.formData ? true : false" check-strictly placeholder="请输入场景名称"
+            style="width: 200px" @node-click="handleTreeSelect" />
         </el-form-item>
         <el-form-item label="设备ID号:" prop="code">
-          <el-input
-            v-model="CameraSRSData.code"
-            placeholder="自定义ID,不能重复"
-            style="width: 200px"
-          />
+          <el-input v-model="CameraSRSData.code" placeholder="自定义ID,不能重复" style="width: 200px" />
         </el-form-item>
         <el-form-item label="工位负责人:" prop="principal">
-          <el-input
-            v-model="CameraSRSData.principal"
-            placeholder="请输入工位负责人"
-            style="width: 200px"
-            :disabled="true"
-          />
+          <el-input v-model="CameraSRSData.principal" placeholder="请输入工位负责人" style="width: 200px" :disabled="true" />
         </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: 685px"
-          />
+          <el-input v-model="CameraSRSData.rtspurl" placeholder="rtsp://192.168.0.249:557/34020000000_00000000000001"
+            style="width: 685px" />
         </el-form-item>
-        <el-form-item label="备注:" prop="remark">
-          <el-input v-model="CameraSRSData.remark" placeholder="请输入备注" style="width: 200px" />
+        <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="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 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="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 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="remark">
+          <el-input v-model="CameraSRSData.remark" placeholder="请输入备注" style="width: 200px" />
+        </el-form-item>
       </el-form>
     </div>
     <span class="pop-footer">
@@ -88,99 +49,100 @@
 </template>
 
 <script setup lang="ts">
-  import { onBeforeMount, ref } from 'vue';
-  import { CameraSRS } from '../type';
-  import useSceneInfos from '@/hooks/useSceneInfos';
-  import { cloneDeep } from 'lodash-es';
-  import { serviceTypeSelect, standardTypeSelect } from '../constant';
-  import { ElMessage } from 'element-plus';
-
-  const props = defineProps<{ formData?: CameraSRS | null }>();
-
-  const emits = defineEmits(['cancel-execute', 'confirm-execute']);
-
-  const sceneInfos = useSceneInfos();
-  const { scenesTree, flattendWorkspaces, getScenesTree } = sceneInfos;
-
-  const IPFormRef = ref();
-
-  const CameraSRSData = ref<CameraSRS>({} as CameraSRS);
-
-  const rules = {
-    name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
-    workspaceCode: [{ required: true, message: '请输入场景名称', trigger: 'blur' }],
-    code: [{ required: true, message: '请输入设备ID号', trigger: 'blur' }],
-    rtspurl: [{ required: true, message: '请输入流媒体地址', trigger: 'blur' }],
-    videoServiceType: [{ required: false }],
-    videoStandard: [{ required: true, message: '请输入视频编码标准', trigger: 'blur' }],
-  };
-
-  const handleCancel = () => {
-    emits('cancel-execute');
-  };
-
-  const handleConfirm = () => {
-    IPFormRef.value.validate((valid) => {
-      if (valid) {
-        const copyData = cloneDeep(CameraSRSData.value);
-        copyData.workspaceId = flattendWorkspaces.value.find(
-          (item) => item.code === CameraSRSData.value.workspaceCode,
-        ).id;
-        delete (copyData as any).workspaceCode;
-        delete (copyData as any).principal;
-        emits('confirm-execute', copyData);
-      }
-    });
-  };
-
-  // const handleTreeSelect = (code: string) => {
-  //   const space = flattendWorkspaces.value.find((item) => item.code === code);
-  //   CameraSRSData.value.workspaceId = space?.id;
-  //   CameraSRSData.value.principal = space?.principal;
-  // };
-
-  const handleTreeSelect = (node) => {
-    const space = flattendWorkspaces.value.find((item) => item.code === node.value);
-    CameraSRSData.value.workspaceId = space?.id;
-    CameraSRSData.value.principal = space?.principal;
-    if (node.disabled && node.children.length < 1) {
-      ElMessage.error('请先添加工位');
-    }
-  };
+import { onBeforeMount, ref } from 'vue';
+import { CameraSRS } from '../type';
+import useSceneInfos from '@/hooks/useSceneInfos';
+import { cloneDeep } from 'lodash-es';
+import { serviceTypeSelect, standardTypeSelect } from '../constant';
+import { ElMessage } from 'element-plus';
+
+const props = defineProps<{ formData?: CameraSRS | null }>();
+
+const emits = defineEmits(['cancel-execute', 'confirm-execute']);
+
+const sceneInfos = useSceneInfos();
+const { scenesTree, flattendWorkspaces, getScenesTree } = sceneInfos;
+
+const IPFormRef = ref();
+
+const CameraSRSData = ref<CameraSRS>({} as CameraSRS);
+
+const rules = {
+  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+  workspaceCode: [{ required: true, message: '请输入场景名称', trigger: 'blur' }],
+  code: [{ required: true, message: '请输入设备ID号', trigger: 'blur' }],
+  rtspurl: [{ required: true, message: '请输入流媒体地址', trigger: 'blur' }],
+  videoServiceType: [{ required: false }],
+  videoStandard: [{ required: true, message: '请输入视频编码标准', trigger: 'blur' }],
+};
 
-  onBeforeMount(() => {
-    getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
-    if (props.formData) {
-      CameraSRSData.value = props.formData;
+const handleCancel = () => {
+  emits('cancel-execute');
+};
+
+const handleConfirm = () => {
+  IPFormRef.value.validate((valid) => {
+    if (valid) {
+      const copyData = cloneDeep(CameraSRSData.value);
+      copyData.workspaceId = flattendWorkspaces.value.find(
+        (item) => item.code === CameraSRSData.value.workspaceCode,
+      ).id;
+      delete (copyData as any).workspaceCode;
+      delete (copyData as any).principal;
+      emits('confirm-execute', copyData);
     }
   });
-</script>
+};
 
-<style scoped>
-  .ip-form {
-    width: 768px;
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    align-content: space-around;
-  }
+// const handleTreeSelect = (code: string) => {
+//   const space = flattendWorkspaces.value.find((item) => item.code === code);
+//   CameraSRSData.value.workspaceId = space?.id;
+//   CameraSRSData.value.principal = space?.principal;
+// };
 
-  .pop-footer {
-    position: absolute;
-    right: 24px;
-    bottom: 27px;
-    display: flex;
-    justify-content: flex-end;
+const handleTreeSelect = (node) => {
+  const space = flattendWorkspaces.value.find((item) => item.code === node.value);
+  CameraSRSData.value.workspaceId = space?.id;
+  CameraSRSData.value.principal = space?.principal;
+  if (node.disabled && node.children.length < 1) {
+    ElMessage.error('请先添加工位');
   }
+};
 
-  :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;
+onBeforeMount(() => {
+  getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
+  if (props.formData) {
+    CameraSRSData.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>

+ 2 - 0
src/views/cameras/overview/type.ts

@@ -85,6 +85,8 @@ export interface CameraShareItem {
 }
 
 export interface CameraSRS {
+  /** 相机IP */
+  cameraIp: string;
   name: string;
   /** 相机ID */
   code: string;