Compare commits

...

76 Commits

Author SHA1 Message Date
宋杰 99c64b3a4d 解决历史记录删除时二次确认框遮挡问题。 46 minutes ago
宋杰 6ac1e2f161 修改移动端历史记录对话框样式异常问题。 1 hour ago
宋杰 879cddb311 股市温度计样式调整。 2 hours ago
宋杰 e1b9ec79e0 解决情绪能量转化器y轴遮挡问题。 2 hours ago
宋杰 4c32ba21b4 股市温度计样式调整。 2 hours ago
宋杰 cbc56a2846 情绪大模型去除对话时间。 2 hours ago
宋杰 27d052fddb 情绪解码器的图表样式调整。 2 hours ago
宋杰 5b98d842d0 情绪大模型在小屏中免责声明的字体修改。 3 hours ago
宋杰 c86ea9cb3f 解决情绪大模型搜索相同股票时互相影响的问题。 3 hours ago
宋杰 f0242c88b9 解决思考过程对话样式问题。 4 hours ago
宋杰 7010a9c76e 解决公告搜索会出现两次对话的问题。 4 hours ago
宋杰 9a033e2ff5 解决情绪大模型搜索同一只股票时音频不会自动播放的问题。 4 hours ago
宋杰 ef2b92996b 解决输入内容过长时会超出的问题。 5 hours ago
no99 5bb0fc6f4d Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 5 hours ago
no99 2e1cbb3e58 打开console语句 5 hours ago
宋杰 05b4f2e230 公告页左上角logo取消;情绪大模型ai回答靠左的问题; 5 hours ago
宋杰 6380772061 情绪大模型文本的内边距增加。 6 hours ago
no99 fe9294aaa1 四步不换行问题和输入框高度问题 6 hours ago
宋杰 486f28b07e 历史记录显示用户输入的内容; 6 hours ago
宋杰 96e1ac25a9 情绪大模型免责声明放在外面。 7 hours ago
宋杰 0b0e2c88f5 情绪能量转化器默认展示一半K线。 9 hours ago
宋杰 33da64acb4 情绪探底雷达默认展示一半的的股票数据。 9 hours ago
宋杰 a1c96a9977 股市温度计默认展示一半K线。 9 hours ago
宋杰 332fd10fec 情绪解码器默认展示一半K线。 9 hours ago
宋杰 5b0b2129bb 情绪大模型免责声明调整到外面;小屏股市温度计适配; 10 hours ago
宋杰 1b2dcc1cfe 解决小屏的情绪解码器有两个dataZoom的问题。 24 hours ago
宋杰 0055c8c9a0 Merge branch 'songjie/feature-20250628160649-上线前优化' into milestone-20250710-上线前优化 24 hours ago
宋杰 492e7b5e32 解决从首页直接到情绪大模型没有横线标识的问题; 24 hours ago
no99 80131f76ef Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 1 day ago
no99 4fd87b97ff 打开手机控制台 1 day ago
no99 7905582284 Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 1 day ago
no99 5e0157b162 1.历史记录的消息改为keyword。 1 day ago
宋杰 2e83f2cf7b 情绪大模型历史记录展示对话时间和接口统一。 1 day ago
宋杰 4f0f33d196 解决情绪大模型遮挡金轮的问题。 1 day ago
宋杰 ca6f8b590a 夺宝奇兵大模型思考过程后不再出现“......” 1 day ago
宋杰 c14a59fb29 修改选择模型页面样式问题。 1 day ago
no99 b187f613bf Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 1 day ago
no99 e185c4679c 1.app手机返回消息异常; 1 day ago
宋杰 9ad6acd078 Merge branch 'milestone-20250710-上线前优化' of http://39.101.133.168:8807/hongxilin/AIxiaocaishen into milestone-20250710-上线前优化 1 day ago
宋杰 e003a93b76 解决情绪大模型搜索股票后再查看历史记录输入框一直禁用的问题。 1 day ago
no99 d5d8b95cc4 Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 1 day ago
no99 4b7b2b0258 情绪大模型和夺宝奇兵大模型历史记录开关分开控制 1 day ago
宋杰 a85ade2bb2 解决情绪大模型音频喇叭状态的问题; 1 day ago
宋杰 e6be67c018 解决新股票结论覆盖旧股票结论的问题; 1 day ago
no99 cc952e0121 正在播放其他音频的过程中,发送消息后播放新音频时,旧音频按钮状态未改变的问题 1 day ago
no99 e0beca81d2 手机版回绝文案溢出问题 1 day ago
宋杰 4c65491889 新增在情绪解码器热力矩阵区域也能缩放; 1 day ago
宋杰 d398e6ac10 Merge branch 'songjie/feature-20250628160649-上线前优化' into milestone-20250710-上线前优化 2 days ago
宋杰 5cb72d6775 情绪大模型喇叭颜色校正; 2 days ago
no99 98c4d841f2 音频问题1 2 days ago
宋杰 6e85ce2338 修改手机端样式; 2 days ago
宋杰 df0f904764 情绪能量转化器中情绪临界区字体颜色修改。 2 days ago
宋杰 b4474927b1 解决第一个接口失败的提示语宽度超出的问题; 2 days ago
宋杰 0ac0744283 第一个工作流请求失败使用接口返回发msg。 2 days ago
宋杰 f3f3896248 Merge branch 'milestone-20250710-上线前优化' of http://39.101.133.168:8807/hongxilin/AIxiaocaishen into milestone-20250710-上线前优化 2 days ago
宋杰 4cab11d3e2 Merge branch 'songjie/feature-20250628160649-上线前优化' into milestone-20250710-上线前优化 2 days ago
宋杰 eeb51c14dc 思考过程完成后不再出现后端的kaishi字段内容; 2 days ago
no99 ac4171fddc Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 2 days ago
no99 c83c36e43c 情绪大模型用户信息添加发送时间 2 days ago
宋杰 55ada1f88c Merge branch 'milestone-20250710-上线前优化' of http://39.101.133.168:8807/hongxilin/AIxiaocaishen into milestone-20250710-上线前优化 2 days ago
宋杰 7f5d3ce5a6 情绪大模型取消对话数限制,并且查询同一只股票不再去重; 2 days ago
no99 bd40aa2408 Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 2 days ago
no99 7677bb7459 夺宝奇兵大模型用户信息添加发送时间 2 days ago
宋杰 c16773e469 情绪大模型返回顶部全局唯一;情绪大模型手机端加入背景颜色; 2 days ago
no99 baabaf73c0 Merge branch 'hongxilin/feature-20250628153758-财神优化:字正确性,一致性等' into milestone-20250710-上线前优化 2 days ago
no99 8ab9e36bde 1.修改用户反馈和公告的位置; 2 days ago
宋杰 dd99f8a220 两个模型的思考过程修改完成;情绪大模型新增计算属性显示对话; 2 days ago
宋杰 4636df2f07 思考过程动图在文本框内部; 2 days ago
宋杰 5236ecc4ba 修改免责声明字体; 2 days ago
宋杰 f1da05ac3d 情绪大模型搜索股票时记录实时更新; 3 days ago
宋杰 4a8daf207a 思考过程使用导入图片的方式; 3 days ago
宋杰 37598eef94 历史记录条目展示股票名称加代码; 3 days ago
宋杰 71df42d399 Merge branch 'milestone-20250710-上线前优化' of http://39.101.133.168:8807/hongxilin/AIxiaocaishen into milestone-20250710-上线前优化 3 days ago
no99 8c0749ed7e 返回首页,获取历史纪录的数据返回格式更改 3 days ago
宋杰 56bd68c1f8 获取历史记录接口没有数据时前端不会报错; 3 days ago
宋杰 1d1e2cbefd 修改情绪大模型字体大小;开发环境加前缀; 3 days ago
  1. 2
      .env.development
  2. 4
      build/vite/build.js
  3. 2
      src/store/chat.js
  4. 35
      src/store/emotion.ts
  5. 278
      src/views/AIchat.vue
  6. 2795
      src/views/AiEmotion.vue
  7. 4
      src/views/DBQBmodel.vue
  8. 2
      src/views/Emotionsmodel.vue
  9. 258
      src/views/components/HistoryRecord.vue
  10. 10
      src/views/components/emoEnergyConverter.vue
  11. 41
      src/views/components/emotionDecod.vue
  12. 4
      src/views/components/emotionalBottomRadar.vue
  13. 4
      src/views/components/marketTemperature.vue
  14. 199
      src/views/homePage.vue

2
.env.development

@ -2,7 +2,7 @@
VITE_ENV = 'development' VITE_ENV = 'development'
VITE_OUTPUT_DIR = 'dev' VITE_OUTPUT_DIR = 'dev'
# public path # public path
VITE_PUBLIC_PATH = /
VITE_PUBLIC_PATH = /aixiaocaishen
#新数据接口 #新数据接口
VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link" VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link"

4
build/vite/build.js

@ -36,8 +36,8 @@ export function createBuild(viteEnv) {
// 压缩配置 // 压缩配置
terserOptions: { terserOptions: {
compress: { compress: {
drop_console: true, // 生产环境移除console
drop_debugger: true // 生产环境移除debugger
drop_console: false, // 生产环境移除console
drop_debugger: false // 生产环境移除debugger
} }
} }
}; };

2
src/store/chat.js

@ -11,6 +11,8 @@ export const useChatStore = defineStore("chat", {
searchRecord: false, searchRecord: false,
currentUserIndex: null, currentUserIndex: null,
announcementMsg: null, announcementMsg: null,
aiChatCall:false,
aiEmotionCall:false
}), }),
actions: { actions: {
async getUserCount() { async getUserCount() {

35
src/store/emotion.ts

@ -6,9 +6,7 @@ export const useEmotionStore = defineStore('emotion', {
history: [] as HistoryItem[], // 历史记录数组 history: [] as HistoryItem[], // 历史记录数组
stockList: [] as StockData[], // 当前显示的股票列表 stockList: [] as StockData[], // 当前显示的股票列表
activeStockIndex: 0, // 当前激活的股票索引 activeStockIndex: 0, // 当前激活的股票索引
maxStocks: 10, // 最大股票数量限制
conversations: [] as ConversationMessage[], // 对话消息数组 conversations: [] as ConversationMessage[], // 对话消息数组
maxConversations: 100, // 最大对话数量限制
}), }),
persist: { persist: {
key: 'emotion-store', key: 'emotion-store',
@ -22,12 +20,8 @@ export const useEmotionStore = defineStore('emotion', {
}, },
// 获取股票数量 // 获取股票数量
stockCount: (state) => state.stockList.length, stockCount: (state) => state.stockList.length,
// 是否达到最大股票数量
isMaxStocks: (state) => state.stockList.length >= state.maxStocks,
// 获取对话数量 // 获取对话数量
conversationCount: (state) => state.conversations.length, conversationCount: (state) => state.conversations.length,
// 是否达到最大对话数量
isMaxConversations: (state) => state.conversations.length >= state.maxConversations,
// 获取最近的对话消息 // 获取最近的对话消息
recentConversations: (state) => { recentConversations: (state) => {
return state.conversations.slice(-20); // 返回最近20条对话 return state.conversations.slice(-20); // 返回最近20条对话
@ -44,28 +38,9 @@ export const useEmotionStore = defineStore('emotion', {
}, },
// 添加新股票 // 添加新股票
addStock(stockData: StockData) { addStock(stockData: StockData) {
// 检查是否已存在相同的股票
const existingIndex = this.stockList.findIndex(
stock => stock.stockInfo.code === stockData.stockInfo.code &&
stock.stockInfo.market === stockData.stockInfo.market
);
if (existingIndex !== -1) {
// 如果股票已存在,更新数据并切换到该股票
this.stockList[existingIndex] = stockData;
this.activeStockIndex = existingIndex;
} else {
// 如果达到最大数量,移除最旧的股票
if (this.stockList.length >= this.maxStocks) {
this.stockList.shift();
if (this.activeStockIndex > 0) {
this.activeStockIndex--;
}
}
// 添加新股票并设为当前激活
this.stockList.push(stockData);
this.activeStockIndex = this.stockList.length - 1;
}
// 添加新股票并设为当前激活
this.stockList.push(stockData);
this.activeStockIndex = this.stockList.length - 1;
// 同时添加到历史记录 // 同时添加到历史记录
// this.addHistory({ // this.addHistory({
@ -130,10 +105,6 @@ export const useEmotionStore = defineStore('emotion', {
}, },
// 添加对话消息 // 添加对话消息
addConversation(message: ConversationMessage) { addConversation(message: ConversationMessage) {
// 如果达到最大数量,移除最旧的消息
if (this.conversations.length >= this.maxConversations) {
this.conversations.shift();
}
// 添加新消息到数组末尾 // 添加新消息到数组末尾
this.conversations.push({ this.conversations.push({
...message, ...message,

278
src/views/AIchat.vue

@ -18,6 +18,10 @@ import { useChatStore } from "../store/chat";
import { useAudioStore } from "../store/audio"; import { useAudioStore } from "../store/audio";
import { useDataStore } from "@/store/dataList.js"; import { useDataStore } from "@/store/dataList.js";
import { marked } from "marked"; // marked import { marked } from "marked"; // marked
// GIF
import thinkingGif from "@/assets/img/gif/思考.gif";
import analyzeGif from "@/assets/img/gif/解析.gif";
import generateGif from "@/assets/img/gif/生成.gif";
import katex from "katex"; // KaTeX import katex from "katex"; // KaTeX
import { htmlToText } from "html-to-text"; import { htmlToText } from "html-to-text";
import { Howl, Howler } from "howler"; import { Howl, Howler } from "howler";
@ -145,7 +149,7 @@ const playNextAudio = () => {
setTimeout(() => { setTimeout(() => {
isCallingPlayNext = false; isCallingPlayNext = false;
playNextAudio(); playNextAudio();
}, 500);
}, 200);
} else { } else {
console.log("🎉 所有音频播放完成,清除音频实例"); console.log("🎉 所有音频播放完成,清除音频实例");
chatStore.messages[chatStore.currentUserIndex].audioStatus = false; chatStore.messages[chatStore.currentUserIndex].audioStatus = false;
@ -748,7 +752,6 @@ const createTypingEffect = (message, content, speed) => {
if (message.end) { if (message.end) {
chatStore.getUserCount(); chatStore.getUserCount();
chatStore.isLoading = false; chatStore.isLoading = false;
chatStore.searchRecord = true;
console.log("打印完毕,接触输入框禁用状态"); console.log("打印完毕,接触输入框禁用状态");
emit("enableInput"); emit("enableInput");
} }
@ -952,8 +955,9 @@ async function showThinkingProcess(stockName = null) {
class: "ing", class: "ing",
type: "ing", type: "ing",
flag: true, flag: true,
content: "正在思考......",
gif: "/src/assets/img/gif/思考.gif",
content: "夺宝奇兵大模型正在思考",
gif: thinkingGif,
nowrap: true,
}); });
chatStore.messages.push(thinkingMessage1); chatStore.messages.push(thinkingMessage1);
await new Promise((resolve) => setTimeout(resolve, 1500)); await new Promise((resolve) => setTimeout(resolve, 1500));
@ -965,8 +969,9 @@ async function showThinkingProcess(stockName = null) {
class: "ing", class: "ing",
type: "ing", type: "ing",
flag: true, flag: true,
content: "正在解析关键数据......",
gif: "/src/assets/img/gif/解析.gif",
content: "正在解析关键数据",
gif: analyzeGif,
nowrap: true,
}); });
chatStore.messages.push(thinkingMessage2); chatStore.messages.push(thinkingMessage2);
@ -985,8 +990,9 @@ async function showThinkingProcess(stockName = null) {
class: "ing", class: "ing",
type: "ing", type: "ing",
flag: true, flag: true,
content: `正在生成${stockName}全景作战报告......`,
gif: "/src/assets/img/gif/生成.gif",
content: `正在生成${stockName}全景作战报告`,
gif: generateGif,
nowrap: true,
}); });
chatStore.messages.push(thinkingMessage3); chatStore.messages.push(thinkingMessage3);
await new Promise((resolve) => setTimeout(resolve, 1500)); await new Promise((resolve) => setTimeout(resolve, 1500));
@ -997,9 +1003,8 @@ async function showThinkingProcess(stockName = null) {
sender: "ai", sender: "ai",
class: "ing", class: "ing",
type: "ing", type: "ing",
flag: true,
content: "报告已生成!", content: "报告已生成!",
gif: "/src/assets/img/gif/生成.gif",
nowrap: true,
}); });
chatStore.messages.push(thinkingMessage4); chatStore.messages.push(thinkingMessage4);
await new Promise((resolve) => setTimeout(resolve, 1500)); await new Promise((resolve) => setTimeout(resolve, 1500));
@ -1027,8 +1032,8 @@ async function continueThinkingProcess(thinkingMessageRef, stockName) {
class: "ing", class: "ing",
type: "ing", type: "ing",
flag: true, flag: true,
content: `正在生成${stockName}全景作战报告......`,
gif: "/src/assets/img/gif/生成.gif",
content: `正在生成${stockName}全景作战报告`,
gif: generateGif,
}); });
chatStore.messages.push(thinkingMessage3); chatStore.messages.push(thinkingMessage3);
await new Promise((resolve) => setTimeout(resolve, 1500)); await new Promise((resolve) => setTimeout(resolve, 1500));
@ -1039,7 +1044,6 @@ async function continueThinkingProcess(thinkingMessageRef, stockName) {
sender: "ai", sender: "ai",
class: "ing", class: "ing",
type: "ing", type: "ing",
flag: true,
content: "报告已生成!", content: "报告已生成!",
}); });
chatStore.messages.push(thinkingMessage4); chatStore.messages.push(thinkingMessage4);
@ -1063,6 +1067,33 @@ watch(
previousMessagesLength.value = newVal.length; previousMessagesLength.value = newVal.length;
if (newVal.length > 0) { if (newVal.length > 0) {
//
console.log("chatStore.currentUserIndex", chatStore.currentUserIndex);
if (chatStore.currentUserIndex != null) {
chatStore.messages[chatStore.currentUserIndex].audioStatus = false;
}
chatStore.currentUserIndex = null;
audioStore.stop(); //
// 🔧
audioQueue.value = [];
isPlayingAudio.value = false;
currentPlayIndex = 0;
isCallingPlayNext = false;
//
audioPreloadStatus.one = { loaded: false, url: null };
audioPreloadStatus.two = { loaded: false, url: null };
audioPreloadStatus.three = { loaded: false, url: null };
audioPreloadStatus.four = { loaded: false, url: null };
//
audioStore.soundInstance = null;
audioStore.nowSound = null;
audioStore.isPlaying = false;
audioStore.isPaused = false;
audioStore.playbackPosition = 0;
console.log("消息列表已更新,最新消息:", newVal[newVal.length - 1]); console.log("消息列表已更新,最新消息:", newVal[newVal.length - 1]);
chatStore.messages.push(newVal[newVal.length - 1]); chatStore.messages.push(newVal[newVal.length - 1]);
chatStore.currentUserIndex = chatStore.messages.length - 1; chatStore.currentUserIndex = chatStore.messages.length - 1;
@ -1101,6 +1132,8 @@ watch(
console.log(codeData.value, "codeData"); console.log(codeData.value, "codeData");
// //
if (result.code == 200) { if (result.code == 200) {
//
chatStore.searchRecord = true;
// //
if (thinkingMessageRef && codeData.value.name) { if (thinkingMessageRef && codeData.value.name) {
await continueThinkingProcess( await continueThinkingProcess(
@ -1108,12 +1141,17 @@ watch(
codeData.value.name codeData.value.name
); );
} }
for (let i = chatStore.messages.length - 1; i >= 0; --i) {
if (chatStore.messages[i].sender == "user") {
chatStore.messages[i].audioStatus = true;
break;
}
}
chatStore.messages.push({ chatStore.messages.push({
class: "ing",
type: "ing",
flag: flag,
content: result.data.kaishi,
// class: "ing",
// type: "ing",
// flag: flag,
// content: result.data.kaishi,
}); });
} else { } else {
// //
@ -1148,7 +1186,7 @@ watch(
class: "ing", class: "ing",
type: "ing", type: "ing",
flag: flag, flag: flag,
content: aiContent,
content: AIcontent,
}); });
chatStore.isLoading = false; chatStore.isLoading = false;
@ -2417,6 +2455,16 @@ watch(
return; return;
} }
try { try {
//
chatStore.currentUserIndex = null;
audioStore.stop(); //
//
emit("enableInput");
//
typingQueue.value = [];
isTypingInProgress.value = false;
// //
chatStore.messages = []; chatStore.messages = [];
@ -2770,7 +2818,7 @@ function KlineCanvsEcharts(containerId) {
name: "\u4eea\u8868\u76d8", name: "\u4eea\u8868\u76d8",
type: "gauge", type: "gauge",
center: ["50%", "50%"], center: ["50%", "50%"],
radius: "90%",
radius: window.innerWidth > 768 ? "90%" : "70%",
startAngle: 140, startAngle: 140,
endAngle: -140, endAngle: -140,
min: 0, min: 0,
@ -3286,10 +3334,10 @@ function KlineCanvsEcharts(containerId) {
{ {
textStyle: { textStyle: {
color: "black", color: "black",
fontSize: window.innerWidth > 768 ? 15 : vwToPx(1.8),
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
width: "100%", width: "100%",
top: window.innerWidth > 768 ? "0%" : "-1%",
top: window.innerWidth > 768 ? "5%" : "4%",
left: "center", left: "center",
itemGap: window.innerWidth > 768 ? 20 : 10, itemGap: window.innerWidth > 768 ? 20 : 10,
itemWidth: 10, itemWidth: 10,
@ -3324,10 +3372,10 @@ function KlineCanvsEcharts(containerId) {
{ {
textStyle: { textStyle: {
color: "black", color: "black",
fontSize: window.innerWidth > 768 ? 15 : vwToPx(1.8),
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
orient: "horizontal", orient: "horizontal",
top: window.innerWidth > 768 ? "3%" : "2%",
top: window.innerWidth > 768 ? "8%" : "7%",
width: "100%", width: "100%",
left: "center", left: "center",
itemGap: 15, itemGap: 15,
@ -3339,11 +3387,11 @@ function KlineCanvsEcharts(containerId) {
rich: { rich: {
green: { green: {
color: "green", color: "green",
fontSize: window.innerWidth > 768 ? 20 : 10,
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
red: { red: {
color: "red", color: "red",
fontSize: window.innerWidth > 768 ? 20 : 10,
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
}, },
}, },
@ -3359,10 +3407,10 @@ function KlineCanvsEcharts(containerId) {
{ {
textStyle: { textStyle: {
color: "black", color: "black",
fontSize: window.innerWidth > 768 ? 15 : vwToPx(1.8),
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
orient: "horizontal", orient: "horizontal",
top: window.innerWidth > 768 ? "68%" : "64%",
top: window.innerWidth > 768 ? "62%" : "60%",
width: "100%", width: "100%",
left: "center", left: "center",
itemGap: 15, itemGap: 15,
@ -3374,11 +3422,11 @@ function KlineCanvsEcharts(containerId) {
rich: { rich: {
green: { green: {
color: "green", color: "green",
fontSize: window.innerWidth > 768 ? 20 : 10,
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
red: { red: {
color: "red", color: "red",
fontSize: window.innerWidth > 768 ? 20 : 10,
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
}, },
}, },
@ -3465,53 +3513,62 @@ function KlineCanvsEcharts(containerId) {
}, },
grid: [ grid: [
{ {
top: window.innerWidth > 768 ? "12%" : "10%",
left: left:
window.innerWidth > 1024 window.innerWidth > 1024
? "70vw"
? "14%"
: window.innerWidth > 768 : window.innerWidth > 768
? "65vw"
: "55vw",
? "18%"
: window.innerWidth > 375
? "20%"
: "22%",
right: right:
window.innerWidth > 1024 window.innerWidth > 1024
? "40vw"
? "9%"
: window.innerWidth > 768 : window.innerWidth > 768
? "30vw"
: "40vw",
top: window.innerWidth > 768 ? "8%" : "5%",
height: window.innerWidth > 768 ? "34%" : "34%",
? "12%"
: "14%",
height: window.innerWidth > 768 ? "27%" : "29%",
containLabel: false, containLabel: false,
}, },
{ {
top: window.innerWidth > 768 ? "42%" : "42%",
left: left:
window.innerWidth > 1024 window.innerWidth > 1024
? "70vw"
? "14%"
: window.innerWidth > 768 : window.innerWidth > 768
? "65vw"
: "55vw",
? "18%"
: window.innerWidth > 375
? "20%"
: "22%",
right: right:
window.innerWidth > 1024 window.innerWidth > 1024
? "40vw"
? "9%"
: window.innerWidth > 768 : window.innerWidth > 768
? "30vw"
: "40vw",
top: window.innerWidth > 768 ? "45%" : "42%",
height: window.innerWidth > 768 ? "22%" : "22%",
? "12%"
: "14%",
height: window.innerWidth > 768 ? "20%" : "18%",
containLabel: false, containLabel: false,
}, },
{ {
top: window.innerWidth > 768 ? "66%" : "64%",
left: left:
window.innerWidth > 1024 window.innerWidth > 1024
? "70vw"
? "14%"
: window.innerWidth > 768 : window.innerWidth > 768
? "65vw"
: "55vw",
? "18%"
: window.innerWidth > 375
? "20%"
: "22%",
right: right:
window.innerWidth > 1024 window.innerWidth > 1024
? "40vw"
? "9%"
: window.innerWidth > 768 : window.innerWidth > 768
? "30vw"
: "40vw",
top: window.innerWidth > 768 ? "73%" : "70%",
? "12%"
: "14%",
height: window.innerWidth > 768 ? "20%" : "22%", height: window.innerWidth > 768 ? "20%" : "22%",
containLabel: false, containLabel: false,
}, },
@ -3556,6 +3613,7 @@ function KlineCanvsEcharts(containerId) {
axisLabel: { axisLabel: {
show: true, show: true,
interval: "auto", interval: "auto",
fontSize: window.innerWidth > 768 ? 12 : 9,
}, },
}, },
], ],
@ -3652,11 +3710,15 @@ function KlineCanvsEcharts(containerId) {
show: true, show: true,
xAxisIndex: [0, 1, 2], xAxisIndex: [0, 1, 2],
type: "slider", type: "slider",
top: window.innerWidth > 768 ? "95%" : "96%",
top: window.innerWidth > 768 ? "90%" : "91%",
// left: window.innerWidth > 768 ? "10%" : "8%", // left: window.innerWidth > 768 ? "10%" : "8%",
// right: window.innerWidth > 768 ? "4%" : "8%", // right: window.innerWidth > 768 ? "4%" : "8%",
height: 20,
start: 98, start: 98,
end: 100, end: 100,
textStyle: {
fontSize: window.innerWidth > 768 ? 12 : 9,
},
}, },
], ],
visualMap: [ visualMap: [
@ -4092,6 +4154,11 @@ function KlineCanvsEcharts(containerId) {
type: "solid", type: "solid",
}, },
data: [{ yAxis: 20 }], data: [{ yAxis: 20 }],
label: {
normal: {
fontSize: window.innerWidth > 768 ? 12 : 9,
},
},
}, },
}, },
{ {
@ -4109,6 +4176,11 @@ function KlineCanvsEcharts(containerId) {
type: "solid", type: "solid",
}, },
data: [{ yAxis: 50 }], data: [{ yAxis: 50 }],
label: {
normal: {
fontSize: window.innerWidth > 768 ? 12 : 9,
},
},
}, },
}, },
{ {
@ -4126,6 +4198,11 @@ function KlineCanvsEcharts(containerId) {
type: "solid", type: "solid",
}, },
data: [{ yAxis: 80 }], data: [{ yAxis: 80 }],
label: {
normal: {
fontSize: window.innerWidth > 768 ? 12 : 9,
},
},
}, },
}, },
{ {
@ -4144,6 +4221,11 @@ function KlineCanvsEcharts(containerId) {
type: "solid", type: "solid",
}, },
data: [{ yAxis: 100 }], data: [{ yAxis: 100 }],
label: {
normal: {
fontSize: window.innerWidth > 768 ? 12 : 9,
},
},
}, },
}, },
], ],
@ -4280,6 +4362,8 @@ onMounted(() => {
}); });
renderAllKlineCharts(); renderAllKlineCharts();
console.log("组件挂载完成"); console.log("组件挂载完成");
//
chatStore.currentUserIndex = null;
chatStore.messages.forEach((item) => { chatStore.messages.forEach((item) => {
if (item.sender == "user") { if (item.sender == "user") {
@ -4376,23 +4460,30 @@ onUnmounted(() => {
<div v-for="(msg, index) in chatMsg" :key="index"> <div v-for="(msg, index) in chatMsg" :key="index">
<!-- 用户消息容器包含喇叭按钮 --> <!-- 用户消息容器包含喇叭按钮 -->
<div v-if="msg.sender === 'user'" class="user-message-container"> <div v-if="msg.sender === 'user'" class="user-message-container">
<img
:src="msg.audioStatus ? voice : voiceNoActive"
class="user-message-speaker"
:class="{
'speaker-active': msg.audioStatus,
}"
@click="toggleVoiceForUser(index)"
alt="喇叭"
/>
<div
:class="{
'message-bubble': true,
[msg.sender]: msg.sender,
[msg.class]: msg.class,
}"
>
<div v-html="msg.content"></div>
<div class="user-msg">
<div class="user-content">
<img
:src="msg.audioStatus ? voice : voiceNoActive"
class="user-message-speaker"
:class="{
'speaker-active': msg.audioStatus,
}"
@click="toggleVoiceForUser(index)"
alt="喇叭"
/>
<div
:class="{
'message-bubble': true,
[msg.sender]: msg.sender,
[msg.class]: msg.class,
}"
>
<div v-html="msg.content"></div>
</div>
</div>
<div v-if="msg.timestamp" class="user-sendTime">
{{ moment(msg.timestamp).format("YYYY-MM-DD HH:mm:ss") }}
</div>
</div> </div>
</div> </div>
@ -4419,7 +4510,7 @@ onUnmounted(() => {
alt="思考过程" alt="思考过程"
class="thinking-gif" class="thinking-gif"
/> />
<div class="ai-message-content">
<div class="ai-message-content" :class="{ fourStep: msg.nowrap }">
<div v-if="msg.flag"> <div v-if="msg.flag">
<span>{{ msg.content }}</span> <span>{{ msg.content }}</span>
<span class="loading-dots"> <span class="loading-dots">
@ -4465,7 +4556,7 @@ onUnmounted(() => {
</div> </div>
<div v-else-if="msg.type == 'content2'" class="content2"> <div v-else-if="msg.type == 'content2'" class="content2">
<div class="kline-container content2chart"> <div class="kline-container content2chart">
<div :id="'kline-container-' + index" class="chart-mount-point">
<div :id="'kline-container-' + index" class="chart-mount-pointJN">
<div v-if="!msg.hasValidData" class="no-data-message"> <div v-if="!msg.hasValidData" class="no-data-message">
<p>暂无数据</p> <p>暂无数据</p>
</div> </div>
@ -4677,18 +4768,37 @@ p {
/* 用户消息容器样式 */ /* 用户消息容器样式 */
.user-message-container { .user-message-container {
display: flex; display: flex;
align-items: flex-start;
/* align-items: flex-start; */
margin: 10px 0px; margin: 10px 0px;
justify-content: flex-end; justify-content: flex-end;
gap: 10px; gap: 10px;
/* align-items: center; */
flex-direction: column;
}
.user-msg {
margin-left: auto;
}
.user-content {
display: flex;
height: 100%;
align-items: center; align-items: center;
margin-right: 5px;
}
.user-sendTime {
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-size: 0.8rem;
} }
.user-message-speaker { .user-message-speaker {
width: 32px; width: 32px;
height: 32px; height: 32px;
object-fit: contain; object-fit: contain;
margin-top: 5px;
margin-right: 5px;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
@ -4951,13 +5061,21 @@ p {
width: 90%; width: 90%;
} }
.kline-container .chart-mount-pointJN {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
}
/* AI消息容器样式 */ /* AI消息容器样式 */
.ai-message-container { .ai-message-container {
display: flex; display: flex;
align-items: flex-start;
align-items: center;
gap: 10px; gap: 10px;
margin-right: auto; margin-right: auto;
max-width: 80%;
/* max-width: 80%; */
} }
/* 思考过程动图样式 */ /* 思考过程动图样式 */
@ -4984,8 +5102,12 @@ p {
.ai-message-content { .ai-message-content {
display: flex; display: flex;
align-items: center; align-items: center;
white-space: nowrap;
/* white-space: nowrap; */
width: fit-content; width: fit-content;
overflow: visible; overflow: visible;
} }
.fourStep {
white-space: nowrap;
}
</style> </style>

2795
src/views/AiEmotion.vue
File diff suppressed because it is too large
View File

4
src/views/DBQBmodel.vue

@ -121,7 +121,7 @@ const goToHomePage = () => {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
/* 添加水平居中 */ /* 添加水平居中 */
gap: 23px;
/* gap: 23px; */
margin-bottom: 10px; margin-bottom: 10px;
flex-wrap: wrap; flex-wrap: wrap;
/* 添加换行支持,防止小屏幕溢出 */ /* 添加换行支持,防止小屏幕溢出 */
@ -181,7 +181,7 @@ const goToHomePage = () => {
.btn-item img { .btn-item img {
width: 50%; width: 50%;
margin-top: 20px;
/* margin-top: 20px; */
} }
} }
</style> </style>

2
src/views/Emotionsmodel.vue

@ -63,7 +63,7 @@ onUnmounted(() => {
const goToAiEmotion = () => { const goToAiEmotion = () => {
// sessionStorage homepage.vue AiEmotion tab // sessionStorage homepage.vue AiEmotion tab
sessionStorage.setItem("activeTabAI", "AiEmotion"); sessionStorage.setItem("activeTabAI", "AiEmotion");
sessionStorage.setItem("activeIndexAI", "2");
sessionStorage.setItem("activeIndexAI", "1");
router.push("/homePage"); router.push("/homePage");
}; };
</script> </script>

258
src/views/components/HistoryRecord.vue

@ -25,23 +25,23 @@
<div v-if="isCollapsed" class="collapsed-bottom-container"> <div v-if="isCollapsed" class="collapsed-bottom-container">
<div <div
class="collapsed-bottom-btn" class="collapsed-bottom-btn"
@click="handleFeedbackClick"
title="用户反馈"
@click="handleAnnouncementClick"
title="公告"
> >
<img <img
class="collapsed-bottom-feedback"
src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
class="collapsed-bottom-announcement"
src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
alt="icon" alt="icon"
/> />
</div> </div>
<div <div
class="collapsed-bottom-btn" class="collapsed-bottom-btn"
@click="handleAnnouncementClick"
title="公告"
@click="handleFeedbackClick"
title="用户反馈"
> >
<img <img
class="collapsed-bottom-announcement"
src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
class="collapsed-bottom-feedback"
src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
alt="icon" alt="icon"
/> />
</div> </div>
@ -78,7 +78,7 @@
</div> </div>
<div v-else v-for="history in categoryHistory" :key="history.name"> <div v-else v-for="history in categoryHistory" :key="history.name">
<div class="categoryName">
<div class="categoryName" v-if="history.list.length!=0">
{{ history.name }} {{ history.name }}
</div> </div>
<div <div
@ -95,9 +95,28 @@
/> />
</div> </div>
<div class="record-msg"> <div class="record-msg">
<div class="record-text">{{ record.stockCode }}</div>
<div class="record-text">
<span class="stock-name">{{ record.stockName }}</span>
<span class="stock-code">({{ record.stockCode }})</span>
<div v-if="history.name === '置顶'">
<svg
t="1755227529729"
class="top-icon"
viewBox="320 280 380 460"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="7392"
>
<path
d="M351.085714 292.571429h321.828572v29.257142H351.085714v-29.257142z m175.542857 125.805714l146.285715 146.285714-20.48 20.48-125.805715-125.805714V731.428571h-29.257142v-272.091428L371.565714 585.142857l-20.48-20.48 146.285715-146.285714h29.257142z"
fill="#FFFFFF"
p-id="7393"
></path>
</svg>
</div>
</div>
<div class="record-time"> <div class="record-time">
{{ moment(record.updatedTime).format("YYYY-MM-DD HH:mm:ss") }}
{{ moment(record.createdTime).format("YYYY-MM-DD HH:mm:ss") }}
</div> </div>
</div> </div>
</div> </div>
@ -167,17 +186,17 @@
</div> </div>
<div class="bottom-container"> <div class="bottom-container">
<div class="bottom-btn" @click="handleFeedbackClick" title="用户反馈">
<div class="bottom-btn" @click="handleAnnouncementClick" title="公告">
<img <img
class="bottom-feedback"
src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
class="bottom-announcement"
src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
alt="icon" alt="icon"
/> />
</div> </div>
<div class="bottom-btn" @click="handleAnnouncementClick" title="公告">
<div class="bottom-btn" @click="handleFeedbackClick" title="用户反馈">
<img <img
class="bottom-announcement"
src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
class="bottom-feedback"
src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
alt="icon" alt="icon"
/> />
</div> </div>
@ -222,7 +241,7 @@
</div> </div>
<div v-else v-for="history in categoryHistory" :key="history.name"> <div v-else v-for="history in categoryHistory" :key="history.name">
<div class="categoryName">
<div class="categoryName" v-if="history.list.length!=0">
{{ history.name }} {{ history.name }}
</div> </div>
<div <div
@ -239,9 +258,28 @@
/> />
</div> </div>
<div class="record-msg"> <div class="record-msg">
<div class="record-text">{{ record.stockCode }}</div>
<div class="record-text">
<span class="stock-name">{{ record.stockName }}</span>
<span class="stock-code">({{ record.stockCode }})</span>
<div v-if="history.name === '置顶'">
<svg
t="1755227529729"
class="top-icon"
viewBox="320 280 380 460"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="7392"
>
<path
d="M351.085714 292.571429h321.828572v29.257142H351.085714v-29.257142z m175.542857 125.805714l146.285715 146.285714-20.48 20.48-125.805715-125.805714V731.428571h-29.257142v-272.091428L371.565714 585.142857l-20.48-20.48 146.285715-146.285714h29.257142z"
fill="#FFFFFF"
p-id="7393"
></path>
</svg>
</div>
</div>
<div class="record-time"> <div class="record-time">
{{ moment(record.updatedTime).format("YYYY-MM-DD HH:mm:ss") }}
{{ moment(record.createdTime).format("YYYY-MM-DD HH:mm:ss") }}
</div> </div>
</div> </div>
</div> </div>
@ -313,33 +351,33 @@
<div class="mobile-bottom-container"> <div class="mobile-bottom-container">
<div <div
class="mobile-bottom-btn" class="mobile-bottom-btn"
@click="handleFeedbackClick"
title="用户反馈"
@click="handleAnnouncementClick"
title="公告"
> >
<img <img
class="mobile-bottom-feedback"
src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
class="mobile-bottom-announcement"
src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
alt="icon" alt="icon"
/> />
<div class="mobile-bottom-text">用户反馈</div>
<div class="mobile-bottom-text">公告</div>
</div> </div>
<div <div
class="mobile-bottom-btn" class="mobile-bottom-btn"
@click="handleAnnouncementClick"
title="公告"
@click="handleFeedbackClick"
title="用户反馈"
> >
<img <img
class="mobile-bottom-announcement"
src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
class="mobile-bottom-feedback"
src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
alt="icon" alt="icon"
/> />
<div class="mobile-bottom-text">公告</div>
<div class="mobile-bottom-text">用户反馈</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<el-dialog v-model="deleteDialogVisible" title="永久删除记录" width="500">
<el-dialog v-model="deleteDialogVisible" title="永久删除记录" :width="computedDialogWidth">
<span>删除后该记录将不可恢复确认删除吗</span> <span>删除后该记录将不可恢复确认删除吗</span>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
@ -404,6 +442,15 @@ const selectedRecordId = ref(null);
const delObj = ref({}); const delObj = ref({});
const deleteDialogVisible = ref(false); const deleteDialogVisible = ref(false);
const dialogWidth = ref('500px'); //
//
const computedDialogWidth = computed(() => {
if (props.isMobile) {
return '70%'; // 使
}
return dialogWidth.value; // 使
});
const openDeleteDialog = () => { const openDeleteDialog = () => {
deleteDialogVisible.value = true; deleteDialogVisible.value = true;
@ -415,11 +462,52 @@ const closeDeleteDialog = () => {
const historyRecords = ref([]); const historyRecords = ref([]);
const categoryHistory = ref([]); const categoryHistory = ref([]);
let chatFirstFlag = true;
let emotionTirstFlag = true;
const getHistoryList = async (params) => { const getHistoryList = async (params) => {
try { try {
const result = await getHistoryListAPI(params); const result = await getHistoryListAPI(params);
historyRecords.value = result.data.list;
let remainingRecords = result.data.list; //
historyRecords.value = result.data;
let remainingRecords = result.data; //
console.log(
"params",
params,
"result",
result.data,
"chatFirstFlag",
chatFirstFlag,
"emotionTirstFlag",
emotionTirstFlag
);
if (chatFirstFlag && params.model == 1 && result.data.length != 0) {
const userAgent = navigator.userAgent;
if (
!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
userAgent
)
) {
chatStore.aiChatCall = true;
}
chatFirstFlag = false;
}
if (emotionTirstFlag && params.model == 2 && result.data.length != 0) {
const userAgent = navigator.userAgent;
if (
!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
userAgent
)
) {
chatStore.aiEmotionCall = true;
}
emotionTirstFlag = false;
}
if (props.currentType == "AIchat") {
isCollapsed.value = !chatStore.aiChatCall;
} else {
isCollapsed.value = !chatStore.aiEmotionCall;
}
// 1. // 1.
let topList = remainingRecords.filter((record) => record.isTop === 1); let topList = remainingRecords.filter((record) => record.isTop === 1);
@ -428,12 +516,12 @@ const getHistoryList = async (params) => {
// 2. // 2.
let todayList = remainingRecords.filter((record) => { let todayList = remainingRecords.filter((record) => {
const today = moment().format("YYYY-MM-DD"); const today = moment().format("YYYY-MM-DD");
const recordDate = moment(record.updatedTime).format("YYYY-MM-DD");
const recordDate = moment(record.createdTime).format("YYYY-MM-DD");
return recordDate === today; return recordDate === today;
}); });
remainingRecords = remainingRecords.filter((record) => { remainingRecords = remainingRecords.filter((record) => {
const today = moment().format("YYYY-MM-DD"); const today = moment().format("YYYY-MM-DD");
const recordDate = moment(record.updatedTime).format("YYYY-MM-DD");
const recordDate = moment(record.createdTime).format("YYYY-MM-DD");
return recordDate !== today; return recordDate !== today;
}); });
@ -441,13 +529,13 @@ const getHistoryList = async (params) => {
let recent3DaysList = remainingRecords.filter((record) => { let recent3DaysList = remainingRecords.filter((record) => {
const threeDaysAgo = moment().subtract(3, "days").startOf("day"); const threeDaysAgo = moment().subtract(3, "days").startOf("day");
const yesterday = moment().subtract(1, "days").endOf("day"); const yesterday = moment().subtract(1, "days").endOf("day");
const recordDate = moment(record.updatedTime);
const recordDate = moment(record.createdTime);
return recordDate.isAfter(threeDaysAgo) && recordDate.isBefore(yesterday); return recordDate.isAfter(threeDaysAgo) && recordDate.isBefore(yesterday);
}); });
remainingRecords = remainingRecords.filter((record) => { remainingRecords = remainingRecords.filter((record) => {
const threeDaysAgo = moment().subtract(3, "days").startOf("day"); const threeDaysAgo = moment().subtract(3, "days").startOf("day");
const yesterday = moment().subtract(1, "days").endOf("day"); const yesterday = moment().subtract(1, "days").endOf("day");
const recordDate = moment(record.updatedTime);
const recordDate = moment(record.createdTime);
return !( return !(
recordDate.isAfter(threeDaysAgo) && recordDate.isBefore(yesterday) recordDate.isAfter(threeDaysAgo) && recordDate.isBefore(yesterday)
); );
@ -456,28 +544,28 @@ const getHistoryList = async (params) => {
// 4. 73 // 4. 73
let recent7DaysList = remainingRecords.filter((record) => { let recent7DaysList = remainingRecords.filter((record) => {
const sevenDaysAgo = moment().subtract(7, "days").startOf("day"); const sevenDaysAgo = moment().subtract(7, "days").startOf("day");
const recordDate = moment(record.updatedTime);
const recordDate = moment(record.createdTime);
return recordDate.isAfter(sevenDaysAgo); return recordDate.isAfter(sevenDaysAgo);
}); });
remainingRecords = remainingRecords.filter((record) => { remainingRecords = remainingRecords.filter((record) => {
const sevenDaysAgo = moment().subtract(7, "days").startOf("day"); const sevenDaysAgo = moment().subtract(7, "days").startOf("day");
const recordDate = moment(record.updatedTime);
const recordDate = moment(record.createdTime);
return !recordDate.isAfter(sevenDaysAgo); return !recordDate.isAfter(sevenDaysAgo);
}); });
// 5. 30 // 5. 30
let recent30DaysList = remainingRecords.filter((record) => { let recent30DaysList = remainingRecords.filter((record) => {
const thirtyDaysAgo = moment().subtract(30, "days").startOf("day"); const thirtyDaysAgo = moment().subtract(30, "days").startOf("day");
const recordDate = moment(record.updatedTime);
const recordDate = moment(record.createdTime);
return recordDate.isAfter(thirtyDaysAgo); return recordDate.isAfter(thirtyDaysAgo);
}); });
remainingRecords = remainingRecords.filter((record) => { remainingRecords = remainingRecords.filter((record) => {
const thirtyDaysAgo = moment().subtract(30, "days").startOf("day"); const thirtyDaysAgo = moment().subtract(30, "days").startOf("day");
const recordDate = moment(record.updatedTime);
const recordDate = moment(record.createdTime);
return !recordDate.isAfter(thirtyDaysAgo); return !recordDate.isAfter(thirtyDaysAgo);
}); });
historyRecords.value = result.data.list;
historyRecords.value = result.data;
categoryHistory.value = [ categoryHistory.value = [
{ {
@ -505,6 +593,9 @@ const getHistoryList = async (params) => {
console.log("categoryHistory", categoryHistory.value); console.log("categoryHistory", categoryHistory.value);
} catch (e) { } catch (e) {
console.error("获取历史记录出错", e); console.error("获取历史记录出错", e);
// historyRecordscategoryHistory
historyRecords.value = [];
categoryHistory.value = [];
} }
}; };
@ -518,11 +609,18 @@ const changeTop = async (param) => {
const changeTopStatus = async (isTop, id) => { const changeTopStatus = async (isTop, id) => {
try { try {
// popover
const popoverElement = document.querySelector('.el-popover');
if (popoverElement) {
popoverElement.style.display = 'none';
}
if (isTop == 0 && categoryHistory.value[0].list.length >= 3) { if (isTop == 0 && categoryHistory.value[0].list.length >= 3) {
console.log("超过置顶上线"); console.log("超过置顶上线");
ElMessage.warning("最多置顶三条内容,已达上限!"); ElMessage.warning("最多置顶三条内容,已达上限!");
return; return;
} }
await changeTop({ await changeTop({
model: props.currentType == "AIchat" ? 1 : 2, model: props.currentType == "AIchat" ? 1 : 2,
recordId: id, recordId: id,
@ -554,10 +652,20 @@ const openHistory = () => {
// token: localStorage.getItem("localToken"), // token: localStorage.getItem("localToken"),
// }); // });
isCollapsed.value = false; isCollapsed.value = false;
if (props.currentType == "AIchat") {
chatStore.aiChatCall = true;
} else if (props.currentType == "AiEmotion") {
chatStore.aiEmotionCall = true;
}
}; };
const closeHistory = () => { const closeHistory = () => {
isCollapsed.value = true; isCollapsed.value = true;
if (props.currentType == "AIchat") {
chatStore.aiChatCall = false;
} else if (props.currentType == "AiEmotion") {
chatStore.aiEmotionCall = false;
}
}; };
const openDetail = (record) => { const openDetail = (record) => {
@ -573,28 +681,37 @@ const selectRecord = async (record) => {
parentId: record.parentId, parentId: record.parentId,
recordId: record.id, recordId: record.id,
}); });
if (result && result.data) { if (result && result.data) {
if (props.isMobile) {
//
isCollapsed.value = true;
if (props.currentType == "AIchat") {
chatStore.aiChatCall = false;
} else if (props.currentType == "AiEmotion") {
chatStore.aiEmotionCall = false;
}
}
historyData.value = result.data; historyData.value = result.data;
chatStore.dbqbClickRecord = historyData.value; chatStore.dbqbClickRecord = historyData.value;
// //
const stockData = { const stockData = {
queryText: record.stockCode || record.stockName || '', // 使
queryText: result.data.keyword, // 使keyword
stockInfo: { stockInfo: {
name: result.data.stockData?.stockName || record.stockName || '',
code: record.stockCode || '',
market: record.stockMarket || 'cn'
name: result.data.stockData?.stockName || record.stockName || "",
code: record.stockCode || "",
market: record.stockMarket || "cn",
}, },
apiData: result.data.stockData || {}, // apiData: result.data.stockData || {}, //
conclusionData: result.data.wokeFlowData?.One || {}, // conclusionData: result.data.wokeFlowData?.One || {}, //
timestamp: new Date().toISOString()
timestamp: record.createdTime || new Date().toISOString(), // 使createdTime
}; };
// emit // emit
emit('selectRecord', stockData);
console.log('历史记录数据已发送给父组件:', stockData);
emit("selectRecord", stockData);
console.log("历史记录数据已发送给父组件:", stockData);
} else { } else {
console.error('历史记录数据格式不正确:', result);
console.error("历史记录数据格式不正确:", result);
} }
} catch (e) { } catch (e) {
console.error("获取历史记录数据失败", e); console.error("获取历史记录数据失败", e);
@ -603,6 +720,16 @@ const selectRecord = async (record) => {
const deleteRecord = (id) => { const deleteRecord = (id) => {
delObj.value.id = id; delObj.value.id = id;
// popover
nextTick(() => {
// popover
const popoverElement = document.querySelector('.el-popover');
if (popoverElement) {
popoverElement.style.display = 'none';
}
// bodypopover
document.body.click();
});
openDeleteDialog(); openDeleteDialog();
}; };
@ -651,6 +778,7 @@ defineExpose({
isCollapsed, isCollapsed,
toggleCollapse, toggleCollapse,
getHistoryList, getHistoryList,
selectedRecordId,
}); });
// //
@ -702,6 +830,7 @@ onMounted(() => {
} }
.mobileCollapsed { .mobileCollapsed {
/* max-width: 400px */
width: 80vw; width: 80vw;
} }
@ -814,6 +943,7 @@ onMounted(() => {
width: 100%; width: 100%;
/* padding: 20px; */ /* padding: 20px; */
overflow: hidden; overflow: hidden;
min-height: 0;
} }
.head-container { .head-container {
@ -909,6 +1039,10 @@ onMounted(() => {
background: rgba(255, 255, 255, 0.1); background: rgba(255, 255, 255, 0.1);
} }
.history-item.active {
background: rgba(255, 255, 255, 0.5);
}
.record-content { .record-content {
display: flex; display: flex;
width: 100%; width: 100%;
@ -932,9 +1066,27 @@ onMounted(() => {
margin-bottom: 6px; margin-bottom: 6px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
display: flex;
}
.top-icon {
margin-left: 5px;
color: white;
height: auto;
width: 15px;
}
.stock-name {
font-weight: 500;
margin-right: 4px;
}
.stock-code {
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
font-weight: 400;
} }
.record-time { .record-time {

10
src/views/components/emoEnergyConverter.vue

@ -152,7 +152,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
max: qxnlzhqData.js, max: qxnlzhqData.js,
name: "【情绪临界区】", name: "【情绪临界区】",
color: "#FFC0AA", color: "#FFC0AA",
fontColor: 'white',
fontColor: '#2D2D89',
NumberColor: 'white', NumberColor: 'white',
}, },
]; ];
@ -455,7 +455,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
{ {
type: 'slider', type: 'slider',
xAxisIndex: 0, xAxisIndex: 0,
start: 0,
start: 50,
end: 100, end: 100,
show: true, show: true,
bottom: 10, bottom: 10,
@ -473,7 +473,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
{ {
type: 'inside', type: 'inside',
xAxisIndex: 0, xAxisIndex: 0,
start: 0,
start: 50,
end: 100, end: 100,
zoomOnMouseWheel: true, zoomOnMouseWheel: true,
moveOnMouseMove: true, moveOnMouseMove: true,
@ -850,12 +850,12 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
// } // }
], ],
grid: { grid: {
left: "13%",
left: window.innerWidth >= 768 ? "13%" : "18%",
right: "10", right: "10",
top: '10', top: '10',
bottom: "60", bottom: "60",
containLabel: false, containLabel: false,
width: '80%',
width: window.innerWidth >= 768 ? '80%': '70%',
height: 'auto', height: 'auto',
overflow: 'hidden' overflow: 'hidden'
}, },

41
src/views/components/emotionDecod.vue

@ -91,12 +91,22 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
grid: [ grid: [
{ {
top: "5%", top: "5%",
height: window.innerWidth <= 768 ? "30%" : "40%"
height: window.innerWidth <= 768 ? "35%" : "40%",
width: window.innerWidth <= 768 ? "70%" : "80%",
left: window.outerWidth <= 768 ? "20%" : "10%",
},
{
top: window.innerWidth <= 768 ? "40%" :"45%",
height: "35%",
width: window.innerWidth <= 768 ? "70%" : "80%",
left: window.outerWidth <= 768 ? "20%" : "10%",
},
{
top: window.innerWidth <= 768 ? "75%" : "80%",
height: "2%",
width: window.innerWidth <= 768 ? "70%" : "80%",
left: window.outerWidth <= 768 ? "20%" : "10%",
}, },
{ top: window.innerWidth <= 768 ? "35%" :"45%",
height: "35%" },
{ top: window.innerWidth <= 768 ? "70%" : "80%",
height: "2%" },
], ],
visualMap: [ visualMap: [
@ -280,14 +290,23 @@ function initQXNLZHEcharts(kline, qxnlzhqData) {
shadowOffsetX: 2, shadowOffsetX: 2,
shadowOffsetY: 2, shadowOffsetY: 2,
}, },
bottom: "8%", //
},
{
show: !1,
type: "slider",
start: 50, //
end: 100,
bottom: window.innerWidth <= 768 ? "5%" : "7%", //
}, },
// {
// show: true,
// type: "slider",
// xAxisIndex: [0, 1, 2],
// bottom: "0%",
// textStyle: {
// color: "white",
// },
// },
{ {
type: "inside", type: "inside",
xAxisIndex: [0, 1, 2],
filterMode: "filter",
}, },
], ],
series: [ series: [
@ -499,7 +518,7 @@ onBeforeUnmount(() => {
@media only screen and (max-width: 768px) { @media only screen and (max-width: 768px) {
.qxjmqEcharts { .qxjmqEcharts {
width: 100%; width: 100%;
height: 400px;
height: 270px;
margin: 0; margin: 0;
/* top: 5rem; */ /* top: 5rem; */
} }

4
src/views/components/emotionalBottomRadar.vue

@ -503,7 +503,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
{ {
type: 'slider', type: 'slider',
xAxisIndex: [0, 1, 2], xAxisIndex: [0, 1, 2],
start: 0,
start: 50,
end: 100, end: 100,
show: true, show: true,
bottom: window.innerWidth > 768 ? 30 : 50, bottom: window.innerWidth > 768 ? 30 : 50,
@ -528,7 +528,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
{ {
type: 'inside', type: 'inside',
xAxisIndex: [0, 1, 2], xAxisIndex: [0, 1, 2],
start: 0,
start: 50,
end: 100, end: 100,
zoomOnMouseWheel: true, zoomOnMouseWheel: true,
moveOnMouseMove: true, moveOnMouseMove: true,

4
src/views/components/marketTemperature.vue

@ -493,7 +493,7 @@ function initChart(raw, klineDataRawValue, WDRLValue) {
textStyle: { color: "white", fontSize: window.innerWidth <= 768 ? 14 : 18 }, textStyle: { color: "white", fontSize: window.innerWidth <= 768 ? 14 : 18 },
}, },
grid: { grid: {
left: window.innerWidth <= 768 ? '50px' : '100px', // 使
left: window.innerWidth <= 768 ? '15%' : '100px', // 使
right: window.innerWidth <= 768 ? '40px' : '100px', // y right: window.innerWidth <= 768 ? '40px' : '100px', // y
top: window.innerWidth <= 768 ? '40px' : '60px', top: window.innerWidth <= 768 ? '40px' : '60px',
bottom: window.innerWidth <= 768 ? '60px' : '80px', // dataZoom bottom: window.innerWidth <= 768 ? '60px' : '80px', // dataZoom
@ -667,6 +667,8 @@ function initChart(raw, klineDataRawValue, WDRLValue) {
textStyle: { textStyle: {
color: "white", color: "white",
}, },
start: 50, //
end: 100,
bottom: "0%", // bottom: "0%", //
}, },
{ {

199
src/views/homePage.vue

@ -34,9 +34,9 @@ import feedbackBtn from "../assets/img/Feedback/feedbackBtn.png";
import AiEmotion from "./AiEmotion.vue"; import AiEmotion from "./AiEmotion.vue";
import HistoryRecord from "./components/HistoryRecord.vue"; import HistoryRecord from "./components/HistoryRecord.vue";
// import VConsole from "vconsole";
import VConsole from "vconsole";
// const vConsole = new VConsole();
const vConsole = new VConsole();
const isMobile = ref(null); const isMobile = ref(null);
@ -181,7 +181,7 @@ watch(
() => chatStore.announcementMsg, () => chatStore.announcementMsg,
(newVal) => { (newVal) => {
console.log("监听到公告改变", chatStore.announcementMsg); console.log("监听到公告改变", chatStore.announcementMsg);
if (chatStore.announcementMsg) {
if (chatStore.announcementMsg && !isInputDisabled.value) {
message.value = chatStore.announcementMsg; message.value = chatStore.announcementMsg;
chatStore.announcementMsg = null; chatStore.announcementMsg = null;
} }
@ -192,6 +192,8 @@ watch(
() => dataStore.isFeedback, () => dataStore.isFeedback,
async (newVal) => { async (newVal) => {
if (!dataStore.isFeedback) { if (!dataStore.isFeedback) {
//
isAnnouncementVisible.value = false;
await nextTick(); await nextTick();
// //
throttledHeightListener(); throttledHeightListener();
@ -217,6 +219,10 @@ const sendMessage = async () => {
// //
//
if (historyRecordRef) {
historyRecordRef.value.selectedRecordId = null;
}
// AiEmotion // AiEmotion
if (activeTab.value === "AiEmotion") { if (activeTab.value === "AiEmotion") {
// //
@ -250,9 +256,8 @@ const sendMessage = async () => {
{ {
sender: "user", sender: "user",
content: messageContent, content: messageContent,
timestamp: new Date().toISOString(),
audioArray: [], audioArray: [],
audioStatus: true,
audioStatus: false,
}, },
]; ];
console.log(messages.value, "messages.value"); console.log(messages.value, "messages.value");
@ -267,19 +272,19 @@ const enableInput = () => {
// //
const handleHistorySelect = (stockData) => { const handleHistorySelect = (stockData) => {
console.log('接收到历史记录数据:', stockData);
console.log("接收到历史记录数据:", stockData);
// AiEmotionAiEmotion // AiEmotionAiEmotion
// if (activeTab.value !== 'AiEmotion') { // if (activeTab.value !== 'AiEmotion') {
// setActiveTab('AiEmotion', 1); // setActiveTab('AiEmotion', 1);
// } // }
// addStock // addStock
nextTick(() => { nextTick(() => {
if (aiEmotionRef.value && aiEmotionRef.value.addStock) { if (aiEmotionRef.value && aiEmotionRef.value.addStock) {
aiEmotionRef.value.addStock(stockData); aiEmotionRef.value.addStock(stockData);
} else { } else {
console.error('AiEmotion组件或addStock方法不可用');
console.error("AiEmotion组件或addStock方法不可用");
} }
}); });
}; };
@ -353,7 +358,7 @@ const throttledSmoothScrollToBottom = _.throttle(smoothScrollToBottom, 300, {
}); });
watch( watch(
() => chatStore.messages,
() => chatStore.messages.length,
() => { () => {
// console.log('messages') // console.log('messages')
// AIchat // AIchat
@ -362,7 +367,7 @@ watch(
} }
// setTimeout(throttledSmoothScrollToBottom, 100); // setTimeout(throttledSmoothScrollToBottom, 100);
}, },
{ deep: true, immediate: true }
{ deep: false, immediate: true }
); );
watch( watch(
@ -382,7 +387,7 @@ watch(
console.log("activeTab变化了", activeTab.value); console.log("activeTab变化了", activeTab.value);
if (activeTab.value == "AIchat" || activeTab.value == "AiEmotion") { if (activeTab.value == "AIchat" || activeTab.value == "AiEmotion") {
if (historyRecordRef.value && historyRecordRef.value.getHistoryList) { if (historyRecordRef.value && historyRecordRef.value.getHistoryList) {
historyRecordRef.value.getHistoryList({
const result = historyRecordRef.value.getHistoryList({
model: activeTab.value == "AIchat" ? 1 : 2, model: activeTab.value == "AIchat" ? 1 : 2,
token: localStorage.getItem("localToken"), token: localStorage.getItem("localToken"),
}); });
@ -392,7 +397,7 @@ watch(
if (activeTab.value === "AIchat") { if (activeTab.value === "AIchat") {
isScrolling.value = false; // isScrolling.value = false; //
setTimeout(() => { setTimeout(() => {
throttledSmoothScrollToBottom();
// throttledSmoothScrollToBottom();
}, 100); }, 100);
} }
// AiEmotion // AiEmotion
@ -548,6 +553,9 @@ const adjustFooterPosition = (height) => {
}, 200); }, 200);
}; };
//
const inputing = ref(false);
const onFocus = function () { const onFocus = function () {
const visualViewport = window.visualViewport; const visualViewport = window.visualViewport;
// //
@ -564,6 +572,7 @@ const onFocus = function () {
}; };
const onBlur = function () { const onBlur = function () {
inputing.value = false;
const visualViewport = window.visualViewport; const visualViewport = window.visualViewport;
setTimeout(() => { setTimeout(() => {
console.log("输入框失焦"); console.log("输入框失焦");
@ -590,6 +599,11 @@ const onBlur = function () {
let touchmoveHandlerRef = null; let touchmoveHandlerRef = null;
const touchmoveHandler = (e) => { const touchmoveHandler = (e) => {
if (!dataStore.isFeedback) { if (!dataStore.isFeedback) {
if (historyRecordRef) {
if (!historyRecordRef.value.isCollapsed) {
return;
}
}
// //
const isScrollableArea = e.target.closest(".tab-content"); const isScrollableArea = e.target.closest(".tab-content");
@ -628,6 +642,45 @@ const expandHistory = () => {
) { ) {
console.log("存在"); console.log("存在");
historyRecordRef.value.isCollapsed = !historyRecordRef.value.isCollapsed; historyRecordRef.value.isCollapsed = !historyRecordRef.value.isCollapsed;
if (activeTab.value == "AIchat") {
chatStore.aiChatCall = true;
} else if (activeTab.value == "AiEmotion") {
chatStore.aiEmotionCall = true;
}
}
};
const backToHome = () => {
if (isMobile.value) {
console.log("用户是移动端");
//
uni.postMessage({
data: {
val: {
name: "JWopenView",
extra: {
data: {
type: 3,
},
},
},
},
});
} else {
console.log("用户是pc端");
const env = import.meta.env.VITE_ENV;
console.log("当前的环境为:", env);
if (env == "development" || env == "test") {
window.parent.location.href =
"http://121.89.234.155:8807/hljw/homepage?menu=999999991";
} else if (env == "product") {
window.parent.location.href =
"https://web.homilychart.com/product/hljw/homepage?menu=999999991";
} else if (env == "production") {
window.parent.location.href =
"https://web.homilychart.com/hljw/homepage?menu=999999991";
}
// window.parent.location.href = window.parent.document.referrer
} }
}; };
@ -716,6 +769,14 @@ onUnmounted(() => {
<div class="count-number">{{ UserCount }}</div> <div class="count-number">{{ UserCount }}</div>
<div class="clickGetCount">点击获取次数</div> <div class="clickGetCount">点击获取次数</div>
</div> </div>
<div class="backToHomeBtn" @click="backToHome()">
<img
src="https://d31zlh4on95l9h.cloudfront.net/images/d8b388e461423f79087ddbe016002217.png"
alt="返回首页"
class="backImg"
/>
<div class="backContent">返回首页</div>
</div>
<!-- <img <!-- <img
:src="announcementBtn" :src="announcementBtn"
class="announcement-btn action-btn" class="announcement-btn action-btn"
@ -750,12 +811,21 @@ onUnmounted(() => {
> >
<span>{{ tab.label }}</span> <span>{{ tab.label }}</span>
</div> </div>
<div v-if="!isMobile" class="pc-count-badge" @click="showCount">
<div class="pc-action-btn">
<div class="pc-count-number">{{ UserCount }}</div>
<div v-if="!isMobile" class="pc-count-badge">
<div class="pc-countBtn" @click="showCount">
<div class="pc-action-btn">
<div class="pc-count-number">{{ UserCount }}</div>
</div>
<div class="pc-clickGetCount">点击获取次数</div>
</div>
<div class="pc-backToHomeBtn" @click="backToHome()">
<img
src="https://d31zlh4on95l9h.cloudfront.net/images/d8b388e461423f79087ddbe016002217.png"
alt="返回首页"
class="pc-backImg"
/>
<div class="pc-backContent">返回首页</div>
</div> </div>
<div class="pc-clickGetCount">点击获取次数</div>
</div> </div>
</div> </div>
</section> </section>
@ -830,13 +900,15 @@ onUnmounted(() => {
@focus="onFocus" @focus="onFocus"
@blur="onBlur" @blur="onBlur"
:autosize="{ minRows: 1, maxRows: 4 }" :autosize="{ minRows: 1, maxRows: 4 }"
placeholder="请输入股票名称或股票代码..."
class="msg-input" class="msg-input"
@keydown.enter.exact.prevent=" @keydown.enter.exact.prevent="
isLoading || isInputDisabled ? null : sendMessage() isLoading || isInputDisabled ? null : sendMessage()
" "
:disabled="isInputDisabled" :disabled="isInputDisabled"
resize="none" resize="none"
:class="{ input: !message && !inputing }"
@compositionstart="inputing = true"
@compositionend="inputing = false"
> >
</el-input> </el-input>
<img <img
@ -866,10 +938,10 @@ onUnmounted(() => {
> >
<el-header class="homepage-head"> <el-header class="homepage-head">
<!-- logo --> <!-- logo -->
<div class="homepage-logo">
<!-- <div class="homepage-logo">
<img :src="logo" alt="图片加载失败" class="logo1" /> <img :src="logo" alt="图片加载失败" class="logo1" />
<!-- <img :src="madeInHL" alt="图片加载失败" class="logo2" /> -->
</div>
<img :src="madeInHL" alt="图片加载失败" class="logo2" />
</div> -->
<div class="homepage-right-group"> <div class="homepage-right-group">
<div class="count-badge" @click="showCount"> <div class="count-badge" @click="showCount">
@ -880,6 +952,14 @@ onUnmounted(() => {
<div class="count-number">{{ UserCount }}</div> <div class="count-number">{{ UserCount }}</div>
<div class="clickGetCount">点击获取次数</div> <div class="clickGetCount">点击获取次数</div>
</div> </div>
<div class="backToHomeBtn" @click="backToHome()">
<img
src="https://d31zlh4on95l9h.cloudfront.net/images/d8b388e461423f79087ddbe016002217.png"
alt="返回首页"
class="backImg"
/>
<div class="backContent">返回首页</div>
</div>
<!-- <img <!-- <img
:src="announcementBtn" :src="announcementBtn"
class="announcement-btn action-btn" class="announcement-btn action-btn"
@ -1178,16 +1258,41 @@ body {
font-size: 12px; font-size: 12px;
} }
.backToHomeBtn {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.backImg {
width: 100%;
height: auto;
}
.backContent {
width: 100%;
text-align: center;
color: white;
font-size: 12px;
white-space: nowrap;
}
.pc-count-badge { .pc-count-badge {
width: 120px;
width: 200px;
height: 100%; height: 100%;
margin-left: auto;
margin-right: 20px;
position: absolute; position: absolute;
right: 20px; right: 20px;
display: flex;
} }
.pc-count-badge:hover {
.pc-countBtn {
width: 65%;
height: 100%;
position: relative;
}
.pc-countBtn:hover {
transform: scale(1.05); transform: scale(1.05);
} }
@ -1217,6 +1322,28 @@ body {
font-size: 12px; font-size: 12px;
} }
.pc-backToHomeBtn {
width: 35%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.pc-backImg {
width: auto;
height: 70%;
}
.pc-backContent {
width: 100%;
text-align: center;
color: white;
font-size: 12px;
}
.pc-backToHomeBtn:hover {
transform: scale(1.05);
}
.homepage-right-group .announcement-btn { .homepage-right-group .announcement-btn {
cursor: pointer; cursor: pointer;
transition: transform 0.3s; transition: transform 0.3s;
@ -1399,12 +1526,6 @@ body {
padding-right: 45px !important; padding-right: 45px !important;
} }
.msg-input:deep(.el-textarea__inner::placeholder) {
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
.msg-input { .msg-input {
min-height: 34px; min-height: 34px;
width: 100%; width: 100%;
@ -1424,6 +1545,20 @@ body {
outline: none; outline: none;
} }
.input::before {
content: "请输入股票名称或股票代码...";
position: absolute;
left: 11px;
top: 5px;
color: var(--el-text-color-secondary);
pointer-events: none;
white-space: nowrap ;
overflow-x: hidden ;
text-overflow: ellipsis ;
width: 80%;
z-index: 6;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.action-btn { .action-btn {
height: 21px; height: 21px;

Loading…
Cancel
Save