1.31 财务分析,财务数据模块完善,产业链桑基图展示

This commit is contained in:
尚政杰
2026-01-31 17:19:16 +08:00
parent 1c13386dfc
commit 0a2dab4936
527 changed files with 3390 additions and 604 deletions

View File

@@ -1,9 +1,111 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const request_http = require("../../request/http.js");
const request_api = require("../../request/api.js");
const common_assets = require("../../common/assets.js");
const echarts = require("../../uni_modules/lime-echart/static/echarts.min.js");
const WordCloud = () => "../../components/WordCloud/WordCloud2.js";
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
}
]
};
const _sfc_main = {
components: {
WordCloud
},
data() {
return {
navH: common_vendor.inject("navHeight"),
@@ -31,161 +133,277 @@ const _sfc_main = {
title: "炸板率"
}
],
bkList: [
wordData: [],
bkList: [],
number_limit_stocks: "",
HEAT_LEVELS: [
{
title: "存储芯片",
count: 8
threshold: 0.7,
color: "#EF4444",
level: "高热度"
},
// >70%
{
title: "存储芯片",
count: 8
threshold: 0.4,
color: "#F97316",
level: "中热度"
},
// 40%~70%
{
title: "存储芯片",
count: 8
threshold: 0.2,
color: "#F3B800",
level: "低热度"
},
// 20%~40%
{
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
threshold: 0,
color: "#01AB5D",
level: "无热度"
}
// ≤20%
],
bkTypes: [
"板块关联图",
"板块分布",
"热门概念词云"
],
option2: {
title: {
show: false
},
legend: {
show: false
},
activeType: 0,
// 默认选中第一个标签
// 饼图配置项
pieOption: {
tooltip: {
show: true,
triggerOn: "mousemove"
trigger: "item"
},
radar: {
indicator: [
{ name: "市场地位", max: 100 },
{ name: "技术实力", max: 100 },
{ name: "品牌价值", max: 100 },
{ name: "运营效率", max: 100 },
{ name: "财务健康", max: 100 },
{ name: "创新能力", max: 100 },
{ name: "风险控制", max: 100 },
{ name: "成长潜力", max: 100 }
],
shape: "polygon",
splitNumber: 5,
axisName: {
color: "#54555A"
},
splitLine: {
lineStyle: {
color: ["#CFD2D7"]
}
},
splitArea: {
areaStyle: {
color: ["#F4F6FA", "white"]
}
},
axisLine: {
lineStyle: {
color: "#CFD2D7"
}
}
animation: false,
legend: {
top: "5%",
left: "center",
show: false
},
series: [
{
name: "Beijing",
type: "radar",
lineStyle: {
width: 1
},
data: [],
symbol: "circle",
symbolSize: 4,
series: [{
name: "Access From",
type: "pie",
radius: ["40%", "70%"],
avoidLabelOverlap: false,
padAngle: 2,
itemStyle: {
borderRadius: 8
},
emphasis: {
label: {
show: true
},
itemStyle: {
color: "#5070DD"
},
areaStyle: {
opacity: 0.1
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 * common_vendor.inject("windowWidth");
this.analyseHighStocks();
},
// mounted() {
// // 初始化当天日期格式(防止日历组件事件未及时触发)
// const today = new Date();
// const month = today.getMonth() + 1;
// const day = today.getDate();
// this.tabTypes[0].data = `${month}月${day}日`;
// this.tabTypes[1].data = '0'; // 默认涨停家数为0后续会被日历数据覆盖
// },
onReady() {
this.fetchData();
this.initGraphChart();
},
methods: {
getHeatColor(value, max) {
if (max === 0)
return "#01AB5D";
const ratio = value / max;
const matchedLevel = this.HEAT_LEVELS.find((level) => ratio > level.threshold);
return matchedLevel ? matchedLevel.color : "#01AB5D";
},
// 切换标签
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)) {
common_vendor.index.__f__("error", "at pages/ztfx/ztfx.vue:483", "日期格式错误,请传入 YYYY-MM-DD 格式的日期");
return "";
}
const [year, month, day] = dateStr.split("-").map(Number);
const date = new Date(year, month - 1, day);
date.setDate(date.getDate() - 2);
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 {
const timestamp = (/* @__PURE__ */ new Date()).getTime();
const formattedDate = this.getPreviousDayDate(this.selectedFullDate);
const baseURL = request_http.getBaseURL1();
const requestUrl = `${baseURL}/data/zt/daily/${formattedDate}.json?t=${timestamp}`;
common_vendor.index.__f__("log", "at pages/ztfx/ztfx.vue:515", "请求URL", requestUrl);
const res = await common_vendor.index.request({
url: requestUrl,
method: "GET"
});
if (res.statusCode === 200 && res.data) {
this.originData = res.data;
const chartData = this.originData.chart_data || {};
const labels = chartData.labels || [];
const counts = chartData.counts || [];
const maxCount = counts.length > 0 ? Math.max(...counts) : 0;
let bkList = [];
const maxLen = Math.min(labels.length, counts.length);
for (let i = 0; i < maxLen; i++) {
const title = labels[i];
const count = counts[i] || 0;
const bgColor = this.getHeatColor(count, maxCount);
const ratio = maxCount === 0 ? 0 : (count / maxCount * 100).toFixed(2);
bkList.push({
title,
// 板块名称
count,
// 数量
bgColor,
// 背景色
ratio
// 占比(百分比,可选)
});
}
this.bkList = bkList.slice(0, 16);
this.initPieChart();
} else {
common_vendor.index.showToast({
title: "数据请求失败",
icon: "none"
});
}
} catch (error) {
common_vendor.index.__f__("error", "at pages/ztfx/ztfx.vue:562", "请求异常:", error);
common_vendor.index.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() {
try {
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]
// 对应数量
});
}
this.pieOption.series[0].data = pieData.length > 0 ? pieData : [
{
value: 10,
name: "科技板块"
},
{
value: 8,
name: "人脑工程"
},
{
value: 9,
name: "商业航天"
}
];
if (this.$refs.chartRef) {
const Piechart = await this.$refs.chartRef.init(echarts);
common_vendor.index.__f__("log", "at pages/ztfx/ztfx.vue:623", "Piechart实例创建成功", Piechart);
Piechart.setOption(this.pieOption);
}
} catch (error) {
common_vendor.index.__f__("error", "at pages/ztfx/ztfx.vue:627", "饼图初始化失败:", error);
}
},
// 初始化词云
initWordCloud() {
if (this.originData.word_freq_data && Array.isArray(this.originData.word_freq_data)) {
this.wordData = this.originData.word_freq_data;
common_vendor.index.__f__("log", "at pages/ztfx/ztfx.vue:636", "词云数据赋值完成", this.wordData);
} else {
this.wordData = [{
name: "脑机",
value: 1e4
}, {
name: "航天",
value: 3428
}];
}
},
handleDateChange(data) {
var _a, _b;
common_vendor.index.__f__("log", "at pages/ztfx/ztfx.vue:345", "从日历组件接收的参数:", (_a = data.item) == null ? void 0 : _a.zt_count);
var _a, _b, _c, _d;
common_vendor.index.__f__("log", "at pages/ztfx/ztfx.vue:654", "从日历组件接收的参数:", {
currentZtCount: (_a = data.item) == null ? void 0 : _a.zt_count,
prevZtCount: (_b = data.prevItem) == null ? void 0 : _b.zt_count
});
this.selectedYearMonth = data.yearMonth;
this.selectedFullDate = data.fullDate;
this.selectedItem = data.item;
@@ -193,11 +411,16 @@ const _sfc_main = {
const [year, month, day] = data.fullDate.split("-").map(Number);
this.tabTypes[0].data = `${month}${day}`;
}
const ztCount = ((_b = data.item) == null ? void 0 : _b.zt_count) ?? 0;
const ztCount = ((_c = data.item) == null ? void 0 : _c.zt_count) ?? 0;
this.tabTypes[1].data = ztCount.toString();
this.number_limit_stocks = ztCount.toString();
const prevZtCount = ((_d = data.prevItem) == null ? void 0 : _d.zt_count) ?? 0;
const changeValue = ztCount === 0 || prevZtCount === 0 ? 0 : ztCount - prevZtCount;
this.tabTypes[1].change = changeValue;
this.fetchData();
},
analyseHighStocks() {
const formatDate = this.selectedFullDate.replace(/-/g, "");
const formatDate = this.getPreviousDayDate(this.selectedFullDate);
let param = {
date: formatDate
};
@@ -205,10 +428,6 @@ const _sfc_main = {
}).catch((error) => {
});
},
async init() {
const chart = await this.$refs.chartRef.init(echarts);
chart.setOption(this.option2);
},
bkydAction(index) {
common_vendor.index.navigateTo({
url: `/pagesStock/stockCenterDetails/bkydmx?index=${index}`
@@ -220,13 +439,15 @@ if (!Array) {
const _easycom_navBar2 = common_vendor.resolveComponent("navBar");
const _easycom_LCCalendar2 = common_vendor.resolveComponent("LCCalendar");
const _easycom_l_echart2 = common_vendor.resolveComponent("l-echart");
(_easycom_navBar2 + _easycom_LCCalendar2 + _easycom_l_echart2)();
const _easycom_WordCloud2 = common_vendor.resolveComponent("WordCloud");
(_easycom_navBar2 + _easycom_LCCalendar2 + _easycom_l_echart2 + _easycom_WordCloud2)();
}
const _easycom_navBar = () => "../../components/navBar/navBar.js";
const _easycom_LCCalendar = () => "../../components/LCCalendar/LCCalendar.js";
const _easycom_l_echart = () => "../../uni_modules/lime-echart/components/l-echart/l-echart.js";
const _easycom_WordCloud = () => "../../components/WordCloud/WordCloud2.js";
if (!Math) {
(_easycom_navBar + _easycom_LCCalendar + _easycom_l_echart)();
(_easycom_navBar + _easycom_LCCalendar + _easycom_l_echart + _easycom_WordCloud)();
}
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return {
@@ -241,43 +462,69 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
e: common_vendor.f($data.tabTypes, (item, index, i0) => {
return common_vendor.e({
a: common_vendor.t(item.data),
b: item.change > 0
}, item.change > 0 ? {
c: common_vendor.t(item.change)
b: item.change !== 0
}, item.change !== 0 ? {
c: common_vendor.t(item.change > 0 ? "+" + item.change : item.change),
d: common_vendor.s({
marginLeft: "10rpx",
borderRadius: "5rpx",
color: "white",
padding: "0 5rpx",
fontSize: "24rpx",
fontWeight: "bold"
}),
e: common_vendor.s(item.change > 0 ? {
backgroundColor: "#F59B38"
} : {
backgroundColor: "#EF4444"
})
} : {}, {
d: common_vendor.t(item.title),
e: index
f: common_vendor.t(item.title),
g: index
});
}),
f: common_vendor.o($options.handleDateChange),
g: common_assets._imports_3$8,
h: common_vendor.f($data.bkList, (item, index, i0) => {
h: common_vendor.t($data.bkList.length),
i: common_vendor.t($data.number_limit_stocks),
j: common_vendor.f($data.bkList, (item, index, i0) => {
return {
a: common_vendor.t(item.title),
b: common_vendor.t(item.count),
c: index,
d: common_vendor.o(($event) => $options.bkydAction(index), index)
d: common_vendor.o(($event) => $options.bkydAction(index), index),
e: item.bgColor
};
}),
i: common_vendor.f($data.bkTypes, (item, index, i0) => {
k: common_vendor.f($data.bkTypes, (item, index, i0) => {
return {
a: common_vendor.t(item),
b: index == 0 ? "#BB8520" : "#999999",
c: `1rpx solid ${index == 0 ? "#F2C369" : "#D2D2D2"}`,
d: index == 0 ? "#FFFAF1" : "#FFF"
b: common_vendor.o(($event) => $options.switchTab(index)),
c: $data.activeType == index ? "#BB8520" : "#999999",
d: `1rpx solid ${$data.activeType == index ? "#F2C369" : "#D2D2D2"}`,
e: $data.activeType == index ? "#FFFAF1" : "#FFF"
};
}),
j: common_vendor.sr("chartRef", "06b829a4-2"),
k: common_assets._imports_3$8,
l: common_vendor.f(10, (item, index, i0) => {
l: common_vendor.sr("graphChartRef", "06b829a4-2"),
m: $data.activeType === 0,
n: common_vendor.sr("chartRef", "06b829a4-3"),
o: $data.activeType === 1,
p: $data.activeType === 2,
q: common_vendor.p({
wordData: $data.wordData,
width: 330,
height: 330
}),
r: common_assets._imports_3$8,
s: common_vendor.f(10, (item, index, i0) => {
return {
a: index
};
}),
m: common_assets._imports_1$11,
n: common_assets._imports_5$4,
o: common_assets._imports_5$4,
p: common_vendor.s("top:" + $data.contentTop + "px;")
t: common_assets._imports_1$11,
v: common_assets._imports_5$4,
w: common_assets._imports_5$4,
x: common_vendor.s("top:" + $data.contentTop + "px;")
};
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);

View File

@@ -1,6 +1,7 @@
{
"navigationBarTitleText": "涨停分析",
"usingComponents": {
"word-cloud": "../../components/WordCloud/WordCloud",
"nav-bar": "../../components/navBar/navBar",
"l-c-calendar": "../../components/LCCalendar/LCCalendar",
"l-echart": "../../uni_modules/lime-echart/components/l-echart/l-echart"

File diff suppressed because one or more lines are too long

View File

@@ -12,3 +12,18 @@ page {
right: 0;
bottom: calc(55px + env(safe-area-inset-bottom));
}
/* 单行省略样式类 */
.single-line-ellipsis {
max-width: 100%;
width: 120rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
}
/* 数量行样式(可选抽离) */
.count-text {
font-size: 22rpx;
margin-top: 4rpx;
text-align: center;
}