314 lines
9.4 KiB
Vue
314 lines
9.4 KiB
Vue
<template>
|
||
<view>
|
||
<navBar leftText="详情" hideNavBg></navBar>
|
||
<image class="topBg absolute" src="/static/image/index/conceptTopBg.png" mode="widthFix"></image>
|
||
<view class="searchC fixed flex" :style="'top:'+navH+'px;'">
|
||
<image class="icon" src="/static/icon/home/conceptCenter/search.png" mode="widthFix"></image>
|
||
<input class="flex1" type="text" v-model="keywords" placeholder="输入股票代码或名称"
|
||
placeholder-style="color:#eeeeee" confirm-type="search" @input="clickSearch()" />
|
||
</view>
|
||
<view v-if="searchShow" class="searchResultList fixed" :style="'top:'+searchResultTop+'px;'" @click="clickSearchResultBg()">
|
||
<view class="list">
|
||
<view class="item" v-for="(item,index) in searchResultList" :key="index" @click.stop="clickSearchResultListItem(item)">
|
||
{{item.stock_code}} {{item.stock_name}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<scroll-view scroll-y class="stockDetailsC fixed" :style="'top:'+contentTop+'px;'">
|
||
<view>
|
||
<view style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 16rpx; margin: 0 20rpx;">
|
||
<view @click="handleTypeClick(index)" v-for="(item,index) in topLists" :key="index"
|
||
style="padding: 12rpx;"
|
||
:style="{'border-bottom': (list2Index == index ? '1rpx solid #F2C369' : 'none')}">
|
||
<view style="font-size: 24rpx; color: #070707; font-weight: bold; text-align: center;"
|
||
:style="{color: (list2Index == index ? '#BB8520' : '#070707')}">
|
||
{{item.title}}
|
||
</view>
|
||
<view style="font-size: 20rpx; font-weight: 400; text-align: center;"
|
||
:style="{color: (list2Index == index ? '#BB8520' : '#070707')}">{{item.value}}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view style="height: 1rpx; margin: 0 20rpx; background-color: #E7E7E7;"></view>
|
||
<!-- '股票名称', '涨跌幅', '市值', '成交额', '行业' -->
|
||
<view
|
||
style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 10rpx; background-color: #FAFAFC; line-height: 60rpx; margin: 0 20rpx; margin-top: 20rpx;">
|
||
<view v-for="(item,index) in ['股票名称', '涨跌幅', '市值', '成交额', '行业']" :key="index"
|
||
style="color: #666666; font-size: 20rpx; font-weight: 500; text-align: center;">
|
||
{{item}}
|
||
</view>
|
||
</view>
|
||
<!-- '股票名称', '涨跌幅', '市值', '成交额', '行业' 的 内容 -->
|
||
<view v-for="(obj, j) in filteredData" @click="itemDetails(obj)"
|
||
style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 10rpx; min-height: 60rpx; margin: 0 20rpx;"
|
||
:style="{'background-color': (j % 2 == 0 ? '#fff' : '#FAFAFC')}">
|
||
<!-- 外层循环:每一行数据 -->
|
||
<view v-for="(item,index) in getTableItem(obj)" :key="index"
|
||
style="padding: 10rpx 0; color: #666666; font-size: 20rpx; font-weight: 500; text-align: center; display: flex; justify-content: center; align-items: center; flex-direction: column;"
|
||
|
||
:style="{
|
||
color: (index == 0 ? '#222222' :
|
||
index == 1 ? (item[2] === 'positive' ? '#EC3440' : '#01AB5D') : '#666666')
|
||
}">
|
||
<view>{{item[0]}}</view>
|
||
<view v-if="index == 0" style="color: #666666; font-size: 20rpx; font-weight: 500;">{{item[1]}}</view>
|
||
</view>
|
||
</view>
|
||
<view style="height: 25rpx;"></view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
inject
|
||
} from 'vue'
|
||
import {
|
||
marketHeatmap,
|
||
searchStockInfo,
|
||
stockBasicInfo
|
||
} from '@/request/api'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
navH: inject('navHeight'),
|
||
contentTop: '',
|
||
allStockData: [],
|
||
filteredData: [],
|
||
currentDate: '', // 最终要赋值的日期
|
||
searchResultTop:'', //搜索结果
|
||
contentTop: '',
|
||
keywords: '', //搜索关键字
|
||
searchShow:false, //是否展示搜索结果
|
||
searchResultList:[], //搜索结果
|
||
selectSearchStockInfo:null, //选中的搜索股票信息
|
||
topLists: [{
|
||
title: '超大盘股',
|
||
value: '(>1000亿)',
|
||
},
|
||
{
|
||
title: '大盘股',
|
||
value: '(500-1000亿)',
|
||
},
|
||
{
|
||
title: '中盘股',
|
||
value: '(100-500亿)',
|
||
}
|
||
],
|
||
list2Index: 0
|
||
}
|
||
},
|
||
onLoad(e) {
|
||
this.currentDate = e.currentDate
|
||
this.searchResultTop = this.navH + (20 + 70) / 750 * inject('windowWidth')
|
||
this.contentTop = this.navH + (20 + 70 + 25) / 750 * inject('windowWidth')
|
||
this.marketHeatmap()
|
||
},
|
||
methods: {
|
||
/**
|
||
* 点击搜索
|
||
*/
|
||
clickSearch() {
|
||
if(this.keywords) {
|
||
this.getSearchStockInfoListData()
|
||
}else
|
||
this.selectSearchStockInfo = null
|
||
},
|
||
/**
|
||
* 点击搜索结果背景
|
||
*/
|
||
clickSearchResultBg()
|
||
{
|
||
this.searchShow = false
|
||
},
|
||
/**
|
||
* 点击搜索结果列表项
|
||
*/
|
||
clickSearchResultListItem(item) {
|
||
this.selectSearchStockInfo = item
|
||
this.searchShow = false
|
||
this.getStockBasicInfoData()
|
||
//this.getQuoteDetailsData()
|
||
},
|
||
/**
|
||
* 根据输入内容获取搜索列表项
|
||
*/
|
||
getSearchStockInfoListData() {
|
||
let param = {q:this.keywords,limit:10}
|
||
searchStockInfo(param).then(res=>{
|
||
this.searchResultList = res.data
|
||
this.searchShow = this.searchResultList.length>0
|
||
}).catch(error=>{
|
||
|
||
})
|
||
},
|
||
/**
|
||
* 获取股票基本信息
|
||
*/
|
||
getStockBasicInfoData() {
|
||
let code = this.stockCode
|
||
if (this.selectSearchStockInfo) {
|
||
code = this.selectSearchStockInfo.stock_code
|
||
}
|
||
// stockBasicInfo(code).then(res=>{
|
||
// this.stockBasicInfo = res.data
|
||
// this.navTitle = res.data.SECNAME+'('+res.data.SECCODE+')'
|
||
// }).catch(error=>{
|
||
|
||
// })
|
||
uni.navigateTo({
|
||
url: '/pagesStock/stockCenterDetails/stockCenterDetails?code=' + code
|
||
})
|
||
},
|
||
handleTypeClick(index) {
|
||
this.list2Index = index;
|
||
// 先请求数据,再筛选
|
||
this.marketHeatmap();
|
||
},
|
||
getTableItem(obj) {
|
||
// 1. 处理空值,避免 toFixed 调用时报错
|
||
const marketCap = obj.market_cap ? obj.market_cap.toFixed(2) : '0.00';
|
||
const amount = obj.amount ? obj.amount.toFixed(2) : '0.00';
|
||
// 统一处理涨跌幅:空值默认0,转数字避免字符串干扰判断
|
||
const changePercent = obj.change_percent ? Number(obj.change_percent) : 0;
|
||
|
||
// 2. 处理涨跌幅的符号和类型标记
|
||
let changePercentStr = '';
|
||
let changeType = ''; // 标记正负:positive/negative/zero
|
||
if (changePercent > 0) {
|
||
changePercentStr = `+${changePercent}%`; // 正数拼接+号
|
||
changeType = 'positive';
|
||
} else if (changePercent < 0) {
|
||
changePercentStr = `${changePercent}%`; // 负数直接显示
|
||
changeType = 'negative';
|
||
} else {
|
||
changePercentStr = '0%'; // 0值统一显示
|
||
changeType = 'zero';
|
||
}
|
||
|
||
// 3. 返回数组:涨跌幅位置新增 changeType 用于模板判断颜色
|
||
return [
|
||
[obj.stock_name, obj.stock_code],
|
||
[changePercentStr, '', changeType], // 第三个元素存类型标记
|
||
[`${marketCap}亿元`],
|
||
[`${amount}亿元`],
|
||
[obj.industry || '暂无'] // 处理行业为空的情况
|
||
];
|
||
},
|
||
marketHeatmap() {
|
||
let param = {
|
||
limit: 500
|
||
}
|
||
if (this.currentDate && this.currentDate !== 'undefined' && this.currentDate.trim() !== '') {
|
||
param.date = this.currentDate;
|
||
}
|
||
marketHeatmap(param).then(res => {
|
||
// 存储原始数据
|
||
this.allStockData = res.data || [];
|
||
// 调用筛选方法
|
||
this.filterStockByMarketCap();
|
||
|
||
}).catch(error => {
|
||
|
||
})
|
||
},
|
||
// 根据市值区间筛选数据
|
||
filterStockByMarketCap() {
|
||
const {
|
||
list2Index,
|
||
allStockData
|
||
} = this;
|
||
let filtered = [];
|
||
|
||
switch (list2Index) {
|
||
case 0: // 超大盘股(>1000亿)
|
||
filtered = allStockData.filter(item => item.market_cap > 1000);
|
||
break;
|
||
case 1: // 大盘股(500-1000亿)
|
||
filtered = allStockData.filter(item => item.market_cap >= 500 && item.market_cap <= 1000);
|
||
break;
|
||
case 2: // 中盘股(100-500亿)
|
||
filtered = allStockData.filter(item => item.market_cap >= 100 && item.market_cap <= 500);
|
||
break;
|
||
default:
|
||
filtered = allStockData;
|
||
}
|
||
|
||
this.filteredData = filtered;
|
||
},
|
||
itemDetails(item) {
|
||
uni.navigateTo({
|
||
url: '/pagesStock/stockCenterDetails/stockCenterDetails?code=' + item.stock_code
|
||
})
|
||
},
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="less">
|
||
page {
|
||
background-color: #070707;
|
||
}
|
||
|
||
.topBg {
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: auto;
|
||
}
|
||
|
||
.searchC {
|
||
background-color: #292929B3;
|
||
left: 0;
|
||
right: 0;
|
||
margin: 20rpx 25rpx 0;
|
||
padding: 0 25rpx;
|
||
height: 70rpx;
|
||
border-radius: 35rpx;
|
||
font-size: 22rpx;
|
||
font-weight: 500;
|
||
|
||
.icon {
|
||
margin-right: 12rpx;
|
||
width: 25rpx;
|
||
height: auto;
|
||
}
|
||
|
||
input {
|
||
height: 100%;
|
||
color: white;
|
||
}
|
||
}
|
||
|
||
.stockDetailsC {
|
||
left: 25rpx;
|
||
width: calc(100vw - 50rpx);
|
||
bottom: env(safe-area-inset-bottom);
|
||
background-color: white;
|
||
border-radius: 10rpx;
|
||
}
|
||
.searchResultList {
|
||
background-color: #00000080;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
padding: 0 25rpx;
|
||
.list
|
||
{
|
||
background-color: white;
|
||
border-radius: 10rpx;
|
||
.item
|
||
{
|
||
padding: 0 42rpx;
|
||
line-height: 60rpx;
|
||
font-size: 22rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
}
|
||
}
|
||
z-index: 20;
|
||
}
|
||
</style> |