refactor: clean up styles, configs and home page

- Migrate inline styles for ChatMainList, AigcPhotoCard and SpriteAnimator, delete unused SCSS files
- Update development proxy target in vite.config.ts and env variables including client ID and token
- Fix prop references and styling in ChatInputArea and Welcome components
- Enable and refactor Calender component integration with proper event handling
- Add tabbed layout to ChatMainList with Discovery and chat message sections
- Update Vue 3 component patterns for better maintainability
- Temporarily comment out ChatInputArea in ChatMainList
This commit is contained in:
duanshuwen
2026-05-28 21:41:33 +08:00
parent 958bc96eb0
commit f74af3a4a5
10 changed files with 194 additions and 142 deletions

View File

@@ -11,7 +11,9 @@ VITE_API_TIMEOUT_MS = 10000
VITE_SOCKET_BASE_URL = "/ingress/agent/ws/chat"
# Client ID
VITE_CLIENT_ID = "12"
VITE_CLIENT_ID = "6"
# Token
VITE_TOKEN = "eyJraWQiOiJiMTVhZTk0Mi03MjI5LTMyOWUtODA1Yi0wNjFlNmRjYTE1MDQiLCJhbGciOiJSUzI1NiJ9.eyJ0ZW5hbnRfaWQiOjEsInN1YiI6ImJyb3RoZXI4IiwiY2xpZW50SWQiOiJwaWciLCJpc3MiOiJodHRwczovL3BpZzRjbG91ZC5jb20iLCJjbGllbnRfaWQiOiJwaWciLCJhdXRob3JpdGllcyI6WyIvbWFya2V0aW5nL2luZGV4IiwiUk9MRV8xIiwiY29kZWdlbl9ncm91cF9hZGQiLCJjb2RlZ2VuX2dyb3VwX2RlbCIsImNvZGVnZW5fZ3JvdXBfZWRpdCIsImNvZGVnZW5fZ3JvdXBfZXhwb3J0IiwiY29kZWdlbl9ncm91cF92aWV3IiwiY29kZWdlbl90ZW1wbGF0ZV9hZGQiLCJjb2RlZ2VuX3RlbXBsYXRlX2RlbCIsImNvZGVnZW5fdGVtcGxhdGVfZWRpdCIsImNvZGVnZW5fdGVtcGxhdGVfZXhwb3J0IiwiY29kZWdlbl90ZW1wbGF0ZV92aWV3Iiwiam9iX3N5c19qb2JfYWRkIiwiam9iX3N5c19qb2JfZGVsIiwiam9iX3N5c19qb2JfZWRpdCIsImpvYl9zeXNfam9iX2V4cG9ydCIsImpvYl9zeXNfam9iX3JlZnJlc2hfam9iIiwiam9iX3N5c19qb2JfcnVuX2pvYiIsImpvYl9zeXNfam9iX3NodXRkb3duX2pvYiIsImpvYl9zeXNfam9iX3N0YXJ0X2pvYiIsInN5c19jbGllbnRfYWRkIiwic3lzX2NsaWVudF9kZWwiLCJzeXNfY2xpZW50X2VkaXQiLCJzeXNfZGVwdF9hZGQiLCJzeXNfZGVwdF9kZWwiLCJzeXNfZGVwdF9lZGl0Iiwic3lzX2RpY3RfYWRkIiwic3lzX2RpY3RfZGVsIiwic3lzX2RpY3RfZWRpdCIsInN5c19maWxlX2RlbCIsInN5c19sb2dfZGVsIiwic3lzX2xvZ19leHBvcnQiLCJzeXNfbWVudV9hZGQiLCJzeXNfbWVudV9kZWwiLCJzeXNfbWVudV9lZGl0Iiwic3lzX3Bvc3RfYWRkIiwic3lzX3Bvc3RfZGVsIiwic3lzX3Bvc3RfZWRpdCIsInN5c19wb3N0X2V4cG9ydCIsInN5c19wb3N0X3ZpZXciLCJzeXNfcm9sZV9hZGQiLCJzeXNfcm9sZV9kZWwiLCJzeXNfcm9sZV9lZGl0Iiwic3lzX3JvbGVfZXhwb3J0Iiwic3lzX3JvbGVfcGVybSIsInN5c19zeXNwdWJsaWNwYXJhbV9hZGQiLCJzeXNfc3lzcHVibGljcGFyYW1fZGVsIiwic3lzX3N5c3B1YmxpY3BhcmFtX2VkaXQiLCJzeXNfdG9rZW5fZGVsIiwic3lzX3VzZXJfYWRkIiwic3lzX3VzZXJfZGVsIiwic3lzX3VzZXJfZWRpdCIsInN5c191c2VyX2V4cG9ydCJdLCJhdWQiOiJwaWciLCJsaWNlbnNlIjoiaHR0cHM6Ly9waWc0Y2xvdWQuY29tIiwibmJmIjoxNzc5OTM3MDMzLCJ1c2VyX2lkIjoiMTk2NjEzNTA2MDA2NTc4NzkwNiIsInNjb3BlIjpbInNlcnZlciJdLCJleHAiOjE3Nzk5ODAyMzMsImRlcHRfaWQiOjEsImlhdCI6MTc3OTkzNzAzMywianRpIjoiNzhiM2E3ODgtOGUwZS00Zjc2LWEwMDgtOGYxYzI4M2YxN2ZiIiwidXNlcm5hbWUiOiJicm90aGVyOCJ9.p6GSKT9JPbXD_L7BBGx4j4-amhqZZmzSVnjOZrAZ7klA3WfqWfNw6xgOgKyJHNeXgdJpFlJ-vw3vTTPxuaUJJ-57ugGc60PjH4PC5ARVGvGe4psbXDEw3oYJPBquzLSFDqwCpYThAvTxXmjE6EA6mlrw5y6__-dF5HREu0Bspew2z5a3DvUR4swBFz3g3yZnQCoYXoY32W7akJ5xz2oYjsib411_bAOkFTSsmde2qXqOZ2ij2hUjImCtEaURP0Exep8J_1AOFBp0VoWuhFlPHj6B1-JmyOW4d_aDEa3bUpo46iA_GsXOfSqVzekdhO1bU0KZQzCmiNqawhECdtW3Jw"
VITE_TOKEN = "eyJraWQiOiJiMTVhZTk0Mi03MjI5LTMyOWUtODA1Yi0wNjFlNmRjYTE1MDQiLCJhbGciOiJSUzI1NiJ9.eyJ0ZW5hbnRfaWQiOjEsInN1YiI6Im94T3NGN2lqTkxvbEFIdkhDZDYtek1acE5kNWsiLCJjbGllbnRJZCI6ImN1c3RvbSIsImlzcyI6Imh0dHBzOi8vcGlnNGNsb3VkLmNvbSIsImNsaWVudF9pZCI6ImN1c3RvbSIsImF1dGhvcml0aWVzIjpbXSwiYXVkIjoiY3VzdG9tIiwibGljZW5zZSI6Imh0dHBzOi8vcGlnNGNsb3VkLmNvbSIsIndlY2hhdF9vcGVuaWQiOiJveE9zRjdpak5Mb2xBSHZIQ2Q2LXpNWnBOZDVrIiwibmJmIjoxNzc5OTcwMzQ4LCJ1c2VyX2lkIjoiMjAwNTEwMjg0NDQ2OTM4NzI2NSIsInNjb3BlIjpbInNlcnZlciJdLCJleHAiOjE3Nzk5ODAzNDgsImlhdCI6MTc3OTk3MDM0OCwianRpIjoiMDJmZDQ1OTAtNTMzYi00ZDRhLWI2NTAtNzVkOWQ5NzAxMDQwIiwidXNlcm5hbWUiOiJveE9zRjdpak5Mb2xBSHZIQ2Q2LXpNWnBOZDVrIn0.IOSrjqHKE_E3Gq4FjTXBDFeCJ35ROP-Szfe9pwGrZNLH_YqMhZM5YMH9nNBdFtuD0Iyu5rzm6y6bT3TafTCiUagE_gl1u7JchOqLlWqBfP8lOcAbo0GyGrrQPHT4i1AO9EmYL6S3ihP27Mw5V-5WHb5o5_gRzrUzMAXK7AF1AS729HyjfLNLZ6Z8DDDU6I_JPCkNmN1YpL-LzMil6rPGhPOurXgcJ-ree6tZKqcDIE7ABaaFFSY684MSmvOBMHOarSYbQGEQ1N59gP01u7Y6qjP52alVUsWtH_jCyRi7Yjdpq1qZKkqIqeXLA7Cd8PR2Jzd0W4vQNTBpd1PKhUQMvw"

View File

@@ -1,5 +1,5 @@
<template>
<div class="sprite-animator" :style="spriteStyle" />
<div v-if="hasSpriteConfig" class="sprite-animator" :style="spriteStyle" />
</template>
<script setup lang="ts">
@@ -7,17 +7,23 @@ import { computed, ref, onMounted, onUnmounted } from "vue";
const props = withDefaults(
defineProps<{
src: string;
frameWidth: number;
frameHeight: number;
totalFrames: number;
columns: number;
displayWidth: number;
src?: string;
frameWidth?: number;
frameHeight?: number;
totalFrames?: number;
columns?: number;
displayWidth?: number;
fps?: number;
autoplay?: boolean;
loop?: boolean;
}>(),
{
src: "",
frameWidth: 0,
frameHeight: 0,
totalFrames: 0,
columns: 0,
displayWidth: 0,
fps: 12,
autoplay: true,
loop: true,
@@ -66,6 +72,16 @@ onMounted(() => {
onUnmounted(() => stop());
const hasSpriteConfig = computed(() => {
return (
!!props.src &&
Number(props.frameWidth) > 0 &&
Number(props.frameHeight) > 0 &&
Number(props.totalFrames) > 0 &&
Number(props.columns) > 0
);
});
const spriteStyle = computed(() => {
const {
src,

View File

@@ -1,20 +1,26 @@
<template>
<div class="aigc-photo-card relative rounded-24 overflow-hidden w-full" :class="{ 'is-disabled': disabled }"
@click="handleAction">
<img class="aigc-photo-card__image block w-full" :src="data.cover" />
<div class="aigc-photo-card__shade"></div>
<div class="h-[272px] bg-[#0f172a] relative rounded-[24px] overflow-hidden w-full"
:class="{ 'is-disabled': disabled }" @click="handleAction">
<img class="block w-full" :src="data.cover" />
<div class="absolute inset-0 bg-[#0f172a]/38"></div>
<div class="aigc-photo-card__play flex flex-items-center flex-justify-center rounded-full">
<div class="aigc-photo-card__triangle"></div>
<div
class="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 w-[76px] h-[76px] border border-white/50 bg-white/30 flex items-center justify-center rounded-full">
<div
class="w-0 h-0 ml-[6px] border-t-[17px] border-t-transparent border-b-[17px] border-b-transparent border-l-[23px] border-l-white">
</div>
</div>
<div class="aigc-photo-card__title color-white font-size-16 font-900">
<div
class="absolute inset-x-0 bottom-[72px] text-center leading-[22px] tracking-normal [text-shadow:0_2px_8px_rgba(0,0,0,0.32)] text-white text-[16px] font-bold">
{{ data.title }}
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
const props = defineProps({
data: {
type: Object,
@@ -34,7 +40,3 @@ const handleAction = () => {
emit("action", props.data);
};
</script>
<style scoped lang="scss">
@import "./styles/index.scss";
</style>

View File

@@ -1,54 +0,0 @@
.aigc-photo-card {
height: 272px;
background: #0f172a;
}
.aigc-photo-card:active {
opacity: 0.86;
}
.aigc-photo-card.is-disabled {
opacity: 0.55;
}
.aigc-photo-card__image {
height: 100%;
}
.aigc-photo-card__shade {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.38);
}
.aigc-photo-card__play {
position: absolute;
left: 50%;
top: 50%;
width: 76px;
height: 76px;
border: 1px solid rgba(255, 255, 255, 0.48);
background: rgba(255, 255, 255, 0.28);
transform: translate(-50%, -50%);
box-sizing: border-box;
}
.aigc-photo-card__triangle {
width: 0;
height: 0;
margin-left: 6px;
border-top: 17px solid transparent;
border-bottom: 17px solid transparent;
border-left: 23px solid #fff;
}
.aigc-photo-card__title {
position: absolute;
left: 0;
right: 0;
bottom: 72px;
text-align: center;
line-height: 22px;
letter-spacing: 0;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.32);
}

View File

@@ -36,7 +36,7 @@
<div class="input-container-send">
<div class="input-container-send-btn" @click="sendMessage">
<div v-if="props.isSessionActive" class="send-stop"> </div>
<div v-if="isSessionActive" class="send-stop"> </div>
<img v-else class="send-icon" src="https://oss.nianxx.cn/mp/static/version_101/home/input_send_icon.png" />
</div>
</div>

View File

@@ -8,7 +8,7 @@
<div class="relative">
<img class="w-full block" :src="mainPageDataModel?.initPageImages?.backgroundImageUrl" style="height: 252px;" />
<div class="absolute bottom-0 left-0 right-0 flex-1">
<div class="px-12 pt-12">
<div class="px-[12px] pt-[12px]">
<Welcome :mainPageDataModel="mainPageDataModel" />
</div>
<div style="margin-bottom: -1px;">
@@ -16,6 +16,116 @@
</div>
</div>
</div>
<div v-show="tabIndex === 0" class="flex-full overflow-hidden min-h-0"
@touchstart.capture="handleScrollAreaTouchStart" @touchstart="handleScrollAreaTouchStart"
@touchmove="handleScrollAreaTouchMove">
<Discovery @scroll-touch-start="handleScrollAreaTouchStart" @scroll-touch="handleScrollAreaTouchMove" />
</div>
<!-- 消息列表可滚动区域 -->
<div v-show="tabIndex === 1" class="flex-full overflow-hidden min-h-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 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))
">
<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" />
<AigcPhotoCard v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.videoCard
" :toolCall="item.toolCall" />
<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
" :activityList="mainPageDataModel.activityList" />
<!-- 先不展示了,等后续有需求再加回来 false -->
<RecommendPostsComponent v-if="
false &&
mainPageDataModel.recommendTheme &&
mainPageDataModel.recommendTheme.length
" :recommendThemeList="mainPageDataModel.recommendTheme" />
</ChatCardOther>
</template>
</div>
</div>
<!-- 输入框区域 -->
<!-- <div>
<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>
@@ -27,7 +137,7 @@ import Welcome from "../Welcome/index.vue";
import AiTabSwitch from "../AiTabSwitch/index.vue";
import Discovery from "../Discovery/index.vue";
import ChatGuide from "../ChatGuide/index.vue";
import AigcPhotoCard from '../AigcPhotoCard/index.vue';
import ChatTopNavBar from "../ChatTopNavBar/index.vue";
import ChatCardAI from "../ChatCardAi/index.vue";
import ChatCardMine from "../ChatCardMine/index.vue";
@@ -373,14 +483,11 @@ const initHandler = () => {
};
onMounted(() => {
try {
getMainPageData();
addNoticeListener();
// 有token时加载最近会话、最近消息、初始化socket
initHandler();
} catch (error) {
console.error("页面初始化错误:", error);
}
console.log("onMounted");
getMainPageData();
addNoticeListener();
// 有token时加载最近会话、最近消息、初始化socket
initHandler();
});
/// =============页面配置↓================
@@ -416,6 +523,7 @@ const getMainPageData = async () => {
mainPageDataModel.value = res.data;
agentId.value = res.data.agentId;
}
appStore.setSceneId(""); // 清空sceneId,分身二次进入展示默认的
};
@@ -1138,7 +1246,3 @@ const resetConfig = () => {
}
};
</script>
<style lang="scss" scoped>
@import "./styles/index.scss";
</style>

View File

@@ -1,6 +0,0 @@
.main-scroll-area {
flex-basis: 0;
height: 0;
min-height: 0;
overscroll-behavior-y: contain;
}

View File

@@ -1,11 +1,13 @@
<template>
<div class="flex w-full">
<div class="flex flex-col flex-full min-width-0 mr-12">
<div class="flex flex-row flex-items-center flex-justify-between min-width-0">
<span class="flex-full min-width-0 text-[20px] text-[600] color-white ellipsis-1">
<div class="flex flex-col flex-full min-width-0 mr-[12px]">
<div class="flex flex-row items-center justify-between min-width-0">
<span class="flex-full min-width-0 text-[20px] font-semibold text-white truncate">
{{ mainPageDataModel.welcomeContent }}
</span>
<span class="shrink-0 text-[20px] text-[600] color-white mt-4"> {{ weatherText }} </span>
<span class="shrink-0 text-[20px] font-semibold text-white mt-[4px]">
{{ weatherText }}
</span>
</div>
<NoticeMessage :tipsMessage="props.mainPageDataModel.tipsMessage" />
@@ -16,9 +18,9 @@
:displayWidth="spriteStyle.displayWidth" :fps="16" />
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import { defineProps, computed } from "vue";
import { defineProps, computed, onMounted, ref } from "vue";
import SpriteAnimator from "@/components/SpriteAnimator/index.vue";
import NoticeMessage from "../NoticeMessage/index.vue";
import { getLocalWeather } from "@/api/home";

View File

@@ -3,8 +3,8 @@
<ChatMainList @showDrawer="showDrawer" />
<!-- 日历组件 -->
<!-- <Calender :visible="calendarVisible" mode="single" :default-value="selectedDate" @close="handleCalendarClose"
@select="handleDateSelect" /> -->
<Calender :visible="calendarVisible" mode="single" :default-value="selectedDate" @close="handleCalendarClose"
@select="handleDateSelect" />
<!-- 更多服务 -->
<MoreService />
@@ -17,67 +17,52 @@
<script setup lang="ts">
import { ref, onUnmounted, onMounted } from "vue";
import { emitter } from '@/utils/events'
// import { getUrlParams } from "@/utils/UrlParams";
// import { useAppStore } from "@/store";
// import { checkToken } from "@/hooks/useGoLogin";
import ChatMainList from "./components/ChatMainList/index.vue";
import MoreService from "./components/MoreService/index.vue";
import DrawerSection from "./components/DrawerSection/index.vue";
// import Calender from "@/components/Calender/index.vue";
import Calender from "@/components/Calender/index.vue";
// const appStore = useAppStore();
// const calendarVisible = ref(false);
// const selectedDate = ref("");
const calendarVisible = ref(false);
const selectedDate = ref("");
// // 处理日历关闭
// const handleCalendarClose = () => {
// calendarVisible.value = false;
// };
// 处理日历关闭
const handleCalendarClose = () => {
calendarVisible.value = false;
};
// // 处理日期选择
// const handleDateSelect = (data) => {
// selectedDate.value = data.date;
// calendarVisible.value = false;
// console.log("选择的日期:", data.date);
// uni.$emit("selectCalendarDate", selectedDate.value); // 传回父组件
// };
// 处理日期选择
const handleDateSelect = (data: any) => {
selectedDate.value = data.date;
calendarVisible.value = false;
console.log("选择的日期:", data.date);
emitter.emit("selectCalendarDate", selectedDate.value); // 传回父组件
};
// const openCalendar = () => {
// calendarVisible.value = true;
// };
const openCalendar = () => {
calendarVisible.value = true;
};
// 打开窗口
const drawerRef = ref(null);
const drawerRef = ref();
const showDrawer = async () => {
// await checkToken();
drawerRef.value?.open?.();
drawerRef.value.open();
};
// 关闭窗口
const closeDrawer = () => drawerRef.value?.close?.();
const closeDrawer = () => drawerRef.value.close();
// ///获取到二维码原始链接内容
// const getWeixinMiniProgramParams = (e) => {
// console.log("Params:", e);
// if (e.q && e.q != "undefined") {
// const qrUrl = decodeURIComponent(e.q);
// const params = getUrlParams(qrUrl);
// appStore.setSceneId(params.sceneId || params.tagId);
// }
// };
// TODO
// onLoad((e) => {
// getWeixinMiniProgramParams(e);
// });
onMounted(() => {
// uni.$on("openCalendar", openCalendar);
emitter.on("openCalendar", openCalendar);
emitter.on("SHOW_DRAWER", showDrawer);
});
onUnmounted(() => {
// uni.$off("openCalendar", openCalendar);
emitter.off("openCalendar", openCalendar);
emitter.off("SHOW_DRAWER", showDrawer);
});
</script>

View File

@@ -40,7 +40,8 @@ export default defineConfig({
open: false,
proxy: {
"/ingress": {
target: "https://abroadbiz.nianxx.com",
// target: "https://abroadbiz.nianxx.com",
target: "https://onefeel.brother7.cn",
changeOrigin: true,
ws: true,
secure: false,