Files
qiming/qiming-mobile/pages/index/index.uvue

341 lines
9.6 KiB
Plaintext
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>
<view class="h-full flex flex-col border-b">
<!-- 顶部导航栏 -->
<custom-nav-bar :title="t('Mobile.Nav.home')" className="border-b">
<template v-slot:left>
<view class="flex flex-row items-center gap-4">
<header-menu
v-if="isLoggedIn"
:userInfo="userInfo"
ref="headerMenuRef"
/>
<view v-else class="login-btn-wrapper" @click="handleLogin">
<text class="login-btn-text">{{
t("Mobile.Common.loginRegister")
}}</text>
</view>
<!-- #ifdef MP-WEIXIN -->
<view class="icon-search-box" @click="handleSearch">
<text class="iconfont iconfont icon-Search font-48"></text>
</view>
<!-- #endif -->
</view>
</template>
<!-- #ifdef H5 || WEB -->
<template v-slot:right>
<view class="icon-search-box" @click="handleSearch">
<text class="iconfont iconfont icon-Search font-48"></text>
</view>
</template>
<!-- #endif -->
</custom-nav-bar>
<uni-notice-bar
v-if="!isLoggedIn"
single
show-close
show-icon
:text="t('Mobile.Common.noticeExperience')"
></uni-notice-bar>
<!-- 未登录时只显示智能体列表,不显示标签页 -->
<agent-list-content
v-if="!isLoggedIn"
class="h-full w-full"
ref="agentListContentRef"
:is-logged-in="isLoggedIn"
@agent-click="handleAgentClick"
/>
<!-- 登录后显示标签页:最近使用 + 会话记录 -->
<pane-tabs
v-if="isLoggedIn"
:key="currentLang"
v-model="activeTab"
:lazy-load="false"
with-bottom-padding
@change="handleTabChange"
>
<pane-tab key-value="recent" tab="Mobile.Common.recentUsed">
<agent-list-content
class="h-full w-full"
ref="agentListContentRef"
:is-logged-in="isLoggedIn"
@agent-click="handleAgentClickLast"
/>
</pane-tab>
<pane-tab
key-value="history"
tab="Mobile.Common.conversationHistory"
>
<conversation-list-content
class="h-full w-full"
ref="conversationListContentRef"
:is-logged-in="isLoggedIn"
@conversation-click="handleConversationClick"
/>
</pane-tab>
</pane-tabs>
<!-- 登录弹窗 -->
<auth-login-popup ref="loginPopupRef" />
</view>
</template>
<script setup lang="uts">
import { SUCCESS_CODE } from "@/constants/codes.constants.uts";
import { apiUserInfo } from "@/servers/account";
import type { AgentInfo } from "@/types/interfaces/agent";
import HeaderMenu from "./header-menu/header-menu.uvue";
import AgentListContent from "./agent-list-content/agent-list-content.uvue";
import ConversationListContent from "./conversation-list-content/conversation-list-content.uvue";
import type { UserInfo } from "@/types/interfaces/login";
import { apiTenantConfig } from "@/servers/account";
import { onAddToFavorites } from "@dcloudio/uni-app";
import {
getCurrentPagePath,
jumpToAgentDetailPage,
} from "@/utils/commonBusiness";
import AuthLoginPopup from "@/components/auth-login-popup/auth-login-popup.uvue";
import { useAuthInterceptor } from "@/hooks/useAuthInterceptor";
import { getCurrentPageFullPath } from "@/utils/common";
import { setCurrentPageNavigationBarTitle } from "@/utils/system";
import PaneTabs from "@/components/pane-tabs/pane-tabs.uvue";
import PaneTab from "@/components/pane-tabs/pane-tab.uvue";
import { TENANT_CONFIG_INFO } from "@/constants/home.constants";
import { useI18n, applyTabBarI18n } from "@/utils/i18n";
const { t, syncLanguageFromUser } = useI18n();
const activeTab = ref("recent");
// 分享标题
const shareTitle = ref("");
const fallbackShareTitle = computed(() => t("Mobile.Nav.home"));
const handleTabChange = (key: string) => {
if (key === "recent" && agentListContentRef.value) {
// 切换到最近使用时加载数据
agentListContentRef.value.loadData();
} else if (key === "history" && conversationListContentRef.value) {
// 切换到会话记录时加载数据
conversationListContentRef.value.loadData();
}
};
// 处理会话项点击
const handleConversationClick = (item: any) => {
// 跳转到智能体详情页面,并传递消息数据
jumpToAgentDetailPage(item.agentId, item.id);
};
// 头部菜单ref
const headerMenuRef = ref<any>(null);
// 智能体列表组件ref
const agentListContentRef = ref<any>(null);
// 会话列表组件ref
const conversationListContentRef = ref<any>(null);
// 使用登录拦截 composable
const {
loginPopupRef,
handleAgentClick: baseHandleAgentClick,
checkAuthAndShowPopup,
hasToken,
} = useAuthInterceptor();
// 包装 handleAgentClick 以适配 AgentInfo 类型
const handleAgentClick = (info: AgentInfo) => {
baseHandleAgentClick({
agentId: info.agentId,
name: info.name,
agentType: info.agentType,
icon: info.icon, // 跳转临时会话页面时使用
description: info.description, // 跳转临时会话页面时使用
});
};
// 最近使用
const handleAgentClickLast = (info: AgentInfo) => {
const { lastConversationId, agentId, name, agentType } = info || {};
if (lastConversationId) {
jumpToAgentDetailPage(agentId, lastConversationId);
} else {
baseHandleAgentClick({
agentId: agentId,
name: name,
agentType: agentType,
icon: info.icon, // 跳转临时会话页面时使用
description: info.description, // 跳转临时会话页面时使用
});
}
};
// 处理登录点击
const handleLogin = () => {
// #ifdef MP-WEIXIN
if (loginPopupRef.value) {
loginPopupRef.value.open();
}
// #endif
// #ifdef H5 || WEB
const currentUrl = getCurrentPageFullPath();
uni.navigateTo({
url:
"/subpackages/pages/login/login?redirect=" +
encodeURIComponent(currentUrl),
});
// #endif
};
// 用户信息
const userInfo = ref<UserInfo>();
// 判断是否登录
const isLoggedIn = ref<boolean>(false);
// 查询当前登录用户信息
const fetchUserInfo = async () => {
const res = await apiUserInfo();
const { code, data } = res || {};
if (code === SUCCESS_CODE) {
userInfo.value = data;
await syncLanguageFromUser(data?.lang || "");
}
};
// 设置分享标题
const setCurrentShareTitle = async () => {
// 获取本地用户配置
const tenantConfigInfoString = await uni.getStorageSync(TENANT_CONFIG_INFO);
if (tenantConfigInfoString) {
try {
const { siteName, siteDescription } = JSON.parse(
tenantConfigInfoString,
);
const titleList = [];
if (siteName) {
titleList.push(siteName);
}
if (siteDescription) {
titleList.push(siteDescription);
}
shareTitle.value = titleList.join(" ");
} catch (error) {
console.error("获取本地用户配置失败:", error);
}
}
};
onLoad((options: { cId?: string; fileProxyUrl?: string }) => {
// 检测是否为文件预览分享跳转
// #ifdef MP-WEIXIN
if (options?.cId && options?.fileProxyUrl) {
// 跳转到文件预览页面
// 注意fileProxyUrl 在分享时已经被 encodeURIComponent 编码过了
// 这里不需要再次编码,直接传递即可
uni.navigateTo({
url: `/subpackages/pages/file-preview-page/file-preview-page?cId=${options.cId}&fileProxyUrl=${encodeURIComponent(options.fileProxyUrl)}`,
});
return;
}
// #endif
// 设置当前页面导航栏标题
setCurrentPageNavigationBarTitle();
// 设置分享标题
setCurrentShareTitle();
});
onPageShow(async () => {
// 确保每次回到首页都刷新一次 TabBar 翻译,
// 解决语言切换重载后 TabBar 对象可能未就绪导致 uni.setTabBarItem 失效的问题。
applyTabBarI18n();
const loggedIn = await hasToken();
isLoggedIn.value = loggedIn || false;
// 如果是登录状态,需要等待 pane-tabs 内的组件初始化
if (isLoggedIn.value) {
await nextTick();
fetchUserInfo();
}
});
// 处理搜索
const handleSearch = () => {
// 检查登录状态,如果未登录则显示登录弹窗
if (!checkAuthAndShowPopup()) {
return;
}
const currentUrl = getCurrentPagePath();
uni.navigateTo({
url:
"/subpackages/pages/agent-search/agent-search?type=Home&backUrl=" +
encodeURIComponent(currentUrl),
});
};
// #ifdef MP-WEIXIN
// 转发给朋友
onShareAppMessage(() => {
return {
title: shareTitle.value || fallbackShareTitle.value,
path: "/pages/index/index",
};
});
// 收藏
onAddToFavorites(() => {
return {
title: shareTitle.value || fallbackShareTitle.value,
};
});
// #endif
onHide(() => {
if (headerMenuRef.value) {
headerMenuRef.value.closeDropdown();
}
});
</script>
<style lang="scss" scoped>
.h-full {
height: 100%;
}
.w-full {
width: 100%;
}
.icon-search-box {
display: flex;
align-items: center;
justify-content: center;
margin-left: 12rpx;
}
.login-btn-wrapper {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 15rpx 20rpx;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 100rpx;
margin-right: 8rpx;
&:active {
background-color: rgba(0, 0, 0, 0.1);
}
.login-btn-text {
color: #333333;
font-size: 26rpx;
font-weight: 400;
}
}
</style>