美化了页面布局,并解决了页面抖动的问题
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -7,23 +7,20 @@
|
||||
<h1>GoFundBot</h1>
|
||||
<p>智能基金分析 · 实时市场追踪</p>
|
||||
</div>
|
||||
<!-- 顶部搜索框 -->
|
||||
<div class="header-search">
|
||||
<FundSearch @fund-selected="handleHeaderSearch" :compact="true" />
|
||||
</div>
|
||||
<!-- 模式切换 -->
|
||||
<div class="header-right">
|
||||
<div class="mode-switch">
|
||||
<button
|
||||
class="mode-btn"
|
||||
:class="{ active: viewMode === 'dashboard' }"
|
||||
@click="viewMode = 'dashboard'"
|
||||
@click="resetToDashboard"
|
||||
>
|
||||
🏠 市场大盘
|
||||
</button>
|
||||
<button
|
||||
class="mode-btn"
|
||||
:class="{ active: viewMode === 'detail' }"
|
||||
@click="viewMode = 'detail'"
|
||||
>
|
||||
📋 基金详情
|
||||
</button>
|
||||
<button
|
||||
class="mode-btn"
|
||||
:class="{ active: viewMode === 'screening' }"
|
||||
@@ -31,13 +28,6 @@
|
||||
>
|
||||
🔍 基金筛选
|
||||
</button>
|
||||
<button
|
||||
class="mode-btn"
|
||||
:class="{ active: viewMode === 'compare' }"
|
||||
@click="viewMode = 'compare'"
|
||||
>
|
||||
📈 基金对比
|
||||
</button>
|
||||
<button
|
||||
class="mode-btn"
|
||||
:class="{ active: viewMode === 'backtest' }"
|
||||
@@ -52,28 +42,40 @@
|
||||
|
||||
<main class="app-main">
|
||||
<!-- 市场大盘模式 -->
|
||||
<div v-if="viewMode === 'dashboard'" class="dashboard-layout">
|
||||
<div v-if="viewMode === 'dashboard'" class="dashboard-layout" :class="{ 'full-content': showFullContent }">
|
||||
<!-- 左侧:自选列表 -->
|
||||
<aside class="dashboard-sidebar">
|
||||
<FundWatchlist
|
||||
@view-fund="handleDashboardFundView"
|
||||
@add-to-compare="handleAddToCompare"
|
||||
:compareMode="false"
|
||||
:compareMode="compareMode"
|
||||
:compareFunds="compareFunds"
|
||||
:showCompareToggle="true"
|
||||
@toggle-compare="toggleCompareMode"
|
||||
/>
|
||||
</aside>
|
||||
|
||||
<!-- 中间:核心内容 -->
|
||||
<div class="dashboard-main">
|
||||
<!-- 基金对比页面(选中多只基金时显示) -->
|
||||
<FundComparison
|
||||
v-if="compareMode && compareFunds.length >= 2"
|
||||
:compareFunds="compareFunds"
|
||||
@remove-fund="handleRemoveFromCompare"
|
||||
@clear-funds="handleClearCompare"
|
||||
/>
|
||||
<!-- 基金详情(选中时显示) -->
|
||||
<FundDetail v-else-if="selectedFundCode && !compareMode" :fundCode="selectedFundCode" />
|
||||
<!-- 市场指数 + 金价 -->
|
||||
<MarketOverview
|
||||
v-else
|
||||
:showGoldHistory="true"
|
||||
:showSSE30Min="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:快讯 + 板块 -->
|
||||
<aside class="dashboard-right">
|
||||
<!-- 右侧:快讯 + 板块(显示详情/对比时隐藏) -->
|
||||
<aside class="dashboard-right" v-if="!showFullContent">
|
||||
<FlashNews :count="15" :refreshInterval="60000" />
|
||||
<SectorRank :limit="50" :initialDisplay="12" />
|
||||
</aside>
|
||||
@@ -86,8 +88,10 @@
|
||||
<FundWatchlist
|
||||
@view-fund="handleFundSelected"
|
||||
@add-to-compare="handleAddToCompare"
|
||||
:compareMode="viewMode === 'compare'"
|
||||
:compareMode="compareMode"
|
||||
:compareFunds="compareFunds"
|
||||
:showCompareToggle="true"
|
||||
@toggle-compare="toggleCompareMode"
|
||||
/>
|
||||
</aside>
|
||||
|
||||
@@ -101,32 +105,12 @@
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 对比模式 -->
|
||||
<template v-else-if="viewMode === 'compare'">
|
||||
<FundComparison
|
||||
:compareFunds="compareFunds"
|
||||
@remove-fund="handleRemoveFromCompare"
|
||||
@clear-funds="handleClearCompare"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 回测模式 -->
|
||||
<template v-else-if="viewMode === 'backtest'">
|
||||
<FundBacktest
|
||||
:fundCode="selectedFundCode"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 详情模式 -->
|
||||
<template v-else>
|
||||
<FundSearch @fund-selected="handleFundSelected" />
|
||||
<FundDetail v-if="selectedFundCode" :fundCode="selectedFundCode" />
|
||||
<div v-else class="welcome-container">
|
||||
<div class="welcome-icon">🔍</div>
|
||||
<h3>搜索基金开始分析</h3>
|
||||
<p>在上方搜索框输入基金代码或名称</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@@ -138,7 +122,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import FundSearch from './components/FundSearch.vue'
|
||||
import FundDetail from './components/FundDetail.vue'
|
||||
import FundWatchlist from './components/FundWatchlist.vue'
|
||||
@@ -167,8 +151,16 @@ export default {
|
||||
const currentTime = ref('')
|
||||
const viewMode = ref('dashboard') // 默认显示市场大盘
|
||||
const compareFunds = ref([]) // 用于对比的基金列表
|
||||
const compareMode = ref(false) // 是否处于对比模式
|
||||
|
||||
// 是否显示全宽内容(详情页或对比页时隐藏右侧栏)
|
||||
const showFullContent = computed(() => {
|
||||
return (compareMode.value && compareFunds.value.length >= 2) ||
|
||||
(selectedFundCode.value && !compareMode.value)
|
||||
})
|
||||
|
||||
const handleFundSelected = (fundOrCode) => {
|
||||
if (compareMode.value) return // 对比模式下不切换基金
|
||||
if (fundOrCode && typeof fundOrCode === 'object') {
|
||||
selectedFundCode.value = fundOrCode.CODE || fundOrCode.fund_code || fundOrCode.code
|
||||
} else {
|
||||
@@ -176,16 +168,31 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 从仪表盘点击基金,切换到详情模式
|
||||
const handleDashboardFundView = (fundOrCode) => {
|
||||
// 顶部搜索框选中基金
|
||||
const handleHeaderSearch = (fundOrCode) => {
|
||||
compareMode.value = false // 退出对比模式
|
||||
handleFundSelected(fundOrCode)
|
||||
viewMode.value = 'detail'
|
||||
}
|
||||
|
||||
// 从仪表盘/自选点击基金
|
||||
const handleDashboardFundView = (fundOrCode) => {
|
||||
if (compareMode.value) return // 对比模式下不切换
|
||||
handleFundSelected(fundOrCode)
|
||||
}
|
||||
|
||||
// 切换对比模式
|
||||
const toggleCompareMode = () => {
|
||||
compareMode.value = !compareMode.value
|
||||
if (!compareMode.value) {
|
||||
// 退出对比模式时清空对比列表
|
||||
compareFunds.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 从筛选页面查看基金详情
|
||||
const handleScreeningFundView = (fundCode) => {
|
||||
selectedFundCode.value = fundCode
|
||||
viewMode.value = 'detail'
|
||||
viewMode.value = 'dashboard'
|
||||
}
|
||||
|
||||
// 添加基金到对比列表
|
||||
@@ -217,6 +224,17 @@ export default {
|
||||
compareFunds.value = []
|
||||
}
|
||||
|
||||
// 重置到市场大盘(点击菜单栏"市场大盘"时)
|
||||
const resetToDashboard = () => {
|
||||
viewMode.value = 'dashboard'
|
||||
selectedFundCode.value = ''
|
||||
// 如果处于对比模式,也退出
|
||||
if (compareMode.value) {
|
||||
compareMode.value = false
|
||||
compareFunds.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 更新时间
|
||||
const updateTime = () => {
|
||||
const now = new Date()
|
||||
@@ -234,12 +252,17 @@ export default {
|
||||
currentTime,
|
||||
viewMode,
|
||||
compareFunds,
|
||||
compareMode,
|
||||
handleFundSelected,
|
||||
handleHeaderSearch,
|
||||
handleDashboardFundView,
|
||||
handleScreeningFundView,
|
||||
handleAddToCompare,
|
||||
handleRemoveFromCompare,
|
||||
handleClearCompare
|
||||
handleClearCompare,
|
||||
toggleCompareMode,
|
||||
showFullContent,
|
||||
resetToDashboard
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,6 +336,79 @@ export default {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* 顶部搜索框 */
|
||||
.header-search {
|
||||
flex: 1;
|
||||
max-width: 600px;
|
||||
margin: 0 40px;
|
||||
}
|
||||
|
||||
.header-search :deep(.fund-search) {
|
||||
margin-bottom: 0;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.header-search :deep(.search-header) {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.header-search :deep(.search-box) {
|
||||
min-width: 300px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.header-search :deep(.search-input) {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 2px solid transparent;
|
||||
height: 40px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.header-search :deep(.search-input:focus) {
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.header-search :deep(.search-btn) {
|
||||
background: linear-gradient(135deg, #ff9f43 0%, #f39c12 100%);
|
||||
height: 40px;
|
||||
padding: 0 24px;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
box-shadow: 0 2px 8px rgba(243, 156, 18, 0.35);
|
||||
}
|
||||
|
||||
.header-search :deep(.search-btn:hover) {
|
||||
background: linear-gradient(135deg, #ffb366 0%, #f5a623 100%);
|
||||
box-shadow: 0 4px 12px rgba(243, 156, 18, 0.45);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.header-search :deep(.refresh-btn) {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.header-search :deep(.refresh-btn:hover:not(:disabled)) {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.header-search :deep(.search-results) {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
margin-top: 4px;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -361,9 +457,14 @@ export default {
|
||||
/* ==================== 仪表盘布局 ==================== */
|
||||
.dashboard-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 320px 1fr 380px;
|
||||
grid-template-columns: 380px 1fr 380px;
|
||||
gap: 20px;
|
||||
min-height: calc(100vh - 140px);
|
||||
transition: grid-template-columns 0.3s ease;
|
||||
}
|
||||
|
||||
.dashboard-layout.full-content {
|
||||
grid-template-columns: 380px 1fr;
|
||||
}
|
||||
|
||||
.dashboard-sidebar {
|
||||
@@ -397,7 +498,7 @@ export default {
|
||||
}
|
||||
|
||||
.sidebar-left {
|
||||
width: 360px;
|
||||
width: 400px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -410,6 +511,15 @@ export default {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* ==================== 对比面板 ==================== */
|
||||
.compare-panel {
|
||||
margin-bottom: 20px;
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--bg-card);
|
||||
box-shadow: var(--shadow-md);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ==================== 欢迎页面 ==================== */
|
||||
.welcome-container {
|
||||
display: flex;
|
||||
@@ -456,9 +566,24 @@ export default {
|
||||
}
|
||||
|
||||
/* ==================== 响应式设计 ==================== */
|
||||
@media (max-width: 1600px) {
|
||||
.header-search {
|
||||
max-width: 400px;
|
||||
margin: 0 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1400px) {
|
||||
.dashboard-layout {
|
||||
grid-template-columns: 280px 1fr 340px;
|
||||
grid-template-columns: 340px 1fr 340px;
|
||||
}
|
||||
|
||||
.sidebar-left {
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.header-search {
|
||||
max-width: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,6 +595,15 @@ export default {
|
||||
.dashboard-sidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-left {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.header-search {
|
||||
max-width: 280px;
|
||||
margin: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
@@ -494,6 +628,13 @@ export default {
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.header-search {
|
||||
order: 3;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@@ -518,6 +659,10 @@ export default {
|
||||
.app-main {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.header-search :deep(.db-status) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 滚动条美化 ==================== */
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
<template>
|
||||
<div class="fund-comparison" v-if="selectedFunds.length > 0 || compareFunds.length > 0">
|
||||
<div class="fund-comparison" :class="{ 'compact-mode': compact }">
|
||||
<div class="comparison-header">
|
||||
<h2>
|
||||
<span class="header-icon">📈</span>
|
||||
基金对比
|
||||
<span class="count-badge" v-if="selectedFunds.length">{{ selectedFunds.length }}/{{ maxFunds }}</span>
|
||||
</h2>
|
||||
<div class="header-actions">
|
||||
<div class="header-actions" v-if="selectedFunds.length > 0">
|
||||
<button
|
||||
class="btn btn-clear"
|
||||
@click="clearSelection"
|
||||
:disabled="selectedFunds.length === 0"
|
||||
>
|
||||
清空对比
|
||||
清空
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<div v-if="selectedFunds.length === 0" class="empty-compare-hint">
|
||||
<span class="hint-icon">👆</span>
|
||||
<span>点击自选基金的 <strong>+</strong> 按钮添加对比</span>
|
||||
</div>
|
||||
|
||||
<!-- 基金选择区域 -->
|
||||
<div class="selection-area">
|
||||
<div class="selection-area" v-if="selectedFunds.length > 0">
|
||||
<div class="selection-tags">
|
||||
<div
|
||||
v-for="fund in selectedFunds"
|
||||
@@ -31,14 +37,14 @@
|
||||
<span class="tag-code">({{ fund.code }})</span>
|
||||
<button class="tag-remove" @click="removeFund(fund.code)">×</button>
|
||||
</div>
|
||||
<div v-if="selectedFunds.length < maxFunds && selectedFunds.length > 0" class="add-fund-hint">
|
||||
<span>👈 继续从左侧添加基金 (还可添加{{ maxFunds - selectedFunds.length }}只)</span>
|
||||
<div v-if="selectedFunds.length < maxFunds" class="add-fund-hint">
|
||||
<span>还可添加{{ maxFunds - selectedFunds.length }}只</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 对比内容区域 -->
|
||||
<div class="comparison-content" v-if="selectedFunds.length >= 2">
|
||||
<!-- 对比内容区域(紧凑模式下隐藏详细内容) -->
|
||||
<div class="comparison-content" v-if="selectedFunds.length >= 2 && !compact">
|
||||
<!-- 净值走势图表 -->
|
||||
<div class="chart-section">
|
||||
<div class="section-header">
|
||||
@@ -266,6 +272,10 @@ export default {
|
||||
compareFunds: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['remove-fund', 'clear-funds'],
|
||||
@@ -700,6 +710,60 @@ export default {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 紧凑模式样式 */
|
||||
.fund-comparison.compact-mode {
|
||||
margin-bottom: 0;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.fund-comparison.compact-mode .comparison-header {
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.fund-comparison.compact-mode .comparison-header h2 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.fund-comparison.compact-mode .selection-area {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.fund-comparison.compact-mode .fund-tag {
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.fund-comparison.compact-mode .tag-code {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fund-comparison.compact-mode .add-fund-hint {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* 空状态提示 */
|
||||
.empty-compare-hint {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
background: #f8fafc;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.empty-compare-hint .hint-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.fund-comparison.compact-mode .empty-compare-hint {
|
||||
padding: 10px 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.comparison-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
<template>
|
||||
<div class="fund-search">
|
||||
<div class="fund-search" :class="{ 'compact-mode': compact }">
|
||||
<div class="search-header">
|
||||
<div class="search-box">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
@input="handleSearch"
|
||||
@keyup.enter="performSearch"
|
||||
placeholder="输入基金代码或名称搜索..."
|
||||
:placeholder="compact ? '输入基金代码或名称搜索...' : '输入基金代码或名称搜索...'"
|
||||
class="search-input"
|
||||
/>
|
||||
<button @click="performSearch" class="search-btn">搜索</button>
|
||||
</div>
|
||||
<div class="db-status">
|
||||
<span v-if="dbStatus.has_cache" class="status-text">
|
||||
📊 {{ dbStatus.count }} 只基金 | 更新: {{ formatDate(dbStatus.last_update) }}
|
||||
</span>
|
||||
<span v-else class="status-text status-empty">
|
||||
⚠️ 暂无数据
|
||||
</span>
|
||||
<button
|
||||
@click="updateDatabase"
|
||||
:disabled="updating"
|
||||
class="update-btn"
|
||||
:title="updating ? '更新中...' : '更新基金数据库'"
|
||||
class="refresh-btn"
|
||||
:title="dbStatus.has_cache ? `${dbStatus.count}只基金 | 更新: ${formatDate(dbStatus.last_update)}` : '更新基金数据库'"
|
||||
>
|
||||
<span v-if="updating" class="spinner"></span>
|
||||
<span v-else>🔄</span>
|
||||
@@ -52,6 +44,12 @@ import { fundAPI } from '../services/api'
|
||||
|
||||
export default {
|
||||
name: 'FundSearch',
|
||||
props: {
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['fund-selected'],
|
||||
data() {
|
||||
return {
|
||||
@@ -151,6 +149,36 @@ export default {
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fund-search.compact-mode {
|
||||
margin-bottom: 0;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.fund-search.compact-mode .search-results {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.fund-search.compact-mode .loading {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
margin-top: 4px;
|
||||
background: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.search-header {
|
||||
@@ -162,9 +190,10 @@ export default {
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
min-width: 280px;
|
||||
min-width: 200px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
@@ -174,6 +203,7 @@ export default {
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
@@ -184,7 +214,7 @@ export default {
|
||||
|
||||
.search-btn {
|
||||
padding: 10px 20px;
|
||||
background: linear-gradient(135deg, #1677ff 0%, #0958d9 100%);
|
||||
background: linear-gradient(135deg, #ff9f43 0%, #f39c12 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
@@ -196,51 +226,30 @@ export default {
|
||||
|
||||
.search-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(22, 119, 255, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(243, 156, 18, 0.4);
|
||||
}
|
||||
|
||||
.db-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
background: #f9fafb;
|
||||
padding: 6px 12px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.status-empty {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.update-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
.refresh-btn {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border: none;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.update-btn:hover:not(:disabled) {
|
||||
background: #1677ff;
|
||||
color: white;
|
||||
.refresh-btn:hover:not(:disabled) {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.update-btn:disabled {
|
||||
.refresh-btn:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
<template>
|
||||
<div class="watchlist-container">
|
||||
<!-- 对比模式切换按钮 -->
|
||||
<div v-if="showCompareToggle" class="compare-toggle-bar">
|
||||
<button
|
||||
class="btn-compare-toggle"
|
||||
:class="{ active: compareMode }"
|
||||
@click="$emit('toggle-compare')"
|
||||
>
|
||||
<span class="toggle-icon">📈</span>
|
||||
<span>{{ compareMode ? '退出对比' : '基金对比' }}</span>
|
||||
<span v-if="compareFunds.length && compareMode" class="compare-count">{{ compareFunds.length }}</span>
|
||||
</button>
|
||||
<!-- 对比模式下显示已选基金 -->
|
||||
<div v-if="compareMode && compareFunds.length > 0" class="compare-selected">
|
||||
<div v-for="fund in compareFunds" :key="fund.code" class="compare-tag">
|
||||
<span class="tag-name">{{ fund.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="compareMode && compareFunds.length === 0" class="compare-hint">
|
||||
👆 点击下方基金的 <strong>+</strong> 按钮添加对比
|
||||
</div>
|
||||
<div v-if="compareMode && compareFunds.length === 1" class="compare-hint">
|
||||
还需选择至少 <strong>1</strong> 只基金才能对比
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 头部操作栏 -->
|
||||
<div class="watchlist-header">
|
||||
<h2>
|
||||
@@ -166,9 +191,10 @@ export default {
|
||||
components: { FundListItems },
|
||||
props: {
|
||||
compareMode: { type: Boolean, default: false },
|
||||
compareFunds: { type: Array, default: () => [] }
|
||||
compareFunds: { type: Array, default: () => [] },
|
||||
showCompareToggle: { type: Boolean, default: false }
|
||||
},
|
||||
emits: ['view-fund', 'add-to-compare'],
|
||||
emits: ['view-fund', 'add-to-compare', 'toggle-compare'],
|
||||
setup(props, { emit }) {
|
||||
const watchlist = ref([])
|
||||
const groups = ref([])
|
||||
@@ -585,6 +611,81 @@ export default {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 对比切换按钮区域 */
|
||||
.compare-toggle-bar {
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.btn-compare-toggle {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-compare-toggle:hover {
|
||||
border-color: #1677ff;
|
||||
color: #1677ff;
|
||||
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
|
||||
}
|
||||
|
||||
.btn-compare-toggle.active {
|
||||
border-color: #1677ff;
|
||||
background: linear-gradient(135deg, #1677ff 0%, #0958d9 100%);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(22, 119, 255, 0.3);
|
||||
}
|
||||
|
||||
.toggle-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.compare-count {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
padding: 2px 10px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.compare-selected {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.compare-tag {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 4px 10px;
|
||||
border-radius: 15px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.compare-hint {
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
padding: 8px;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 头部 */
|
||||
.watchlist-header {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user