feat(实时资讯): 新增周热度统计图表组件及交互功能
添加LineHol和LineHolYellow图表组件用于展示周热度统计数据 实现行业、概念标签和媒体来源的tab切换功能 优化页面布局和样式,调整部分标题文字
This commit is contained in:
parent
2204df2614
commit
4f5682c80a
|
|
@ -0,0 +1,149 @@
|
|||
<template>
|
||||
<view>
|
||||
<div ref="chartDom" style="width: 100vw; height: 700rpx"></div>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { watch, onMounted, reactive, ref } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { newsInfoScore } from "@/api/newsInfo";
|
||||
|
||||
const chartDom = ref(null);
|
||||
let myChart = null;
|
||||
|
||||
const data = reactive({});
|
||||
const keys = ref([]);
|
||||
const values = ref([]);
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
// 初始化图表
|
||||
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,
|
||||
},
|
||||
components: {
|
||||
geo: 2788,
|
||||
title: 9575,
|
||||
legend: 9400,
|
||||
tooltip: 9466,
|
||||
grid: 9266,
|
||||
markPoint: 3419,
|
||||
markLine: 2984,
|
||||
timeline: 2739,
|
||||
dataZoom: 2744,
|
||||
visualMap: 2466,
|
||||
toolbox: 3034,
|
||||
polar: 1945,
|
||||
},
|
||||
ie: 9743,
|
||||
};
|
||||
|
||||
const waterMarkText = "ECHARTS";
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
// canvas.width = canvas.height = 100;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.globalAlpha = 0.08;
|
||||
ctx.font = "20px Microsoft Yahei";
|
||||
ctx.translate(50, 50);
|
||||
ctx.rotate(-Math.PI / 4);
|
||||
ctx.fillText(waterMarkText, 0, 0);
|
||||
let option = {
|
||||
backgroundColor: {
|
||||
type: "pattern",
|
||||
image: canvas,
|
||||
repeat: "repeat",
|
||||
},
|
||||
tooltip: {},
|
||||
title: [],
|
||||
grid: [
|
||||
{
|
||||
top: 0,
|
||||
width: "90%",
|
||||
bottom: "0%",
|
||||
left: 0,
|
||||
containLabel: true,
|
||||
},
|
||||
],
|
||||
xAxis: [
|
||||
{
|
||||
type: "value",
|
||||
max: builderJson.all,
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: Object.keys(builderJson.charts),
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
rotate: 30,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: "bar",
|
||||
stack: "chart",
|
||||
z: 3,
|
||||
label: {
|
||||
position: "right",
|
||||
show: true,
|
||||
},
|
||||
data: Object.keys(builderJson.charts).map(function (key) {
|
||||
return builderJson.charts[key];
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
//使用配置
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// setInterval(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// }, 5000);
|
||||
|
||||
initChart();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<template>
|
||||
<view>
|
||||
<div ref="chartDom" style="width: 100vw; height: 700rpx"></div>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { watch, onMounted, reactive, ref } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { newsInfoScore } from "@/api/newsInfo";
|
||||
|
||||
const chartDom = ref(null);
|
||||
let myChart = null;
|
||||
|
||||
const data = reactive({});
|
||||
const keys = ref([]);
|
||||
const values = ref([]);
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
myChart = echarts.init(chartDom.value);
|
||||
|
||||
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"],
|
||||
],
|
||||
},
|
||||
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"],
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "bar",
|
||||
encode: {
|
||||
// Map the "amount" column to X axis.
|
||||
x: "amount",
|
||||
// Map the "product" column to Y axis
|
||||
y: "product",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
//使用配置
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// setInterval(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// }, 5000);
|
||||
|
||||
initChart();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
@ -6,9 +6,7 @@
|
|||
<img :src="bannerImg" class="banner_bk" />
|
||||
<view class="r_banner_title">
|
||||
<img :src="bannerTitle" class="banner_title" />
|
||||
<text>数据更新时间:{{
|
||||
dayjs(new Date().getTime()).format("YYYY-MM-DD")
|
||||
}}</text>
|
||||
<text>数据更新时间:{{ dayjs(new Date().getTime()).format("YYYY-MM-DD") }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- banner end -->
|
||||
|
|
@ -60,31 +58,32 @@
|
|||
<indexMenuTitle title="资讯评分分布区间"></indexMenuTitle>
|
||||
<Line style="margin-top: 30rpx" :data="lineData"></Line>
|
||||
|
||||
<view style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-bottom: 30rpx;
|
||||
">
|
||||
<view style="display: flex; flex-direction: column; text-align: center; justify-content: center; align-items: center; padding-bottom: 30rpx">
|
||||
<InfoSummary style="width: 85%" :count="newsNum"></InfoSummary>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<indexMenuTitle title="资讯头条榜 Top20"></indexMenuTitle>
|
||||
<indexMenuTitle title="周热度统计"></indexMenuTitle>
|
||||
<LineHol v-if="lineTabIndex === 0"></LineHol>
|
||||
<LineHolYellow v-else-if="lineTabIndex === 2"></LineHolYellow>
|
||||
|
||||
<div style="display: flex; justify-content: center; margin-bottom: 20px; margin-top: 20px">
|
||||
<div class="tabs">
|
||||
<div :class="['tab', 'tab_left', { active: lineTabIndex === 0 }]" @click="handleTabClick(0)">申万行业</div>
|
||||
<div :class="['tab', { active: lineTabIndex === 1 }]" @click="handleTabClick(1)">概念标签</div>
|
||||
<div :class="['tab', 'tab_right', { active: lineTabIndex === 2 }]" @click="handleTabClick(2)">媒体来源</div>
|
||||
</div>
|
||||
</div>
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<indexMenuTitle title="编辑精选 Top20"></indexMenuTitle>
|
||||
<RankList :newsList="newsList"></RankList>
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<view style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-right: 30rpx;
|
||||
height: 100rpx;
|
||||
">
|
||||
<view style="display: flex; justify-content: space-between; align-items: center; padding-right: 30rpx; height: 100rpx">
|
||||
<indexMenuTitle title="热门行业池 Top10"></indexMenuTitle>
|
||||
<view style="display: flex; gap: 3rpx">
|
||||
<text class="view-all" @click="onViewAll(0)">查看全部</text>
|
||||
|
|
@ -96,13 +95,7 @@
|
|||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<view style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-right: 30rpx;
|
||||
height: 100rpx;
|
||||
">
|
||||
<view style="display: flex; justify-content: space-between; align-items: center; padding-right: 30rpx; height: 100rpx">
|
||||
<indexMenuTitle title="风口概念池 Top10"></indexMenuTitle>
|
||||
<view style="display: flex; gap: 3rpx">
|
||||
<text class="view-all" @click="onViewAll(1)">查看全部</text>
|
||||
|
|
@ -115,8 +108,11 @@
|
|||
|
||||
<view class="logout" @click="loginOut" v-if="Session.get('token')">退出登录</view>
|
||||
|
||||
<LoginPopup :show="LoginShow" @handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback" @handlePopupErrorCallback="handlePopupErrorCallback" />
|
||||
<LoginPopup
|
||||
:show="LoginShow"
|
||||
@handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback"
|
||||
@handlePopupErrorCallback="handlePopupErrorCallback" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
@ -132,21 +128,15 @@ 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 } from "@/api/newsInfo";
|
||||
import countTo from "@/components/count-to/vue-countTo.vue";
|
||||
import RankList from "@/components/RankList.vue"; // 路径根据实际调整
|
||||
import InfoSummary from "@/components/InfoSummary.vue"; // 路径根据实际调整
|
||||
import indexMenuTitle from "@/components/indexMenuTitle.vue"; // 路径根据实际调整
|
||||
import dayjs from "dayjs/esm/index";
|
||||
import HotIndustryList from "@/components/HotIndustryList.vue"; // 路径根据实际调整
|
||||
import LineHol from "@/components/charts/LineHol.vue";
|
||||
import LineHolYellow from "@/components/charts/LineHolYellow.vue";
|
||||
|
||||
const newsList = ref([]);
|
||||
|
||||
|
|
@ -218,9 +208,9 @@ function initData() {
|
|||
getNews_cnt_dFn();
|
||||
}
|
||||
|
||||
const type = ref();
|
||||
function onViewAll(type) {
|
||||
type.value = type;
|
||||
const type = ref(null);
|
||||
function onViewAll(type1) {
|
||||
type.value = type1;
|
||||
if (Session.get("token")) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/realtimeInfo/rankDetail?type=" + type,
|
||||
|
|
@ -260,6 +250,11 @@ function loginOut() {
|
|||
window.location.reload();
|
||||
}
|
||||
|
||||
const lineTabIndex = ref(0);
|
||||
function handleTabClick(index) {
|
||||
lineTabIndex.value = index;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer);
|
||||
});
|
||||
|
|
@ -400,4 +395,41 @@ onMounted(async () => {
|
|||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
border-radius: 10px;
|
||||
|
||||
.tab {
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid #e7e7e7;
|
||||
color: #000;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tab_left {
|
||||
border-start-start-radius: 10px;
|
||||
border-end-start-radius: 10px;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.tab_right {
|
||||
border-start-end-radius: 10px;
|
||||
border-end-end-radius: 10px;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 1px solid #007bff;
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue