feat(图表): 优化图表组件并添加动态数据支持

- 修改Line.vue组件,修复默认值格式和优化数据反转逻辑
- 更新newsInfo.ts API,修改热门标签/行业/来源的请求参数拼接方式
- 重构LineHol.vue组件,移除硬编码数据,支持动态数据绑定和样式优化
- 在realtimeInfo页面添加7天热度统计功能,支持不同标签切换
- 改进LineHolYellow.vue组件,支持动态数据并优化图表样式
This commit is contained in:
zzp 2025-09-12 16:20:38 +08:00
parent 2e68592cf1
commit 3a29305df7
5 changed files with 151 additions and 65 deletions

View File

@ -42,15 +42,14 @@ export const getNews_cnt_d = (data: any) => {
// 热门标签某时间段内topN列表
export const getTopConceptPeriod = (data: any) => {
return request.get("/top_concept_period", data);
return request.get("/top_concept_period?start_date=" + data.start_time + "&end_date=" + data.end_time + "&limit_num=" + data.limit_num, data);
};
// 热门标签某时间段内topN列表
// 热门行业某时间段内topN列表
export const getTopIndustryPeriod = (data: any) => {
return request.get("/top_industry_period", data);
return request.get("/top_industry_period?start_date=" + data.start_time + "&end_date=" + data.end_time + "&limit_num=" + data.limit_num, data);
};
// 热门标签某时间段内topN列表
export const getTopSourcePeriod = (data: any) => {
return request.get("/top_source_period", data);
return request.get("/top_source_period?start_date=" + data.start_date + "&end_date=" + data.end_time + "&limit_num=" + data.limit_num, data);
};

View File

@ -28,7 +28,7 @@ const colorList = ["#F05040", "#696BBE", "#93CFED", "#FE9F19", "#3C74F1"];
const props = defineProps({
data: {
type: Object,
default: () => { },
default: () => {},
},
});
@ -42,8 +42,8 @@ watch(
keys.value.push(item.key);
values.value.push(item.doc_count);
});
keys.value.reverse()
values.value.reverse()
keys.value.reverse();
values.value.reverse();
initChart();
}
);

View File

@ -23,30 +23,22 @@ const props = defineProps({
},
});
watch(
() => props.data,
(newVal) => {
if (newVal) {
initChart();
}
}
);
//
const initChart = () => {
myChart = echarts.init(chartDom.value);
const builderJson = {
all: 10887,
charts: {
map: 3237,
lines: 2164,
bar: 7561,
line: 7778,
pie: 7355,
scatter: 2405,
candlestick: 1842,
radar: 2090,
heatmap: 1762,
treemap: 1593,
graph: 2060,
boxplot: 1537,
parallel: 1908,
gauge: 2107,
funnel: 1692,
sankey: 1568,
},
charts: {},
components: {
geo: 2788,
title: 9575,
@ -63,6 +55,16 @@ const initChart = () => {
},
ie: 9743,
};
// value
const maxItem = props.data.reduce((prev, current) => {
// value
return current.value > prev.value ? current : prev;
}, props.data[0]); //
props.data.forEach((item) => {
builderJson.charts[item.content] = item.value;
});
builderJson.all = maxItem.value;
const waterMarkText = "ECHARTS";
const canvas = document.createElement("canvas");
@ -76,19 +78,20 @@ const initChart = () => {
ctx.rotate(-Math.PI / 4);
ctx.fillText(waterMarkText, 0, 0);
let option = {
backgroundColor: {
type: "pattern",
image: canvas,
repeat: "repeat",
},
// backgroundColor: {
// type: "pattern",
// image: canvas,
// repeat: "repeat",
// },
tooltip: {},
title: [],
grid: [
{
top: 0,
width: "90%",
bottom: "0%",
left: 0,
top: "5%",
bottom: "10%",
left: 10,
containLabel: true,
},
],
@ -123,6 +126,12 @@ const initChart = () => {
position: "right",
show: true,
},
itemStyle: {
color: "#52A8FF",
normal: {
borderRadius: [0, 4, 4, 0],
},
},
data: Object.keys(builderJson.charts).map(function (key) {
return builderJson.charts[key];
}),
@ -141,8 +150,6 @@ onMounted(async () => {
// await getData();
// initChart();
// }, 5000);
initChart();
});
</script>

View File

@ -26,40 +26,77 @@ const props = defineProps({
//
const initChart = () => {
myChart = echarts.init(chartDom.value);
let source = [];
source.push(["score", "amount", "product"]);
props.data.forEach((item) => {
source.push([item.value, item.value, item.content]);
});
let option = {
dataset: {
source: [
["score", "amount", "product"],
[89.3, 58212, "Matcha Latte"],
[57.1, 78254, "Milk Tea"],
[74.4, 41032, "Cheese Cocoa"],
[50.1, 12755, "Cheese Brownie"],
[89.7, 20145, "Matcha Cocoa"],
[68.1, 79146, "Tea"],
[19.6, 91852, "Orange Juice"],
[10.6, 101852, "Lemon Juice"],
[32.7, 20112, "Walnut Brownie"],
],
source: source,
// [
// ["score", "amount", "product"],
// [89.3, 58212, "Matcha Latte"],
// [57.1, 78254, "Milk Tea"],
// [74.4, 41032, "Cheese Cocoa"],
// [50.1, 12755, "Cheese Brownie"],
// [89.7, 20145, "Matcha Cocoa"],
// [68.1, 79146, "Tea"],
// [19.6, 91852, "Orange Juice"],
// [10.6, 101852, "Lemon Juice"],
// [32.7, 20112, "Walnut Brownie"],
// ],
},
grid: { containLabel: true },
xAxis: { name: "amount" },
yAxis: { type: "category" },
visualMap: {
orient: "horizontal",
left: "center",
min: 10,
max: 100,
text: ["High Score", "Low Score"],
// Map the score column to color
dimension: 0,
inRange: {
color: ["#65B581", "#FFCE34", "#FD665F"],
grid: {
top: 0,
width: "90%",
top: "5%",
bottom: "10%",
left: 10,
containLabel: true,
},
xAxis: {
splitLine: {
show: false,
},
},
yAxis: {
type: "category",
axisLabel: {
interval: 0,
rotate: 30,
},
splitLine: {
show: false,
},
},
// visualMap: {
// show: false,
// orient: "horizontal",
// left: "center",
// min: 1,
// max: 100,
// text: ["High Score", "Low Score"],
// // Map the score column to color
// dimension: 0,
// inRange: {
// color: ["#65B581", "#FFCE34", "#FD665F"],
// },
// },
series: [
{
type: "bar",
label: {
position: "right",
show: true,
},
itemStyle: {
color: "#FFCE34",
normal: {
borderRadius: [0, 4, 4, 0],
},
},
encode: {
// Map the "amount" column to X axis.
x: "amount",

View File

@ -64,10 +64,10 @@
</view>
<view style="background-color: white; margin-top: 40rpx">
<indexMenuTitle title="热度统计"></indexMenuTitle>
<LineHol v-if="lineTabIndex === 0"></LineHol>
<LineHol v-else-if="lineTabIndex === 1"></LineHol>
<LineHolYellow v-else-if="lineTabIndex === 2"></LineHolYellow>
<indexMenuTitle title="近7天热度统计"></indexMenuTitle>
<LineHol v-if="lineTabIndex === 0" :data="lineTopData"></LineHol>
<LineHol v-else-if="lineTabIndex === 1" :data="lineTopData"></LineHol>
<LineHolYellow v-else-if="lineTabIndex === 2" :data="lineTopData"></LineHolYellow>
<div style="display: flex; justify-content: center; margin-bottom: 20px; margin-top: 20px">
<div class="tabs">
@ -143,7 +143,18 @@ import tagicon_2 from "@/assets/zixun/tagicon_2.png";
import LoginPopup from "@/components/loginPopup/index.vue";
import { Session } from "@/utils/storage";
import { getindustryCount, getConceptCount, getTopNews, getTopIndustry_d, getTopConcept_d, getNews_cnt_d, newsInfoScore } from "@/api/newsInfo";
import {
getindustryCount,
getConceptCount,
getTopNews,
getTopIndustry_d,
getTopConcept_d,
getNews_cnt_d,
newsInfoScore,
getTopConceptPeriod,
getTopIndustryPeriod,
getTopSourcePeriod,
} from "@/api/newsInfo";
import countTo from "@/components/count-to/vue-countTo.vue";
import RankList from "@/components/RankList.vue"; //
import InfoSummary from "@/components/InfoSummary.vue"; //
@ -268,6 +279,36 @@ function loginOut() {
const lineTabIndex = ref(0);
function handleTabClick(index) {
lineTabIndex.value = index;
getLineDataFn();
}
const lineTopData = ref({});
async function getLineDataFn() {
if (lineTabIndex.value == 0) {
getTopConceptPeriod({
start_time: "2025-09-06",
end_time: "2025-09-13",
limit_num: 10,
}).then((res) => {
lineTopData.value = res;
});
} else if (lineTabIndex.value == 1) {
getTopIndustryPeriod({
start_time: "2025-09-06",
end_time: "2025-09-13",
limit_num: 10,
}).then((res) => {
lineTopData.value = res;
});
} else if (lineTabIndex.value == 2) {
getTopSourcePeriod({
start_time: "2025-09-06",
end_time: "2025-09-13",
limit_num: 10,
}).then((res) => {
lineTopData.value = res;
});
}
}
function goSreach() {
@ -290,6 +331,8 @@ onMounted(async () => {
if (!Session.get("token")) {
LoginShow.value = true;
}
getLineDataFn();
});
</script>