This commit is contained in:
lcw
2025-11-28 22:25:58 +08:00
parent 85f1f3a6f7
commit e2a54c16eb
90 changed files with 2451 additions and 511 deletions

View File

@ -1,38 +1,39 @@
<template>
<div class="comom-title">
<div class="title">预警处置统计</div>
<div class="title">预警处置统计</div>
</div>
<div class="comom-cnt" style="border-right: 1px solid #ebebeb;width: 100%;" v-loading="list.YjczDate.loading">
<BarHatEcharts echartsId="qylxEcharts" :data="list.YjczDate" :autoTooltip="true"></BarHatEcharts>
<BarHatEcharts echartsId="qylxEcharts" :data="list.YjczDate" :autoTooltip="true"></BarHatEcharts>
</div>
</template>
<script setup>
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted,reactive } from "vue";
import { onMounted, reactive } from "vue";
const list = reactive({
YjczDate: {
loading: false,
xDate: [],
list: [],
},
});
const getYjczDate = () => {
list.YjczDate.loading = true;
list.YjczDate.loading = true;
qcckGet({}, '/mosty-gsxt/tbYjxx/getYjCzztTj').then(res => {
list.YjczDate.loading = false;
list.YjczDate.xDate = res.map(item => item.zdmc);
list.YjczDate.list = [{ name:'总数',
value: res.map(item => item.count),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
list.YjczDate.list = [
{
name: '总数',
value: res.map(item => item.count),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
})
};
onMounted(() => {
getYjczDate()
getYjczDate()
});
// const tabHeightFn = () => {
@ -47,29 +48,32 @@ getYjczDate()
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
::v-deeep .comom-title{
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
}
::v-deeep .comom-cnt{
::v-deeep .comom-title {
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
}
::v-deep .el-table td.el-table__cell{
::v-deeep .comom-cnt {
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
}
::v-deep .el-table td.el-table__cell {
color: #ffffff;
}
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell{
background: rgba(0,61,130,0.75);
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell {
background: rgba(0, 61, 130, 0.75);
}
</style>
<style lang="scss">
.zdy_bkcz_table td.el-table__cell {
color: #ffffff !important;
color: #ffffff !important;
}
.zdy_bkcz_table th.el-table__cell {
color: #ffffff !important;
font-size: 15px;
color: #ffffff !important;
font-size: 15px;
}
</style>

View File

@ -28,7 +28,7 @@
<script setup>
import emitter from "@/utils/eventBus.js";
// import { qcckPost } from "@/api/qcckApi.js";
import { getPageAllList, yjzxXwyjId, tbYjxxGetInfo } from '@/api/yj.js'
import { getPageAllList, yjzxXwyjId, tbYjxxGetInfo,yjzxyjzxSfyjSelectList,yjzxZhyjSelectList } from '@/api/yj.js'
import DeployControlItem from "@/views/home/components/deployControlItem.vue";
import * as MOSTY from "@/components/MyComponents/index";
import CheckBox from "@/components/checkBox/index.vue";
@ -205,7 +205,10 @@ const content = ref({
hplx: null
})
const chooseItem = (item) => {
console.log(item.yjlx);
switch (item.yjlx) {
case '01':
tbYjxxGetInfo(item.id).then(res => {
content.value = {
@ -240,12 +243,15 @@ const chooseItem = (item) => {
yjlb: item.yjlb || '',
czzt: res.czzt || '',
yjbt: res.yjBt || '',
yjlx:item.yjlx
}
emitter.emit('showHomeYJ', [content.value]);
})
break;
case '03':
content.value = {
yjzxyjzxSfyjSelectList(item.id).then(res => {
content.value = {
id: item.id,
ryxm: res.xm || '',
rysfzh: res.sfzh,
@ -255,12 +261,15 @@ const chooseItem = (item) => {
yjbq: res.xwms || '',
yjlb: item.yjlb || '',
czzt: res.czzt || '',
yjbt: res.yjBt || '',
yjbt: res.yjBt || '',
yjlx:item.yjlx
}
emitter.emit('showHomeYJ', [content.value]);
})
break;
case '04':
content.value = {
yjzxZhyjSelectList(item.id).then(res => {
content.value = {
id: item.id,
ryxm: res.xm || '',
rysfzh: res.sfzh,
@ -270,9 +279,11 @@ const chooseItem = (item) => {
yjbq: res.xwms || '',
yjlb: item.yjlb || '',
czzt: res.czzt || '',
yjbt: res.yjBt || '',
yjbt: res.yjBt || '',
yjlx:item.yjlx
}
emitter.emit('showHomeYJ', [content.value]);
})
break;
}

View File

@ -1,6 +1,7 @@
<template>
<div class="comom-title" @click="chooseForumPost">
<span class="title">情报论坛</span>
<!-- <span class="title">情报论坛</span> -->
<div class="title">情报论坛<span class="switchover" @click.stop="reversalPush">切换</span></div>
</div>
<div class="comom-cnt" >
<div class="zdryBox">
@ -25,7 +26,10 @@ import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
import {useRouter} from 'vue-router'
import * as MOSTY from "@/components/MyComponents/index";
const router = useRouter()
const emit = defineEmits(["reversalPush"])
const reversalPush = () => {
emit('reversalPush')
}
// 数据相关
const personList = ref([]);
const loading = ref(false);
@ -206,4 +210,10 @@ onBeforeUnmount(() => {
}
}
}
.switchover{
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
}
</style>

View File

@ -1,22 +1,26 @@
<template>
<div class="comom-title">
<span class="title">战术战略研判</span>
</div>
<div class="comom-cnt zdryBox">
<div class="model-box">
<div class="model-commom" style="" v-for="value in judgmentList" :key="value.title">
<img :src="value.img" alt="">
<div class="fontStlye">
<div class="font-bold" :style="{color: value.color}">{{value.title}}</div>
<div>{{value.num}}</div>
</div>
</div>
<div>
<span class="title" @click="reversalShow = true" :class="{ 'switchover': reversalShow }">战术研判</span>
<span class="title" @click="reversalShow = false" :class="{ 'switchover': !reversalShow }">战略研判</span>
</div>
</div>
<!-- <div class="comom-cnt zdryBox"> -->
<transition name="flip" mode="out-in">
<div :key="'qb'" v-if="reversalShow" class="flip-wrapper">
<TacticalYp></TacticalYp>
</div>
<div :key="'text'" v-else class="flip-wrapper">
<StrategyYp></StrategyYp>
</div>
</transition>
<!-- </div> -->
</template>
<script setup>
import { ref, onMounted } from 'vue';
import TacticalYp from './tacticalYp.vue'
import StrategyYp from './strategyYp.vue'
const judgmentList = ref([
{
title: '战略研判数',
@ -28,24 +32,22 @@ const judgmentList = ref([
title: '战术研判数',
num: 12,
img: require('@/assets/images/y2.png'),
color: '#e5d923'
color: '#e5d923'
},
{
title: '战术会商数',
num: 24,
img: require('@/assets/images/y3.png'),
color: '#e56723'
color: '#e56723'
},
{
title: '战略会商数',
num: 30,
img: require('@/assets/images/y4.png') ,
color: '#77e523'
img: require('@/assets/images/y4.png'),
color: '#77e523'
}
])
const reversalShow = ref(true)
</script>
@ -119,23 +121,70 @@ const judgmentList = ref([
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner::before {
background: #000;
}
.model-box{
display: flex;justify-content: space-between;padding: 20px;flex-wrap: wrap;
.model-box {
display: flex;
justify-content: space-between;
padding: 20px;
flex-wrap: wrap;
}
.model-commom {
width: 50%;
border-radius: 5px;
height: 100px;
position: relative;
.fontStlye{
.fontStlye {
font-size: 20px;
font-weight: 500;
position: absolute;z-index: 20;top: 18px;left: 80px;
.font-bold{
margin-bottom: 10px;
font-family: "YSBTH";
}
font-weight: 500;
position: absolute;
z-index: 20;
top: 18px;
left: 80px;
.font-bold {
margin-bottom: 10px;
font-family: "YSBTH";
}
}
}
.switchover {
cursor: pointer;
font-size: 14px;
color: rgb(255, 146, 4);
}
/* 包装层样式 */
.flip-wrapper {
position: relative;
width: 100%;
// height: calc(100%/3 - 8px);
height: 100%;
backface-visibility: hidden;
perspective: 1000px;
}
/* 翻转过渡动画 */
.flip-enter-active,
.flip-leave-active {
transition: all 0.6s ease;
transform-style: preserve-3d;
}
.flip-enter-from {
transform: rotateX(90deg);
opacity: 0;
}
.flip-leave-to {
transform: rotateX(-90deg);
opacity: 0;
}
.flip-enter-to,
.flip-leave-from {
transform: rotateX(0deg);
opacity: 1;
}
</style>

View File

@ -1,6 +1,7 @@
<template>
<div class="comom-title">
<span class="title">重点人员类型</span>
<!-- <span class="title">重点人员类型</span> -->
<div class="title">重点人员类型<span class="switchover" @click.stop="reversalPush">切换</span></div>
<div class="title titleFz" style="" @click="visible = true">
查看列表
</div>
@ -26,6 +27,10 @@ const data = ref([
{ value: 30, name: '重点上访人员' },
{ value: 30, name: '僧尼人员' },
])
const emit = defineEmits(["reversalPush"])
const reversalPush = () => {
emit('reversalPush')
}
const visible = ref(false)
const tbGsxtZdryzdryBqtjFn = () => {
tbGsxtZdryzdryBqtj({ bqlx: '01' }).then(res => {
@ -56,4 +61,10 @@ tbGsxtZdryzdryBqtjFn()
font-size: 14px !important;
color: rgb(255, 166, 14);
}
.switchover{
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
}
</style>

View File

@ -29,7 +29,7 @@ const list = reactive({
xDate: ['110警情', '人力情报', '系统采集', '民警处置单'],
list: [
{ name: "总数", value: [0, 0, 0, 0,], color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'], hatColor: '#087df9' },
{ name: "已处置", value: [0, 0, 0, 0], color: ['rgba(24, 232, 229, 1)', 'rgba(3, 110, 83, 1)'], hatColor: '#00FFFF' },
// { name: "已处置", value: [0, 0, 0, 0], color: ['rgba(24, 232, 229, 1)', 'rgba(3, 110, 83, 1)'], hatColor: '#00FFFF' },
],
})
const emit = defineEmits(['reversalPush'])
@ -43,11 +43,18 @@ const getCount = () => {
startTime: listQuery.value?.startTime || "",
endTime: listQuery.value?.endTime || ""
}
qcckPost(promes, '/mosty-gsxt/qbcj/getXscjTjForLylx').then(res => {
list.xDate = res ? res.cz.map(v => v.zdmc) : [];
list.list[0].value = res ? res.zs.map(v => v.count) : [];
list.list[1].value = res ? res.cz.map(v => v.count) : [];
// qcckPost(promes, '/mosty-gsxt/qbcj/getXscjTjForLylx').then(res => {
// list.xDate = res ? res.cz.map(v => v.zdmc) : [];
// list.list[0].value = res ? res.zs.map(v => v.count) : [];
// list.list[1].value = res ? res.cz.map(v => v.count) : [];
// })
qcckPost(promes, '/mosty-gsxt/qbcj/sjlyCount').then(res => {
list.xDate = res ? res.map(v => v.zdmc) : [];
list.list[0].value = res ? res.map(v => v.count) : [];
})
}
const changeTime = (val) => {
listQuery.value = {
@ -56,7 +63,6 @@ const changeTime = (val) => {
getCount()
}
const reversalPush = () => {
emit('reversalPush')
}
const close = () => {

View File

@ -0,0 +1,254 @@
<template>
<div class="comom-cnt chart-container" @mouseenter="mouseEnter" @mouseleave="mouseLeave">
<span class="toggle-btn" @click="addFn">切换</span>
<transition name="flip" mode="out-in">
<div v-if="list[add]" class="flip-wrapper chart-content" :key="add">
<BarHatEcharts :isXAxisData="true" :echartsId="`qylxEchartsmm-${add}`" :data="list[add]" :autoTooltip="true" :chartLeft="{ dataAxis:'25%', categoryAxis: '5%' }" />
</div>
<div v-else class="flip-wrapper no-data">
暂无数据
</div>
</transition>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, onUnmounted } from 'vue';
import { tbGsxtXscjTjForSjbm } from '@/api/qbcj'
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
const list = ref([]);
// 请求数据
const getXscjTjForSjbm = () => {
tbGsxtXscjTjForSjbm({}).then(res => {
// 先将原始数据处理为一维数组
const zsDataArray = res.zs.map((item, index) => {
return {
org_name: item.org_name,
zsCount: item.count,
yczCount: item.org_name === res.ycz[index].org_name ? res.ycz[index].count : 0
}
});
// 将一维数组转换为每7个元素为一组的二维数组
const groupSize = 7;
const ZsData = Array.from({
length: Math.ceil(zsDataArray.length / groupSize)
}, (_, i) => zsDataArray.slice(i * groupSize, (i + 1) * groupSize));
console.log(ZsData);
list.value = ZsData.map(item => {
return {
loading: false,
list: [{
name: '总数',
value: item.map(items => items.zsCount),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
}, {
name: '已处置',
value: item.map(items => items.yczCount),
color: ['rgba(24, 232, 229, 1)', 'rgba(3, 110, 83, 1)'],
}],
xDate: item.map(item => {
if (item.org_name.indexOf('林芝市公安局') == 0) {
return item.org_name.slice(6, item.org_name.length)
} else if (item.org_name.indexOf('林芝市') == 0) {
return item.org_name.slice(3, item.org_name.length)
} else if (item.org_name.indexOf('西藏自治区林芝市') == 0) {
return item.org_name.slice(8, item.org_name.length)
} else {
return item.org_name
}
})
}
})
})
}
const add = ref(0)
const addFn = () => {
// 确保list数组有数据时才执行切换操作
if (list.value.length > 0) {
// 确保不超过list的长度实现循环切换
add.value = (add.value + 1) % list.value.length
}
}
let times=ref()
onMounted(() => {
getXscjTjForSjbm()
times.value=setInterval(() => {
addFn()
}, 30000);
// getYjczDate()
})
// 鼠标移入
const mouseEnter = () => {
clearInterval(times.value)
}
// 鼠标移出
const mouseLeave = () => {
// 清除可能存在的旧定时器,避免多个定时器同时运行
clearInterval(times.value)
// 设置为5秒自动切换更容易测试效果
times.value = setInterval(() => {
addFn()
}, 30000)
}
onUnmounted(() => {
clearInterval(times.value)
})
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.loading-more {
text-align: center;
padding: 8px;
color: #83bff6;
background: rgba(0, 0, 0, 0.3);
font-size: 12px;
}
.zdryBox {
height: 100%;
position: relative;
overflow: hidden;
.ryBox {
height: 100%;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
// 隐藏滚动条但保留滚动功能
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none; // IE和Edge
scrollbar-width: none; // Firefox
li {
padding: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background-color 0.3s;
cursor: pointer;
box-sizing: border-box;
&:hover {
background-color: rgba(20, 107, 190, 0.2);
}
>div:first-child {
font-weight: bold;
color: #fff;
margin-bottom: 8px;
font-size: 14px;
/* 标题限制1行超出用省略号 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.meta-info {
text-align: right;
color: #83bff6;
font-size: 12px;
margin-bottom: 8px;
}
>div:last-child {
color: rgba(255, 255, 255, 0.8);
font-size: 13px;
line-height: 1.6;
/* 内容限制3行超出用省略号 */
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
.switchover {
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
}
/* 图表容器样式 */
.chart-container {
border-right: 1px solid #ebebeb;
width: 100%;
height: 100% !important;
}
/* 切换按钮样式 */
.toggle-btn {
position: absolute;
z-index: 10;
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
font-family: 'YSBTH';
}
/* 图表内容区域样式 */
.chart-content {
height: 100%;
}
/* 暂无数据样式 */
.no-data {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
// 翻转过渡动画样式
.flip-wrapper {
position: relative;
width: 100%;
height: 100%;
perspective: 1000px;
}
.flip-enter-active,
.flip-leave-active {
transition: all 0.6s ease;
transform-style: preserve-3d;
}
.flip-enter-from {
transform: rotateY(90deg);
opacity: 0;
}
.flip-enter-to {
transform: rotateY(0deg);
opacity: 1;
}
.flip-leave-from {
transform: rotateY(0deg);
opacity: 1;
}
.flip-leave-to {
transform: rotateY(-90deg);
opacity: 0;
}
</style>

View File

@ -0,0 +1,216 @@
<template>
<div class="comom-cnt" >
<div class="zdryBox">
<ul class="ryBox" :infinite-scroll-distance="30" ref="carouselList" @mouseenter="stopAutoScroll" @mouseleave="startAutoScroll"
v-loading="loading" v-infinite-scroll="loadList">
<li v-for="item in personList" :key="item.id" @click="chooseItem(item)">
<div>{{ item.title }}</div>
<div class="meta-info">{{ item.time }}{{ item.fbrxm }}</div>
<div>{{ item.content }}</div>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
</ul>
<!-- 触底加载更多数据 -->
<div v-if="loadingMore" class="loading-more">加载中...</div>
</div>
</div>
</template>
<script setup>
import { tbGsxtXxltSelectPage } from '@/api/tbGsxtXxltHf'
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
import {useRouter} from 'vue-router'
import * as MOSTY from "@/components/MyComponents/index";
const router = useRouter()
const emit = defineEmits(["reversalPush"])
const reversalPush = () => {
emit('reversalPush')
}
// 数据相关
const personList = ref([]);
const loading = ref(false);
const loadingMore = ref(false);
const total = ref(0);
const pageNum = ref(1);
// 滚动相关
const carouselList = ref(null);
const isAutoScrolling = ref(false);
let scrollTimer = null;
// 获取数据
const getList = (type) => {
loading.value = !type ? true : false;
loadingMore.value = !!type;
tbGsxtXxltSelectPage({ pageSize: 10, pageCurrent: pageNum.value }).then(res => {
loading.value = false;
loadingMore.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(() => {
loading.value = false;
loadingMore.value = false;
})
};
// 触底加载
const loadList = () => {
if (personList.value.length == total.value || loadingMore.value) return;
pageNum.value++;
getList(true)
};
// 自动滚动函数
const autoScroll = () => {
if (!carouselList.value || !isAutoScrolling.value) return;
const container = carouselList.value;
const speed = 1; // 滚动速度
// 滚动容器
container.scrollTop += speed;
// 判断是否滚动到底部,如果是则回到顶部重新开始
if (container.scrollTop >= container.scrollHeight - container.clientHeight - 5) {
container.scrollTop = 0;
}
};
// 开始自动滚动
const startAutoScroll = () => {
if (isAutoScrolling.value || !carouselList.value) return;
isAutoScrolling.value = true;
// 清除可能存在的定时器
if (scrollTimer) {
clearInterval(scrollTimer);
}
// 设置新的定时器,控制滚动速度
scrollTimer = setInterval(autoScroll, 30);
};
// 停止自动滚动
const stopAutoScroll = () => {
isAutoScrolling.value = false;
if (scrollTimer) {
clearInterval(scrollTimer);
scrollTimer = null;
}
};
// 点击项
const chooseItem = (item) => {
stopAutoScroll(); // 点击时停止自动滚动
router.push({
path: '/forumPost',
query: { id: item.id }
})
};
// 添加跳转
const chooseForumPost = () => {
stopAutoScroll(); // 点击时停止自动滚动
router.push({ path: '/forumPost' })
};
// 生命周期
onMounted(() => {
getList();
// 数据加载完成后启动自动滚动
setTimeout(() => {
if (personList.value.length > 0) {
startAutoScroll();
}
}, 1000);
});
// 组件卸载前清除定时器
onBeforeUnmount(() => {
stopAutoScroll();
});
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.loading-more {
text-align: center;
padding: 8px;
color: #83bff6;
background: rgba(0, 0, 0, 0.3);
font-size: 12px;
}
.zdryBox {
height: 100%;
position: relative;
overflow: hidden;
.ryBox {
height: 100%;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
// 隐藏滚动条但保留滚动功能
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none; // IE和Edge
scrollbar-width: none; // Firefox
li {
padding: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background-color 0.3s;
cursor: pointer;
box-sizing: border-box;
&:hover {
background-color: rgba(20, 107, 190, 0.2);
}
> div:first-child {
font-weight: bold;
color: #fff;
margin-bottom: 8px;
font-size: 14px;
/* 标题限制1行超出用省略号 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.meta-info {
text-align: right;
color: #83bff6;
font-size: 12px;
margin-bottom: 8px;
}
> div:last-child {
color: rgba(255, 255, 255, 0.8);
font-size: 13px;
line-height: 1.6;
/* 内容限制3行超出用省略号 */
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
.switchover{
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
}
</style>

View File

@ -0,0 +1,215 @@
<template>
<div class="comom-cnt" >
<div class="zdryBox">
<ul class="ryBox" :infinite-scroll-distance="30" ref="carouselList" @mouseenter="stopAutoScroll" @mouseleave="startAutoScroll"
v-loading="loading" v-infinite-scroll="loadList">
<li v-for="item in personList" :key="item.id" @click="chooseItem(item)">
<div>{{ item.title }}</div>
<div class="meta-info">{{ item.time }}{{ item.fbrxm }}</div>
<div>{{ item.content }}</div>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
</ul>
<!-- 触底加载更多数据 -->
<div v-if="loadingMore" class="loading-more">加载中...</div>
</div>
</div>
</template>
<script setup>
import { tbGsxtXxltSelectPage } from '@/api/tbGsxtXxltHf'
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
import {useRouter} from 'vue-router'
import * as MOSTY from "@/components/MyComponents/index";
const router = useRouter()
const emit = defineEmits(["reversalPush"])
const reversalPush = () => {
emit('reversalPush')
}
// 数据相关
const personList = ref([]);
const loading = ref(false);
const loadingMore = ref(false);
const total = ref(0);
const pageNum = ref(1);
// 滚动相关
const carouselList = ref(null);
const isAutoScrolling = ref(false);
let scrollTimer = null;
// 获取数据
const getList = (type) => {
loading.value = !type ? true : false;
loadingMore.value = !!type;
tbGsxtXxltSelectPage({ pageSize: 10, pageCurrent: pageNum.value }).then(res => {
loading.value = false;
loadingMore.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(() => {
loading.value = false;
loadingMore.value = false;
})
};
// 触底加载
const loadList = () => {
if (personList.value.length == total.value || loadingMore.value) return;
pageNum.value++;
getList(true)
};
// 自动滚动函数
const autoScroll = () => {
if (!carouselList.value || !isAutoScrolling.value) return;
const container = carouselList.value;
const speed = 1; // 滚动速度
// 滚动容器
container.scrollTop += speed;
// 判断是否滚动到底部,如果是则回到顶部重新开始
if (container.scrollTop >= container.scrollHeight - container.clientHeight - 5) {
container.scrollTop = 0;
}
};
// 开始自动滚动
const startAutoScroll = () => {
if (isAutoScrolling.value || !carouselList.value) return;
isAutoScrolling.value = true;
// 清除可能存在的定时器
if (scrollTimer) {
clearInterval(scrollTimer);
}
// 设置新的定时器,控制滚动速度
scrollTimer = setInterval(autoScroll, 30);
};
// 停止自动滚动
const stopAutoScroll = () => {
isAutoScrolling.value = false;
if (scrollTimer) {
clearInterval(scrollTimer);
scrollTimer = null;
}
};
// 点击项
const chooseItem = (item) => {
stopAutoScroll(); // 点击时停止自动滚动
router.push({
path: '/forumPost',
query: { id: item.id }
})
};
// 添加跳转
const chooseForumPost = () => {
stopAutoScroll(); // 点击时停止自动滚动
router.push({ path: '/forumPost' })
};
// 生命周期
onMounted(() => {
getList();
// 数据加载完成后启动自动滚动
setTimeout(() => {
if (personList.value.length > 0) {
startAutoScroll();
}
}, 1000);
});
// 组件卸载前清除定时器
onBeforeUnmount(() => {
stopAutoScroll();
});
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.loading-more {
text-align: center;
padding: 8px;
color: #83bff6;
background: rgba(0, 0, 0, 0.3);
font-size: 12px;
}
.zdryBox {
height: 100%;
position: relative;
overflow: hidden;
.ryBox {
height: 100%;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
// 隐藏滚动条但保留滚动功能
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none; // IE和Edge
scrollbar-width: none; // Firefox
li {
padding: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background-color 0.3s;
cursor: pointer;
box-sizing: border-box;
&:hover {
background-color: rgba(20, 107, 190, 0.2);
}
> div:first-child {
font-weight: bold;
color: #fff;
margin-bottom: 8px;
font-size: 14px;
/* 标题限制1行超出用省略号 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.meta-info {
text-align: right;
color: #83bff6;
font-size: 12px;
margin-bottom: 8px;
}
> div:last-child {
color: rgba(255, 255, 255, 0.8);
font-size: 13px;
line-height: 1.6;
/* 内容限制3行超出用省略号 */
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
.switchover{
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
}
</style>