Files
JiaZhiQianYan/pages/ztfx/ztfx.vue
renzhijun 44d8ecf318 饼图
2026-01-31 11:40:28 +08:00

1027 lines
27 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<navBar leftText="涨停分析" hideNavBg hideBack></navBar>
<image class="topBg absolute" src="/static/image/index/conceptTopBg.png" mode="widthFix"></image>
<scroll-view scroll-y class="stockDetailsC fixed" :style="'top:'+contentTop+'px;'">
<view style="color: white; font-weight: 500; display: flex; align-items: center; margin: 35rpx 25rpx;">
<image style="width: 40rpx; height: 40rpx;" src="/pagesStock/static/icon/ai-icon.png" mode="widthFix">
</image>
<text style="font-size: 36rpx; margin-left: 10rpx; margin-right: 20rpx;">AI总结</text>
<text style="font-size: 28rpx;">市场情绪温和主线题材存储芯片</text>
</view>
<view style="background-color: white; border-radius: 10rpx; overflow: hidden; margin: 25rpx;">
<view
style="color: #2B2B2B; font-weight: 500; display: flex; align-items: center; margin: 25rpx 20rpx;">
<image style="width: 40rpx; height: 40rpx;" src="/pagesStock/static/icon/ai-icon-1.png"
mode="widthFix"></image>
<text
style="font-size: 30rpx; font-weight: bold; margin-left: 10rpx; margin-right: 20rpx;">核心指标</text>
</view>
<view style="display: grid; gap: 15rpx; grid-template-columns: repeat(3, 1fr); margin: 20rpx;">
<view v-for="(item,index) in tabTypes" :key="index"
style="display: flex; align-items: center; justify-content: center; flex-direction: column; background-color: #FFF8F0; border: 1rpx solid #F59B38; border-radius: 5rpx; padding: 20rpx; box-sizing: border-box;">
<view style="display: flex;align-items: center;justify-content: center;">
<view style="color: #F59B38; font-size: 30rpx;">{{item.data}}</view>
<view v-if="item.change > 0"
style="margin-left: 10rpx; background-color: #F59B38; border-radius: 5rpx; color: white; padding: 0 5rpx; font-size: 24rpx; font-weight: bold;">
+{{item.change}}</view>
</view>
<view style="color: #555555; font-size: 20rpx; margin-top: 5rpx;">{{item.title}}</view>
</view>
</view>
<view style="margin: 25rpx;">
<LCCalendar @date-change="handleDateChange"></LCCalendar>
</view>
<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"
mode="widthFix"></image>
<view style="margin-left: 10rpx;">
<view style="font-size: 30rpx; font-weight: bold;">市场全景</view>
<view style="font-size: 24rpx; font-weight: 500; margin-top: 10rpx;">
<text
style="color: #F3C368; border: 1rpx solid #F3C368; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">35个板块</text>
<text
style="color: #EC3440; border: 1rpx solid #EC3440; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin: 0 10rpx;">102只涨停</text>
<text
style="color: #F59B38; border: 1rpx solid #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">高位股风险:
</text>
</view>
</view>
</view>
<view
style="background-color: #FAFAFC; border-radius: 10rpx; padding: 30rpx 20rpx; box-sizing: border-box; margin: 25rpx;">
<view style="display: flex; align-items: center; font-size: 22rpx; font-weight: 500;">
<view style="flex: 1; color: #2B2B2B; font-weight: bold; font-size: 28rpx;">板块热力图</view>
<view style="color: #EF4444; display: flex;align-items: center;">
<view
style="margin: 0 10rpx; box-sizing: border-box; border-radius: 15rpx; background-color: #EF4444; overflow: hidden; width: 15rpx; height: 15rpx;">
</view>高热度
</view>
<view style="color: #F97316; display: flex;align-items: center;">
<view
style="margin: 0 10rpx; box-sizing: border-box; border-radius: 15rpx; background-color: #F97316; overflow: hidden; width: 15rpx; height: 15rpx;">
</view>中热度
</view>
<view style="color: #F3B800; display: flex;align-items: center;">
<view
style="margin: 0 10rpx; box-sizing: border-box; border-radius: 15rpx; background-color: #F3B800; overflow: hidden; width: 15rpx; height: 15rpx;">
</view>低热度
</view>
<view style="color: #01AB5D; display: flex;align-items: center;">
<view
style="margin: 0 10rpx; box-sizing: border-box; border-radius: 15rpx; background-color: #01AB5D; overflow: hidden; width: 15rpx; height: 15rpx;">
</view>冷门
</view>
</view>
<view style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 7rpx; margin-top: 25rpx;">
<view v-for="(item, index) in bkList" :key="index" @click="bkydAction(index)"
style="background-color: #EF4444; border-radius: 5rpx; padding: 15rpx; color: white; font-size: 24rpx; font-weight: 500;">
<view>{{item.title}}</view>
<view style="font-size: 22rpx;">{{item.count}}</view>
</view>
</view>
</view>
<view
style="margin: 25rpx; display: grid; grid-template-columns: repeat(3, 1fr); gap: 20rpx; color: #999999; font-size: 22rpx; font-weight: 500;">
<!-- <view v-for="(item, index) in bkTypes"
style="display: flex; align-items: center; justify-content: center; padding: 10rpx 20rpx;"
:style="{color: (index == 0 ? '#BB8520' : '#999999'), border: `1rpx solid ${index == 0 ? '#F2C369' : '#D2D2D2'}`, 'background-color' : (index == 0 ? '#FFFAF1' : '#FFF')}">
{{item}}
</view> -->
<view v-for="(item, index) in bkTypes" @click="switchTab(index)"
style="display: flex; align-items: center; justify-content: center; padding: 10rpx 20rpx; border-radius: 8rpx;"
:style="{
color: (activeType == index ? '#BB8520' : '#999999'),
border: `1rpx solid ${activeType == index ? '#F2C369' : '#D2D2D2'}`,
'background-color' : (activeType == index ? '#FFFAF1' : '#FFF'),
'cursor': 'pointer'
}">
{{item}}
</view>
</view>
<view style=" display: flex; align-items: center; justify-content: center;padding: 0 25rpx; ">
<!-- <view v-if="activeType === 0"
style="width: 100%; height: 500rpx; display: flex; align-items: center; justify-content: center; color: #999;">
板块关联图内容区域
</view> -->
<view v-show="activeType === 0" style="width: 100%; height: 500rpx;">
<l-echart ref="graphChartRef"></l-echart>
</view>
<view v-show="activeType === 1" style="width: 100%; height: 500rpx;">
<l-echart ref="chartRef"></l-echart>
</view>
<WordCloud v-show="activeType === 2" :wordData="wordData" :width="330" :height="330" />
</view>
<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"
mode="widthFix"></image>
<view style="margin-left: 10rpx;">
<view style="font-size: 30rpx; font-weight: bold;">高位股统计</view>
<view style="font-size: 24rpx; font-weight: 500; margin-top: 10rpx;">
<text
style="color: #F3C368; border: 1rpx solid #F3C368; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">高位股10只</text>
<text
style="color: #EC3440; border: 1rpx solid #EC3440; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin: 0 10rpx;">平均3.7</text>
<text
style="color: #F59B38; border: 1rpx solid #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">最高9版</text>
<text
style="color: #FFF; background-color: #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin-left: 10rpx;">中风险</text>
</view>
</view>
</view>
<view v-for="(item,index) in 10" :key="index"
style="background-color: #FAFAFC; border-radius: 10rpx; padding: 15rpx 20rpx; display: flex; align-items: center; margin: 10rpx 25rpx;">
<view style="flex: 1;">
<view style="color: #2B2B2B; font-weight: bold; font-size: 26rpx;">博菲电气</view>
<view style="color: #999999; font-weight: 500; font-size: 24rpx; margin-top: 5rpx;">(销量一字,高风险)
</view>
</view>
<view
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;">
<image style="width: 15rpx; height: 17rpx; margin-right: 10rpx;"
src="/pagesStock/static/icon/all-icon-4.png" mode="widthFix"></image>
<view>9连板</view>
</view>
<image style="width: 27rpx; height: 25rpx;" src="/pagesStock/static/icon/all-icon-5.png"
mode="widthFix"></image>
</view>
<view
style="margin: 20rpx 30rpx; color: #EF4444; font-size: 24rpx; font-weight: 500; display: flex; align-items: center;">
<image style="width: 27rpx; height: 25rpx; margin-right: 10rpx;"
src="/pagesStock/static/icon/all-icon-5.png" mode="widthFix"></image>
<text>高位股风险较高追涨需谨慎</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import {getBaseURL1 } from '@/request/http.js'
import {
inject
} from 'vue'
import {
calendarCombinedData,
analyseHighStocks
} from '@/request/api'
const echarts = require('../../uni_modules/lime-echart/static/echarts.min.js');
import WordCloud from '@/components/WordCloud/WordCloud.vue';
// 模拟关系图数据替代接口请求的les-miserables.json
const mockGraphData = {
categories: [{
name: '板块'
},
{
name: '概念'
},
{
name: '个股'
}
],
nodes: [{
name: '科技板块',
symbolSize: 50,
category: 0
},
{
name: '人工智能',
symbolSize: 30,
category: 1
},
{
name: '大数据',
symbolSize: 25,
category: 1
},
{
name: '科大讯飞',
symbolSize: 20,
category: 2
},
{
name: '百度',
symbolSize: 20,
category: 2
},
{
name: '金融板块',
symbolSize: 50,
category: 0
},
{
name: '数字货币',
symbolSize: 30,
category: 1
},
{
name: '招商银行',
symbolSize: 20,
category: 2
},
{
name: '平安银行',
symbolSize: 20,
category: 2
}
],
links: [{
source: '科技板块',
target: '人工智能',
value: 10
},
{
source: '科技板块',
target: '大数据',
value: 8
},
{
source: '人工智能',
target: '科大讯飞',
value: 6
},
{
source: '人工智能',
target: '百度',
value: 6
},
{
source: '金融板块',
target: '数字货币',
value: 9
},
{
source: '数字货币',
target: '招商银行',
value: 5
},
{
source: '数字货币',
target: '平安银行',
value: 5
}
]
};
export default {
components: {
WordCloud
},
data() {
return {
navH: inject('navHeight'),
contentTop: '',
selectedYearMonth: '', // 年-月(去掉日)
selectedFullDate: '', // 年-月-日
selectedItem: null, // 选中的item完整数据
tabTypes: [{
data: '',
change: 0,
title: '当前日期'
},
{
data: '',
change: 3,
title: '涨停家数'
},
{
data: '22%',
change: 0,
title: '炸板率'
}
],
wordData: [],
bkList: [{
title: '存储芯片',
count: 8
}, {
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
},
{
title: '存储芯片',
count: 8
}
],
bkTypes: [
'板块关联图',
'板块分布',
'热门概念词云'
],
activeType: 0, // 默认选中第一个标签
// 饼图配置项
pieOption: {
tooltip: {
trigger: 'item'
},
animation:false,
legend: {
top: '5%',
left: 'center',
show:false
},
series: [{
name: 'Access From',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
padAngle: 2,
itemStyle: {
borderRadius: 8
},
emphasis: {
label: {
show: true,
fontSize: 10,
}
},
labelLine: {
length:1,
length2:5,
},
data: []
}]
},
// 关系图配置项
graphOption: {
tooltip: {},
legend: [],
series: [{
name: '板块关联',
type: 'graph',
layout: 'none',
data: [],
links: [],
categories: [],
roam: true, // 允许拖拽和缩放
label: {
show: true,
position: 'right',
formatter: '{b}'
},
labelLayout: {
hideOverlap: true
},
scaleLimit: {
min: 0.4,
max: 2
},
lineStyle: {
color: 'source',
curveness: 0.3
}
}]
},
}
},
onLoad(e) {
this.activeIndex = e.index
this.contentTop = this.navH + 20 / 750 * inject('windowWidth')
this.analyseHighStocks()
},
onReady() {
this.fetchData()
// 页面就绪后,若默认选中的是板块分布,初始化饼图
//if (this.activeType === 0) {
this.initGraphChart(); // 初始化关系图
//} else if (this.activeType === 1) {
// 初始化饼图
//}
},
methods: {
// 切换标签
async switchTab(index) {
this.activeType = index;
switch (index) {
case 0:
this.$refs.graphChartRef && this.initGraphChart(); // 增加存在性判断
break;
case 1:
this.$refs.chartRef && this.initPieChart(); // 增加存在性判断
break;
case 2:
this.initWordCloud();
break;
}
},
getPreviousDayDate(dateStr) {
// 校验输入日期格式是否正确
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
console.error('日期格式错误,请传入 YYYY-MM-DD 格式的日期');
return '';
}
// 创建日期对象(注意:月份是 0 开始的,所以需要处理)
const [year, month, day] = dateStr.split('-').map(Number);
const date = new Date(year, month - 1, day);
// 将日期减一天
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}`;
},
/**
* 请求接口数据(优化:动态日期+自动时间戳)
*/
async fetchData() {
try {
// 1. 自动生成当前时间戳(替代固定值)
const timestamp = new Date().getTime();
// 调用上面的函数获取前一天的格式化日期YYYYMMDD
const formattedDate = this.getPreviousDayDate(this.selectedFullDate);
const baseURL = getBaseURL1();
const requestUrl = `${baseURL}/data/zt/daily/${formattedDate}.json?t=${timestamp}`;
console.log('请求URL', requestUrl); // 打印URL便于调试
const res = await uni.request({
url: requestUrl,
method: 'GET'
});
if (res.statusCode === 200 && res.data) {
this.originData = res.data;
console.log('接口数据请求成功', this.originData.chart_data );
this.initPieChart();
} else {
uni.showToast({
title: '数据请求失败',
icon: 'none'
});
}
} catch (error) {
console.error('请求异常:', error);
uni.showToast({
title: '网络异常',
icon: 'none'
});
}
},
// 初始化关系图(增加容错)
async initGraphChart() {
const chart = await this.$refs.graphChartRef.init(echarts);
this.graphOption.legend = [{
data: mockGraphData.categories.map(a => a.name)
}];
this.graphOption.series[0].data = mockGraphData.nodes;
this.graphOption.series[0].links = mockGraphData.links;
this.graphOption.series[0].categories = mockGraphData.categories;
chart.setOption(this.graphOption);
},
// 初始化饼图(核心修复)
async initPieChart() {
// const Piechart = await this.$refs.chartRef.init(echarts);
// console.log("Piechart", Piechart);
// Piechart.setOption(this.pieOption);
try {
// 处理饼图数据将labels和counts组合成name/value格式
let pieData = [];
const chartData = this.originData.chart_data || {};
const labels = chartData.labels || [];
const counts = chartData.counts || [];
// 遍历组合数据,确保数组长度一致
const maxLen = Math.min(labels.length, counts.length);
for (let i = 0; i < maxLen; i++) {
pieData.push({
name: labels[i], // 板块名称
value: counts[i] // 对应数量
});
}
// 更新饼图配置的data
this.pieOption.series[0].data = pieData.length > 0 ? pieData : [
{ value: 10, name: '科技板块' },
{ value: 8, name: '人脑工程' },
{ value: 9, name: '商业航天' }
];
// 初始化ECharts并设置配置
if (this.$refs.chartRef) {
const Piechart = await this.$refs.chartRef.init(echarts);
console.log("Piechart实例创建成功", Piechart);
Piechart.setOption(this.pieOption);
}
} catch (error) {
console.error('饼图初始化失败:', error);
}
},
// 初始化词云
initWordCloud() {
if (this.originData.word_freq_data && Array.isArray(this.originData.word_freq_data)) {
// 直接赋值接口返回的词频数据
this.wordData = this.originData.word_freq_data;
console.log('词云数据赋值完成', this.wordData);
} else {
// 兜底默认数据
this.wordData = [{
name: "脑机",
value: 10000
}, {
name: "航天",
value: 3428
}];
}
// this.wordData = [{
// name: "脑机",
// value: 10000
// },
// {
// name: "航天",
// value: 3428
// },
// {
// name: "商业",
// value: 1747
// },
// {
// name: "智能",
// value: 1692
// },
// {
// name: "量产",
// value: 1589
// },
// {
// name: "落地",
// value: 1555
// },
// {
// name: "存储芯片",
// value: 1487
// },
// {
// name: "医疗",
// value: 1348
// },
// {
// name: "马斯克",
// value: 1346
// },
// {
// name: "业绩",
// value: 1234
// },
// {
// name: "康复",
// value: 1143
// },
// {
// name: "机器人",
// value: 1127
// },
// {
// name: "洁净室",
// value: 1078
// },
// {
// name: "标的",
// value: 1072
// },
// {
// name: "设备",
// value: 1071
// },
// {
// name: "算力",
// value: 1015
// },
// {
// name: "材料",
// value: 983
// },
// {
// name: "卫星",
// value: 970
// },
// {
// name: "科技",
// value: 947
// },
// {
// name: "资产",
// value: 828
// },
// {
// name: "半导体",
// value: 774
// },
// {
// name: "重估",
// value: 750
// },
// {
// name: "人脑",
// value: 747
// },
// {
// name: "平台",
// value: 737
// },
// {
// name: "产业链",
// value: 726
// },
// {
// name: "赛道",
// value: 715
// },
// {
// name: "电池",
// value: 694
// },
// {
// name: "估值",
// value: 689
// },
// {
// name: "景气",
// value: 682
// },
// {
// name: "A股",
// value: 662
// },
// {
// name: "商业化",
// value: 643
// },
// {
// name: "固态",
// value: 642
// },
// {
// name: "工程",
// value: 642
// },
// {
// name: "军工",
// value: 642
// },
// {
// name: "芯片",
// value: 615
// },
// {
// name: "医疗器械",
// value: 606
// },
// {
// name: "供应链",
// value: 585
// },
// {
// name: "弹性",
// value: 573
// },
// {
// name: "蓝箭",
// value: 551
// },
// {
// name: "市值",
// value: 541
// },
// {
// name: "高端",
// value: 527
// },
// {
// name: "植入",
// value: 523
// },
// {
// name: "耗材",
// value: 523
// },
// {
// name: "逻辑",
// value: 519
// },
// {
// name: "数据",
// value: 512
// },
// {
// name: "服务器",
// value: 504
// },
// {
// name: "供应商",
// value: 503
// },
// {
// name: "电子",
// value: 483
// },
// {
// name: "芳纶",
// value: 458
// },
// {
// name: "传闻",
// value: 454
// },
// {
// name: "国产化",
// value: 453
// },
// {
// name: "营销",
// value: 452
// },
// {
// name: "涨价",
// value: 450
// },
// {
// name: "临床",
// value: 449
// },
// {
// name: "转型",
// value: 444
// },
// {
// name: "强脑",
// value: 441
// },
// {
// name: "储能",
// value: 441
// },
// {
// name: "智能家居",
// value: 438
// },
// {
// name: "场景",
// value: 435
// },
// {
// name: "港股",
// value: 423
// },
// {
// name: "柔性",
// value: 422
// },
// {
// name: "人形",
// value: 414
// },
// {
// name: "国产",
// value: 411
// },
// {
// name: "接口技术",
// value: 401
// },
// {
// name: "消费",
// value: 399
// },
// {
// name: "创板",
// value: 397
// },
// {
// name: "全球",
// value: 389
// },
// {
// name: "替代",
// value: 389
// },
// {
// name: "融资",
// value: 388
// },
// {
// name: "补贴",
// value: 369
// },
// {
// name: "管线",
// value: 368
// },
// {
// name: "电极",
// value: 367
// },
// {
// name: "模态",
// value: 364
// },
// {
// name: "国家",
// value: 361
// },
// {
// name: "盈利",
// value: 359
// },
// {
// name: "测试",
// value: 356
// },
// {
// name: "子公司",
// value: 354
// },
// {
// name: "实控",
// value: 353
// },
// {
// name: "八院",
// value: 353
// },
// {
// name: "价格",
// value: 352
// },
// {
// name: "旗下",
// value: 351
// },
// {
// name: "组件",
// value: 346
// },
// {
// name: "电解液",
// value: 342
// },
// {
// name: "中标",
// value: 340
// }
// ];
//console.log('父页面设置词云数据:', JSON.stringify(this.wordData));
},
handleDateChange(data) {
console.log('从日历组件接收的参数:', data.item?.zt_count);
// 赋值到父页面的变量中
this.selectedYearMonth = data.yearMonth;
this.selectedFullDate = data.fullDate;
this.selectedItem = data.item;
// 2. 格式化日期:年-月-日 → 月日(如 2026-01-14 → 1月14日
if (data.fullDate) {
const [year, month, day] = data.fullDate.split('-').map(Number);
this.tabTypes[0].data = `${month}${day}`;
}
// 3. 赋值涨停家数优先取item中的zt_count无数据则显示0
const ztCount = data.item?.zt_count ?? 0;
this.tabTypes[1].data = ztCount.toString(); // 转为字符串保证格式统一
// this.analyseHighStocks()
},
analyseHighStocks() {
const formatDate = this.getPreviousDayDate(this.selectedFullDate);
let param = {
date: formatDate
}
analyseHighStocks(param).then(res => {
}).catch(error => {
})
},
bkydAction(index) {
uni.navigateTo({
url: `/pagesStock/stockCenterDetails/bkydmx?index=${index}`
})
}
}
}
</script>
<style lang="less">
page {
background-color: #070707;
}
.topBg {
top: 0;
left: 0;
width: 100%;
height: auto;
}
.stockDetailsC {
left: 0;
right: 0;
bottom: calc(55px + env(safe-area-inset-bottom));
}
</style>