|
|
|
@ -159,13 +159,13 @@ |
|
|
|
<view v-show="message.isThinking" class="thinking-content"> |
|
|
|
<view class="thinking-item"> |
|
|
|
<view class="item-status"> |
|
|
|
<span class="checkmark">✓</span> |
|
|
|
<span v-if="message.isFirst" class="checkmark">✓</span> |
|
|
|
</view> |
|
|
|
<view class="item-text">问题分析完成</view> |
|
|
|
</view> |
|
|
|
<view class="thinking-item"> |
|
|
|
<view class="item-status"> |
|
|
|
<span class="checkmark">✓</span> |
|
|
|
<span v-if="message.isSecond" class="checkmark">✓</span> |
|
|
|
</view> |
|
|
|
<view class="item-text">收集相关信息</view> |
|
|
|
</view> |
|
|
|
@ -222,39 +222,6 @@ |
|
|
|
|
|
|
|
<!-- 搜索历史侧拉框 --> |
|
|
|
<view class="drawer-overlay" v-show="showHistoryDrawer"></view> |
|
|
|
<!-- <view class="drawer-panel" v-show="showHistoryDrawer" @click.stop @touchmove.stop.prevent |
|
|
|
:style="{ transform: 'translateY(' + drawerOffsetY + 'px)' }"> |
|
|
|
|
|
|
|
<view class="drawer-header"> |
|
|
|
<text class="drawer-title">历史对话</text> |
|
|
|
<view class="drawer-actions"> |
|
|
|
<view class="delete-all-container"> |
|
|
|
<image class="delete-icon" src="/static/icons/Group_48095481.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> |
|
|
|
<scroll-view scroll-y="true" class="drawer-content"> |
|
|
|
<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> |
|
|
|
</scroll-view> |
|
|
|
</view> --> |
|
|
|
<view |
|
|
|
class="drawer-panel" |
|
|
|
v-show="showHistoryDrawer" |
|
|
|
@ -279,15 +246,15 @@ |
|
|
|
</view> |
|
|
|
<scroll-view scroll-y="true" class="drawer-content"> |
|
|
|
<view class="drawer-inner"> |
|
|
|
<view v-if="historyList.length === 0" class="empty-history"> |
|
|
|
<view v-if="groupedHistory.length === 0" class="empty-history"> |
|
|
|
<text>暂无历史记录</text> |
|
|
|
</view> |
|
|
|
<view |
|
|
|
v-for="(section, sIdx) in historyList" |
|
|
|
v-for="(section, sIdx) in groupedHistory" |
|
|
|
:key="sIdx" |
|
|
|
class="history-section" |
|
|
|
> |
|
|
|
<text class="section-title">{{ section.stockName }}</text> |
|
|
|
<text class="section-title">{{ section.title }}</text> |
|
|
|
<view |
|
|
|
v-for="(item, idx) in section.items" |
|
|
|
:key="idx" |
|
|
|
@ -302,15 +269,17 @@ |
|
|
|
<text class="history-query">{{ item.stockName }}</text> |
|
|
|
<text class="history-query">({{ item.stockCode }})</text> |
|
|
|
</view> |
|
|
|
<text class="history-time">{{ item.createdTime }}</text> |
|
|
|
<text class="history-time">{{ |
|
|
|
formatTimeForHistory(item.createdTime) |
|
|
|
}}</text> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</scroll-view> |
|
|
|
</view> |
|
|
|
|
|
|
|
<footerBar class="static-footer" :type="type"></footerBar> |
|
|
|
</view> |
|
|
|
<LoginPrompt ref="loginPrompt"></LoginPrompt> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script setup> |
|
|
|
@ -357,6 +326,7 @@ const showHistoryDrawer = ref(false); |
|
|
|
const drawerOffsetY = ref(0); |
|
|
|
const searchHistory = ref([]); |
|
|
|
const historyList = ref([]); |
|
|
|
|
|
|
|
const hotTopics = ref([ |
|
|
|
{ |
|
|
|
id: 1, |
|
|
|
@ -404,8 +374,8 @@ onMounted(() => { |
|
|
|
} |
|
|
|
|
|
|
|
// 载入历史 |
|
|
|
const hist = uni.getStorageSync("search_history") || []; |
|
|
|
searchHistory.value = Array.isArray(hist) ? hist : []; |
|
|
|
// const hist = uni.getStorageSync("search_history") || []; |
|
|
|
// searchHistory.value = Array.isArray(hist) ? hist : []; |
|
|
|
|
|
|
|
// 缓存今天日期(YYYY-MM-DD) |
|
|
|
const todayStr = new Date().toISOString().slice(0, 10); |
|
|
|
@ -454,8 +424,8 @@ const goBlank = () => { |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
// 历史抽屉控制 |
|
|
|
const openHistoryDrawer = async() => { |
|
|
|
// 历史记录 |
|
|
|
const openHistoryDrawer = async () => { |
|
|
|
const res = await postHistory({ |
|
|
|
model: 5, |
|
|
|
}); |
|
|
|
@ -497,65 +467,93 @@ const formatTime = (t) => { |
|
|
|
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; |
|
|
|
// }); |
|
|
|
// 为历史记录格式化时间:YYYY-MM-DD HH:mm |
|
|
|
const formatTimeForHistory = (timeString) => { |
|
|
|
// 假设 timeString 格式为 "YYYY-MM-DD HH:mm:ss" |
|
|
|
const parts = timeString.split(" "); |
|
|
|
if (parts.length >= 2) { |
|
|
|
const datePart = parts[0]; |
|
|
|
const timePart = parts[1]; |
|
|
|
const timeParts = timePart.split(":"); |
|
|
|
if (timeParts.length >= 2) { |
|
|
|
return `${datePart} ${timeParts[0]}:${timeParts[1]}`; |
|
|
|
} |
|
|
|
} |
|
|
|
return timeString; |
|
|
|
}; |
|
|
|
|
|
|
|
// 历史分组(今天/昨天/近一周/按月) |
|
|
|
const groupedHistory = computed(() => { |
|
|
|
const sections = []; |
|
|
|
|
|
|
|
// 从缓存获取今天日期,如果没有则使用当前日期 |
|
|
|
const now = 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(); |
|
|
|
|
|
|
|
// 使用 historyList.value 替代 searchHistory.value |
|
|
|
historyList.value.forEach((item) => { |
|
|
|
// 根据你的数据结构,使用 createdTime 字段 |
|
|
|
const dt = new Date(item.createdTime); |
|
|
|
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: `${year}年${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", []); |
|
|
|
// uni.setStorageSync("search_history", []); |
|
|
|
}; |
|
|
|
|
|
|
|
// 发送消息 |
|
|
|
@ -573,9 +571,9 @@ const sendMessage = () => { |
|
|
|
inputMessage.value = ""; |
|
|
|
|
|
|
|
// 记录搜索历史 |
|
|
|
const entry = { query: userMessage.content, time: Date.now() }; |
|
|
|
searchHistory.value.unshift(entry); |
|
|
|
uni.setStorageSync("search_history", searchHistory.value); |
|
|
|
// const entry = { query: userMessage.content, time: Date.now() }; |
|
|
|
// searchHistory.value.unshift(entry); |
|
|
|
// uni.setStorageSync("search_history", searchHistory.value); |
|
|
|
|
|
|
|
// 发送后强制恢复并滚到底部 |
|
|
|
shouldAutoScroll.value = true; |
|
|
|
@ -595,6 +593,8 @@ const simulateBotResponse = async (userMessage) => { |
|
|
|
isUser: false, |
|
|
|
isTyping: true, |
|
|
|
isThinking: true, |
|
|
|
isFirst: false, |
|
|
|
isSecond: false, |
|
|
|
}; |
|
|
|
|
|
|
|
messages.value.push(botMsg); |
|
|
|
@ -616,10 +616,12 @@ const simulateBotResponse = async (userMessage) => { |
|
|
|
if (res.code !== 200) { |
|
|
|
console.log("未通过意图识别"); |
|
|
|
|
|
|
|
messages.value[messages.value.length - 1].isThinking = false; |
|
|
|
|
|
|
|
// 更新机器人的消息内容 |
|
|
|
const errorMessage = res.message || "请求失败,请稍后重试"; |
|
|
|
let responseText = `我已经收到您的消息: "${userMessage}"。错误信息: "${errorMessage}"`; |
|
|
|
|
|
|
|
|
|
|
|
// 开始打字机效果显示错误信息 |
|
|
|
let index = 0; |
|
|
|
const botIndex = messages.value.length - 1; |
|
|
|
@ -664,6 +666,7 @@ const simulateBotResponse = async (userMessage) => { |
|
|
|
} |
|
|
|
|
|
|
|
console.log("通过意图识别"); |
|
|
|
messages.value[messages.value.length - 1].isFirst = true; |
|
|
|
|
|
|
|
// 获取意图识别结果 |
|
|
|
const recordId = res.data.recordId; |
|
|
|
@ -693,6 +696,9 @@ const simulateBotResponse = async (userMessage) => { |
|
|
|
// console.log(toDataInfo); |
|
|
|
// dataInfo.value = toDataInfo.data; |
|
|
|
// console.log(dataInfo.value); |
|
|
|
|
|
|
|
messages.value[messages.value.length - 1].isSecond = true; |
|
|
|
|
|
|
|
messages.value[messages.value.length - 1].isThinking = false; |
|
|
|
|
|
|
|
// 滚动到底部 |
|
|
|
|