Merge branch 'hongxilin/feature-20251023103318-行情数据及页面' into milestone-20251031-简版功能开发
zhaowenkang/feature-20251028181547-行情页面
-
70api/marketSituation/marketSituation.js
-
288components/IndexCard.vue
-
589pages/marketSituation/countryMarket.vue
-
842pages/marketSituation/globalIndex.vue
-
74pages/marketSituation/marketCondition.vue
-
697pages/marketSituation/marketDetail.vue
-
121pages/marketSituation/marketOverview.vue
-
844pages/marketSituation/marketSituation.vue
-
BINstatic/marketSituation-image/country-flag/can.png
-
BINstatic/marketSituation-image/country-flag/cn.png
-
BINstatic/marketSituation-image/country-flag/global.png
-
BINstatic/marketSituation-image/country-flag/hk.png
-
BINstatic/marketSituation-image/country-flag/my.png
-
BINstatic/marketSituation-image/country-flag/sg.png
-
BINstatic/marketSituation-image/country-flag/th.png
-
BINstatic/marketSituation-image/country-flag/us.png
-
BINstatic/marketSituation-image/country-flag/vi.png
-
78stores/modules/marketSituation.js
@ -0,0 +1,70 @@ |
|||||
|
/** @format */ |
||||
|
|
||||
|
import { http } from "../../utils/http"; |
||||
|
|
||||
|
export const getData = () => { |
||||
|
return http({ |
||||
|
method: "GET", |
||||
|
url: "/ka", |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* 获取全球指数 |
||||
|
* POST /api/global/getGlobalIndex |
||||
|
*/ |
||||
|
export const getGlobalIndexAPI = (data) => { |
||||
|
return http({ |
||||
|
method: "POST", |
||||
|
url: "/api/global/getGlobalIndex", |
||||
|
data, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* 获取地区分组列表 |
||||
|
* POST /api/global/regionalGroup |
||||
|
*/ |
||||
|
export const getRegionalGroupAPI = (data) => { |
||||
|
return http({ |
||||
|
method: "POST", |
||||
|
url: "/api/global/regionalGroup", |
||||
|
data, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* 获取地区详情 |
||||
|
* POST /api/global/regionalGroupList |
||||
|
*/ |
||||
|
export const getRegionalGroupListAPI = (data) => { |
||||
|
return http({ |
||||
|
method: "POST", |
||||
|
url: "/api/global/regionalGroupList", |
||||
|
data, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* 一次性查询所有Tab栏父子结构 |
||||
|
* POST /api/homework/tab/getAll |
||||
|
*/ |
||||
|
export const getAllTabsAPI = (data) => { |
||||
|
return http({ |
||||
|
method: "POST", |
||||
|
url: "/api/homework/tab/getAll", |
||||
|
data, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* 通用市场数据分页查询接口(默认1页20条) |
||||
|
* POST /api/market/data/page/query |
||||
|
*/ |
||||
|
export const queryStockDataAPI = (data) => { |
||||
|
return http({ |
||||
|
method: "POST", |
||||
|
url: "/api/market/data/page/query", |
||||
|
data, |
||||
|
}); |
||||
|
}; |
||||
@ -1,190 +1,220 @@ |
|||||
|
<!-- @format --> |
||||
|
|
||||
<template> |
<template> |
||||
<view class="index-card"> |
|
||||
<view class="card-header"> |
|
||||
<view class="flag-container"> |
|
||||
<image :src="flagIcon" class="flag-icon" mode="aspectFit"></image> |
|
||||
</view> |
|
||||
<text class="index-name">{{ stockName }}</text> |
|
||||
</view> |
|
||||
|
|
||||
<view class="price-info"> |
|
||||
<text class="current-price" :style="{ color: priceColor }">{{ currentPrice }}</text> |
|
||||
<view class="change-info"> |
|
||||
<text class="change-amount" :style="{ color: priceColor }">{{ changeAmount }}</text> |
|
||||
<text class="change-percent" :style="{ color: priceColor }">{{ changePercent }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<view class="chart-container"> |
|
||||
<view class="mini-chart" :style="{ backgroundColor: chartBgColor }"> |
|
||||
<!-- 这里可以放置实际的图表组件,目前用简单的波浪线表示 --> |
|
||||
<view class="chart-line" :style="{ borderColor: priceColor }"></view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
<view class="index-card"> |
||||
|
<view class="card-header"> |
||||
|
<view class="flag-container"> |
||||
|
<image :src="getMarketFlag(market)" class="flag-icon" mode="aspectFit"></image> |
||||
|
</view> |
||||
|
<text class="index-name">{{ stockName }}</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="price-info"> |
||||
|
<text class="current-price" :style="{ color: priceColor }">{{ currentPrice }}</text> |
||||
|
<view class="change-info"> |
||||
|
<text class="change-amount" :style="{ color: priceColor }">{{ changeAmount }}</text> |
||||
|
<text class="change-percent" :style="{ color: priceColor }">{{ changePercent }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="chart-container"> |
||||
|
<view class="mini-chart" :style="{ backgroundColor: chartBgColor }"> |
||||
|
<!-- 这里可以放置实际的图表组件,目前用简单的波浪线表示 --> |
||||
|
<view class="chart-line" :style="{ borderColor: priceColor }"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup> |
<script setup> |
||||
import { computed } from 'vue' |
|
||||
|
import { computed } from "vue"; |
||||
|
|
||||
// 定义组件属性 |
// 定义组件属性 |
||||
const props = defineProps({ |
const props = defineProps({ |
||||
// 国旗图标路径 |
|
||||
flagIcon: { |
|
||||
type: String, |
|
||||
required: true |
|
||||
}, |
|
||||
// 指数名称 |
|
||||
stockName: { |
|
||||
type: String, |
|
||||
required: true |
|
||||
}, |
|
||||
// 当前价格 |
|
||||
currentPrice: { |
|
||||
type: [String, Number], |
|
||||
required: true |
|
||||
}, |
|
||||
// 涨跌金额 |
|
||||
changeAmount: { |
|
||||
type: [String, Number], |
|
||||
required: true |
|
||||
}, |
|
||||
// 涨跌幅 |
|
||||
changePercent: { |
|
||||
type: [String, Number], |
|
||||
required: true |
|
||||
}, |
|
||||
// 是否上涨 |
|
||||
isRising: { |
|
||||
type: Boolean, |
|
||||
default: true |
|
||||
} |
|
||||
}) |
|
||||
|
// 国旗图标路径 |
||||
|
market: { |
||||
|
type: String, |
||||
|
required: true, |
||||
|
}, |
||||
|
// 指数名称 |
||||
|
stockName: { |
||||
|
type: String, |
||||
|
required: true, |
||||
|
}, |
||||
|
// 当前价格 |
||||
|
currentPrice: { |
||||
|
type: [String, Number], |
||||
|
required: true, |
||||
|
}, |
||||
|
// 涨跌金额 |
||||
|
changeAmount: { |
||||
|
type: [String, Number], |
||||
|
required: true, |
||||
|
}, |
||||
|
// 涨跌幅 |
||||
|
changePercent: { |
||||
|
type: [String, Number], |
||||
|
required: true, |
||||
|
}, |
||||
|
// 是否上涨 |
||||
|
isRising: { |
||||
|
type: Boolean, |
||||
|
default: true, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
const getMarketFlag = (market) => { |
||||
|
console.log("market", market); |
||||
|
let imagePath; |
||||
|
|
||||
|
if (market === "cn") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/cn.png"; |
||||
|
} else if (market === "hk") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/hk.png"; |
||||
|
} else if (market === "can") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/can.png"; |
||||
|
} else if (market === "my") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/my.png"; |
||||
|
} else if (market === "sg") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/sg.png"; |
||||
|
} else if (market === "th") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/th.png"; |
||||
|
} else if (market === "vi") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/vi.png"; |
||||
|
} else if (market === "us" || market === "usa") { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/us.png"; |
||||
|
} else { |
||||
|
imagePath = "/static/marketSituation-image/country-flag/global.png"; |
||||
|
} |
||||
|
|
||||
|
console.log("返回的图片路径:", imagePath); |
||||
|
return imagePath; |
||||
|
}; |
||||
|
|
||||
// 计算价格颜色 |
// 计算价格颜色 |
||||
const priceColor = computed(() => { |
const priceColor = computed(() => { |
||||
return props.isRising ? '#00C853' : '#FF1744' |
|
||||
}) |
|
||||
|
return props.isRising ? "#00C853" : "#FF1744"; |
||||
|
}); |
||||
|
|
||||
// 计算图表背景色 |
// 计算图表背景色 |
||||
const chartBgColor = computed(() => { |
const chartBgColor = computed(() => { |
||||
return props.isRising ? '#E8F5E8' : '#FFEBEE' |
|
||||
}) |
|
||||
|
return props.isRising ? "#E8F5E8" : "#FFEBEE"; |
||||
|
}); |
||||
</script> |
</script> |
||||
|
|
||||
<style scoped> |
<style scoped> |
||||
.index-card { |
.index-card { |
||||
background-color: #ffffff; |
|
||||
border-radius: 12rpx; |
|
||||
padding: 20rpx; |
|
||||
margin: 16rpx; |
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
|
||||
border: 1rpx solid #f0f0f0; |
|
||||
|
background-color: #ffffff; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 20rpx; |
||||
|
margin: 16rpx; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
|
border: 1rpx solid #f0f0f0; |
||||
} |
} |
||||
|
|
||||
.card-header { |
.card-header { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
margin-bottom: 16rpx; |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-bottom: 16rpx; |
||||
} |
} |
||||
|
|
||||
.flag-container { |
.flag-container { |
||||
width: 48rpx; |
|
||||
height: 32rpx; |
|
||||
margin-right: 12rpx; |
|
||||
border-radius: 4rpx; |
|
||||
overflow: hidden; |
|
||||
|
width: 48rpx; |
||||
|
height: 32rpx; |
||||
|
margin-right: 12rpx; |
||||
|
border-radius: 4rpx; |
||||
|
overflow: hidden; |
||||
} |
} |
||||
|
|
||||
.flag-icon { |
.flag-icon { |
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
} |
} |
||||
|
|
||||
.index-name { |
.index-name { |
||||
font-size: 28rpx; |
|
||||
font-weight: 500; |
|
||||
color: #333333; |
|
||||
flex: 1; |
|
||||
white-space: nowrap; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
|
font-size: 28rpx; |
||||
|
font-weight: 500; |
||||
|
color: #333333; |
||||
|
flex: 1; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
} |
} |
||||
|
|
||||
.price-info { |
.price-info { |
||||
margin-bottom: 20rpx; |
|
||||
|
margin-bottom: 20rpx; |
||||
} |
} |
||||
|
|
||||
.current-price { |
.current-price { |
||||
font-size: 36rpx; |
|
||||
font-weight: bold; |
|
||||
display: block; |
|
||||
margin-bottom: 8rpx; |
|
||||
|
font-size: 36rpx; |
||||
|
font-weight: bold; |
||||
|
display: block; |
||||
|
margin-bottom: 8rpx; |
||||
} |
} |
||||
|
|
||||
.change-info { |
.change-info { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
gap: 16rpx; |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 16rpx; |
||||
} |
} |
||||
|
|
||||
.change-amount { |
.change-amount { |
||||
font-size: 24rpx; |
|
||||
font-weight: 500; |
|
||||
|
font-size: 24rpx; |
||||
|
font-weight: 500; |
||||
} |
} |
||||
|
|
||||
.change-percent { |
.change-percent { |
||||
font-size: 24rpx; |
|
||||
font-weight: 500; |
|
||||
|
font-size: 24rpx; |
||||
|
font-weight: 500; |
||||
} |
} |
||||
|
|
||||
.chart-container { |
.chart-container { |
||||
height: 80rpx; |
|
||||
border-radius: 8rpx; |
|
||||
overflow: hidden; |
|
||||
|
height: 80rpx; |
||||
|
border-radius: 8rpx; |
||||
|
overflow: hidden; |
||||
} |
} |
||||
|
|
||||
.mini-chart { |
.mini-chart { |
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
position: relative; |
|
||||
border-radius: 8rpx; |
|
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
border-radius: 8rpx; |
||||
} |
} |
||||
|
|
||||
.chart-line { |
.chart-line { |
||||
position: absolute; |
|
||||
bottom: 20rpx; |
|
||||
left: 10rpx; |
|
||||
right: 10rpx; |
|
||||
height: 2rpx; |
|
||||
border-top: 2rpx solid; |
|
||||
border-style: solid; |
|
||||
|
position: absolute; |
||||
|
bottom: 20rpx; |
||||
|
left: 10rpx; |
||||
|
right: 10rpx; |
||||
|
height: 2rpx; |
||||
|
border-top: 2rpx solid; |
||||
|
border-style: solid; |
||||
} |
} |
||||
|
|
||||
/* 添加一些波浪效果 */ |
/* 添加一些波浪效果 */ |
||||
.chart-line::before { |
.chart-line::before { |
||||
content: ''; |
|
||||
position: absolute; |
|
||||
top: -10rpx; |
|
||||
left: 20%; |
|
||||
width: 20rpx; |
|
||||
height: 20rpx; |
|
||||
border: 2rpx solid; |
|
||||
border-color: inherit; |
|
||||
border-radius: 50%; |
|
||||
background: transparent; |
|
||||
|
content: ""; |
||||
|
position: absolute; |
||||
|
top: -10rpx; |
||||
|
left: 20%; |
||||
|
width: 20rpx; |
||||
|
height: 20rpx; |
||||
|
border: 2rpx solid; |
||||
|
border-color: inherit; |
||||
|
border-radius: 50%; |
||||
|
background: transparent; |
||||
} |
} |
||||
|
|
||||
.chart-line::after { |
.chart-line::after { |
||||
content: ''; |
|
||||
position: absolute; |
|
||||
top: -6rpx; |
|
||||
right: 30%; |
|
||||
width: 12rpx; |
|
||||
height: 12rpx; |
|
||||
border: 2rpx solid; |
|
||||
border-color: inherit; |
|
||||
border-radius: 50%; |
|
||||
background: transparent; |
|
||||
|
content: ""; |
||||
|
position: absolute; |
||||
|
top: -6rpx; |
||||
|
right: 30%; |
||||
|
width: 12rpx; |
||||
|
height: 12rpx; |
||||
|
border: 2rpx solid; |
||||
|
border-color: inherit; |
||||
|
border-radius: 50%; |
||||
|
background: transparent; |
||||
} |
} |
||||
</style> |
|
||||
|
</style> |
||||
@ -1,493 +1,498 @@ |
|||||
|
<!-- @format --> |
||||
|
|
||||
<template> |
<template> |
||||
<view class="content"> |
|
||||
<!-- 市场子Tab --> |
|
||||
<view class="sub_tabs"> |
|
||||
<view v-for="(tab, i) in marketTabs" :key="tab" :class="['tab_item', i === activeTabIndex ? 'active' : '']" |
|
||||
@click="switchTab(i)"> |
|
||||
<text>{{ tab }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 大盘指数 --> |
|
||||
<view class="section"> |
|
||||
<view class="section_header"> |
|
||||
<text class="section_title">大盘指数</text> |
|
||||
<text class="section_action" @click="viewMore('indices')">查看更多 ></text> |
|
||||
</view> |
|
||||
<view class="indices_grid"> |
|
||||
<view v-for="(index, i) in countryInfo.mainIndices" :key="i" class="index_item"> |
|
||||
<IndexCard :flagIcon="countryInfo.flag" :indexName="index.name" :currentPrice="index.price" |
|
||||
:changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" /> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 今日市场情绪温度 --> |
|
||||
<view class="sentiment"> |
|
||||
<view class="section_subtitle"> |
|
||||
<text>今日市场情绪温度</text> |
|
||||
</view> |
|
||||
<view class="meters"> |
|
||||
<view class="meter_item" v-for="(m, i) in sentimentMeters" :key="i"> |
|
||||
<image class="meter_icon" :class="m.theme" :src="selectIcons[m.theme]" mode="aspectFit"></image> |
|
||||
<view class="meter_info"> |
|
||||
<text class="meter_value" :class="m.theme">{{ m.value }}°C</text> |
|
||||
<text class="meter_label" :class="m.theme">{{ m.label }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 板块 --> |
|
||||
<view class="section"> |
|
||||
<view class="section_header"> |
|
||||
<text class="section_title">板块</text> |
|
||||
<text class="section_action" @click="viewMore('sectors')">查看更多 ></text> |
|
||||
</view> |
|
||||
<view class="sectors_grid"> |
|
||||
<view v-for="(sec, i) in sectors" :key="i" class="sector_item"> |
|
||||
<view class="sector_header"> |
|
||||
<text class="sector_name">{{ sec.name }}</text> |
|
||||
<text :class="['sector_change', sec.isRising ? 'rising' : 'falling']"> |
|
||||
{{ sec.change }} |
|
||||
</text> |
|
||||
</view> |
|
||||
<view class="sector_price">{{ sec.price }}</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 股票 --> |
|
||||
<view class="section"> |
|
||||
<view class="section_header"> |
|
||||
<text class="section_title">股票</text> |
|
||||
<text class="section_action" @click="viewMore('stocks')">查看更多 ></text> |
|
||||
</view> |
|
||||
<view class="table"> |
|
||||
<view class="table_header"> |
|
||||
<text class="cell name">名称</text> |
|
||||
<text class="cell price">最新</text> |
|
||||
<text class="cell change">涨幅</text> |
|
||||
</view> |
|
||||
<view class="table_row" v-for="(stk, i) in stocks" :key="i"> |
|
||||
<view class="cell name"> |
|
||||
<text class="stk_name">{{ stk.name }}</text> |
|
||||
<text class="stk_code">{{ stk.code }}</text> |
|
||||
</view> |
|
||||
<view class="cell price"> |
|
||||
<text class="stk_price">{{ stk.price }}</text> |
|
||||
</view> |
|
||||
<view class="cell change"> |
|
||||
<text :class="['stk_change', stk.isRising ? 'rising' : 'falling']"> |
|
||||
{{ stk.change }} |
|
||||
</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 底部安全区域 --> |
|
||||
<view class="bottom_safe_area"></view> |
|
||||
</view> |
|
||||
|
<view class="content"> |
||||
|
<!-- 市场子Tab --> |
||||
|
<view class="sub_tabs"> |
||||
|
<view v-for="(tab, i) in marketTabs" :key="tab" :class="['tab_item', i === activeTabIndex ? 'active' : '']" @click="switchTab(i)"> |
||||
|
<text>{{ tab }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 大盘指数 --> |
||||
|
<view class="section"> |
||||
|
<view class="section_header"> |
||||
|
<text class="section_title">大盘指数</text> |
||||
|
<text class="section_action" @click="viewMore('indices')">查看更多 ></text> |
||||
|
</view> |
||||
|
<view class="indices_grid"> |
||||
|
<view v-for="(index, i) in countryInfo.mainIndices" :key="i" class="index_item"> |
||||
|
<IndexCard :market="countryInfo.market" :indexName="index.name" :currentPrice="index.price" :changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 今日市场情绪温度 --> |
||||
|
<view class="sentiment"> |
||||
|
<view class="section_subtitle"> |
||||
|
<text>今日市场情绪温度</text> |
||||
|
</view> |
||||
|
<view class="meters"> |
||||
|
<view class="meter_item" v-for="(m, i) in sentimentMeters" :key="i"> |
||||
|
<image class="meter_icon" :class="m.theme" :src="selectIcons[m.theme]" mode="aspectFit"></image> |
||||
|
<view class="meter_info"> |
||||
|
<text class="meter_value" :class="m.theme">{{ m.value }}°C</text> |
||||
|
<text class="meter_label" :class="m.theme">{{ m.label }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 板块 --> |
||||
|
<view class="section"> |
||||
|
<view class="section_header"> |
||||
|
<text class="section_title">板块</text> |
||||
|
<text class="section_action" @click="viewMore('sectors')">查看更多 ></text> |
||||
|
</view> |
||||
|
<view class="sectors_grid"> |
||||
|
<view v-for="(sec, i) in sectors" :key="i" class="sector_item"> |
||||
|
<view class="sector_header"> |
||||
|
<text class="sector_name">{{ sec.name }}</text> |
||||
|
<text :class="['sector_change', sec.isRising ? 'rising' : 'falling']"> |
||||
|
{{ sec.change }} |
||||
|
</text> |
||||
|
</view> |
||||
|
<view class="sector_price">{{ sec.price }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 股票 --> |
||||
|
<view class="section"> |
||||
|
<view class="section_header"> |
||||
|
<text class="section_title">股票</text> |
||||
|
<text class="section_action" @click="viewMore('stocks')">查看更多 ></text> |
||||
|
</view> |
||||
|
<view class="table"> |
||||
|
<view class="table_header"> |
||||
|
<text class="cell name">名称</text> |
||||
|
<text class="cell price">最新</text> |
||||
|
<text class="cell change">涨幅</text> |
||||
|
</view> |
||||
|
<view class="table_row" v-for="(stk, i) in stocks" :key="i"> |
||||
|
<view class="cell name"> |
||||
|
<text class="stk_name">{{ stk.name }}</text> |
||||
|
<text class="stk_code">{{ stk.code }}</text> |
||||
|
</view> |
||||
|
<view class="cell price"> |
||||
|
<text class="stk_price">{{ stk.price }}</text> |
||||
|
</view> |
||||
|
<view class="cell change"> |
||||
|
<text :class="['stk_change', stk.isRising ? 'rising' : 'falling']"> |
||||
|
{{ stk.change }} |
||||
|
</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部安全区域 --> |
||||
|
<view class="bottom_safe_area"></view> |
||||
|
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup> |
<script setup> |
||||
import { ref, computed, onMounted } from 'vue' |
|
||||
import IndexCard from '../../components/IndexCard.vue' |
|
||||
|
import { ref, computed, onMounted } from "vue"; |
||||
|
import IndexCard from "../../components/IndexCard.vue"; |
||||
|
|
||||
// 子Tab与操作 |
// 子Tab与操作 |
||||
const marketTabs = ['全部', '美股', '纽交所', '纳斯达克'] |
|
||||
const activeTabIndex = ref(0) |
|
||||
|
// const marketTabs = ["全部", "美股", "纽交所", "纳斯达克"]; |
||||
|
const activeTabIndex = ref(0); |
||||
const switchTab = (i) => { |
const switchTab = (i) => { |
||||
activeTabIndex.value = i |
|
||||
} |
|
||||
|
activeTabIndex.value = i; |
||||
|
}; |
||||
|
|
||||
// 今日情绪温度示例数据 |
// 今日情绪温度示例数据 |
||||
const sentimentMeters = [ |
const sentimentMeters = [ |
||||
{ value: 90, label: '道琼斯', theme: 'hot' }, |
|
||||
{ value: 60, label: '纳斯达克', theme: 'warm' }, |
|
||||
{ value: 20, label: '标普500', theme: 'cool' } |
|
||||
] |
|
||||
|
{ value: 90, label: "道琼斯", theme: "hot" }, |
||||
|
{ value: 60, label: "纳斯达克", theme: "warm" }, |
||||
|
{ value: 20, label: "标普500", theme: "cool" }, |
||||
|
]; |
||||
|
|
||||
// 图标映射 |
// 图标映射 |
||||
const selectIcons = { |
const selectIcons = { |
||||
hot: '/static/marketSituation-image/hot.png', |
|
||||
warm: '/static/marketSituation-image/warm.png', |
|
||||
cool: '/static/marketSituation-image/cool.png' |
|
||||
} |
|
||||
|
hot: "/static/marketSituation-image/hot.png", |
||||
|
warm: "/static/marketSituation-image/warm.png", |
||||
|
cool: "/static/marketSituation-image/cool.png", |
||||
|
}; |
||||
|
|
||||
// Props |
// Props |
||||
const props = defineProps({ |
const props = defineProps({ |
||||
countryId: { |
|
||||
type: Number, |
|
||||
required: true |
|
||||
} |
|
||||
}) |
|
||||
|
countryId: { |
||||
|
type: Number, |
||||
|
required: true, |
||||
|
}, |
||||
|
marketTabs: { |
||||
|
type: Array, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
// 国家/地区信息映射 |
// 国家/地区信息映射 |
||||
const countryInfoMap = { |
const countryInfoMap = { |
||||
2: { // 新加坡 |
|
||||
name: '新加坡', |
|
||||
flag: '🇸🇬', |
|
||||
isMarketOpen: true, |
|
||||
mainIndices: [ |
|
||||
{ name: '海峡时报指数', price: '3,234.56', change: '+12.34', changePercent: '+0.38%', isRising: true }, |
|
||||
{ name: 'FTSE ST Mid Cap', price: '1,234.56', change: '-5.67', changePercent: '-0.46%', isRising: false } |
|
||||
], |
|
||||
hotStocks: [ |
|
||||
{ name: '星展银行', code: 'D05.SI', price: '35.20', change: '+0.15', isRising: true }, |
|
||||
{ name: '华侨银行', code: 'O39.SI', price: '13.45', change: '-0.05', isRising: false } |
|
||||
] |
|
||||
}, |
|
||||
3: { // 马来西亚 |
|
||||
name: '马来西亚', |
|
||||
flag: '🇲🇾', |
|
||||
isMarketOpen: false, |
|
||||
mainIndices: [ |
|
||||
{ name: '富时大马KLCI指数', price: '1,567.89', change: '+8.90', changePercent: '+0.57%', isRising: true } |
|
||||
], |
|
||||
hotStocks: [ |
|
||||
{ name: '马来亚银行', code: '1155.KL', price: '9.85', change: '+0.10', isRising: true }, |
|
||||
{ name: '大众银行', code: '1295.KL', price: '4.32', change: '-0.02', isRising: false } |
|
||||
] |
|
||||
}, |
|
||||
4: { // 印度尼西亚 |
|
||||
name: '印度尼西亚', |
|
||||
flag: '🇮🇩', |
|
||||
isMarketOpen: true, |
|
||||
mainIndices: [ |
|
||||
{ name: '雅加达综合指数', price: '7,234.56', change: '+45.67', changePercent: '+0.63%', isRising: true } |
|
||||
], |
|
||||
hotStocks: [] |
|
||||
}, |
|
||||
5: { // 美国 |
|
||||
name: '美国', |
|
||||
flag: '🇺🇸', |
|
||||
isMarketOpen: false, |
|
||||
mainIndices: [ |
|
||||
{ name: '道琼斯', price: '45,757.90', change: '-125.22', changePercent: '-0.27%', isRising: false }, |
|
||||
{ name: '纳斯达克', price: '22,333.96', change: '+125.22', changePercent: '+0.47%', isRising: true }, |
|
||||
{ name: '标普500', price: '6,606.08', change: '+125.22', changePercent: '+0.27%', isRising: true } |
|
||||
], |
|
||||
hotStocks: [ |
|
||||
{ name: '苹果', code: 'AAPL', price: '195.89', change: '+2.34', isRising: true }, |
|
||||
{ name: '微软', code: 'MSFT', price: '378.85', change: '-1.23', isRising: false } |
|
||||
] |
|
||||
} |
|
||||
} |
|
||||
|
2: { |
||||
|
// 新加坡 |
||||
|
name: "新加坡", |
||||
|
flag: "🇸🇬", |
||||
|
isMarketOpen: true, |
||||
|
mainIndices: [ |
||||
|
{ name: "海峡时报指数", price: "3,234.56", change: "+12.34", changePercent: "+0.38%", isRising: true }, |
||||
|
{ name: "FTSE ST Mid Cap", price: "1,234.56", change: "-5.67", changePercent: "-0.46%", isRising: false }, |
||||
|
], |
||||
|
hotStocks: [ |
||||
|
{ name: "星展银行", code: "D05.SI", price: "35.20", change: "+0.15", isRising: true }, |
||||
|
{ name: "华侨银行", code: "O39.SI", price: "13.45", change: "-0.05", isRising: false }, |
||||
|
], |
||||
|
}, |
||||
|
3: { |
||||
|
// 马来西亚 |
||||
|
name: "马来西亚", |
||||
|
flag: "🇲🇾", |
||||
|
isMarketOpen: false, |
||||
|
mainIndices: [{ name: "富时大马KLCI指数", price: "1,567.89", change: "+8.90", changePercent: "+0.57%", isRising: true }], |
||||
|
hotStocks: [ |
||||
|
{ name: "马来亚银行", code: "1155.KL", price: "9.85", change: "+0.10", isRising: true }, |
||||
|
{ name: "大众银行", code: "1295.KL", price: "4.32", change: "-0.02", isRising: false }, |
||||
|
], |
||||
|
}, |
||||
|
4: { |
||||
|
// 印度尼西亚 |
||||
|
name: "印度尼西亚", |
||||
|
flag: "🇮🇩", |
||||
|
isMarketOpen: true, |
||||
|
mainIndices: [{ name: "雅加达综合指数", price: "7,234.56", change: "+45.67", changePercent: "+0.63%", isRising: true }], |
||||
|
hotStocks: [], |
||||
|
}, |
||||
|
5: { |
||||
|
// 美国 |
||||
|
name: "美国", |
||||
|
flag: "🇺🇸", |
||||
|
isMarketOpen: false, |
||||
|
mainIndices: [ |
||||
|
{ name: "道琼斯", price: "45,757.90", change: "-125.22", changePercent: "-0.27%", isRising: false }, |
||||
|
{ name: "纳斯达克", price: "22,333.96", change: "+125.22", changePercent: "+0.47%", isRising: true }, |
||||
|
{ name: "标普500", price: "6,606.08", change: "+125.22", changePercent: "+0.27%", isRising: true }, |
||||
|
], |
||||
|
hotStocks: [ |
||||
|
{ name: "苹果", code: "AAPL", price: "195.89", change: "+2.34", isRising: true }, |
||||
|
{ name: "微软", code: "MSFT", price: "378.85", change: "-1.23", isRising: false }, |
||||
|
], |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
// 计算当前国家信息 |
// 计算当前国家信息 |
||||
const countryInfo = computed(() => { |
const countryInfo = computed(() => { |
||||
return countryInfoMap[props.countryId] || { |
|
||||
name: '未知地区', |
|
||||
flag: '🌍', |
|
||||
isMarketOpen: false, |
|
||||
mainIndices: [], |
|
||||
hotStocks: [] |
|
||||
} |
|
||||
}) |
|
||||
|
return ( |
||||
|
countryInfoMap[props.countryId] || { |
||||
|
name: "未知地区", |
||||
|
flag: "🌍", |
||||
|
isMarketOpen: false, |
||||
|
mainIndices: [], |
||||
|
hotStocks: [], |
||||
|
} |
||||
|
); |
||||
|
}); |
||||
|
|
||||
// 计算当前国家的板块与股票 |
// 计算当前国家的板块与股票 |
||||
const sectors = computed(() => { |
const sectors = computed(() => { |
||||
return countryInfoMap[props.countryId]?.sectors || [] |
|
||||
}) |
|
||||
|
return countryInfoMap[props.countryId]?.sectors || []; |
||||
|
}); |
||||
const stocks = computed(() => { |
const stocks = computed(() => { |
||||
return countryInfoMap[props.countryId]?.stocks || [] |
|
||||
}) |
|
||||
|
return countryInfoMap[props.countryId]?.stocks || []; |
||||
|
}); |
||||
|
|
||||
// 查看更多占位 |
// 查看更多占位 |
||||
const viewMore = (type) => { |
const viewMore = (type) => { |
||||
// 可根据 type 跳转到相应页面或加载更多 |
|
||||
// 例如:indices/sectors/stocks |
|
||||
// uni.navigateTo({ url: `/pages/marketSituation/${type}List` }) |
|
||||
} |
|
||||
|
// 可根据 type 跳转到相应页面或加载更多 |
||||
|
// 例如:indices/sectors/stocks |
||||
|
// uni.navigateTo({ url: `/pages/marketSituation/${type}List` }) |
||||
|
}; |
||||
</script> |
</script> |
||||
|
|
||||
<style scoped> |
<style scoped> |
||||
.content { |
.content { |
||||
padding: 0 20rpx 20rpx 20rpx; |
|
||||
|
padding: 0 20rpx 20rpx 20rpx; |
||||
} |
} |
||||
|
|
||||
/* 子Tab */ |
/* 子Tab */ |
||||
.sub_tabs { |
.sub_tabs { |
||||
display: flex; |
|
||||
gap: 16rpx; |
|
||||
padding: 0 20rpx 20rpx 20rpx; |
|
||||
|
display: flex; |
||||
|
gap: 16rpx; |
||||
|
padding: 0 20rpx 20rpx 20rpx; |
||||
} |
} |
||||
|
|
||||
.tab_item { |
.tab_item { |
||||
padding: 6rpx 20rpx; |
|
||||
border-radius: 5rpx; |
|
||||
background: #f5f5f5; |
|
||||
color: #666; |
|
||||
font-size: 24rpx; |
|
||||
|
padding: 6rpx 20rpx; |
||||
|
border-radius: 5rpx; |
||||
|
background: #f5f5f5; |
||||
|
color: #666; |
||||
|
font-size: 24rpx; |
||||
} |
} |
||||
|
|
||||
.tab_item.active { |
.tab_item.active { |
||||
background: #ff4444; |
|
||||
color: #fff; |
|
||||
|
background: #ff4444; |
||||
|
color: #fff; |
||||
} |
} |
||||
|
|
||||
.section { |
.section { |
||||
padding: 20rpx; |
|
||||
border-radius: 16rpx; |
|
||||
|
padding: 20rpx; |
||||
|
border-radius: 16rpx; |
||||
} |
} |
||||
|
|
||||
.section_header { |
.section_header { |
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
margin-bottom: 16rpx; |
|
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 16rpx; |
||||
} |
} |
||||
|
|
||||
.section_title { |
.section_title { |
||||
font-size: 28rpx; |
|
||||
font-weight: bold; |
|
||||
color: #333; |
|
||||
|
font-size: 28rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
} |
} |
||||
|
|
||||
.section_action { |
.section_action { |
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
} |
} |
||||
|
|
||||
.indices_grid { |
.indices_grid { |
||||
padding: 20rpx; |
|
||||
display: grid; |
|
||||
grid-template-columns: repeat(3, 1fr); |
|
||||
gap: 20rpx; |
|
||||
background-color: #F6F6F6; |
|
||||
|
padding: 20rpx; |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
|
gap: 20rpx; |
||||
|
background-color: #f6f6f6; |
||||
} |
} |
||||
|
|
||||
/* 情绪温度 */ |
/* 情绪温度 */ |
||||
.sentiment { |
.sentiment { |
||||
background-color: #F6F6F6; |
|
||||
padding: 0 20rpx 20rpx 20rpx; |
|
||||
|
background-color: #f6f6f6; |
||||
|
padding: 0 20rpx 20rpx 20rpx; |
||||
} |
} |
||||
|
|
||||
.section_subtitle { |
.section_subtitle { |
||||
font-size: 24rpx; |
|
||||
color: #000000; |
|
||||
padding: 20rpx 0; |
|
||||
|
font-size: 24rpx; |
||||
|
color: #000000; |
||||
|
padding: 20rpx 0; |
||||
} |
} |
||||
|
|
||||
.meters { |
.meters { |
||||
display: grid; |
|
||||
grid-template-columns: repeat(3, 1fr); |
|
||||
gap: 16rpx; |
|
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
|
gap: 16rpx; |
||||
} |
} |
||||
|
|
||||
.meter_item { |
.meter_item { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
/* padding: 10rpx; */ |
|
||||
background: #ffffff; |
|
||||
border-radius: 12rpx; |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
/* padding: 10rpx; */ |
||||
|
background: #ffffff; |
||||
|
border-radius: 12rpx; |
||||
} |
} |
||||
|
|
||||
.meter_item image { |
.meter_item image { |
||||
width: 100rpx; |
|
||||
height: 100rpx; |
|
||||
|
width: 100rpx; |
||||
|
height: 100rpx; |
||||
} |
} |
||||
|
|
||||
.meter_info { |
.meter_info { |
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
} |
} |
||||
|
|
||||
.meter_value { |
.meter_value { |
||||
font-size: 36rpx; |
|
||||
|
font-size: 36rpx; |
||||
} |
} |
||||
|
|
||||
.meter_value.hot { |
.meter_value.hot { |
||||
color: #ff6b6b; |
|
||||
|
color: #ff6b6b; |
||||
} |
} |
||||
|
|
||||
.meter_value.warm { |
.meter_value.warm { |
||||
color: #ffd166; |
|
||||
|
color: #ffd166; |
||||
} |
} |
||||
|
|
||||
.meter_value.cool { |
.meter_value.cool { |
||||
color: #60a5fa; |
|
||||
|
color: #60a5fa; |
||||
} |
} |
||||
|
|
||||
.meter_label { |
.meter_label { |
||||
font-size: 22rpx; |
|
||||
|
font-size: 22rpx; |
||||
} |
} |
||||
|
|
||||
.meter_label.hot { |
.meter_label.hot { |
||||
color: #ff6b6b; |
|
||||
|
color: #ff6b6b; |
||||
} |
} |
||||
|
|
||||
.meter_label.warm { |
.meter_label.warm { |
||||
color: #ffd166; |
|
||||
|
color: #ffd166; |
||||
} |
} |
||||
|
|
||||
.meter_label.cool { |
.meter_label.cool { |
||||
color: #60a5fa; |
|
||||
|
color: #60a5fa; |
||||
} |
} |
||||
|
|
||||
/* 板块 */ |
/* 板块 */ |
||||
.sectors_grid { |
.sectors_grid { |
||||
display: grid; |
|
||||
grid-template-columns: repeat(3, 1fr); |
|
||||
gap: 16rpx; |
|
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
|
gap: 16rpx; |
||||
} |
} |
||||
|
|
||||
.sector_item { |
.sector_item { |
||||
background: #fafafa; |
|
||||
border-radius: 12rpx; |
|
||||
padding: 16rpx; |
|
||||
|
background: #fafafa; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 16rpx; |
||||
} |
} |
||||
|
|
||||
.sector_header { |
.sector_header { |
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
margin-bottom: 12rpx; |
|
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 12rpx; |
||||
} |
} |
||||
|
|
||||
.sector_name { |
.sector_name { |
||||
font-size: 24rpx; |
|
||||
color: #333; |
|
||||
|
font-size: 24rpx; |
||||
|
color: #333; |
||||
} |
} |
||||
|
|
||||
.sector_change { |
.sector_change { |
||||
font-size: 22rpx; |
|
||||
|
font-size: 22rpx; |
||||
} |
} |
||||
|
|
||||
.sector_change.rising { |
.sector_change.rising { |
||||
color: #e74c3c; |
|
||||
|
color: #e74c3c; |
||||
} |
} |
||||
|
|
||||
.sector_change.falling { |
.sector_change.falling { |
||||
color: #27ae60; |
|
||||
|
color: #27ae60; |
||||
} |
} |
||||
|
|
||||
.sector_price { |
.sector_price { |
||||
font-size: 24rpx; |
|
||||
color: #666; |
|
||||
|
font-size: 24rpx; |
||||
|
color: #666; |
||||
} |
} |
||||
|
|
||||
/* 股票表 */ |
/* 股票表 */ |
||||
.table { |
.table { |
||||
background: #fff; |
|
||||
border-radius: 12rpx; |
|
||||
overflow: hidden; |
|
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
} |
} |
||||
|
|
||||
.table_header, |
.table_header, |
||||
.table_row { |
.table_row { |
||||
display: grid; |
|
||||
grid-template-columns: 2fr 1fr 1fr; |
|
||||
padding: 18rpx 20rpx; |
|
||||
border-bottom: 1rpx solid #f0f0f0; |
|
||||
|
display: grid; |
||||
|
grid-template-columns: 2fr 1fr 1fr; |
||||
|
padding: 18rpx 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
} |
} |
||||
|
|
||||
.table_header { |
.table_header { |
||||
background: #fafafa; |
|
||||
|
background: #fafafa; |
||||
} |
} |
||||
|
|
||||
.cell.name { |
.cell.name { |
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
} |
} |
||||
|
|
||||
.stk_name { |
.stk_name { |
||||
font-size: 26rpx; |
|
||||
color: #333; |
|
||||
|
font-size: 26rpx; |
||||
|
color: #333; |
||||
} |
} |
||||
|
|
||||
.stk_code { |
.stk_code { |
||||
font-size: 22rpx; |
|
||||
color: #999; |
|
||||
|
font-size: 22rpx; |
||||
|
color: #999; |
||||
} |
} |
||||
|
|
||||
.stk_price { |
.stk_price { |
||||
font-size: 26rpx; |
|
||||
color: #333; |
|
||||
|
font-size: 26rpx; |
||||
|
color: #333; |
||||
} |
} |
||||
|
|
||||
.stk_change { |
.stk_change { |
||||
font-size: 24rpx; |
|
||||
|
font-size: 24rpx; |
||||
} |
} |
||||
|
|
||||
.stk_change.rising { |
.stk_change.rising { |
||||
color: #e74c3c; |
|
||||
|
color: #e74c3c; |
||||
} |
} |
||||
|
|
||||
.stk_change.falling { |
.stk_change.falling { |
||||
color: #27ae60; |
|
||||
|
color: #27ae60; |
||||
} |
} |
||||
|
|
||||
.index_item { |
.index_item { |
||||
background: #fff; |
|
||||
border-radius: 12rpx; |
|
||||
overflow: hidden; |
|
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
} |
} |
||||
|
|
||||
.hot_stocks { |
.hot_stocks { |
||||
margin-bottom: 30rpx; |
|
||||
|
margin-bottom: 30rpx; |
||||
} |
} |
||||
|
|
||||
.stocks_list { |
.stocks_list { |
||||
background: #fff; |
|
||||
border-radius: 12rpx; |
|
||||
overflow: hidden; |
|
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
} |
} |
||||
|
|
||||
.stock_item { |
.stock_item { |
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
padding: 24rpx 20rpx; |
|
||||
border-bottom: 1rpx solid #f0f0f0; |
|
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 24rpx 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
} |
} |
||||
|
|
||||
.stock_item:last-child { |
.stock_item:last-child { |
||||
border-bottom: none; |
|
||||
|
border-bottom: none; |
||||
} |
} |
||||
|
|
||||
.stock_info { |
.stock_info { |
||||
flex: 1; |
|
||||
|
flex: 1; |
||||
} |
} |
||||
|
|
||||
.stock_name { |
.stock_name { |
||||
font-size: 28rpx; |
|
||||
color: #333; |
|
||||
display: block; |
|
||||
margin-bottom: 8rpx; |
|
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
display: block; |
||||
|
margin-bottom: 8rpx; |
||||
} |
} |
||||
|
|
||||
.stock_code { |
.stock_code { |
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
} |
} |
||||
|
|
||||
.stock_price { |
.stock_price { |
||||
text-align: right; |
|
||||
|
text-align: right; |
||||
} |
} |
||||
|
|
||||
.price { |
.price { |
||||
font-size: 28rpx; |
|
||||
color: #333; |
|
||||
display: block; |
|
||||
margin-bottom: 8rpx; |
|
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
display: block; |
||||
|
margin-bottom: 8rpx; |
||||
} |
} |
||||
|
|
||||
.change { |
.change { |
||||
font-size: 24rpx; |
|
||||
|
font-size: 24rpx; |
||||
} |
} |
||||
|
|
||||
.change.rising { |
.change.rising { |
||||
color: #e74c3c; |
|
||||
|
color: #e74c3c; |
||||
} |
} |
||||
|
|
||||
.change.falling { |
.change.falling { |
||||
color: #27ae60; |
|
||||
|
color: #27ae60; |
||||
} |
} |
||||
|
|
||||
.bottom_safe_area { |
.bottom_safe_area { |
||||
height: 120rpx; |
|
||||
|
height: 120rpx; |
||||
} |
} |
||||
</style> |
|
||||
|
</style> |
||||
@ -1,586 +1,566 @@ |
|||||
|
<!-- @format --> |
||||
|
|
||||
<template> |
<template> |
||||
<view class="main"> |
|
||||
<!-- 固定头部 --> |
|
||||
<view class="header_fixed" :style="{ top: iSMT + 'px' }"> |
|
||||
<view class="header_content"> |
|
||||
<view class="header_back" @click="goBack"> |
|
||||
<image src="/static/marketSituation-image/back.png" mode=""></image> |
|
||||
</view> |
|
||||
<view class="header_input_wrapper"> |
|
||||
<image class="search_icon" src="/static/marketSituation-image/search.png" mode="" |
|
||||
@click="onSearchClick"></image> |
|
||||
<input class="header_input" type="text" placeholder="搜索" |
|
||||
placeholder-style="color: #A6A6A6; font-size: 22rpx;" v-model="searchValue" |
|
||||
@input="onSearchInput" @confirm="onSearchConfirm" /> |
|
||||
</view> |
|
||||
<view class="header_icons"> |
|
||||
<view class="header_icon" @click="selected"> |
|
||||
<image src="/static/marketSituation-image/mySeclected.png" mode=""></image> |
|
||||
</view> |
|
||||
<view class="header_icon" @click="history"> |
|
||||
<image src="/static/marketSituation-image/history.png" mode=""></image> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="warn"> |
|
||||
<image src="/static/marketSituation-image/warn.png" mode="aspectFit"></image> |
|
||||
<view class="warn_text_container"> |
|
||||
<text :class="warnTextClass">{{ $t('marketSituation.warn') }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
<view class="main"> |
||||
|
<!-- 固定头部 --> |
||||
|
<view class="header_fixed" :style="{ top: iSMT + 'px' }"> |
||||
|
<view class="header_content"> |
||||
|
<view class="header_back" @click="goBack"> |
||||
|
<image src="/static/marketSituation-image/back.png" mode=""></image> |
||||
</view> |
</view> |
||||
|
|
||||
<!-- 内容区域 --> |
|
||||
<scroll-view class="content" :style="{ top: contentTopPosition + 'px' }" scroll-y="true"> |
|
||||
<!-- 亚太-中华 --> |
|
||||
<view class="market-section"> |
|
||||
<view class="market-header"> |
|
||||
<text class="market-title">亚太-中华</text> |
|
||||
<view class="market-more" @click="viewMore('asia-china')"> |
|
||||
<text class="more-text">查看更多</text> |
|
||||
<text class="more-arrow">></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="cards-grid-three"> |
|
||||
<view v-for="(item, index) in asiachinaIndexes" :key="index" class="card-item"> |
|
||||
<IndexCard :flagIcon="item.flagIcon" :stockName="item.stockName" |
|
||||
:currentPrice="item.currentPrice" :changeAmount="item.changeAmount" |
|
||||
:changePercent="item.changePercent" :isRising="item.isRising" |
|
||||
@click="viewIndexDetail(item)" /> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 亚太 --> |
|
||||
<view class="market-section"> |
|
||||
<view class="market-header"> |
|
||||
<text class="market-title">亚太</text> |
|
||||
<view class="market-more" @click="viewMore('asia')"> |
|
||||
<text class="more-text">查看更多</text> |
|
||||
<text class="more-arrow">></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="cards-grid-three"> |
|
||||
<view v-for="(item, index) in asiaIndexes" :key="index" class="card-item"> |
|
||||
<IndexCard :flagIcon="item.flagIcon" :stockName="item.stockName" |
|
||||
:currentPrice="item.currentPrice" :changeAmount="item.changeAmount" |
|
||||
:changePercent="item.changePercent" :isRising="item.isRising" |
|
||||
@click="viewIndexDetail(item)" /> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 美洲 --> |
|
||||
<view class="market-section"> |
|
||||
<view class="market-header"> |
|
||||
<text class="market-title">美洲</text> |
|
||||
<view class="market-more" @click="viewMore('america')"> |
|
||||
<text class="more-text">查看更多</text> |
|
||||
<text class="more-arrow">></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="cards-grid-three"> |
|
||||
<view v-for="(item, index) in americaIndexes" :key="index" class="card-item"> |
|
||||
<IndexCard :flagIcon="item.flagIcon" :stockName="item.stockName" |
|
||||
:currentPrice="item.currentPrice" :changeAmount="item.changeAmount" |
|
||||
:changePercent="item.changePercent" :isRising="item.isRising" |
|
||||
@click="viewIndexDetail(item)" /> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 底部安全区域 --> |
|
||||
<view class="bottom-safe-area"></view> |
|
||||
</scroll-view> |
|
||||
|
<view class="header_input_wrapper"> |
||||
|
<image class="search_icon" src="/static/marketSituation-image/search.png" mode="" @click="onSearchClick"></image> |
||||
|
<input class="header_input" type="text" placeholder="搜索" placeholder-style="color: #A6A6A6; font-size: 22rpx;" v-model="searchValue" @input="onSearchInput" @confirm="onSearchConfirm" /> |
||||
|
</view> |
||||
|
<view class="header_icons"> |
||||
|
<view class="header_icon" @click="selected"> |
||||
|
<image src="/static/marketSituation-image/mySeclected.png" mode=""></image> |
||||
|
</view> |
||||
|
<view class="header_icon" @click="history"> |
||||
|
<image src="/static/marketSituation-image/history.png" mode=""></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="warn"> |
||||
|
<image src="/static/marketSituation-image/warn.png" mode="aspectFit"></image> |
||||
|
<view class="warn_text_container"> |
||||
|
<text :class="warnTextClass">{{ $t("marketSituation.warn") }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
</view> |
</view> |
||||
|
|
||||
<!-- 底部导航栏 --> |
|
||||
<footerBar class="static-footer" :type="'marketSituation'"></footerBar> |
|
||||
|
<!-- 内容区域 --> |
||||
|
<scroll-view class="content" :style="{ top: contentTopPosition + 'px' }" scroll-y="true"> |
||||
|
<!-- 亚太-中华 --> |
||||
|
<view class="market-section" v-for="item in globalIndexArray" :key="item"> |
||||
|
<view class="market-header"> |
||||
|
<text class="market-title">{{ item.ac }}</text> |
||||
|
<view class="market-more" @click="viewMore(item.ac)"> |
||||
|
<text class="more-text">查看更多</text> |
||||
|
<text class="more-arrow">></text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="cards-grid-three"> |
||||
|
<view v-for="iitem in item.list" :key="iitem" class="card-item"> |
||||
|
<IndexCard |
||||
|
:market="iitem.market" |
||||
|
:stockName="iitem.name" |
||||
|
:currentPrice="iitem.currentPrice" |
||||
|
:changeAmount="iitem.changeAmount" |
||||
|
:changePercent="iitem.changePercent" |
||||
|
:isRising="iitem.isRising" |
||||
|
@click="viewIndexDetail(iitem)" |
||||
|
/> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部安全区域 --> |
||||
|
<view class="bottom-safe-area"></view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部导航栏 --> |
||||
|
<footerBar class="static-footer" :type="'marketSituation'"></footerBar> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup> |
<script setup> |
||||
import { ref, onMounted, computed, nextTick, watch } from 'vue' |
|
||||
import footerBar from '../../components/footerBar.vue' |
|
||||
import IndexCard from '../../components/IndexCard.vue' |
|
||||
|
import { ref, onMounted, computed, nextTick, watch } from "vue"; |
||||
|
import footerBar from "../../components/footerBar.vue"; |
||||
|
import IndexCard from "../../components/IndexCard.vue"; |
||||
|
import { getRegionalGroupAPI } from "../../api/marketSituation/marketSituation.js"; |
||||
|
|
||||
// 响应式数据 |
// 响应式数据 |
||||
const iSMT = ref(0) // 状态栏高度 |
|
||||
const contentHeight = ref(0) |
|
||||
const headerHeight = ref(0) // 头部高度 |
|
||||
const searchValue = ref('') // 搜索值 |
|
||||
const isWarnTextOverflow = ref(false) // warn文字是否溢出 |
|
||||
|
const iSMT = ref(0); // 状态栏高度 |
||||
|
const contentHeight = ref(0); |
||||
|
const headerHeight = ref(0); // 头部高度 |
||||
|
const searchValue = ref(""); // 搜索值 |
||||
|
const isWarnTextOverflow = ref(false); // warn文字是否溢出 |
||||
|
|
||||
// warn文字的class计算属性 |
// warn文字的class计算属性 |
||||
const warnTextClass = computed(() => { |
const warnTextClass = computed(() => { |
||||
return isWarnTextOverflow.value ? 'warn_text scroll-active' : 'warn_text' |
|
||||
}) |
|
||||
|
return isWarnTextOverflow.value ? "warn_text scroll-active" : "warn_text"; |
||||
|
}); |
||||
|
|
||||
// 检测warn文字是否溢出 |
// 检测warn文字是否溢出 |
||||
const checkWarnTextOverflow = () => { |
const checkWarnTextOverflow = () => { |
||||
nextTick(() => { |
|
||||
setTimeout(() => { |
|
||||
const query = uni.createSelectorQuery() |
|
||||
|
|
||||
// 同时查询容器和文字元素 |
|
||||
query.select('.warn_text_container').boundingClientRect() |
|
||||
query.select('.warn_text').boundingClientRect() |
|
||||
query.exec((res) => { |
|
||||
const containerRect = res[0] |
|
||||
const textRect = res[1] |
|
||||
|
|
||||
if (!containerRect || !textRect) { |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
// 判断文字是否超出容器(留一些余量) |
|
||||
const isOverflow = textRect.width > (containerRect.width - 10) |
|
||||
|
|
||||
isWarnTextOverflow.value = isOverflow |
|
||||
}) |
|
||||
}, 500) |
|
||||
}) |
|
||||
} |
|
||||
|
nextTick(() => { |
||||
|
setTimeout(() => { |
||||
|
const query = uni.createSelectorQuery(); |
||||
|
|
||||
|
// 同时查询容器和文字元素 |
||||
|
query.select(".warn_text_container").boundingClientRect(); |
||||
|
query.select(".warn_text").boundingClientRect(); |
||||
|
query.exec((res) => { |
||||
|
const containerRect = res[0]; |
||||
|
const textRect = res[1]; |
||||
|
|
||||
|
if (!containerRect || !textRect) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 判断文字是否超出容器(留一些余量) |
||||
|
const isOverflow = textRect.width > containerRect.width - 10; |
||||
|
|
||||
|
isWarnTextOverflow.value = isOverflow; |
||||
|
}); |
||||
|
}, 500); |
||||
|
}); |
||||
|
}; |
||||
|
const globalIndexArray = ref([]); |
||||
// 亚太-中华指数数据 |
// 亚太-中华指数数据 |
||||
const asiachinaIndexes = ref([ |
const asiachinaIndexes = ref([ |
||||
{ |
|
||||
flagIcon: '/static/c1.png', |
|
||||
stockName: '上证指数', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '3933.96', |
|
||||
changeAmount: '+24.32', |
|
||||
changePercent: '+0.62%', |
|
||||
isRising: true |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c2.png', |
|
||||
stockName: '深证成指', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '45757.90', |
|
||||
changeAmount: '-123.45', |
|
||||
changePercent: '-0.27%', |
|
||||
isRising: false |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c3.png', |
|
||||
stockName: '创业板指', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '6606.08', |
|
||||
changeAmount: '+89.76', |
|
||||
changePercent: '+1.38%', |
|
||||
isRising: true |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c4.png', |
|
||||
stockName: 'HSI50', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '22333.96', |
|
||||
changeAmount: '+156.78', |
|
||||
changePercent: '+0.71%', |
|
||||
isRising: true |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c5.png', |
|
||||
stockName: '沪深300', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '45757.90', |
|
||||
changeAmount: '-89.12', |
|
||||
changePercent: '-0.19%', |
|
||||
isRising: false |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c6.png', |
|
||||
stockName: '上证50', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '45757.90', |
|
||||
changeAmount: '+234.56', |
|
||||
changePercent: '+0.52%', |
|
||||
isRising: true |
|
||||
} |
|
||||
]) |
|
||||
|
{ |
||||
|
flagIcon: "/static/c1.png", |
||||
|
stockName: "上证指数", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "3933.96", |
||||
|
changeAmount: "+24.32", |
||||
|
changePercent: "+0.62%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c2.png", |
||||
|
stockName: "深证成指", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "45757.90", |
||||
|
changeAmount: "-123.45", |
||||
|
changePercent: "-0.27%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c3.png", |
||||
|
stockName: "创业板指", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "6606.08", |
||||
|
changeAmount: "+89.76", |
||||
|
changePercent: "+1.38%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c4.png", |
||||
|
stockName: "HSI50", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "22333.96", |
||||
|
changeAmount: "+156.78", |
||||
|
changePercent: "+0.71%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c5.png", |
||||
|
stockName: "沪深300", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "45757.90", |
||||
|
changeAmount: "-89.12", |
||||
|
changePercent: "-0.19%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c6.png", |
||||
|
stockName: "上证50", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "45757.90", |
||||
|
changeAmount: "+234.56", |
||||
|
changePercent: "+0.52%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
// 亚太指数数据 |
// 亚太指数数据 |
||||
const asiaIndexes = ref([ |
const asiaIndexes = ref([ |
||||
{ |
|
||||
flagIcon: '/static/c7.png', |
|
||||
stockName: '日经225', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '28456.78', |
|
||||
changeAmount: '+234.56', |
|
||||
changePercent: '+0.83%', |
|
||||
isRising: true |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c8.png', |
|
||||
stockName: '韩国KOSPI', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '2567.89', |
|
||||
changeAmount: '-12.34', |
|
||||
changePercent: '-0.48%', |
|
||||
isRising: false |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c9.png', |
|
||||
stockName: '印度孟买', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '65432.10', |
|
||||
changeAmount: '+456.78', |
|
||||
changePercent: '+0.70%', |
|
||||
isRising: true |
|
||||
} |
|
||||
]) |
|
||||
|
{ |
||||
|
flagIcon: "/static/c7.png", |
||||
|
stockName: "日经225", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "28456.78", |
||||
|
changeAmount: "+234.56", |
||||
|
changePercent: "+0.83%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c8.png", |
||||
|
stockName: "韩国KOSPI", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "2567.89", |
||||
|
changeAmount: "-12.34", |
||||
|
changePercent: "-0.48%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c9.png", |
||||
|
stockName: "印度孟买", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "65432.10", |
||||
|
changeAmount: "+456.78", |
||||
|
changePercent: "+0.70%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
// 美洲指数数据 |
// 美洲指数数据 |
||||
const americaIndexes = ref([ |
const americaIndexes = ref([ |
||||
{ |
|
||||
flagIcon: '/static/c7.png', |
|
||||
stockName: '道琼斯指数', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '34567.89', |
|
||||
changeAmount: '+123.45', |
|
||||
changePercent: '+0.36%', |
|
||||
isRising: true |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c8.png', |
|
||||
stockName: '纳斯达克', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '13456.78', |
|
||||
changeAmount: '-67.89', |
|
||||
changePercent: '-0.50%', |
|
||||
isRising: false |
|
||||
}, |
|
||||
{ |
|
||||
flagIcon: '/static/c9.png', |
|
||||
stockName: '标普500', |
|
||||
stockCode:'noCode', |
|
||||
currentPrice: '4234.56', |
|
||||
changeAmount: '+23.45', |
|
||||
changePercent: '+0.56%', |
|
||||
isRising: true |
|
||||
} |
|
||||
]) |
|
||||
|
{ |
||||
|
flagIcon: "/static/c7.png", |
||||
|
stockName: "道琼斯指数", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "34567.89", |
||||
|
changeAmount: "+123.45", |
||||
|
changePercent: "+0.36%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c8.png", |
||||
|
stockName: "纳斯达克", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "13456.78", |
||||
|
changeAmount: "-67.89", |
||||
|
changePercent: "-0.50%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "/static/c9.png", |
||||
|
stockName: "标普500", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "4234.56", |
||||
|
changeAmount: "+23.45", |
||||
|
changePercent: "+0.56%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
// 计算属性:内容区域顶部位置 |
// 计算属性:内容区域顶部位置 |
||||
const contentTopPosition = computed(() => { |
const contentTopPosition = computed(() => { |
||||
const statusBarHeight = iSMT.value || 0 |
|
||||
const currentHeaderHeight = headerHeight.value > 0 ? headerHeight.value : 100 |
|
||||
return statusBarHeight + currentHeaderHeight |
|
||||
}) |
|
||||
|
const statusBarHeight = iSMT.value || 0; |
||||
|
const currentHeaderHeight = headerHeight.value > 0 ? headerHeight.value : 100; |
||||
|
return statusBarHeight + currentHeaderHeight; |
||||
|
}); |
||||
|
|
||||
// 方法:返回上一页 |
// 方法:返回上一页 |
||||
const goBack = () => { |
const goBack = () => { |
||||
uni.navigateBack() |
|
||||
} |
|
||||
|
uni.navigateBack(); |
||||
|
}; |
||||
|
|
||||
// 方法:搜索输入 |
// 方法:搜索输入 |
||||
const onSearchInput = (e) => { |
const onSearchInput = (e) => { |
||||
searchValue.value = e.detail.value |
|
||||
} |
|
||||
|
searchValue.value = e.detail.value; |
||||
|
}; |
||||
|
|
||||
// 方法:清除搜索 |
// 方法:清除搜索 |
||||
const clearSearch = () => { |
const clearSearch = () => { |
||||
searchValue.value = '' |
|
||||
} |
|
||||
|
searchValue.value = ""; |
||||
|
}; |
||||
|
|
||||
// 方法:查看更多 |
// 方法:查看更多 |
||||
const viewMore = (market) => { |
const viewMore = (market) => { |
||||
console.log('查看更多:', market) |
|
||||
uni.navigateTo({ |
|
||||
url: `/pages/marketSituation/marketDetail?market=${market}` |
|
||||
}) |
|
||||
} |
|
||||
|
console.log("查看更多:", market); |
||||
|
uni.navigateTo({ |
||||
|
url: `/pages/marketSituation/marketDetail?market=${market}`, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
// 方法:查看指数详情 |
// 方法:查看指数详情 |
||||
const viewIndexDetail = (item) => { |
const viewIndexDetail = (item) => { |
||||
console.log('查看指数详情:', item.stockName) |
|
||||
// uni.showToast({ |
|
||||
// title: `查看 ${item.stockName} 详情`, |
|
||||
// icon: 'none', |
|
||||
// duration: 2000 |
|
||||
// }) |
|
||||
// 这里可以跳转到具体的指数详情页面 |
|
||||
uni.navigateTo({ |
|
||||
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}` |
|
||||
}) |
|
||||
} |
|
||||
|
console.log("查看指数详情:", item.stockName); |
||||
|
// uni.showToast({ |
||||
|
// title: `查看 ${item.stockName} 详情`, |
||||
|
// icon: 'none', |
||||
|
// duration: 2000 |
||||
|
// }) |
||||
|
// 这里可以跳转到具体的指数详情页面 |
||||
|
uni.navigateTo({ |
||||
|
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}`, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const getRegionalGroup = async () => { |
||||
|
try { |
||||
|
const result = await getRegionalGroupAPI(); |
||||
|
globalIndexArray.value = result.data; |
||||
|
} catch (e) { |
||||
|
console.log("获取区域指数失败", e); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
// 生命周期:页面挂载 |
// 生命周期:页面挂载 |
||||
onMounted(() => { |
|
||||
// 获取系统信息 |
|
||||
const systemInfo = uni.getSystemInfoSync() |
|
||||
iSMT.value = systemInfo.statusBarHeight || 0 |
|
||||
|
|
||||
console.log('全球指数页面加载完成') |
|
||||
// 动态计算header实际高度 |
|
||||
uni.createSelectorQuery().select('.header_fixed').boundingClientRect((rect) => { |
|
||||
if (rect) { |
|
||||
headerHeight.value = rect.height |
|
||||
console.log('Header实际高度:', headerHeight.value, 'px') |
|
||||
} |
|
||||
}).exec() |
|
||||
// 检测warn文字是否溢出 |
|
||||
checkWarnTextOverflow() |
|
||||
}) |
|
||||
|
onMounted(async () => { |
||||
|
await getRegionalGroup(); |
||||
|
// 获取系统信息 |
||||
|
const systemInfo = uni.getSystemInfoSync(); |
||||
|
iSMT.value = systemInfo.statusBarHeight || 0; |
||||
|
|
||||
|
console.log("全球指数页面加载完成"); |
||||
|
// 动态计算header实际高度 |
||||
|
uni |
||||
|
.createSelectorQuery() |
||||
|
.select(".header_fixed") |
||||
|
.boundingClientRect((rect) => { |
||||
|
if (rect) { |
||||
|
headerHeight.value = rect.height; |
||||
|
console.log("Header实际高度:", headerHeight.value, "px"); |
||||
|
} |
||||
|
}) |
||||
|
.exec(); |
||||
|
// 检测warn文字是否溢出 |
||||
|
checkWarnTextOverflow(); |
||||
|
}); |
||||
|
|
||||
// 监听headerHeight变化,重新计算contentHeight |
// 监听headerHeight变化,重新计算contentHeight |
||||
watch(headerHeight, (newHeight) => { |
watch(headerHeight, (newHeight) => { |
||||
if (newHeight > 0) { |
|
||||
const systemInfo = uni.getSystemInfoSync() |
|
||||
const windowHeight = systemInfo.windowHeight |
|
||||
const statusBarHeight = systemInfo.statusBarHeight || 0 |
|
||||
const footerHeight = 100 |
|
||||
|
|
||||
contentHeight.value = windowHeight - statusBarHeight - newHeight - footerHeight |
|
||||
console.log('重新计算contentHeight:', contentHeight.value) |
|
||||
} |
|
||||
}) |
|
||||
|
if (newHeight > 0) { |
||||
|
const systemInfo = uni.getSystemInfoSync(); |
||||
|
const windowHeight = systemInfo.windowHeight; |
||||
|
const statusBarHeight = systemInfo.statusBarHeight || 0; |
||||
|
const footerHeight = 100; |
||||
|
|
||||
|
contentHeight.value = windowHeight - statusBarHeight - newHeight - footerHeight; |
||||
|
console.log("重新计算contentHeight:", contentHeight.value); |
||||
|
} |
||||
|
}); |
||||
</script> |
</script> |
||||
|
|
||||
<style lang="scss" scoped> |
<style lang="scss" scoped> |
||||
.main { |
.main { |
||||
position: relative; |
|
||||
height: 100vh; |
|
||||
overflow: hidden; |
|
||||
background-color: #f5f5f5; |
|
||||
|
position: relative; |
||||
|
height: 100vh; |
||||
|
overflow: hidden; |
||||
|
background-color: #f5f5f5; |
||||
} |
} |
||||
|
|
||||
/* 状态栏占位 */ |
/* 状态栏占位 */ |
||||
.top { |
.top { |
||||
position: fixed; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
z-index: 1001; |
|
||||
background-color: #ffffff; |
|
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
z-index: 1001; |
||||
|
background-color: #ffffff; |
||||
} |
} |
||||
|
|
||||
/* 固定头部样式 */ |
/* 固定头部样式 */ |
||||
.header_fixed { |
.header_fixed { |
||||
position: fixed; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
z-index: 1000; |
|
||||
background-color: #ffffff; |
|
||||
padding: 20rpx 0 0 0; |
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
|
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
z-index: 1000; |
||||
|
background-color: #ffffff; |
||||
|
padding: 20rpx 0 0 0; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
} |
} |
||||
|
|
||||
.header_content { |
.header_content { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
height: 80rpx; |
|
||||
padding: 0 20rpx; |
|
||||
margin-bottom: 10rpx; |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
height: 80rpx; |
||||
|
padding: 0 20rpx; |
||||
|
margin-bottom: 10rpx; |
||||
} |
} |
||||
|
|
||||
.header_back { |
.header_back { |
||||
margin-right: 20rpx; |
|
||||
width: 25rpx; |
|
||||
height: 30rpx; |
|
||||
|
margin-right: 20rpx; |
||||
|
width: 25rpx; |
||||
|
height: 30rpx; |
||||
} |
} |
||||
|
|
||||
.header_back image { |
.header_back image { |
||||
width: 25rpx; |
|
||||
height: 30rpx; |
|
||||
|
width: 25rpx; |
||||
|
height: 30rpx; |
||||
} |
} |
||||
|
|
||||
.header_input_wrapper { |
.header_input_wrapper { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
width: 100%; |
|
||||
margin: 0 20rpx 0 0; |
|
||||
height: 70rpx; |
|
||||
border-radius: 35rpx; |
|
||||
background-color: #ffffff; |
|
||||
border: 1rpx solid #e9ecef; |
|
||||
padding: 0 80rpx 0 30rpx; |
|
||||
font-size: 28rpx; |
|
||||
color: #5c5c5c; |
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
width: 100%; |
||||
|
margin: 0 20rpx 0 0; |
||||
|
height: 70rpx; |
||||
|
border-radius: 35rpx; |
||||
|
background-color: #ffffff; |
||||
|
border: 1rpx solid #e9ecef; |
||||
|
padding: 0 80rpx 0 30rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #5c5c5c; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
} |
} |
||||
|
|
||||
.search_icon { |
.search_icon { |
||||
width: 40rpx; |
|
||||
height: 40rpx; |
|
||||
opacity: 0.6; |
|
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
opacity: 0.6; |
||||
} |
} |
||||
|
|
||||
.header_input { |
.header_input { |
||||
margin-left: 10rpx; |
|
||||
|
margin-left: 10rpx; |
||||
} |
} |
||||
|
|
||||
.header_icons { |
.header_icons { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
gap: 15rpx; |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 15rpx; |
||||
} |
} |
||||
|
|
||||
.header_icon { |
.header_icon { |
||||
width: 40rpx; |
|
||||
height: 40rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
} |
} |
||||
|
|
||||
.header_icon image { |
.header_icon image { |
||||
width: 40rpx; |
|
||||
height: 40rpx; |
|
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
} |
} |
||||
|
|
||||
|
|
||||
.warn { |
.warn { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: flex-start; |
|
||||
gap: 10rpx; |
|
||||
font-size: 28rpx; |
|
||||
color: #666666; |
|
||||
padding: 20rpx; |
|
||||
max-width: 100%; |
|
||||
overflow: hidden; |
|
||||
position: relative; |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: flex-start; |
||||
|
gap: 10rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #666666; |
||||
|
padding: 20rpx; |
||||
|
max-width: 100%; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
} |
} |
||||
|
|
||||
.warn image { |
.warn image { |
||||
width: 40rpx; |
|
||||
height: 40rpx; |
|
||||
flex-shrink: 0; |
|
||||
/* 防止图片被压缩 */ |
|
||||
position: relative; |
|
||||
z-index: 2; |
|
||||
/* 确保图片在最上层 */ |
|
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
flex-shrink: 0; |
||||
|
/* 防止图片被压缩 */ |
||||
|
position: relative; |
||||
|
z-index: 2; |
||||
|
/* 确保图片在最上层 */ |
||||
} |
} |
||||
|
|
||||
.warn_text_container { |
.warn_text_container { |
||||
flex: 1; |
|
||||
overflow: hidden; |
|
||||
position: relative; |
|
||||
min-width: 0; |
|
||||
/* 允许容器收缩 */ |
|
||||
|
flex: 1; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
min-width: 0; |
||||
|
/* 允许容器收缩 */ |
||||
} |
} |
||||
|
|
||||
.warn_text { |
.warn_text { |
||||
display: block; |
|
||||
white-space: nowrap; |
|
||||
will-change: transform; |
|
||||
/* 优化动画性能 */ |
|
||||
|
display: block; |
||||
|
white-space: nowrap; |
||||
|
will-change: transform; |
||||
|
/* 优化动画性能 */ |
||||
} |
} |
||||
|
|
||||
/* 文字滚动动画 */ |
/* 文字滚动动画 */ |
||||
@keyframes scrollText { |
@keyframes scrollText { |
||||
0% { |
|
||||
transform: translateX(0); |
|
||||
} |
|
||||
|
0% { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
|
||||
20% { |
|
||||
transform: translateX(0); |
|
||||
} |
|
||||
|
20% { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
|
||||
80% { |
|
||||
transform: translateX(-85%); |
|
||||
} |
|
||||
|
80% { |
||||
|
transform: translateX(-85%); |
||||
|
} |
||||
|
|
||||
100% { |
|
||||
transform: translateX(-85%); |
|
||||
} |
|
||||
|
100% { |
||||
|
transform: translateX(-85%); |
||||
|
} |
||||
} |
} |
||||
|
|
||||
/* 当文字超长时启用滚动动画 */ |
/* 当文字超长时启用滚动动画 */ |
||||
.warn_text.scroll-active { |
.warn_text.scroll-active { |
||||
animation: scrollText 12s linear infinite; |
|
||||
animation-delay: 2s; |
|
||||
/* 延迟2秒开始滚动,让用户先看到开头 */ |
|
||||
|
animation: scrollText 12s linear infinite; |
||||
|
animation-delay: 2s; |
||||
|
/* 延迟2秒开始滚动,让用户先看到开头 */ |
||||
} |
} |
||||
|
|
||||
/* 内容区域 */ |
/* 内容区域 */ |
||||
.content { |
.content { |
||||
position: fixed; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
bottom: 120rpx; |
|
||||
background-color: #f5f5f5; |
|
||||
padding: 0; |
|
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 120rpx; |
||||
|
background-color: #f5f5f5; |
||||
|
padding: 0; |
||||
} |
} |
||||
|
|
||||
/* 市场分组 */ |
/* 市场分组 */ |
||||
.market-section { |
.market-section { |
||||
background-color: white; |
|
||||
border-radius: 20rpx; |
|
||||
|
background-color: white; |
||||
|
border-radius: 20rpx; |
||||
} |
} |
||||
|
|
||||
.market-header { |
.market-header { |
||||
margin: 20rpx 20rpx 0 20rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
margin-bottom: 10rpx; |
|
||||
padding-bottom: 10rpx; |
|
||||
border-bottom: 2rpx solid #f0f0f0; |
|
||||
|
margin: 20rpx 20rpx 0 20rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
margin-bottom: 10rpx; |
||||
|
padding-bottom: 10rpx; |
||||
|
border-bottom: 2rpx solid #f0f0f0; |
||||
} |
} |
||||
|
|
||||
.market-title { |
.market-title { |
||||
font-size: 32rpx; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
|
font-size: 32rpx; |
||||
|
font-weight: 600; |
||||
|
color: #333; |
||||
} |
} |
||||
|
|
||||
.market-more { |
.market-more { |
||||
display: flex; |
|
||||
align-items: center; |
|
||||
gap: 8rpx; |
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 8rpx; |
||||
} |
} |
||||
|
|
||||
.more-text { |
.more-text { |
||||
font-size: 24rpx; |
|
||||
color: #666; |
|
||||
|
font-size: 24rpx; |
||||
|
color: #666; |
||||
} |
} |
||||
|
|
||||
.more-arrow { |
.more-arrow { |
||||
font-size: 20rpx; |
|
||||
color: #666; |
|
||||
font-weight: bold; |
|
||||
|
font-size: 20rpx; |
||||
|
color: #666; |
||||
|
font-weight: bold; |
||||
} |
} |
||||
|
|
||||
/* 三列卡片网格 */ |
/* 三列卡片网格 */ |
||||
.cards-grid-three { |
.cards-grid-three { |
||||
display: grid; |
|
||||
grid-template-columns: repeat(3, 1fr); |
|
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
} |
} |
||||
|
|
||||
.card-item { |
.card-item { |
||||
background-color: white; |
|
||||
border-radius: 16rpx; |
|
||||
overflow: hidden; |
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease; |
|
||||
|
background-color: white; |
||||
|
border-radius: 16rpx; |
||||
|
overflow: hidden; |
||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease; |
||||
} |
} |
||||
|
|
||||
.card-item:active { |
.card-item:active { |
||||
transform: scale(0.98); |
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.12); |
|
||||
|
transform: scale(0.98); |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.12); |
||||
} |
} |
||||
|
|
||||
/* 底部安全区域 */ |
/* 底部安全区域 */ |
||||
.bottom-safe-area { |
.bottom-safe-area { |
||||
height: 40rpx; |
|
||||
background-color: transparent; |
|
||||
|
height: 40rpx; |
||||
|
background-color: transparent; |
||||
} |
} |
||||
|
|
||||
/* 底部导航栏 */ |
/* 底部导航栏 */ |
||||
.static-footer { |
.static-footer { |
||||
position: fixed; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
z-index: 1000; |
|
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
z-index: 1000; |
||||
} |
} |
||||
|
|
||||
/* 响应式设计 */ |
/* 响应式设计 */ |
||||
@media (max-width: 400rpx) { |
@media (max-width: 400rpx) { |
||||
.cards-grid-three { |
|
||||
grid-template-columns: repeat(2, 1fr); |
|
||||
} |
|
||||
|
.cards-grid-three { |
||||
|
grid-template-columns: repeat(2, 1fr); |
||||
|
} |
||||
} |
} |
||||
</style> |
|
||||
|
</style> |
||||
844
pages/marketSituation/marketSituation.vue
File diff suppressed because it is too large
View File
|
After Width: 32 | Height: 32 | Size: 1.1 KiB |
|
After Width: 32 | Height: 32 | Size: 1.1 KiB |
|
After Width: 32 | Height: 32 | Size: 2.5 KiB |
|
After Width: 32 | Height: 32 | Size: 1.7 KiB |
|
After Width: 32 | Height: 32 | Size: 1.7 KiB |
|
After Width: 32 | Height: 32 | Size: 1.1 KiB |
|
After Width: 32 | Height: 32 | Size: 703 B |
|
After Width: 32 | Height: 32 | Size: 1.4 KiB |
|
After Width: 32 | Height: 32 | Size: 1.1 KiB |
@ -0,0 +1,78 @@ |
|||||
|
/** @format */ |
||||
|
|
||||
|
import { defineStore } from "pinia"; |
||||
|
import { ref } from "vue"; |
||||
|
// 定义 Store
|
||||
|
export const useMarketSituationStore = defineStore( |
||||
|
"marketSituation", |
||||
|
() => { |
||||
|
const cardData = ref([ |
||||
|
{ |
||||
|
market: "usa", |
||||
|
stockName: "道琼斯", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "45757.90", |
||||
|
changeAmount: "-125.22", |
||||
|
changePercent: "-0.27%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
market: "usa", |
||||
|
stockName: "纳斯达克", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "22333.96", |
||||
|
changeAmount: "+125.22", |
||||
|
changePercent: "+0.47%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
market: "usa", |
||||
|
stockName: "标普500", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "6606.08", |
||||
|
changeAmount: "+125.22", |
||||
|
changePercent: "+0.27%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
market: "cn", |
||||
|
stockName: "上证指数", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "3333.96", |
||||
|
changeAmount: "+125.22", |
||||
|
changePercent: "+0.27%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
market: "cn", |
||||
|
stockName: "科创50", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "757.90", |
||||
|
changeAmount: "-25.22", |
||||
|
changePercent: "-0.27%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
|
// 记得 return
|
||||
|
return { |
||||
|
cardData |
||||
|
}; |
||||
|
}, |
||||
|
// TODO: 持久化
|
||||
|
{ |
||||
|
// 网页端持久化
|
||||
|
// persist: true,
|
||||
|
// 小程序端持久化
|
||||
|
persist: { |
||||
|
storage: { |
||||
|
getItem(key) { |
||||
|
return uni.getStorageSync(key); |
||||
|
}, |
||||
|
setItem(key, value) { |
||||
|
uni.setStorageSync(key, value); |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
} |
||||
|
); |
||||