Files
ycc-proxy-webview/src/views/Me.vue
2026-02-08 16:56:41 +08:00

488 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="box-border min-h-screen">
<div class="flex flex-col p-4 space-y-6">
<!-- 用户信息和资产卡片合并 -->
<div class="profile-section group relative rounded-xl p-0.5 transition-all hover:shadow-xl"
:class="isAgent ? levelGradient.cardBorder : 'bg-gray-200'"
@click="!isLoggedIn ? redirectToLogin() : null">
<div class="rounded-xl bg-white p-6">
<!-- 上半部分用户信息 -->
<div class="flex items-center gap-4 mb-4">
<div class="relative">
<!-- 头像容器添加overflow-hidden解决边框问题 -->
<div class="overflow-hidden rounded-full p-0.5" :class="levelGradient.border">
<img :src="userAvatar || getDefaultAvatar()" alt="User Avatar"
class="h-20 w-20 rounded-full border-4 border-white" />
</div>
<!-- 代理标识 -->
<div v-if="isAgent" class="absolute -bottom-2 -right-2">
<div class="flex items-center justify-center rounded-full px-3 py-1 text-xs font-bold text-white shadow-sm"
:class="levelGradient.badge">
{{ levelNamesMap[level] || levelNamesMap[1] }}
</div>
</div>
</div>
<div class="flex-1 space-y-1">
<h2 class="text-2xl font-bold" style="color: var(--van-text-color);">
{{
!isLoggedIn
? "点击登录"
: mobile
? mobile
: isWeChat
? "微信用户"
: "未绑定手机号"
}}
</h2>
<!-- 手机号绑定提示 -->
<template v-if="isLoggedIn && !mobile">
<p @click.stop="showRegisterAgentDialog" class="text-sm cursor-pointer hover:underline"
style="color: var(--van-theme-primary);">
点击注册成为代理
</p>
</template>
<!-- 普通用户申请成为代理提示 -->
<template v-else-if="isLoggedIn && mobile && !isAgent">
<p @click.stop="toRegister" class="text-sm cursor-pointer hover:underline"
style="color: var(--van-theme-primary);">
点击申请成为代理
</p>
</template>
<p v-if="isAgent" class="font-bold" :class="levelGradient.text">
ID: {{ agentCode }}
</p>
</div>
<!-- 右侧资产信息仅代理显示 -->
<div v-if="isAgent" class="text-right">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">余额</div>
<div class="text-2xl font-bold"
:style="(revenueData?.balance || 0) < 0 ? 'color: #ef4444;' : 'color: var(--van-theme-primary);'">
¥ {{ (revenueData?.balance || 0).toFixed(2) }}
</div>
<!-- 负数余额提示 -->
<div v-if="(revenueData?.balance || 0) < 0" class="text-xs mt-1" style="color: #ef4444;">
账户存在欠款需补足后才能提现
</div>
</div>
</div>
<!-- 下半部分资产详情和操作按钮仅代理显示 -->
<template v-if="isAgent">
<div class="grid grid-cols-3 gap-3 mb-4 pt-4 border-t"
style="border-color: var(--van-border-color);">
<div class="text-center">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">累计收益</div>
<div class="text-base font-semibold" style="color: var(--van-text-color);">
¥ {{ (revenueData?.total_earnings || 0).toFixed(2) }}
</div>
</div>
<div class="text-center">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">风险保障金</div>
<div class="text-base font-semibold" style="color: var(--van-text-color);">
¥ {{ (revenueData?.frozen_balance || 0).toFixed(2) }}
</div>
</div>
<div class="text-center">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">累计提现</div>
<div class="text-base font-semibold" style="color: var(--van-text-color);">
¥ {{ (revenueData?.withdrawn_amount || 0).toFixed(2) }}
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-3">
<button @click.stop="toWithdraw"
class="text-white rounded-full py-1.5 px-4 shadow-md flex items-center justify-center text-base"
style="background: linear-gradient(135deg, var(--van-theme-primary), var(--van-theme-primary-dark)); min-height: 36px;">
<van-icon name="gold-coin" class="mr-1" />
提现
</button>
<button @click.stop="toWithdrawDetails"
class="bg-white/90 border rounded-full py-1.5 px-4 shadow-sm flex items-center justify-center text-base"
style="color: var(--van-text-color-2); border-color: var(--van-border-color); min-height: 36px;">
<van-icon name="notes" class="mr-1" />
提现记录
</button>
</div>
</template>
</div>
</div>
<!-- 佣金和下级推广收益合并 -->
<div v-if="isAgent" class="rounded-xl shadow-lg bg-white p-5">
<div class="grid grid-cols-2 gap-4">
<!-- 我的推广收益部分 -->
<div class="pr-4 border-r" style="border-color: var(--van-border-color);">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center">
<van-icon name="balance-list" class="text-lg mr-2"
style="color: var(--color-warning);" />
<span class="text-base font-bold" style="color: var(--van-text-color);">我的推广收益</span>
</div>
</div>
<div class="text-center mb-3">
<div class="text-xl font-bold" style="color: var(--color-warning);">
¥ {{ (revenueData?.commission_total || 0).toFixed(2) }}
</div>
<div class="text-sm mt-0.5" style="color: var(--van-text-color-2);">累计总收益</div>
</div>
<div class="grid grid-cols-2 gap-2 mb-3">
<div class="text-center">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">今日</div>
<div class="text-base font-semibold" style="color: var(--color-warning);">
¥ {{ (revenueData?.commission_today || 0).toFixed(2) }}
</div>
</div>
<div class="text-center">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">本月</div>
<div class="text-base font-semibold" style="color: var(--color-warning);">
¥ {{ (revenueData?.commission_month || 0).toFixed(2) }}
</div>
</div>
</div>
<div class="flex items-center justify-center text-sm font-semibold cursor-pointer"
style="color: var(--color-warning);" @click="goToPromoteDetail">
<span>查看明细</span>
<span class="ml-1 text-base"></span>
</div>
</div>
<!-- 下级推广收益部分 -->
<div class="pl-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center">
<van-icon name="gift-o" class="text-lg mr-2" style="color: var(--color-success);" />
<span class="text-base font-bold" style="color: var(--van-text-color);">下级推广收益</span>
</div>
</div>
<div class="text-center mb-3">
<div class="text-xl font-bold" style="color: var(--color-success);">
¥ {{ (revenueData?.rebate_total || 0).toFixed(2) }}
</div>
<div class="text-sm mt-0.5" style="color: var(--van-text-color-2);">累计总收益</div>
</div>
<div class="grid grid-cols-2 gap-2 mb-3">
<div class="text-center">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">今日</div>
<div class="text-base font-semibold" style="color: var(--color-success);">
¥ {{ (revenueData?.rebate_today || 0).toFixed(2) }}
</div>
</div>
<div class="text-center">
<div class="text-sm mb-1" style="color: var(--van-text-color-2);">本月</div>
<div class="text-base font-semibold" style="color: var(--color-success);">
¥ {{ (revenueData?.rebate_month || 0).toFixed(2) }}
</div>
</div>
</div>
<div class="flex items-center justify-center text-sm font-semibold cursor-pointer"
style="color: var(--color-success);" @click="goToRebateDetail">
<span>查看明细</span>
<span class="ml-1 text-base"></span>
</div>
</div>
</div>
</div>
<!-- 功能菜单 -->
<div class="">
<div class="bg-white rounded-xl shadow-sm p-4">
<div class="grid grid-cols-4 gap-4">
<!-- 升级功能入口如果不是钻石代理 -->
<button v-if="isAgent && level !== 3"
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-purple-50 transition-colors"
@click="toUpgrade">
<img src="@/assets/images/me/sjdl.svg" class="w-8 h-8 object-contain" alt="升级代理" />
<span class="text-xs text-gray-700 font-medium text-center">升级代理</span>
</button>
<!-- 升级下级入口仅钻石代理 -->
<button v-if="isAgent && level === 3"
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-purple-50 transition-colors"
@click="toUpgradeSubordinate">
<img src="@/assets/images/me/sjxj.svg" class="w-8 h-8 object-contain" alt="调整下级级别" />
<span class="text-xs text-gray-700 font-medium text-center">调整级别</span>
</button>
<!-- 邀请码管理入口 -->
<button v-if="isAgent"
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-blue-50 transition-colors"
@click="toInviteCodeManage">
<img src="@/assets/images/me/yqmgl.svg" class="w-8 h-8 object-contain" alt="邀请码管理" />
<span class="text-xs text-gray-700 font-medium text-center">邀请码管理</span>
</button>
<!-- 实名认证入口所有代理 -->
<button v-if="isAgent"
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-green-50 transition-colors"
@click="toRealNameAuth">
<img src="@/assets/images/me/smrz.svg" class="w-8 h-8 object-contain" alt="提现" />
<span class="text-xs text-gray-700 font-medium text-center">实名认证</span>
</button>
<!-- 提现入口所有代理 -->
<!-- <button v-if="isAgent"
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-blue-50 transition-colors"
@click="toWithdraw">
<img src="@/assets/images/me/tx.svg" class="w-8 h-8 object-contain" alt="提现" />
<span class="text-xs text-gray-700 font-medium text-center">提现</span>
</button> -->
<button
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-purple-50 transition-colors"
@click="toAgentSystemGuide">
<img src="@/assets/images/me/yhxy.svg" class="w-8 h-8 object-contain" alt="代理系统指南" />
<span class="text-xs text-gray-700 font-medium text-center">代理系统指南</span>
</button>
<!-- 推广查询记录 -->
<button v-if="isAgent"
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-blue-50 transition-colors"
@click="toAgentReport">
<img src="@/assets/images/me/tgcxjl.svg" class="w-8 h-8 object-contain" alt="推广查询记录" />
<span class="text-xs text-gray-700 font-medium text-center">推广查询记录</span>
</button>
<button
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-blue-50 transition-colors"
@click="toUserAgreement">
<img src="@/assets/images/me/yhxy.svg" class="w-8 h-8 object-contain" alt="用户协议" />
<span class="text-xs text-gray-700 font-medium text-center">用户协议</span>
</button>
<button
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-blue-50 transition-colors"
@click="toPrivacyPolicy">
<img src="@/assets/images/me/yszc.svg" class="w-8 h-8 object-contain" alt="隐私政策" />
<span class="text-xs text-gray-700 font-medium text-center">隐私政策</span>
</button>
<button
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-blue-50 transition-colors"
@click="toService">
<img src="@/assets/images/me/lxkf.svg" class="w-8 h-8 object-contain" alt="联系客服" />
<span class="text-xs text-gray-700 font-medium text-center">联系客服</span>
</button>
<button v-if="isLoggedIn && !isWeChat"
class="flex flex-col items-center justify-center gap-2 py-4 rounded-lg hover:bg-red-50 transition-colors"
@click="handleLogout">
<img src="@/assets/images/me/tcdl.png" class="w-8 h-8 object-contain" alt="退出登录" />
<span class="text-xs text-gray-700 font-medium text-center">退出登录</span>
</button>
</div>
</div>
</div>
</div>
<BindPhoneDialog />
</div>
</template>
<script setup>
import { storeToRefs } from "pinia";
import { ref, computed, onBeforeMount, onMounted } from "vue";
import { useRouter } from "vue-router";
import headShot from "@/assets/images/head_shot.webp";
import { useAgentStore } from "@/stores/agentStore";
import { useUserStore } from "@/stores/userStore";
import { useEnv } from "@/composables/useEnv";
import { useDialogStore } from "@/stores/dialogStore";
import useApiFetch from "@/composables/useApiFetch";
import { getRevenueInfo } from '@/api/agent';
import BindPhoneDialog from "@/components/BindPhoneDialog.vue";
const router = useRouter();
const agentStore = useAgentStore();
const userStore = useUserStore();
const dialogStore = useDialogStore();
const { isAgent, level, levelName, agentCode } = storeToRefs(agentStore);
const { userName, userAvatar, isLoggedIn, mobile } = storeToRefs(userStore);
const { isWeChat } = useEnv();
const revenueData = ref(null);
// 等级名称映射(数字等级)
const levelNamesMap = {
1: "普通代理",
2: "黄金代理",
3: "钻石代理",
};
const levelTextMap = {
1: "基础代理特权",
2: "高级代理特权",
3: "尊享代理特权",
};
const levelGradient = computed(() => {
const currentLevel = level.value || 1;
const gradients = {
1: {
border: "bg-gradient-to-r from-gray-300 to-gray-400",
badge: "bg-gradient-to-r from-gray-500 to-gray-600",
text: "text-gray-600",
cardBorder: "bg-gradient-to-r from-gray-300 to-gray-400",
},
2: {
border: "bg-gradient-to-r from-yellow-400 to-amber-500",
badge: "bg-gradient-to-r from-yellow-500 to-amber-600",
text: "text-amber-600",
cardBorder: "bg-gradient-to-r from-yellow-400 to-amber-500",
},
3: {
border: "bg-gradient-to-r from-purple-400 to-pink-400 shadow-[0_0_15px_rgba(163,51,200,0.2)]",
badge: "bg-gradient-to-r from-purple-500 to-pink-500",
text: "text-purple-600",
cardBorder: "bg-gradient-to-r from-purple-400 to-pink-400 shadow-[0_0_20px_rgba(163,51,200,0.3)]",
},
};
return gradients[currentLevel] || gradients[1];
});
const maskName = (name) => {
if (!name || name.length < 11) return name;
return name.substring(0, 3) + "****" + name.substring(7);
};
function toUserAgreement() {
router.push(`/userAgreement`);
}
function toPrivacyPolicy() {
router.push(`/privacyPolicy`); // 新增隐私政策路由
}
function redirectToLogin() {
router.push(`/login`);
}
function handleLogout() {
// 改进的存储管理
localStorage.removeItem("token");
localStorage.removeItem("refreshAfter");
localStorage.removeItem("accessExpire");
localStorage.removeItem("userInfo");
localStorage.removeItem("agentInfo");
// 重置状态
userStore.resetUser();
agentStore.resetAgent();
location.reload();
}
const toBigData = () => {
window.location.href = "https://www.tybigdata.com/";
};
function handleCancelAccount() {
// 账号注销功能
if (confirm("注销账号后,您的所有数据将被清除且无法恢复,确定要继续吗?")) {
useApiFetch("/user/cancelOut")
.post()
.json()
.then(({ data, error }) => {
if (!error && data.value && data.value.code === 200) {
alert("账号已注销");
handleLogout();
}
})
.catch((error) => {
console.error("注销账号失败:", error);
});
}
}
function toService() {
window.location.href =
"https://work.weixin.qq.com/kfid/kfc82d4424e4b19e5f3"; // 跳转到客服页面
}
const toUpgrade = () => {
router.push({ name: "agentUpgrade" });
};
const toUpgradeSubordinate = () => {
router.push({ name: "upgradeSubordinate" });
};
const toInviteCodeManage = () => {
router.push({ name: "invitation" });
};
const toRealNameAuth = () => {
dialogStore.openRealNameAuth();
};
const toAgentReport = () => {
router.push({ name: "agentPromotionQueryList" })
}
const toWithdraw = () => {
router.push({ name: "withdraw" });
};
const toAgentSystemGuide = () => {
router.push({ name: "agentSystemGuide" });
};
const toWithdrawDetails = () => {
router.push({ name: "withdrawDetails" });
};
const goToPromoteDetail = () => {
router.push({ name: "promoteDetails" });
};
const goToRebateDetail = () => {
router.push({ name: "rewardsDetails" });
};
const getRevenueData = async () => {
if (!isAgent.value) return;
const { data: revenueResponse, error: revenueError } = await getRevenueInfo();
if (revenueResponse.value?.code === 200 && !revenueError.value) {
revenueData.value = revenueResponse.value.data;
}
};
const getDefaultAvatar = () => {
if (!isAgent.value) return headShot;
const currentLevel = level.value || 1;
switch (currentLevel) {
case 1:
return "/image/shot_nonal.png";
case 2:
return "/image/shot_vip.png";
case 3:
return "/image/shot_svip.png";
default:
return headShot;
}
};
const showRegisterAgentDialog = () => {
dialogStore.openRegisterAgent();
};
const toRegister = () => {
router.push("/register");
};
onBeforeMount(() => {
// 获取存储的用户和代理信息
const userInfo = localStorage.getItem("userInfo");
if (userInfo) {
try {
const parsedUserInfo = JSON.parse(userInfo);
userStore.updateUserInfo(parsedUserInfo);
} catch (e) {
console.error("解析用户信息失败", e);
}
}
const agentInfo = localStorage.getItem("agentInfo");
if (agentInfo) {
try {
const parsedAgentInfo = JSON.parse(agentInfo);
agentStore.updateAgentInfo(parsedAgentInfo);
} catch (e) {
console.error("解析代理信息失败", e);
}
}
});
onMounted(() => {
if (isAgent.value) {
getRevenueData();
}
});
</script>
<style scoped></style>