You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
4.9 KiB
232 lines
4.9 KiB
<!-- @format -->
|
|
|
|
<template>
|
|
<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>
|
|
|
|
<script setup>
|
|
import { computed } from "vue";
|
|
|
|
// 定义组件属性
|
|
const props = defineProps({
|
|
// 国旗图标路径
|
|
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 judgeSymbol = (num) => {
|
|
// 兼容 undefined/null/数字/字符串
|
|
if (num === null || num === undefined) return '';
|
|
const n = Number(num);
|
|
if (!isNaN(n)) {
|
|
// 数值:正数加'+',负数原样
|
|
return (n < 0 ? '' : '+') + n;
|
|
}
|
|
// 字符串:去空格后判断前缀
|
|
const s = String(num).trim();
|
|
if (s.startsWith('-')) return s;
|
|
if (s.startsWith('+')) return s;
|
|
return '+' + s;
|
|
};
|
|
|
|
const getMarketFlag = (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";
|
|
}
|
|
return imagePath;
|
|
};
|
|
|
|
// 计算价格颜色
|
|
const priceColor = computed(() => {
|
|
return props.isRising ? "#00C853" : "#FF1744";
|
|
});
|
|
|
|
// 计算图表背景色
|
|
const chartBgColor = computed(() => {
|
|
return props.isRising ? "#E8F5E8" : "#FFEBEE";
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.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;
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
|
|
.flag-container {
|
|
width: 48rpx;
|
|
height: 32rpx;
|
|
margin-right: 12rpx;
|
|
border-radius: 4rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.flag-icon {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.index-name {
|
|
font-size: 28rpx;
|
|
font-weight: 500;
|
|
color: #333333;
|
|
flex: 1;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.price-info {
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.current-price {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
display: block;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.change-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.change-amount {
|
|
font-size: 24rpx;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.change-percent {
|
|
font-size: 24rpx;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.chart-container {
|
|
height: 80rpx;
|
|
border-radius: 8rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.mini-chart {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
border-radius: 8rpx;
|
|
}
|
|
|
|
.chart-line {
|
|
position: absolute;
|
|
bottom: 20rpx;
|
|
left: 10rpx;
|
|
right: 10rpx;
|
|
height: 2rpx;
|
|
border-top: 2rpx solid;
|
|
border-style: solid;
|
|
}
|
|
|
|
/* 添加一些波浪效果 */
|
|
.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;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
</style>
|