Browse Source

加入温度计图表,数据显示正常。

ds_hxl
宋杰 3 weeks ago
parent
commit
3e5e8d9938
  1. BIN
      src/assets/img/AiEmotion/tree.png
  2. BIN
      src/assets/img/AiEmotion/tree02.png
  3. 221
      src/views/AiEmotion.vue
  4. 127
      src/views/components/marketTemperature.vue
  5. 7
      src/views/emotionsEcharts.vue

BIN
src/assets/img/AiEmotion/tree.png

Before

Width: 568  |  Height: 319  |  Size: 312 KiB

BIN
src/assets/img/AiEmotion/tree02.png

After

Width: 351  |  Height: 176  |  Size: 98 KiB

221
src/views/AiEmotion.vue

@ -1,7 +1,10 @@
<template>
<div class="ai-emotion-container">
<!-- 金轮 -->
<div class="golden-wheel">
<img src="@/assets/img/AiEmotion/金轮.png" alt="金轮图标" class="rotating-image">
</div>
<!-- 消息显示区域 -->
<div class="user-input-display">
<div v-for="(message, index) in messages" :key="index" class="message-container">
<!-- 用户输入内容 -->
@ -21,21 +24,22 @@
</div>
</div>
<!-- 渲染整个页面 -->
<div class="class01">
<div v-if="isPageLoaded" class="class01">
<!-- 四维矩阵图 -->
<div class="class02">
<div class="span01">
{{ stockName || '未选择股票' }}
{{ stockName }}
</div>
<span class="span02"> 2025/06/07</span>
<span class="span02">{{ displayDate }}</span>
</div>
<div class="class0201">
<img src="@/assets/img/AiEmotion/L1.png" alt="情绪监控图标">
</div>
<!-- 温度计图表 -->
<div class="class03">
<marketTemperature />
<marketTemperature ref="marketTemperatureRef" />
</div>
<div class="class0301">
<img src="@/assets/img/AiEmotion/L2.png" alt="情绪解码图标">
@ -73,29 +77,43 @@
</div>
<!-- 核心看点 -->
<div class="class0702">
<img src="@/assets/img/AiEmotion/核心看点.png" alt="核心逻辑字样">
<img src="@/assets/img/AiEmotion/核心看点.png" alt="核心看点字样">
</div>
<div class="bk-image">
<div class="text-container">
<p>情绪监控-金融宇宙的量子检测网络核心任务:构建全市场情绪引力场雷达</p>
<p>情绪解码-主力思维的神经破译矩阵核心任务:解构资金行为的量子密码</p>
<p>情绪推演-未来战争的时空推演舱核心任务:情绪推演</p>
<p>情绪套利-财富裂变的粒子对撞机核心任务:将情绪差转化为a收益粒子流</p>
</div>
<div class="class07">
</div>
<!-- 核心逻辑 -->
<div class="class0700">
<img src="@/assets/img/AiEmotion/核心逻辑.png" alt="">
<img src="@/assets/img/AiEmotion/核心逻辑.png" alt="核心逻辑字样">
</div>
<div class="class07000">
</div>
<div class="class0701">
<div class="class08">
<div class="lz-img">
<img src="@/assets/img/AiEmotion/量子神经决策树.png" alt="树标题">
</div>
<div class="class08">
<img src="@/assets/img/AiEmotion/tree.png" alt="树图片">
<div class="scaled-img">
<img src="@/assets/img/AiEmotion/tree02.png" alt="树图片">
</div>
</div>
<!-- 场景应用 -->
<div class="class09">
<img src="@/assets/img/AiEmotion/场景应用.png" alt="场景应用标题">
<div class="bk-image"></div>
<div class="bk-image">
<!-- <div class="text-container">
<p>情绪监控-金融宇宙的量子检测网络核心任务:构建全市场情绪引力场雷达</p>
<p>情绪解码-主力思维的神经破译矩阵核心任务:解构资金行为的量子密码</p>
<p>情绪推演-未来战争的时空推演舱核心任务:情绪推演</p>
<p>情绪套利-财富裂变的粒子对撞机核心任务:将情绪差转化为a收益粒子流</p>
</div> -->
</div>
</div>
</div>
<div v-else class="loading">
<p>数据加载中请稍候...</p>
</div>
</template>
@ -109,12 +127,25 @@ import emoEnergyConverter from '@/views/components/emoEnergyConverter.vue'; //
import marketTemperature from '@/views/components/marketTemperature.vue';
const stockName = ref(''); //
const marketTemperatureRef = ref(null); //
const emoEnergyConverterRef = ref(null)
const emotionDecodRef = ref(null)
const emotionalBottomRadarRef = ref(null)
const userInput = ref('');
const messages = ref([]);
const displayDate = ref(''); //
const isPageLoaded = ref(false); //
// span01
function updateSpan01() {
nextTick(() => {
const span01 = document.querySelector('.span01');
if (span01) {
span01.textContent = `${stockName.value}量子四维矩阵图`;
}
});
}
//
async function sendMessage() {
@ -126,6 +157,12 @@ async function sendMessage() {
messages.value.push(userMessage);
userInput.value = ''; //
//
messages.value.push({
sender: 'ai',
text: '数据加载中,请稍候...'
});
try {
//
const params = {
@ -159,6 +196,9 @@ async function sendMessage() {
stockName.value = parsedData.name || '未知股票';
//
fetchData(parsedData.code, parsedData.market);
// span01
updateSpan01();
} else {
console.error('工作流接口返回非股票信息:', parsedData.refuse);
messages.value.push({
@ -188,8 +228,8 @@ async function fetchData(code, market) {
const stockDataParams = {
// token: '+XgqsgdW0RLIbIG2pxnnbZi0+fEeMx8pywnIlrmTxtkSaPZ9xjSOWrxq+s0rL3RrfNhXPvGtz9srFfjwu8A',
token: '9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs',
market: 'my',
code: '1295',
market: 'usa',
code: 'TSLA',
language: 'cn',
};
@ -216,6 +256,17 @@ async function fetchData(code, market) {
//
renderCharts(stockDataResponse.data);
console.log('2222222222222222222222')
//
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
displayDate.value = `${year}/${month}/${day}`;
//
isPageLoaded.value = true;
} else {
console.error('图表数据接口返回数据不完整');
messages.value.push({
@ -233,8 +284,50 @@ async function fetchData(code, market) {
}
//
// function renderCharts(data) {
// nextTick(() => {
// //
// if (marketTemperatureRef.value && data.GSWDJ) {
// console.log('');
// console.log('', data.GSWDJ)
// marketTemperatureRef.value.initChart(data.GSWDJ, data.KLine20, data.WDRL);
// console.log('');
// }
// //
// if (emotionDecodRef.value && data.QXJMQ) {
// console.log('');
// console.log('', data.QXJMQ)
// emotionDecodRef.value.initQXNLZHEcharts(data.KLine20, data.QXJMQ);
// console.log('');
// }
// //
// if (emotionalBottomRadarRef.value && data.QXTDLD) {
// console.log('');
// console.log('', data.QXTDLD)
// emotionalBottomRadarRef.value.initEmotionalBottomRadar(data.KLine20, data.QXTDLD);
// console.log('');
// }
// //
// if (emoEnergyConverterRef.value && data.QXNLZHQ) {
// console.log('');
// console.log('KLine20:', data.KLine20);
// console.log('QXNLZHQ:', data.QXNLZHQ);
// emoEnergyConverterRef.value.initQXNLZHEcharts(data.KLine20, data.QXNLZHQ);
// console.log('');
// }
// });
// }
function renderCharts(data) {
return new Promise((resolve) => {
nextTick(() => {
//
if (marketTemperatureRef.value && data.GSWDJ) {
console.log('开始渲染股市温度计图表');
console.log('股市温度计数据', data.GSWDJ)
marketTemperatureRef.value.initChart(data.GSWDJ, data.KLine20, data.WDRL);
console.log('股市温度计图表已渲染');
}
//
if (emotionDecodRef.value && data.QXJMQ) {
console.log('开始渲染情绪解码器图表');
@ -257,23 +350,65 @@ function renderCharts(data) {
emoEnergyConverterRef.value.initQXNLZHEcharts(data.KLine20, data.QXNLZHQ);
console.log('情绪能量转化器图表已渲染');
}
// resolve
resolve();
});
});
}
</script>
<style scoped>
/* 定义旋转动画 */
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/* 应用动画到图片 */
.rotating-image {
animation: rotate 5s linear;
/* 5 秒完成一次旋转,线性速度*/
}
.bk-image {
background-image: url('@/assets/img/AiEmotion/bk03.png');
background-size: cover;
background-position: center;
/* background-position: center; */
background-repeat: no-repeat;
width: 95%;
height: 70rem;
height: 30rem;
margin: 0 auto;
margin-top: 20px;
}
/* 最后文字的颜色 */
.text-container {
position: relative;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
/* 设置文字颜色 */
text-align: left;
/* 文字居中对齐 */
padding: 20px;
}
.text-container p {
margin: 10px 0;
/* 设置段落间距 */
font-size: 40px;
/* 设置字体大小 */
margin-left: 50px;
}
.class07 {
background-image: url('@/assets/img/AiEmotion/bk03.png');
/* 使用导入的背景图片 */
@ -290,16 +425,6 @@ function renderCharts(data) {
margin: 0 auto;
}
.class07000 {
background-image: url(/src/assets/img/AiEmotion/bk03.png);
background-size: contain;
background-repeat: no-repeat;
width: 95%;
height: auto;
min-height: 70rem;
margin: 0 auto;
}
.class0700 {
margin: 0 auto;
width: fit-content;
@ -365,9 +490,27 @@ function renderCharts(data) {
text-align: center;
}
/* 为需要放大的图片添加样式 */
.scaled-img {
transform: scale(2.5);
text-align: center;
}
.lz-img {
margin-bottom: 10rem;
text-align: center;
padding-top: 70px;
}
.class08 {
background-image: url('@/assets/img/AiEmotion/bk03.png');
background-size: cover;
background-repeat: no-repeat;
width: 95%;
height: auto;
min-height: 40rem;
margin: 0 auto;
width: fit-content;
}
.class06 {
@ -434,6 +577,12 @@ function renderCharts(data) {
margin: 0 auto;
}
.span02 {
margin-left: 500px;
font-size: 1.5rem;
color: white;
}
.span01 {
background-image: url('@/assets/img/AiEmotion/bk01.png');
/* 使用导入的背景图片 */
@ -451,8 +600,10 @@ function renderCharts(data) {
/* 添加圆角 */
min-height: 3rem;
min-width: 30rem;
font-size: 1.5rem; /* 增加字体大小以便更清晰显示股票名称 */
text-align: center; /* 文字居中 */
font-size: 1.5rem;
/* 增加字体大小以便更清晰显示股票名称 */
text-align: center;
/* 文字居中 */
}
.class01 {

127
src/views/components/marketTemperature.vue

@ -1,12 +1,12 @@
<template>
<div class="home">
<div class="market-temperature">
<div class="container">
<div class="border3">
<section class="chart-section">
<div>
<div class="trapezoid">
<span>NVIDIA</span>
<span>NVDA</span>
<span>{{ companyName }}</span>
<span>{{ stockCode }}</span>
</div>
<div ref="KlineCanvs" class="KlineClass"></div>
</div>
@ -14,18 +14,9 @@
</div>
<div class="border4">
<el-table
:data="groupedWDRL"
border
:row-style="{ height: '8.6vw' }"
header-cell-class-name="table_header"
:cell-style="tableCellStyle"
>
<el-table-column
v-for="(day, colIndex) in ['一', '二', '三', '四', '五', '六', '日']"
:key="colIndex"
:label="day"
>
<el-table :data="groupedWDRL" border :row-style="{ height: '8.6vw' }" header-cell-class-name="table_header"
:cell-style="tableCellStyle">
<el-table-column v-for="(day, colIndex) in ['一', '二', '三', '四', '五', '六', '日']" :key="colIndex" :label="day">
<template #default="{ $index: rowIndex }">
<div v-if="getDayData(rowIndex, colIndex + 1)">
<p class="WDRL_date">
@ -64,14 +55,27 @@
</template>
<script setup>
import { ref, computed, onMounted, defineExpose } from 'vue'
import { ref, computed, onMounted, defineExpose, defineProps } from 'vue'
import * as echarts from 'echarts'
import axios from 'axios'
const props = defineProps({
companyName: {
type: String,
default: ''
},
stockCode: {
type: String,
default: ''
}
})
const KlineCanvs = ref()
const WDRL = ref([])
const klineDataRaw = ref([]) // K 线
const indexCodes = ['NDX', 'DJIA', 'SPX', 'STI', 'KLSE', 'TSX', 'N225', 'KS11', 'JKSE', '1A0001', 'HSI', 'I63', 'VNINDE']
const isIndexCode = computed(() => indexCodes.includes(localStorage.getItem('localCode')))
const isIndexCode = computed(() => indexCodes.includes(props.code))
// WDRL
const groupedWDRL = computed(() => {
const result = []
for (let i = 0; i < WDRL.value.length; i += 7) {
@ -79,6 +83,8 @@ const groupedWDRL = computed(() => {
}
return result
})
//
function getDayData(rowIndex, dayIndex) {
const weekData = groupedWDRL.value[rowIndex]
if (weekData && weekData.length >= dayIndex) {
@ -86,14 +92,20 @@ function getDayData(rowIndex, dayIndex) {
}
return {}
}
//
function shouldShowDivider(rowIndex, dayIndex) {
const data = getDayData(rowIndex, dayIndex)
return data?.market_temperature && data?.stock_temperature
}
//
function isBothRest(rowIndex, colIndex) {
const data = getDayData(rowIndex, colIndex)
return data && data.stock_temperature === '休市' && data.market_temperature === '休市'
}
//
function shouldShowRest(rowIndex, dayIndex) {
const data = getDayData(rowIndex, dayIndex)
if (data && (data.stock_temperature || data.market_temperature)) return false
@ -108,16 +120,22 @@ function shouldShowRest(rowIndex, dayIndex) {
const weekday = dateObj.getDay()
return weekday >= 1 && weekday <= 5
}
//
function formatMonth(dateStr) {
if (!dateStr) return ''
const month = dateStr.split('/')[1]
const map = { '01': '一月', '02': '二月', '03': '三月', '04': '四月', '05': '五月', '06': '六月', '07': '七月', '08': '八月', '09': '九月', 10: '十月', 11: '十一月', 12: '十二月' }
return map[month] || ''
}
//
function formatDate(dateStr) {
if (!dateStr) return ''
return dateStr.split('/')[2]
}
//
function tableCellStyle({ row, column, rowIndex, columnIndex }) {
const data = getDayData(rowIndex, columnIndex + 1)
let value = isIndexCode.value ? Number(data?.market_temperature) : Number(data?.stock_temperature)
@ -129,36 +147,30 @@ function tableCellStyle({ row, column, rowIndex, columnIndex }) {
else if (value > 0) return { backgroundColor: '#87CEEB', color: 'white' }
else return { backgroundColor: '#4b759f', color: 'white' }
}
const fetchData = async () => {
try {
const response = await axios.post('http://39.101.133.168:8828/link/api/aiEmotion/client/getAiEmotionData', {
token: '9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs',
market: 'usa',
code: 'TSLA',
language: 'cn'
}, {
headers: { 'Content-Type': 'application/json' }
})
if (response.data.code === 200) {
WDRL.value = response.data.data.WDRL
const raw = response.data.data.GSWDJ
initChart(raw)
}
} catch (error) {
console.error('fetchData error:', error)
}
//
function initChart(raw, klineDataRawValue, WDRLValue) {
if (!raw || !klineDataRawValue || !WDRLValue) {
console.error('initChart: raw, klineDataRawValue or WDRLValue is undefined')
return
}
function initChart(raw) {
// K 线
const klineData = klineDataRawValue.map(item => {
const open = item[1]
const close = item[2]
const low = item[3]
const high = item[4]
return [open, close, low, high]
})
//
WDRL.value = WDRLValue
klineDataRaw.value = klineDataRawValue
const dateLabels = raw.map(item => item[0])
const marketData = raw.map(item => Math.round(item[1]))
const stockData = raw.map(item => Math.round(item[2]))
const klineData = marketData.map(base => {
const open = base - 3 + Math.random() * 6
const close = base - 3 + Math.random() * 6
const low = Math.min(open, close) - Math.random() * 3
const high = Math.max(open, close) + Math.random() * 3
return [open, close, low, high].map(v => Math.round(v * 10) / 10)
})
const chart = echarts.init(KlineCanvs.value)
chart.setOption({
tooltip: {},
@ -195,10 +207,23 @@ function initChart(raw) {
yAxisIndex: 1,
data: stockData
}
],
// dataZoom
dataZoom: [
{
type: 'slider',
xAxisIndex: 0,
filterMode: 'filter'
},
{
type: 'inside',
xAxisIndex: 0,
filterMode: 'filter'
}
]
})
}
onMounted(fetchData)
defineExpose({ initChart })
</script>
@ -211,6 +236,7 @@ defineExpose({ initChart })
padding-top: 0%;
position: relative;
}
.month-display {
position: absolute;
top: 0;
@ -218,30 +244,37 @@ defineExpose({ initChart })
font-size: 1vw;
color: rgb(58, 58, 58);
}
.WDRL_data {
margin-top: 5px;
text-align: center;
font-size: 1vw;
font-weight: bold;
}
.table_header {
color: white;
background: #2a2a2a;
}
.KlineClass {
width: 100%;
height: 400px;
}
.home {
.market-temperature {
min-height: 100vh;
background-color: rgb(0, 22, 65);
}
.container {
margin: 0 auto;
padding: 20px;
max-width: 80vw;
}
.border3, .border4 {
.border3,
.border4 {
margin-top: 40px;
background-color: #1a1a1a;
border-radius: 8px;

7
src/views/emotionsEcharts.vue

@ -3,17 +3,20 @@
<emoEnergyConverter ref="emoEnergyConverterRef"></emoEnergyConverter>
<emotionDecod ref="emotionDecodRef"></emotionDecod>
<EmotionalBottomRadar ref="emotionalBottomRadarRef"></EmotionalBottomRadar>
<marketTemperature ref="marketTemperatureRef"></marketTemperature>
</template>
<script setup>
import emoEnergyConverter from '@/views/components/emoEnergyConverter.vue'
import emotionDecod from '@/views/components/emotionDecod.vue'
import EmotionalBottomRadar from '@/views/components/emotionalBottomRadar.vue'
import { ref, onMounted, onBeforeUnmount, toRef } from 'vue';
import marketTemperature from '@/views/components/marketTemperature.vue';
import axios from "axios";
const emoEnergyConverterRef = ref(null)
const emotionDecodRef = ref(null)
const emotionalBottomRadarRef = ref(null)
const marketTemperatureRef = ref(null)
onMounted(()=>{
axios({
@ -35,6 +38,8 @@ onMounted(()=>{
//
emotionalBottomRadarRef.value.initEmotionalBottomRadar(res.data.data.KLine20, res.data.data.QXTDLD)
//
marketTemperatureRef.value.initChart(res.data.data.GSWDJ, res.data.data.KLine20, res.data.data.WDRL)
})
})
})

Loading…
Cancel
Save