涨停分析高股对接
@@ -142,42 +142,77 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
<!-- <view style="color: #2B2B2B; font-weight: 500; display: flex; margin: 25rpx 20rpx;">
|
<view style="color: #2B2B2B; font-weight: 500; display: flex; margin: 25rpx 20rpx;">
|
||||||
<image style="width: 40rpx; height: 42rpx;" src="/pagesStock/static/icon/all-icon-3.png"
|
<image style="width: 40rpx; height: 42rpx;" src="/pagesStock/static/icon/all-icon-3.png"
|
||||||
mode="widthFix"></image>
|
mode="widthFix"></image>
|
||||||
<view style="margin-left: 10rpx;">
|
<view style="margin-left: 10rpx;">
|
||||||
<view style="font-size: 30rpx; font-weight: bold;">高位股统计</view>
|
<view style="font-size: 30rpx; font-weight: bold;">高位股统计</view>
|
||||||
<view style="font-size: 24rpx; font-weight: 500; margin-top: 10rpx;">
|
<view style="font-size: 24rpx; font-weight: 500; margin-top: 10rpx;">
|
||||||
<text
|
<text
|
||||||
style="color: #F3C368; border: 1rpx solid #F3C368; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">高位股10只</text>
|
style="color: #F3C368; border: 1rpx solid #F3C368; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">
|
||||||
|
高位股{{highPositionStats.total_count}}只
|
||||||
|
</text>
|
||||||
<text
|
<text
|
||||||
style="color: #EC3440; border: 1rpx solid #EC3440; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin: 0 10rpx;">平均3.7</text>
|
style="color: #EC3440; border: 1rpx solid #EC3440; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin: 0 10rpx;">
|
||||||
|
平均{{highPositionStats.avg_continuous_days}}
|
||||||
|
</text>
|
||||||
<text
|
<text
|
||||||
style="color: #F59B38; border: 1rpx solid #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">最高9版</text>
|
style="color: #F59B38; border: 1rpx solid #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">
|
||||||
<text
|
最高{{highPositionStats.max_continuous_days}}板
|
||||||
style="color: #FFF; background-color: #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin-left: 10rpx;">中风险</text>
|
</text>
|
||||||
|
<text :style="{
|
||||||
|
color: '#FFF',
|
||||||
|
backgroundColor: riskAssessment.color,
|
||||||
|
borderRadius: '5rpx',
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: '0 10rpx',
|
||||||
|
marginLeft: '10rpx'
|
||||||
|
}">
|
||||||
|
{{riskAssessment.level}}
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
<view v-for="(item,index) in 10" :key="index"
|
<view v-for="(stock,index) in highPositionStockList" :key="index"
|
||||||
style="background-color: #FAFAFC; border-radius: 10rpx; padding: 15rpx 20rpx; display: flex; align-items: center; margin: 10rpx 25rpx;">
|
style="background-color: #FAFAFC; border-radius: 10rpx; padding: 15rpx 20rpx; display: flex; align-items: center; margin: 10rpx 25rpx;">
|
||||||
<view style="flex: 1;">
|
<view style="flex: 1;">
|
||||||
<view style="color: #2B2B2B; font-weight: bold; font-size: 26rpx;">博菲电气</view>
|
<view style="color: #2B2B2B; font-weight: bold; font-size: 26rpx;">{{stock.sname}}</view>
|
||||||
<view style="color: #999999; font-weight: 500; font-size: 24rpx; margin-top: 5rpx;">(销量一字,高风险)
|
<view :style="{
|
||||||
|
color: '#999999',
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: '24rpx',
|
||||||
|
marginTop: '5rpx'
|
||||||
|
}">
|
||||||
|
({{stock.risk_info.status}})
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view :style="{
|
||||||
style="display: flex; align-items: center; justify-content: center; padding: 4rpx 10rpx; background-color: #FFECEC; border-radius: 5rpx; border: 1rpx solid #EF4444; color: #EF4444; font-size: 20rpx; font-weight: 400; margin: 0 10rpx;">
|
display: 'flex',
|
||||||
<image style="width: 15rpx; height: 17rpx; margin-right: 10rpx;"
|
alignItems: 'center',
|
||||||
src="/pagesStock/static/icon/all-icon-4.png" mode="widthFix"></image>
|
justifyContent: 'center',
|
||||||
<view>9连板</view>
|
padding: '4rpx 10rpx',
|
||||||
|
backgroundColor: stock.risk_info.bg,
|
||||||
|
borderRadius: '5rpx',
|
||||||
|
border: `1rpx solid ${stock.risk_info.border}`,
|
||||||
|
color: stock.risk_info.color,
|
||||||
|
fontSize: '20rpx',
|
||||||
|
fontWeight: 400,
|
||||||
|
margin: '0 10rpx'
|
||||||
|
}">
|
||||||
|
<image v-if="['high', 'medium'].includes(getStockHeatType(stock))" :style="{
|
||||||
|
width: '15rpx',
|
||||||
|
height: '17rpx',
|
||||||
|
marginRight: '10rpx',
|
||||||
|
tintColor: heatIconMap[getStockHeatType(stock)].icon4Color
|
||||||
|
}" :src="heatIconMap[getStockHeatType(stock)].icon4" mode="widthFix"></image>
|
||||||
|
<view>{{stock.continuous_days_num}}连板</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<image style="width: 27rpx; height: 25rpx;" src="/pagesStock/static/icon/all-icon-5.png"
|
<image :style="{width: '27rpx', height: '25rpx'}" :src="heatIconMap[getStockHeatType(stock)].icon5"
|
||||||
mode="widthFix"></image>
|
mode="widthFix"></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
@@ -186,7 +221,7 @@
|
|||||||
<image style="width: 27rpx; height: 25rpx; margin-right: 10rpx;"
|
<image style="width: 27rpx; height: 25rpx; margin-right: 10rpx;"
|
||||||
src="/pagesStock/static/icon/all-icon-5.png" mode="widthFix"></image>
|
src="/pagesStock/static/icon/all-icon-5.png" mode="widthFix"></image>
|
||||||
<text>高位股风险较高,追涨需谨慎</text>
|
<text>高位股风险较高,追涨需谨慎</text>
|
||||||
</view> -->
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
@@ -360,6 +395,69 @@
|
|||||||
// '板块分布',
|
// '板块分布',
|
||||||
// '热门概念词云'
|
// '热门概念词云'
|
||||||
// ],
|
// ],
|
||||||
|
highPositionStats: {
|
||||||
|
total_count: 0, // 高位股数量
|
||||||
|
avg_continuous_days: 0, // 平均连板数
|
||||||
|
max_continuous_days: 0 // 最高连板数
|
||||||
|
},
|
||||||
|
riskAssessment: { // 风险评估结果
|
||||||
|
level: "正常",
|
||||||
|
color: "#22c55e"
|
||||||
|
},
|
||||||
|
highPositionStockList: [], // 新增:存储筛选后的高位股列表
|
||||||
|
// 风险阈值常量(对应参考代码)
|
||||||
|
RISK_THRESHOLDS: {
|
||||||
|
CRITICAL: 7,
|
||||||
|
HIGH: 5,
|
||||||
|
MEDIUM: 3,
|
||||||
|
LOW: 2,
|
||||||
|
},
|
||||||
|
// 风险颜色常量
|
||||||
|
RISK_COLORS: {
|
||||||
|
critical: {
|
||||||
|
color: "#ef4444",
|
||||||
|
bg: "rgba(239, 68, 68, 0.2)",
|
||||||
|
border: "rgba(239, 68, 68, 0.4)",
|
||||||
|
},
|
||||||
|
high: {
|
||||||
|
color: "#f97316",
|
||||||
|
bg: "rgba(249, 115, 22, 0.2)",
|
||||||
|
border: "rgba(249, 115, 22, 0.4)",
|
||||||
|
},
|
||||||
|
medium: {
|
||||||
|
color: "#eab308",
|
||||||
|
bg: "rgba(234, 179, 8, 0.2)",
|
||||||
|
border: "rgba(234, 179, 8, 0.4)",
|
||||||
|
},
|
||||||
|
low: {
|
||||||
|
color: "#22c55e",
|
||||||
|
bg: "rgba(34, 197, 94, 0.2)",
|
||||||
|
border: "rgba(34, 197, 94, 0.4)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
heatIconMap: {
|
||||||
|
high: {
|
||||||
|
icon4: '/pagesStock/static/icon/all-icon-4.png',
|
||||||
|
icon4Color: '#EF4444', // 高热度图标颜色
|
||||||
|
icon5: '/pagesStock/static/icon/all-icon-5.png' // 高热度右侧图标
|
||||||
|
},
|
||||||
|
medium: {
|
||||||
|
icon4: '/pagesStock/static/icon/all-icon-9.png',
|
||||||
|
icon4Color: '#F97316', // 中热度图标颜色
|
||||||
|
icon5: '/pagesStock/static/icon/all-icon-6.png' // 中热度右侧图标
|
||||||
|
},
|
||||||
|
low: {
|
||||||
|
icon4: '', // 低热度不显示icon4
|
||||||
|
icon4Color: '#F3B800',
|
||||||
|
icon5: '/pagesStock/static/icon/all-icon-7.png' // 低热度右侧图标
|
||||||
|
},
|
||||||
|
none: {
|
||||||
|
icon4: '', // 冷门
|
||||||
|
icon4Color: '#01AB5D',
|
||||||
|
icon5: '/pagesStock/static/icon/all-icon-8.png' // 无热度右侧图标
|
||||||
|
}
|
||||||
|
},
|
||||||
|
originData: null, // 原始接口数据
|
||||||
bkTypes: [
|
bkTypes: [
|
||||||
|
|
||||||
'板块分布',
|
'板块分布',
|
||||||
@@ -442,9 +540,6 @@
|
|||||||
this.activeIndex = e.index
|
this.activeIndex = e.index
|
||||||
this.contentTop = this.navH + 20 / 750 * inject('windowWidth')
|
this.contentTop = this.navH + 20 / 750 * inject('windowWidth')
|
||||||
|
|
||||||
//this.selectedFullDate = this.getPreviousDayDate();
|
|
||||||
//console.log("selectedFullDate", this.selectedFullDate)
|
|
||||||
//this.fetchData()
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -461,6 +556,155 @@
|
|||||||
//}
|
//}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getStockHeatType(stock) {
|
||||||
|
// 假设通过连板数计算热度(可根据实际业务逻辑调整)
|
||||||
|
const days = stock.continuous_days_num || 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (days >= this.RISK_THRESHOLDS.CRITICAL) { // ≥5连板 → 高热度
|
||||||
|
return 'high';
|
||||||
|
} else if (days >= this.RISK_THRESHOLDS.HIGH) { // 3-4连板 → 中热度
|
||||||
|
return 'medium';
|
||||||
|
} else if (days >= this.RISK_THRESHOLDS.MEDIUM) { // 2连板 → 低热度
|
||||||
|
return 'low';
|
||||||
|
} else { // <2连板 → 冷门(无热度)
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
//解析连板数(从"2天2板"格式中提取数字)
|
||||||
|
parseContinuousDays(continuousDaysStr) {
|
||||||
|
if (!continuousDaysStr) return 0;
|
||||||
|
const match = continuousDaysStr.match(/(\d+)天/);
|
||||||
|
return match ? Number(match[1]) : 0;
|
||||||
|
},
|
||||||
|
// 风险等级判断函数
|
||||||
|
getRiskLevel(days) {
|
||||||
|
const {
|
||||||
|
RISK_THRESHOLDS,
|
||||||
|
RISK_COLORS
|
||||||
|
} = this;
|
||||||
|
if (days >= RISK_THRESHOLDS.CRITICAL) {
|
||||||
|
return {
|
||||||
|
level: "极高",
|
||||||
|
color: RISK_COLORS.critical.color,
|
||||||
|
bg: RISK_COLORS.critical.bg,
|
||||||
|
border: RISK_COLORS.critical.border,
|
||||||
|
status: "缩量一字,高风险",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (days >= RISK_THRESHOLDS.HIGH) {
|
||||||
|
return {
|
||||||
|
level: "高",
|
||||||
|
color: RISK_COLORS.high.color,
|
||||||
|
bg: RISK_COLORS.high.bg,
|
||||||
|
border: RISK_COLORS.high.border,
|
||||||
|
status: "放量分歧,需观察",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (days >= RISK_THRESHOLDS.MEDIUM) {
|
||||||
|
return {
|
||||||
|
level: "中",
|
||||||
|
color: RISK_COLORS.medium.color,
|
||||||
|
bg: RISK_COLORS.medium.bg,
|
||||||
|
border: RISK_COLORS.medium.border,
|
||||||
|
status: "正常波动",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
level: "低",
|
||||||
|
color: RISK_COLORS.low.color,
|
||||||
|
bg: RISK_COLORS.low.bg,
|
||||||
|
border: RISK_COLORS.low.border,
|
||||||
|
status: "健康",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 计算高位股统计数据
|
||||||
|
calculateHighPositionStats() {
|
||||||
|
if (!this.originData || !this.originData.stocks) return;
|
||||||
|
|
||||||
|
// 1. 筛选高位股:连板数 >= 2 的股票 + 补充连板数和风险信息
|
||||||
|
const highPositionStocks = this.originData.stocks
|
||||||
|
.filter(stock => {
|
||||||
|
const days = this.parseContinuousDays(stock.continuous_days);
|
||||||
|
return days >= 2;
|
||||||
|
})
|
||||||
|
.map(stock => {
|
||||||
|
const days = this.parseContinuousDays(stock.continuous_days);
|
||||||
|
const riskInfo = this.getRiskLevel(days);
|
||||||
|
return {
|
||||||
|
...stock,
|
||||||
|
continuous_days_num: days, // 提取纯数字的连板数
|
||||||
|
risk_info: riskInfo // 风险等级信息
|
||||||
|
};
|
||||||
|
})
|
||||||
|
// 2. 按连板天数降序排列
|
||||||
|
.sort((a, b) => b.continuous_days_num - a.continuous_days_num);
|
||||||
|
|
||||||
|
// 3. 赋值给页面渲染用的列表(
|
||||||
|
this.highPositionStockList = highPositionStocks
|
||||||
|
|
||||||
|
// 4. 原有统计数据计算逻辑(保持不变)
|
||||||
|
const totalCount = highPositionStocks.length;
|
||||||
|
const maxDays = highPositionStocks.length ?
|
||||||
|
Math.max(...highPositionStocks.map(s => this.parseContinuousDays(s.continuous_days))) :
|
||||||
|
0;
|
||||||
|
const totalDays = highPositionStocks.reduce((sum, stock) => {
|
||||||
|
return sum + this.parseContinuousDays(stock.continuous_days);
|
||||||
|
}, 0);
|
||||||
|
const avgDays = totalCount > 0 ? (totalDays / totalCount).toFixed(1) : 0;
|
||||||
|
|
||||||
|
// 5. 更新统计数据
|
||||||
|
this.highPositionStats = {
|
||||||
|
total_count: totalCount,
|
||||||
|
avg_continuous_days: avgDays,
|
||||||
|
max_continuous_days: maxDays
|
||||||
|
};
|
||||||
|
|
||||||
|
// 6. 计算风险等级
|
||||||
|
this.calculateRiskAssessment();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// 计算风险评估
|
||||||
|
calculateRiskAssessment() {
|
||||||
|
const {
|
||||||
|
avg_continuous_days,
|
||||||
|
max_continuous_days,
|
||||||
|
total_count
|
||||||
|
} = this.highPositionStats;
|
||||||
|
const avgDays = Number(avg_continuous_days) || 0;
|
||||||
|
const maxDays = Number(max_continuous_days) || 0;
|
||||||
|
const totalCount = Number(total_count) || 0;
|
||||||
|
|
||||||
|
// 计算风险评分(和参考代码一致)
|
||||||
|
const score = avgDays * 2 + maxDays * 0.5 + totalCount * 0.3;
|
||||||
|
|
||||||
|
// 根据评分确定风险等级和颜色
|
||||||
|
if (score >= 20) {
|
||||||
|
this.riskAssessment = {
|
||||||
|
level: "高风险",
|
||||||
|
color: "#ef4444"
|
||||||
|
};
|
||||||
|
} else if (score >= 12) {
|
||||||
|
this.riskAssessment = {
|
||||||
|
level: "中风险",
|
||||||
|
color: "#f97316"
|
||||||
|
};
|
||||||
|
} else if (score >= 6) {
|
||||||
|
this.riskAssessment = {
|
||||||
|
level: "偏高",
|
||||||
|
color: "#eab308"
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.riskAssessment = {
|
||||||
|
level: "正常",
|
||||||
|
color: "#22c55e"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getHeatColor(value, max) {
|
getHeatColor(value, max) {
|
||||||
// 处理边界:最大值为0时直接返回绿色
|
// 处理边界:最大值为0时直接返回绿色
|
||||||
if (max === 0) return '#01AB5D';
|
if (max === 0) return '#01AB5D';
|
||||||
@@ -575,6 +819,9 @@
|
|||||||
// 3. 核心:限制最多显示16条(切片操作放在最后)
|
// 3. 核心:限制最多显示16条(切片操作放在最后)
|
||||||
this.bkList = bkList.slice(0, 16);
|
this.bkList = bkList.slice(0, 16);
|
||||||
this.initPieChart();
|
this.initPieChart();
|
||||||
|
|
||||||
|
this.calculateHighPositionStats();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '数据请求失败',
|
title: '数据请求失败',
|
||||||
@@ -702,39 +949,39 @@
|
|||||||
ztCount - prevZtCount;
|
ztCount - prevZtCount;
|
||||||
this.tabTypes[1].change = changeValue;
|
this.tabTypes[1].change = changeValue;
|
||||||
// =======================================
|
// =======================================
|
||||||
// ===== 新增:判断选中日期是否为系统当天,若是则日期减一天 =====
|
// ===== 新增:判断选中日期是否为系统当天,若是则日期减一天 =====
|
||||||
if (this.selectedFullDate) {
|
if (this.selectedFullDate) {
|
||||||
// 获取系统当前日期并格式化为 YYYYMMDD
|
// 获取系统当前日期并格式化为 YYYYMMDD
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const todayYear = today.getFullYear();
|
const todayYear = today.getFullYear();
|
||||||
const todayMonth = String(today.getMonth() + 1).padStart(2, '0');
|
const todayMonth = String(today.getMonth() + 1).padStart(2, '0');
|
||||||
const todayDay = String(today.getDate()).padStart(2, '0');
|
const todayDay = String(today.getDate()).padStart(2, '0');
|
||||||
const todayFormatted = `${todayYear}${todayMonth}${todayDay}`;
|
const todayFormatted = `${todayYear}${todayMonth}${todayDay}`;
|
||||||
|
|
||||||
// 判断选中日期是否等于系统当天
|
// 判断选中日期是否等于系统当天
|
||||||
if (this.selectedFullDate === todayFormatted) {
|
if (this.selectedFullDate === todayFormatted) {
|
||||||
// 创建选中日期的Date对象
|
// 创建选中日期的Date对象
|
||||||
const selectedDate = new Date(
|
const selectedDate = new Date(
|
||||||
parseInt(this.selectedFullDate.substring(0, 4)), // 年
|
parseInt(this.selectedFullDate.substring(0, 4)), // 年
|
||||||
parseInt(this.selectedFullDate.substring(4, 6)) - 1, // 月(月份从0开始)
|
parseInt(this.selectedFullDate.substring(4, 6)) - 1, // 月(月份从0开始)
|
||||||
parseInt(this.selectedFullDate.substring(6, 8)) // 日
|
parseInt(this.selectedFullDate.substring(6, 8)) // 日
|
||||||
);
|
);
|
||||||
|
|
||||||
// 将日期减一天
|
// 将日期减一天
|
||||||
selectedDate.setDate(selectedDate.getDate() - 1);
|
selectedDate.setDate(selectedDate.getDate() - 1);
|
||||||
|
|
||||||
// 格式化前一天的日期为 YYYYMMDD 格式(补零处理)
|
// 格式化前一天的日期为 YYYYMMDD 格式(补零处理)
|
||||||
const prevYear = selectedDate.getFullYear();
|
const prevYear = selectedDate.getFullYear();
|
||||||
const prevMonth = String(selectedDate.getMonth() + 1).padStart(2, '0');
|
const prevMonth = String(selectedDate.getMonth() + 1).padStart(2, '0');
|
||||||
const prevDay = String(selectedDate.getDate()).padStart(2, '0');
|
const prevDay = String(selectedDate.getDate()).padStart(2, '0');
|
||||||
const prevDateFormatted = `${prevYear}${prevMonth}${prevDay}`;
|
const prevDateFormatted = `${prevYear}${prevMonth}${prevDay}`;
|
||||||
|
|
||||||
// 更新选中的日期为前一天
|
// 更新选中的日期为前一天
|
||||||
this.selectedFullDate = prevDateFormatted;
|
this.selectedFullDate = prevDateFormatted;
|
||||||
|
|
||||||
console.log(`选中日期为当天(${todayFormatted}),已自动调整为前一天:`, prevDateFormatted);
|
console.log(`选中日期为当天(${todayFormatted}),已自动调整为前一天:`, prevDateFormatted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fetchData()
|
this.fetchData()
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
pagesStock/static/icon/all-icon-6.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
pagesStock/static/icon/all-icon-7.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
pagesStock/static/icon/all-icon-8.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
pagesStock/static/icon/all-icon-9.png
Normal file
|
After Width: | Height: | Size: 698 B |
BIN
pagesStock/static/icon/first-icon.png
Normal file
|
After Width: | Height: | Size: 717 B |
BIN
pagesStock/static/icon/first-icon1.png
Normal file
|
After Width: | Height: | Size: 701 B |
BIN
pagesStock/static/icon/first-icon2.png
Normal file
|
After Width: | Height: | Size: 400 B |
@@ -2,64 +2,95 @@
|
|||||||
<view>
|
<view>
|
||||||
<navBar leftText="板块异动明细" :hideNavBg="true"></navBar>
|
<navBar leftText="板块异动明细" :hideNavBg="true"></navBar>
|
||||||
<image class="topBg absolute" src="/static/image/index/conceptTopBg.png" mode="widthFix"></image>
|
<image class="topBg absolute" src="/static/image/index/conceptTopBg.png" mode="widthFix"></image>
|
||||||
|
|
||||||
<view class="stockDetailsC fixed" style="background-color: white; border-radius: 10rpx; overflow: hidden;" :style="'top:'+contentTop+'px;'">
|
<view class="stockDetailsC fixed" style="background-color: white; border-radius: 10rpx; overflow: hidden;"
|
||||||
|
:style="'top:'+contentTop+'px;'">
|
||||||
<view style="height: 86rpx;">
|
|
||||||
<scroll-view scroll-x style="white-space: nowrap; height: 100%; padding: 0 20rpx; box-sizing: border-box;" scroll-with-animation :scroll-into-view="'tab-' + activeIndex">
|
<view style="height: 86rpx;">
|
||||||
<view style="display: flex; align-items: center; height: 100%; font-weight: 500;">
|
<scroll-view scroll-x
|
||||||
<view :id="'tab-' + index" @click="activeIndex = index" v-for="(item,index) in bkList" :key="index" style="display: flex; align-items: center; justify-content: center; line-height: 85rpx; margin: 0 20rpx;" :style="{color: (activeIndex == index ? '#2B2B2B' : '#999999'), 'border-bottom': (activeIndex == index ? '1rpx solid #F2C369' : 'none'), 'font-size' : (activeIndex == index ? '28rpx' : '26rpx')}">
|
style="white-space: nowrap; height: 100%; padding: 0 20rpx; box-sizing: border-box;"
|
||||||
{{item.title}}
|
scroll-with-animation :scroll-into-view="'tab-' + activeIndex">
|
||||||
</view>
|
<view style="display: flex; align-items: center; height: 100%; font-weight: 500;">
|
||||||
</view>
|
<view :id="'tab-' + index" @click="activeIndex = index" v-for="(item,index) in bkList"
|
||||||
</scroll-view>
|
:key="index"
|
||||||
</view>
|
style="display: flex; align-items: center; justify-content: center; line-height: 85rpx; margin: 0 20rpx;"
|
||||||
|
:style="{color: (activeIndex == index ? '#2B2B2B' : '#999999'), 'border-bottom': (activeIndex == index ? '1rpx solid #F2C369' : 'none'), 'font-size' : (activeIndex == index ? '28rpx' : '26rpx')}">
|
||||||
<view style="height: 1rpx; background-color: #E7E7E7; margin: 0 20rpx;"></view>
|
{{item.title}}
|
||||||
|
</view>
|
||||||
<view style="height: 48rpx; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10rpx; margin: 23rpx 40rpx;">
|
</view>
|
||||||
<view @click="filterIndex = index" style="height: 45rpx; display: flex; align-items: center; justify-content: center; color: #939393; font-size: 24rpx; font-weight: 500; border-radius: 5rpx;" :style="{color: (filterIndex == index ? '#070707' : '#939393'), 'border': (filterIndex == index ? '1rpx solid #F2C369' : '1rpx solid #E5E5E5'), 'background-color' : (filterIndex == index ? '#F2C369' : '#fff')}" v-for="(item,index) in bkFilters" :key="index">
|
</scroll-view>
|
||||||
{{item}}
|
</view>
|
||||||
</view>
|
|
||||||
</view>
|
<view style="height: 1rpx; background-color: #E7E7E7; margin: 0 20rpx;"></view>
|
||||||
|
|
||||||
|
|
||||||
<view style="margin: 0 20rpx; background-color: #FAFAFC; display: grid; grid-template-columns: 35% 20% 20% 25%;">
|
|
||||||
<view v-for="(item,index) in ['名称', '涨幅', '连板', '板块']" :key="index" style="font-size: 22rpx; color: #666666; padding: 0 15rpx; box-sizing: border-box; font-weight: 500; line-height: 60rpx;" :style="{'text-align' : index == 0 ? 'left' : 'center'}">
|
|
||||||
{{item}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<scroll-view scroll-y style="position: absolute; top: 241rpx; left: 0; right: 0; bottom: 0; font-size: 20rpx; font-weight: 500;">
|
|
||||||
<view v-for="(item, index) in 30" style="margin: 0 20rpx; display: grid; grid-template-columns: 35% 20% 20% 25%;" :style="{'background-color': (index % 2 == 0 ? '#fff' : '#FAFAFC')}">
|
|
||||||
<view style="display: flex; align-items: center; color: #666666; height: 60rpx;">
|
|
||||||
<view style="display: flex; align-items: center; background-color: #FFF0E6; border-radius: 5rpx; padding: 0 10rpx; margin-left: 14rpx;">
|
|
||||||
<image style="width: 15rpx; height: 17rpx;" src="/pagesStock/static/icon/all-icon-4.png" mode="widthFix"></image>
|
|
||||||
<view style="color: #F97316; margin-left: 5rpx;">跟风</view>
|
|
||||||
</view>
|
|
||||||
<view style="margin-left: 10rpx;">康强电子</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view style="display: flex; align-items: center; justify-content: center;">
|
|
||||||
<view style="font-size: 24rpx; color: #EC3440; font-weight: bold;">+10.00%</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view style="display: flex; align-items: center; justify-content: center;">
|
|
||||||
<view style="color: #F3B800; padding: 0 10rpx; border-radius: 5rpx; background-color: #FFF9E6; border: 1rpx solid #F3B800; display: flex; align-items: center; justify-content: center;">2连板</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view style="display: flex; align-items: center; justify-content: center;">
|
|
||||||
<view style="background-color: #F4EFFF; border-radius: 5rpx; padding: 0 10rpx; color: #8B5CF6;">芯片(封装材料)</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
|
||||||
|
<view
|
||||||
|
style="height: 48rpx; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10rpx; margin: 23rpx 40rpx;">
|
||||||
|
<view @click="handleFilterChange(index)"
|
||||||
|
style="height: 45rpx; display: flex; align-items: center; justify-content: center; color: #939393; font-size: 24rpx; font-weight: 500; border-radius: 5rpx;"
|
||||||
|
:style="{color: (filterIndex == index ? '#070707' : '#939393'), 'border': (filterIndex == index ? '1rpx solid #F2C369' : '1rpx solid #E5E5E5'), 'background-color' : (filterIndex == index ? '#F2C369' : '#fff')}"
|
||||||
|
v-for="(item,index) in bkFilters" :key="index">
|
||||||
|
{{item}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<view
|
||||||
|
style="margin: 0 20rpx; background-color: #FAFAFC; display: grid; grid-template-columns: 35% 20% 20% 25%;">
|
||||||
|
<view v-for="(item,index) in ['名称', '涨幅', '连板', '板块']" :key="index"
|
||||||
|
style="font-size: 22rpx; color: #666666; padding: 0 15rpx; box-sizing: border-box; font-weight: 500; line-height: 60rpx;"
|
||||||
|
:style="{'text-align' : index == 0 ? 'left' : 'center'}">
|
||||||
|
{{item}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<scroll-view scroll-y
|
||||||
|
style="position: absolute; top: 241rpx; left: 0; right: 0; bottom: 0; font-size: 20rpx; font-weight: 500;">
|
||||||
|
<!-- 真实股票数据渲染 -->
|
||||||
|
<view v-for="(item, index) in filteredStocks" :key="item.scode"
|
||||||
|
style="margin: 0 20rpx; display: grid; grid-template-columns: 35% 20% 20% 25%;"
|
||||||
|
:style="{'background-color': (index % 2 == 0 ? '#fff' : '#FAFAFC')}">
|
||||||
|
<!-- 股票名称 + 角色标签 -->
|
||||||
|
<view style="display: flex; align-items: center; color: #666666; height: 60rpx;">
|
||||||
|
<!-- 角色标签 -->
|
||||||
|
<view v-if="item.stockRole"
|
||||||
|
style="display: flex; align-items: center; border-radius: 5rpx; padding: 0 10rpx; margin-left: 14rpx;"
|
||||||
|
:style="getRoleTagStyle(item.stockRole)">
|
||||||
|
<image v-if="item.stockRole.icon" style="width: 15rpx; height: 17rpx; margin-right: 5rpx;"
|
||||||
|
:src="item.stockRole.icon" mode="widthFix"></image>
|
||||||
|
<!-- <image style="width: 15rpx; height: 17rpx;" src="/pagesStock/static/icon/all-icon-4.png" mode="widthFix"></image> -->
|
||||||
|
<view :style="{'color': item.stockRole.color}">{{item.stockRole.text}}</view>
|
||||||
|
</view>
|
||||||
|
<view style="margin-left: 10rpx;">{{item.sname}}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 涨幅(硬编码+10%) -->
|
||||||
|
<view style="display: flex; align-items: center; justify-content: center;">
|
||||||
|
<view style="font-size: 24rpx; color: #EC3440; font-weight: bold;">+10.00%</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 连板数 -->
|
||||||
|
<view style="display: flex; align-items: center; justify-content: center;">
|
||||||
|
<view
|
||||||
|
style="padding: 0 10rpx; border-radius: 5rpx; display: flex; align-items: center; justify-content: center;"
|
||||||
|
:style="getBoardTagStyleByLevel(item.continuous_days)">
|
||||||
|
{{formatBoardText(item.continuous_days)}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 核心板块(按关键词匹配颜色) -->
|
||||||
|
<view style="display: flex; align-items: center; justify-content: center;">
|
||||||
|
<view style="background-color: #F4EFFF; border-radius: 5rpx; padding: 0 10rpx; white-space: nowrap; max-width: 120rpx; overflow: hidden;text-overflow: ellipsis;" :style="{color: getSectorTextColor(item.core_sectors[0] || '未知板块')}">
|
||||||
|
{{item.core_sectors[0] || '未知板块'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -68,73 +99,306 @@
|
|||||||
import {
|
import {
|
||||||
inject
|
inject
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import {
|
import {
|
||||||
getBaseURL1
|
getBaseURL1
|
||||||
} from '@/request/http.js'
|
} from '@/request/http.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
navH: inject('navHeight'),
|
navH: inject('navHeight'),
|
||||||
contentTop: '',
|
contentTop: '',
|
||||||
activeIndex: 0,
|
activeIndex: 0,
|
||||||
bkList: [],
|
bkList: [],
|
||||||
bkFilters: [
|
bkFilters: [
|
||||||
'按涨幅',
|
|
||||||
'按连板数',
|
'按连板数',
|
||||||
'只看龙头'
|
'只看龙头'
|
||||||
],
|
],
|
||||||
filterIndex: 0,
|
filterIndex: 0,
|
||||||
selectedFullDate: '', // 年-月-日
|
selectedFullDate: '', // 年-月-日
|
||||||
|
originData: null, // 原始接口数据
|
||||||
|
allStocks: [], // 所有股票数据(带角色标签)
|
||||||
|
// 角色配置
|
||||||
|
STOCK_ROLES: {
|
||||||
|
dragon: {
|
||||||
|
text: '龙头',
|
||||||
|
color: '#EC3440',
|
||||||
|
bgColor: '#FFE8E9',
|
||||||
|
icon: '/pagesStock/static/icon/first-icon1.png'
|
||||||
|
},
|
||||||
|
follow: {
|
||||||
|
text: '跟风',
|
||||||
|
color: '#F97316',
|
||||||
|
bgColor: '#FFF0E6',
|
||||||
|
icon: '/pagesStock/static/icon/first-icon2.png'
|
||||||
|
},
|
||||||
|
first: {
|
||||||
|
text: '首板',
|
||||||
|
color: '#01AB5D',
|
||||||
|
bgColor: '#E4F9EF',
|
||||||
|
icon: '/pagesStock/static/icon/first-icon.png'
|
||||||
|
},
|
||||||
|
normal: {
|
||||||
|
text: '',
|
||||||
|
color: '',
|
||||||
|
bgColor: '',
|
||||||
|
icon: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 连板层级样式配置(新规则)
|
||||||
|
BOARD_LEVEL_STYLES: {
|
||||||
|
dragon: { // 5板及以上 龙头
|
||||||
|
|
||||||
|
color: '#ef4444',
|
||||||
|
bgColor: '#FFE8E9',
|
||||||
|
borderColor: '#ef4444'
|
||||||
|
},
|
||||||
|
high: { // 3-4板 高位
|
||||||
|
|
||||||
|
color: '#f97316',
|
||||||
|
bgColor: '#FFF0E6',
|
||||||
|
borderColor: '#f97316'
|
||||||
|
},
|
||||||
|
mid: { // 2板 中位
|
||||||
|
|
||||||
|
color: '#eab308',
|
||||||
|
bgColor: '#FFF9E6',
|
||||||
|
borderColor: '#eab308'
|
||||||
|
},
|
||||||
|
first: { // 1板 首板
|
||||||
|
|
||||||
|
color: '#22c55e',
|
||||||
|
bgColor: '#E4F9EF',
|
||||||
|
borderColor: '#22c55e'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 板块文字颜色配置(新规则)
|
||||||
|
SECTOR_COLOR_RULES: [
|
||||||
|
{ keyword: '公告', color: '#D4AF37' }, // 金色
|
||||||
|
{ keyword: '其他', color: '#9CA3AF' }, // 灰色
|
||||||
|
{ keyword: ['AI', '人工智能', '芯片'], color: '#8B5CF6' }, // 紫色
|
||||||
|
{ keyword: ['锂电', '电池', '新能源'], color: '#10B981' }, // 翠绿
|
||||||
|
{ keyword: ['医药', '医疗'], color: '#EC4899' }, // 粉色
|
||||||
|
{ keyword: ['金融', '银行'], color: '#F59E0B' }, // 橙黄
|
||||||
|
{ keyword: ['军工', '航空'], color: '#EF4444' }, // 红色
|
||||||
|
],
|
||||||
|
DEFAULT_SECTOR_COLOR: '#06B6D4' // 默认 青色
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
// 筛选后的股票列表
|
||||||
|
filteredStocks() {
|
||||||
|
if (!this.allStocks.length) return [];
|
||||||
|
|
||||||
|
let stocks = [...this.allStocks];
|
||||||
|
|
||||||
|
// 先筛选当前选中板块的股票
|
||||||
|
if (this.activeIndex >= 0 && this.bkList.length) {
|
||||||
|
const currentSector = this.bkList[this.activeIndex]?.title;
|
||||||
|
if (currentSector) {
|
||||||
|
stocks = stocks.filter(stock => {
|
||||||
|
// 匹配核心板块或板块分类
|
||||||
|
const sectorMatch = stock.core_sectors.some(s => s.includes(currentSector)) ||
|
||||||
|
(Array.isArray(stock.sector_category) ? stock.sector_category.includes(currentSector) : stock.sector_category === currentSector);
|
||||||
|
return sectorMatch;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据筛选类型排序/过滤
|
||||||
|
switch (this.filterIndex) {
|
||||||
|
case 0: // 按连板数
|
||||||
|
stocks.sort((a, b) => {
|
||||||
|
const aDays = this.parseContinuousDays(a.continuous_days);
|
||||||
|
const bDays = this.parseContinuousDays(b.continuous_days);
|
||||||
|
return bDays - aDays;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 1: // 只看龙头(≥2连板)
|
||||||
|
stocks = stocks.filter(stock => this.parseContinuousDays(stock.continuous_days) >= 2);
|
||||||
|
stocks.sort((a, b) => {
|
||||||
|
const aDays = this.parseContinuousDays(a.continuous_days);
|
||||||
|
const bDays = this.parseContinuousDays(b.continuous_days);
|
||||||
|
return bDays - aDays;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return stocks;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onLoad(e) {
|
onLoad(e) {
|
||||||
this.activeIndex = e.index
|
this.activeIndex = e.index
|
||||||
this.selectedFullDate=e.data
|
this.selectedFullDate = e.data
|
||||||
|
console.log("selectedFullDate", this.selectedFullDate)
|
||||||
this.contentTop = this.navH + 20 / 750 * inject('windowWidth')
|
this.contentTop = this.navH + 20 / 750 * inject('windowWidth')
|
||||||
|
|
||||||
this.fetchData()
|
this.fetchData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
getPreviousDayDate(dateStr) {
|
// 解析连板数
|
||||||
// 校验输入日期格式是否正确
|
parseContinuousDays(continuousDaysStr) {
|
||||||
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
if (!continuousDaysStr) return 0;
|
||||||
console.error('日期格式错误,请传入 YYYY-MM-DD 格式的日期');
|
const match = continuousDaysStr.match(/(\d+)天/);
|
||||||
return '';
|
return match ? Number(match[1]) : 0;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// 格式化连板文本(适配新层级)
|
||||||
|
formatBoardText(continuousDaysStr) {
|
||||||
|
const boardDays = this.parseContinuousDays(continuousDaysStr);
|
||||||
|
|
||||||
|
if (boardDays === 1) return '首板'; // 1板显示首板
|
||||||
|
if (boardDays > 1) return `${boardDays}连板`; // 2板及以上显示 X连板
|
||||||
|
|
||||||
|
return ''; // 无连板数时返回空
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取连板标签样式(按新层级规则)
|
||||||
|
getBoardTagStyleByLevel(continuousDaysStr) {
|
||||||
|
const boardDays = this.parseContinuousDays(continuousDaysStr);
|
||||||
|
let styleConfig = {};
|
||||||
|
|
||||||
|
if (boardDays >= 5) {
|
||||||
|
styleConfig = this.BOARD_LEVEL_STYLES.dragon;
|
||||||
|
} else if (boardDays >= 3 && boardDays <= 4) {
|
||||||
|
styleConfig = this.BOARD_LEVEL_STYLES.high;
|
||||||
|
} else if (boardDays === 2) {
|
||||||
|
styleConfig = this.BOARD_LEVEL_STYLES.mid;
|
||||||
|
} else if (boardDays === 1) {
|
||||||
|
styleConfig = this.BOARD_LEVEL_STYLES.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'color': styleConfig.color || '#FFFFFF',
|
||||||
|
'background-color': styleConfig.bgColor || '#eab308',
|
||||||
|
'border': `1rpx solid ${styleConfig.borderColor || '#eab308'}`
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取板块文字颜色(按关键词匹配)
|
||||||
|
getSectorTextColor(sectorName) {
|
||||||
|
if (!sectorName) return this.DEFAULT_SECTOR_COLOR;
|
||||||
|
|
||||||
|
// 遍历匹配规则
|
||||||
|
for (const rule of this.SECTOR_COLOR_RULES) {
|
||||||
|
if (Array.isArray(rule.keyword)) {
|
||||||
|
// 多关键词匹配
|
||||||
|
const isMatch = rule.keyword.some(key => sectorName.includes(key));
|
||||||
|
if (isMatch) return rule.color;
|
||||||
|
} else {
|
||||||
|
// 单关键词完全匹配
|
||||||
|
if (sectorName === rule.keyword) return rule.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无匹配返回默认色
|
||||||
|
return this.DEFAULT_SECTOR_COLOR;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取股票角色
|
||||||
|
getStockRole(stock, sectorStocks, sectorIndex) {
|
||||||
|
const boardDays = this.parseContinuousDays(stock.continuous_days);
|
||||||
|
|
||||||
|
// 5板以上直接是龙头
|
||||||
|
if (boardDays >= 5) {
|
||||||
|
return this.STOCK_ROLES.dragon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首板判断:连板数为1
|
||||||
|
if (boardDays === 1) {
|
||||||
|
return this.STOCK_ROLES.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跟风判断:热门板块(前3) + 2-4连板
|
||||||
|
if (sectorIndex < 3 && boardDays >= 2 && boardDays < 5) {
|
||||||
|
// 特殊情况:板块内涨停最早 + 3板以上 → 龙头
|
||||||
|
const sortedByTime = [...sectorStocks].sort((a, b) =>
|
||||||
|
(a.zt_time || "").localeCompare(b.zt_time || "")
|
||||||
|
);
|
||||||
|
if (sortedByTime[0]?.scode === stock.scode && boardDays >= 3) {
|
||||||
|
return this.STOCK_ROLES.dragon;
|
||||||
|
}
|
||||||
|
return this.STOCK_ROLES.follow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他:普通
|
||||||
|
return this.STOCK_ROLES.normal;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取角色标签样式
|
||||||
|
getRoleTagStyle(role) {
|
||||||
|
return {
|
||||||
|
'background-color': role.bgColor
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
// 创建日期对象(注意:月份是 0 开始的,所以需要处理)
|
// 处理板块切换
|
||||||
const [year, month, day] = dateStr.split('-').map(Number);
|
handleTabChange(index) {
|
||||||
const date = new Date(year, month - 1, day);
|
this.activeIndex = index;
|
||||||
|
// 切换板块后重新计算股票角色(可选)
|
||||||
// 将日期减一天
|
this.setStockRoles();
|
||||||
date.setDate(date.getDate() - 2);
|
|
||||||
|
|
||||||
// 格式化前一天的日期为 YYYYMMDD 格式(补零处理)
|
|
||||||
const prevYear = date.getFullYear();
|
|
||||||
const prevMonth = String(date.getMonth() + 1).padStart(2, '0');
|
|
||||||
const prevDay = String(date.getDate()).padStart(2, '0');
|
|
||||||
|
|
||||||
return `${prevYear}${prevMonth}${prevDay}`;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 处理筛选切换
|
||||||
|
handleFilterChange(index) {
|
||||||
|
this.filterIndex = index;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// 为所有股票添加角色标签
|
||||||
|
setStockRoles() {
|
||||||
|
if (!this.originData || !this.originData.stocks || !this.bkList.length) return;
|
||||||
|
console.log("setStockRoles",JSON.stringify(this.originData.stocks))
|
||||||
|
this.allStocks = this.originData.stocks.map(stock => {
|
||||||
|
// 找到股票所属板块的热度排名
|
||||||
|
let sectorIndex = -1;
|
||||||
|
const stockSectors = Array.isArray(stock.sector_category) ? stock.sector_category : [stock.sector_category];
|
||||||
|
|
||||||
|
// 匹配板块列表中的位置
|
||||||
|
this.bkList.some((bk, idx) => {
|
||||||
|
const match = stockSectors.some(s => s.includes(bk.title));
|
||||||
|
if (match) {
|
||||||
|
sectorIndex = idx;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取同板块的所有股票
|
||||||
|
const sectorStocks = this.originData.stocks.filter(s => {
|
||||||
|
const sSectors = Array.isArray(s.sector_category) ? s.sector_category : [s.sector_category];
|
||||||
|
return sSectors.some(ss => stockSectors.includes(ss));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取股票角色
|
||||||
|
const stockRole = this.getStockRole(stock, sectorStocks, sectorIndex);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...stock,
|
||||||
|
stockRole: stockRole.text ? stockRole : null
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求接口数据(优化:动态日期+自动时间戳)
|
* 请求接口数据(优化:动态日期+自动时间戳)
|
||||||
*/
|
*/
|
||||||
|
// 请求接口数据
|
||||||
async fetchData() {
|
async fetchData() {
|
||||||
try {
|
try {
|
||||||
// 1. 自动生成当前时间戳(替代固定值)
|
|
||||||
const timestamp = new Date().getTime();
|
const timestamp = new Date().getTime();
|
||||||
|
const formattedDate = this.selectedFullDate;
|
||||||
|
|
||||||
// 调用上面的函数,获取前一天的格式化日期(YYYYMMDD)
|
|
||||||
const formattedDate = this.getPreviousDayDate(this.selectedFullDate);
|
|
||||||
const baseURL = getBaseURL1();
|
const baseURL = getBaseURL1();
|
||||||
const requestUrl = `${baseURL}/data/zt/daily/${formattedDate}.json?t=${timestamp}`;
|
const requestUrl = `${baseURL}/data/zt/daily/${formattedDate}.json?t=${timestamp}`;
|
||||||
|
|
||||||
console.log('请求URL:', requestUrl); // 打印URL便于调试
|
console.log('请求URL:', requestUrl);
|
||||||
|
|
||||||
const res = await uni.request({
|
const res = await uni.request({
|
||||||
url: requestUrl,
|
url: requestUrl,
|
||||||
@@ -144,30 +408,28 @@ import {
|
|||||||
if (res.statusCode === 200 && res.data) {
|
if (res.statusCode === 200 && res.data) {
|
||||||
this.originData = res.data;
|
this.originData = res.data;
|
||||||
|
|
||||||
|
// 处理板块列表
|
||||||
const chartData = this.originData.chart_data || {};
|
const chartData = this.originData.chart_data || {};
|
||||||
const labels = chartData.labels || [];
|
const labels = chartData.labels || [];
|
||||||
const counts = chartData.counts || [];
|
const counts = chartData.counts || [];
|
||||||
|
|
||||||
// 1. 找到counts中的最大值(用于计算热度颜色)
|
|
||||||
const maxCount = counts.length > 0 ? Math.max(...counts) : 0;
|
const maxCount = counts.length > 0 ? Math.max(...counts) : 0;
|
||||||
|
const maxLen = Math.min(labels.length, counts.length);
|
||||||
// 2. 遍历组装bkList(包含标题、数量、背景色、占比),先保证labels和counts长度一致
|
|
||||||
let bkList = [];
|
let bkList = [];
|
||||||
const maxLen = Math.min(labels.length, counts.length); // 取两者较短的长度,避免越界
|
|
||||||
for (let i = 0; i < maxLen; i++) {
|
for (let i = 0; i < maxLen; i++) {
|
||||||
const title = labels[i];
|
const title = labels[i];
|
||||||
const count = counts[i] || 0;
|
const count = counts[i] || 0;
|
||||||
|
|
||||||
bkList.push({
|
bkList.push({
|
||||||
title, // 板块名称
|
title,
|
||||||
count, // 数量
|
count
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.bkList = bkList;
|
this.bkList = bkList;
|
||||||
|
|
||||||
|
// 为股票添加角色标签
|
||||||
|
this.setStockRoles();
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '数据请求失败',
|
title: '数据请求失败',
|
||||||
@@ -200,7 +462,7 @@ import {
|
|||||||
|
|
||||||
.stockDetailsC {
|
.stockDetailsC {
|
||||||
left: 25rpx;
|
left: 25rpx;
|
||||||
right: 25rpx;
|
right: 25rpx;
|
||||||
width: calc(100vw - 50rpx);
|
width: calc(100vw - 50rpx);
|
||||||
bottom: env(safe-area-inset-bottom);
|
bottom: env(safe-area-inset-bottom);
|
||||||
}
|
}
|
||||||
|
|||||||