index.vue 6.18 KB
<template>
  <view class="page-container">
    <!-- 加载页 -->
    <up-loading-page
        :loading="loading"
        loading-text="加载中..."
        color="#577ee3"
        zIndex="1000"
    ></up-loading-page>

    <!-- 蓝色装饰块 -->
    <view class="blue-decor-block" v-show="!loading">
      <text class="welcome-text u-line-1">你好{{ userInfo?.user?.nickname || '' }},欢迎登录</text>
      <text class="platform-name">蓟城山水智慧园林养护平台</text>
    </view>

    <!-- 内容容器 -->
    <view class="content-wrap">
      <!-- 空状态:过滤后无数据且非加载中时显示 -->
      <u-empty
          v-if="!filteredModuleList.length && !loading"
          mode="permission"
      ></u-empty>

      <!-- 菜单卡片列表:仅渲染有子节点的父模块 -->
      <view class="menu-card-wrap">
        <up-card
            :title-size="14"
            :titleColor="'#000'"
            :border="false"
            :shadow="true"
            :head-style="{
             fontWeight:'500'
            }"
            :foot-border-top="false"
            v-for="(parentModule, index) in filteredModuleList"
            :key="`$parentModule.id_${index}`"
            :title="parentModule.name"
            class="card-container"
        >
          <template #body>
            <view class="card-content">
              <view
                  v-for="(listItem, listIndex) in parentModule.children"
                  :key="listItem.id"
                  class="content-block"
                  @click="handleMenuClick(listItem)"
              >
                <u-image
                    :src="listItem.icon"
                    mode="aspectFit"
                    width="48px"
                    height="48px"
                    lazy-load
                    radius="8px"
                    class="block-icon"
                ></u-image>
                <text class="grid-text">{{ listItem.name }}</text>
              </view>
            </view>
          </template>
        </up-card>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import {ref, computed} from 'vue';
import {onShow} from '@dcloudio/uni-app';
import {useUserStore} from '@/pinia/user';
import globalConfig from '@/common/config/global';
import cache from '@/common/utils/cache';

interface MenuItem {
  id: number;
  name: string;
  subtitle?: string;
  type: number;
  sort: number;
  parentId: number;
  icon: string;
  jumpUrl: string;
  miniAppId?: string;
  badgeText?: string;
  badgeColor?: string;
  statisticCount: number | null;
  hasStatistic: boolean;
  extra: any;
  children: MenuItem[];
}

// ========== 全局变量定义区 ==========
const loading = ref(true);
const userStore = useUserStore();
const moduleList = ref<MenuItem[]>([]);
const userInfo = ref<any>(cache.get(globalConfig.cache.userInfoKey) || userStore.userInfo || {});

// 计算属性:过滤出有子节点的父模块(children 存在且长度 > 0)
const filteredModuleList = computed(() => {
  return moduleList.value.filter(item => {
    return Array.isArray(item.children) && item.children.length > 0;
  });
});

onShow(async () => {
  try {
    loading.value = true;
    userInfo.value = cache.get(globalConfig.cache.userInfoKey) || userStore.userInfo || {};

    // 登录状态判断(多维度校验,确保准确性)
    const isLogin = () => {
      const token = cache.get(globalConfig.cache.tokenKey) || userStore.token;
      const userInfoVal = userInfo.value;
      console.log('当前用户信息:', userInfoVal?.user);
      return !!token && !!userInfoVal;
    };

    // 未登录处理:跳转登录页,阻止后续逻辑执行
    if (!isLogin()) {
      uni.showToast({title: '请先登录', icon: 'none', duration: 1500});
      setTimeout(() => {
        uni.reLaunch({
          url: '/pages/login/index',
          fail: (err) => {
            console.error('跳转登录页失败:', err);
            uni.showToast({title: '跳转登录页异常', icon: 'none'});
          }
        });
      }, 1500);
      loading.value = false;
      return;
    }

    const rawMenuData = userStore.moduleListInfo || cache.get(globalConfig.cache.moduleListKey);
    moduleList.value = rawMenuData || [];
    loading.value = false;
    console.log('原始菜单数据:', moduleList.value);
    console.log('过滤后有子节点的父模块:', filteredModuleList.value);
  } catch (error) {
    console.error('获取菜单数据失败:', error);
    moduleList.value = [];
    loading.value = false;
  }
});

const handleMenuClick = (item: MenuItem) => {
  if (!item.jumpUrl) {
    uni.showToast({title: '暂无跳转链接', icon: 'none', duration: 2000});
    return;
  }
  uni.navigateTo({
    url: item.jumpUrl,
    fail: (err) => {
      console.error('页面跳转失败:', err);
      uni.showToast({title: '页面路径错误', icon: 'none', duration: 2000});
    }
  });
};
</script>

<style scoped lang="scss">
.page-container {
  position: relative;
  min-height: 100vh;
}

.blue-decor-block {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  padding: 80px 15px 115px;
  background: url("https://img.jichengshanshui.com.cn:28207/appimg/bg.jpg") no-repeat;
  background-size: 100% 100%;
  z-index: 1;
  color: #fff;
  text-align: left;

  .welcome-text {
    font-size: 16px;
    display: block;
    margin-bottom: 4px;
  }

  .platform-name {
    margin-bottom: 10px;
    font-size: 16px;
    display: block;
  }
}

.content-wrap {
  position: relative;
  z-index: 2;
  padding: 125px 0 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.menu-card-wrap {
  width: 100%;
}

.card-container {
  --u-card-content-padding: 0;
  border-radius: 4px;
  overflow: hidden;
}

.card-content {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.content-block {
  width: calc((100% - 3 * 10px) / 4);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 7px 0;
  border-radius: 4px;
  touch-action: manipulation;
  transition: background-color 0.2s;
}

.content-block:active {
  background-color: #e9ecef;
}

.block-icon {
  display: block;
  margin: 0 auto;
}

.grid-text {
  font-size: 13px;
  color: #1C1C1C;
  text-align: center;
  margin-top: 5px;
  display: block;
}
</style>