src/components/SideList.vue
@@ -1,36 +1,153 @@
<template>
  <el-tree
    class="el-tree"
    v-loading="isLoading"
    :data="dataList"
    :props="defaultProps"
    @node-click="handleNodeClick"
    default-expand-all
    highlight-current
    check-on-click-node
    empty-text="暂无记录"
  >
    <template #default="{ node, data }">
      <div
        :class="
          data.selected
            ? 'selected-tree-node custom-tree-node'
            : 'custom-tree-node'
        "
      >
        <el-icon v-if="data.type == 2" color="var(--el-color-success)"
          ><SuccessFilled
        /></el-icon>
        <el-icon v-else-if="data.type == 1" color="var(--el-color-warning)"
          ><WarningFilled
        /></el-icon>
        <el-icon v-else-if="data.type == 0" color="var(--el-color-danger)"
          ><WarningFilled
        /></el-icon>
        <div>{{ node.label }}</div>
      </div>
    </template>
  </el-tree>
  <div style="padding-right: 10px;">
    <div v-if="legend" class="state-label">
      <el-input
        v-model="filterText"
        icon="Search"
        style="width: 180px"
        placeholder="关键字筛选"
        clearable
      />
      <el-tooltip placement="bottom-start" effect="dark">
        <template #content>
          <el-space>
            <el-space
              v-for="(item, index) in stateLabels"
              :key="index"
              :size="1"
            >
              <el-icon :color="item.color">
                <component :is="item.icon"></component>
              </el-icon>
              {{ item.name }}
              <!-- <el-text size="small">{{ item.name }}</el-text> -->
            </el-space>
          </el-space>
          <br />
          <el-space>
            <el-space :size="1">
              <el-icon :size="16" color="var(--el-color-success)">
                <Avatar />
              </el-icon>
              正在执行巡查
            </el-space>
            <el-space :size="1">
              <el-icon :size="16" color="var(--el-color-info)">
                <Avatar />
              </el-icon>
              未执行
            </el-space>
          </el-space>
        </template>
        <el-space>
          <el-icon class="cursor-p" :size="16" color="var(--el-color-primary)"
            ><QuestionFilled
          /></el-icon>
          <el-text size="small" class="cursor-p">审核状态图例</el-text>
        </el-space>
      </el-tooltip>
    </div>
    <el-tree
      ref="treeRef"
      class="el-tree"
      v-loading="isLoading"
      :data="dataList"
      :props="defaultProps"
      @node-click="handleNodeClick"
      :filter-node-method="filterNode"
      default-expand-all
      highlight-current
      check-on-click-node
      empty-text="暂无记录"
    >
      <template #default="{ node, data }">
        <slot :node="node" :data="data">
          <div
            :class="
              data.selected
                ? 'selected-tree-node custom-tree-node'
                : 'custom-tree-node'
            "
          >
            <el-icon
              v-if="data.status == '正在执行'"
              :size="16"
              color="var(--el-color-success)"
              style="margin-left: -16px"
            >
              <Avatar />
            </el-icon>
            <el-icon
              v-if="data.status == '未执行'"
              :size="16"
              color="var(--el-color-info)"
              style="margin-left: -16px"
            >
              <Avatar />
            </el-icon>
            <!-- <el-icon :color="stateLabels[data.type].color">
            <component :is="stateLabels[data.type].icon"></component>
          </el-icon> -->
            <el-icon
              v-if="data.type == 0"
              :size="16"
              color="var(--el-color-info)"
            >
              <SuccessFilled />
            </el-icon>
            <el-icon
              v-else-if="data.type == 1"
              :size="16"
              color="var(--el-color-danger)"
            >
              <QuestionFilled />
            </el-icon>
            <el-icon
              v-else-if="data.type == 2"
              :size="16"
              color="var(--el-color-warning)"
            >
              <QuestionFilled />
            </el-icon>
            <el-icon
              v-else-if="data.type == 3"
              :size="16"
              color="var(--el-color-danger)"
            >
              <WarnTriangleFilled />
            </el-icon>
            <el-icon
              v-else-if="data.type == 4"
              :size="16"
              color="var(--el-color-danger)"
            >
              <WarningFilled />
            </el-icon>
            <el-icon
              v-else-if="data.type == 5"
              :size="16"
              color="var(--el-color-warning)"
            >
              <WarningFilled />
            </el-icon>
            <el-icon
              v-else-if="data.type == 6"
              :size="16"
              color="var(--el-color-success)"
            >
              <SuccessFilled />
            </el-icon>
            <!-- <el-text>{{ node.label }}</el-text> -->
            {{ node.label }}
            <span v-if="data.count">
              {{ '_(' + data.count + ')' }}
              <!-- <el-text size="small">点次</el-text>) -->
            </span>
          </div>
        </slot>
      </template>
    </el-tree>
  </div>
</template>
<script>
@@ -43,20 +160,63 @@
          type: 0,
          title: 'title',
          categoly: '2022-10-10',
          data: {},
        },
      ],
          data: {}
        }
      ]
    },
    loading: Boolean,
    // 是否展示图例
    legend: {
      type: Boolean,
      default: false
    }
  },
  emits: ['itemClick'],
  data() {
    return {
      filterText: '',
      defaultProps: {
        children: 'children',
        label: 'title',
        label: 'title'
      },
      isLoading: this.loading,
      stateLabels: [
        {
          color: 'var(--el-color-info)',
          name: '无问题',
          icon: 'SuccessFilled'
        },
        {
          color: 'var(--el-color-danger)',
          name: '问题未审核',
          icon: 'QuestionFilled'
        },
        {
          color: 'var(--el-color-warning)',
          name: '问题部分审核',
          icon: 'QuestionFilled'
        },
        {
          color: 'var(--el-color-danger)',
          name: '未整改',
          icon: 'WarnTriangleFilled'
        },
        {
          color: 'var(--el-color-danger)',
          name: '整改未审核',
          icon: 'WarningFilled'
        },
        {
          color: 'var(--el-color-warning)',
          name: '整改部分审核',
          icon: 'WarningFilled'
        },
        {
          color: 'var(--el-color-success)',
          name: '审核完成',
          icon: 'SuccessFilled'
        }
      ]
    };
  },
  computed: {
@@ -75,7 +235,8 @@
      for (const [key, value] of itemMap) {
        const i = {
          title: key,
          children: [],
          count: value.length,
          children: []
        };
        value.forEach((v) => {
          i.children.push(v);
@@ -92,51 +253,64 @@
        }
      });
      return list;
    },
    }
  },
  watch: {
    filterText(val) {
      this.$refs.treeRef.filter(val);
    },
    loading(nValue) {
      this.isLoading = nValue
      this.isLoading = nValue;
    },
    //当数据第一次更新时
    dataList(nValue) {
      if (this.isLoading) {
        if (nValue.length > 0) {
          this.dataList.forEach((d) => {
            d.children.forEach((c) => {
              c.selected = false;
            });
          });
          // this.dataList.forEach((d) => {
          //   d.children.forEach((c) => {
          //     c.selected = false;
          //   });
          // });
          if (nValue[0].children.length > 0) {
            const c = nValue[0].children[0];
            c.selected = true;
            // c.selected = true;
            this.$emit('itemClick', c);
          } else {
            nValue[0].selected = true;
            // nValue[0].selected = true;
          }
        }
        this.isLoading = false;
      }
    },
    }
  },
  methods: {
    handleNodeClick(data) {
      this.dataList.forEach((d) => {
        d.children.forEach((c) => {
          c.selected = false;
        });
      });
      data.selected = true;
      // this.dataList.forEach((d) => {
      //   d.children.forEach((c) => {
      //     c.selected = false;
      //   });
      // });
      // data.selected = true;
      //父节点的点击事件不做传递
      if (data.children == undefined) {
        this.$emit('itemClick', data);
      }
    },
  },
    filterNode(value, data) {
      if (!value) return true;
      return data.title.includes(value);
    }
  }
};
</script>
<style lang="scss" scoped>
.el-tree {
  // background-color: aliceblue;
  // width: var(--el-aside-width, 200px)
}
.custom-tree-node {
  display: flex;
  align-items: center;
@@ -144,4 +318,15 @@
.selected-tree-node {
  color: var(--el-color-primary);
}
.state-label {
  position: sticky;
  z-index: 1;
  top: 0;
  background-color: white;
  // box-shadow: var(--el-box-shadow-light);
  border-bottom: var(--el-border);
  display: flex;
  padding-bottom: 4px;
}
</style>