You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

491 lines
14 KiB

4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
  1. <template>
  2. <div class="ai-emotion-container">
  3. <!-- 消息显示区域 -->
  4. <div class="user-input-display">
  5. <div v-for="(message, index) in messages" :key="index" class="message-container">
  6. <!-- 用户输入内容 -->
  7. <div v-if="message.sender === 'user'" class="message-bubble user-message">
  8. {{ message.text }}
  9. </div>
  10. <!-- AI返回结果 -->
  11. <div v-if="message.sender === 'ai'" class="message-bubble ai-message">
  12. {{ message.text }}
  13. </div>
  14. </div>
  15. </div>
  16. <!-- 输入框和发送按钮 -->
  17. <div class="input-container fixed-bottom">
  18. <input type="text" v-model="userInput" placeholder="请输入内容..." class="input-box" />
  19. <button @click="sendMessage" class="send-button">发送</button>
  20. </div>
  21. </div>
  22. <!-- 渲染整个页面 -->
  23. <div class="class01">
  24. <!-- 四维矩阵图 -->
  25. <div class="class02">
  26. <span class="span01">房间卡方法啊付了款公交卡阿济格</span>
  27. <span class="span02"> 2025/06/07</span>
  28. </div>
  29. <div class="class0201">
  30. <img src="@/assets/img/AiEmotion/L1.png" alt="情绪监控图标">
  31. </div>
  32. <!-- 温度计图表 -->
  33. <div class="class03">
  34. </div>
  35. <div class="class0301">
  36. <img src="@/assets/img/AiEmotion/L2.png" alt="情绪解码图标">
  37. </div>
  38. <!-- 情绪解码器图表 -->
  39. <div class="class04">
  40. <div class="class0401">
  41. <img src='@/assets/img/AiEmotion/emotionDecod.png' alt="情绪解码器图标">
  42. </div>
  43. <div class="class0402">
  44. <emotionDecod ref="emotionDecodRef"></emotionDecod>
  45. </div>
  46. </div>
  47. <div class="class0403">
  48. <img src="@/assets/img/AiEmotion/L3.png" alt="情绪推演图标">
  49. </div>
  50. <!-- 情绪探底雷达图表 -->
  51. <div class="class05">
  52. <div class="class0502">
  53. <img src="@/assets/img/AiEmotion/探底雷达.png" alt="探底雷达图表">
  54. </div>
  55. <div class="class0503">
  56. <emotionalBottomRadar ref="emotionalBottomRadarRef"></emotionalBottomRadar>
  57. </div>
  58. </div>
  59. <div class="class0501">
  60. <img src="@/assets/img/AiEmotion/L4.png" alt="情绪套利">
  61. </div>
  62. <!-- 情绪能量转化器图表 -->
  63. <div class="class06">
  64. <div class="class0601">
  65. <img src="@/assets/img/AiEmotion/能量转化器.png" alt="能量转化器图标">
  66. </div>
  67. <emoEnergyConverter ref="emoEnergyConverterRef"></emoEnergyConverter>
  68. </div>
  69. <!-- 核心看点 -->
  70. <div class="class07">
  71. </div>
  72. <!-- 核心逻辑 -->
  73. <div class="class0701">
  74. <img src="@/assets/img/AiEmotion/量子神经决策树.png" alt="">
  75. </div>
  76. <div class="class08">
  77. </div>
  78. <div class="class09"></div>
  79. </div>
  80. </template>
  81. <script setup>
  82. import { ref, reactive } from 'vue';
  83. import { getReplyAPI } from '@/api/AiEmotionApi.js'; // 导入工作流接口方法
  84. import axios from 'axios';
  85. import emotionDecod from '@/views/components/emotionDecod.vue'; // 导入情绪解码组件
  86. import emotionalBottomRadar from '@/views/components/emotionalBottomRadar.vue'; // 导入情绪探底雷达图组件
  87. import emoEnergyConverter from '@/views/components/emoEnergyConverter.vue'; // 导入情绪能量转化器组件
  88. const emoEnergyConverterRef = ref(null)
  89. const emotionDecodRef = ref(null)
  90. const emotionalBottomRadarRef = ref(null)
  91. const userInput = ref('');
  92. const messages = ref([]);
  93. // 请求工作流接口
  94. async function sendMessage() {
  95. console.log('发送内容:', userInput.value);
  96. // 检查用户输入内容是否为空
  97. if (userInput.value.trim()) {
  98. const userMessage = reactive({ sender: 'user', text: userInput.value });
  99. messages.value.push(userMessage);
  100. userInput.value = ''; // 清空输入框
  101. try {
  102. // 调用工作流接口
  103. const params = {
  104. content: userMessage.text,
  105. userData: {
  106. token: '9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs',
  107. language: 'cn',
  108. brainPrivilegeState: '1',
  109. swordPrivilegeState: '1',
  110. stockForecastPrivile: '1',
  111. spaceForecastPrivile: '1',
  112. aibullPrivilegeState: '1',
  113. aigoldBullPrivilegeS: '1',
  114. airadarPrivilegeStat: '1',
  115. marketList: 'hk,cn,usa,my,sg,vi,in,gb',
  116. },
  117. };
  118. const result = await getReplyAPI(params);
  119. const response = await result.json(); // 解析返回的 JSON 数据
  120. console.log('工作流接口返回数据:', response);
  121. // 解析 data 字段
  122. const parsedData = JSON.parse(response.data); // 将字符串形式的 JSON 转换为对象
  123. console.log('解析后的数据:', parsedData);
  124. if (parsedData && parsedData.market && parsedData.code) {
  125. console.log('工作流接口返回股票信息:', parsedData);
  126. // 请求数据接口
  127. fetchData(parsedData.code, parsedData.market);
  128. } else {
  129. console.error('工作流接口返回非股票信息:', parsedData.refuse);
  130. messages.value.push({
  131. sender: 'ai',
  132. text: `工作流接口返回信息: ${parsedData.refuse || '未知错误'}`,
  133. });
  134. }
  135. } catch (error) {
  136. console.error('请求工作流接口失败:', error);
  137. messages.value.push({
  138. sender: 'ai',
  139. text: '工作流接口请求失败,请稍后再试。',
  140. });
  141. }
  142. } else {
  143. console.warn('用户输入内容为空,无法发送请求');
  144. messages.value.push({
  145. sender: 'ai',
  146. text: '请输入内容后再发送。',
  147. });
  148. }
  149. }
  150. // 请求数据接口
  151. async function fetchData(code, market) {
  152. try {
  153. const stockDataParams = {
  154. // token: '+XgqsgdW0RLIbIG2pxnnbZi0+fEeMx8pywnIlrmTxtkSaPZ9xjSOWrxq+s0rL3RrfNhXPvGtz9srFfjwu8A',
  155. token: '9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs',
  156. market: 'usa',
  157. code: 'TSLA',
  158. language: 'cn',
  159. };
  160. const stockDataResult = await axios.post(
  161. 'http://39.101.133.168:8828/link/api/aiEmotion/client/getAiEmotionData',
  162. // 'https://api.homilychart.com/link/api/aiEmotion/client/getAiEmotionData',
  163. stockDataParams,
  164. {
  165. headers: {
  166. 'Content-Type': 'application/json',
  167. },
  168. }
  169. );
  170. const stockDataResponse = stockDataResult.data; // 获取返回的数据
  171. console.log('图表数据接口返回数据:', stockDataResponse);
  172. if (stockDataResponse.data) {
  173. messages.value.push({
  174. sender: 'ai',
  175. text: `股票数据已成功获取: ${JSON.stringify(stockDataResponse.data)}`,
  176. });
  177. console.log('1111111111111111111111')
  178. // 调用渲染图表的方法
  179. renderCharts(stockDataResponse.data);
  180. console.log('2222222222222222222222')
  181. } else {
  182. console.error('图表数据接口返回数据不完整');
  183. messages.value.push({
  184. sender: 'ai',
  185. text: '图表数据接口返回数据不完整,请稍后再试。',
  186. });
  187. }
  188. } catch (error) {
  189. console.error('请求图表数据接口失败:', error);
  190. messages.value.push({
  191. sender: 'ai',
  192. text: '图表数据接口请求失败,请稍后再试。',
  193. });
  194. }
  195. }
  196. // 渲染组件图表的方法
  197. function renderCharts(data) {
  198. nextTick(() => {
  199. // 渲染情绪解码器图表
  200. if (emotionDecodRef.value && data.QXJMQ) {
  201. console.log('开始渲染情绪解码器图表');
  202. console.log('情绪解码器数据', data.QXJMQ)
  203. emotionDecodRef.value.initQXNLZHEcharts(data.KLine20, data.QXJMQ);
  204. console.log('情绪解码器图表已渲染');
  205. }
  206. // 渲染情绪探底雷达图表
  207. if (emotionalBottomRadarRef.value && data.QXTDLD) {
  208. console.log('开始渲染情绪探底雷达图表');
  209. console.log('数据', data.QXTDLD)
  210. emotionalBottomRadarRef.value.initEmotionalBottomRadar(data.KLine20, data.QXTDLD);
  211. console.log('情绪探底雷达图表已渲染');
  212. }
  213. // 渲染情绪能量转化器图表
  214. if (emoEnergyConverterRef.value && data.QXNLZHQ) {
  215. console.log('开始渲染情绪能量转化器图表');
  216. console.log('KLine20:', data.KLine20);
  217. console.log('QXNLZHQ:', data.QXNLZHQ);
  218. emoEnergyConverterRef.value.initQXNLZHEcharts(data.KLine20, data.QXNLZHQ);
  219. console.log('情绪能量转化器图表已渲染');
  220. }
  221. });
  222. }
  223. </script>
  224. <style scoped>
  225. /* .class0402 {
  226. width: fit-content;
  227. margin: 0 auto;
  228. } */
  229. .class0601 {
  230. padding-top: 10rem;
  231. text-align: center;
  232. }
  233. .class0502 {
  234. padding-top: 10rem;
  235. text-align: center;
  236. }
  237. .class0701 {
  238. margin: 0 auto;
  239. width: fit-content;
  240. }
  241. .class0501 {
  242. margin: 0 auto;
  243. width: fit-content;
  244. }
  245. .class0403 {
  246. margin: 0 auto;
  247. width: fit-content;
  248. }
  249. .class0301 {
  250. margin: 0 auto;
  251. width: fit-content;
  252. }
  253. .class0201 {
  254. margin: 0 auto;
  255. width: fit-content;
  256. }
  257. .class0401 {
  258. padding-top: 10rem;
  259. text-align: center;
  260. }
  261. .class08 {
  262. background-image: url('@/assets/img/AiEmotion/tree.png');
  263. /* 使用导入的背景图片 */
  264. background-size: cover;
  265. /* 确保背景图片完整显示 */
  266. background-repeat: no-repeat;
  267. /* 防止背景图片重复 */
  268. width: 95%;
  269. /* 设置容器宽度 */
  270. height: auto;
  271. /* 高度根据内容动态变化 */
  272. min-height: 400px;
  273. /* 设置最小高度,确保图片显示 */
  274. margin: 0 auto;
  275. /* margin-bottom: 10rem; */
  276. }
  277. .class06 {
  278. background-image: url('@/assets/img/AiEmotion/bk03.png');
  279. /* 使用导入的背景图片 */
  280. background-size: cover;
  281. /* 确保背景图片完整显示 */
  282. background-repeat: no-repeat;
  283. /* 防止背景图片重复 */
  284. width: 95%;
  285. /* 设置容器宽度 */
  286. height: auto;
  287. /* 高度根据内容动态变化 */
  288. min-height: 70rem;
  289. /* 设置最小高度,确保图片显示 */
  290. margin: 0 auto;
  291. }
  292. .class05 {
  293. background-image: url('@/assets/img/AiEmotion/bk03.png');
  294. /* 使用导入的背景图片 */
  295. background-size: cover;
  296. /* 确保背景图片完整显示 */
  297. background-repeat: no-repeat;
  298. /* 防止背景图片重复 */
  299. width: 95%;
  300. /* 设置容器宽度 */
  301. height: auto;
  302. /* 高度根据内容动态变化 */
  303. min-height: 575px;
  304. /* 设置最小高度,确保图片显示 */
  305. margin: 0 auto;
  306. }
  307. .class04 {
  308. background-image: url('@/assets/img/AiEmotion/bk03.png');
  309. /* 使用导入的背景图片 */
  310. background-size: cover;
  311. /* 确保背景图片完整显示 */
  312. background-repeat: no-repeat;
  313. /* 防止背景图片重复 */
  314. width: 95%;
  315. /* 设置容器宽度 */
  316. height: auto;
  317. /* 高度根据内容动态变化 */
  318. min-height: 69rem;
  319. /* 设置最小高度,确保图片显示 */
  320. margin: 0 auto;
  321. }
  322. .class03 {
  323. background-image: url('@/assets/img/AiEmotion/bk03.png');
  324. /* 使用导入的背景图片 */
  325. background-size: cover;
  326. /* 确保背景图片完整显示 */
  327. background-repeat: no-repeat;
  328. /* 防止背景图片重复 */
  329. width: 95%;
  330. /* 设置容器宽度 */
  331. height: auto;
  332. /* 高度根据内容动态变化 */
  333. min-height: 70rem;
  334. /* 设置最小高度,确保图片显示 */
  335. margin: 0 auto;
  336. }
  337. .span01 {
  338. background-image: url('@/assets/img/AiEmotion/bk01.png');
  339. /* 使用导入的背景图片 */
  340. background-size: cover;
  341. /* 背景图片覆盖整个容器 */
  342. background-repeat: no-repeat;
  343. /* 防止背景图片重复 */
  344. display: inline-block;
  345. /* 确保容器是块级元素 */
  346. padding: 10px;
  347. /* 添加内边距以显示内容 */
  348. color: #fff;
  349. /* 设置文字颜色以确保可读性 */
  350. border-radius: 5px;
  351. /* 添加圆角 */
  352. }
  353. .class01 {
  354. width: 90%;
  355. /* 固定容器宽度 */
  356. min-height: 100px;
  357. /* 设置最小高度,确保初始显示 */
  358. height: auto;
  359. /* 高度根据内容动态变化 */
  360. padding: 20px;
  361. /* 添加内边距,确保内容与边界有间距 */
  362. box-sizing: border-box;
  363. /* 包括内边距在宽度和高度计算中 */
  364. background-color: #5e81a7;
  365. margin: 0 auto;
  366. /* 居中容器 */
  367. margin-bottom: 10rem;
  368. }
  369. .ai-emotion-container {
  370. display: flex;
  371. flex-direction: column;
  372. align-items: center;
  373. justify-content: center;
  374. padding: 20px;
  375. position: relative;
  376. }
  377. .user-input-display {
  378. margin-top: 20px;
  379. display: flex;
  380. flex-direction: column;
  381. width: 100%;
  382. }
  383. .message-container {
  384. display: flex;
  385. margin-bottom: 10px;
  386. }
  387. .user-message {
  388. background-color: #007bff;
  389. color: #fff;
  390. padding: 10px 15px;
  391. border-radius: 15px;
  392. max-width: 60%;
  393. text-align: left;
  394. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  395. align-self: flex-end;
  396. }
  397. .ai-message {
  398. background-color: #f1f1f1;
  399. color: #333;
  400. padding: 10px 15px;
  401. border-radius: 15px;
  402. max-width: 60%;
  403. text-align: left;
  404. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  405. align-self: flex-start;
  406. }
  407. .input-container {
  408. display: flex;
  409. align-items: center;
  410. gap: 10px;
  411. }
  412. .fixed-bottom {
  413. position: fixed;
  414. bottom: 100px;
  415. left: 0;
  416. width: 100%;
  417. background-color: #f8f9fa;
  418. padding: 10px 20px;
  419. box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
  420. }
  421. .input-box {
  422. padding: 10px;
  423. font-size: 16px;
  424. border: 1px solid #ccc;
  425. border-radius: 5px;
  426. width: calc(100% - 120px);
  427. }
  428. .send-button {
  429. padding: 10px 20px;
  430. font-size: 16px;
  431. color: #fff;
  432. background-color: #007bff;
  433. border: none;
  434. border-radius: 5px;
  435. cursor: pointer;
  436. }
  437. .send-button:hover {
  438. background-color: #0056b3;
  439. }
  440. </style>