all.vue 5.89 KB
<template>
  <view>
    <uv-input v-model="searchVal" :placeholder="t('app.common.search')" prefixIconStyle="color:#6d778f" prefixIcon="search" border="none"
      customStyle="background-color:#F2F3F6;border-radius:8rpx;padding:8rpx 20rpx;margin: 28rpx"
      placeholder-style="font-size:26rpx;color:#6d778f;margin-top:3rpx" />

    <uv-index-list :index-list="filteredData.indexList" customNavHeight="100rpx" v-if="filteredData.itemArr.length>0">
      <template v-for="(item, index) in filteredData.itemArr">
        <!-- #ifdef APP-NVUE -->
        <uv-index-anchor height="48rpx" bg-color="#F2F3F6" color="#202328" size="24rpx"
          :text="filteredData.indexList[index]"></uv-index-anchor>
        <!-- #endif -->
        <uv-index-item>
          <!-- #ifndef APP-NVUE -->
          <uv-index-anchor height="48rpx" bg-color="#F2F3F6" color="#202328" size="24rpx"
            :text="filteredData.indexList[index]"></uv-index-anchor>
          <!-- #endif -->
          <view class="list-cell" v-for="(cell, index) in item" @tap="handleTapCell(cell)">
            {{cell.name}}
          </view>
        </uv-index-item>
      </template>
    </uv-index-list>
    <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 {
    pinyin
  } from 'pinyin-pro';
  import {
    getAccountStoreApi
  } from '@/api'
  import {
    getStageObj
  } from '@/utils'
  import {
    onLoad
  } from '@dcloudio/uni-app'
  import {
    ref,
    onMounted,
    computed
  } from 'vue'
  import {
    t
  } from '@/plugins/index.js'


  /******************  搜索相关  ********************/
  const searchVal = ref('')
  // 存储原始数据
  const originalData = ref({
    indexList: [],
    itemArr: []
  });
  // 新增:带搜索过滤的计算属性
  const filteredData = computed(() => {
    const searchText = searchVal.value.trim().toLowerCase();

    // 无搜索值时返回完整数据
    if (!searchText) return originalData.value;

    const result = {
      indexList: [],
      itemArr: []
    };

    originalData.value.indexList.forEach((letter, index) => {
      const originItems = originalData.value.itemArr[index];

      // 过滤当前字母下的项目
      const matchedItems = originItems.filter(oItem => {
        return oItem.name.toLowerCase().includes(searchText)
      });

      // 只保留有匹配项的字母
      if (matchedItems.length > 0) {
        result.indexList.push(letter);
        result.itemArr.push(matchedItems);
      }
    });

    return result;
  });


  const allStore = ref([])
  onLoad(() => {
    
    uni.setNavigationBarTitle({
      title: t('DownloadInfo.allStore')
    })
    getAllStore()
  })

  // 选中
  const handleTapCell = (cell) => {
    cell.type = 'store'
    uni.$emit('mallSelect', cell)
    uni.navigateBack({
      delta: 2
    })
  }
  // 获取拼音
  const getFullPinYin = (str) => {
    if (!str || typeof str !== 'string') return '';
    // const firstChar = str.charAt(0);
    // const pinyinArr = pinyin(firstChar, {
    //   toneType: 'none'
    // });
    const pinyinArr = pinyin(str, {
      toneType: 'none',
      nonZh: 'consecutive',
      type: 'array'
    });
    return pinyinArr.join('');
    // return pinyinArr.length > 0 ? pinyinArr[0] : '';

  }

  const indexList = ref([])
  const itemArr = ref([])
  const getAllStore = async () => {
    try {
      uni.showLoading({
        title: '数据加载中...'
      })
      const account = await getStageObj('account');
      const {
        data
      } = await getAccountStoreApi({
        accountId: account.id,
        status: 1,
        // sortName: 'name',
        // sortOrder: 'desc'
      });

      // 1. 中文拼音排序
      const sortedData = [...data].sort((a, b) => {
        const pyA = getFullPinYin(a.name);
        const pyB = getFullPinYin(b.name);
        // const pyA = pinyin(a.name, {
        // 	pattern: 'first',
        // 	toneType: 'none'
        // });
        // const pyB = pinyin(b.name, {
        // 	pattern: 'first',
        // 	toneType: 'none'
        // });
        return pyA.localeCompare(pyB);
      });

      // 2. 生成A-Z字母表
      const allLetters = Array.from({
          length: 26
        }, (_, i) =>
        String.fromCharCode(65 + i) // A-Z
      );

      // 3. 初始化分组容器
      const grouped = allLetters.reduce((acc, cur) => {
        acc[cur] = [];
        return acc;
      }, {});

      // 4. 数据分组
      sortedData.forEach(store => {
        const firstChar = pinyin(store.name, {
          pattern: 'first',
          toneType: 'none',
          nonZh: 'consecutive'
        }).charAt(0).toUpperCase();

        if (/^[A-Z]$/.test(firstChar)) { // 仅处理A-Z
          grouped[firstChar].push(store);
        }
      });

      // 5. 过滤空分组并保持字母顺序
      const validLetters = allLetters.filter(letter =>
        grouped[letter].length > 0
      );
      originalData.value = {
        indexList: validLetters,
        itemArr: validLetters.map(letter => grouped[letter])
      };
    } catch (error) {
      console.error("数据处理失败:", error);
      return {
        indexList: [],
        itemArr: []
      };
    } finally {
      uni.hideLoading()
    }
  };
</script>
<style lang="scss" scoped>
  .list-cell {
    padding: 0 32rpx 0 28rpx;
    height: 68rpx;
    line-height: 68rpx;
    color: #202328;
    font-size: 28rpx;
    /* #ifdef APP-NVUE */
    lines: 1;
    /* #endif */
    /* #ifndef APP-NVUE */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    /* #endif */
    &:active {
      background-color: #f2f3f6;
    }

  }
</style>