Files
qiming/qiming-mobile/hooks/useAuthInterceptor.uts

164 lines
4.5 KiB
Plaintext
Raw Permalink 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.
import { ref, Ref } from "vue";
import { ACCESS_TOKEN } from "@/constants/home.constants";
import { jumpToAgentDetailPage } from "@/utils/commonBusiness";
import { AgentComponentTypeEnum } from "@/types/enums/agent";
import { apiUserInfo } from "@/servers/account";
import { SUCCESS_CODE } from "@/constants/codes.constants";
import { getCurrentPageFullPath } from "@/utils/common";
/**
* 智能体信息基础接口
*/
interface AgentInfoBase {
targetId: number;
name: string;
agentType?: "ChatBot" | "PageApp";
targetType?: AgentComponentTypeEnum;
agentId?: number;
icon?: string;
description?: string;
}
/**
* 登录拦截 composable
* 用于在点击智能体时进行登录拦截,未登录时显示登录弹窗
*
* @returns 返回登录弹窗 ref、处理点击的函数和登录成功回调
*/
export const useAuthInterceptor = () => {
// 登录弹窗ref
const loginPopupRef = ref<any>(null);
// 待跳转的智能体信息
// const pendingAgentInfo = ref<AgentInfoBase | null>(null);
/**
* 检查是否登录
*
* - 小程序、H5 开发环境:仅根据本地 ACCESS_TOKEN 是否存在判断
* - H5 正式环境:调用 apiUserInfo 接口判断是否处于登录状态
*
* @returns 是否已登录
*/
const hasToken = async (): Promise<boolean> => {
// #ifdef MP-WEIXIN
const mpToken = uni.getStorageSync(ACCESS_TOKEN);
return !!mpToken;
// #endif
// #ifdef H5 || WEB
// 开发环境:只判断本地是否有 token
if (process.env.NODE_ENV === "development") {
const devToken = uni.getStorageSync(ACCESS_TOKEN);
return !!devToken;
}
// 正式环境:通过接口校验登录状态
try {
const res = await apiUserInfo();
const { code, data } = res || {};
if (code === SUCCESS_CODE && data) {
return true;
}
} catch (error) {
console.error("检查登录状态失败(apiUserInfo):", error);
}
return false;
// #endif
};
/**
* 处理智能体点击事件
* @param info 智能体信息
*/
const handleAgentClick = async (info: AgentInfoBase) => {
// #ifdef H5 || WEB
// H5 端统一走登录校验逻辑
const loggedIn = await hasToken();
if (!loggedIn) {
// 微信小程序:获取当前页面的 url
const currentUrl = getCurrentPageFullPath();
const redirectUrl =
"/subpackages/pages/login/login?redirect=" +
encodeURIComponent(currentUrl);
uni.reLaunch({ url: redirectUrl });
// H5 未登录暂不弹登录弹窗,这里直接返回
return;
}
performJump(info);
// #endif
// #ifdef MP-WEIXIN
// 检查是否登录
const loggedInMp = await hasToken();
if (!loggedInMp) {
// 未登录,保存待跳转的智能体信息(包括 icon, name, description到本地缓存
const tempAgentInfo = {
name: info.name,
icon: info.icon || "",
description: info.description || "",
};
uni.setStorageSync("temp_agent_info", JSON.stringify(tempAgentInfo));
// 跳转到临时会话页面
uni.navigateTo({
url: "/subpackages/pages/temporary-session/temporary-session",
});
} else {
// 已登录,直接跳转详情页
performJump(info);
}
// #endif
};
/**
* 执行跳转逻辑
* @param info 智能体信息
*/
const performJump = (info: AgentInfoBase) => {
// 优先使用 agentType如果没有则根据 targetType 判断
let agentType: "ChatBot" | "PageApp" = "ChatBot";
if (info.agentType) {
agentType = info.agentType;
} else if (info.targetType === AgentComponentTypeEnum.Page) {
agentType = "PageApp";
}
// 使用 targetId 或 agentId兼容不同数据结构
const agentId = info.targetId || info.agentId;
if (agentId) {
jumpToAgentDetailPage(agentId, null, agentType, info.name);
}
};
/**
* 检查登录状态,如果未登录则显示登录弹窗
* @returns 是否已登录
*/
const checkAuthAndShowPopup = async (): Promise<boolean> => {
// #ifdef H5 || WEB
// H5根据环境和接口结果判断是否已登录
const loggedInH5 = await hasToken();
return loggedInH5;
// #endif
// #ifdef MP-WEIXIN
const loggedInMp = await hasToken();
if (loggedInMp) {
return true;
}
if (loginPopupRef.value) {
loginPopupRef.value.open();
}
return false;
// #endif
};
return {
loginPopupRef,
handleAgentClick,
checkAuthAndShowPopup,
hasToken,
};
};