502 lines
14 KiB
Vue
502 lines
14 KiB
Vue
<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: 1000,
|
||
});
|
||
}
|
||
|
||
// 热门行业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("登录失败");
|
||
};
|
||
import { doLogout } from "@/api";
|
||
function loginOut() {
|
||
doLogout({
|
||
financialAccount: Session.get("userPhone"),
|
||
});
|
||
|
||
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>
|