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. 9
      main.js
  4. 267
      pages/deepMate/deepMate.vue
  5. 13
      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) => {
return http({
method: 'POST',
url: '/testApi/api/deepMate/dmSecond',
url: '/api/deepMate/dmSecond',
data
})
}

2
components/login-prompt.vue

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

9
main.js

@ -1,4 +1,4 @@
import LoginPrompt from './components/login-prompt.vue'
import pinia from './stores/index.js'
// #ifndef VUE3
import Vue from 'vue'
@ -7,6 +7,7 @@ import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
Vue.component('LoginPrompt', LoginPrompt)
Vue.config.productionTip = false
@ -17,7 +18,7 @@ const app = new Vue({
pinia
})
app.use(ElementPlus)
for (const [key, component] of Object.entries(ElementPlusIconsVue)){
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.$mount()
@ -57,7 +58,7 @@ function getCurrentLocale() {
})
console.log(language);
return language
}else if (language.indexOf('zh') != -1) {
} else if (language.indexOf('zh') != -1) {
if (language.indexOf('CN') != -1) {
language = 'zh_CN'
uni.setStorageSync('languageData', {
@ -113,6 +114,8 @@ const i18n = createI18n({
})
export function createApp() {
const app = createSSRApp(App)
app.component('LoginPrompt', LoginPrompt)
app.use(pinia)
app.use(i18n)
return {

267
pages/deepMate/deepMate.vue

@ -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,11 +246,11 @@
</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"
>
@ -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,9 +424,9 @@ const goBlank = () => {
});
};
//
const openHistoryDrawer = () => {
const res = postHistory({
//
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);
@ -604,18 +604,70 @@ const simulateBotResponse = async (userMessage) => {
//
const res = await postIntent({
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);
//
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;
}
console.log("通过意图识别");
messages.value[messages.value.length - 1].isFirst = true;
//
const recordId = res.data.recordId;
const parentId = res.data.parentId;
@ -654,6 +706,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;
//

13
pages/home/deepExploration.vue

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

5
utils/http.js

@ -38,9 +38,8 @@ const httpInterceptor = {
}
//4 添加token,优先用store,没有则回退到body中的token,保持与Apifox一致
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) {
options.header.token = token
}

Loading…
Cancel
Save