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.
250 lines
8.1 KiB
250 lines
8.1 KiB
<template>
|
|
<div class="home">
|
|
<div class="container">
|
|
<div class="border3">
|
|
<section class="chart-section">
|
|
<div>
|
|
<div class="trapezoid">
|
|
<span>NVIDIA</span>
|
|
<span>NVDA</span>
|
|
</div>
|
|
<div ref="KlineCanvs" class="KlineClass"></div>
|
|
</div>
|
|
</section>
|
|
</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"
|
|
>
|
|
<template #default="{ $index: rowIndex }">
|
|
<div v-if="getDayData(rowIndex, colIndex + 1)">
|
|
<p class="WDRL_date">
|
|
{{ formatDate(getDayData(rowIndex, colIndex + 1).date) }}
|
|
<span class="month-display">{{ formatMonth(getDayData(rowIndex, colIndex + 1).date) }}</span>
|
|
</p>
|
|
<p class="WDRL_data">
|
|
<template v-if="isIndexCode">
|
|
<span v-if="getDayData(rowIndex, colIndex + 1).market_temperature">
|
|
{{ getDayData(rowIndex, colIndex + 1).market_temperature }}
|
|
</span>
|
|
</template>
|
|
<template v-else>
|
|
<template v-if="isBothRest(rowIndex, colIndex + 1)">休市</template>
|
|
<template v-else>
|
|
<span v-if="getDayData(rowIndex, colIndex + 1).stock_temperature">
|
|
{{ getDayData(rowIndex, colIndex + 1).stock_temperature }}
|
|
</span>
|
|
<span v-if="shouldShowDivider(rowIndex, colIndex + 1)"> | </span>
|
|
<span v-if="getDayData(rowIndex, colIndex + 1).market_temperature">
|
|
{{ getDayData(rowIndex, colIndex + 1).market_temperature }}
|
|
</span>
|
|
</template>
|
|
</template>
|
|
</p>
|
|
</div>
|
|
<div v-else-if="shouldShowRest(rowIndex, colIndex + 1)">
|
|
<p class="WDRL_date">休市</p>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, onMounted, defineExpose } from 'vue'
|
|
import * as echarts from 'echarts'
|
|
import axios from 'axios'
|
|
|
|
const KlineCanvs = ref()
|
|
const WDRL = ref([])
|
|
const indexCodes = ['NDX','DJIA','SPX','STI','KLSE','TSX','N225','KS11','JKSE','1A0001','HSI','I63','VNINDE']
|
|
const isIndexCode = computed(() => indexCodes.includes(localStorage.getItem('localCode')))
|
|
const groupedWDRL = computed(() => {
|
|
const result = []
|
|
for (let i = 0; i < WDRL.value.length; i += 7) {
|
|
result.push(WDRL.value.slice(i, i + 7))
|
|
}
|
|
return result
|
|
})
|
|
function getDayData(rowIndex, dayIndex) {
|
|
const weekData = groupedWDRL.value[rowIndex]
|
|
if (weekData && weekData.length >= dayIndex) {
|
|
return weekData[dayIndex - 1] || {}
|
|
}
|
|
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
|
|
const flatIndex = rowIndex * 7 + (dayIndex - 1)
|
|
const targetDay = WDRL.value[flatIndex]
|
|
if (!targetDay || !targetDay.date) return false
|
|
const [year, month, day] = targetDay.date.split('/').map(Number)
|
|
if (!year || !month || !day) return false
|
|
const dateObj = new Date(year, month - 1, day)
|
|
const today = new Date()
|
|
if (dateObj.getMonth() !== today.getMonth() || dateObj.getFullYear() !== today.getFullYear()) return false
|
|
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)
|
|
if (isNaN(value)) return { backgroundColor: '#4b759f', color: 'white' }
|
|
if (value >= 90) return { backgroundColor: '#BD0000', color: 'white' }
|
|
else if (value >= 70) return { backgroundColor: '#FF5638', color: 'white' }
|
|
else if (value >= 50) return { backgroundColor: '#C929E6', color: 'white' }
|
|
else if (value >= 20) return { backgroundColor: '#00AB00', color: 'white' }
|
|
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) {
|
|
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: {},
|
|
legend: { data: ['K线', '市场温度', '股票温度'], textStyle: { color: 'white' } },
|
|
xAxis: {
|
|
type: 'category',
|
|
data: dateLabels,
|
|
axisLine: { lineStyle: { color: '#8392A5' } }
|
|
},
|
|
yAxis: [{}, {
|
|
min: 0,
|
|
max: 100,
|
|
position: 'right',
|
|
axisLabel: { color: '#FFA500' },
|
|
axisLine: { lineStyle: { color: 'purple', width: 2 } }
|
|
}],
|
|
color: ['#f00', '#9370DB'],
|
|
series: [
|
|
{
|
|
name: 'K线',
|
|
type: 'candlestick',
|
|
data: klineData,
|
|
itemStyle: { color: '#0CF49B', color0: '#FD1050' }
|
|
},
|
|
{
|
|
name: '市场温度',
|
|
type: 'line',
|
|
yAxisIndex: 1,
|
|
data: marketData
|
|
},
|
|
{
|
|
name: '股票温度',
|
|
type: 'line',
|
|
yAxisIndex: 1,
|
|
data: stockData
|
|
}
|
|
]
|
|
})
|
|
}
|
|
onMounted(fetchData)
|
|
defineExpose({ initChart })
|
|
</script>
|
|
|
|
<style scoped>
|
|
.WDRL_date {
|
|
margin-top: 2px;
|
|
text-align: center;
|
|
font-size: 1.6vw;
|
|
font-weight: bold;
|
|
padding-top: 0%;
|
|
position: relative;
|
|
}
|
|
.month-display {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
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 {
|
|
min-height: 100vh;
|
|
background-color: rgb(0, 22, 65);
|
|
}
|
|
.container {
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
max-width: 80vw;
|
|
}
|
|
.border3, .border4 {
|
|
margin-top: 40px;
|
|
background-color: #1a1a1a;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
}
|
|
</style>
|