productSpaceManage.vue 7.37 KB
<template>
  <div class="container_wrap">
    <div class="table_tool_wrap">
      <el-button type="primary" @click="newCreate">新增</el-button>
      <el-input v-model.trim="pageInfo.keyWord" placeholder="名称搜索" :suffix-icon="Search" clearable
        @blur="toSearch(true, true)" @keyup.enter.native="searchEnterFun" />
    </div>
    <div class="table_panel_wrap">
      <div v-show="listData.length" class="data-content" v-loading="listDataLoading">
        <div class="card-content" v-for="(item, index) in listData" :key="item.guid" @click="handleDataClick(item)">
          <div class="v-top">
            <span class="title">{{ item.name }}</span>
            <el-tag :type="tagType(item, 'approveState')">{{ tagMethod(item, 'approveState') }}</el-tag>
          </div>
          <div class="v-middle">
            <div class="per">
              <div class="desc">产品数量</div>
              <div class="cnt">{{ item.productNum == null ? '--' : changeNum(item.productNum, 0) }}</div>
            </div>
            <div class="per">
              <div class="desc">成员数量</div>
              <div class="cnt">{{ item.productNum == null ? '--' : changeNum(item.productNum, 0) }}</div>
            </div>
          </div>
          <div class="v-bottom">
            <div class="per" @click.stop="clickDetail(item)">详情</div>
            <div class="divider" @click.stop></div>
            <div class="per" @click.stop="clickDelete(item)">删除</div>
            <!-- TODO 只有审批中才有删除 -->
          </div>
        </div>
      </div>
      <div v-show="!listData.length" class="empty-content">
        <img src="../../assets/images/empty-data.png" :style="{ width: '168px', height: '96px' }" />
        <div class="empty-text">暂无数据</div>
      </div>
    </div>
    <PageNav :class="[pageInfo.type]" :pageInfo="pageInfo" @pageChange="pageChange" />
  </div>
</template>
<script setup lang="ts" name="productSpaceManage">
import { commonPageConfig } from '@/components/PageNav';
import { changeNum, tagMethod, tagType } from '@/utils/common';
import { Search } from "@element-plus/icons-vue";

const router = useRouter();
const { proxy } = getCurrentInstance() as any;

/** 卡片加载条 */
const listDataLoading = ref(false);
/** 列表数据 */
const listData: any = ref([{ guid: '1', name: '产品空间1' }, { guid: '2', name: '产品空间1' }, { guid: '3', name: '产品空间1' }, { guid: '4', name: '产品空间1' },
{ guid: '5', name: '产品空间1' }
]);

const oldKeyWord = ref(""); // 记录上次输入的关键字,避免重复搜索
const isEnter = ref(false); // 标识是否通过回车键触发搜索

const pageInfo = ref({
  ...commonPageConfig,
  rows: 0,
  type: "normal",
  keyWord: '',
});

const getTableData = (clear = false) => {
  // listDataLoading.value = true;
  // getDamCatalogTable({
  //   pageSize: pageInfo.value.limit,
  //   pageIndex: pageInfo.value.curr,
  //   keyWord: pageInfo.value.keyWord
  // }).then((res: any) => {
  //   listDataLoading.value = false;
  //   if (res.code == proxy.$passCode) {
  //     const data = res.data || {}
  //     listData.value = data.records || [];
  //     pageInfo.value.limit = data.pageSize
  //     pageInfo.value.curr = data.pageIndex
  //     pageInfo.value.rows = data.totalRows
  //   } else {
  //     proxy.$ElMessage.error(res.msg);
  //   }
  // });
}

const pageChange = (info) => {
  pageInfo.value.curr = Number(info.curr);
  pageInfo.value.limit = Number(info.limit);
  getTableData();
};

/**
 * 触发搜索查询
 * @param clear - 是否清空页码,默认为true
 * @param isBlur - 是否是失焦触发,默认为false
 */
const toSearch = (clear: boolean = true, isBlur: boolean = false) => {
  if (clear) {
    pageInfo.value.curr = 1 // 重置为第一页
  }
  // 如果是失焦且不是回车触发,且关键词没有变化,则不执行搜索
  if (isBlur && !isEnter.value && oldKeyWord.value === pageInfo.value.keyWord) {
    return;
  }
  isEnter.value = false; // 重置回车状态
  oldKeyWord.value = pageInfo.value.keyWord; // 更新关键词记录
  getTableData(clear);
}

/**
 * 回车搜索事件处理
 * 在输入框按下回车键时触发
 * @param event - 键盘事件对象
 */
const searchEnterFun = (event) => {
  isEnter.value = true; // 标记为回车触发
  event.target?.blur(); // 输入框失去焦点
}

const newCreate = () => {
  router.push({
    name: 'productSpaceEdit'
  })
}

const handleDataClick = (item) => {
  router.push({
    name: 'productSpaceEdit',
    query: {
      guid: item.guid,
      name: item.name
    }
  })
}

const clickDetail = (item) => {
  router.push({
    name: 'productSpaceDetail',
    query: {
      guid: item.guid,
      name: item.name
    }
  })
}

const clickDelete = (item) => {
  proxy.$openMessageBox('此操作将永久删除该空间,是否继续?', () => {
    // TODO
  }, () => {
    proxy.$ElMessage.info('已取消删除');
  });
}

</script>

<style lang="scss" scoped>
.container_wrap {
  padding: 0 16px;
}

.table_tool_wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 12px;

  .el-input {
    width: 240px;
  }
}

.table_panel_wrap {
  height: calc(100% - 94px);
  margin-top: 12px;
  position: relative;

  .data-content {
    display: flex;
    flex-wrap: wrap;
    gap: 16px 16px;
    align-content: flex-start;
    overflow-y: auto;

    .card-content {
      width: calc(25% - 13px);
      min-width: 220px;
      height: 174px;
      border: 1px solid rgba(229, 229, 229, 1);
      border-radius: 4px;
      cursor: pointer;
      position: relative;

      &:hover {
        border-color: var(--el-color-primary);
      }

      .v-top {
        height: 48px;
        padding: 12px 16px;
        display: flex;

        .title {
          font-size: 16px;
          color: #212121;
          line-height: 24px;
          font-weight: 600;
          width: calc(100% - 58px);
          white-space: nowrap;
          /* 防止文本换行 */
          overflow: hidden;
          /* 隐藏超出容器的文本 */
          text-overflow: ellipsis;
          /* 显示省略号 */
        }

        .el-tag {
          width: 50px;
          text-align: center;
          line-height: 18px;
        }
      }

      .v-middle {
        height: 80px;
        display: flex;

        .per {
          width: 50%;
          height: 100%;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;

          .desc {
            font-size: 14px;
            color: #999999;
            line-height: 21px;
            margin-bottom: 4px;
          }

          .cnt {
            font-size: 24px;
            color: #44ABB4;
            line-height: 36px;
            font-weight: 600;
          }
        }
      }

      .v-bottom {
        background: #FAFAFA;
        height: 44px;
        display: flex;
        border-top: 1px solid rgba(229, 229, 229, 1);

        .divider {
          border-right: 1px solid rgba(229, 229, 229, 1);
        }

        .per {
          width: 50%;
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 8px 0px;
        }
      }
    }
  }
}

.empty-content {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
  flex-direction: column;

  .empty-text {
    font-size: 14px;
    color: #b2b2b2;
    margin-top: 12px;
  }
}
</style>