Files
dy_app/src/pages/yyzx/views/wzzxIndex.vue
2025-09-04 16:35:14 +08:00

741 lines
18 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>
<div class="containerBox" style="padding-top: 13vw">
<TopNav navTitle="位置中心" />
<div class="main">
<!-- 位置统计 -->
<div class="contant">
<div class="header">
<span>
<van-icon name="friends" size="20px" color="#3e6ee8"></van-icon>
<span class="title">实时巡组</span>
</span>
</div>
<ItemList title="今日" :list="dayList" />
<ItemList title="近一周" :list="weekList" />
<ItemList title="近一月" :list="monthList" />
</div>
<!-- 实时巡组 -->
<div class="contant">
<div class="header">
<span>
<van-icon name="friends" size="20px" color="#3e6ee8"></van-icon>
<span class="title">实时巡组</span>
</span>
<div class="callAll" style="font-size: 10px">全部呼叫</div>
</div>
<div class="select_box">
<div>
<van-checkbox-group
v-model="checked"
direction="horizontal"
@change="onChangeXfzt"
>
<van-checkbox
icon-size="16"
shape="square"
:name="item.name"
v-for="(item, index) in checkList"
:key="index"
>
<span
class="dian"
:class="
item.name == 0 ? 'online' : item.name == 1 ? 'busy' : ''
"
></span>
{{ item.label }}({{ item.value }})
</van-checkbox>
</van-checkbox-group>
</div>
</div>
<div class="group item_box">
<ul class="groupList positionList" ref="xzScroll">
<li
v-for="item in xzList.list"
:key="item.id"
@click="handelClick(item)"
>
<div class="top">
<div class="top-cnt">
<span
class="dian online"
title="巡逻中"
v-if="item.xfzt == 0"
></span>
<span
class="dian busy"
title="处警中"
v-if="item.xfzt == 1"
></span>
<span class="dian" title="离线" v-if="item.xfzt == 2"></span>
<span class="name">{{ item.jzMc ? item.jzMc:item.fzrXm+'巡组' }}</span
><br />
<span class="other"
>负责人{{ item.fzrXm }} ({{ item.fzrLxdh }})</span
>
</div>
<div class="imgBtn">
<van-icon name="phone-circle-o" color="#25b882" size="30" />
</div>
</div>
<div class="address">
<van-icon
name="location"
size="15px"
color="#3e6ee8"
></van-icon>
<span>{{ item.dqwz }}</span>
</div>
</li>
<van-loading
type="spinner"
v-if="xzLoading"
style="padding-top: 50vw; text-align: center"
/>
<van-empty
image="default"
description="无列表数据"
v-if="xzList.list.length <= 0 && !xzLoading"
/>
</ul>
</div>
</div>
<!-- 人员实时位置 -->
<div class="contant">
<div class="header">
<span>
<van-icon name="manager" size="20px" color="#3e6ee8"></van-icon>
<span class="title">人员实时位置</span>
</span>
</div>
<div class="group item_box">
<Search
v-model="localVal"
placeholder="请输入相关信息"
@update:modelValue="SeachLocation"
></Search>
<ul class="groupList positionList" ref="ryScroll">
<li
v-for="item in wzList.list"
:key="item.id"
@click="handelClick(item)"
style="border-bottom:1px solid #eff0f5"
>
<div class="top">
<div class="top-cnt">
<span class="other">负责人{{ item.yh_xm }}</span>
<div class="text">
{{ item.dwrq }}
{{ item.kssj ? item.kssj.slice(11, 16) : "00:00" }}
{{ item.jssj ? item.jssj.slice(11, 16) : "00:00" }}
</div>
</div>
<div class="imgBtn">
<van-icon name="phone-circle-o" color="#25b882" size="30" />
</div>
</div>
<div class="address" v-if="item.dqwz">
<van-icon
name="location"
size="15px"
color="#3e6ee8"
></van-icon>
<span>{{ item.dqwz }}</span>
</div>
</li>
<van-loading
type="spinner"
v-if="renLoading"
style="padding-top: 4vw; text-align: center"
/>
<van-empty
image="default"
description="无列表数据"
v-if="wzList.list.length <= 0 && !renLoading"
/>
</ul>
</div>
</div>
</div>
</div>
</template>
<script setup>
import {
locationLCS,
locationXZWZS,
locationWZRS,
locationRYSSWZ,
getSelectDeckList,
} from "../../../api/yyzxApi.js";
import ItemList from "../../../components/component/itemList.vue";
import TopNav from "../../../components/topNav.vue";
import { timeValidate, getRecentDay } from "../../../utils/tools.js";
import { ref, reactive, onMounted, defineEmits } from "vue";
import Search from "../../../components/search.vue";
import { Toast } from "vant";
const xzLoading = ref(false);
const xzScroll = ref(null);
const renLoading = ref(false);
const ryScroll = ref(null);
//状态数据
const Searvalue = ref([]); // 巡组搜索关键字
const checked = ref([0, 1, 2]); //巡组复选框
const checkList = reactive([
{
name: 0,
label: "巡逻中",
value: 0,
},
{
name: 1,
value: 0,
label: "处警中",
},
{
name: 2,
value: 0,
label: "离线",
},
]);
const today = ref(timeValidate(new Date(), "ymd")); //今天
const week = ref(getRecentDay(-6, "ymd")); //近7天
const month = ref(getRecentDay(-29, "ymd"));
//今日统计数据
const dayList = ref([
{
name: "坐标总数",
count: 0,
},
{
name: "里程数",
count: 0,
isShowKm: true,
},
{
name: "巡组位置数",
count: 0,
},
]);
//周统计
const weekList = ref([
{
name: "坐标总数",
count: 0,
},
{
name: "里程数",
count: 0,
isShowKm: true,
},
{
name: "巡组位置数",
count: 0,
},
]);
//月统计
const monthList = ref([
{
name: "坐标总数",
count: 0,
},
{
name: "里程数",
count: 0,
isShowKm: true,
},
{
name: "巡组位置数",
count: 0,
},
]);
let pageCurrent = ref(1);
let xzTotal = ref(0);
let xzList = reactive({
list: [],
}); //巡组数据
let wzList = reactive({
list: [],
}); //人员实时位置
const wzTotal = ref(0);
const wzPageNum = ref(1);
const localVal = ref("");
onMounted(() => {
Toast.loading({
message: "加载...",
forbidClick: true,
loadingType: "spinner",
duration: 0,
});
// <!-- 位置统计 -->
// //里程数 今天 -近七天 -近30天 )
// getLcs(today.value, today.value, "day");
// getLcs(week.value, today.value, "week");
// getLcs(month.value, today.value, "month");
// // //位置人数(坐标总数) 今天 -近七天 -近30天
// getWzrs(today.value, today.value, "day");
// getWzrs(week.value, today.value, "week");
// getWzrs(month.value, today.value, "month");
// // //巡组位置巡数 今天 -近七天 -近30天
// getXzwzs(today.value, today.value, "day");
// getXzwzs(week.value, today.value, "week");
// getXzwzs(month.value, today.value, "month");
// // 实时巡组
// SelectDeckList(0);
// SelectDeckList(1);
// SelectDeckList(2);
// onChangeXfzt();
// // 人员实时位置
// getDataList();
// scroll("xz");
// scroll("ry");
Promise.all([
getLcs(today.value, today.value, "day"),
getLcs(week.value, today.value, "week"),
getLcs(month.value, today.value, "month"),
getWzrs(today.value, today.value, "day"),
getWzrs(week.value, today.value, "week"),
getWzrs(month.value, today.value, "month"),
getXzwzs(today.value, today.value, "day"),
getXzwzs(week.value, today.value, "week"),
getXzwzs(month.value, today.value, "month"),
SelectDeckList(0),
SelectDeckList(1),
SelectDeckList(2),
onChangeXfzt(),
getDataList(),
scroll("xz"),
scroll("ry"),
])
.then((res) => {
Toast.clear();
})
.catch((err) => {
Toast.clear();
});
});
// 里程数
function getLcs(start, end, type) {
let params = {
ksrq: start + " 00:00:00",
jsrq: end + " 23:59:59",
};
locationLCS("/mosty-wzzx/wztj/tj/jrlcs", params).then((res) => {
if (type == "day") {
dayList.value[1].count = (res[0].lcs / 1000).toFixed(0);
}
if (type == "week") {
weekList.value[1].count = (res[0].lcs / 1000).toFixed(0);
}
if (type == "month") {
monthList.value[1].count = (res[0].lcs / 1000).toFixed(0);
}
});
}
// 获取位置人数 / 坐标总数
function getWzrs(start, end, type) {
let params = {
ksrq: start + " 00:00:00",
jsrq: end + " 23:59:59",
};
locationWZRS(params).then((res) => {
if (type == "day") {
dayList.value[0].count = res[0].sl;
}
if (type == "week") {
weekList.value[0].count = res[0].sl;
}
if (type == "month") {
monthList.value[0].count = res[0].sl;
}
});
}
// 获取巡组位置巡数
function getXzwzs(start, end, type, status) {
let params = {
ksrq: start + " 00:00:00",
jsrq: end + " 23:59:59",
};
locationXZWZS("/mosty-wzzx/wztj/tj/jrxzwzs", params).then((res) => {
if (type == "day") {
dayList.value[2].count = res[0].wzs;
}
if (type == "week") {
weekList.value[2].count = res[0].wzs;
}
if (type == "month") {
monthList.value[2].count = res[0].wzs;
}
});
}
//选择巡防状态
function onChangeXfzt() {
let status = checked.value.join(",");
pageCurrent.value = 1;
xzList.list = [];
SelectDeckList(status);
}
//巡组列表
function SelectDeckList(xfzt) {
let data = {
xfzt,
pageSize: 10,
pageCurrent: pageCurrent.value,
};
xzLoading.value = true;
getSelectDeckList("/mosty-qwzx/tbQwXfbb/selectDeckList", data)
.then((res) => {
xzLoading.value = false;
if (res.records.length > 0) {
if (pageCurrent.value == 1) {
xzList.list = res.records;
} else {
xzList.list = xzList.list.concat(res.records);
}
}
xzTotal.value = res.total;
if (xfzt == 0) {
checkList[0].value = res.total;
}
if (xfzt == 1) {
checkList[0].value = res.total;
}
if (xfzt == 2) {
checkList[2].value = res.total;
}
})
.catch(() => {
xzLoading.value = false;
});
}
// 清除搜索
function clearDataSearch() {
wzPageNum.value = 1;
getDataList();
}
// 人员事实位置搜索
function SeachLocation() {
wzPageNum.value = 1;
getDataList();
}
// 人员实时获取数据列表
function getDataList() {
let params = {
yhxm: localVal.value,
pageCurrent: wzPageNum.value,
pageSize: 10,
};
renLoading.value = true;
locationRYSSWZ("/mosty-wzzx/wztj/wz/rywzlb", params)
.then((res) => {
renLoading.value = false;
if (wzPageNum.value == 1) {
wzList.list = res.records ? res.records : [];
} else {
let arr = res.records ? res.records : [];
wzList.list = wzList.list.concat(arr);
}
wzTotal.value = res.total;
})
.catch(() => {
renLoading.value = false;
});
}
//触底加载
function scroll(type) {
let scrollTargetBox = "";
if (type == "xz") {
scrollTargetBox = xzScroll.value;
} else {
scrollTargetBox = ryScroll.value;
}
scrollTargetBox.onscroll = (e) => {
var scrollHeight = scrollTargetBox.scrollHeight;
var scrollTop = scrollTargetBox.scrollTop;
var clientHeight = scrollTargetBox.clientHeight;
if (scrollHeight - clientHeight == scrollTop) {
//滚动条滚到最底部
if (type == "xz") {
if (xzList.list.length < xzTotal.value) {
pageCurrent++;
}
} else {
if (wzList.list.length < wzTotal.value) {
wzPageNum.value++;
getDataList();
}
}
}
};
}
</script>
<style lang="scss" scoped>
@import "../../../assets/styles/mixin.scss";
.main {
// padding: 0 4vw;
box-sizing: border-box;
height: calc(100vh - 100px);
overflow: hidden;
overflow-y: auto;
.contant {
margin: 2vw 0;
.header {
height: 10vw;
display: flex;
align-items: center;
justify-content: space-between;
margin: 0 3.5vw;
// padding: 2vw 0;
.icon {
display: inline-block;
width: 6vw;
height: 6vw;
border: 1px solid #e5e5e5;
margin-right: 2vw;
}
.title {
font-size: 4vw;
font-weight: 600;
margin-left: 1vw;
@include font_color($font-color-theme);
}
}
.select_box {
padding-top: 8px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: space-between;
padding: 3.5vw;
@include font_size($font_medium_s);
}
// 位置统计
.position {
min-height: 40vh;
.position-item {
height: 24vw;
margin-bottom: 2vw;
display: flex;
border-radius: 2vw;
overflow: hidden;
box-shadow: 0 0 4px 4px #e5e5e5;
.item-left {
display: flex;
align-items: center;
justify-content: center;
width: 10vw;
height: 24vw;
background: #1e4eca;
font-size: 4vw;
color: #fff;
padding: 0 2vw;
box-sizing: border-box;
text-align: center;
}
.item-right {
flex: 1;
display: flex;
justify-content: space-around;
align-items: center;
.item {
text-align: center;
.title {
text-align: center;
font-size: 4vw;
}
.numb {
font-size: 6vw;
font-weight: bold;
line-height: 9vw;
}
.num2 {
color: #e36356;
}
.num3 {
color: #205bf3;
}
.proportion {
text-align: center;
width: 100%;
font-size: 3vw;
img {
margin: 0 2px 0 4px;
}
.up-color {
color: #2bf242;
}
.down-color {
color: #e64a4a;
}
}
}
}
}
}
// 实时巡组
.callAll {
padding: 2px 5px;
background: linear-gradient(#00befb, #0b66d8);
border-radius: 1vw;
color: #fff;
margin-right: 1vw;
}
.group {
// box-shadow: 0 0 10px #ccc;
// padding: 4vw 2vw;
box-sizing: border-box;
margin: 0 3.5vw;
.search {
display: flex;
height: 8vw;
// ::v-deep .van-search__content {
// height: 8vw;
// }
.setchBtn {
margin-left: 1vw;
background: #2c5ff1;
padding: 1vw 4vw;
border-radius: 2vw;
color: #fff;
line-height: 6.5vw;
@include font_size($font_medium_s);
}
}
ul.groupList {
min-height: 10vh;
margin-top: 2vw;
overflow: hidden;
li {
padding-bottom: 2vw;
border-radius: 2vw;
margin-top: 2vw;
position: relative;
// background: #f7f7f7;
&:first-child {
margin-top: 0px;
}
.top {
display: flex;
justify-content: space-between;
padding: 0 3vw;
padding-top: 3vw;
line-height: 7vw;
padding-bottom: 1vw;
.top-cnt {
width: 80%;
@include font_size($font_medium_s);
}
.dian {
width: 2vw;
height: 2vw;
border-radius: 50%;
background: #999;
display: inline-block;
vertical-align: middle;
margin-right: 2vw;
&.online {
background: #1fd038;
}
&.busy {
background: #ed0000;
}
}
.name {
font-size: 4vw;
color: #5471f3;
vertical-align: middle;
}
.other {
font-size: 3vw;
}
.imgBtn {
padding-top: 10px;
margin-left: 2px;
img {
margin-right: 2vw;
width: 6vw;
height: 6vw;
border: 1px solid #e5e5e5;
&:last-child {
margin-right: 0;
}
}
}
}
li.active {
border: 1px solid #108fe7;
.checkBox {
display: block;
}
}
}
}
ul.positionList {
max-height: 60vh;
overflow: hidden;
overflow-y: auto;
}
// 地址
.address {
margin: 0 2vw;
@include bottm_tab_top_color($bottom-border-top-clore-theme);
height: 6vw;
line-height: 6vw;
font-size: 3vw;
padding: 2vw 0;
img,
span {
vertical-align: middle;
}
img {
margin-right: 2vw;
width: 4vw;
height: 4vw;
border: 1px solid #e5e5e5;
}
}
}
::v-deep .van-checkbox__label {
@include font_color($font-color-theme);
font-size: 3vw;
.dian {
width: 2vw;
height: 2vw;
border-radius: 50%;
background: #999;
display: inline-block;
vertical-align: middle;
margin-right: 1vw;
&.online {
background: #1fd038;
}
&.busy {
background: #ed0000;
}
&.blue {
background: #229bf0;
}
}
}
}
}
</style>