zhudie пре 2 година
родитељ
комит
d99c912013

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

@@ -37,6 +37,7 @@
     <AddCamera class="add-popover" v-model="showAddPopover" />
     <EditCamera class="add-popover" v-model="showEditPopover" :edit-data="editCameraData" />
     <ShareCamera class="add-popover" v-model="addSharedPopover" :share-data="shareCameraData" />
+    <EditSharedCamera class="add-popover" v-model="showSharedPopover" />
   </div>
 </template>
 
@@ -49,6 +50,7 @@
   import AddCamera from './components/CameraAddPopover.vue';
   import ShareCamera from './components/CameraSharePopover.vue';
   import EditCamera from './components/CameraEditPopover.vue';
+  import EditSharedCamera from './components/CameraSharedEdit.vue';
   import emptyImg from '@/assets/images/table/table-empty.png';
   import { Plus } from '@element-plus/icons-vue';
   import shareIcon from '@/assets/images/table/table-share.png';

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

@@ -0,0 +1,103 @@
+<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(false)"><Close /></el-icon>
+      </div>
+    </template>
+    <div class="pop-content flex justify-center items-center">
+      <EditSharedCamera
+        @cancel-execute="updateValue(false)"
+        @confirm-execute="onAddCamera"
+        :form-data="props.editData"
+      />
+      <!-- <RangeAddCamera v-if="addType === 'ipRange'" @cancel-execute="updateValue(false)" /> -->
+    </div>
+  </el-card>
+</template>
+
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import { CameraSharedItem, cameraAddType } from '../constant';
+  import { Close } from '@element-plus/icons-vue';
+  import EditSharedCamera from './EditSharedCamera.vue';
+  import RangeAddCamera from './AddCameraByRange.vue';
+  import useCameraOverview from '../stores/useCameraOverview';
+  import { emit } from 'process';
+
+  const props = defineProps<{ modelValue: boolean; editData: CameraSharedItem }>();
+
+  const emits = defineEmits(['update:modelValue', 'updateData']);
+
+  const cameraOverview = useCameraOverview();
+  const { addCamera } = cameraOverview;
+
+  const addType = ref(cameraAddType[0].value);
+
+  const updateValue = (value) => {
+    addType.value = cameraAddType[0].value;
+    emits('update:modelValue', value);
+  };
+
+  const onAddCamera = (data) => {
+    // addCamera(data);
+    updateValue(false);
+    emits('updateData', data);
+    // console.log('data', data);
+  };
+</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: 566px;
+  }
+
+  :deep(.el-card__header) {
+    padding: 0;
+  }
+  :deep(.el-card__body) {
+    padding: 0;
+  }
+</style>

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

@@ -0,0 +1,113 @@
+<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>
+        <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" /></div>
+    <!-- <div class="pop-content flex justify-center items-center">
+      <IPAddCamera
+        v-if="addType === 'ip'"
+        @cancel-execute="updateValue(false)"
+        @confirm-execute="onAddCamera"
+      />
+      <RangeAddCamera v-if="addType === 'ipRange'" @cancel-execute="updateValue(false)" />
+    </div> -->
+  </el-card>
+</template>
+
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import { sharedCaremaType } from '../constant';
+  import { Close } from '@element-plus/icons-vue';
+  import SharedTable from './SharedTable.vue';
+  import IPAddCamera from './AddCameraByIP.vue';
+  import RangeAddCamera from './AddCameraByRange.vue';
+  import useCameraOverview from '../stores/useCameraOverview';
+
+  const props = defineProps<{ modelValue: boolean }>();
+
+  const emits = defineEmits(['update:modelValue']);
+
+  const cameraOverview = useCameraOverview();
+  const { addCamera } = cameraOverview;
+
+  const addType = ref(sharedCaremaType[0].value);
+
+  const updateValue = (value) => {
+    addType.value = sharedCaremaType[0].value;
+    emits('update:modelValue', value);
+  };
+
+  const onAddCamera = (data) => {
+    addCamera(data);
+    updateValue(false);
+  };
+</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: 566px;
+  }
+
+  :deep(.el-card__header) {
+    padding: 0;
+  }
+  :deep(.el-card__body) {
+    padding: 0;
+  }
+</style>

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

@@ -0,0 +1,139 @@
+<template>
+  <div>
+    <div style="margin-bottom: 120px">
+      <el-form
+        class="ip-form"
+        :inline="true"
+        :model="cameraIPData"
+        :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="cameraIPData[item.prop]"
+            :placeholder="item.placeholder"
+            style="width: 200px"
+            :type="item.prop === 'password' ? 'password' : ''"
+            :show-password="item.prop === 'password'"
+            :disabled="item.prop === 'principal' && props.formData !== undefined"
+          />
+          <el-select
+            v-if="item.type === 'select'"
+            v-model="cameraIPData[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-tree-select
+            v-if="item.type === 'tree-select'"
+            v-model="cameraIPData[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 { CameraIPItem } from '../type';
+  import { CameraSharedItem, cameraSharedForm } from '../constant';
+  import useSceneInfos from '@/hooks/useSceneInfos';
+  import { cloneDeep } from 'lodash-es';
+
+  const props = defineProps<{ formData?: CameraSharedItem | null }>();
+
+  const emits = defineEmits(['cancel-execute', 'confirm-execute']);
+
+  const sceneInfos = useSceneInfos();
+  const { scenesTree, flattendWorkspaces, getScenesTree } = sceneInfos;
+
+  const cameraIPData = ref<CameraSharedItem>({} as CameraSharedItem);
+
+  const rules = computed(() => {
+    const newRule = {};
+    cameraSharedForm.forEach((item) => {
+      if (item.required) {
+        newRule[item.prop] = item.rule;
+      }
+    });
+    return newRule;
+  });
+
+  const handleCancel = () => {
+    emits('cancel-execute');
+  };
+
+  const handleConfirm = () => {
+    const copyData = cloneDeep(cameraIPData.value);
+    // copyData.workspaceId = flattendWorkspaces.value.find(
+    //   (item) => item.code === cameraIPData.value.workspaceCode,
+    // ).id;
+    // delete (copyData as any).workspaceCode;
+    emits('confirm-execute', copyData);
+  };
+
+  // const handleTreeSelect = (code: string) => {
+  //   cameraIPData.value.workspaceId = flattendWorkspaces.value.find((item) => item.code === code).id;
+  // };
+
+  onBeforeMount(() => {
+    getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
+    if (props.formData) {
+      cameraIPData.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>

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

@@ -0,0 +1,237 @@
+<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="columns"
+        :data-source="props.addCameraType === 'complete' ? cameraCompleted : cameraInCompleted"
+        :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"
+      @update-data="updateData"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { h, onMounted, reactive, ref, computed } from 'vue';
+  import { columns } from '../sharedColumns';
+  import editIcon from '@/assets/images/table/table-edit.png';
+  import deleteIcon from '@/assets/images/table/table-delete.png';
+  import { queryTypeSelect, protocalTypeSelect, CameraSharedItem } from '../constant';
+  import useCameraOverview from '../stores/useCameraOverview';
+  import useSceneInfos from '@/hooks/useSceneInfos';
+  import { storeToRefs } from 'pinia';
+  import { BasicColumn, TableActionIcons, BasicTable } from '@/components/Table';
+  import { Plus } from '@element-plus/icons-vue';
+  import CameraEditshared from '../components/CameraEditshared.vue';
+
+  const props = defineProps<{ addCameraType: string }>();
+
+  const cameraCompleted = ref<CameraSharedItem[]>([
+    {
+      cameraIp: '11133',
+      cameraType: 'haikang',
+      cameraPort: '11',
+      companyAccount: 111,
+      companyName: '1111',
+      code: '3',
+      workshopName: '222',
+      workspaceName: '2233',
+      shareState: 'complete',
+      password: '11',
+      username: '22',
+    },
+  ]);
+  const cameraInCompleted = ref<CameraSharedItem[]>([
+    {
+      cameraIp: '111',
+      cameraType: 'haikang',
+      cameraPort: '11',
+      companyAccount: 111,
+      companyName: '1111',
+      code: '1',
+      workshopName: '222',
+      workspaceName: '2233',
+      shareState: 'incomplete',
+      password: '11',
+      username: '22',
+    },
+    {
+      cameraIp: '11122',
+      cameraType: 'haikang',
+      cameraPort: '11',
+      companyAccount: 111,
+      companyName: '1111',
+      code: '2',
+      workshopName: '222',
+      workspaceName: '2233',
+      shareState: 'incomplete',
+      password: '11',
+      username: '22',
+    },
+  ]);
+
+  const queryName = ref<string>();
+  const queryAccount = ref<string>();
+  const shareEditedPopover = ref<boolean>(false);
+
+  const handleAdd = (row) => {
+    if (props.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!);
+    }
+  };
+
+  const handleEditData = ref<CameraSharedItem>({} as CameraSharedItem);
+  const handleEdit = (row) => {
+    shareEditedPopover.value = true;
+    handleEditData.value = row;
+  };
+  const handleDelete = (_row) => {};
+
+  const updateData = (data) => {
+    console.log(data);
+    if (props.addCameraType === 'complete') {
+      //   const currentData = cameraCompleted.value.find((item) => (item.cameraIp = data.cameraIp));
+      const indexToRemove = cameraInCompleted.value.findIndex(
+        (item) => item.cameraIp === row.cameraIp,
+      );
+      currentData = data;
+    } else {
+    }
+  };
+
+  //操作列
+  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: Plus,
+            onClick: handleAdd.bind(null, record.row),
+          },
+          {
+            label: '编辑',
+            icon: editIcon,
+            onClick: handleEdit.bind(null, record.row),
+          },
+          {
+            label: '删除',
+            icon: deleteIcon,
+            onClick: handleDelete.bind(null, record.row),
+          },
+        ],
+      });
+    },
+  });
+
+  const queryCameraItems = () => {};
+
+  // 重置查询条件
+  const resetSearch = () => {
+    queryName.value = '';
+    queryAccount.value = '';
+    // queryCameraType.value = '';
+    // queryWorkSpace.value = '';
+  };
+
+  //   onMounted(() => {
+  //     getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name' });
+  //   });
+</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>

+ 108 - 3
src/views/cameras/overview/constant.ts

@@ -323,9 +323,7 @@ export const columns: BasicColumn[] = [
     render(record) {
       return h(
         ElTag,
-        {
-          //  record.row.networkingState
-        },
+        {},
         {
           default: () => {
             return record.row.networkingState === 0 ? '连接' : '断开连接';
@@ -336,3 +334,110 @@ export const columns: BasicColumn[] = [
     minWidth: 120,
   },
 ];
+
+export const sharedCaremaType = [
+  {
+    value: 'incomplete',
+    label: '待添加',
+  },
+  {
+    value: 'complete',
+    label: '已添加',
+  },
+];
+
+export const cameraSharedForm: CameraAddFormItem[] = [
+  {
+    label: '名称:',
+    prop: 'name',
+    placeholder: '请输入名称',
+    type: 'input',
+    required: true,
+    rule: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+  },
+  {
+    label: 'IP地址:',
+    prop: 'cameraIp',
+    placeholder: '请输入IP地址',
+    type: 'input',
+    required: true,
+    rule: [{ required: true, message: '请输入IP地址', trigger: 'blur' }],
+  },
+  {
+    label: '端口:',
+    prop: 'cameraPort',
+    placeholder: '请输入端口号',
+    type: 'input',
+    required: true,
+    rule: [{ required: true, message: '请输入端口号', trigger: 'blur' }],
+  },
+  {
+    label: '协议类型:',
+    prop: 'cameraType',
+    placeholder: '请输入协议类型',
+    type: 'select',
+    required: true,
+    option: protocalTypeSelect,
+    rule: [{ required: true, message: '请输入协议类型', trigger: 'blur' }],
+  },
+  {
+    label: '用户名:',
+    prop: 'username',
+    placeholder: '请输入用户名',
+    type: 'input',
+    required: true,
+    rule: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
+  },
+  {
+    label: '场景:',
+    prop: 'workshopName',
+    placeholder: '请输入场景名称',
+    type: 'input',
+    required: true,
+    rule: [{ required: true, message: '请输入场景名称', trigger: 'blur' }],
+  },
+  {
+    label: '密码:',
+    prop: 'password',
+    placeholder: '请输入用户名密码',
+    type: 'input',
+    required: true,
+    rule: [{ required: true, message: '请输入用户名密码', trigger: 'blur' }],
+  },
+  {
+    label: '企业账号:',
+    prop: 'companyAccount',
+    placeholder: '请输入企业账号',
+    type: 'input',
+    required: false,
+  },
+  {
+    label: '设备ID号:',
+    prop: 'code',
+    placeholder: '自定义ID,不能重复',
+    type: 'input',
+    required: true,
+    rule: [{ required: true, message: '请输入设备ID号', trigger: 'blur' }],
+  },
+  {
+    label: '企业名称:',
+    prop: 'companyName',
+    placeholder: '请输入企业名称',
+    type: 'input',
+    required: false,
+  },
+];
+
+export interface CameraSharedItem {
+  cameraIp: string; //ip地址
+  cameraType: string; //协议类型
+  cameraPort: string; //端口地址
+  companyAccount: number; //企业账号
+  companyName: string; //企业名称
+  code: string; //设备ID
+  workshopName: string; //车间场景
+  workspaceName: string; //工位场景
+  shareState: string; //是否添加
+  password?: string; //密码
+  username?: string; //用户名
+}

+ 62 - 0
src/views/cameras/overview/sharedColumns.ts

@@ -0,0 +1,62 @@
+import { h } from 'vue';
+import type { BasicColumn } from '@/components/Table';
+import { protocalTypeSelect } from './constant';
+
+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: () =>
+            protocalTypeSelect.find((item) => item.value === record.row.cameraType)?.label,
+        },
+      );
+    },
+  },
+  {
+    label: '端口地址',
+    prop: 'cameraPort',
+    minWidth: 120,
+  },
+  {
+    label: '企业账号',
+    prop: 'companyAccount',
+    minWidth: 140,
+  },
+  {
+    label: '企业名称',
+    prop: 'companyName',
+    minWidth: 140,
+  },
+  {
+    label: '设备ID',
+    prop: 'code',
+    minWidth: 150,
+  },
+  {
+    label: '车间场景',
+    prop: 'workshopName',
+    minWidth: 140,
+  },
+  {
+    label: '工位场景',
+    prop: 'workspaceName',
+    minWidth: 140,
+  },
+];