Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	src/views/BI/js/trajectory.js
pull/3/head
fangjiakai 2024-03-01 17:14:34 +08:00
commit 3ad5910d14
4 changed files with 117 additions and 118 deletions

View File

@ -78,8 +78,8 @@ const props = defineProps({
const emits = defineEmits([ const emits = defineEmits([
"update:leftCurrentComponent", "update:leftCurrentComponent",
"update:rightCurrentComponent", "update:rightCurrentComponent",
"update:isHistoricalTrajectory",
"update:rightOption", "update:rightOption",
"update:isHistoricalTrajectory",
]); ]);
const { const {
leftCurrentComponent, leftCurrentComponent,

View File

@ -22,30 +22,39 @@
<div <div
v-for="(item, index) in data.block2OptionsList" v-for="(item, index) in data.block2OptionsList"
:key="index" :key="index"
:class="['list', { alarm: item.total > 0 }]" :class="['list', { alarm: item.count > 0 }]"
@click="fnAlarmTypeClick(item)" @click="fnAlarmTypeClick(item)"
> >
<div class="name">{{ item.label }}</div> <div class="name">{{ typeList[item.eleType] }}</div>
<div class="num"> <div class="num">
<count-up :end-val="item.total"></count-up> <count-up :end-val="item.count"></count-up>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="block3"> <div class="block3">
<layout-title title="人员定位情况" /> <layout-title title="区域人员统计" />
<div class="option"> <div class="option">
<div class="table"> <div class="table">
<div class="tr"> <div class="tr">
<div class="td">姓名</div> <div class="td">区域</div>
<div class="td">卡号</div> <div class="td">人员</div>
<div class="td">电量</div>
</div> </div>
<div v-for="(item, index) in data.block3List" :key="index" class="tr"> <seamless-scroll
<div class="td">{{ item.name }}</div> :list="data.block3List"
<div class="td">{{ item.cardNo }}</div> hover
<div class="td">{{ item.stset + "%" }}</div> class="scroll"
:step="0.5"
>
<div
v-for="(item, index) in data.block3List"
:key="index"
class="tr"
>
<div class="td line-1">{{ item.group }}</div>
<div class="td">{{ item.count }}</div>
</div> </div>
</seamless-scroll>
</div> </div>
</div> </div>
</div> </div>
@ -55,9 +64,11 @@
v-model:pd="data.form" v-model:pd="data.form"
:ele-type-num="+data.eleType" :ele-type-num="+data.eleType"
/> />
<template v-if="data.block2OptionsList.some((item) => item.total > 0)">
<teleport to="body"> <teleport to="body">
<div class="alarm_full_screen"> <div
v-if="data.block2OptionsList.some((item) => item.count > 0)"
class="alarm_full_screen"
>
<div <div
v-for="item in 4" v-for="item in 4"
:key="item" :key="item"
@ -65,91 +76,21 @@
/> />
</div> </div>
</teleport> </teleport>
</template>
</div> </div>
</template> </template>
<script setup> <script setup>
import LayoutTitle from "./title.vue"; import LayoutTitle from "./title.vue";
import AlarmDialog from "../components/dialog/alarm_dialog.vue"; import AlarmDialog from "../components/dialog/alarm_dialog.vue";
import CountUp from "vue-countup-v3"; import CountUp from "vue-countup-v3";
import { nextTick, reactive } from "vue"; import { onBeforeUnmount, reactive } from "vue";
import { import {
getPersonnelTypeCount, handleGetPerList,
getAlarmTypeCount, handleTrajectory,
getPersonnelPositioningCount, } from "@/views/BI/js/trajectory.js";
} from "@/request/bi/mapApi.js"; import { Vue3SeamlessScroll as SeamlessScroll } from "vue3-seamless-scroll";
import { useIntervalFn } from "@vueuse/core";
const data = reactive({
block1OptionsList: [
{
img: new URL("/src/assets/images/map/img1.png", import.meta.url).href,
label: "全部人员",
count: 0,
},
],
eleType: 0,
block2OptionsList: [],
block3List: [
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
{
name: "赵一诺",
Office: "大堂经理",
electricity: "30%",
},
],
form: {},
drawer: false,
});
const getPersonnelData = async () => {
const resData = await getPersonnelTypeCount();
await nextTick(() => {
data.block1OptionsList.forEach((item) => {
item.count = resData.userCount;
});
});
};
const fnAlarmTypeClick = (e) => {
data.drawer = true;
data.form.title = e.label;
data.eleType = e.type;
};
const getAlarmTypeData = async () => {
const resData = await getAlarmTypeCount();
const dataList = resData.data.data.data;
const typeList = { const typeList = {
1: "滞留报警", 1: "滞留报警",
2: "串岗报警", 2: "串岗报警",
@ -159,19 +100,55 @@ const getAlarmTypeData = async () => {
6: "一键报警", 6: "一键报警",
7: "越界报警", 7: "越界报警",
8: "聚集告警", 8: "聚集告警",
9: "作业告警",
}; };
dataList.forEach((item) => { const data = reactive({
item.label = typeList[item.type]; block1OptionsList: [
{
img: new URL("/src/assets/images/map/img1.png", import.meta.url).href,
label: "全部人员",
count: 0,
},
{
img: new URL("/src/assets/images/map/img2.png", import.meta.url).href,
label: "外来人员",
count: 0,
},
{
img: new URL("/src/assets/images/map/img3.png", import.meta.url).href,
label: "第三方人员",
count: 0,
},
],
eleType: 0,
block2OptionsList: [],
block3List: [],
form: {},
drawer: false,
}); });
data.block2OptionsList = dataList; useIntervalFn(async () => {
const res = await handleGetPerList();
for (let i = 0; i < res.perDataList.data?.length; i++) {
data.block1OptionsList[i].label = res.perDataList.data[i].name;
data.block1OptionsList[i].count = res.perDataList.data[i].value;
}
data.block2OptionsList = res.armDataList;
data.block3List = res.regPerDataList;
}, 2000);
const fnInit = async () => {
await handleTrajectory(true);
}; };
const getPositionData = async () => { fnInit();
const resData = await getPersonnelPositioningCount(); const fnAlarmTypeClick = (e) => {
data.block3List = resData.data.rows; data.drawer = true;
data.form.title = e.label;
data.eleType = e.eleType;
}; };
getPersonnelData();
getAlarmTypeData(); // websocket
getPositionData(); onBeforeUnmount(async () => {
await handleTrajectory(false);
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.container { .container {
@ -292,9 +269,6 @@ getPositionData();
width: 430px; width: 430px;
margin-top: 10px; margin-top: 10px;
.tab_list {
}
.option { .option {
width: 100%; width: 100%;
min-height: 100px; min-height: 100px;
@ -336,6 +310,11 @@ getPositionData();
} }
} }
.scroll {
height: 210px;
overflow: hidden;
}
.table { .table {
margin-top: 5px; margin-top: 5px;
@ -347,22 +326,18 @@ getPositionData();
} }
.td { .td {
flex: 1;
text-align: left; text-align: left;
font-size: 12px; font-size: 12px;
color: #fff; color: #fff;
padding: 6px 10px; padding: 6px 10px;
&:nth-child(1) { &:nth-child(1) {
flex-basis: 30%; flex: 1;
} }
&:nth-child(2) { &:nth-child(2) {
flex-basis: 50%;
}
&:nth-child(3) {
flex-basis: 20%; flex-basis: 20%;
text-align: center;
} }
} }

View File

@ -59,7 +59,6 @@
<div v-show="right_option" class="right_ico"> <div v-show="right_option" class="right_ico">
<right-ico v-model:is-pure-map="isPureMap" /> <right-ico v-model:is-pure-map="isPureMap" />
</div> </div>
<transition <transition
enter-active-class="animate__animated animate__fadeInDown" enter-active-class="animate__animated animate__fadeInDown"
leave-active-class="animate__animated animate__fadeOutDown" leave-active-class="animate__animated animate__fadeOutDown"
@ -77,11 +76,11 @@ import autofit from "autofit.js";
import { onBeforeUnmount, onMounted, ref } from "vue"; import { onBeforeUnmount, onMounted, ref } from "vue";
import RightIco from "./components/rightico.vue"; import RightIco from "./components/rightico.vue";
import BottomOptions from "./components/bottom_options.vue"; import BottomOptions from "./components/bottom_options.vue";
import HistoricalTrajectoryOptions from "./components/historical_trajectory_options.vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { initMap } from "./js/map"; import { initMap } from "./js/map";
import { useUserStore } from "@/pinia/user.js"; import { useUserStore } from "@/pinia/user.js";
import { getEnterpriseInfo } from "@/request/enterprise_management.js"; import { getEnterpriseInfo } from "@/request/enterprise_management.js";
import HistoricalTrajectoryOptions from "@/views/BI/components/historical_trajectory_options.vue";
const router = useRouter(); const router = useRouter();
const right_option = ref(true); const right_option = ref(true);

View File

@ -10,7 +10,12 @@ const pls_ip = userStore.getUserInfo.POST_URL;
let entityArr = []; let entityArr = [];
let billboardArr = []; let billboardArr = [];
const fencesArr = []; const fencesArr = [];
const leftObj = {
perDataList: [],
armDataList: [],
regPerDataList: [], // 区域人员统计
deptDataList: [], // 部门统计
};
const { open, close } = useWebSocket( const { open, close } = useWebSocket(
encodeURI("ws://" + pls_ip.replace("http://", "") + "/netty/test.io?u=1"), encodeURI("ws://" + pls_ip.replace("http://", "") + "/netty/test.io?u=1"),
// encodeURI("ws://58.58.162.14:8084/netty/test.io?userid=1"), // encodeURI("ws://58.58.162.14:8084/netty/test.io?userid=1"),
@ -25,7 +30,6 @@ const { open, close } = useWebSocket(
onMessage: (ws, event) => { onMessage: (ws, event) => {
const msg = unzip(event.data); const msg = unzip(event.data);
const decodedMsg = JSON.parse(decodeURIComponent(msg)); const decodedMsg = JSON.parse(decodeURIComponent(msg));
console.log(decodedMsg);
if (decodedMsg.msg === "000") { if (decodedMsg.msg === "000") {
peoMovement(decodedMsg.data); peoMovement(decodedMsg.data);
} }
@ -35,6 +39,7 @@ const { open, close } = useWebSocket(
if (decodedMsg.msg === "008") { if (decodedMsg.msg === "008") {
removePerson(decodedMsg.data); removePerson(decodedMsg.data);
} }
changeLeftObjData(decodedMsg);
}, },
onDisconnected: () => { onDisconnected: () => {
if (entityArr && entityArr.children) { if (entityArr && entityArr.children) {
@ -50,6 +55,13 @@ const { open, close } = useWebSocket(
}, },
} }
); );
export const handleGetPerList = async () => {
return leftObj;
};
export const handleInit = async () => {
getOnlineUser();
open();
};
export const handleTrajectory = (b) => { export const handleTrajectory = (b) => {
if (b) { if (b) {
getOnlineUser(); getOnlineUser();
@ -154,7 +166,20 @@ const drawCanvas = (name, floor) => {
ctx.fillText((name || "未知人员") + `(${floor}F)`, width / 2, height / 2); ctx.fillText((name || "未知人员") + `(${floor}F)`, width / 2, height / 2);
return canvas; return canvas;
}; };
const changeLeftObjData = (decodedMsg) => {
if (decodedMsg.msg === "005") {
leftObj.perDataList = decodedMsg.data;
}
if (decodedMsg.msg === "003") {
leftObj.armDataList = decodedMsg.data;
}
if (decodedMsg.msg === "002") {
leftObj.regPerDataList = decodedMsg.data;
}
if (decodedMsg.msg === "008") {
leftObj.deptDataList = decodedMsg.data;
}
};
const addNewPerson = (data) => { const addNewPerson = (data) => {
data.forEach((item) => { data.forEach((item) => {
const entity = item.split(","); const entity = item.split(",");