Browse Source

Merge branch 'wangyi/feature-20251026183100-deepmate王毅' into milestone-20251031-简版功能开发

zhaowenkang/feature-20251028181547-行情页面
Ethereal 4 weeks ago
parent
commit
51d740aca9
  1. 2
      api/deepMate/deepMate.js
  2. 2
      components/login-prompt.vue
  3. 45
      main.js
  4. 267
      pages/deepMate/deepMate.vue
  5. 15
      pages/home/deepExploration.vue
  6. 5
      utils/http.js

2
api/deepMate/deepMate.js

@ -34,7 +34,7 @@ export const postIntent = (data) => {
export const postStock = (data) => { export const postStock = (data) => {
return http({ return http({
method: 'POST', method: 'POST',
url: '/testApi/api/deepMate/dmSecond',
url: '/api/deepMate/dmSecond',
data data
}) })
} }

2
components/login-prompt.vue

@ -23,6 +23,8 @@ const userStore = useUserStore();
onMounted(() => { onMounted(() => {
if (!userStore.userInfo) { if (!userStore.userInfo) {
show(); show();
} }
}); });

45
main.js

@ -1,4 +1,4 @@
import LoginPrompt from './components/login-prompt.vue'
import pinia from './stores/index.js' import pinia from './stores/index.js'
// #ifndef VUE3 // #ifndef VUE3
import Vue from 'vue' import Vue from 'vue'
@ -7,17 +7,18 @@ import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue' import * as ElementPlusIconsVue from '@element-plus/icons-vue'
Vue.component('LoginPrompt', LoginPrompt)
Vue.config.productionTip = false Vue.config.productionTip = false
App.mpType = 'app' App.mpType = 'app'
const app = new Vue({ const app = new Vue({
...App,
...App,
pinia pinia
}) })
app.use(ElementPlus) app.use(ElementPlus)
for (const [key, component] of Object.entries(ElementPlusIconsVue)){
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component) app.component(key, component)
} }
app.$mount() app.$mount()
@ -57,7 +58,7 @@ function getCurrentLocale() {
}) })
console.log(language); console.log(language);
return language return language
}else if (language.indexOf('zh') != -1) {
} else if (language.indexOf('zh') != -1) {
if (language.indexOf('CN') != -1) { if (language.indexOf('CN') != -1) {
language = 'zh_CN' language = 'zh_CN'
uni.setStorageSync('languageData', { uni.setStorageSync('languageData', {
@ -99,24 +100,26 @@ function getCurrentLocale() {
} }
// 创建 i18n 实例 // 创建 i18n 实例
const i18n = createI18n({ const i18n = createI18n({
locale: getCurrentLocale(),
legacy: false, // 使用 Composition API 模式
globalInjection: true, // 全局注入 $t 函数
messages: {
'en': en,
'ms': ms,
'th': th,
'vi': vi,
'zh_CN': zh_CN,
'zh_HK': zh_HK
}
locale: getCurrentLocale(),
legacy: false, // 使用 Composition API 模式
globalInjection: true, // 全局注入 $t 函数
messages: {
'en': en,
'ms': ms,
'th': th,
'vi': vi,
'zh_CN': zh_CN,
'zh_HK': zh_HK
}
}) })
export function createApp() { export function createApp() {
const app = createSSRApp(App)
app.use(pinia)
app.use(i18n)
return {
app
}
const app = createSSRApp(App)
app.component('LoginPrompt', LoginPrompt)
app.use(pinia)
app.use(i18n)
return {
app
}
} }
// #endif // #endif

267
pages/deepMate/deepMate.vue

@ -159,13 +159,13 @@
<view v-show="message.isThinking" class="thinking-content"> <view v-show="message.isThinking" class="thinking-content">
<view class="thinking-item"> <view class="thinking-item">
<view class="item-status"> <view class="item-status">
<span class="checkmark"></span>
<span v-if="message.isFirst" class="checkmark"></span>
</view> </view>
<view class="item-text">问题分析完成</view> <view class="item-text">问题分析完成</view>
</view> </view>
<view class="thinking-item"> <view class="thinking-item">
<view class="item-status"> <view class="item-status">
<span class="checkmark"></span>
<span v-if="message.isSecond" class="checkmark"></span>
</view> </view>
<view class="item-text">收集相关信息</view> <view class="item-text">收集相关信息</view>
</view> </view>
@ -222,39 +222,6 @@
<!-- 搜索历史侧拉框 --> <!-- 搜索历史侧拉框 -->
<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 @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 <view
class="drawer-panel" class="drawer-panel"
v-show="showHistoryDrawer" v-show="showHistoryDrawer"
@ -279,11 +246,11 @@
</view> </view>
<scroll-view scroll-y="true" class="drawer-content"> <scroll-view scroll-y="true" class="drawer-content">
<view class="drawer-inner"> <view class="drawer-inner">
<view v-if="historyList.length === 0" class="empty-history">
<view v-if="groupedHistory.length === 0" class="empty-history">
<text>暂无历史记录</text> <text>暂无历史记录</text>
</view> </view>
<view <view
v-for="(section, sIdx) in historyList"
v-for="(section, sIdx) in groupedHistory"
:key="sIdx" :key="sIdx"
class="history-section" class="history-section"
> >
@ -302,15 +269,17 @@
<text class="history-query">{{ item.stockName }}</text> <text class="history-query">{{ item.stockName }}</text>
<text class="history-query">{{ item.stockCode }}</text> <text class="history-query">{{ item.stockCode }}</text>
</view> </view>
<text class="history-time">{{ item.createdTime }}</text>
<text class="history-time">{{
formatTimeForHistory(item.createdTime)
}}</text>
</view> </view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<footerBar class="static-footer" :type="type"></footerBar> <footerBar class="static-footer" :type="type"></footerBar>
</view> </view>
<LoginPrompt ref="loginPrompt"></LoginPrompt>
</template> </template>
<script setup> <script setup>
@ -357,6 +326,7 @@ const showHistoryDrawer = ref(false);
const drawerOffsetY = ref(0); const drawerOffsetY = ref(0);
const searchHistory = ref([]); const searchHistory = ref([]);
const historyList = ref([]); const historyList = ref([]);
const hotTopics = ref([ const hotTopics = ref([
{ {
id: 1, 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 // YYYY-MM-DD
const todayStr = new Date().toISOString().slice(0, 10); const todayStr = new Date().toISOString().slice(0, 10);
@ -454,9 +424,9 @@ const goBlank = () => {
}); });
}; };
//
const openHistoryDrawer = () => {
const res = postHistory({
//
const openHistoryDrawer = async () => {
const res = await postHistory({
model: 5, model: 5,
}); });
@ -497,65 +467,93 @@ 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;
// });
// 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 = () => { const clearAllHistory = () => {
searchHistory.value = []; searchHistory.value = [];
uni.setStorageSync("search_history", []);
// uni.setStorageSync("search_history", []);
}; };
// //
@ -573,9 +571,9 @@ const sendMessage = () => {
inputMessage.value = ""; 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; shouldAutoScroll.value = true;
@ -595,6 +593,8 @@ const simulateBotResponse = async (userMessage) => {
isUser: false, isUser: false,
isTyping: true, isTyping: true,
isThinking: true, isThinking: true,
isFirst: false,
isSecond: false,
}; };
messages.value.push(botMsg); messages.value.push(botMsg);
@ -604,18 +604,70 @@ const simulateBotResponse = async (userMessage) => {
// //
const res = await postIntent({ const res = await postIntent({
content: userMessage, content: userMessage,
language: 'cn',
marketList: 'hk,cn,usa,my,sg,vi,in,gb',
token: "pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q",
language: "cn",
marketList: "hk,cn,usa,my,sg,vi,in,gb",
token:
"pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q",
}); });
console.log("res" + res); console.log("res" + res);
// //
if (res.code !== 200) { 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;
const typeWriter = () => {
if (index < responseText.length) {
const ch = responseText.charAt(index);
const current = messages.value[botIndex];
//
messages.value.splice(botIndex, 1, {
...current,
content: current.content + ch,
isTyping: true,
});
index++;
scrollToBottom();
//
const baseDelay = 5; //
const slowPunct = /[。!?!?;;]/; //
const midPunct = /[,、,::]/; //
const delay = slowPunct.test(ch)
? 220
: midPunct.test(ch)
? 120
: baseDelay;
setTimeout(typeWriter, delay);
} else {
//
const current = messages.value[botIndex];
messages.value.splice(botIndex, 1, { ...current, isTyping: false });
isSending.value = false;
nextTick(() => {
scrollToBottom();
});
}
};
//
setTimeout(typeWriter, 300);
return; return;
} }
console.log("通过意图识别");
messages.value[messages.value.length - 1].isFirst = true;
// //
const recordId = res.data.recordId; const recordId = res.data.recordId;
const parentId = res.data.parentId; const parentId = res.data.parentId;
@ -654,6 +706,9 @@ const simulateBotResponse = async (userMessage) => {
// console.log(toDataInfo); // console.log(toDataInfo);
// dataInfo.value = toDataInfo.data; // dataInfo.value = toDataInfo.data;
// console.log(dataInfo.value); // console.log(dataInfo.value);
messages.value[messages.value.length - 1].isSecond = true;
messages.value[messages.value.length - 1].isThinking = false; messages.value[messages.value.length - 1].isThinking = false;
// //

15
pages/home/deepExploration.vue

@ -1,11 +1,16 @@
<template> <template>
<view class="content"> <view class="content">
<view class="text-area">
</view>
<view class="text-area"> </view>
<LoginPrompt ref="loginPrompt"></LoginPrompt> <LoginPrompt ref="loginPrompt"></LoginPrompt>
<button @click="showLoginPrompt">deepMate</button>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
<button @click="showLoginPrompt">deepMate</button>
<text class="title" @click="showLoginPrompt">{{ title }}</text>
</view> </view>
</template> </template>
@ -20,6 +25,8 @@ function showLoginPrompt() {
userStore.clearUserInfo(); userStore.clearUserInfo();
} }
console.log(userStore.userInfo);
function toDeepMate() { function toDeepMate() {
uni.navigateTo({ uni.navigateTo({
url: "/pages/deepMate/deepMate", url: "/pages/deepMate/deepMate",

5
utils/http.js

@ -38,9 +38,8 @@ const httpInterceptor = {
} }
//4 添加token,优先用store,没有则回退到body中的token,保持与Apifox一致 //4 添加token,优先用store,没有则回退到body中的token,保持与Apifox一致
const memberStore = useUserStore() const memberStore = useUserStore()
// const token = memberStore.userInfo?.token || options.data?.token
options.header.token = 'dccec0b65a94f498b8183a17589ab16e'
const token = 'dccec0b65a94f498b8183a17589ab16e'
const token = memberStore.userInfo?.token || options.data?.token
// const token = 'dccec0b65a94f498b8183a17589ab16e'
if (token) { if (token) {
options.header.token = token options.header.token = token
} }

Loading…
Cancel
Save