This commit is contained in:
lcw
2025-10-26 12:25:50 +08:00
parent 5e18952b55
commit ea3022c3f6
617 changed files with 86322 additions and 185615 deletions

View File

@ -1,22 +1,26 @@
<template>
<div class="warning-card ">
<div class="warning-card" :style="{'border':`1px solid ${changeBG(item.yjJb)}`}" >
<div class="warning-image flex">
<el-image style="width: 65px; height: 70px" :src="item.yjTp" :preview-src-list="[item.yjTp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2"/>
<img src="@/assets/images/default_male.png" width="65" height="70" v-else/>
</div>
<!-- -->
<template v-if="!item.yjTp || item.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</template>
</el-image>
<el-image v-else style="width: 65px; height: 70px" :src="item.yjTp" :preview-src-list="[item.yjTp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</div>
</template>
</el-image>
<div class="ml10 warning-info">
<div class="flex just-between align-center">
<div class="flex align-center mt4" v-if="item.yjLx == 2">
<span >{{ item.yjClcph }}</span>
</div>
<span>{{ item.yjClcph }}</span>
</div>
<div class="flex align-center mt4" v-else>
<span>{{ item.yjRyxm }}</span>
<span class="gapline mr10 ml10"></span>
@ -24,11 +28,11 @@
<span class="gapline mr10 ml10"></span>
<span>{{ IdCard(item.yjRysfzh, 3) }}</span>
</div>
<span class="tag" v-if="item.yjbqmc">{{ item.yjbqmc }}</span>
<span class="tag" v-if="item.yjbqmc" :style="{'background':`${changeBG(item.yjJb)}`}">{{ item.yjbqmc }}</span>
</div>
<div v-if="item.yjLx == 2" class="flex">车牌类型
<DictTag :tag="false" :value="item.yjHplx" color="#fff" :options="dict.D_BZ_HPZL" />
</div>
<div v-if="item.yjLx == 2" class="flex">车牌类型
<DictTag :tag="false" :value="item.yjHplx" color="#fff" :options="dict.D_BZ_HPZL"/>
</div>
<div class="mt4" v-else>身份证{{ item.yjRysfzh }}</div>
<div class="mt4 two_text_detail">预警时间{{ item.yjSj }}</div>
</div>
@ -40,7 +44,9 @@
<div class="mt4 two_text_detail">处置结果{{ item.yjNr }}</div>
</div>
<div class="warning-info pt5 ">
<div class="two_text_detail flex lh25"><img src="@/assets/images/ddtb.png" width="20" height="25" alt="" srcset="">{{ item.yjNr }}</div>
<div class="two_text_detail flex lh25"><img src="@/assets/images/ddtb.png" width="20" height="25" alt=""
srcset="">{{
item.yjNr }}</div>
</div>
</div>
</template>
@ -65,7 +71,7 @@ const changeBG = (str) => {
case "20":
return "orange";
case "30":
return "yellow";
return "#b5b522";
default: return "blue";
}
};
@ -73,8 +79,9 @@ const changeBG = (str) => {
<style lang="scss" scoped>
.warning-card {
background: url("~@/assets/images/xxxxxx.png") no-repeat center center;
// background: url("~@/assets/images/xxxxxx.png") no-repeat center center;
background-size: 100% 100%;
gap: 12px;
margin-bottom: 4px;
padding: 10px;
@ -129,8 +136,9 @@ const changeBG = (str) => {
width: 100%;
height: 100%;
}
.warning-boder{
border-bottom: 2px dashed #0958b2;
.warning-boder {
border-bottom: 2px dashed #0958b2;
}
}

View File

@ -1,20 +1,32 @@
<template>
<div class="warning-card flex align-center" :class="changeBG(item.yjJb)">
<div class="warning-image">
<el-image style="width: 80px; height:120px" :src="item.yjTp" :preview-src-list="[item.yjTp]" show-progress>
<template v-if="!item.yjTp || item.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</template>
<el-image v-else style="width: 80px; height:120px" :src="item.yjTp" :preview-src-list="[item.yjTp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</div>
</template>
</el-image>
<!-- <el-image style="width: 80px; height:120px" :src="item.yjTp" :preview-src-list="[item.yjTp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2"/>
<img src="@/assets/images/default_male.png" width="65" height="70" v-else/>
</div>
</template>
</el-image>
</el-image> -->
<!-- <img :src="item.yjTp" width="80" height="120" alt="" /> -->
</div>
<div class="warning-info">
<div class="flex just-between align-center">
<div class="flex align-center mt4" v-if="item.yjLx == 2">
<span >{{ item.yjClcph }}</span>
<span>{{ item.yjClcph }}</span>
</div>
<div class="flex align-center mt4" v-else>
<span>{{ item.yjRyxm }}</span>
@ -24,15 +36,24 @@
<span>{{ IdCard(item.yjRysfzh, 3) }}</span>
</div>
<span class="tag" v-if="item.yjbqmc">{{ item.yjbqmc }}</span>
<span class="tag" v-if="item.yjbqmc" :style="{ 'background': `${changeBG(item.yjJb)}` }">{{ item.yjbqmc }}</span>
</div>
<div v-if="item.yjLx == 2" class="flex">车牌类型
<DictTag :tag="false" :value="item.yjHplx" color="#fff" :options="dict.D_BZ_HPZL"/>
<div v-if="item.yjLx == 2" class="flex">车牌类型
<DictTag :tag="false" :value="item.yjHplx" color="#fff" :options="dict.D_BZ_HPZL" />
</div>
<div class="mt4" v-else>身份证{{ item.yjRysfzh }}</div>
<div class="mt4 two_text_detail">预警时间{{ item.yjSj }}</div>
<div class="mt4 one_text_detail">预警地址{{ item.yjDz }}</div>
<div class="mt4 two_text_detail">预警内容{{ item.yjNr }}</div>
<div class="mt4 two_text_detail">
<el-button type="primary">全息档案</el-button>
<el-button color="#ef7762" style="color: #fff;">转合成</el-button>
<el-button type="warning">转基管</el-button>
<el-button type="danger">转会商</el-button>
<el-button type="success">查看反馈</el-button>
<el-button type="success">轨迹上图</el-button>
</div>
</div>
</div>
</template>
@ -57,7 +78,7 @@ const changeBG = (str) => {
case "20":
return "orange";
case "30":
return "yellow";
return "#b5b522";
default: return "blue";
}
};

View File

@ -1,29 +1,25 @@
<template>
<DialogDragger title="预警详情" top="150px" v-model="props.show" @close="close">
<ul class="warningList" ref="gjyjList">
<li v-for="item in props.data" :key="item.id">
<YjItem :item="item" />
</li>
<MOSTY.Empty :show="props.data.length <= 0" :imgSize="150"></MOSTY.Empty>
</ul>
<!-- :style="{height: `calc(100vh - ${handleHs}px)`}" -->
<div style="position:relative;width: 100%;" :style="{ height: `calc(100vh - ${handleHs}px)` }">
<GdMap v-if="showMap"></GdMap>
<GdMap v-if="showMap" :mapKey="'home_yj_map'" :mapid="'homeYjMap'" />
</div>
</DialogDragger>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import GdMap from "@/components/GdMap/index.vue";
import DialogDragger from "@/views/home/layout/dialogDragger.vue";
import YjItem from "@/views/home/components/yjItem.vue";
import { ref, defineProps, onMounted, watch } from "vue";
import { ref, defineProps, onMounted, watch, getCurrentInstance } from "vue";
import emitter from "@/utils/eventBus.js";
const gjyjList = ref(null); //预警列表数据
const { proxy } = getCurrentInstance();
//参数传递
const props = defineProps({
//某条预警详情
@ -36,7 +32,6 @@ const props = defineProps({
default: false
},
});
console.log(props.show);
//关闭
function close() {
@ -48,23 +43,51 @@ onMounted(() => {
setTimeout(() => {
showMap.value = true
setTimeout(() => {
// 只删除一次home_yj_map区域的点避免影响其他地图
emitter.emit('deletePointArea', 'home_yj_map');
// 收集所有有效坐标的数据点
const validPoints = [];
for (let i = 0; i < props.data.length; i++) {
const item = props.data[i];
console.log(item);
// 修复重复的坐标判断条件
if (!item.jd || !item.wd) {
// 使用警告而不是return避免中断循环
console.warn("该预警没有坐标:", item);
continue;
}
validPoints.push(item);
}
emitter.emit('showHomeYJ', [item]);
emitter.emit('deletePointArea', 'home_yj_map');
if (!item.jd || !item.jd) return proxy.$message({ type: "warning", message: "该预警没有坐标!" });
let icon = require('@/assets/point/yj.png');
if (item.yjjb == '20') icon = require('@/assets/point/yj1.png');
if (item.yjjb == '30') icon = require('@/assets/point/yj2.png');
if (item.yjjb == '40') icon = require('@/assets/point/yj3.png');
emitter.emit('addPointArea', { flag: 'home_yj_map', icon, coords: [item] });
emitter.emit('setMapCenter', { location: [item.jd, item.wd], zoomLevel: 10 });
// 如果有有效点,显示第一条并添加所有点
if (validPoints.length > 0) {
// 只显示第一条数据的详情
emitter.emit('showHomeYJ', [validPoints[0]]);
// 为每个有效点添加标记
validPoints.forEach((item, index) => {
let icon = require('@/assets/point/yj.png');
if (item.yjjb == '20') icon = require('@/assets/point/yj1.png');
if (item.yjjb == '30') icon = require('@/assets/point/yj2.png');
if (item.yjjb == '40') icon = require('@/assets/point/yj3.png');
// 为每个点添加唯一标识,避免与其他地图冲突
emitter.emit('addPointArea', {
flag: `home_yj_map_${index}`,
baseFlag: 'home_yj_map',
icon,
coords: [item]
});
});
// 只设置一次地图中心(使用第一个有效点)
emitter.emit('setMapCenter', {
location: [validPoints[0].jd, validPoints[0].wd],
zoomLevel: 10,
flag: 'home_yj_map' // 添加标识,确保只影响当前地图
});
}
}, 500);
}, 200);
})
const handleHs = ref(0)

View File

@ -254,6 +254,10 @@ function lineChartFn(xDate, legend, series) {
transitionDuration: 0.2,
// 设置提示框位置
position: function (point, params, dom, rect, size) {
// console.log(point, params, dom, rect, size);
// 设置提示框的z-index为999确保显示在最上层
dom.style.zIndex = 999;
// 计算提示框位置,避免超出边界
let x = point[0] + 15;
let y = point[1] - 10;

View File

@ -1,11 +1,12 @@
<template>
<div class="homeBox">
<!-- <GdMap></GdMap> -->
<!-- 头部 -->
<Head></Head>
<!-- 左边 -->
<div class="home-aside asideL">
<div class="asideL-top">
<DbCount></DbCount>
</div>
<div class="asideL-Bottom">
@ -16,116 +17,175 @@
<QblyType></QblyType>
</div>
<div class="commom-aside">
<QbfkCount></QbfkCount>
<!-- <GroupWarning /> -->
<TextType></TextType>
<!-- <QbfkCount></QbfkCount> -->
</div>
</div>
</div>
<!-- 右边 -->
<div class="home-aside asideR">
<div class="commom-aside-big">
<SituationAssessment />
<Calendar />
</div>
<div class="commom-aside-big">
<GroupWarning />
<Experience />
</div>
<div class="commom-aside-small">
<Experience />
<SituationAssessment />
</div>
</div>
<!-- 中间 -->
<div class="home-center">
<div class="middle-top"><Yszs /></div>
<div class="flex middle-bottom mt10">
<div class="mr10" style="width: 50%;"><DeployControl /></div>
<div class="flex-1" style="flex: 1;"><ZdryWarning /></div>
<div class="middle-top">
<Yszs />
</div>
<div class="flex middle-bottom mt10">
<div style="width: 100%;border: 1px sienna;position: relative">
<GdMap></GdMap>
</div>
<div class="flex-1" style="width: 340px;position: absolute;z-index: 100;right: 0;">
<DeployControl />
</div>
<!-- <div class="mr10" style="width: 30%;"><DeployControl /></div> -->
<!-- <div class="flex-1" style="flex: 1;"><ZdryWarning /></div> -->
</div>
</div>
<!-- 底部 -->
<div class="home-foot-t">
<Bkcz></Bkcz>
</div>
</div>
<!-- 左边弹窗 -->
<LeftDialog></LeftDialog>
<Fxq :initial-position="{ x: position.x, y: position.y }">
<el-badge value="0" class="item badge-top-left">
<div class='fxq fxq1'>
<div class="title" @click.stop="opneMsg('xtxx')"> <img src="@/assets/images/xtxx.png" /> 系统消息</div>
</div>
</el-badge>
<!-- <div class='fxq fxq2'>
<div class="title" @click.stop="opneMsg('tztg')"> <img src="@/assets/images/tztg.png" /> 通知通报</div>
</div>
<div class='fxq fxq3'>
<div class="title"> <img src="@/assets/images/xxxt.png" /> 消息协同</div>
</div> -->
</Fxq>
<Information v-model='showDialog' :title='title'>
<systemMessages :dict="{ BD_D_XXLX, BD_D_XXLY }" :idEntityCard='idEntityCard' :xxlx="showMsgLx" />
</Information>
</template>
<script setup>
import { ref, getCurrentInstance, reactive } from 'vue'
import { ref, getCurrentInstance, reactive, onMounted } from 'vue'
import LeftDialog from './dialog/leftDialog'
import GdMap from "@/components/GdMap/index.vue";
import Head from './layout/head.vue'
import DbCount from './model/dbCount.vue'
import QbfkCount from './model/qbfkCount.vue'
import QbsbCount from './model/qbsbCount.vue'
import QblyType from './model/qblyType.vue'
import TextType from './model/textType.vue'
import Bkcz from './model/bkcz.vue'
import ZdryWarning from './model/zdryWarning.vue'
import GroupWarning from './model/groupWarning.vue'
import Yszs from './model/yszs.vue'
import DeployControl from './model/deployControl.vue';
import SituationAssessment from './model/situationAssessment.vue'
import Experience from './model/experience.vue'
import Fxq from './model/fxq.vue'
import Information from './model/information.vue'
import systemMessages from './model/mesgSwitch/systemMessages.vue'
import { getItem } from '@/utils/storage.js'
import { queryXxTj} from '@/api/commit.js'
const { proxy } = getCurrentInstance();
const { BD_D_XXLX, BD_D_XXLY } = proxy.$dict('BD_D_XXLX', 'BD_D_XXLY'); //获取字典数据
const idEntityCard = getItem('idEntityCard')
const position = reactive({
x: window.innerWidth - 120,
y: window.innerHeight - 100
})
import Calendar from './model/calendar.vue'
//消息
const title = ref('系统消息')
const showDialog = ref(false)
const showMsgLx = ref('')
const opneMsg = (val) => {
showDialog.value = true
showMsgLx.value = val
switch (val) {
case 'xtxx':
title.value = '系统消息'
break;
case 'tztg':
title.value = '通知通告'
break;
case 'xxxt':
title.value = '消息协同'
break;
import { getItem, setItem} from "@/utils/storage";
import emitter from "@/utils/eventBus.js";
import { bm ,centralPoint} from '@/views/backOfficeSystem/IntelligentControl/DeploymentArea/xzqh.js'
import SwitchSysDialog from '@/components/SwitchSysDialog.vue'
const changeXzqh = (val,trg) => {
setTimeout(() => {
// 先移除已有的边界
emitter.emit('removeBj')
if (trg) {
console.log("多个");
// 如果传入的是多个区域数据(二维数组)
const features = val.map((area, index) => ({
geometry: {
type: "Polygon",
coordinates: [area] // 确保格式正确
},
properties: {
},
type: "Feature"
}))
// 循环为每个区域创建单独的多边形,这样可以设置不同的样式
features.forEach((feature, index) => {
emitter.emit('setBoundarys', {
data: {
type: "FeatureCollection",
features: [feature]
},
color: '#cf1010',
fillColor: 'rgba(255, 255, 255,0)',
})
})
} else {
// 保持原来的逻辑,处理单个区域
emitter.emit('setBoundarys', {
data: {
type: "FeatureCollection",
features: [
{
geometry: {
type: "Polygon",
coordinates: [val] // 使用正确的GeoJSON格式
},
properties: {},
type: "Feature"
}
]
},
color: '#cf1010',
fillColor: 'rgba(255, 255, 255,0)',
})
}
}, 3000)
}
const getDepId = () => {
const deptId = getItem('deptId')
const deptLevel = deptId[0].deptLevel ? deptId[0].deptLevel : null
const deptCode = deptId[0].deptCode ? deptId[0].deptCode : null
if (deptLevel.startsWith('2')) {
const data = Object.values(bm).map(item => item);
changeXzqh(data,true)
} else {
switch (deptCode) {
case '54040200000'://巴宜区
changeXzqh(bm[542621])
break;
case '54042400000'://波密县
changeXzqh(bm[542625])
break;
case '54042500000'://察隅县
changeXzqh(bm[542626])
break;
case '54042100000'://工布江达县
changeXzqh(bm[542622])
break;
case '54042600000'://朗县
changeXzqh(bm[542627])
break;
case '54042200000'://米林县
changeXzqh(bm[542623])
break;
case '54042300000'://墨脱县
changeXzqh(bm[542624])
break;
default:
const data = Object.values(bm).map(item => item);
changeXzqh(data,true)
break;
}
}
}
const queryXxTjList = () => {
queryXxTj({}).then((res) => {
console.log(res);
}).catch((err) => {
});
const makerCenter = () => {
const dw = require("@/assets/point/dingwei.png")
const coords = centralPoint.map(item => {
return { jd: item.point[0], wd: item.point[1], jzMc: item.name }
})
emitter.emit("addPointArea", { coords, icon: dw, flag: "hm", size: '14px', showTitle: true, offset: [0, -25] });
}
queryXxTjList()
onMounted(() => {
getDepId()
makerCenter()
})
</script>
<style lang="scss" scoped>
@ -189,4 +249,36 @@ queryXxTjList()
left: -10px;
transform: translateY(-50%) translateX(-50%);
}
.badge-content {
display: flex;
flex-direction: column;
overflow: hidden;
transition: all 0.3s ease;
max-height: 200px;
/* 默认展开的最大高度 */
min-height: 45px;
/* 确保收缩时有足够空间显示第一个图标 */
}
.badge-content:not(.expanded) {
max-height: 45px;
}
/* 收缩时只显示第一个图标,隐藏其他内容 */
.badge-content:not(.expanded)> :not(:first-child) {
opacity: 0;
max-height: 0;
margin: 0;
padding: 0;
overflow: hidden;
}
.badge-container {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
</style>

View File

@ -156,8 +156,9 @@ onMounted(() => {
// 按钮切换
const handleBtns = (val) => {
btnsActive.value = val;
console.log(val);
btnsActive.value = val;
switch (val) {
case "智能布控":
router.push("/DeploymentArea");
@ -177,12 +178,7 @@ const handleBtns = (val) => {
// window.open(NPShref.href, "_blank");
break;
case "退出登录":
window.opener = null;
window.open('', '_self');
window.close();
store.commit("app/clearTag", null, { immediate: true });
store.commit("permission/deleteRouter", { immediate: true });
store.commit("user/deleteKeepLiiveRoute", "home");
store.dispatch("user/logout");
break;
}
};

View File

@ -7,7 +7,18 @@
<div class="comom-cnt" id="qcbk">
<MyTable @changePage="changePage" customClass="zdy_bkcz_table" :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight" :key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" >
<template #tp="{row}">
<img width="30" height="30" src="" alt="">
<!-- <img width="30" height="30" src="" alt=""> -->
<template v-if="!row.ryzp || row.ryzp.includes('baidu')">
<img src="@/assets/images/default_male.png" width="30" height="30" />
</template>
<el-image v-else :preview-teleported="true" style="width: 30px; height: 30px" :src="row.ryzp"
:preview-src-list="[row.ryzp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/default_male.png" width="30" height="30"/>
</div>
</template>
</el-image>
</template>
<template #ryXb="{row}">
<DictTag :tag="false" :value="row.ryXb" color="#fff" :options="D_BZ_XB"/>
@ -28,11 +39,11 @@
<template #qtLb="{row}">
<DictTag :value="row.qtLb" color="#fff" :options="D_GS_ZDQT_LB" />
</template>
</MyTable>
</div>
</template>
<script setup>
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import MyTable from "@/components/aboutTable/DarkTable.vue";
@ -135,8 +146,8 @@ const tabHeightFn = () => {
};
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
::v-deeep .comom-title{
@ -164,4 +175,4 @@ const tabHeightFn = () => {
color: #ffffff !important;
font-size: 15px;
}
</style>
</style>

View File

@ -0,0 +1,426 @@
<template>
<div class="comom-title" @click="calendarPush">
<span class="title">敏感节点</span>
</div>
<el-calendar ref="calendar" v-model="currentDate">
<template #header="{ date }">
<div>
<el-select size="small" @change="goToSelectedMonth" v-model="selectedYear"
style="width: 80px; margin-right: 10px;">
<el-option v-for="year in years" :key="year" :label="year + '年'" :value="year" />
</el-select>
<el-select size="small" @change="goToSelectedMonth" v-model="selectedMonth" style="width: 80px;">
<el-option v-for="month in months" :key="month.value" :label="month.label" :value="month.value" />
</el-select>
</div>
<div>
<el-button size="small" @click="selectDate('today')">今天</el-button>
</div>
</template>
<template #dateCell="{ data }">
<el-popover trigger="click" :width="400" title="敏感事件" popper-class="custom-sensitive-popover">
<!-- 日期信息区域 -->
<div class="date-info-section">
<div class="gan-date-item">
<span class="date-label">公历日期</span>
<span class="date-value">{{ getYearInGanDate(data) }}</span>
</div>
<div class="lunar-date-item">
<span class="date-label">农历日期</span>
<span class="date-value">农历 {{ getLunarMonthDay(data.date, true) }}({{ getYearInGanZhis(data) }})</span>
</div>
<div class="jieqi-date-item">
<span class="date-label">节气信息</span>
<span class="date-value jieqi-highlight">{{ getYearInGanjq(data) || '无' }}</span>
</div>
</div>
<!-- 敏感时间节点内容 -->
<div v-if="sensitiveNodes.length > 0" class="sensitive-content-popover">
<div v-for="(item, index) in sensitiveNodes" :key="index" class="sensitive-item-popover">
<div class="sensitive-date-popover">{{ item.jdrq }}</div>
<div class="sensitive-title-popover">{{ item.jdbt }}</div>
<div class="sensitive-desc-popover">{{ item.jdnr }}</div>
</div>
</div>
<div v-else class="sensitive-empty-popover">
暂无敏感事件
</div>
<template #reference>
<div @click="chooseDay(data)" class="dayonChage" :class="{
'day': dateVal == data.day,
'special': dataIntegration.includes(data.day)
}">
<span> {{ data.day.split("-")[2] }}</span>
<span style="font-size: 8px;"> {{ getLunarMonthDay(data.date) }}</span>
</div>
</template>
</el-popover>
</template>
</el-calendar>
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { Solar, Lunar } from 'lunar-javascript'
import { timeValidate } from "@/utils/tools";
import { useRouter } from 'vue-router'
import { tbGsxtMgjdSave, tbGsxtMgjdSelectList, tbGsxtMgjdUpdate, tbGsxtMgjdDelete } from "@/api/tbGsxtMgjd";
const dateVal = ref();
const router = useRouter()
// 获取农历月日
const getLunarMonthDay = (date, pd) => {
if (!date) return ''
const solar = Solar.fromDate(date)
const lunar = solar.getLunar()
if (pd) {
return `${lunar.getMonthInChinese()}${lunar.getDayInChinese()}`
} else {
return lunar.getJieQi() ? lunar.getJieQi() : lunar.getDayInChinese()
}
}
// 获取生效年
const getYearInGanZhis = (data) => {
const solar = Solar.fromDate(data.date)
const lunar = solar.getLunar()
return `${lunar.getYearInGanZhi()}${lunar.getMonthInGanZhiExact()}${lunar.getDayInGanZhi()}`
}
// 获取日期
const getYearInGanDate = (data) => {
const solar = Solar.fromDate(data.date)
return `${solar.getYear()}${solar.getMonth()}${solar.getDay()}日 星期${solar.getWeekInChinese()}`
}
// 获取节气
const getYearInGanjq = (data) => {
const solar = Solar.fromDate(data.date)
const lunar = solar.getLunar()
return lunar.getJieQi()
}
const selectedYear = ref();
const selectedMonth = ref('');
const calendar = ref(null)
// 生成年份选项前后10年
const years = computed(() => {
const currentYear = new Date().getFullYear();
const years = [];
for (let i = currentYear - 10; i <= currentYear + 10; i++) {
years.push(i);
}
return years;
});
// 月份选项
const months = ref([
{ label: '1月', value: 0 },
{ label: '2月', value: 1 },
{ label: '3月', value: 2 },
{ label: '4月', value: 3 },
{ label: '5月', value: 4 },
{ label: '6月', value: 5 },
{ label: '7月', value: 6 },
{ label: '8月', value: 7 },
{ label: '9月', value: 8 },
{ label: '10月', value: 9 },
{ label: '11月', value: 10 },
{ label: '12月', value: 11 }
]);
const chooseDay = (data) => {
dateVal.value = data.day
querySensitiveNodes()
}
// 敏感时间节点数据
const sensitiveNodes = ref([]);
// 查询敏感事件
const querySensitiveNodes = () => {
tbGsxtMgjdSelectList({ jdrq: dateVal.value }).then((res) => {
sensitiveNodes.value = res && res.length > 0 ? res : []
})
}
const currentDate = ref(new Date());
onMounted(() => {
initialize()
})
const goToSelectedMonth = () => {
if (selectedYear.value && selectedMonth.value !== '') {
const newDate = new Date(selectedYear.value, selectedMonth.value, 1);
currentDate.value = newDate;
dateVal.value = timeValidate(currentDate.value, 'ymd')
}
};
const selectDate = (val) => {
if (!calendar.value) return
dateVal.value = timeValidate(currentDate.value, 'ymd')
calendar.value.selectDate(val)
initialize()
}
// 获取当前时间
const initialize = () => {
const year = timeValidate(currentDate.value, 'yd')
const month = timeValidate(currentDate.value, 'ym')
dateVal.value = timeValidate(currentDate.value, 'ymd')
selectedYear.value = parseFloat(year)
selectedMonth.value = parseFloat(month) - 1
gettingData()
}
const dataIntegration = ref([])
// 获取当前月份的所有信息
const gettingData = () => {
const date = new Date(dateVal.value);
date.setDate(1)
const startTime = timeValidate(date.toLocaleDateString(), 'ymd')
date.setMonth(date.getMonth() + 1);
date.setDate(0);
const endTime = timeValidate(date.toLocaleDateString(), 'ymd')
const params = { startTime, endTime }
tbGsxtMgjdSelectList(params).then(res => {
if (res && res.length > 0) {
dataIntegration.value = [...new Set(res.map(item => item.jdrq))] ? [...new Set(res.map(item => item.jdrq))] : []
}
})
}
// 获取农历月日
// const getLunarMonthDay = (date) => {
// if (!date) return ''
// const solar = Solar.fromDate(date)
// const lunar = solar.getLunar()
// return `${lunar.getMonthInChinese()}${lunar.getDayInChinese()}`
// }
const calendarPush = () => {
router.push('/calendar')
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox {
background: #052249;
height: 100%;
padding: 10px;
.ryBox {
height: 100%;
overflow: hidden;
overflow-y: auto;
}
}
::-webkit-scrollbar {
background-color: #263b70;
}
::-webkit-scrollbar-thumb {
background-color: #146bbe;
}
::-webkit-scrollbar-track {
background-color: #263b70;
}
::-webkit-scrollbar-corner {
background-color: #142141;
}
::v-deep .el-calendar__header {
padding: 4px 20px !important;
color: #fff;
}
::v-deep .el-calendar__body {
padding: 3px 20px 35px !important;
}
::v-deep .el-calendar-table thead th {
padding: 4px 0 !important;
color: #fff;
}
::v-deep .el-calendar-table td.is-today {
color: #35ff02;
}
/* 敏感事件列表容器 */
.sensitive-content-popover {
padding: 12px;
overflow: auto;
max-height: 350px;
background-color: #fff;
}
/* 敏感事件项 */
.sensitive-item-popover {
margin-bottom: 16px;
padding: 12px;
background-color: #fafafa;
border-radius: 6px;
border-left: 4px solid #f56c6c;
transition: all 0.3s ease;
}
.sensitive-item-popover:hover {
background-color: #f5f7fa;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.sensitive-item-popover:last-child {
margin-bottom: 0;
}
/* 敏感事件日期 */
.sensitive-date-popover {
color: #909399;
font-size: 12px;
margin-bottom: 6px;
font-family: 'Courier New', monospace;
}
/* 敏感事件标题 */
.sensitive-title-popover {
font-weight: 600;
color: #303133;
margin-bottom: 8px;
font-size: 14px;
line-height: 1.4;
}
/* 敏感事件描述 */
.sensitive-desc-popover {
color: #606266;
font-size: 13px;
line-height: 1.6;
word-break: break-word;
}
/* 无敏感事件提示 */
.sensitive-empty-popover {
text-align: center;
padding: 30px 20px;
color: #909399;
font-size: 13px;
}
.sensitive-empty-popover:before {
content: "📅";
display: block;
font-size: 32px;
margin-bottom: 12px;
opacity: 0.5;
}
/* 日期信息区域样式 */
.date-info-section {
padding: 12px;
background-color: #f8f9fa;
border-radius: 6px;
margin-bottom: 10px;
border-left: 4px solid #409eff;
}
.gan-date-item,
.lunar-date-item,
.jieqi-date-item {
line-height: 28px;
display: flex;
margin-bottom: 4px;
}
.gan-date-item:last-child,
.lunar-date-item:last-child,
.jieqi-date-item:last-child {
margin-bottom: 0;
}
.date-label {
color: #606266;
font-size: 13px;
font-weight: 500;
min-width: 70px;
}
.date-value {
color: #303133;
font-size: 13px;
}
.jieqi-highlight {
color: #f56c6c;
font-weight: 500;
}
/* 自定义el-popover标题样式 */
.custom-sensitive-popover .el-popover__title {
background-color: #409eff;
color: white;
padding: 10px 15px;
margin: -1px -1px 0 -1px;
border-radius: 4px 4px 0 0;
font-size: 14px;
font-weight: 500;
}
/* 优化el-popover内容区域 */
.custom-sensitive-popover .el-popover__content {
padding: 0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* 优化日历单元格样式 */
.dayonChage {
position: relative;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.dayonChage:hover {
background-color: #ecf5ff;
}
.dayonChage.day {
background-color: #409eff;
color: white;
border-radius: 4px;
}
.dayonChage.special {
// background-color: #fef0f0;
border-radius: 4px;
}
.dayonChage.special.day {
background-color: #e6a23c;
color: white;
}
/* 修复日历单元格高度 */
::v-deep .el-calendar-day {
height: 35px !important;
padding: 5px !important;
text-align: center !important;
padding: 0 !important;
}
::v-deep .el-calendar-table:not(.is-range) td.prev,
::v-deep .el-calendar-table:not(.is-range) td.next {
color: #646464;
}
.day {
background-color: rgb(76, 134, 243);
color: #35ff02;
}
.special {
background-color: rgba(253, 112, 112, 0.856);
color: #ffffff;
}
</style>

View File

@ -1,10 +1,23 @@
<template>
<div class="comom-title">
<span class="title">线索研判盯办统计</span>
</div>
<el-popover placement="right" :width="430">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
</template>
<el-date-picker
v-model="value2"
type="datetimerange"
:shortcuts="shortcuts"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
</el-popover>
</div>
<ul class="comom-cnt xsBox flex flex-warp just-between align-center">
<li class="xs-item" v-for="(item, idx) in contentItem" :key="idx">
{{ item.label }}:{{ item.value }}
{{ item.label }}:{{ item.value }}
</li>
</ul>
</template>
@ -12,29 +25,61 @@
<script setup>
import { ref } from 'vue';
const contentItem = ref([
{label:'线索总数',value:'892'},
{label:'下发总数',value:'892'},
{label:'已处置总数',value:'892'},
{label:'反馈总数',value:'892'},
{label:'未反馈总数',value:'892'},
{label:'未处置总数',value:'892'},
{ label: '线索总数', value: '82' },
{ label: '下发总数', value: '82' },
{ label: '已处置总数', value: '80' },
{ label: '反馈总数', value: '50' },
{ label: '未反馈总数', value: '30' },
{ label: '未处置总数', value: '2' },
])
const value2 = ref([])
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.xsBox{
background: url("~@/assets/images/bg_12.png") no-repeat center center;
background-size: 100% 100%;
.xs-item{
width: 31%;
height: 36px;
line-height: 36px;
text-align: center;
background: url("~@/assets/images/content-item.png") no-repeat center center;
background-size: 100% 100%;
}
}
</style>
.xsBox {
background: url("~@/assets/images/bg_12.png") no-repeat center center;
background-size: 100% 100%;
.xs-item {
width: 31%;
height: 36px;
line-height: 36px;
text-align: center;
background: url("~@/assets/images/content-item.png") no-repeat center center;
background-size: 100% 100%;
}
}
</style>

View File

@ -1,14 +1,24 @@
<template>
<div class="comom-title">
<span class="title">布控预警</span>
<div class="title">预警列表</div>
<div class="expand-btn" @click="changeTab('deployControl')">
<el-icon size="20">
<ArrowDownBold v-if="isExpanded" />
<ArrowUpBold v-else />
</el-icon>
</div>
</div>
<div class="comom-cnt zdryBox">
<div style="height:33px;">
<div class=" zdryBox" v-show="isExpanded">
<div>
<CheckBox :data="checkDatas" @changeData="changeDatas"></CheckBox>
</div>
<div v-if="typeS">
<CheckBox :data="checkData" @changeData="changeData"></CheckBox>
</div>
<ul class="ryBox" ref="scrollTableRef" @mouseenter="stopAutoScroll" @mouseleave="startAutoScroll" v-loading="loading" v-infinite-scroll="loadList" >
<ul class="ryBox" ref="scrollTableRef" @mouseenter="stopAutoScroll" @mouseleave="startAutoScroll"
v-loading="loading" v-infinite-scroll="loadList">
<li v-for="item in personList" :key="item.id" @click="chooseItem(item)">
<DeployControlItem :item="item" :dict="{D_BZ_HPZL}"/>
<DeployControlItem :item="item" :dict="{ D_BZ_HPZL }" />
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
</ul>
@ -21,172 +31,267 @@ import { qcckPost } from "@/api/qcckApi.js";
import DeployControlItem from "@/views/home/components/deployControlItem.vue";
import * as MOSTY from "@/components/MyComponents/index";
import CheckBox from "@/components/checkBox/index.vue";
import { ref ,reactive, onMounted,onUnmounted,getCurrentInstance} from 'vue';
import { ref, reactive, onMounted, onUnmounted, getCurrentInstance } from 'vue';
import { ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue';
const { proxy } = getCurrentInstance();
const {D_BZ_HPZL} =proxy.$dict('D_BZ_HPZL')
const { D_BZ_HPZL } = proxy.$dict('D_BZ_HPZL')
const checkData = reactive({
list: ["一级", "二级", "三级", "四级"],
hasChoose: ["一级", "二级", "三级", "四级"]
});
const checkDatas = reactive({
list: ["布控", "行为", "身份", "组合"],
hasChoose: ["布控", "行为", "身份", "组合"]
});
const total = ref(0);
const yjJb = ref('10,20,30,40');
const pageNum = ref(1);
const loading = ref(false); // 加载中
const personList = ref([]);
const scrollTableRef = ref(null) // 滚动元素区域
let isAutoScrolling = true // 是否自动滚动
const intervalId = ref(null) //定时器
onMounted(()=>{
getList()
autoScroll()
})
onUnmounted(() => {
if (intervalId.value) clearInterval(intervalId.value)// 清理定时器
stopAutoScroll()
})
// 自动滚动
const autoScroll = () => {
if(personList.value.length==0){return}
intervalId.value = setInterval(() => {
if (!isAutoScrolling) return
const scrollTableEl = scrollTableRef.value
scrollTableEl.scrollTop += 1 // 垂直滚动距离
let scrollTop = scrollTableEl.scrollTop;
let scrollHeight = scrollTableEl.scrollHeight;
let offsetHeight = Math.ceil(scrollTableEl.getBoundingClientRect().height);
let currentHeight = scrollTop + offsetHeight;
if (currentHeight >= scrollHeight) { // 到底部
if(personList.value.length == total.value){
scrollTableEl.scrollTop = 0;
}else{
pageNum.value++;
getList('load')
}
const scrollTableRef = ref(null);
const isAutoScrolling = ref(false);
let scrollTimer = null;
onMounted(() => {
getList();
// 数据加载完成后启动自动滚动
setTimeout(() => {
if (personList.value.length > 0) {
startAutoScroll();
}
}, 100)
}
// 停止滚动
const stopAutoScroll = () => {
isAutoScrolling = false
}
// 开始滚动
const startAutoScroll = () => {
isAutoScrolling = true
autoScroll()
}
}, 1000);
})
// 复选框切换
function changeData(val){
function changeData(val) {
pageNum.value = 1;
personList.value = [];
checkData.hasChoose = val;
let ids = [];
val.forEach(it => {
if(it == '一级') ids.push(10);
if(it == '二级') ids.push(20);
if(it == '三级') ids.push(30);
if(it == '四级') ids.push(40);
if (it == '一级') ids.push(10);
if (it == '二级') ids.push(20);
if (it == '三级') ids.push(30);
if (it == '四级') ids.push(40);
});
yjJb.value = ids.join(',')
if(val.length == 0) personList.value = [];
if (val.length == 0) personList.value = [];
else getList();
}
const typeS=ref(true)
function changeDatas(val) {
console.log(val);
console.log(val.includes('布控'));
pageNum.value = 1;
personList.value = [];
checkDatas.hasChoose = val;
let ids = [];
if (val.includes('布控')) {
typeS.value=true
} else {
typeS.value=false
}
val.forEach(it => {
if (it == '布控') {
ids.push(10)
typeS.value=true
};
if (it == '行为') ids.push(20);
if (it == '身份') ids.push(30);
if (it == '组合') ids.push(40);
});
yjJb.value = ids.join(',')
if (val.length == 0) personList.value = [];
else getList();
}
const isExpanded = ref(true); // 控制展开/收缩状态
const changeTab = () => {
// 切换展开/收缩状态
isExpanded.value = !isExpanded.value;
// 如果是收缩状态,停止自动滚动
if (!isExpanded.value) {
stopAutoScroll();
} else if (personList.value.length > 0) {
// 如果是展开状态并且有数据,启动自动滚动
startAutoScroll();
}
}
// 自动滚动函数
const autoScroll = () => {
if (!scrollTableRef.value || !isAutoScrolling.value) return;
const container = scrollTableRef.value;
const speed = 1; // 滚动速度
// 滚动容器
container.scrollTop += speed;
// 判断是否滚动到底部,如果是则回到顶部重新开始
if (container.scrollTop >= container.scrollHeight - container.clientHeight - 5) {
container.scrollTop = 0;
}
};
// 开始自动滚动
const startAutoScroll = () => {
if (isAutoScrolling.value || !scrollTableRef.value) return;
isAutoScrolling.value = true;
// 清除可能存在的定时器
if (scrollTimer) {
clearInterval(scrollTimer);
}
// 设置新的定时器,控制滚动速度
scrollTimer = setInterval(autoScroll, 30);
};
// 停止自动滚动
const stopAutoScroll = () => {
isAutoScrolling.value = false;
if (scrollTimer) {
clearInterval(scrollTimer);
scrollTimer = null;
}
};
onUnmounted(() => {
// 组件卸载时清理定时器
stopAutoScroll();
});
// 触底加载
const loadList = () =>{
if( personList.value.length == total.value) return;
const loadList = () => {
if (personList.value.length == total.value) return;
pageNum.value++;
getList()
}
const getList = (type) =>{
let data = { pageSize:10, pageNum:pageNum.value,yjJb:yjJb.value ,bkyj:1};
const getList = (type) => {
let data = { pageSize: 10, pageNum: pageNum.value, yjJb: yjJb.value, bkyj: 1 };
loading.value = !type ? true : false;
qcckPost(data,'/mosty-gsxt/tbYjxx/getPageList').then(res=>{
qcckPost(data, '/mosty-gsxt/tbYjxx/getPageList').then(res => {
loading.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(()=>{
}).catch(() => {
loading.value = false;
})
}
const chooseItem = (item) =>{
emitter.emit('showHomeYJ',[item]);
emitter.emit('deletePointArea','home_yj_map');
if(!item.jd || !item.jd) return proxy.$message({ type: "warning", message: "该预警没有坐标!" });
let icon = require('@/assets/point/yj.png');
if(item.yjjb == '20') icon = require('@/assets/point/yj1.png');
if(item.yjjb == '30') icon = require('@/assets/point/yj2.png');
if(item.yjjb == '40') icon = require('@/assets/point/yj3.png');
emitter.emit('addPointArea',{flag:'home_yj_map',icon,coords:[item]});
emitter.emit('setMapCenter',{location:[item.jd,item.wd],zoomLevel:10});
const chooseItem = (item) => {
emitter.emit('showHomeYJ', [item]);
// emitter.emit('deletePointArea','home_yj_map');
// if(!item.jd || !item.jd) return proxy.$message({ type: "warning", message: "该预警没有坐标!" });
// let icon = require('@/assets/point/yj.png');
// if(item.yjjb == '20') icon = require('@/assets/point/yj1.png');
// if(item.yjjb == '30') icon = require('@/assets/point/yj2.png');
// if(item.yjjb == '40') icon = require('@/assets/point/yj3.png');
// emitter.emit('addPointArea',{flag:'home_yj_map',icon,coords:[item]});
// emitter.emit('setMapCenter',{location:[item.jd,item.wd],zoomLevel:10});
}
</script>
<style>
.el-loading-mask{
background: rgba(0,0,0,0.5);
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox{
.zdryBox {
background: #052249;
height: 100%;
.ryBox{
height: calc(100% - 33px);
height: 560px;
.ryBox {
height: calc(100% - 80px);
overflow: hidden;
overflow-y: auto;
}
}
::v-deep .el-checkbox {
margin-right: 10px;
}
::-webkit-scrollbar {
background-color: #263b70;
}
::-webkit-scrollbar-thumb {
background-color: #146bbe;
}
::-webkit-scrollbar-track {
background-color: #263b70;
}
::-webkit-scrollbar-corner {
background-color: #142141;
}
::v-deep .el-checkbox__label{
color:#fff;
::v-deep .el-checkbox__label {
color: #fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label{
color:#00FFFF;
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label {
color: #00FFFF;
}
::v-deep .el-checkbox__inner{
background:rgba(0,144,255,0.2);
border:1px solid #0072FF;
::v-deep .el-checkbox__inner {
background: rgba(0, 144, 255, 0.2);
border: 1px solid #0072FF;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner{
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #00FFFF;
border-color:#00FFFF;
border-color: #00FFFF;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner{
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: #00FFFF;
border-color:#00FFFF;
border-color: #00FFFF;
}
::v-deep .el-checkbox__inner::after{
border:2px solid #000;
border-left:0;
border-top:0;
left:3px;
top:0px;
::v-deep .el-checkbox__inner::after {
border: 2px solid #000;
border-left: 0;
border-top: 0;
left: 3px;
top: 0px;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner::before{
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner::before {
background: #000;
}
.comom-title {
display: flex;
justify-content: space-between;
align-items: center;
}
.expand-btn {
display: flex;
align-items: center;
justify-content: center;
// background: linear-gradient(135deg, #0072FF 0%, #00B4FF 100%);
// border-radius: 50%;
color: white;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 114, 255, 0.3);
}
.expand-btn:hover {
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(0, 114, 255, 0.5);
}
.expand-btn:active {
transform: scale(0.95);
}
</style>

View File

@ -0,0 +1,144 @@
<template>
<div class="comom-title">
<span class="title">经验分享</span>
</div>
<div class="comom-cnt zdryBox">
<!-- <ul class="ryBox" v-loading="loading" v-infinite-scroll="loadList" style="overflow: auto">
<li v-for="item in personList" :key="item.id" >
<Assessment :item="item" :dict="{D_GS_ZDQT_LB,D_BZ_TYJB}" :lx="3"/>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
</ul> -->
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import { qcckPost } from "@/api/qcckApi.js";
import Assessment from "@/views/home/components/assessmentItem.vue";
import * as MOSTY from "@/components/MyComponents/index";
import CheckBox from "@/components/checkBox/index.vue";
import { ref ,reactive, onMounted,getCurrentInstance} from 'vue';
const { proxy } = getCurrentInstance();
const {D_GS_ZDQT_LB,D_BZ_TYJB} =proxy.$dict('D_GS_ZDQT_LB','D_BZ_TYJB')
const checkData = reactive({
list: ["人员", "车辆"],
hasChoose: ["人员", "车辆"],
});
const total = ref(0);
const yjJb = ref('10,20,30,40');
const pageNum = ref(1);
const loading = ref(false); // 加载中
const personList = ref([]);
onMounted(()=>{
getList()
})
// 复选框切换
function changeData(val){
pageNum.value = 1;
personList.value = [];
checkData.hasChoose = val;
let ids = [];
val.forEach(it => {
if(it == '人员') ids.push(1);
if(it == '车辆') ids.push(2);
});
yjJb.value = ids.join(',')
if(val.length == 0) personList.value = [];
else getList();
}
// 触底加载
const loadList = () =>{
if( personList.value.length == total.value) return;
pageNum.value++;
getList()
}
const getList = () =>{
let data = { pageSize:10, pageCurrent:pageNum.value };
loading.value = true;
qcckPost(data,'/mosty-gsxt/gsxt/jyfx/selectPage').then(res=>{
loading.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(()=>{
loading.value = false;
})
}
const chooseItem = (item) =>{
emitter.emit('showHomeYJ',[item]);
emitter.emit('deletePointArea','home_yj_map');
if(!item.jd || !item.jd) return proxy.$message({ type: "warning", message: "该预警没有坐标!" });
let icon = require('@/assets/point/yj.png');
if(item.yjjb == '20') icon = require('@/assets/point/yj1.png');
if(item.yjjb == '30') icon = require('@/assets/point/yj2.png');
if(item.yjjb == '40') icon = require('@/assets/point/yj3.png');
emitter.emit('addPointArea',{flag:'home_yj_map',icon,coords:[item]});
emitter.emit('setMapCenter',{location:[item.jd,item.wd],zoomLevel:10});
}
</script>
<style>
.el-loading-mask{
background: rgba(0,0,0,0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox{
background: #052249;
height: 100%;
.ryBox{
height: 100%;
overflow: hidden;
overflow-y: auto;
}
}
::-webkit-scrollbar {
background-color: #263b70;
}
::-webkit-scrollbar-thumb {
background-color: #146bbe;
}
::-webkit-scrollbar-track {
background-color: #263b70;
}
::-webkit-scrollbar-corner {
background-color: #142141;
}
::v-deep .el-checkbox__label{
color:#fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label{
color:#00FFFF;
}
::v-deep .el-checkbox__inner{
background:rgba(0,144,255,0.2);
border:1px solid #0072FF;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner{
background-color: #00FFFF;
border-color:#00FFFF;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner{
background-color: #00FFFF;
border-color:#00FFFF;
}
::v-deep .el-checkbox__inner::after{
border:2px solid #000;
border-left:0;
border-top:0;
left:3px;
top:0px;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner::before{
background: #000;
}
</style>

View File

@ -1,144 +1,192 @@
<template>
<div class="comom-title">
<span class="title">经验分享</span>
<div class="comom-title" @click="chooseForumPost">
<span class="title">情报论坛</span>
</div>
<div class="comom-cnt zdryBox">
<ul class="ryBox" v-loading="loading" v-infinite-scroll="loadList" style="overflow: auto">
<li v-for="item in personList" :key="item.id" >
<Assessment :item="item" :dict="{D_GS_ZDQT_LB,D_BZ_TYJB}" :lx="3"/>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
</ul>
<div class="comom-cnt" style="height: 300px;">
<div class="zdryBox">
<div class="carousel-container"
@mouseenter="pauseCarousel"
@mouseleave="startCarousel">
<ul class="ryBox" ref="carouselList">
<li v-for="item in displayList" :key="item.id" @click="chooseItem(item)">
<div>{{ item.title }}</div>
<div class="meta-info">{{ item.time }}{{ item.fbrxm }}</div>
<div>{{ item.content }}</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import { qcckPost } from "@/api/qcckApi.js";
import Assessment from "@/views/home/components/assessmentItem.vue";
import * as MOSTY from "@/components/MyComponents/index";
import CheckBox from "@/components/checkBox/index.vue";
import { ref ,reactive, onMounted,getCurrentInstance} from 'vue';
const { proxy } = getCurrentInstance();
const {D_GS_ZDQT_LB,D_BZ_TYJB} =proxy.$dict('D_GS_ZDQT_LB','D_BZ_TYJB')
const checkData = reactive({
list: ["人员", "车辆"],
hasChoose: ["人员", "车辆"],
});
const total = ref(0);
const yjJb = ref('10,20,30,40');
const pageNum = ref(1);
const loading = ref(false); // 加载中
import { tbGsxtXxltSelectPage } from '@/api/tbGsxtXxltHf'
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
import {useRouter} from 'vue-router'
const router = useRouter()
// 数据相关
const personList = ref([]);
onMounted(()=>{
getList()
})
// 复选框切换
function changeData(val){
pageNum.value = 1;
personList.value = [];
checkData.hasChoose = val;
let ids = [];
val.forEach(it => {
if(it == '人员') ids.push(1);
if(it == '车辆') ids.push(2);
});
yjJb.value = ids.join(',')
if(val.length == 0) personList.value = [];
else getList();
}
const displayList = ref([]); // 用于显示的数据列表
const loading = ref(false);
// 触底加载
const loadList = () =>{
if( personList.value.length == total.value) return;
pageNum.value++;
getList()
}
// 轮播相关
const carouselList = ref(null);
const scrollTimer = ref(null);
const scrollSpeed = ref(3000); // 滚动间隔时间(ms)
const itemHeight = ref(106); // 每个item的高度(px)
const currentIndex = ref(0);
const getList = () =>{
let data = { pageSize:10, pageCurrent:pageNum.value };
// 获取数据
const getList = () => {
loading.value = true;
qcckPost(data,'/mosty-gsxt/gsxt/jyfx/selectPage').then(res=>{
tbGsxtXxltSelectPage({ pageSize: 10, pageCurrent: 1 }).then(res => {
loading.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(()=>{
personList.value = res.records || [];
// 复制一份数据到displayList实现无缝滚动效果
displayList.value = [...personList.value, ...personList.value];
}).catch(() => {
loading.value = false;
})
}
};
const chooseItem = (item) =>{
emitter.emit('showHomeYJ',[item]);
emitter.emit('deletePointArea','home_yj_map');
if(!item.jd || !item.jd) return proxy.$message({ type: "warning", message: "该预警没有坐标!" });
let icon = require('@/assets/point/yj.png');
if(item.yjjb == '20') icon = require('@/assets/point/yj1.png');
if(item.yjjb == '30') icon = require('@/assets/point/yj2.png');
if(item.yjjb == '40') icon = require('@/assets/point/yj3.png');
emitter.emit('addPointArea',{flag:'home_yj_map',icon,coords:[item]});
emitter.emit('setMapCenter',{location:[item.jd,item.wd],zoomLevel:10});
}
// 开始轮播
const startCarousel = () => {
if (scrollTimer.value) return;
scrollTimer.value = setInterval(() => {
scrollToNext();
}, scrollSpeed.value);
};
// 暂停轮播
const pauseCarousel = () => {
if (scrollTimer.value) {
clearInterval(scrollTimer.value);
scrollTimer.value = null;
}
};
// 滚动到下一项
const scrollToNext = () => {
if (!carouselList.value || personList.value.length === 0) return;
currentIndex.value++;
// 实现平滑滚动
const scrollHeight = currentIndex.value * itemHeight.value;
carouselList.value.style.transition = 'transform 0.5s ease-out';
carouselList.value.style.transform = `translateY(-${scrollHeight}px)`;
// 当滚动到复制的数据部分时,重置位置实现无缝滚动
if (currentIndex.value >= personList.value.length) {
setTimeout(() => {
currentIndex.value = 0;
carouselList.value.style.transition = 'none';
carouselList.value.style.transform = 'translateY(0)';
}, 500);
}
};
// 点击项
const chooseItem = (item) => {
pauseCarousel(); // 点击时暂停轮播
router.push({
path: '/forumPost',
query: { id: item.id }
})
};
// 添加跳转
const chooseForumPost = () => {
pauseCarousel(); // 点击时暂停轮播
router.push({ path: '/forumPost' })
};
// 生命周期
onMounted(() => {
getList();
// 数据加载后开始轮播
setTimeout(() => {
startCarousel();
}, 1000);
});
// 组件卸载前清除定时器
onBeforeUnmount(() => {
pauseCarousel();
});
</script>
<style>
.el-loading-mask{
background: rgba(0,0,0,0.5);
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox{
background: #052249;
.zdryBox {
height: 100%;
.ryBox{
position: relative;
overflow: hidden;
.carousel-container {
height: 100%;
overflow: hidden;
overflow-y: auto;
position: relative;
}
.ryBox {
position: absolute;
top: 0;
left: 0;
width: 100%;
margin: 0;
padding: 0;
list-style: none;
li {
padding: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background-color 0.3s;
cursor: pointer;
&: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;
}
}
}
}
::-webkit-scrollbar {
background-color: #263b70;
}
::-webkit-scrollbar-thumb {
background-color: #146bbe;
}
::-webkit-scrollbar-track {
background-color: #263b70;
}
::-webkit-scrollbar-corner {
background-color: #142141;
}
::v-deep .el-checkbox__label{
color:#fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label{
color:#00FFFF;
}
::v-deep .el-checkbox__inner{
background:rgba(0,144,255,0.2);
border:1px solid #0072FF;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner{
background-color: #00FFFF;
border-color:#00FFFF;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner{
background-color: #00FFFF;
border-color:#00FFFF;
}
::v-deep .el-checkbox__inner::after{
border:2px solid #000;
border-left:0;
border-top:0;
left:3px;
top:0px;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner::before{
background: #000;
}
</style>

View File

@ -0,0 +1,56 @@
<template>
<div class="custom-iframe-dialog-container">
<el-dialog :model-value="modelValue" width="70%" :before-close="close" :destroy-on-close="true"
class="custom-iframe-dialog" top="6vh">
<div style="height: 70vh;">
<iframe :src="src" frameborder="0" width="100%" height="100%"></iframe>
</div>
</el-dialog>
</div>
</template>
<script setup>
import { ref } from 'vue'
const props = defineProps({
modelValue: {
type: Boolean,
required: true
}, title: {
type: String,
default: '提示'
}, showFooter: {
type: Boolean,
default: true
}, src: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:modelValue', 'submit', 'close'])
const close = () => {
emit('update:modelValue', false)
emit('close')
}
const submit = () => {
emit('submit')
}
</script>
<style lang="scss" scoped>
/* 使用自定义类名直接应用样式 */
.custom-iframe-dialog {
margin-top: 6vh !important;
background-color: transparent !important;
}
::deep(.el-dialog) {
background-color: rgba(0, 255, 255, 0);
}
/* 同时确保wrapper的正确布局 */
:deep(.el-dialog__wrapper) {
display: flex !important;
align-items: flex-start !important;
justify-content: center !important;
}
</style>

View File

@ -1,7 +1,20 @@
<template>
<div class="comom-title">
<span class="title">情报来源类型</span>
</div>
<el-popover placement="right" :width="430">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
</template>
<el-date-picker
v-model="value2"
type="datetimerange"
:shortcuts="shortcuts"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
</el-popover>
</div>
<div class="comom-cnt">
<BarHatEcharts echartsId="qbltBox" :autoTooltip="true" :data="list"></BarHatEcharts>
</div>
@ -10,7 +23,7 @@
<script setup>
import { qcckPost } from "@/api/qcckApi.js";
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted, reactive } from "vue";
import { onMounted, reactive ,ref} from "vue";
const list = reactive({
xDate: ['110警情','人力情报','系统采集','民警处置单'],
list:[
@ -29,7 +42,36 @@ const getCount = () =>{
list.list[1].value = res ? res.cz.map(v=>v.count):[];
})
}
const value2 = ref([])
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
</script>
@ -40,4 +82,4 @@ const getCount = () =>{
background: rgba(0,29,75,0.6);
border-radius: 0 0 4px 4px;
}
</style>
</style>

View File

@ -1,42 +1,87 @@
<template>
<div class="comom-title">
<span class="title">情报上报数量统计</span>
</div>
<el-popover placement="right" :width="430">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
</template>
<el-date-picker v-model="listQuery" type="datetimerange" :shortcuts="shortcuts" range-separator="至"
start-placeholder="开始时间" value-format="YYYY-MM-DD HH:mm:ss"
format="YYYY-MM-DD HH:mm:ss" end-placeholder="结束时间" @change="changeTime" />
</el-popover>
</div>
<div class="comom-cnt qxsbBox">
<LineEcharts echartsId="qbsbEcharts" :data="dataList"></LineEcharts>
<LineEcharts echartsId="qbsbEcharts" :data="dataList"></LineEcharts>
</div>
</template>
<script setup>
import { qcckPost } from "@/api/qcckApi.js";
import LineEcharts from "../echarts/moreLineEcharts.vue";
import { reactive, onMounted } from 'vue';
import { reactive, onMounted, ref } from 'vue';
const dataList = reactive({
xData:['巴宜区','工布江达县','米林县','墨脱县','波密县','察隅县','朗县'],
color:['#0386FB','#00FFFF'],
list:[
{label:'总数',val:[0,0,0,0,0,0,0]},
{label:'已处置',val:[0,0,0,0,0,0,0]},
xData: ['巴宜区', '工布江达县', '米林县', '墨脱县', '波密县', '察隅县', '朗县'],
color: ['#0386FB', '#00FFFF'],
list: [
{ label: '总数', val: [0, 0, 0, 0, 0, 0, 0] },
{ label: '已处置', val: [0, 0, 0, 0, 0, 0, 0] },
]
});
onMounted(() => {
getCount()
});
const getCount = () =>{
qcckPost({},'/mosty-gsxt/qbcj/getXscjTjForQx').then(res=>{
dataList.xDate = res ? res.ycz.map(v=> v.org_name):[];
dataList.list[0].val = res ? res.zs.map(v=>v.count):[];
dataList.list[1].val = res ? res.ycz.map(v=>v.count):[];
const listQuery = ref()
const getCount = () => {
const promes = {
startTime: listQuery.value ? listQuery.value[0] : "",
endTime: listQuery.value ? listQuery.value[1] : ""
}
qcckPost(promes, '/mosty-gsxt/qbcj/getXscjTjForQx').then(res => {
dataList.xDate = res ? res.ycz.map(v => v.org_name) : [];
dataList.list[0].val = res ? res.zs.map(v => v.count) : [];
dataList.list[1].val = res ? res.ycz.map(v => v.count) : [];
})
}
const changeTime = () => {
console.log(listQuery.value);
getCount()
}
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
</style>
</style>

View File

@ -0,0 +1,87 @@
<template>
<div class="comom-title">
<span class="title">情报文本类型</span>
<el-popover placement="right" :width="430">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
</template>
<el-date-picker
v-model="value2"
type="datetimerange"
:shortcuts="shortcuts"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
</el-popover>
</div>
<div class="comom-cnt" >
<BarHatEcharts echartsId="qbltBoxs" :autoTooltip="true" :data="list" ></BarHatEcharts>
</div>
</template>
<script setup>
import { qcckPost } from "@/api/qcckApi.js";
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted, reactive ,ref} from "vue";
const list = reactive({
xDate: ['上访','诈骗','敲诈勒索','盗窃'],
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' },
],
})
onMounted(() => {
getCount()
});
const getCount = () => {
// list.list[0].value =[0,0,0,0]
// qcckPost({},'/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):[];
// })
}
const value2 = ref([])
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.qbltBox {
height: 100%;
background: rgba(0,29,75,0.6);
border-radius: 0 0 4px 4px;
}
</style>

View File

@ -4,7 +4,7 @@
<div class="mr10"><img :src="item.icon" alt=""></div>
<div class="vountItem">
<div style="color:#ffffff" class="f16 lh20">{{ item.label }}</div>
<div class="mt4 f12" style="color: #ffffff;">{{ item.value }}</div>
<div class="mt4 f12" style="color: #ffffff;font-size: 24px;">{{ item.value }}</div>
</div>
</div>
</div>
@ -14,10 +14,10 @@
import { qcckPost } from "@/api/qcckApi.js";
import { ref, onMounted } from "vue";
const contentItem = ref([
{ type:"xs", label: "线索总数", value: "0" ,icon:require('@/assets/images/top-1.png')},
{ type:"xscz", label: "已处置线索总数", value: "0",icon:require('@/assets/images/top-2.png') },
{ type:"zdry", label: "重点人总数", value: "0",icon:require('@/assets/images/top-3.png') },
{ type:"zdqt", label: "重点群体总数", value: "0" ,icon:require('@/assets/images/top-4.png')},
{ type:"xs", label: "警情总数", value: "0" ,icon:require('@/assets/images/top-1.png')},
{ type:"xscz", label: "预警总数", value: "0",icon:require('@/assets/images/top-2.png') },
{ type:"zdry", label: "案件总数", value: "0",icon:require('@/assets/images/top-3.png') },
{ type:"zdqt", label: "舆情总数", value: "0" ,icon:require('@/assets/images/top-4.png')},
]);
onMounted(() => {