浏览代码

feat(components): 添加“数据选择”组件

wangshun 1 月之前
父节点
当前提交
1766764879
共有 1 个文件被更改,包括 358 次插入0 次删除
  1. 358 0
      src/components/DataSelection.vue

+ 358 - 0
src/components/DataSelection.vue

@@ -0,0 +1,358 @@
+<script setup lang="ts">
+import { ref } from 'vue';
+import { message } from 'ant-design-vue';
+
+import { useRequest } from '@/hooks/request';
+import { useViewVisible } from '@/hooks/view-visible';
+import { getDeviceGroupList, getDeviceListSimple, queryDevicesList } from '@/api';
+
+import type { DataSelection, DeviceGroup, DeviceParams, DevicesListItem } from '@/types';
+
+interface Props {
+  form: DataSelection;
+  selectType: number;
+}
+
+const props = defineProps<Props>();
+const { handleRequest } = useRequest();
+const { visible, showView, hideView } = useViewVisible();
+const emit = defineEmits(['confirmClick']);
+const oneDeviceGroup = ref<DeviceGroup[]>([]);
+const twoDeviceGroup = ref<DeviceGroup[]>([]);
+const equipmentList = ref<DevicesListItem[]>([]);
+const parametersList = ref<DeviceParams[]>([]);
+const gradeOne = ref<number | undefined>(undefined);
+const gradeTwo = ref<number | undefined>(undefined);
+const equipmentId = ref<number | undefined>(undefined);
+const equipmentName = ref<string>('');
+const parametersId = ref<number | undefined>(undefined);
+const parametersCode = ref<string>('');
+const parametersName = ref<string>('');
+
+const addAllGatewayList = (value: number) => {
+  handleRequest(async () => {
+    const data = await getDeviceGroupList({
+      parentId: value,
+    });
+
+    if (value === -1) {
+      oneDeviceGroup.value = data;
+      if (data.length) {
+        if (props.form.groupId) {
+          gradeOne.value = props.form.groupId;
+          addAllGatewayList(props.form.groupId);
+        } else {
+          gradeOne.value = data[0].id;
+          addAllGatewayList(data[0].id);
+        }
+      } else {
+        twoDeviceGroup.value = [];
+        gradeTwo.value = undefined;
+      }
+    } else {
+      twoDeviceGroup.value = data;
+      if (data.length) {
+        if (props.form.childGroupId) {
+          gradeTwo.value = props.form.childGroupId;
+          getEquipmentList(props.form.childGroupId);
+        } else {
+          gradeTwo.value = data[0].id;
+          getEquipmentList(data[0].id);
+        }
+      } else {
+        parametersList.value = [];
+        equipmentId.value = undefined;
+        equipmentName.value = '';
+      }
+    }
+  });
+};
+
+const getEquipmentList = (id: number) => {
+  handleRequest(async () => {
+    const { records } = await queryDevicesList({
+      pageIndex: 1,
+      pageSize: 99999,
+      groupId: id,
+    });
+    equipmentList.value = records;
+    if (records.length) {
+      if (props.form.deviceId) {
+        equipmentId.value = props.form.deviceId;
+        records.forEach((item) => {
+          if (item.id === props.form.deviceId) {
+            equipmentName.value = item.deviceName;
+          }
+        });
+        getParameters(props.form.deviceId);
+      } else {
+        equipmentId.value = records[0].id;
+        equipmentName.value = records[0].deviceName;
+        getParameters(records[0].id);
+      }
+    } else {
+      parametersList.value = [];
+      parametersId.value = undefined;
+      parametersCode.value = '';
+      parametersName.value = '';
+    }
+  });
+};
+
+const getParameters = (id: number) => {
+  handleRequest(async () => {
+    parametersList.value = await getDeviceListSimple(id);
+    if (parametersList.value.length) {
+      if (props.form.paramCode) {
+        parametersList.value.forEach((item) => {
+          if (item.deviceParamCode === props.form.paramCode) {
+            parametersId.value = item.id;
+            parametersCode.value = item.deviceParamCode;
+            parametersName.value = item.deviceParamName;
+          }
+        });
+      } else {
+        parametersId.value = parametersList.value[0].id;
+        parametersCode.value = parametersList.value[0].deviceParamCode;
+        parametersName.value = parametersList.value[0].deviceParamName;
+      }
+    }
+  });
+};
+
+const addParameters = (id: number, index: number) => {
+  if (index === 1) {
+    gradeOne.value = id;
+    addAllGatewayList(id);
+  } else if (index === 2) {
+    gradeTwo.value = id;
+    getEquipmentList(id);
+  }
+};
+
+const chooseEquipment = (item: DevicesListItem) => {
+  equipmentId.value = item.id;
+  equipmentName.value = item.deviceName;
+  getParameters(item.id);
+};
+
+const chooseParameters = (item: DeviceParams) => {
+  parametersId.value = item.id;
+  parametersCode.value = item.deviceParamCode;
+  parametersName.value = item.deviceParamName;
+};
+
+const okConfirm = () => {
+  if (props.selectType === 0) {
+    if (!parametersId.value) {
+      return message.warning('参数未选择!');
+    }
+  } else if (props.selectType === 1) {
+    if (!equipmentId.value) {
+      return message.warning('下属设备未选择!');
+    }
+  }
+
+  emit('confirmClick', {
+    groupId: gradeOne.value,
+    childGroupId: gradeTwo.value,
+    deviceId: equipmentId.value,
+    deviceName: equipmentName.value,
+    parametersName: parametersName.value,
+    paramCode: parametersCode.value,
+    selectType: props.selectType,
+  });
+};
+defineExpose({
+  showView,
+  hideView,
+  addAllGatewayList,
+});
+</script>
+
+<template>
+  <div>
+    <AModal
+      v-model:open="visible"
+      title="选择参数"
+      @ok="okConfirm"
+      :centered="true"
+      :width="selectType === 0 ? 1070 : 814"
+    >
+      <AFlex class="parameters-content">
+        <div class="content-div">
+          <AFlex align="center" class="content-div-top">
+            <div class="content-div-top-text">设备组一</div>
+          </AFlex>
+          <div class="content-div-content">
+            <AFlex class="no-data" justify="center" align="center" v-if="!oneDeviceGroup.length">暂无数据</AFlex>
+            <div v-else v-for="item in oneDeviceGroup" :key="item.id">
+              <div @click="addParameters(item.id, 1)">
+                <AFlex
+                  justify="space-between"
+                  align="center"
+                  :class="gradeOne === item.id ? 'parameters-dev-bgd' : 'parameters-dev'"
+                >
+                  <div class="parameters-text">{{ item.groupName }}</div>
+                  <div v-if="gradeOne === item.id">
+                    <SvgIcon class="icon-style" name="right" />
+                  </div>
+                </AFlex>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="content-div border-radius">
+          <AFlex align="center" class="content-div-top">
+            <div class="content-div-top-text">设备组二</div>
+          </AFlex>
+          <div class="content-div-content">
+            <AFlex class="no-data" justify="center" align="center" v-if="!twoDeviceGroup.length">暂无数据</AFlex>
+            <div v-else v-for="item in twoDeviceGroup" :key="item.id">
+              <div @click="addParameters(item.id, 2)">
+                <AFlex
+                  justify="space-between"
+                  align="center"
+                  :class="gradeTwo === item.id ? 'parameters-dev-bgd' : 'parameters-dev'"
+                >
+                  <div class="parameters-text">{{ item.groupName }}</div>
+                  <div v-if="gradeTwo === item.id">
+                    <SvgIcon class="icon-style" name="right" />
+                  </div>
+                </AFlex>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div :class="selectType === 0 ? 'content-div border-radius' : 'content-div border-radius border-right'">
+          <AFlex align="center" class="content-div-top">
+            <div class="content-div-top-text">设备组属性/下属设备</div>
+          </AFlex>
+          <div class="content-div-content">
+            <AFlex class="no-data" justify="center" align="center" v-if="!equipmentList.length">暂无数据</AFlex>
+            <div v-else v-for="item in equipmentList" :key="item.id">
+              <div @click="chooseEquipment(item)">
+                <AFlex
+                  justify="space-between"
+                  align="center"
+                  :class="equipmentId === item.id ? 'parameters-dev-bgd' : 'parameters-dev'"
+                >
+                  <div class="parameters-text">{{ item.deviceName }}</div>
+                  <div v-if="equipmentId === item.id && selectType === 0">
+                    <SvgIcon class="icon-style" name="right" />
+                  </div>
+                </AFlex>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div v-if="selectType === 0" class="content-div border-radius border-right">
+          <AFlex align="center" class="content-div-top">
+            <div class="content-div-top-text">参数</div>
+          </AFlex>
+          <div class="content-div-content">
+            <AFlex class="no-data" justify="center" align="center" v-if="!parametersList.length">暂无数据</AFlex>
+            <div v-else v-for="item in parametersList" :key="item.id">
+              <div @click="chooseParameters(item)">
+                <AFlex
+                  justify="space-between"
+                  align="center"
+                  :class="parametersId === item.id ? 'parameters-dev-bgd' : 'parameters-dev'"
+                >
+                  <div class="parameters-text">{{ item.deviceParamName }}</div>
+                </AFlex>
+              </div>
+            </div>
+          </div>
+        </div>
+      </AFlex>
+    </AModal>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.no-data {
+  height: 100%;
+  color: rgb(0 0 0 / 65%);
+}
+
+.parameters-text {
+  font-size: 14px;
+  font-style: normal;
+  font-weight: 400;
+  line-height: 24px;
+  color: rgb(0 0 0 / 65%);
+  text-align: left;
+}
+
+.icon-style {
+  margin-top: 5px;
+  color: #8c94a8;
+}
+
+.parameters-dev {
+  width: 100%;
+  height: 48px;
+  padding: 0 12px 0 16px;
+  margin-top: 8px;
+  cursor: pointer;
+  background: #fff;
+  border-radius: 4px;
+}
+
+.parameters-dev-bgd {
+  width: 100%;
+  height: 48px;
+  padding: 0 12px 0 16px;
+  margin-top: 8px;
+  cursor: pointer;
+  background: rgb(50 186 192 / 15%);
+  border-radius: 4px;
+}
+
+.content-div-content {
+  height: 375px;
+  padding: 0 8px;
+  overflow: hidden;
+  overflow: hidden auto; /* 隐藏水平滚动条 */ /* 只显示垂直滚动条 */
+}
+
+.content-div-top-text {
+  font-size: 14px;
+  font-style: normal;
+  font-weight: 600;
+  line-height: 24px;
+  color: #000;
+  text-align: left;
+}
+
+.content-div-top {
+  height: 56px;
+  padding-left: 24px;
+  background: #f5f6f7;
+  border-radius: 4px 0 0;
+}
+
+.content-div {
+  width: 256px;
+  height: 436px;
+  background: #fff;
+  border: 1px solid #e4e7ed;
+  border-right: none;
+  border-radius: 4px 0 0 4px;
+}
+
+.border-radius {
+  border-radius: 0;
+}
+
+.border-right {
+  border-right: 1px solid #e4e7ed;
+  border-radius: 0 4px 4px 0;
+}
+
+.parameters-content {
+  height: 470px;
+  padding-top: 16px;
+}
+</style>