cankao-h5/src/pages/realtimeInfo/index.vue

496 lines
14 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>
<!-- 顶部 banner 区域 -->
<view class="all">
<!-- banner start -->
<view class="banner">
<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>
</view>
</view>
<!-- banner end -->
<view class="">
<view class="tag">
<view class="r_tag_img">
<img :src="tagicon_1_bg" class="tag_bk" />
<view class="tag_content">
<view class="tag_item_left">
<text class="tag_title">行业分类贴标</text>
<view style="display: flex; margin-top: 15rpx">
<!-- <text class="tag_num">{{ topNum.leftNum }}</text> -->
<countTo :startVal="lastLeftNum" :endVal="topNum.leftNum" :duration="5000" class="tag_num"></countTo>
<text class="tag_status">已处理</text>
</view>
</view>
<view class="tag_item_right">
<img :src="tagicon_1" class="tag_icon" />
</view>
</view>
</view>
<view class="r_tag_img">
<img :src="tagicon_2_bg" class="tag_bk" />
<view class="tag_content">
<view class="tag_item_left">
<text class="tag_title">概念标签贴标</text>
<view style="display: flex; margin-top: 15rpx">
<!-- <text class="tag_num">{{ topNum.rightNum }}</text> -->
<countTo :startVal="lastRightNum" :endVal="topNum.rightNum" :duration="5000" class="tag_num"></countTo>
<text class="tag_status">已处理</text>
</view>
</view>
<view class="tag_item_right">
<img :src="tagicon_2" class="tag_icon" />
</view>
</view>
</view>
</view>
</view>
<view style="background-color: white; margin-top: 40rpx">
<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">
<InfoSummary style="width: 85%" :count="newsNum"></InfoSummary>
</view>
</view>
<view style="background-color: white; margin-top: 40rpx">
<div style="display: flex; justify-content: space-between; align-items: center">
<indexMenuTitle title="资讯头条 Top20"></indexMenuTitle>
<view style="display: flex; align-items: center; margin-right: 15rpx; font-size: 30rpx; gap: 10rpx; margin-top: 10rpx" @click="showCalendar">
{{ chooseDate.startDate.split(" ")[0] }}
<u-icon name="calendar" size="26" style="margin-right: 10rpx"></u-icon>
</view>
<!-- <view style="display: flex; align-items: center; gap: 25rpx;margin-right: 15px;margin-top: 10px;">
<u-icon name="play-left-fill" color="#2979ff" size="20"></u-icon>
{{ chooseDate.startDate.split(' ')[0] }}
<u-icon name="play-right-fill" color="#2979ff" size="20"></u-icon>
</view> -->
</div>
<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">
<indexMenuTitle title="热门行业池 Top10"></indexMenuTitle>
<view style="display: flex; gap: 3rpx">
<text class="view-all" @click="onViewAll(0)">查看全部</text>
<u-icon size="12" name="arrow-right"></u-icon>
</view>
</view>
<HotIndustryList :industryList="industryList" :type="0" @viewAll="handleViewAll" />
</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">
<indexMenuTitle title="风口概念池 Top10"></indexMenuTitle>
<view style="display: flex; gap: 3rpx">
<text class="view-all" @click="onViewAll(1)">查看全部</text>
<u-icon size="12" name="arrow-right"></u-icon>
</view>
</view>
<HotIndustryList :type="1" :industryList="topConceptList" @viewAll="handleViewAll" />
</view>
<view class="logout" @click="loginOut" v-if="Session.get('token')">退出登录</view>
<LoginPopup
:show="LoginShow"
@handlePopupClose="handlePopupClose"
@handlePopupSuccessCallback="handlePopupSuccessCallback"
@handlePopupErrorCallback="handlePopupErrorCallback" />
<u-calendar
:show="calendarShow"
min-date="2025-01-01"
closeOnClickOverlay
:max-date="maxDate"
:default-date="chooseDate.startDate"
monthNum="12"
:key="chooseDate.startDate"
@confirm="calendarConfirm"
@close="calendarShow = false">
</u-calendar>
</view>
</template>
<script setup>
import { ref, onMounted, onUnmounted, reactive } from "vue";
import Line from "@/components/charts/Line.vue";
import bannerImg from "@/assets/zixun/banner_pic.png";
import bannerTitle from "@/assets/zixun/banner_title.png";
import tagicon_1_bg from "@/assets/zixun/tagicon_1_bg.png";
import tagicon_2_bg from "@/assets/zixun/tagicon_2_bg.png";
import tagicon_1 from "@/assets/zixun/tagicon_1.png";
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 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"; // 路径根据实际调整
const d = new Date();
const year = d.getFullYear();
let month = d.getMonth() + 1;
month = month < 10 ? `0${month}` : month;
const date = d.getDate();
const maxDate = ref(`${year}-${month}-${date} 23:59:59`);
const minDate = ref(`${year}-${month}-${date}`);
const calendarShow = ref(false);
const newsList = ref([]);
const lastLeftNum = ref(0);
const lastRightNum = ref(0);
const industryList = ref([]);
const topConceptList = ref([]);
const newsNum = ref(0);
const lineData = ref();
const handleViewAll = () => {
// 在这里处理点击“查看全部”的逻辑,比如跳转新页面等
console.log("点击了查看全部");
};
const topNum = ref({});
// 获取顶部两个统计数据
async function getTopNum() {
let res1 = await getindustryCount({});
topNum.value.leftNum = res1.aggregations.industry_non_empty.doc_count;
let res2 = await getConceptCount({});
topNum.value.rightNum = res2.aggregations.concept_non_empty.doc_count;
lastLeftNum.value = topNum.value.leftNum;
lastRightNum.value = topNum.value.rightNum;
}
const chooseDate = reactive({
startDate: `${year}-${month}-${date}`,
endDate: null,
});
const today = new Date();
function calendarConfirm(dateList) {
console.log("🚀 ~ calendarConfirm ~ dateList:", dateList);
if (dateList && dateList.length > 0) {
chooseDate.startDate = dateList[0] + " 00:00:00";
chooseDate.endDate = dateList[dateList.length - 1] + " 23:59:59";
}
getNewsList();
calendarShow.value = false;
console.log("🚀 ~ calendarConfirm ~ chooseDate:", chooseDate);
}
// 概念标签贴标
async function getNewsList() {
newsList.value = await getTopNews({
start_date: chooseDate.startDate
? timeFormat(chooseDate.startDate)
: timeFormat(new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0)),
end_date: chooseDate.endDate
? timeFormat(chooseDate.endDate)
: timeFormat(new Date(today.getFullYear(), today.getMonth(), today.getDate(), 12, 0, 0, 0)),
limit_num: 20,
});
}
// 热门行业top10
async function getTopIndustry_dFn() {
industryList.value = await getTopIndustry_d({});
}
// 风口概念池top10
async function getTopConcept_dFn() {
topConceptList.value = await getTopConcept_d({});
}
// 今日精选
async function getNews_cnt_dFn() {
let temp = await getNews_cnt_d({});
newsNum.value = temp[0].value;
}
// 获取柱状图数据
async function getLineData() {
let res = await newsInfoScore({});
lineData.value = res;
}
function initData() {
// 获取柱状图数据
getLineData();
// 获取顶部两个统计数据
getTopNum();
// 热门行业top10
getTopIndustry_dFn();
// 风口概念池top10
getTopConcept_dFn();
// 今日精选
getNews_cnt_dFn();
}
const type = ref(null);
function onViewAll(type1) {
type.value = type1;
if (Session.get("token")) {
uni.navigateTo({
url: "/pages/realtimeInfo/rankDetail?type=" + type,
});
} else {
LoginShow.value = true;
}
}
const timer = setInterval(() => {
initData();
}, 5000);
function showCalendar() {
calendarShow.value = true;
}
const LoginShow = ref(false);
const isLoginStatus = ref();
// 关闭弹框
const handlePopupClose = () => {
LoginShow.value = false;
};
// 登录成功之后的回调
const handlePopupSuccessCallback = () => {
isLoginStatus.value = true;
// uni.navigateTo({
// url: "/pages/realtimeInfo/rankDetail?type=" + type.value,
// });
};
// 登录失败之后的回调
const handlePopupErrorCallback = () => {
console.log("登录失败");
};
function loginOut() {
Session.clear();
window.location.reload();
}
onUnmounted(() => {
clearInterval(timer);
});
onMounted(async () => {
initData();
if (!Session.get("token")) {
LoginShow.value = true;
}
// 概念标签贴标
getNewsList();
const { aplus_queue } = window;
aplus_queue.push({
action: 'aplus.sendPV',
arguments: [{ is_auto: false }] // 此处上报的数据暂时在后台没有展示
});
});
/**
* @description 格式化时间
* @param {String|Number} dateTime 需要格式化的时间戳
* @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
* @returns {string} 返回格式化后的字符串
*/
function timeFormat(dateTime = null, formatStr = "yyyy-mm-dd hh:MM:ss") {
let date;
// 若传入时间为假值,则取当前时间
if (!dateTime) {
date = new Date();
}
// 若为unix秒时间戳则转为毫秒时间戳逻辑有点奇怪但不敢改以保证历史兼容
else if (/^\d{10}$/.test(dateTime.toString().trim())) {
date = new Date(dateTime * 1000);
}
// 若用户传入字符串格式时间戳new Date无法解析需做兼容
else if (typeof dateTime === "string" && /^\d+$/.test(dateTime.trim())) {
date = new Date(Number(dateTime));
}
// 其他都认为符合 RFC 2822 规范
else {
// 处理平台性差异在Safari/Webkit中new Date仅支持/作为分割符的字符串时间
date = new Date(typeof dateTime === "string" ? dateTime.replace(/-/g, "/") : dateTime);
}
const timeSource = {
y: date.getFullYear().toString(), // 年
m: (date.getMonth() + 1).toString().padStart(2, "0"), // 月
d: date.getDate().toString().padStart(2, "0"), // 日
h: date.getHours().toString().padStart(2, "0"), // 时
M: date.getMinutes().toString().padStart(2, "0"), // 分
s: date.getSeconds().toString().padStart(2, "0"), // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (const key in timeSource) {
const [ret] = new RegExp(`${key}+`).exec(formatStr) || [];
if (ret) {
// 年可能只需展示两位
const beginIndex = key === "y" && ret.length === 2 ? 2 : 0;
formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex));
}
}
return formatStr;
}
</script>
<style scoped lang="scss">
.all {
display: flex;
flex-direction: column;
background: #f3f5f8;
}
.banner {
position: relative;
}
.banner_bk {
width: 100vw;
}
.r_banner_title {
position: absolute;
top: 160rpx;
left: 50rpx;
display: flex;
flex-direction: column;
.banner_title {
width: 364rpx;
height: 134rpx;
}
text {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
}
.tag {
display: flex;
margin-top: -150rpx;
position: relative;
z-index: 999;
padding: 0 25rpx;
gap: 20rpx;
}
.r_tag_img {
width: calc(50vw - 20rpx);
height: 175rpx;
position: relative;
box-shadow: 0 10rpx 10rpx rgba(80, 80, 80, 0.1);
border-radius: 20rpx;
}
.tag_bk {
width: 100%;
height: 100%;
}
.tag_content {
display: flex;
position: absolute;
top: 40rpx;
left: 30rpx;
width: 83%;
justify-content: space-between;
.tag_item_left {
display: flex;
flex-direction: column;
}
.tag_title {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: #222222;
line-height: 33rpx;
}
.tag_num {
font-family: PingFangSC, PingFang SC;
font-weight: bold;
font-size: 38rpx;
color: #222222;
line-height: 56rpx;
}
.tag_status {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 22rpx;
color: #999999;
line-height: 33rpx;
margin-top: 15rpx;
margin-left: 7rpx;
}
.tag_item_right {
width: 70rpx;
height: 84rpx;
}
}
.tag_icon {
width: 70rpx;
height: 84rpx;
}
.view-all {
font-size: 14px;
color: #999;
text-decoration: underline;
}
.logout {
// width: 100%;
height: 80rpx;
background-color: red;
display: flex;
text-align: center;
justify-content: center;
align-items: center;
color: white;
margin-top: 50rpx;
border-radius: 20rpx;
margin-left: 20rpx;
margin-right: 20rpx;
margin-bottom: 20rpx;
}
</style>