chore: dev proxy config, sprite animator refactor, cleanups

- add vite dev proxy for `/ingress` to forward requests to backend https://onefeel.brother7.cn
- update .env.development to use relative proxy paths instead of full backend URLs
- move SpriteAnimator component to correct directory, update all imports and global type declarations in components.d.ts
- remove unused CSS styles and fix styling for ChatTopNavBar component, including switching to van-icon and hardcoding temporary site name
- uncomment and enable the ChatMainList component in home page
- clean up unused code, fix formatting, and set default client ID in src/utils/request.ts
- comment out redundant uni API calls in ChatMainList to simplify code
- update WebSocket URL handling to support relative paths in ChatMainList
This commit is contained in:
DEV_DSW
2026-05-27 10:40:21 +08:00
parent 0d46ac0e2c
commit a75bb909f1
11 changed files with 109 additions and 250 deletions

View File

@@ -1,153 +1,14 @@
<template>
<div class="flex flex-col h-screen relative overflow-hidden">
<!-- 顶部自定义导航栏 -->
<div class="header absolute top-0 left-0 w-full z-10" :style="{ paddingTop: statusBarHeight + 'px' }">
<div class="absolute top-0 left-0 w-full z-10">
<ChatTopNavBar ref="topNavBarRef" :mainPageDataModel="mainPageDataModel" @showDrawer="handleShowDrawer" />
</div>
<div class="relative">
<img class="w-full block" :src="mainPageDataModel?.initPageImages?.backgroundImageUrl" mode="aspectFill"
style="height: 252px;" />
<div class="absolute bottom-0 left-0 right-0 flex-full">
<div class="px-12 pt-12">
<HomeWelcome :mainPageDataModel="mainPageDataModel" />
</div>
<div style="margin-bottom: -1px;">
<AiTabSwitch v-model="tabIndex" :list="tabList" @change="handleChange" />
</div>
</div>
</div>
<div v-show="tabIndex === 0" class="main-scroll-area flex-full overflow-hidden min-height-0"
@touchstart.capture="handleScrollAreaTouchStart" @touchstart="handleScrollAreaTouchStart"
@touchmove="handleScrollAreaTouchMove">
<Discovery @scroll-touch-start="handleScrollAreaTouchStart" @scroll-touch="handleScrollAreaTouchMove" />
</div>
<!-- 消息列表可滚动区域 -->
<div v-show="tabIndex === 1" class="main main-scroll-area flex-full overflow-hidden min-height-0" scroll-y
:scroll-top="scrollTop" :scroll-with-animation="true" @scroll="handleScroll" @scrolltolower="handleScrollToLower"
@touchstart.capture="handleScrollAreaTouchStart" @touchstart="handleScrollAreaTouchStart"
@touchmove="handleScrollAreaTouchMove">
<div class="area-msg-list-content" v-for="item in chatMsgList" :key="item.msgId" :id="item.msgId">
<template v-if="item.msgType === MessageRole.AI">
<ChatCardAI class="flex flex-justify-start" :key="`ai-${item.msgId}-${item.msg ? item.msg.length : 0}`" :text="item.componentName && isLongTextCard(item.componentName)
? ''
: item.msg || ''
" :isLoading="item.isLoading">
<template #content v-if="
item.toolCall ||
(item.componentName && isLongTextCard(item.componentName))
">
<!-- <AnswerComponent
v-if="isLongTextCard(item.componentName)"
:longTextData="item.longTextData"
:finish="item.finish"
/> -->
<LongTextGuideCardPreview v-if="item.componentName && isLongTextCard(item.componentName)"
:componentName="item.componentName" />
<QuickBookingComponent v-if="
item.toolCall &&
item.toolCall.componentName === CompName.quickBookingCard
" />
<DiscoveryCardComponent v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.discoveryCard
" />
<CreateServiceOrder v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.callServiceCard
" :toolCall="item.toolCall" />
<OpenMapComponent v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.mapCard
" />
<GeneratorPhotoComponent v-else-if="
item.toolCall &&
item.toolCall.componentName ===
CompName.aigcPhotoGeneratorCard
" :toolCall="item.toolCall" />
<!-- <ZModuleC01
v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.aigcPhotoGeneratorCard
"
/> -->
<Feedback v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.feedbackCard
" :toolCall="item.toolCall" />
<DetailCardCompontent v-else-if="
item.toolCall &&
item.toolCall.componentName ===
CompName.pictureAndCommodityCard
" :toolCall="item.toolCall" />
<AddCarCrad v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.enterLicensePlateCard
" :toolCall="item.toolCall" />
<SurveyQuestionnaire v-else-if="
item.toolCall &&
item.toolCall.componentName ===
CompName.callSurveyQuestionnaire
" :toolCall="item.toolCall" />
</template>
<template #footer>
<!-- 这个是底部 -->
<AttachListComponent v-if="item.question" :question="item.question" />
</template>
</ChatCardAI>
</template>
<template v-else-if="item.msgType === MessageRole.ME">
<ChatCardMine class="flex flex-justify-end" :text="item.msg" />
</template>
<template v-else>
<ChatCardOther class="flex flex-justify-center" :text="item.msg">
<ChatGuide v-if="chatMsgList.length < 2" />
<ActivityListComponent v-if="
mainPageDataModel.activityList &&
mainPageDataModel.activityList.length > 0
" :activityList="mainPageDataModel.activityList" />
<!-- 先不展示了,等后续有需求再加回来 false -->
<RecommendPostsComponent v-if="
false &&
mainPageDataModel.recommendTheme &&
mainPageDataModel.recommendTheme.length > 0
" :recommendThemeList="mainPageDataModel.recommendTheme" />
</ChatCardOther>
</template>
</div>
</div>
<!-- 输入框区域 -->
<div class="pb-safe-area">
<ChatQuickAccess />
<ChatInputArea ref="inputAreaRef" v-model="inputMessage" :holdKeyboard="holdKeyboard"
:is-session-active="isSessionActive" :stop-request="stopRequest" @send="sendMessageAction"
@noHideKeyboard="handleNoHideKeyboard" @keyboardShow="handleKeyboardShow" @keyboardHide="handleKeyboardHide" />
</div>
</div>
</template>
<script setup>
import { onMounted, nextTick, onUnmounted, ref } from "vue";
import {
SWITCH_TO_COMPANION_TAB,
SWITCH_TO_DISCOVERY_TAB,
SCROLL_TO_BOTTOM,
SEND_MESSAGE_CONTENT_TEXT,
SEND_MESSAGE_COMMAND_TYPE,
NOTICE_EVENT_LOGOUT,
NOTICE_EVENT_LOGIN_SUCCESS,
} from "@/constants/constant";
import { MessageRole, MessageType, CompName, Command } from "@/constants/ChatModel";
import HomeWelcome from "../HomeWelcome/index.vue";
@@ -195,8 +56,7 @@ import { getAccessToken } from "@/constants/token";
const emit = defineEmits(["showDrawer"]);
const appStore = useAppStore();
/// 导航栏相关
const statusBarHeight = ref(20);
/// 输入框组件引用
const inputAreaRef = ref(null);
const topNavBarRef = ref();
@@ -278,7 +138,7 @@ const handleTouchEnd = () => {
holdKeyboardTimer.value = setTimeout(() => {
// 键盘弹出时点击界面则关闭键盘
if (holdKeyboardFlag.value && isKeyboardShow.value) {
uni.hideKeyboard();
// uni.hideKeyboard();
}
holdKeyboardFlag.value = true;
}, 100);
@@ -319,13 +179,7 @@ const hideKeyboardByScroll = () => {
inputAreaRef.value.blurInput();
}
uni.hideKeyboard();
// #ifdef APP-PLUS
if (typeof plus !== "undefined" && plus.key && plus.key.hideSoftKeybord) {
plus.key.hideSoftKeybord();
}
// #endif
};
const hideKeyboardAfterSend = () => {
@@ -338,8 +192,6 @@ const hideKeyboardAfterSend = () => {
typeof inputAreaRef.value.blurInput === "function"
) {
inputAreaRef.value.blurInput();
} else {
uni.hideKeyboard();
}
};
@@ -439,54 +291,48 @@ const sendMessageAction = (inputText) => {
/// 添加通知
const addNoticeListener = () => {
uni.$on(NOTICE_EVENT_LOGIN_SUCCESS, () => {
if (!isWsConnected()) {
initHandler();
}
});
// uni.$on(NOTICE_EVENT_LOGIN_SUCCESS, () => {
// if (!isWsConnected()) {
// initHandler();
// }
// });
uni.$on(NOTICE_EVENT_LOGOUT, () => {
resetConfig();
});
// uni.$on(NOTICE_EVENT_LOGOUT, () => {
// resetConfig();
// });
uni.$on(SCROLL_TO_BOTTOM, () => {
setTimeout(() => {
scrollToBottom(true);
}, 200);
});
// uni.$on(SCROLL_TO_BOTTOM, () => {
// setTimeout(() => {
// scrollToBottom(true);
// }, 200);
// });
uni.$on(SEND_MESSAGE_CONTENT_TEXT, (value) => {
console.log("SEND_MESSAGE_CONTENT_TEXT:", value);
if (value && value.length > 0) {
handleReplyText(value);
}
});
// uni.$on(SEND_MESSAGE_CONTENT_TEXT, (value) => {
// console.log("SEND_MESSAGE_CONTENT_TEXT:", value);
// if (value && value.length > 0) {
// handleReplyText(value);
// }
// });
uni.$on(SEND_MESSAGE_COMMAND_TYPE, (item) => {
console.log("SEND_MESSAGE_COMMAND_TYPE:", item);
if (item && item.type) {
handleReplyInstruct(item);
}
});
// uni.$on(SEND_MESSAGE_COMMAND_TYPE, (item) => {
// console.log("SEND_MESSAGE_COMMAND_TYPE:", item);
// if (item && item.type) {
// handleReplyInstruct(item);
// }
// });
uni.$on(SWITCH_TO_COMPANION_TAB, () => {
tabIndex.value = 1;
});
// uni.$on(SWITCH_TO_COMPANION_TAB, () => {
// tabIndex.value = 1;
// });
uni.$on(SWITCH_TO_DISCOVERY_TAB, () => {
tabIndex.value = 0;
});
// uni.$on(SWITCH_TO_DISCOVERY_TAB, () => {
// tabIndex.value = 0;
// });
};
/// =============生命周期函数↓================
// TODO
// onLoad(() => {
// uni.getSystemInfo({
// success: (res) => {
// statusBarHeight.value = res.statusBarHeight || 20;
// },
// });
// });
// onReady(() => {
// // #ifdef APP-PLUS
@@ -548,9 +394,10 @@ const loadConversationMsgList = async () => {
// 获取首页数据
const getMainPageData = async () => {
/// 从个渠道获取如二维,没有的时候就返回首页的数据
// 从个渠道获取如二维,没有的时候就返回首页的数据
const sceneId = appStore.sceneId || "";
const res = await mainPageData({ sceneId });
console.log("🚀 ~ getMainPageData ~ res:", res)
if (res.code === 0) {
initData();
@@ -582,7 +429,18 @@ const initWebSocket = async () => {
// 使用配置的WebSocket服务器地址
const token = getAccessToken();
const wsUrl = `${appStore.serverConfig.wssUrl}?access_token=${token}`;
const rawWsUrl = appStore.serverConfig.wssUrl;
const resolvedWsUrl =
typeof rawWsUrl === "string" &&
(rawWsUrl.startsWith("ws://") || rawWsUrl.startsWith("wss://"))
? rawWsUrl
: `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}${typeof rawWsUrl === "string"
? rawWsUrl.startsWith("/")
? rawWsUrl
: `/${rawWsUrl}`
: ""
}`;
const wsUrl = `${resolvedWsUrl}?access_token=${token}`;
// 初始化WebSocket管理器
webSocketManager = new WebSocketManager({
@@ -917,9 +775,9 @@ const sendMessage = async (message, isInstruct = false) => {
if (!isWsConnected()) {
console.log("WebSocket未连接尝试重新连接...");
// 显示加载提示
uni.showLoading({
title: "正在连接服务器...",
});
// uni.showLoading({
// title: "正在连接服务器...",
// });
// 尝试重新初始化WebSocket连接
try {
@@ -929,34 +787,34 @@ const sendMessage = async (message, isInstruct = false) => {
// 检查连接是否成功建立
if (!isWsConnected()) {
uni.hideLoading();
// uni.hideLoading();
setTimeout(() => {
uni.showToast({
title: "连接服务器失败,请稍后重试",
icon: "none",
});
// uni.showToast({
// title: "连接服务器失败,请稍后重试",
// icon: "none",
// });
}, 100);
return;
}
uni.hideLoading();
// uni.hideLoading();
} catch (error) {
console.error("重新连接WebSocket失败:", error);
uni.hideLoading();
// uni.hideLoading();
setTimeout(() => {
uni.showToast({
title: "连接服务器失败,请稍后重试",
icon: "none",
});
// uni.showToast({
// title: "连接服务器失败,请稍后重试",
// icon: "none",
// });
}, 100);
return;
}
}
if (isSessionActive.value) {
uni.showToast({
title: "请等待当前回复完成",
icon: "none",
});
// uni.showToast({
// title: "请等待当前回复完成",
// icon: "none",
// });
return;
}
isSessionActive.value = true;
@@ -1230,11 +1088,11 @@ const stopRequest = async () => {
// 组件销毁时清理资源
onUnmounted(() => {
uni.$off(NOTICE_EVENT_LOGIN_SUCCESS);
uni.$off(SCROLL_TO_BOTTOM);
uni.$off(SEND_MESSAGE_CONTENT_TEXT);
uni.$off(SEND_MESSAGE_COMMAND_TYPE);
uni.$off(NOTICE_EVENT_LOGOUT);
// uni.$off(NOTICE_EVENT_LOGIN_SUCCESS);
// uni.$off(SCROLL_TO_BOTTOM);
// uni.$off(SEND_MESSAGE_CONTENT_TEXT);
// uni.$off(SEND_MESSAGE_COMMAND_TYPE);
// uni.$off(NOTICE_EVENT_LOGOUT);
resetConfig();
});