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.

249 lines
8.1 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
  1. <template>
  2. <div class="home">
  3. <div class="container">
  4. <div class="border3">
  5. <section class="chart-section">
  6. <div>
  7. <div class="trapezoid">
  8. <span>NVIDIA</span>
  9. <span>NVDA</span>
  10. </div>
  11. <div ref="KlineCanvs" class="KlineClass"></div>
  12. </div>
  13. </section>
  14. </div>
  15. <div class="border4">
  16. <el-table
  17. :data="groupedWDRL"
  18. border
  19. :row-style="{ height: '8.6vw' }"
  20. header-cell-class-name="table_header"
  21. :cell-style="tableCellStyle"
  22. >
  23. <el-table-column
  24. v-for="(day, colIndex) in ['一', '二', '三', '四', '五', '六', '日']"
  25. :key="colIndex"
  26. :label="day"
  27. >
  28. <template #default="{ $index: rowIndex }">
  29. <div v-if="getDayData(rowIndex, colIndex + 1)">
  30. <p class="WDRL_date">
  31. {{ formatDate(getDayData(rowIndex, colIndex + 1).date) }}
  32. <span class="month-display">{{ formatMonth(getDayData(rowIndex, colIndex + 1).date) }}</span>
  33. </p>
  34. <p class="WDRL_data">
  35. <template v-if="isIndexCode">
  36. <span v-if="getDayData(rowIndex, colIndex + 1).market_temperature">
  37. {{ getDayData(rowIndex, colIndex + 1).market_temperature }}
  38. </span>
  39. </template>
  40. <template v-else>
  41. <template v-if="isBothRest(rowIndex, colIndex + 1)">休市</template>
  42. <template v-else>
  43. <span v-if="getDayData(rowIndex, colIndex + 1).stock_temperature">
  44. {{ getDayData(rowIndex, colIndex + 1).stock_temperature }}
  45. </span>
  46. <span v-if="shouldShowDivider(rowIndex, colIndex + 1)"> | </span>
  47. <span v-if="getDayData(rowIndex, colIndex + 1).market_temperature">
  48. {{ getDayData(rowIndex, colIndex + 1).market_temperature }}
  49. </span>
  50. </template>
  51. </template>
  52. </p>
  53. </div>
  54. <div v-else-if="shouldShowRest(rowIndex, colIndex + 1)">
  55. <p class="WDRL_date">休市</p>
  56. </div>
  57. </template>
  58. </el-table-column>
  59. </el-table>
  60. </div>
  61. </div>
  62. </div>
  63. </template>
  64. <script setup>
  65. import { ref, computed, onMounted, defineExpose } from 'vue'
  66. import * as echarts from 'echarts'
  67. import axios from 'axios'
  68. const KlineCanvs = ref()
  69. const WDRL = ref([])
  70. const indexCodes = ['NDX','DJIA','SPX','STI','KLSE','TSX','N225','KS11','JKSE','1A0001','HSI','I63','VNINDE']
  71. const isIndexCode = computed(() => indexCodes.includes(localStorage.getItem('localCode')))
  72. const groupedWDRL = computed(() => {
  73. const result = []
  74. for (let i = 0; i < WDRL.value.length; i += 7) {
  75. result.push(WDRL.value.slice(i, i + 7))
  76. }
  77. return result
  78. })
  79. function getDayData(rowIndex, dayIndex) {
  80. const weekData = groupedWDRL.value[rowIndex]
  81. if (weekData && weekData.length >= dayIndex) {
  82. return weekData[dayIndex - 1] || {}
  83. }
  84. return {}
  85. }
  86. function shouldShowDivider(rowIndex, dayIndex) {
  87. const data = getDayData(rowIndex, dayIndex)
  88. return data?.market_temperature && data?.stock_temperature
  89. }
  90. function isBothRest(rowIndex, colIndex) {
  91. const data = getDayData(rowIndex, colIndex)
  92. return data && data.stock_temperature === '休市' && data.market_temperature === '休市'
  93. }
  94. function shouldShowRest(rowIndex, dayIndex) {
  95. const data = getDayData(rowIndex, dayIndex)
  96. if (data && (data.stock_temperature || data.market_temperature)) return false
  97. const flatIndex = rowIndex * 7 + (dayIndex - 1)
  98. const targetDay = WDRL.value[flatIndex]
  99. if (!targetDay || !targetDay.date) return false
  100. const [year, month, day] = targetDay.date.split('/').map(Number)
  101. if (!year || !month || !day) return false
  102. const dateObj = new Date(year, month - 1, day)
  103. const today = new Date()
  104. if (dateObj.getMonth() !== today.getMonth() || dateObj.getFullYear() !== today.getFullYear()) return false
  105. const weekday = dateObj.getDay()
  106. return weekday >= 1 && weekday <= 5
  107. }
  108. function formatMonth(dateStr) {
  109. if (!dateStr) return ''
  110. const month = dateStr.split('/')[1]
  111. const map = { '01': '一月', '02': '二月', '03': '三月', '04': '四月', '05': '五月', '06': '六月', '07': '七月', '08': '八月', '09': '九月', 10: '十月', 11: '十一月', 12: '十二月' }
  112. return map[month] || ''
  113. }
  114. function formatDate(dateStr) {
  115. if (!dateStr) return ''
  116. return dateStr.split('/')[2]
  117. }
  118. function tableCellStyle({ row, column, rowIndex, columnIndex }) {
  119. const data = getDayData(rowIndex, columnIndex + 1)
  120. let value = isIndexCode.value ? Number(data?.market_temperature) : Number(data?.stock_temperature)
  121. if (isNaN(value)) return { backgroundColor: '#4b759f', color: 'white' }
  122. if (value >= 90) return { backgroundColor: '#BD0000', color: 'white' }
  123. else if (value >= 70) return { backgroundColor: '#FF5638', color: 'white' }
  124. else if (value >= 50) return { backgroundColor: '#C929E6', color: 'white' }
  125. else if (value >= 20) return { backgroundColor: '#00AB00', color: 'white' }
  126. else if (value > 0) return { backgroundColor: '#87CEEB', color: 'white' }
  127. else return { backgroundColor: '#4b759f', color: 'white' }
  128. }
  129. const fetchData = async () => {
  130. try {
  131. const response = await axios.post('http://39.101.133.168:8828/link/api/aiEmotion/client/getAiEmotionData', {
  132. token: '9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs',
  133. market: 'usa',
  134. code: 'TSLA',
  135. language: 'cn'
  136. }, {
  137. headers: { 'Content-Type': 'application/json' }
  138. })
  139. if (response.data.code === 200) {
  140. WDRL.value = response.data.data.WDRL
  141. const raw = response.data.data.GSWDJ
  142. initChart(raw)
  143. }
  144. } catch (error) {
  145. console.error('fetchData error:', error)
  146. }
  147. }
  148. function initChart(raw) {
  149. const dateLabels = raw.map(item => item[0])
  150. const marketData = raw.map(item => Math.round(item[1]))
  151. const stockData = raw.map(item => Math.round(item[2]))
  152. const klineData = marketData.map(base => {
  153. const open = base - 3 + Math.random() * 6
  154. const close = base - 3 + Math.random() * 6
  155. const low = Math.min(open, close) - Math.random() * 3
  156. const high = Math.max(open, close) + Math.random() * 3
  157. return [open, close, low, high].map(v => Math.round(v * 10) / 10)
  158. })
  159. const chart = echarts.init(KlineCanvs.value)
  160. chart.setOption({
  161. tooltip: {},
  162. legend: { data: ['K线', '市场温度', '股票温度'], textStyle: { color: 'white' } },
  163. xAxis: {
  164. type: 'category',
  165. data: dateLabels,
  166. axisLine: { lineStyle: { color: '#8392A5' } }
  167. },
  168. yAxis: [{}, {
  169. min: 0,
  170. max: 100,
  171. position: 'right',
  172. axisLabel: { color: '#FFA500' },
  173. axisLine: { lineStyle: { color: 'purple', width: 2 } }
  174. }],
  175. color: ['#f00', '#9370DB'],
  176. series: [
  177. {
  178. name: 'K线',
  179. type: 'candlestick',
  180. data: klineData,
  181. itemStyle: { color: '#0CF49B', color0: '#FD1050' }
  182. },
  183. {
  184. name: '市场温度',
  185. type: 'line',
  186. yAxisIndex: 1,
  187. data: marketData
  188. },
  189. {
  190. name: '股票温度',
  191. type: 'line',
  192. yAxisIndex: 1,
  193. data: stockData
  194. }
  195. ]
  196. })
  197. }
  198. onMounted(fetchData)
  199. defineExpose({ initChart })
  200. </script>
  201. <style scoped>
  202. .WDRL_date {
  203. margin-top: 2px;
  204. text-align: center;
  205. font-size: 1.6vw;
  206. font-weight: bold;
  207. padding-top: 0%;
  208. position: relative;
  209. }
  210. .month-display {
  211. position: absolute;
  212. top: 0;
  213. right: 0;
  214. font-size: 1vw;
  215. color: rgb(58, 58, 58);
  216. }
  217. .WDRL_data {
  218. margin-top: 5px;
  219. text-align: center;
  220. font-size: 1vw;
  221. font-weight: bold;
  222. }
  223. .table_header {
  224. color: white;
  225. background: #2a2a2a;
  226. }
  227. .KlineClass {
  228. width: 100%;
  229. height: 400px;
  230. }
  231. .home {
  232. min-height: 100vh;
  233. background-color: rgb(0, 22, 65);
  234. }
  235. .container {
  236. margin: 0 auto;
  237. padding: 20px;
  238. max-width: 80vw;
  239. }
  240. .border3, .border4 {
  241. margin-top: 40px;
  242. background-color: #1a1a1a;
  243. border-radius: 8px;
  244. padding: 20px;
  245. }
  246. </style>