productSpaceManage.vue 9.45 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" v-loading="listDataLoading">
      <div v-show="listData.length" class="data-content">
        <div class="card-content" v-for="(item, index) in listData" :key="item.guid" @click="handleDataClick(item)">
          <div class="v-top">
            <span class="title">{{ item.spaceName }}</span>
            <el-tag :type="tagType(item, 'bizApproveState')">{{ tagMethod(item, 'bizApproveState') }}</el-tag>
          </div>
          <div class="v-middle">
            <div class="per">
              <div class="desc">产品数量</div>
              <div class="cnt">{{ item.damCount == null ? '--' : changeNum(item.damCount, 0) }}</div>
            </div>
            <div class="per">
              <div class="desc">成员数量</div>
              <div class="cnt">{{ item.memberCount == null ? '--' : changeNum(item.memberCount, 0) }}</div>
            </div>
          </div>
          <div class="v-bottom">
            <template v-if="item.bizApproveState == 'N'">
              <div class="per" @click.stop="clickEdit(item)">编辑</div>
              <div class="divider" @click.stop></div>
              <div class="per" @click.stop="clickDelete(item)">删除</div>
            </template>
            <template v-else-if="item.bizApproveState == 'A'">
              <div class="per" @click.stop="clickDetail(item)">详情</div>
              <div class="divider" @click.stop></div>
              <div class="per" style="cursor: default;">--</div>
            </template>
            <template v-else>
              <div class="per" @click.stop="clickDetail(item)">详情</div>
              <div class="divider" @click.stop></div>
              <div class="per" @click.stop="clickDelete(item)">删除</div>
            </template>
            <!-- 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";
import { getLogicSpacePageList, deleteLogicSpace } from '@/api/modules/dataAsset';
import useDataProductSpaceStore from "@/store/modules/productSpace";

const productSpaceStore = useDataProductSpaceStore();

const router = useRouter();
const { proxy } = getCurrentInstance() as any;
const userData = JSON.parse(localStorage.userData);

/** 卡片加载条 */
const listDataLoading = ref(false);
/** 列表数据 */
const listData: any = ref([]);

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

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

const getTableData = (clear = false) => {
  listDataLoading.value = true;
  getLogicSpacePageList({
    pageSize: pageInfo.value.limit,
    pageIndex: pageInfo.value.curr,
    spaceName: 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) => {
  let approveState = item.bizApproveState;
  if (approveState == 'A' || approveState == 'Y') { //通过或审批中,点进去是详情
    router.push({
      name: 'productSpaceDetail',
      query: {
        guid: item.guid,
        name: item.spaceName
      }
    })
    return;
  }
  const staffGuid = item.createUserId || '';
  let currentStaffGuid = userData.tenantGuid;
  // 如果是驳回等状态,是自己创建的可以编辑。
  if ((approveState == 'C' || approveState == 'E' || approveState == 'R')) {
    router.push({
      name: staffGuid == currentStaffGuid ? 'productSpaceEdit' : 'productSpaceDetail',
      query: {
        guid: item.guid,
        name: item.spaceName
      }
    })
    return;
  }
  router.push({
    name: 'productSpaceEdit',
    query: {
      guid: item.guid,
      name: item.spaceName
    }
  })
}

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

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

const clickDelete = (item) => {
  proxy.$openMessageBox('此操作将永久删除该逻辑空间,是否继续?', () => {
    deleteLogicSpace([item.guid]).then((res: any) => {
      if (res?.code == proxy.$passCode) {
        proxy.$ElMessage.success('删除成功');
        pageInfo.value.curr = 1;
        getTableData();
      } else {
        res?.msg && proxy.$ElMessage.error(res.msg);
      }
    })
  }, () => {
    proxy.$ElMessage.info('已取消删除');
  });
}

onActivated(() => {
  if (productSpaceStore.isRefresh) {
    pageInfo.value.keyWord = '';
    pageInfo.value.curr = 1;
    getTableData();
    productSpaceStore.setIsRefresh(false);
  }
})

onBeforeMount(() => {
  pageInfo.value.keyWord = '';
  pageInfo.value.curr = 1;
  getTableData();
})

</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>