Organization.nvue 7.61 KB
<template>
  <view class="inspection">
    <view class="organization">
      <uv-input :placeholder="t('app.common.search')" prefixIcon="search" prefixIconStyle="font-size: 46rpx;color: #333333" border="none"
        placeholderStyle="color:#90949D;font-size:26rpx" clearable
        style="background-color: #fff;height: 68rpx;flex: none;margin-top: 16rpx;padding: 0 24rpx;"
        v-model="searchVal"></uv-input>
    </view>

    <view class="i-o-content" v-if="displayList.length>0 && !searchVal">
      <view class="tag_title">
        <text v-for="(levelId, levelIndex) in levelList" :key="levelId" class="tag_title_text"
          @tap="handleBackLevel(levelIndex)">
          {{ getLevelText(levelId) }}
        </text>
      </view>
      <view class="v-l">
        <view v-for="item in displayList" :key="item.type + item.id">
          <view class="v-l-item" v-if="item.type !== 'store'">
            <image class="v-l-item-img" :src="renderDisplayImage(item)" mode=""></image>
            <view class="v-l-item-text">
              <text class="overflow" style="font-size: 28rpx;">{{item.name}}</text>
              <text v-if="item.type !== 'store'" style="font-size: 28rpx;"> ({{ item.mallNum }})</text>
            </view>
            <view class="v-l-item-next" v-if="item.children && item.children.length >0" @tap.stop="toNext(item)">
              <image class="v-l-item-next-img" src="/static/tabbar/next.png" mode=""></image>
              <text class="v-l-item-next-text" style="font-size: 28rpx;">{{ t('app.common.nextLevel') }}</text>
            </view>
          </view>
          <view class="v-l-store" v-if="item.type === 'store'">
            <StoreItem :item="item"></StoreItem>
          </view>
        </view>
      </view>
    </view>
    <view class="store-list" style="padding: 0 20rpx;" v-else-if="showMallList.length>0">
      <StoreItem v-for="sItem in showMallList" :key="sItem.id" :item="sItem" style="margin-bottom: 16rpx;"></StoreItem>
    </view>
    <view class="p-empty" v-else style="margin-top: 280rpx;">
      <image class="p-empty-img" v-if="!searchVal" src="/static/common/empty.png" mode=""></image>
      <image class="p-empty-img" v-else src="/static/common/no-result.png" mode=""></image>
      <text class="p-empty-text">{{ searchVal?t('app.common.noFilterData'):t('maintenance.monitor.project.empty.text') }}</text>
    </view>
  </view>
</template>
<script setup>
  import {
    onMounted,
    computed,
    ref
  } from 'vue';
  import {
    doMonitorGroupApi
  } from '@/api';
  import {
    getStageObj
  } from '@/utils'
  import accountImg from '@/static/tabbar/account.png'
  import storeImg from '@/static/tabbar/store.png'
  import moreImg from '@/static/tabbar/more.png'
  import levelImg from '@/static/tabbar/level.png'
  import StoreItem from './components/StoreItem.vue';
  import {
    t
  } from '@/plugins/index.js'
  
  onMounted(() => {
    getMallList()
  })


  const mallList = ref([])
  const mallMap = ref({})
  
  const resourceData = ref([])
  const showMallList = computed(() => {
    if (searchVal.value) {
      return resourceData.value.filter(item => {
        if (item.name.includes(searchVal.value)) {
          return true
        } else {
          return false
        }
      })
    } else {
      return resourceData.value
    }
  })
  const getMallList = async () => {
    try {
      const account = getStageObj('account')?.id
      const params = {
        accountId: account
      }
      const res = await doMonitorGroupApi(params)
      if (res.code === 200) {
        mallMap.value = {}
        mallList.value = formatMallListAndMap(res.data ? [res.data] : [])
        console.log(resourceData.value);
      }

    } catch (e) {
      console.log(e);
    }
  }
  // 格式化源数据
  
  const formatMallListAndMap = (list) => {
    return list?.map(el => {
      const children = [...(el.subGroups || []), ...(el.malls || [])]

      const formatChildren = children.length > 0 ? formatMallListAndMap(children) : []
      const params = {
        ...el,
        type: el.unid ? 'account' : el.groupId ? 'store' : 'group',
        children: formatChildren
      }
      if(params.type === 'store'){
        resourceData.value.push(params)
      }
      if (params.type !== 'store') {
        mallMap.value[`${params.type}_${params.id}`] = params
      }
      return params
    })
  }

  // 到下一级
  const toNext = (item) => {
    levelList.value.push(`${item.type}_${item.id}`)
  }
  // 返回上层数据结构
  const handleBackLevel = (levelIndex) => {
    levelList.value.splice(levelIndex + 1)
  }
  const getLevelText = (id) => {
    if (id === -1) {
      return t('app.title.enterprise')
    }
    return ` / ${mallMap.value[id]?.name}`
  }

  // 展示图标
  const renderDisplayImage = (item) => {
    if (item.type === 'account') {
      return accountImg
    }
    if (item.type === 'store') {
      return storeImg
    }
    if (item.pid === -1) {
      return levelImg
    }
    return moreImg
  }

  const searchVal = ref('')
  const levelList = ref([-1])
  const storeDataSource = ref([])
  const groupStoreSourceData = ref([])


  const displayList = computed(() => {
    const lastLevelIndex = levelList.value.length - 1
    const levelLast = levelList.value[lastLevelIndex] // id

    // 如果searchVal || 标签有值, 只展示门店列表
    if (searchVal.value) {
      return storeDataSource.value?.filter(item => item.name?.includes(searchVal.value)) || []
    }

    if (levelLast === -1) {
      return mallList.value
    } else {
      return mallMap.value[levelLast]?.children || []
    }
  })
</script>

<style lang="scss">
  .inspection {
    position: relative;
    display: flex;
    flex-direction: column;
    .organization {
      position: sticky;
      left: 0;
      top: 0;
      width: 750rpx;
      height: 100rpx;
      background-color: #f2f3f6;
      z-index: 100;
      padding: 0 20rpx;
    }

    .i-o-content {
      width: 710rpx;
      flex: 1;
      margin: 0 20rpx;
      // padding: 28rpx;
      background-color: #fff;
      border-radius: 16rpx;
      .tag_title {
        padding: 28rpx 24rpx 0;
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        &_text {
          font-weight: bold;
          font-size: 28rpx;
          color: #121415;

          &:active {
            color: #3277FB;
          }
        }
      }

      .v-l {
        flex: 1;
        min-height: 0;

        &-item {
          margin: 0 24rpx;
          height: 92rpx;
          display: flex;
          flex-direction: row;
          align-items: center;
          border-bottom: 2rpx solid #EEF0F3;

          &:active {
            background-color: #f2f3f6;
          }

          &-img {
            min-width: 40rpx;
            width: 40rpx;
            height: 40rpx;
            margin-right: 12rpx;
          }

          &-text {
            flex: 1;
            display: flex;
            flex-direction: row;
            font-size: 28rpx;
            color: #202328;

          }
          .overflow{
            /* #ifdef APP-NVUE */
            lines: 1;
            /* #endif */
            /* #ifndef APP-NVUE */
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
            /* #endif */
          }

          &-next {
            min-width: 120rpx;
            margin-left: 16rpx;
            display: flex;
            flex-direction: row;
            align-items: center;

            &-img {
              width: 26rpx;
              height: 26rpx;
              margin-right: 12rpx;
            }

            &-text {
              font-size: 24rpx;
              color: #202328;
            }
          }
        }
      }
    }
  }
</style>