3 Commits

  1. 53
      components/IndexCard.vue
  2. 54
      components/h-loading.vue
  3. 8
      pages/marketSituation/globalIndex.vue
  4. 31
      pages/marketSituation/marketDetail.vue
  5. 32
      pages/marketSituation/marketOverview.vue
  6. BIN
      static/loading-gif.gif
  7. BIN
      static/marketSituation-image/downTimeChart.png
  8. BIN
      static/marketSituation-image/upTimeChart.png

53
components/IndexCard.vue

@ -18,9 +18,8 @@
</view>
<view class="chart-container">
<view class="mini-chart" :style="{ backgroundColor: chartBgColor }">
<!-- 这里可以放置实际的图表组件目前用简单的波浪线表示 -->
<view class="chart-line" :style="{ borderColor: priceColor }"></view>
<view class="mini-chart" >
<image class="time-chart" :src="timeChart" mode="aspectFit"></image>
</view>
</view>
</view>
@ -97,10 +96,14 @@ const priceColor = computed(() => {
return props.isRising ? "#00C853" : "#FF1744";
});
//
const chartBgColor = computed(() => {
return props.isRising ? "#E8F5E8" : "#FFEBEE";
const timeChart = computed(() => {
return props.isRising ? "/static/marketSituation-image/upTimeChart.png" : "/static/marketSituation-image/downTimeChart.png";
});
//
// const chartBgColor = computed(() => {
// return props.isRising ? "#E8F5E8" : "#FFEBEE";
// });
</script>
<style scoped>
@ -182,40 +185,8 @@ const chartBgColor = computed(() => {
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;
.time-chart {
width: 100%;
height: 100%;
}
</style>

54
components/h-loading.vue

@ -0,0 +1,54 @@
<!-- @format -->
<template>
<view v-if="loading" class="loading">
<image class="loadingGif" src="/static/loading-gif.gif" mode=""></image>
</view>
</template>
<script setup>
import { ref, computed, onMounted,watch } from "vue";
// props
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
});
const loading = ref(false);
// props.loading
watch(() => props.loading, (newVal) => {
loading.value = newVal;
});
//
onMounted(() => {
loading.value = props.loading;
});
</script>
<style scoped>
.loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
.loadingGif {
width: 100rpx;
height: 100rpx;
}
</style>

8
pages/marketSituation/globalIndex.vue

@ -2,6 +2,8 @@
<template>
<view class="main">
<!-- 加载中 -->
<h-loading :loading="loading"></h-loading>
<!-- 固定头部 -->
<view class="header_fixed" :style="{ top: iSMT + 'px' }">
<view class="header_content">
@ -69,6 +71,7 @@ import { ref, onMounted, onUnmounted, computed, nextTick, watch } from "vue";
import { onShow, onHide } from "@dcloudio/uni-app";
import footerBar from "../../components/footerBar.vue";
import IndexCard from "../../components/IndexCard.vue";
import hLoading from "@/components/h-loading.vue";
import { getRegionalGroupAPI } from "../../api/marketSituation/marketSituation.js";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
const marketSituationStore = useMarketSituationStore();
@ -78,7 +81,7 @@ const contentHeight = ref(0);
const headerHeight = ref(0); //
const searchValue = ref(""); //
const isWarnTextOverflow = ref(false); // warn
const loading = ref(false);
//
const isDataLoaded = ref(false);
@ -160,11 +163,14 @@ const viewIndexDetail = (item, parentIndex, index) => {
const getRegionalGroup = async () => {
try {
loading.value = true;
const result = await getRegionalGroupAPI();
globalIndexArray.value = result.data;
marketSituationStore.gloablCardData = result.data;
loading.value = false;
} catch (e) {
console.log("获取区域指数失败", e);
loading.value = false;
}
};

31
pages/marketSituation/marketDetail.vue

@ -2,6 +2,8 @@
<template>
<view class="main">
<!-- 加载中 -->
<h-loading :loading="loading"></h-loading>
<!-- 自定义导航栏 -->
<view class="header_fixed" :style="{ top: iSMT + 'px' }">
<view class="header-content">
@ -65,8 +67,9 @@
<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import footerBar from "@/components/footerBar.vue";
import hLoading from "@/components/h-loading.vue";
import { getRegionalGroupListAPI } from "../../api/marketSituation/marketSituation.js";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
const marketSituationStore = useMarketSituationStore();
@ -77,7 +80,7 @@ const headerHeight = ref(80);
const marketTitle = ref();
const sortType = ref(""); // 'price' 'change'
const sortOrder = ref("desc"); // 'asc' 'desc'
const loading = ref(false);
const regionalGroupArray = ref([]);
//
@ -111,13 +114,16 @@ const judgeSymbol = (num) => {
const getRegionalGroupList = async () => {
try {
loading.value = true;
const result = await getRegionalGroupListAPI({
name: marketTitle.value,
});
regionalGroupArray.value = result.data;
marketSituationStore.marketDetailCardData = result.data;
loading.value = false;
} catch (e) {
console.error("获取区域分组列表失败:", e);
loading.value = false;
}
};
@ -430,15 +436,26 @@ const startTcp = () => {
}
};
onShow(async () => {
console.log("显示页面");
await getRegionalGroupList();
initTcpListeners();
await nextTick();
//
startTcp();
});
onHide(() => {
console.log("隐藏页面");
sendTcpMessage("stop_real_time");
removeTcpListeners();
disconnectTcp();
});
//
onLoad(async (options) => {
if (options && options.market) {
marketTitle.value = options.market;
await getRegionalGroupList();
initTcpListeners();
await nextTick();
//
startTcp();
}
});

32
pages/marketSituation/marketOverview.vue

@ -2,14 +2,23 @@
<template>
<view class="main">
<h-loading :loading="loading"></h-loading>
<!-- 可滚动内容区域 -->
<scroll-view class="content_scroll" scroll-y="true" :style="{ top: contentTopPosition + 'px' }">
<view class="content">
<view class="map">
<view class="INDU">道琼斯<view :class="getSignClass(INDU.value)">{{ judgeSymbol(INDU.value) }}</view></view>
<view class="NDX">纳斯达克<view :class="getSignClass(NDX.value)">{{ judgeSymbol(NDX.value) }}</view></view>
<view class="HSI">恒生指数<view :class="getSignClass(HSI.value)">{{ judgeSymbol(HSI.value) }}</view></view>
<view class="CN">上证指数<view :class="getSignClass(CN.value)">{{ judgeSymbol(CN.value) }}</view></view>
<view class="INDU"
>道琼斯<view :class="getSignClass(INDU.value)">{{ judgeSymbol(INDU.value) }}</view></view
>
<view class="NDX"
>纳斯达克<view :class="getSignClass(NDX.value)">{{ judgeSymbol(NDX.value) }}</view></view
>
<view class="HSI"
>恒生指数<view :class="getSignClass(HSI.value)">{{ judgeSymbol(HSI.value) }}</view></view
>
<view class="CN"
>上证指数<view :class="getSignClass(CN.value)">{{ judgeSymbol(CN.value) }}</view></view
>
<image src="/static/marketSituation-image/map.png" mode="widthFix"></image>
</view>
<view class="global_index">
@ -54,6 +63,7 @@ import { ref, onMounted, onUnmounted, watch, nextTick, computed } from "vue";
import { onShow, onHide } from "@dcloudio/uni-app";
import util from "../../common/util.js";
import IndexCard from "../../components/IndexCard.vue";
import hLoading from "@/components/h-loading.vue";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
const marketSituationStore = useMarketSituationStore();
import { getGlobalIndexAPI } from "../../api/marketSituation/marketSituation.js";
@ -63,6 +73,7 @@ const searchValue = ref("");
const contentHeight = ref(0);
const headerHeight = ref(0); // header
const isWarnTextOverflow = ref(false); // warn
const loading = ref(false);
const INDU = ref({ stockName: "道琼斯", stockCode: "INDU", value: "" });
const NDX = ref({ stockName: "纳斯达克", stockCode: "513300", value: "" });
@ -91,13 +102,13 @@ const judgeSymbol = (num) => {
};
function getSignClass(value) {
const s = typeof value === 'string' ? value : String(value ?? '');
const s = typeof value === "string" ? value : String(value ?? "");
const trimmed = s.trim();
if (trimmed.startsWith('-')) return 'index-down';
if (trimmed.startsWith('+')) return 'index-up';
if (trimmed.startsWith("-")) return "index-down";
if (trimmed.startsWith("+")) return "index-up";
const n = parseFloat(trimmed);
if (!isNaN(n)) return n >= 0 ? 'index-up' : 'index-down';
return '';
if (!isNaN(n)) return n >= 0 ? "index-up" : "index-down";
return "";
}
//
@ -185,10 +196,13 @@ const goToGlobalIndex = () => {
const getGlobalIndex = async () => {
try {
loading.value = true;
const result = await getGlobalIndexAPI();
globalIndexArray.value = result.data;
loading.value = false;
} catch (e) {
console.log("获取全球指数失败", e);
loading.value = false;
}
};

BIN
static/loading-gif.gif

After

Width: 120  |  Height: 120  |  Size: 134 KiB

BIN
static/marketSituation-image/downTimeChart.png

After

Width: 160  |  Height: 62  |  Size: 8.4 KiB

BIN
static/marketSituation-image/upTimeChart.png

After

Width: 160  |  Height: 62  |  Size: 9.1 KiB

Loading…
Cancel
Save