cankao-h5/src/components/RankList.vue

425 lines
10 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>
<view class="news-rank-list">
<u-skeleton rows="5" title loading style="margin-bottom: 30rpx" v-if="loading"></u-skeleton>
<view class="list" v-else>
<view v-for="(item, index) in rankListLocal" :key="index" class="news-item" @click="goDetail(item, 0)">
<view class="rank-tag">
<view v-if="index == 0" class="rank-text-top3">
<img src="@/assets/zixun/ranking_icon_1.png" />
</view>
<view v-else-if="index == 1" class="rank-text-top3">
<img src="@/assets/zixun/ranking_icon_2.png" />
</view>
<view v-else-if="index == 2" class="rank-text-top3">
<img src="@/assets/zixun/ranking_icon_3.png" />
</view>
<text class="rank-text" v-else>{{ index + 1 }}</text>
</view>
<view class="news-content" :style="{ filter: Session.get('token') ? '' : 'blur(5px)' }">
<text class="news-title">{{ item.title }}</text>
<text class="news-desc">{{ item.summary }}</text>
<!-- 两个标签 start -->
<view class="r_r_tags" v-if="hasTag">
<view style="display: flex; margin-top: 20rpx; overflow-x: auto; width: 95vw">
<view class="r_tags">
<view
class="tag"
style="background-color: #fff2e9; color: #ff8125"
v-for="(item, index) in item.conceptLabels"
:key="index"
>{{ item }}</view
>
</view>
</view>
<view style="display: flex; margin-top: 4pt; overflow-x: auto; width: 100vw">
<view class="r_tags">
<view
class="tag"
style="background-color: #f5f8fe; color: #007aff"
v-for="(item, index) in item.industryLabels"
:key="index"
>{{ item }}</view
>
</view>
</view>
</view>
<!-- 两个标签 end -->
<view class="news-meta">
<view>
<text class="source">中国证券报</text>
<!-- <text class="time">{{ dayjs(item.publish_time).format("YYYY-MM-DD HH:MM:ss") }}</text> -->
<!-- .format('YYYY-MM-DD HH:mm:ss'); -->
<text class="time">
{{ timeFormat(new Date(item.publish_time).getTime()) }}
</text>
</view>
<text class="score" v-if="needExp">
<text v-if="index < 3">资讯评分:</text>
{{ item.news_score }}</text
>
</view>
</view>
</view>
</view>
<view @click="isExp = !isExp" class="r_exp" v-if="needExp">
<text v-if="isExp">收起</text>
<text v-else>展开全部</text>
<img src="@/assets/zixun/up_icon.png" class="exp_up" v-if="isExp" />
<img src="@/assets/zixun/down_icon.png" class="exp_up" v-else />
</view>
<LoginPopup
:show="LoginShow"
@handlePopupClose="handlePopupClose"
@handlePopupSuccessCallback="handlePopupSuccessCallback"
@handlePopupErrorCallback="handlePopupErrorCallback"
/>
</view>
</template>
<script setup lang="ts">
import { ref, watch, computed } from "vue";
import dayjs from "dayjs/esm/index";
import LoginPopup from "@/components/loginPopup/index.vue";
import { Session } from "@/utils/storage";
const isExp = ref(false);
const rankListLocal = ref([]);
const loading = ref(true);
watch(
() => isExp.value,
(newValue, oldValue) => {
rankListLocal.value = [];
props.newsList.forEach((item, index) => {
if (!isExp.value && index > 9) {
return;
}
let concept_label = "";
let industry_label = "";
try {
concept_label = JSON.parse(item.concept_label);
industry_label = JSON.parse(item.industry_label);
} catch (e) {}
rankListLocal.value.push({
...item,
conceptLabels: concept_label,
industryLabels: industry_label,
});
});
loading.value = false;
},
);
watch(
() => props.newsList,
(newValue, oldValue) => {
if (!props.needExp) {
isExp.value = true;
}
rankListLocal.value = [];
props.newsList.forEach((item, index) => {
if (!isExp.value && index > 9) {
return;
}
let concept_label = "";
let industry_label = "";
try {
concept_label = JSON.parse(item.concept_label);
industry_label = JSON.parse(item.industry_label);
} catch (e) {}
rankListLocal.value.push({
...item,
conceptLabels: concept_label,
industryLabels: industry_label,
});
});
loading.value = false;
},
);
// 接收父组件传入的新闻列表
const props = defineProps({
newsList: {
type: Array,
required: true,
default: () => [],
},
needExp: {
type: Boolean,
default: true,
},
hasTag: {
type: Boolean,
default: false,
},
});
const clickItem = ref({});
function goDetail(item) {
if (Session.get("token")) {
clickItem.value = item;
uni.navigateTo({
url: `/pages/detail/indexNewsInfo?id=${item.news_id}`,
});
} else {
LoginShow.value = true;
}
}
const LoginShow = ref(false);
const isLoginStatus = ref();
// 关闭弹框
const handlePopupClose = () => {
LoginShow.value = false;
};
// 登录成功之后的回调
const handlePopupSuccessCallback = () => {
isLoginStatus.value = true;
// uni.navigateTo({
// url: `/pages/detail/indexNewsInfo?id=${clickItem.value.news_id}`,
// });
};
// 登录失败之后的回调
const handlePopupErrorCallback = () => {
console.log("登录失败");
};
/**
* @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">
.news-rank-list {
padding: 10px;
}
.list {
min-height: 700rpx;
}
.news-item {
display: flex;
align-items: flex-start;
margin-bottom: 15px;
border-bottom: 1px solid #f2f2f2;
padding-bottom: 10px;
}
.rank-tag {
width: 30px;
height: 30px;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
margin-right: 6rpx;
}
.rank-text-top3 {
font-family:
PingFangSC,
PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #ffffff;
line-height: 33rpx;
text-shadow: 0px 0px 2px #deb72b;
text-align: left;
font-style: normal;
img {
width: 33rpx;
height: 41rpx;
margin-top: -10rpx;
}
}
.rank-text {
font-family:
PingFangSC,
PingFang SC;
font-weight: bold;
font-size: 28rpx;
color: #e98254;
margin-top: -20rpx;
}
.news-content {
flex: 1;
display: flex;
flex-direction: column;
}
.news-title {
font-family:
PingFangSC,
PingFang SC,
Helvetica,
Noto Sans SC,
Hiragino Sans GB,
Microsoft YaHei,
Arial,
sans-serif;
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 5px;
line-height: 1.2;
}
.news-desc {
font-family:
PingFangSC,
PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: #333333;
text-align: left;
font-style: normal;
display: -webkit-box;
/* 设置为WebKit内核的弹性盒子模型 */
-webkit-box-orient: vertical;
/* 垂直排列 */
-webkit-line-clamp: 2;
/* 限制显示三行 */
overflow: hidden;
/* 隐藏超出范围的内容 */
text-overflow: ellipsis;
/* 使用省略号 */
}
.news-meta {
display: flex;
justify-content: space-between;
font-size: 12px;
color: #999;
margin-top: 10rpx;
}
.source,
.time,
.score {
// opacity: 0.8;
font-family:
PingFangSC,
PingFang SC;
font-weight: 400;
font-size: 22rpx;
color: #999999;
line-height: 30rpx;
text-align: left;
font-style: normal;
}
.time {
margin-left: 10rpx;
}
.score {
font-family:
PingFangSC,
PingFang SC;
font-weight: 500;
font-size: 22rpx;
color: #ffa800;
line-height: 30rpx;
text-align: center;
font-style: normal;
}
.exp_up {
width: 21rpx;
height: 20rpx;
}
.r_exp {
display: flex;
text-align: center;
justify-content: center;
align-items: center;
gap: 10rpx;
}
.r_r_tags {
// margin-left: 20rpx;
width: 85vw;
overflow-x: scroll;
}
.r_tags {
display: flex;
gap: 4pt;
.tag {
font-family:
PingFangSC,
PingFang SC;
font-weight: 400;
font-size: 22rpx;
color: #3f80fa;
padding: 5rpx 20rpx;
border-radius: 10rpx;
white-space: nowrap;
}
}
</style>