ProfilePage.vue 8.99 KB
<template>
  <AppLayout :right-content="rightContent">
    <div
      class="bg-gradient-to-br from-green-50 via-green-100/30 to-blue-50/30 min-h-screen"
    >
      <!-- User Profile Header with Enhanced Design -->
      <div class="pt-6 pb-8 relative">
        <div
          class="absolute inset-0 bg-gradient-to-r from-green-500 to-blue-500 opacity-15"
        ></div>
        <div class="relative z-10 flex flex-col items-center">
          <div
            class="w-24 h-24 rounded-full overflow-hidden border-4 border-white shadow-lg mb-4"
          >
            <img
              :src="profile.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'"
              :alt="profile.name"
              class="w-full h-full object-cover"
              @error="handleImageError"
            />
          </div>
          <h2 class="text-2xl font-bold mb-1">{{ profile.name }}</h2>
          <!-- <div class="flex items-center text-sm text-gray-600">
            <span>会员等级: 普通会员</span>
            <span class="mx-2">|</span>
            <span>ID: {{ profile.id }}</span>
          </div> -->
        </div>
      </div>

      <!-- Check-in Statistics -->
      <div class="px-4 mb-5 pt-4">
        <FrostedGlass class="p-4 rounded-xl">
          <div class="flex justify-between items-center mb-4">
            <h3 class="font-semibold text-base">打卡统计</h3>
            <!-- <span class="text-xs text-blue-500">查看更多</span> -->
          </div>

          <div class="flex justify-between">
            <div class="flex flex-col items-center">
              <div class="text-2xl font-bold text-gray-800">
                {{ checkIns?.total_days || 0 }}
              </div>
              <div class="text-xs text-gray-500 mt-1">累计打卡</div>
            </div>
            <div class="flex flex-col items-center">
              <div class="text-2xl font-bold text-green-600">
                {{ checkIns?.consecutive_days || 0 }}
              </div>
              <div class="text-xs text-gray-500 mt-1">连续打卡</div>
            </div>
            <div class="flex flex-col items-center">
              <div class="text-2xl font-bold text-blue-600">
                {{ checkIns?.longest_consecutive_days || 0 }}
              </div>
              <div class="text-xs text-gray-500 mt-1">最长连续</div>
            </div>
            <div>
              <div @click="handleCheckin" class="cursor-pointer">
                <button
                  class="bg-gradient-to-r from-green-500 to-green-600 text-white py-2 px-6 rounded-full text-sm shadow-sm"
                >
                  立即打卡
                </button>
              </div>
            </div>
          </div>
        </FrostedGlass>
      </div>

      <!-- User Menu Options -->
      <div class="px-4 pb-16">
        <FrostedGlass class="rounded-xl overflow-hidden mb-5">
          <MenuItem
            v-for="item in menuItems1"
            :key="item.path"
            v-bind="item"
            @click="handleMenuClick(item.path)"
          />
        </FrostedGlass>

        <FrostedGlass class="rounded-xl overflow-hidden mb-5">
          <MenuItem
            v-for="item in menuItems2"
            :key="item.path"
            v-bind="item"
            @click="handleMenuClick(item.path)"
          />
        </FrostedGlass>

        <FrostedGlass v-if="isTeacher" class="rounded-xl overflow-hidden mb-5">
          <MenuItem
            v-for="item in menuItems4"
            :key="item.path"
            v-bind="item"
            @click="handleMenuClick(item.path)"
          />
        </FrostedGlass>

        <FrostedGlass class="rounded-xl overflow-hidden mb-5">
          <MenuItem
            v-for="item in menuItems3"
            :key="item.path"
            v-bind="item"
            @click="handleMenuClick(item.path)"
          />
        </FrostedGlass>

        <!-- Version Info -->
        <div class="text-center text-xs text-gray-400 mb-4">美乐爱觉教育</div>

        <!-- Logout Button -->
        <!-- <button
          @click="handleLogout"
          class="w-full bg-white/70 backdrop-blur-sm text-red-500 py-3 rounded-xl mb-6 font-medium shadow-sm"
        >
          退出登录
        </button> -->
      </div>
    </div>
  </AppLayout>

  <CheckInDialog
    v-model:show="showCheckInDialog"
    @check-in-success="handleCheckInSuccess"
    @check-in-data="handleCheckInData"
  />
</template>

<script setup>
import { ref, h } from "vue";
import { useRoute, useRouter } from "vue-router";
import AppLayout from "@/components/layout/AppLayout.vue";
import FrostedGlass from "@/components/ui/FrostedGlass.vue";
import MenuItem from "@/components/ui/MenuItem.vue";
import { useAuth } from "@/contexts/auth";
import CheckInDialog from "@/components/ui/CheckInDialog.vue";
import { getUserInfoAPI } from "@/api/users";
import { showToast } from "vant";

import { useTitle } from "@vueuse/core";

const router = useRouter();
const $route = useRoute();
useTitle($route.meta.title);

const profile = ref({});
const checkIns = ref({});
const isTeacher = ref(false);

onMounted(async () => {
  const { code, data } = await getUserInfoAPI();
  if (code) {
    profile.value = data.user;
    checkIns.value = data.checkin;
    isTeacher.value = data.is_teacher;
    // 处理消息中心的未读消息数量
    menuItems2.value.forEach(item => {
      if (item.path === '/profile/messages') {
        item.badge = +data.unread_msg_count || 0;
      }
    });
  }
})

const showCheckInDialog = ref(false);

// 处理打卡成功
const handleCheckInSuccess = () => {
  checkIns.value.total_days++;
  checkIns.value.consecutive_days++;
  checkIns.value.longest_consecutive_days = Math.max(
    checkIns.value.longest_consecutive_days,
    checkIns.value.consecutive_days
  );
};

const checkinData = ref([]);
const handleCheckInData = (data) => {
  checkinData.value = data;
}

// Handle logout
const { logout } = useAuth();
const handleLogout = () => {
  logout();
  // window.location.href = import.meta.env.VITE_BASE || '/';
  // 返回首页
  router.replace({ path: '/' });
};

// Handle menu item click
const handleMenuClick = (path) => {
  if (path === '/profile/community') {
    // window.location.href = 'https://community.mlaj.com';
    showToast('功能暂未开放')
  } else if(path === '/profile/activities') {
      // showToast('功能暂未开放')
      window.location.href = 'https://wxm-dev.behalo.cc/pages/activity/activity?token=&user_id=';
  } else if(path === '/profile/userinfo') {
      // showToast('功能暂未开放')
      window.location.href = 'https://wxm-dev.behalo.cc/pages/student/student?token=&user_id=';
  } else {
    router.push(path);
  }
};

// Handle image error
const handleImageError = (e) => {
  e.target.onerror = null;
  e.target.src = "https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg";
};

// Handle check-in type click
const handleCheckInClick = (path) => {
  router.push(path);
};

// Right content component
const rightContent = h("div", { class: "flex items-center" }, [
  h("button", { class: "p-2" }, [
    h(
      "svg",
      {
        xmlns: "http://www.w3.org/2000/svg",
        class: "h-6 w-6 text-gray-700",
        fill: "none",
        viewBox: "0 0 24 24",
        stroke: "currentColor",
      },
      [
        h("path", {
          "stroke-linecap": "round",
          "stroke-linejoin": "round",
          "stroke-width": "2",
          d:
            "M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9",
        }),
      ]
    ),
  ]),
]);

// Menu items
const menuItems1 = [
  {
    icon: "clock",
    title: "学习记录",
    path: "/profile/learning-records",
    badge: "",
  },
  {
    icon: "wallet",
    title: "活动报名",
    path: "/profile/activities",
  },
  {
    icon: "user",
    title: "人员信息",
    path: "/profile/userinfo",
  },
  {
    icon: "book",
    title: "我的课程",
    path: "/profile/courses",
  },
  {
    icon: "document",
    title: "课程订单",
    path: "/profile/orders",
  },
];

const menuItems2 = ref([
  // {
  //   icon: "wallet",
  //   title: "我的钱包",
  //   path: "/profile/wallet",
  // },
  {
    icon: "heart",
    title: "我的收藏",
    path: "/profile/favorites",
  },
  {
    icon: "chat",
    title: "我的圈子",
    path: "/profile/community",
  },
  {
    icon: "email",
    title: "我的消息",
    path: "/profile/messages",
    badge: "",
  },
]);

const menuItems3 = ref([
  {
    icon: "question",
    title: "帮助中心",
    path: "/profile/help",
  },
  {
    icon: "settings",
    title: "设置",
    path: "/profile/settings",
  },
]);

const menuItems4 = ref([
  // {
  //   icon: "book",
  //   title: "打卡管理",
  //   path: "/teacher/checkin",
  // },
  {
    icon: "user",
    title: "我的班级",
    path: "/teacher/myClass",
  },
]);

const handleCheckin = () => {
  if (checkinData.value.length) {
    showCheckInDialog.value = true;
  } else {
    showToast('暂无打卡任务')
  }
}
</script>