index.vue 8.46 KB
<template>
  <div class="table-content">
    <table align="center" style="width: 100%" cellspacing="0">
      <thead>
        <tr>
          <th></th>
          <th>Key</th>
          <th>Value</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(item, index) in tableArray.content" :key="index">
          <td>
            {{ index + 1 }}
          </td>
          <td>
            <Select
              v-model:value="item.key"
              placeholder="请选择"
              notFoundContent="请选择"
              style="width: 14rem"
              :options="selectOptions"
              @change="handleChange(item)"
              allowClear
            />
          </td>
          <td>
            <a-input
              v-if="item.key === 'scope'"
              placeholder="请输入"
              v-model:value="item.value"
              style="width: 14rem"
            />
            <a-tree-select
              v-else-if="item.key === 'organizationId'"
              v-model:value="item.value"
              show-search
              style="width: 14rem"
              :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
              placeholder="请选择组织"
              allow-clear
              tree-default-expand-all
              :tree-data="treeData"
              @change="handleOrgnationChange(item)"
            />
            <Select
              v-else-if="item.key === 'entityId'"
              v-model:value="item.value"
              placeholder="请选择"
              notFoundContent="请选择"
              style="width: 14rem"
              :options="entityOptions"
              allowClear
            />
            <Select
              v-else-if="item.key === 'keys'"
              v-model:value="item.value"
              placeholder="请选择"
              notFoundContent="请选择"
              style="width: 14rem"
              :options="attributeOptions"
              allowClear
            />
            <Select
              v-else
              v-model:value="item.value"
              placeholder="请选择"
              notFoundContent="请选择"
              style="width: 14rem"
              :options="valueOptions"
              allowClear
              @change="handleValueChange(item)"
            />
          </td>
          <td>
            <div>
              <Button type="dashed" @click="add(index)">
                <template #icon><PlusOutlined /></template
              ></Button>
              <Button type="dashed" style="margin-left: 5px" @click="remove(item, index)">
                <template #icon> <MinusOutlined /></template>
              </Button>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script lang="ts" setup name="editCellTable">
  import { reactive, ref, onMounted } from 'vue';
  import { Select, Button } from 'ant-design-vue';
  import { findDictItemByCode } from '/@/api/system/dict';
  import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue';
  import { getAllDeviceByOrg } from '/@/api/dataBoard';
  import { getDeviceAttributes } from '/@/api/dataBoard';
  import { useApi } from '../../hooks/useApi';
  import { buildUUID } from '/@/utils/uuid';

  const props = defineProps({
    method: {
      type: String,
    },
  });

  onMounted(async () => {
    const res = await findDictItemByCode({ dictCode: 'dataview_builtin_params' });
    selectOptions.value = res.map((m) => ({ label: m.itemText, value: m.itemValue }));
    selectOptions.value.push({
      label: '自定义',
      value: 'scope',
    });
    if (props.method === '2')
      selectOptions.value = selectOptions.value.filter((f) => f.value !== 'scope');
  });

  const selectOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]);

  const valueOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]);

  const entityOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]);

  const attributeOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]);

  const treeData = ref([]);

  type defaultItem = {
    id: string;
    key: null | string;
    value: null | string;
    editDisabled: boolean;
  };

  const tableArray = reactive<{
    content: defaultItem[];
  }>({
    content: [
      {
        id: buildUUID(),
        key: null,
        value: null,
        editDisabled: false,
      },
    ],
  });

  // 新增
  const add = (index: number) => {
    tableArray.content.splice(index + 1, 0, {
      id: buildUUID(),
      key: null,
      value: null,
      editDisabled: false,
    });
  };

  // 减少
  const remove = (item, index: number) => {
    if (item.key === 'organizationId') {
      entityOptions.value.length = 0;
      tableArray.content.forEach((f) => {
        if (f.key === 'entityId') {
          f.value = null;
        }
      });
    }
    if (item.key === 'deviceProfileId') {
      attributeOptions.value.length = 0;
      tableArray.content.forEach((f) => {
        if (f.key === 'keys') {
          f.value = null;
        }
      });
    }
    if (tableArray.content.length !== 1) {
      selectOptions.value.forEach((ele) => {
        if (ele.value == item.key) {
          ele.disabled = false;
        }
      });
      tableArray.content.splice(index, 1);
    }
  };

  //Select互斥
  const handleChange = async (e) => {
    selectOptions.value.forEach((ele) => {
      ele.disabled = false;
      tableArray.content.forEach((element) => {
        if (element.key === e.key && element.key !== 'scope') {
          element.value = null;
        }
        if (element.key === ele.value && element.key !== 'scope') {
          ele.disabled = true;
        }
      });
    });
    //获取对应项
    if (e.key === 'deviceProfileId') {
      const { options } = await useApi(e.key);
      valueOptions.value = options;
    } else if (e.key === 'organizationId') {
      const { options } = await useApi(e.key);
      treeData.value = options as any;
    } else if (e.key === 'entityId') {
      const getOrganizationIds = tableArray.content
        .map((f) => {
          if (f.key === 'organizationId') {
            return f.value;
          }
        })
        .filter(Boolean);
      if (getOrganizationIds.length === 0) return;
      getEntityOptions(getOrganizationIds?.at(-1));
    } else if (e.key === 'keys') {
      const getIds = tableArray.content
        .map((f) => {
          if (f.key === 'deviceProfileId') {
            return f.value;
          }
        })
        .filter(Boolean);
      if (getIds.length === 0) return;
      getAttributeOptions({ deviceProfileId: getIds?.at(-1) });
    } else if (e.key === 'date') {
      valueOptions.value = [];
    }
  };

  const handleOrgnationChange = async (e) => {
    tableArray.content.forEach((f) => {
      if (f.key === 'entityId') {
        f.value = null;
      }
    });
    getEntityOptions(e.value);
  };

  const getEntityOptions = async (organizationId: string, deviceProfileId?: string) => {
    const res = await getAllDeviceByOrg(organizationId, deviceProfileId);
    entityOptions.value = res.map((item) => ({
      label: item.name,
      value: item.tbDeviceId,
    }));
  };

  const getAttributeOptions = async (params) => {
    const res = await getDeviceAttributes(params);
    if (Object.keys(res).length === 0) return (attributeOptions.value.length = 0);
    attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier }));
  };

  const handleValueChange = (e) => {
    if (e.key === 'deviceProfileId') {
      tableArray.content.forEach((f) => {
        if (f.key === 'keys') {
          f.value = null;
        }
      });
      getAttributeOptions({ deviceProfileId: e.value });
    }
  };

  //获取数据
  const getValue = () => {
    return tableArray.content;
  };
  defineExpose({
    getValue,
  });
</script>

<style scoped lang="less">
  @table-color: #e5e7eb;

  .table-border-color {
    border: 1px solid #e5e7eb;
    text-align: center;
  }

  .table-content {
    table {
      &:extend(.table-border-color);
    }

    table td {
      padding: 5px;
      white-space: nowrap;
      &:extend(.table-border-color);
    }

    table th {
      padding: 5px;
      &:extend(.table-border-color);
    }
  }
</style>