6 changed files with 991 additions and 596 deletions
-
2src/main.js
-
103src/store/emotion.ts
-
154src/views/AiEmotion.vue
-
223src/views/components/StockTabs.vue
-
6src/views/components/emotionalBottomRadar.vue
-
43src/views/components/marketTemperature.vue
@ -0,0 +1,223 @@ |
|||
<template> |
|||
<div class="stock-tabs" v-if="stockList.length > 0"> |
|||
<div class="tabs-container"> |
|||
<div |
|||
v-for="(stock, index) in stockList" |
|||
:key="`${stock.stockInfo.code}-${stock.stockInfo.market}`" |
|||
:class="['tab-item', { active: index === activeStockIndex }]" |
|||
@click="switchStock(index)" |
|||
> |
|||
<div class="stock-info"> |
|||
<span class="stock-name">{{ stock.stockInfo.name }}</span> |
|||
<span class="stock-code">{{ stock.stockInfo.code }}</span> |
|||
</div> |
|||
<button |
|||
class="close-btn" |
|||
@click.stop="removeStock(index)" |
|||
v-if="stockList.length > 1" |
|||
> |
|||
× |
|||
</button> |
|||
</div> |
|||
</div> |
|||
<div class="tabs-actions"> |
|||
<span class="stock-count">{{ stockCount }}/{{ maxStocks }}</span> |
|||
<button |
|||
class="clear-all-btn" |
|||
@click="clearAllStocks" |
|||
v-if="stockList.length > 1" |
|||
> |
|||
清空全部 |
|||
</button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { computed } from 'vue' |
|||
import { useEmotionStore } from '@/store/emotion' |
|||
import { ElMessageBox } from 'element-plus' |
|||
|
|||
const emotionStore = useEmotionStore() |
|||
|
|||
// 计算属性 |
|||
const stockList = computed(() => emotionStore.stockList) |
|||
const activeStockIndex = computed(() => emotionStore.activeStockIndex) |
|||
const stockCount = computed(() => emotionStore.stockCount) |
|||
const maxStocks = computed(() => emotionStore.maxStocks) |
|||
|
|||
// 切换股票 |
|||
const switchStock = (index) => { |
|||
emotionStore.switchStock(index) |
|||
} |
|||
|
|||
// 移除股票 |
|||
const removeStock = async (index) => { |
|||
try { |
|||
await ElMessageBox.confirm( |
|||
'确定要移除这只股票吗?', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning', |
|||
} |
|||
) |
|||
emotionStore.removeStock(index) |
|||
} catch { |
|||
// 用户取消操作 |
|||
} |
|||
} |
|||
|
|||
// 清空所有股票 |
|||
const clearAllStocks = async () => { |
|||
try { |
|||
await ElMessageBox.confirm( |
|||
'确定要清空所有股票吗?', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning', |
|||
} |
|||
) |
|||
emotionStore.clearAllStocks() |
|||
} catch { |
|||
// 用户取消操作 |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.stock-tabs { |
|||
background: #f8f9fa; |
|||
border-radius: 8px; |
|||
padding: 12px; |
|||
margin-bottom: 16px; |
|||
border: 1px solid #e9ecef; |
|||
} |
|||
|
|||
.tabs-container { |
|||
display: flex; |
|||
gap: 8px; |
|||
flex-wrap: wrap; |
|||
margin-bottom: 8px; |
|||
} |
|||
|
|||
.tab-item { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 8px; |
|||
padding: 8px 12px; |
|||
background: #ffffff; |
|||
border: 1px solid #dee2e6; |
|||
border-radius: 6px; |
|||
cursor: pointer; |
|||
transition: all 0.2s ease; |
|||
min-width: 120px; |
|||
} |
|||
|
|||
.tab-item:hover { |
|||
border-color: #007bff; |
|||
box-shadow: 0 2px 4px rgba(0, 123, 255, 0.1); |
|||
} |
|||
|
|||
.tab-item.active { |
|||
background: #007bff; |
|||
border-color: #007bff; |
|||
color: white; |
|||
} |
|||
|
|||
.stock-info { |
|||
display: flex; |
|||
flex-direction: column; |
|||
flex: 1; |
|||
} |
|||
|
|||
.stock-name { |
|||
font-size: 14px; |
|||
font-weight: 500; |
|||
line-height: 1.2; |
|||
} |
|||
|
|||
.stock-code { |
|||
font-size: 12px; |
|||
opacity: 0.8; |
|||
line-height: 1.2; |
|||
} |
|||
|
|||
.close-btn { |
|||
width: 20px; |
|||
height: 20px; |
|||
border: none; |
|||
background: rgba(0, 0, 0, 0.1); |
|||
border-radius: 50%; |
|||
cursor: pointer; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
font-size: 14px; |
|||
line-height: 1; |
|||
transition: background-color 0.2s ease; |
|||
} |
|||
|
|||
.close-btn:hover { |
|||
background: rgba(255, 0, 0, 0.2); |
|||
} |
|||
|
|||
.tab-item.active .close-btn { |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
|
|||
.tab-item.active .close-btn:hover { |
|||
background: rgba(255, 255, 255, 0.3); |
|||
} |
|||
|
|||
.tabs-actions { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding-top: 8px; |
|||
border-top: 1px solid #e9ecef; |
|||
} |
|||
|
|||
.stock-count { |
|||
font-size: 12px; |
|||
color: #6c757d; |
|||
} |
|||
|
|||
.clear-all-btn { |
|||
padding: 4px 8px; |
|||
font-size: 12px; |
|||
background: #dc3545; |
|||
color: white; |
|||
border: none; |
|||
border-radius: 4px; |
|||
cursor: pointer; |
|||
transition: background-color 0.2s ease; |
|||
} |
|||
|
|||
.clear-all-btn:hover { |
|||
background: #c82333; |
|||
} |
|||
|
|||
/* 响应式设计 */ |
|||
@media (max-width: 768px) { |
|||
.tabs-container { |
|||
gap: 6px; |
|||
} |
|||
|
|||
.tab-item { |
|||
min-width: 100px; |
|||
padding: 6px 8px; |
|||
} |
|||
|
|||
.stock-name { |
|||
font-size: 13px; |
|||
} |
|||
|
|||
.stock-code { |
|||
font-size: 11px; |
|||
} |
|||
} |
|||
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue