519 lines
21 KiB
JavaScript
519 lines
21 KiB
JavaScript
|
|
import { createRouter, createWebHistory } from "vue-router";
|
|||
|
|
import NProgress from "nprogress";
|
|||
|
|
import GlobalLayout from "@/layouts/GlobalLayout.vue";
|
|||
|
|
import HomeLayout from "@/layouts/HomeLayout.vue";
|
|||
|
|
import PageLayout from "@/layouts/PageLayout.vue";
|
|||
|
|
import index from "@/views/index.vue";
|
|||
|
|
import Promote from "@/views/Promote.vue";
|
|||
|
|
import PromotePage from "@/views/PromotePage.vue";
|
|||
|
|
import { useAgentStore } from "@/stores/agentStore";
|
|||
|
|
import { useUserStore } from "@/stores/userStore";
|
|||
|
|
import { useDialogStore } from "@/stores/dialogStore";
|
|||
|
|
import { useEnv } from "@/composables/useEnv";
|
|||
|
|
import { storeToRefs } from "pinia";
|
|||
|
|
import { useSEO } from "@/composables/useSEO";
|
|||
|
|
|
|||
|
|
const router = createRouter({
|
|||
|
|
history: createWebHistory(import.meta.env.BASE_URL),
|
|||
|
|
// 路由切换时的滚动行为
|
|||
|
|
scrollBehavior(to, from, savedPosition) {
|
|||
|
|
// 如果有保存的位置(浏览器前进/后退)
|
|||
|
|
if (savedPosition) {
|
|||
|
|
return savedPosition;
|
|||
|
|
} else {
|
|||
|
|
// 否则滚动到顶部
|
|||
|
|
return { top: 0, behavior: "smooth" };
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
routes: [
|
|||
|
|
{
|
|||
|
|
path: "/",
|
|||
|
|
component: GlobalLayout, // 使用 Layout 作为父组件
|
|||
|
|
children: [
|
|||
|
|
{
|
|||
|
|
path: "",
|
|||
|
|
component: HomeLayout, // 使用 Layout 作为父组件
|
|||
|
|
children: [
|
|||
|
|
{
|
|||
|
|
path: "",
|
|||
|
|
name: "index",
|
|||
|
|
component: index,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "promote",
|
|||
|
|
name: "promote",
|
|||
|
|
component: PromotePage,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/agent",
|
|||
|
|
name: "agent",
|
|||
|
|
component: () => import("@/views/Agent.vue"),
|
|||
|
|
meta: { title: "代理主页", requiresAuth: true },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "me",
|
|||
|
|
name: "me",
|
|||
|
|
component: () => import("@/views/Me.vue"),
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "",
|
|||
|
|
component: PageLayout,
|
|||
|
|
children: [
|
|||
|
|
{
|
|||
|
|
path: "/historyQuery",
|
|||
|
|
name: "history",
|
|||
|
|
component: () => import("@/views/HistoryQuery.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "历史报告",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
notNeedBindPhone: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/help",
|
|||
|
|
name: "help",
|
|||
|
|
component: () => import("@/views/Help.vue"),
|
|||
|
|
meta: { title: "帮助中心" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/help/detail",
|
|||
|
|
name: "helpDetail",
|
|||
|
|
component: () => import("@/views/HelpDetail.vue"),
|
|||
|
|
meta: { title: "帮助中心" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/help/guide",
|
|||
|
|
name: "helpGuide",
|
|||
|
|
component: () => import("@/views/HelpGuide.vue"),
|
|||
|
|
meta: { title: "引导指南" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/agent/system-guide",
|
|||
|
|
name: "agentSystemGuide",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentSystemGuide.vue"),
|
|||
|
|
meta: { title: "代理系统指南" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/withdraw",
|
|||
|
|
name: "withdraw",
|
|||
|
|
component: () => import("@/views/Withdraw.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "提现",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/service",
|
|||
|
|
name: "service",
|
|||
|
|
component: () => import("@/views/Service.vue"),
|
|||
|
|
meta: { title: "客服" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/complaint",
|
|||
|
|
name: "complaint",
|
|||
|
|
component: () => import("@/views/Complaint.vue"),
|
|||
|
|
meta: { title: "投诉" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/report",
|
|||
|
|
name: "report",
|
|||
|
|
component: () => import("@/views/Report.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "报告结果",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
notNeedBindPhone: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/example",
|
|||
|
|
name: "example",
|
|||
|
|
component: () => import("@/views/Example.vue"),
|
|||
|
|
meta: { title: "示例报告", notNeedBindPhone: true },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/vant-theme-test",
|
|||
|
|
name: "vantThemeTest",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/VantThemeTest.vue"),
|
|||
|
|
meta: { title: "Vant主题色测试" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/privacyPolicy",
|
|||
|
|
name: "privacyPolicy",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/PrivacyPolicy.vue"),
|
|||
|
|
meta: { title: "隐私政策" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/userAgreement",
|
|||
|
|
name: "userAgreement",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/UserAgreement.vue"),
|
|||
|
|
meta: { title: "用户协议" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/agentManageAgreement",
|
|||
|
|
name: "agentManageAgreement",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentManageAgreement.vue"),
|
|||
|
|
meta: { title: "代理管理协议" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/agentSerivceAgreement",
|
|||
|
|
name: "agentSerivceAgreement",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentServiceAgreement.vue"),
|
|||
|
|
meta: { title: "信息技术服务合同" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/inquire/:feature",
|
|||
|
|
name: "inquire",
|
|||
|
|
component: () => import("@/views/Inquire.vue"),
|
|||
|
|
meta: { title: "查询报告" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/authorization",
|
|||
|
|
name: "authorization",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/Authorization.vue"),
|
|||
|
|
meta: { title: "授权书" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/payment/result",
|
|||
|
|
name: "paymentResult",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/PaymentResult.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "支付结果",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
notNeedBindPhone: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "agent",
|
|||
|
|
component: PageLayout,
|
|||
|
|
children: [
|
|||
|
|
{
|
|||
|
|
path: "/agent/promote",
|
|||
|
|
name: "agentPromote",
|
|||
|
|
component: Promote,
|
|||
|
|
meta: {
|
|||
|
|
title: "推广报告",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/agent/promotion/query/list",
|
|||
|
|
name: "agentPromotionQueryList",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentPromotionHistory.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "推广查询记录",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "promoteDetails",
|
|||
|
|
name: "promoteDetails",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentPromoteDetails.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "我的推广收益",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "rewardsDetails",
|
|||
|
|
name: "rewardsDetails",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentRewardsDetails.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "下级推广收益",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
path: "invitation",
|
|||
|
|
name: "invitation",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/InvitationPage.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "邀请下级",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "withdraw",
|
|||
|
|
name: "withdraw",
|
|||
|
|
component: () => import("@/views/Withdraw.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "提现",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "withdrawDetails",
|
|||
|
|
name: "withdrawDetails",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/WithdrawDetails.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "提现记录",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "teamList",
|
|||
|
|
name: "teamList",
|
|||
|
|
component: () => import("@/views/TeamList.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "我的团队",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "upgradeSubordinate",
|
|||
|
|
name: "upgradeSubordinate",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/UpgradeSubordinate.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "调整下级级别",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "upgrade",
|
|||
|
|
name: "agentUpgrade",
|
|||
|
|
component: () => import("@/views/AgentUpgrade.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "升级代理",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "subordinateList",
|
|||
|
|
name: "subordinateList",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/SubordinateList.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "我的下级",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "subordinateDetail/:id",
|
|||
|
|
name: "subordinateDetail",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/SubordinateDetail.vue"),
|
|||
|
|
meta: {
|
|||
|
|
title: "下级贡献详情",
|
|||
|
|
requiresAuth: true,
|
|||
|
|
requiresAgent: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "app",
|
|||
|
|
children: [
|
|||
|
|
{
|
|||
|
|
path: "authorization",
|
|||
|
|
name: "appAuthorization",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/Authorization.vue"),
|
|||
|
|
meta: { title: "授权书" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "privacyPolicy",
|
|||
|
|
name: "appPrivacyPolicy",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/PrivacyPolicy.vue"),
|
|||
|
|
meta: { title: "隐私政策" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "userAgreement",
|
|||
|
|
name: "appUserAgreement",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/UserAgreement.vue"),
|
|||
|
|
meta: { title: "用户协议" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "agentManageAgreement",
|
|||
|
|
name: "appAgentManageAgreement",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentManageAgreement.vue"),
|
|||
|
|
meta: { title: "代理管理协议" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "agentSerivceAgreement",
|
|||
|
|
name: "appAgentSerivceAgreement",
|
|||
|
|
component: () =>
|
|||
|
|
import("@/views/AgentServiceAgreement.vue"),
|
|||
|
|
meta: { title: "信息技术服务合同" },
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
path: "/login",
|
|||
|
|
name: "login",
|
|||
|
|
component: () => import("@/views/Login.vue"),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/register",
|
|||
|
|
name: "register",
|
|||
|
|
component: () => import("@/views/Register.vue"),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/agent/promotionInquire/:linkIdentifier",
|
|||
|
|
name: "promotionInquire",
|
|||
|
|
component: () => import("@/views/PromotionInquire.vue"),
|
|||
|
|
meta: { notNeedBindPhone: true },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/agent/invitationAgentApply/:linkIdentifier",
|
|||
|
|
name: "invitationAgentApply",
|
|||
|
|
component: () => import("@/views/InvitationAgentApply.vue"),
|
|||
|
|
meta: { title: "代理申请" },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/report/share/:linkIdentifier",
|
|||
|
|
name: "reportShare",
|
|||
|
|
component: () => import("@/views/ReportShare.vue"),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: "/:pathMatch(.*)*",
|
|||
|
|
name: "NotFound",
|
|||
|
|
component: () => import("@/views/NotFound.vue"),
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
NProgress.configure({
|
|||
|
|
easing: "ease", // 动画方式
|
|||
|
|
speed: 500, // 递增进度条的速度(毫秒)
|
|||
|
|
showSpinner: false, // 是否显示加载的圆圈
|
|||
|
|
trickleSpeed: 200, // 自动递增间隔
|
|||
|
|
minimum: 0.3, // 初始化最小百分比
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 路由导航守卫
|
|||
|
|
router.beforeEach(async (to, from, next) => {
|
|||
|
|
NProgress.start();
|
|||
|
|
const isAuthenticated = localStorage.getItem("token");
|
|||
|
|
const agentStore = useAgentStore();
|
|||
|
|
const userStore = useUserStore();
|
|||
|
|
const dialogStore = useDialogStore();
|
|||
|
|
const authStore = useAuthStore();
|
|||
|
|
const { isWeChat } = useEnv();
|
|||
|
|
const { isAgent, isLoaded } = storeToRefs(agentStore);
|
|||
|
|
const { mobile, isLoggedIn } = storeToRefs(userStore);
|
|||
|
|
// 检查 token 是否过期
|
|||
|
|
const accessExpire = localStorage.getItem("accessExpire");
|
|||
|
|
const now = Date.now();
|
|||
|
|
let isTokenExpired = false;
|
|||
|
|
if (accessExpire) {
|
|||
|
|
isTokenExpired = now > parseInt(accessExpire) * 1000;
|
|||
|
|
}
|
|||
|
|
// ============================================================
|
|||
|
|
// 场景 2: 需要登录的页面 + 无 token 或 token 过期 → 跳转登录
|
|||
|
|
// ============================================================
|
|||
|
|
if (to.meta.requiresAuth && (!isAuthenticated || isTokenExpired)) {
|
|||
|
|
const loginQuery = {
|
|||
|
|
redirect: to.fullPath,
|
|||
|
|
};
|
|||
|
|
if (from && from.name === "promotionInquire") {
|
|||
|
|
loginQuery.from = "promotionInquire";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next({ path: "/login", query: loginQuery });
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// 场景 3: 已登录状态下的处理
|
|||
|
|
// ============================================================
|
|||
|
|
if (isAuthenticated && !isTokenExpired) {
|
|||
|
|
// 确保用户信息已加载
|
|||
|
|
if (!isLoggedIn.value) {
|
|||
|
|
try {
|
|||
|
|
await userStore.fetchUserInfo();
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error("Error loading user info:", err);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查代理权限(仅在 requiresAgent 为 true 时)
|
|||
|
|
if (to.meta.requiresAgent) {
|
|||
|
|
if (!mobile.value) {
|
|||
|
|
if (to.meta.notNeedBindPhone) {
|
|||
|
|
dialogStore.openBindPhone();
|
|||
|
|
} else {
|
|||
|
|
next("/register");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 确保代理信息已加载
|
|||
|
|
if (!isLoaded.value) {
|
|||
|
|
try {
|
|||
|
|
await agentStore.fetchAgentStatus();
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error("Error loading agent info:", err);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果不是代理,跳转到注册页(带上手机号参数)
|
|||
|
|
if (!isAgent.value) {
|
|||
|
|
const registerQuery = {};
|
|||
|
|
if (mobile.value) {
|
|||
|
|
registerQuery.mobile = mobile.value;
|
|||
|
|
}
|
|||
|
|
next({ path: "/register", query: registerQuery });
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// 其他情况正常通过
|
|||
|
|
// ============================================================
|
|||
|
|
next();
|
|||
|
|
});
|
|||
|
|
router.afterEach((to) => {
|
|||
|
|
NProgress.done(); // 结束进度条
|
|||
|
|
|
|||
|
|
// SEO优化:更新页面标题和meta信息
|
|||
|
|
const { updateSEO } = useSEO();
|
|||
|
|
|
|||
|
|
// 根据路由meta信息更新SEO
|
|||
|
|
if (to.meta.title) {
|
|||
|
|
const seoConfig = {
|
|||
|
|
title: `${to.meta.title} - 全能查`,
|
|||
|
|
description: `全能查${to.meta.title}页面,提供专业的大数据风险管控服务。`,
|
|||
|
|
url: `https://www.zhinengcha.cn${to.path}`,
|
|||
|
|
};
|
|||
|
|
updateSEO(seoConfig);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
export default router;
|