Browse Source

优化历史结构

wangyi/feature-20251022162725-启动页登录注册
wangyetao 4 weeks ago
parent
commit
63f8144af0
  1. 4
      pages.json
  2. 2
      pages/blank/blank.vue
  3. 275
      pages/deepMate/deepMate.vue

4
pages.json

@ -135,7 +135,9 @@
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"navigationStyle": "custom", "navigationStyle": "custom",
"titleNView": false
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
} }
}, },
{ {

2
pages/blank/blank.vue

@ -1,6 +1,6 @@
<template> <template>
<view class="blank-page"> <view class="blank-page">
<text class="tip">这是一个空白页</text>
<text class="tip">当前特斯拉该如何布局</text>
</view> </view>
</template> </template>

275
pages/deepMate/deepMate.vue

@ -48,7 +48,7 @@
</view> --> </view> -->
<!-- 特斯拉推荐卡片 --> <!-- 特斯拉推荐卡片 -->
<view class="recommend-card" v-if="messages.length === 0">
<view class="recommend-card" v-if="messages.length === 0" @click="goBlank">
<view class="arrow" v-if="messages.length === 0"></view> <view class="arrow" v-if="messages.length === 0"></view>
<view class="card-content"> <view class="card-content">
<image src="../../static/images/tesla-logo.png" class="logo"></image> <image src="../../static/images/tesla-logo.png" class="logo"></image>
@ -82,8 +82,7 @@
<view class="robot-container"> <view class="robot-container">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg" <image src="https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg"
class="robot-avatar"></image> class="robot-avatar"></image>
<view class="welcome-message"> <text class="greeting">Hi, 我是您的股市随身顾问~</text> <text
class="description">个股诊断市场情绪解读都可以找我</text>
<view class="welcome-message"> <text class="greeting">Hi, 我是您的股市随身顾问~</text>
</view> </view>
</view> </view>
</view> </view>
@ -169,19 +168,35 @@
<!-- 搜索历史侧拉框 --> <!-- 搜索历史侧拉框 -->
<view class="drawer-overlay" v-show="showHistoryDrawer"></view> <view class="drawer-overlay" v-show="showHistoryDrawer"></view>
<view class="drawer-panel" v-show="showHistoryDrawer" @click.stop :style="{ transform: 'translateX(' + drawerOffsetX + 'px)' }">
<view class="drawer-back" @click="onDrawerBackClick"><text class="drawer-back-icon">></text></view>
<view class="drawer-panel" v-show="showHistoryDrawer" @click.stop :style="{ transform: 'translateY(' + drawerOffsetY + 'px)' }">
<view class="drawer-header"> <view class="drawer-header">
<text class="drawer-title">搜索历史</text>
<!-- <text class="drawer-close" @click="closeHistoryDrawer">×</text> -->
<text class="drawer-title">历史对话</text>
<view class="drawer-actions">
<view class="delete-all-container">
<image class="delete-icon" src="https://d31zlh4on95l9h.cloudfront.net/images/a62a41f8513bf00b040fd8e79cfe04f4.svg"></image>
<text class="delete-all" @click="clearAllHistory">删除全部</text>
</view>
<view class="drawer-close" @click="onDrawerBackClick"><text class="drawer-close-icon"></text></view>
</view>
</view> </view>
<scroll-view scroll-y="true" class="drawer-content"> <scroll-view scroll-y="true" class="drawer-content">
<view v-if="searchHistory.length === 0" class="empty-history">
<text>暂无搜索历史</text>
</view>
<view v-for="(item, idx) in searchHistory" :key="idx" class="history-card">
<text class="history-query">{{ item.query }}</text>
<text class="history-time">{{ formatTime(item.time) }}</text>
<view class="drawer-inner">
<view v-if="groupedHistory.length === 0" class="empty-history">
<text>暂无历史记录</text>
</view>
<view v-for="(section, sIdx) in groupedHistory" :key="sIdx" class="history-section">
<text class="section-title">{{ section.title }}</text>
<view v-for="(item, idx) in section.items" :key="idx" class="history-item">
<view class="history-left">
<view class="flag-circle"><text class="flag-emoji">🇺🇸</text></view>
</view>
<view class="history-main">
<text class="history-query">{{ item.query }}</text>
</view>
<text class="history-time">{{ formatTime(item.time) }}</text>
</view>
</view>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
@ -262,7 +277,7 @@ const chatContainerHeight = ref(0);
const uuid = ref(""); const uuid = ref("");
const messages = ref([]); const messages = ref([]);
const showHistoryDrawer = ref(false); const showHistoryDrawer = ref(false);
const drawerOffsetX = ref(0);
const drawerOffsetY = ref(0);
const searchHistory = ref([]); const searchHistory = ref([]);
const hotTopics = ref([ const hotTopics = ref([
{ {
@ -314,6 +329,10 @@ onMounted(() => {
// //
const hist = uni.getStorageSync("search_history") || []; const hist = uni.getStorageSync("search_history") || [];
searchHistory.value = Array.isArray(hist) ? hist : []; searchHistory.value = Array.isArray(hist) ? hist : [];
// YYYY-MM-DD
const todayStr = new Date().toISOString().slice(0, 10);
uni.setStorageSync('today_date', todayStr);
}); });
// UUID // UUID
@ -359,13 +378,19 @@ const goBlank = () => {
}; };
// //
const openHistoryDrawer = () => { showHistoryDrawer.value = true; };
const openHistoryDrawer = () => {
const hideDistance = uni.upx2px(900);
drawerOffsetY.value = hideDistance;
showHistoryDrawer.value = true;
setTimeout(() => { drawerOffsetY.value = 0; }, 10);
};
const closeHistoryDrawer = () => { showHistoryDrawer.value = false; }; const closeHistoryDrawer = () => { showHistoryDrawer.value = false; };
const onDrawerBackClick = () => { const onDrawerBackClick = () => {
drawerOffsetX.value = 500;
const hideDistance = uni.upx2px(900);
drawerOffsetY.value = hideDistance;
setTimeout(() => { setTimeout(() => {
closeHistoryDrawer(); closeHistoryDrawer();
drawerOffsetX.value = 0;
drawerOffsetY.value = 0;
}, 180); }, 180);
}; };
@ -381,6 +406,67 @@ const formatTime = (t) => {
return `${y}-${m}-${day} ${hh}:${mm}`; return `${y}-${m}-${day} ${hh}:${mm}`;
}; };
// ///
const groupedHistory = computed(() => {
const sections = [];
// 使
const cachedTodayStr = uni.getStorageSync('today_date');
const now = cachedTodayStr ? new Date(cachedTodayStr + 'T00:00:00') : new Date();
const startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
const isSameDay = (a, b) => startOfDay(a).getTime() === startOfDay(b).getTime();
const isYesterday = (d) => {
const y = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
return isSameDay(d, y);
};
const isToday = (d) => isSameDay(d, now);
const withinLast7Days = (d) => {
const seven = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7);
return d >= seven && !isToday(d) && !isYesterday(d);
};
const monthLabel = (d) => `${d.getMonth() + 1}`;
const today = [];
const yesterday = [];
const last7 = [];
const byMonth = new Map();
searchHistory.value.forEach((item) => {
const dt = new Date(item.time);
if (isToday(dt)) {
today.push(item);
} else if (isYesterday(dt)) {
yesterday.push(item);
} else if (withinLast7Days(dt)) {
last7.push(item);
} else {
const year = dt.getFullYear();
const month = dt.getMonth() + 1;
const key = `${year}-${month}`;
if (!byMonth.has(key)) byMonth.set(key, { title: `${month}`, year, month, items: [] });
byMonth.get(key).items.push(item);
}
});
if (today.length) sections.push({ title: '今天', items: today });
if (yesterday.length) sections.push({ title: '昨天', items: yesterday });
if (last7.length) sections.push({ title: '近一周', items: last7 });
const monthSections = Array.from(byMonth.values()).sort((a, b) => {
if (a.year !== b.year) return b.year - a.year;
return b.month - a.month; // 10 9
});
sections.push(...monthSections);
return sections;
});
const clearAllHistory = () => {
searchHistory.value = [];
uni.setStorageSync('search_history', []);
};
// //
const sendMessage = () => { const sendMessage = () => {
if (inputMessage.value.trim() === "" || isSending.value) return; if (inputMessage.value.trim() === "" || isSending.value) return;
@ -817,7 +903,7 @@ const onBackTopClick = () => {
.section-title { .section-title {
display: block; display: block;
text-align: center;
text-align: left;
font-size: 26rpx; font-size: 26rpx;
color: #666666; color: #666666;
margin-bottom: 20rpx; margin-bottom: 20rpx;
@ -872,9 +958,10 @@ const onBackTopClick = () => {
margin-bottom: 30rpx; margin-bottom: 30rpx;
} }
/* .user-message {
.user-message {
flex-direction: row-reverse; flex-direction: row-reverse;
} */
justify-content: flex-start;
}
.message-icon { .message-icon {
font-size: 24rpx; font-size: 24rpx;
@ -890,16 +977,14 @@ const onBackTopClick = () => {
} }
.user-message .message-icon { .user-message .message-icon {
background-color: transparent;
border-radius: 0;
/* padding: 0;
width: auto;
height: auto; */
color: #333;
background-color: #007aff;
border-radius: 50%;
color: #fff;
/* box-shadow: 0 0 12rpx rgba(0, 122, 255, 0.4); */
} }
.bot-message .message-icon { .bot-message .message-icon {
background: url('https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg');
background: url('https://d31zlh4on95l9h.cloudfront.net/images/e723171126bd31c52137709ebbd1a7ea.svg');
color: white; color: white;
} }
@ -910,9 +995,10 @@ const onBackTopClick = () => {
} }
.user-message .message-content { .user-message .message-content {
background-color: #007aff;
border-radius: 10rpx;
padding: 15rpx;
/* background-color: #007aff; */
border: 2rpx solid #f3908f;
border-radius: 20rpx;
padding: 10rpx;
} }
.bot-message .message-content { .bot-message .message-content {
@ -927,7 +1013,7 @@ const onBackTopClick = () => {
} }
.user-message .message-text { .user-message .message-text {
color: white;
color:black;
} }
.bot-message .message-text { .bot-message .message-text {
@ -1119,45 +1205,87 @@ const onBackTopClick = () => {
.drawer-panel { .drawer-panel {
position: fixed; position: fixed;
top: 0;
left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
width: 600rpx;
max-width: 75%;
height: 75vh;
max-height: 80vh;
width: 100%;
background: #ffffff; background: #ffffff;
box-shadow: -8rpx 0 20rpx rgba(0, 0, 0, 0.08);
z-index: 901;
box-shadow: 0 -8rpx 20rpx rgba(0, 0, 0, 0.06);
z-index: 1000;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
transition: transform 0.2s ease;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
transition: transform 0.22s ease;
} }
.drawer-back { .drawer-back {
position: absolute; position: absolute;
left: -14px;
top: 50%;
transform: translateY(-50%);
left: 50%;
top: -14px;
transform: translateX(-50%);
width: 28px; width: 28px;
height: 28px;
border-radius: 14px;
height: 48px;
border-radius: 12px;
background: #fff; background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,.15);
border: 1px solid #eee;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.drawer-back-icon { .drawer-back-icon {
font-size: 16px; font-size: 16px;
color: #666;
color: #8a8a8a;
}
.drawer-actions {
display: flex;
align-items: center;
gap: 40rpx;
}
.delete-all-container {
display: flex;
align-items: center;
gap: 14rpx;
}
.delete-icon {
width: 45rpx;
height: 40rpx;
}
.delete-all {
font-size: 28rpx;
}
.drawer-close {
background: url('https://d31zlh4on95l9h.cloudfront.net/images/444fbe3218954f3f907664c91025c4e4.svg');
width: 48rpx;
height: 48rpx;
border-radius: 24rpx;
/* background: #f5f5f5; */
/* box-shadow: 0 2px 8px rgba(0,0,0,0.08); */
display: flex;
align-items: center;
justify-content: center;
}
.drawer-close-icon {
font-size: 24rpx;
color: #8a8a8a;
} }
.drawer-header { .drawer-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 24rpx 28rpx;
border-bottom: 2rpx solid #f0f0f0;
padding: 52rpx 28rpx 0rpx 28rpx;
/* border-bottom: 2rpx solid #f0f0f0; */
} }
.drawer-title { .drawer-title {
@ -1173,7 +1301,58 @@ const onBackTopClick = () => {
.drawer-content { .drawer-content {
flex: 1; flex: 1;
padding: 20rpx 24rpx;
min-height: 0; /* 让 flex 子元素可在容器内收缩以启用滚动 */
}
.drawer-inner {
padding: 20rpx 24rpx 20rpx 24rpx;
}
.history-section {
margin-bottom: 20rpx;
/* margin: 0 24rpx; */
}
.section-title {
font-size: 26rpx;
color: #888;
margin: 10rpx 6rpx 16rpx;
}
.history-item {
display: flex;
align-items: center;
padding: 19rpx 18rpx;
background-color: #f6f7f9;
border-radius: 12rpx;
margin-bottom: 12rpx;
}
.history-left { margin-right: 12rpx; }
.flag-circle {
width: 36rpx;
height: 36rpx;
border-radius: 50%;
background: #fff;
border: 2rpx solid #eee;
display: flex;
align-items: center;
justify-content: center;
}
.flag-emoji { font-size: 24rpx; }
.history-main { flex: 1; }
.history-query {
font-size: 28rpx;
color: #333;
}
.history-time {
font-size: 22rpx;
color: #999;
} }
.history-card { .history-card {

Loading…
Cancel
Save