初始提交

This commit is contained in:
2025-09-04 16:27:57 +08:00
commit f2faa2d5fd
1076 changed files with 478489 additions and 0 deletions

View File

@ -0,0 +1,115 @@
<template>
<div>
<el-dialog title="模型预警" @close="closed" width="1400px" :model-value="props.modelValue">
<el-form :model="listQuery" label-width="100px">
<el-form-item prop="mxlx" label="模型类型">
<el-select v-model="listQuery.mxlx">
<el-option
v-for="(dict, index) in gzyList"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="模型名称" prop="mxmc">
<el-input
v-model="listQuery.mxmc"
placeholder="请输入模型名称"
clearable
/>
</el-form-item>
<el-form-item label="感知源" prop="gzy">
<el-input v-model="listQuery.gzy" readonly clearable />
</el-form-item>
<el-form-item prop="yjsc" label="预警时长">
<div class="itemText">
<el-select v-model="listQuery.yjsc">
<el-option
v-for="(dict, index) in arrList"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
<el-input v-model="listQuery.sc" readonly clearable />
<div class="text">分钟</div>
</div>
</el-form-item>
<el-form-item prop="yjry" label="预警人员">
<div class="itemText">
<el-select v-model="listQuery.yjry">
<el-option
v-for="(dict, index) in arrList"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
<el-input v-model="listQuery.rysc" readonly clearable />
<div class="text"></div>
</div>
</el-form-item>
<el-form-item prop="rylb" label="人员类别">
<el-select v-model="listQuery.rylb">
<el-option
v-for="(dict, index) in D_BZ_RYBQ"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, getCurrentInstance, defineProps,defineEmits } from "vue";
const props = defineProps({
type: String,
modelValue:Boolean
});
const emits = defineEmits(["update:modelValue"]);
const { proxy } = getCurrentInstance();
const { D_BZ_RYBQ } = proxy.$dict("D_BZ_RYBQ");
const listQuery = ref({
gzy: "所有",
mxlx: "01",
sc: 0,
rysc:0
});
const gzyList = ref([
{ label: "感知源模型", value: "01" },
{ label: "位置模型", value: "02" },
{ label: "关注对象模型", value: "03" }
]);
const arrList = ref([
{ label: "小于", value: "01" },
{ label: "大于", value: "02" },
{ label: "等于", value: "03" },
{ label: "小于等于", value: "04" },
{ label: "大于等于", value: "05" }
]);
const modelValue = ref(false);
const closed = () => {
emits("update:modelValue", false);
};
</script>
<style lang="scss" scoped>
.itemText {
display: flex;
width: 100%;
.text{
width: 60px;
}
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<div class="centerBox">
<!-- 警力的弹框 -->
<GrouListJl />
<!-- 巡组的弹框 -->
<GrouListJmxz />
<!-- 街面力量的弹框 -->
<GrouListJmll />
<!-- 巡逻时长的弹框 -->
<GrouListXllsclc />
<!-- 盘查工作的弹框 -->
<GrouListPcgz />
<!-- 指令弹窗 -->
<GrouListZl />
<!-- 单独播放视频弹窗 -->
<ViedeoDialog />
<!-- 新增勤务 -->
<AddQwDialog />
<!-- 展示大图 -->
<ImgBox />
</div>
</template>
<script setup>
import GrouListJl from "./dialog/grouListJl.vue";
import GrouListJmxz from "./dialog/grouListJmxz.vue";
import GrouListJmll from "./dialog/grouListJmll.vue";
import GrouListXllsclc from "./dialog/grouListXllsclc.vue";
import GrouListPcgz from "./dialog/grouListPcgz.vue";
import GrouListZl from "./dialog/grouListZl.vue";
import ViedeoDialog from "@/components/video/index.vue";
import AddQwDialog from "./dialog/addQwDialog.vue";
import ImgBox from "./dialog/imgBox.vue";
import { ref, defineProps, onMounted, onUnmounted, reactive } from "vue";
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
</style>

View File

@ -0,0 +1,916 @@
<!--
* @Author: 孙总
* @Date: 2022-10-17 15:42:41
* @LastEditTime: 2022-12-26 19:01:06
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
-->
<template>
<div class="message" @click.stop="closed">
<div class="message_main" @click.stop>
<div class="message_title">
<span>指令详情</span>
<Close @click="closed" style="width: 1.2em; height: 1.2em; cursor: pointer"/>
</div>
<div class="message_content">
<div class="zl_title">
{{ props.data.zlbt }}
</div>
<div class="zl_info">
<img v-if="props.data.zltp" :src="props.data.zltp" alt="" />
<div class="info_r">
<div class="r_title">
<span>{{ props.data.zlfqr }}</span>
<span v-if="props.data.zlfqr !== '系统'">{{
props.data.zlfqrSfzh.substr(props.data.zlfqrSfzh.length - 2,1) %2 ===0? "": ""}}</span>
<span
class="block"
:style="{
color:props.data.zldj == 10? 'red' : props.data.zldj == 20? '#da5724': props.data.zldj == 30? 'yellow': 'blue'}"
>指令等级
<dict-tag
:options="D_BZ_TYJB"
:value="props.data.zldj"
:tag="false"
></dict-tag
></span>
<span class="qszt"
><dict-tag
:options="D_BZ_ZXZTAI"
:value="props.data.zlzxzt"
:tag="false"
></dict-tag
></span>
</div>
<div v-if="props.data.zlfqr !== '系统'">
汉族 44岁 51033656582252258 &emsp; 指令类型人员预警
</div>
<div class="block">
指令来源<dict-tag
:options="D_BZ_ZLLY"
:value="props.data.zlly"
:tag="false"
></dict-tag>
位置{{ props.data.zlfsdd }}
</div>
<!-- <div class="zxdt">最新执行记录{{ props.data.dqztsm }}</div> -->
</div>
</div>
<div class="zl_nr">
内容{{ props.data.zlnr }}
<span>附近监控</span>
</div>
</div>
<div class="message_list" ref="scroll">
<div v-for="item in list" :key="item.id">
<template v-if="item.xtCjrId == userId">
<p style="text-align: right; color: #82878f">
{{ item.zxsj }}
</p>
<template v-if="item.fjid">
<p v-if="item.fileFormat == 'png'" style="text-align: right">
<el-image
@click="
setIndex(
'/mosty-api/mosty-base/minio/image/download/' + item.fjid
)
"
style="width: 100px; height: 100px"
:src="
'/mosty-api/mosty-base/minio/image/download/' + item.fjid
"
:preview-src-list="srcList"
:initial-index="srcIndex"
fit="cover"
preview-teleported
></el-image>
</p>
<div
class="audio-detail-msg msgRight_box"
v-if="item.fileFormat == 'mp3'"
>
<div class="duration-seconds">
{{ item.yysc ? item.yysc : 1 }}s
</div>
<div
class="audio-style msgRight"
style="margin-left: 8px"
:class="{ 'add-animation': isPlay && audioId == item.fjid }"
:style="{
width: handleAudioStyleWidth(item.yysc ? item.yysc : 1)
}"
@click="
playAudio(
item.fjid,
item.yysc ? item.yysc : 1,
item.audioUrl
)
"
>
<div class="small"></div>
<div class="middle"></div>
<div class="large"></div>
</div>
<audio :id="item.fjid" style="display: none"></audio>
</div>
<div
style="display: flex; position: relative"
class="msgRight_box"
v-if="item.fileFormat == 'mp4'"
>
<video
:id="item.id"
:src="item.videoUrl"
style="width: 100px"
></video>
<img
class="rigth_video_play"
src="@/assets/play.png"
alt=""
@click="onClickVideo(item.videoUrl)"
/>
</div>
<div
style="display: flex; justify-content: flex-end"
v-if="item.fileFormat == 'file'"
>
<p class="wenjian" @click="downFile(item.fjid)">
{{ item.zxnr }}
</p>
</div>
</template>
<div v-else style="text-align: right">
<div class="xx_item">
<span class="xx">
{{ item.zxnr }}
</span>
</div>
</div>
</template>
<template v-else>
<p style="color: #82878f">
{{ item.zxsj }}&emsp;{{ item.zlzxrXm }}
</p>
<template v-if="item.fjid">
<p v-if="item.fileFormat == 'png'">
<el-image
@click="
setIndex(
'/mosty-api/mosty-base/minio/image/download/' + item.fjid
)
"
style="width: 100px; height: 100px"
:src="
'/mosty-api/mosty-base/minio/image/download/' + item.fjid
"
:preview-src-list="srcList"
:initial-index="srcIndex"
preview-teleported
fit="cover"
></el-image>
</p>
<div class="audio-detail-msg" v-if="item.fileFormat == 'mp3'">
<div
class="audio-style"
style="margin-right: 8px"
:class="{ 'add-animation': isPlay && audioId == item.fjid }"
:style="{
width: handleAudioStyleWidth(item.yysc ? item.yysc : 1)
}"
@click="
playAudio(
item.fjid,
item.yysc ? item.yysc : 1,
item.audioUrl
)
"
>
<div class="small"></div>
<div class="middle"></div>
<div class="large"></div>
</div>
<div class="duration-seconds">
{{ item.yysc ? item.yysc : 1 }}s
</div>
<audio :id="item.fjid" style="display: none"></audio>
</div>
<div
style="display: flex; position: relative"
v-if="item.fileFormat == 'mp4'"
>
<video
:id="item.id"
:src="item.videoUrl"
style="width: 100px"
></video>
<img
class="left_video_play"
src="@/assets/play.png"
alt=""
@click="onClickVideo(item.videoUrl)"
/>
</div>
<div
style="display: flex; justify-content: flex-end"
v-if="item.fileFormat == 'file'"
>
<p class="wenjian" @click="downFile(item.fjid)">
{{ item.zxnr }}
</p>
</div>
<div v-if="item.fileFormat == 'file'" style="text-align: left">
<div class="xx_item">
<span @click="downFile(item.fjid)" class="wenjian_l">
{{ item.zxnr }}
</span>
</div>
</div>
</template>
<div v-else>
<div class="xx_item">
<span class="xx_l">
{{ item.zxnr }}
</span>
</div>
</div>
</template>
</div>
</div>
<div class="message_form">
<input
v-model="value"
placeholder="请输入你描述的内容"
@keyup.enter="submit"
/>
<el-upload
v-model:file-list="fileList"
:limit="1"
action="/mosty-api/mosty-base/minio/image/upload/id"
:on-change="upImgFile"
:on-success="upImg"
:show-file-list="false"
>
<CirclePlus
color="#4e6e95"
class="plus"
style="width: 1.5em; height: 1.5em"
/>
</el-upload>
<el-button @click="submit">发送</el-button>
</div>
</div>
<div
v-if="dialogShowVideo"
class="dialogShowVideo"
@click.stop="dialogShowVideo = false"
>
<video :src="langVideoUrl" class="video_box" controls></video>
<el-icon :size="40" color="#999" class="video_close">
<CircleClose />
</el-icon>
</div>
</div>
</template>
<script setup>
import axios from "axios";
import {
reactive,
ref,
defineProps,
defineEmits,
getCurrentInstance,
onMounted,
nextTick,
onUnmounted,
onBeforeUnmount
} from "vue";
import { getZxjlList, addZxjl, downFiles } from "@/api/instructCenter.js";
import { IS_PNG, IS_MP3, IS_MP4 } from "@/utils/tools.js";
import { getItem } from "@/utils/storage.js";
import { Emitter } from "@fullcalendar/core";
const playActive = reactive({
icon: "close",
id: ""
});
const fileList = ref([]);
//图片格式
const imgLx = ["png", "jpg", "jpeg", "bmp", "gif"];
//音频格式
const radioFormat = ["wav"];
const srcIndex = ref(0);
const { proxy } = getCurrentInstance();
const { D_BZ_TYJB, D_BZ_ZLLY, D_BZ_ZLLX, D_BZ_ZXZTAI } = proxy.$dict(
"D_BZ_TYJB",
"D_BZ_ZLLY",
"D_BZ_ZLLX",
"D_BZ_ZXZTAI"
);
const userId = getItem("USERID");
const copyVal = ref("");
//消息列表
const list = ref([]);
const dialogShowVideo = ref(false); //视频放大
const langVideoUrl = ref(""); //预览视频地址
//图片预览列表
const srcList = ref([]);
const timer = ref(null);
const scroll = ref(null);
const props = defineProps({
modelValue: {
type: Boolean,
required: true
},
data: {
type: Object,
required: true
}
});
const isPlay = ref(false); //开始语音播放动画
const playAudioTimer = ref(null); //语音播放定时器
const audioId = ref(""); //被选中播放的音频ID
const value = ref("");
const fjId = ref(false);
const emits = defineEmits(["update:modelValue", "upData"]);
const closed = () => {
emits("update:modelValue", false);
};
//点击视频放大
function onClickVideo(url) {
langVideoUrl.value = url;
dialogShowVideo.value = true;
}
//播放语音
function playAudio(id, yysc, url) {
let au = document.getElementById(id);
au.src = url;
audioId.value = id;
if (isPlay.value) {
isPlay.value = false;
au.pause();
return;
}
isPlay.value = true;
playAudioTimer.value = setTimeout(() => {
isPlay.value = false;
}, parseInt(yysc * 1000));
au.play();
}
// 设置语音条宽度样式
function handleAudioStyleWidth(yycs) {
if (yycs === 1) {
return "38px";
} else if (yycs > 1 && yycs < 20) {
return `${38 + (yycs / 10) * 36}px`;
} else if (yycs >= 20) {
return `${106.39 + (yycs / 10) * 18.935}px`;
}
}
//获取消息记录
function getZxjl() {
getZxjlList({
zlid: props.data.id,
time: list.value.length > 0 ? list.value[list.value.length - 1].zxsj : ""
}).then(async (res) => {
if (res && res.length > 0) {
for (let i = 0; i < res.length; i++) {
let item = res[i];
if (item.zxnr && item.fjid) {
//判断是那种文件类型.
let fjIndex = item.zxnr.lastIndexOf(".");
if (fjIndex != -1) {
let file_Format = item.zxnr.substring(
fjIndex + 1,
item.zxnr.length
);
if (IS_PNG(file_Format)) {
item.fileFormat = "png";
} else if (IS_MP3(file_Format)) {
await _getAudioAndVideoUrl(item.fjid).then((res) => {
item.audioUrl = res;
});
item.fileFormat = "mp3";
} else if (IS_MP4(file_Format)) {
item.fileFormat = "mp4";
await _getAudioAndVideoUrl(item.fjid).then((res) => {
item.videoUrl = res;
});
} else {
item.fileFormat = "file";
}
}
}
list.value.push(item);
}
srcList.value = list.value
.filter((item) => isImg(item.zxnr) && item.fjid)
.map(
(item) => "/mosty-api/mosty-base/minio/image/download/" + item.fjid
);
nextTick(() => {
try {
scroll.value.scrollTop = scroll.value.scrollHeight;
} catch (error) {
return;
}
});
}
});
}
//获取视频音频地址
function _getAudioAndVideoUrl(fjid) {
return new Promise((ok) => {
axios
.get(`/mosty-api/mosty-base/minio/file/download/${fjid}`, {
params: {}
})
.then((res) => {
if (res) {
ok(res.data.data.url);
}
});
});
}
function setIndex(e) {
srcIndex.value = srcList.value.indexOf(e);
}
//判断是否为图片
function isImg(fileName) {
let suffix = fileName.substr(fileName.lastIndexOf(".") + 1, 4);
return imgLx.includes(suffix);
}
//下载文件
function downFile(id) {
let el = document.createElement("a");
el.href = `/mosty-api/mosty-base/minio/image/download/${id}`;
el.click();
el.remove();
}
//发送消息
function submit() {
if (!value.value) {
return false;
}
const data = {
zxnr: value.value,
jd: props.data.jd,
wd: props.data.wd,
zlId: props.data.id
};
value.value = "";
addZxjl(data).then(() => {
fileList.value = [];
});
}
function upImg(row) {
fjId.value = row.data;
const data = {
zxnr: copyVal.value,
jd: props.data.jd,
wd: props.data.wd,
zlId: props.data.id,
fjid: fjId.value
};
addZxjl(data).then(() => {
fileList.value = [];
fjId.value = false;
});
}
function upImgFile(row) {
copyVal.value = row.name;
}
onMounted(() => {
getZxjl();
//轮询
timer.value = setInterval(() => {
getZxjl();
}, 2e3);
});
onUnmounted(() => {
clearInterval(timer.value);
});
onBeforeUnmount(() => {
clearTimeout(playAudioTimer.value);
playAudioTimer.value = null;
});
</script>
<style lang="scss" scoped>
p {
margin: 0;
padding: 0;
}
.message {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, 0.4);
display: flex;
justify-content: center;
align-items: center;
.message_main {
width: 820px;
background: #091e33;
border-radius: 8px;
overflow: hidden;
min-height: 650px;
.message_title {
display: flex;
justify-content: space-between;
padding: 6px 16px;
background: #14427e;
font-size: 18px;
}
.message_content {
background: #052342;
border-bottom: 2px solid #193b62;
.zl_title {
font-size: 16px;
line-height: 1.5em;
padding: 6px 12px 0;
}
.zl_nr {
color: #56759c;
line-height: 1.8em;
position: relative;
border-top: 1px solid #193b62;
padding: 4px 0;
padding-right: 55px;
margin: 0 12px;
> span {
position: absolute;
text-decoration: underline;
cursor: pointer;
bottom: 4px;
right: 0;
color: #027ce6;
}
}
.zl_info {
display: flex;
padding: 6px 12px;
color: #5a79a0;
> img {
width: 60px;
height: 60px;
margin-right: 12px;
}
.block div {
display: inline-block;
margin-right: 16px;
}
.info_r {
flex: 1;
line-height: 1.9em;
.r_title {
color: #fff;
font-size: 18px;
position: relative;
font-weight: 300;
span {
margin-right: 18px;
}
.qszt {
position: absolute;
right: 0px;
top: 0;
color: #027ce6;
font-size: 14px;
margin: 0;
}
}
.zxdt {
color: #027ce6;
}
}
}
}
.message_list {
height: 400px;
background: #091e33;
padding: 0 8px;
margin: 4px;
overflow: auto;
p {
line-height: 2em;
}
.xx_item {
text-align: right;
background: #12294c;
max-width: 500px;
width: auto;
display: inline-block;
padding: 4px 12px;
word-wrap: break-word;
border-radius: 4px;
}
.wenjian {
display: inline-block;
background: #12294c;
color: #00a0e0;
line-height: 2em;
padding: 0 12px;
border-radius: 4px;
cursor: pointer;
text-decoration: underline;
}
.wenjian_l {
display: inline-block;
background: #12294c;
color: #00a0e0;
line-height: 2em;
padding: 0 12px;
border-radius: 4px;
cursor: pointer;
text-decoration: underline;
}
.radio {
background: #052342;
display: inline-block;
padding: 4px 12px;
border-radius: 4px;
.sc {
display: inline-block;
padding-left: 12px;
}
}
}
.message_form {
background: #052342;
padding: 8px;
display: flex;
position: relative;
.el-button {
margin-left: 12px;
box-shadow: inset 0px 0px 8px 4px #0e3054;
}
.el-button:hover {
background: #0c376e;
}
.el-button:focus {
background: #0c376e;
border-color: #0c376e;
}
.plus {
position: absolute;
right: 88px;
top: 16px;
}
input {
outline: none;
flex: 1;
color: #fff;
background: #0d2a48;
border: none;
border-radius: 2px;
text-indent: 8px;
padding-right: 36px;
}
}
}
}
// 语音条
.audio-detail-msg {
display: flex;
align-items: center;
.msgRight {
transform: rotate(180deg);
}
.audio-style {
display: flex;
align-items: center;
height: 32px;
padding: 0 10px;
border-radius: 4px;
background: rgba(149, 236, 105, 0.5);
.small {
border: 4px solid #fff;
border-top-color: transparent;
border-left-color: transparent;
border-bottom-color: transparent;
}
.middle {
width: 16px;
height: 16px;
margin-left: -11px;
opacity: 1;
}
.large {
width: 24px;
height: 24px;
margin-left: -19px;
opacity: 1;
}
& > div {
border: 2px solid #fff;
border-top-color: transparent;
border-left-color: transparent;
border-bottom-color: transparent;
border-radius: 50%;
box-sizing: border-box;
}
&.add-animation {
.middle {
animation: show2 1.2s ease-in-out infinite;
}
.large {
animation: show3 1.2s ease-in-out infinite;
}
}
}
// 语音播放动画
@keyframes show2 {
0% {
opacity: 0;
}
10% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes show3 {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
60% {
opacity: 0;
}
100% {
opacity: 0;
}
}
// 语音录制动画
@keyframes backgroundInfinite2 {
0% {
background: #666;
}
20% {
background: #f5f5f5;
}
95% {
background: #f5f5f5;
}
100% {
background: #666;
}
}
@keyframes backgroundInfinite3 {
0% {
background: #666;
}
30% {
background: #f5f5f5;
}
85% {
background: #f5f5f5;
}
100% {
background: #666;
}
}
@keyframes backgroundInfinite4 {
0% {
background: #666;
}
55% {
background: #f5f5f5;
}
75% {
background: #f5f5f5;
}
100% {
background: #666;
}
}
@keyframes backgroundInfinite5 {
0% {
background: #666;
}
45% {
background: #666;
}
60% {
background: #f5f5f5;
}
75% {
background: #f5f5f5;
}
100% {
background: #666;
}
}
@keyframes backgroundInfinite6 {
0% {
background: #666;
}
65% {
background: #666;
}
85% {
background: #f5f5f5;
}
100% {
background: #666;
}
}
@keyframes backgroundInfinite7 {
0% {
background: #666;
}
75% {
background: #666;
}
95% {
background: #f5f5f5;
}
100% {
background: #666;
}
}
}
.msgRight_box {
justify-content: flex-end;
}
.rigth_video_play {
position: absolute;
width: 40px;
height: 40px;
top: 50%;
right: 50px;
margin-top: -20px;
margin-right: -20px;
}
.left_video_play {
position: absolute;
width: 40px;
height: 40px;
top: 50%;
left: 50px;
margin-top: -20px;
margin-left: -20px;
}
.dialogShowVideo {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.9);
padding: 80px 0;
text-align: center;
.video_box {
height: 100%;
}
.video_close {
position: absolute;
top: 80px;
right: 50px;
}
}
</style>

View File

@ -0,0 +1,273 @@
<template>
<!--新增勤务等级 -->
<div>
<el-dialog
v-model="dialogFormVisiblejs"
title="新增勤务等级"
width="80%"
top="5vh"
:destroy-on-close="true"
>
<el-form
ref="elform"
:model="form"
:rules="rules"
:inline="true"
label-position="top"
>
<el-form-item prop="qwdj" label="勤务等级">
<el-select @change="checkQwdj" style="width: 100%" v-model="form.qwdj">
<el-option
v-for="dict in D_BZ_DJQW"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item style="width: 48%" required label="勤务起止时间">
<el-date-picker
style="width: 100%"
v-model="qwQzsj"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item prop="zxfw" label="执行范围">
<el-select disabled style="width: 100%" v-model="form.zxfw">
<el-option
v-for="dict in D_BZ_ZXFW"
:key="dict.value"
:disabled="dict.value != '03'"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="jyzqrybl" label="建议执勤人员比例(%">
<el-input-number
:max="100"
:min="0"
style="width: 100%"
v-model="form.jyzqrybl"
:step="1"
/>
</el-form-item>
<el-form-item prop="jyzqclbl" label="建议执勤车辆比例(%">
<el-input-number
style="width: 100%"
v-model="form.jyzqclbl"
:step="1"
/>
</el-form-item>
<el-form-item
class="twoh"
style="width: 100%"
prop="qwyy"
label="勤务原因"
>
<el-input
v-model="form.qwyy"
placeholder="请填写勤务原因"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item
class="twoh"
style="width: 100%"
prop="qwyq"
label="勤务要求"
>
<el-input
v-model="form.qwyq"
placeholder="请填写勤务要求"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item style="width: 100%" prop="fjzl" label="附件资料">
<MOSTY.Upload
width="800px"
:limit="3"
:isImg="false"
v-model="form.fjzl"
></MOSTY.Upload>
</el-form-item>
<el-form-item label="备注" style="width: 100%">
<el-input
v-model="form.bz"
placeholder="请输入关键字"
show-word-limit
type="textarea"
/>
</el-form-item>
</el-form>
<div class="but_box">
<el-button
type="primary"
size="large"
:loading="btnLoading"
@click="submit"
>保存</el-button
>
</div>
</el-dialog>
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import * as MOSTY from "@/components/MyComponents/index";
import { addQwdj } from "@/api/service/grade.js";
import { getItem } from "@/utils/storage";
import { reactive, ref, onMounted, onUnmounted, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_DJQW, D_BZ_ZXFW } = proxy.$dict("D_BZ_DJQW", "D_BZ_ZXFW"); //获取字典数据
const dialogFormVisiblejs = ref(false); //是否显示对话框
const elform = ref(null); //表单对象
const btnLoading = ref(false); //按钮截流
const qwQzsj = ref([]); //勤务起止时间
//表单数据
const form = ref({
jyzqclbl: 34,
jyzqrybl: 34,
zxfw: "03",
qwdj: "",
qwyy: "",
qwyq: "",
fjzl: "",
bz: ""
});
//表单验证
const rules = reactive({
qwdj: [
{
required: true,
message: "请选择勤务等级",
trigger: "change"
}
],
qwkssj: [
{
required: true,
message: "请选择勤务开始日期",
trigger: "change"
}
],
qwjssj: [
{
required: true,
message: "请选择勤务结束日期",
trigger: "change"
}
],
zxfw: [
{
required: true,
message: "请选择执行范围",
trigger: "change"
}
]
});
onMounted(() => {
emitter.on("showAddQw", (res) => {
dialogFormVisiblejs.value = true;
});
});
onUnmounted(() => {
emitter.off("showAddQw");
});
//提交
function submit() {
form.value.pzrId = getItem("USERID") + "";
elform.value.validate((valid) => {
if (valid) {
btnLoading.value = true;
setTimeout(() => {
btnLoading.value = false;
}, 1500);
addQwdj(form.value).then(() => {
proxy.$message({
type: "success",
message: "新增成功"
});
dialogFormVisiblejs.value = false;
});
}
});
}
</script>
<style lang="scss" scoped>
.but_box {
text-align: center;
}
::v-deep .el-input__inner,
::v-deep .el-input.is-disabled .el-input__inner {
background: #001238;
border: 1px solid #03438b;
color: #fff;
}
::v-deep .el-range-input,
::v-deep .el-input-number__decrease,
::v-deep .el-input-number__increase {
background: #001238;
color: #fff;
}
::v-deep .el-range-separator {
color: #fff;
}
::v-deep .el-form--inline {
display: flex;
flex-wrap: wrap;
padding: 0rem 12rem 0rem 12rem;
}
::v-deep .el-form-item--default {
width: 23%;
padding-bottom: 1.5rem;
margin: 0 1%;
}
::v-deep .el-form-item--default.two {
width: 46%;
padding-bottom: 1.5rem;
margin: 0 1%;
}
::v-deep .el-form-item--default.one {
width: 92%;
padding-bottom: 1.5rem;
margin: 0 1%;
}
::v-deep .el-textarea__inner {
height: 5.5em;
border: 1px solid #07376d;
background-color: #02163b;
color: #fff;
}
::v-deep .el-dialog{
background: #02163b;
}
::v-deep .el-dialog__title{
color: #fff;
}
::v-deep .el-form-item__label{
color: #fff;
}
::v-deep.el-form{
max-height: 74vh;
overflow: hidden;
overflow-y: auto;
}
</style>

View File

@ -0,0 +1,94 @@
<!--
* @Author: your name
* @Date: 2024-07-01 10:34:30
* @LastEditTime: 2024-07-04 10:11:46
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \my_web_new_gd\src\views\largeScreen\home\components\dialog\ajInfo.vue
-->
<template>
<div class="dialogBox">
<div class="title">
<span class="mc">警情详情</span>
<span @click="close" class="close">
<el-icon><Close /></el-icon>
</span>
</div>
<div class="box-contant" style="padding: 4px 10px; box-sizing: border-box">
<div v-for="(item, index) in props.data" :key="index">
<div class="infoBox">
<JqItm :data="item" :isDetail="true"></JqItm>
</div>
<div class="btnBox">
<button class="dp-default small" @click="handleGroup(item)">
推荐处警巡组
</button>
<button class="dp-default small">现场视频</button>
<button class="dp-default small" @click="handleVideo(item)">
周边视频
</button>
<button class="dp-default small" @click="XZBtnShowFn(item)">
指定处置
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import JqItm from "@/views/largeScreen/home/components/jqIem.vue";
import { ref, defineProps } from "vue";
import { useRouter } from "vue-router";
import emitter from "@/utils/eventBus.js"; // 左右折叠状态
import { addNewEvent } from "@/api/dpApi/home.js";
const props = defineProps({
data: {
type: Array,
default: []
}
});
const router = useRouter();
//关闭弹窗
function close() {
emitter.emit("showAj", false);
emitter.emit("deletePointArea", "jq");
emitter.emit("removePlot", "PIOT");
}
// 周边视频
function handleVideo(item) {
emitter.emit("videoClick", item);
}
//出警巡组
function handleGroup(item) {
if (item.jd && item.wd) {
emitter.emit("showZbxz", { data: item, type: "jq" });
} else {
ElMessage({ message: "该警情暂时没有经纬度!", type: "warning" });
}
}
//先用转为指令弹窗
function XZBtnShowFn(item) {
let obj = { type: "jq", data: item };
emitter.emit("showXZBtn", obj);
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.box-contant {
max-height: 700px;
overflow: hidden;
overflow-y: auto;
}
.btnBox{
text-align: center;
button{
margin: 0 2px;
}
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<div class="dialogBox">
<div class="title">
<span class="mc">公安资源</span>
<span @click="close" class="close">
<el-icon><Close /></el-icon>
</span>
</div>
<div v-if="info" class="containner">
<div class="info-contant" v-for="(ele, index1) in info.data" :key="index1">
<div class="infoBox">
<div>{{ ele.gajgmc }}</div>
<div class="other">所属部门{{ ele.ssbm }}</div>
</div>
<div class="groupList" v-loading="loading" v-if=" ele.identification == 'jwz' || ele.identification == 'pcs' || ele.identification == 'xfq'">
<div class="other"><p>巡防巡组列表{{ele.list instanceof Array}}</p></div>
<ul v-if ="ele.list">
<li class="chidrensItem" v-for="(item, index) in ele.list" :key="index">
<div class="top">
<div class="top-cnt">
<span class="dian online" title="巡逻中"></span>
<span class="name">{{ item.jzMc }}</span><br />
<span class="other">民警{{ item.mjsl }}辅警{{ item.fjsl }}</span><br />
<span class="other">联系电话{{ item.fzrLxdh }}</span><br />
<span>巡逻时长{{ item.xfsc ? item.xfsc : 0 }} h巡逻里程{{ item.xflc ? item.xflc : 0 }}km</span>
</div>
<span class="imgBtn">
<img src="@/assets/images/situationPresentation/shipin.png" />
<img src="@/assets/images/situationPresentation/tel.png" />
</span>
</div>
<div class="address">
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ item.dqwz }}</span>
</div>
</li>
</ul>
<el-empty description="没有数据" :image-size="0.1" v-if="!loading && ele && ele.list.length <= 0"/>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, reactive, watch } from "vue";
import { getSelectDeckList, pcsHasXz } from "@/api/dpApi/home.js";
// 左右折叠状态
import emitter from "@/utils/eventBus.js";
const props = defineProps({
data: {
type: Object,
default: {}
}
});
const data = ref();
const info = reactive({ data: [] }); //警情数据
const loading = ref(false);
watch(
() => props.data,
(val) => {
if(val.length>0){
info.data = val;
if (val[0].identification == "jwz") {
val.forEach((item) => { item.list = [] ; getList(item); });
}
if (val[0].identification == "pcs") {
val.forEach((item) => { item.list = []; getPcsList(item); });
}
}
},
);
// 警务站
function getList(item) {
let data = { xfzt: 0, jd: item.jd, wd: item.wd, pageSize: 10086, pageCurrent: 1, radius: 300};
getSelectDeckList(data).then((res) => {
loading.value = false;
item.list = res.records ? res.records : [];
}).catch(() => {
loading.value = false;
});
}
// 派出所
function getPcsList(item) {
let data = { ysid: item.id};
pcsHasXz(data).then((res) => {
loading.value = false;
item.list = res.records ? res.records : [];
}).catch(() => {
loading.value = false;
});
}
//关闭弹窗
function close() {
emitter.emit("showGazy", false);
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.containner {
max-height: 700px;
overflow: hidden;
overflow-y: auto;
.info-contant {
padding: 0px 14px;
box-sizing: border-box;
.infoBox {
position: relative;
margin-bottom: 4px;
.other {
color: #779dcd;
list-style: none;
p {
margin: 0 2px;
}
}
}
.address {
padding: 4px 0;
box-sizing: border-box;
border-top: 1px solid #193074;
border-bottom: 1px solid #193074;
margin: 4px 0;
img {
margin-right: 4px;
}
}
}
ul.groupList {
margin-bottom: 0;
.chidrensItem {
.top {
position: relative;
.imgBtn {
position: absolute;
right: 0;
bottom: 2px;
img {
margin: 0 4px;
}
}
}
}
}
.info-contant:last-child(1) {
.address {
margin-bottom: 0;
border-bottom: none;
}
}
}
</style>

View File

@ -0,0 +1,197 @@
<template>
<div class="bigBox" v-if="modelValue">
<div class="container">
<div class="header">
<span class="title">{{ title }}</span>
<span class="close" @click="closeDialog">
<el-icon :size="22"><CircleClose /></el-icon>
</span>
</div>
<div class="search">
<el-form ref="formRef" :model="listQuery">
<el-form-item label="所属部门">
<MOSTY.Department width="200px" clearable v-model="listQuery.ssbmdm" />
</el-form-item>
&nbsp;<el-form-item label=" 姓名">
<el-input v-model="listQuery.jlxm" placeholder="请输入姓名"/>
</el-form-item>
&nbsp;<el-form-item label=" 警号">
<el-input v-model="listQuery.jh" placeholder="请输入警号"/>
</el-form-item>
<el-form-item>
<el-button class="serchBtn" @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="datalist">
<el-table ref="multipleUserRef" :data="list.tableData" border width="100%" height="100%">
<el-table-column label="序号" type="index" align="center" width="80"/>
<el-table-column prop="jlxm" show-overflow-tooltip align="center" label="姓名" />
<el-table-column prop="xbdm" align="center" label="性别">
<template #default="{ row }">
<dict-tag :options="D_BZ_XB" :value="row.xbdm" :tag="false" />
</template>
</el-table-column>
<el-table-column prop="sfzh" show-overflow-tooltip align="center" label="身份证号码" />
<el-table-column prop="ssbm" label="所属部门" align="center" />
<el-table-column prop="jh" label="警号" align="center" />
</el-table>
</div>
<div class="fenye">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
import { timeValidate } from "@/utils/time.js";
import { http } from "@/api/service";
import { ref, onMounted, onUnmounted, getCurrentInstance, reactive } from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_XB } = proxy.$dict("D_BZ_XB");
const list = reactive({
tableData: []
});
const title = ref("");
const modelValue = ref(false);
const total = ref(0);
const listQueryDefault = ref({})
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
ssbmdm: "",
jlxm: "",
jh: ""
});
onMounted(() => {
listQueryDefault.value = JSON.parse(JSON.stringify(listQuery.value))
emitter.on("showJLWindow", (res) => {
title.value = res == "mj" ? "在岗警力-民警":"在岗警力-辅警"
getList_Mj();
modelValue.value = true;
});
});
onUnmounted(() => {
emitter.off("showJLWindow");
});
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getList_Mj();
};
// pageSize 改变触发
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getList_Mj();
};
// 关闭弹窗
function closeDialog() {
modelValue.value = false;
listQuery.value = JSON.parse(JSON.stringify(listQueryDefault.value))
list.tableData = [];
}
// 搜索
function handleFilter() {
listQuery.value.pageCurrent = 1;
getList_Mj();
}
//重置
function reset() {
listQuery.value = JSON.parse(JSON.stringify(listQueryDefault.value))
handleFilter();
}
// 警力情况 - 民警 - 全部
function getList_Mj() {
let pramas = {
pageCurrent: listQuery.value.pageCurrent,
pageSize: listQuery.value.pageSize,
ssbmdm: listQuery.value.ssbmdm,
jlxm: listQuery.value.jlxm,
jh: listQuery.value.jh,
bbrq: timeValidate(new Date(), 'ymd')
};
if (title.value == "在岗警力-民警") {
pramas.jllx = "01";
http.getJlmj(pramas).then((res) => {
list.tableData = res.records;
total.value = res.total;
listQuery.value.pageCurrent = res.current;
});
} else {
pramas.jllx = "02";
http.getJlfj(pramas).then((res) => {
list.tableData = res.records;
total.value = res.total;
listQuery.value.pageCurrent = res.current;
});
}
}
</script>
<style lang="scss" scoped>
.bigBox {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 99;
.container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 80%;
height: 80vh;
background: #052342;
padding: 0 20px;
.header {
width: 100%;
height: 60px;
line-height: 60px;
.title {
float: left;
font-size: 16px;
}
.close {
float: right;
font-size: 16px;
cursor: pointer;
}
}
.datalist {
height: 60vh;
}
.fenye {
height: 60px;
}
}
}
.el-form {
display: flex;
}
.serchBtn {
margin-left: 20px;
}
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
</style>

View File

@ -0,0 +1,253 @@
<template>
<div class="bigBox" v-if="modelValue">
<div class="container">
<div class="header">
<span class="title">{{ title }}</span>
<span class="close" @click="closeDialog">
<el-icon :size="22"><CircleClose /></el-icon>
</span>
</div>
<div class="search">
<el-form ref="formRef" :model="listQuery">
<el-form-item label="所属部门">
<MOSTY.Department
width="200px"
clearable
v-model="listQuery.ssbmdm"
/>
</el-form-item>
&nbsp;&nbsp;
<el-form-item label=" 时间段">
<el-date-picker
v-model="timeRange"
popper-class="jl-time"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
range-separator=""
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开始时间"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button class="serchBtn" @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="datalist">
<el-table
ref="multipleUserRef"
:data="list.tableData"
border
width="100%"
height="100%"
>
<el-table-column
label="序号"
type="index"
align="center"
width="80"
/>
<el-table-column
prop="jlxm"
show-overflow-tooltip
align="center"
label="姓名"
>
</el-table-column>
<el-table-column
prop="xbdm"
show-overflow-tooltip
align="center"
label="性别"
>
<template #default="{ row }">
{{ row.sfzh.charAt(16) % 2 ? "男" : "女" }}
</template>
</el-table-column>
<el-table-column
prop="sfzh"
show-overflow-tooltip
align="center"
label="身份证号码"
>
</el-table-column>
<el-table-column
prop="ssbm"
label="所属部门"
show-overflow-tooltip
align="center"
></el-table-column>
<el-table-column
prop="lxdh"
label="联系电话"
align="center"
></el-table-column>
</el-table>
</div>
<div class="fenye">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
import { timeValidate } from "@/utils/time.js";
import { http } from "@/api/service";
import { ref, onMounted, reactive, onUnmounted } from "vue";
const timeRange = ref([])
const modelValue = ref(false);
const list = reactive({
tableData: []
});
const title = ref("");
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
ssbmdm: ""
});
onMounted(() => {
emitter.on("showJMLLWindow", (res) => {
title.value = res == "mj" ? "街面力量-民警" : "街面力量-辅警"
modelValue.value = true;
getList();
});
});
onUnmounted(() => {
emitter.off("showJMLLWindow");
});
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getList();
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getList();
};
function closeDialog() {
modelValue.value = false;
listQuery.value.ssbmdm = "";
listQuery.value.pageCurrent = 1;
listQuery.value.pageSize = 10;
list.tableData = [];
timeRange.value = []
}
// 搜索
function handleFilter() {
listQuery.value.pageCurrent = 1;
getList();
}
//重置
function reset() {
listQuery.value.ssbmdm = "";
listQuery.value.pageCurrent = 1;
timeRange.value = []
getList();
}
function getList() {
let pramas = {
pageNum: listQuery.value.pageCurrent,
pageSize: listQuery.value.pageSize,
xfbmdm: listQuery.value.ssbmdm
};
if(timeRange.value.length > 0){
pramas.startTime = timeRange.value[0]
pramas.endTime = timeRange.value[1]
}
pramas.jllx = title.value == "街面力量-民警" ? '01' : '02'
http.getjMJLmj(pramas).then((res) => {
list.tableData = res.records;
total.value = res.total
});
}
</script>
<style lang="scss" scoped>
.bigBox {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 99;
.container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 80%;
height: 80vh;
background: #052342;
padding: 0 20px;
.header {
width: 100%;
height: 60px;
line-height: 60px;
.title {
float: left;
font-size: 16px;
}
.close {
float: right;
font-size: 16px;
cursor: pointer;
}
}
.datalist {
height: 60vh;
}
.fenye {
height: 60px;
}
}
}
.el-form {
display: flex;
}
.serchBtn {
margin-left: 20px;
}
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-form-item{
align-items: center;
}
::v-deep .el-input__inner{
margin: 0 !important;
}
</style>

View File

@ -0,0 +1,272 @@
<template>
<div class="bigBox" v-if="modelValue">
<div
class="container"
:class="title == '街面巡组-实际列表' ? 'container1' : ''"
>
<div class="header">
<span class="title">{{ title }}</span>
<span class="close" @click="closeDialog">
<el-icon :size="22"><CircleClose /></el-icon>
</span>
</div>
<div class="search">
<el-form ref="formRef" :model="listQuery">
<el-form-item label="所属部门">
<MOSTY.Department width="200px" clearable v-model="listQuery.ssbmdm"/>
</el-form-item> &nbsp;&nbsp;
<el-form-item label=" 负责人">
<el-input v-model="listQuery.fzrXm" placeholder="请输入负责人" />
</el-form-item> &nbsp;&nbsp;
<el-form-item label=" 时间段">
<el-date-picker
v-model="timeRange"
popper-class="jl-time"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
range-separator=""
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开始时间"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button class="serchBtn" @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="datalist">
<el-table ref="multipleUserRef" :data="list.tableData" border width="100%" height="100%">
<el-table-column label="序号" type="index" align="center" width="80"/>
<el-table-column label="部门名称" show-overflow-tooltip align="center" prop="ssbm"/>
<el-table-column label="巡组名称" align="center" prop="jzMc">
<template #default="{ row }">
<div v-if="row.jzMc">{{ row.jzMc }}</div>
<div v-else>{{ row.fzrXm }}巡组</div>
</template>
</el-table-column>
<el-table-column label="报备类型" align="center">
<template #default="{ row }">
<dict-tag :options="D_BZ_BBFS" :value="row.bblx" :tag="false" />
</template>
</el-table-column>
<el-table-column label="巡逻时间" align="center" prop="kssj" width="146">
<template #default="{ row }">
<div v-show="row.bblx != '02'">{{ row.kssj + "至" + row.jssj }}</div>
</template>
</el-table-column>
<el-table-column label="巡逻车辆" align="center" prop="">
<template #default="{ row }">
<el-tag v-for="(item, index) in checkJson(row.pbcl)" :key="index" >{{ item }}</el-tag>
</template>
</el-table-column>
<el-table-column label="负责人" align="center" prop="fzrXm" />
<template v-if="title == '街面巡组-实际列表'">
<el-table-column label="巡逻时长" prop="xfsc" align="center" />
<el-table-column label="巡逻里程" prop="xflc" align="center" />
<!-- <el-table-column label="接收指令数" align="center" width="95" />
<el-table-column label="盘查人员数" align="center" width="95" />
<el-table-column label="盘查车辆数" align="center" width="95" /> -->
</template>
</el-table>
</div>
<div class="fenye">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
import { timeValidate } from "@/utils/time.js";
import { http } from "@/api/service";
import { ref, onMounted, getCurrentInstance, reactive, onUnmounted } from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_BBFS} = proxy.$dict("D_BZ_BBFS");
const timeRange = ref([])
const list = reactive({
tableData: []
});
const title = ref("");
onMounted(() => {
emitter.on("showJMXZWindow", (res) => {
title.value = res == "jh" ? "街面巡组-计划列表" : "街面巡组-实际列表"
getList();
modelValue.value = true;
});
});
function checkJson(e) {
let data = [];
if (e) {
data = JSON.parse(e).map((item) => item.jdchphm);
}
return data;
}
onUnmounted(() => {
emitter.off("showJMXZWindow");
});
const modelValue = ref(false);
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
ssbmdm: "",
fzrXm: ""
});
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getList();
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getList();
};
function closeDialog() {
modelValue.value = false;
listQuery.value.ssbmdm = "";
listQuery.value.fzrXm = "";
listQuery.value.pageCurrent = 1;
listQuery.value.pageSize = 20;
timeRange.value = []
list.tableData = [];
}
// 搜索
function handleFilter() {
listQuery.value.pageCurrent = 1;
getList();
}
//重置
function reset() {
listQuery.value.ssbmdm = "";
listQuery.value.fzrXm = "";
listQuery.value.pageCurrent = 1;
listQuery.value.pageSize = 20;
timeRange.value = []
getList();
}
function getList() {
let pramas = {
pageNum: listQuery.value.pageCurrent,
pageSize: listQuery.value.pageSize,
fzrXm: listQuery.value.fzrXm,
ssbmdm: listQuery.value.ssbmdm,
};
if(timeRange.value.length > 0){
pramas.startTime = timeRange.value[0]
pramas.endTime = timeRange.value[1]
}
if (title.value == "街面巡组-计划列表") {
pramas.xzlx = "01";
http.getJMXZ(pramas).then((res) => {
if (res.records) list.tableData = res.records;
total.value = res.total;
});
} else {
pramas.xzlx = "02";
http.selectSjjmxzList(pramas).then((res) => {
if (res.records) {
res.records.forEach((item) => {
if (item.xfsc != 0) item.xfsc = (item.xfsc / 3600).toFixed(2) + "/h";
if (item.xflc != 0) item.xflc = (item.xflc / 1000).toFixed(2) + "/KM";
});
list.tableData = res.records;
}
total.value = res.total;
});
}
}
</script>
<style lang="scss" scoped>
.bigBox {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 99;
.container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 80%;
height: 80vh;
background: #052342;
padding: 0 20px;
.header {
width: 100%;
height: 60px;
line-height: 60px;
.title {
float: left;
font-size: 16px;
}
.close {
float: right;
font-size: 16px;
cursor: pointer;
}
}
.datalist {
height: 60vh;
}
.fenye {
height: 60px;
}
}
.container1 {
width: 82%;
}
}
.el-form {
display: flex;
}
.serchBtn {
margin-left: 20px;
}
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-form-item{
align-items: center;
}
::v-deep .el-input__inner{
margin: 0 !important;
}
</style>

View File

@ -0,0 +1,278 @@
<template>
<div class="bigBox" v-if="modelValue">
<div class="container">
<div class="header">
<span class="title">{{ title }}</span>
<span class="close" @click="closeDialog">
<el-icon :size="22"><CircleClose /></el-icon>
</span>
</div>
<div class="search">
<el-form ref="formRef" :model="listQuery">
<el-form-item label="所属部门">
<MOSTY.Department width="200px" clearable v-model="listQuery.ssbmdm" />
</el-form-item> &nbsp;&nbsp;
<el-form-item label=" 时间段">
<el-date-picker
v-model="timeRange"
popper-class="jl-time"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
range-separator=""
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开始时间"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button class="serchBtn" @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="datalist">
<!-- 盘人 -->
<el-table
ref="multipleUserRef"
:data="list.tableData"
border
width="100%"
height="100%"
v-if="title == '盘查工作-盘人'"
>
<el-table-column
label="序号"
type="index"
align="center"
width="80"
/>
<el-table-column
prop="xm"
show-overflow-tooltip
align="center"
label="姓名"
/>
<el-table-column prop="xbdm" align="center" label="性别">
<template #default="{ row }">
<dict-tag :options="D_BZ_XB" :value="row.xbdm" :tag="false" />
</template>
</el-table-column>
<el-table-column
prop="sfzh"
align="center"
label="身份证号码"
show-overflow-tooltip
/>
<el-table-column
prop="bqxxsj"
align="center"
label="标签名称"
show-overflow-tooltip
/>
<el-table-column prop="pcclJgmc" align="center" label="盘查结果" />
<el-table-column prop="pcsj" label="盘查时间" align="center" />
<el-table-column prop="pcmjXm" label="盘查民警姓名" align="center" />
<el-table-column prop="pcmjJh" label="盘查民警警号" align="center" />
<el-table-column
prop="ssbm"
label="所属部门"
align="center"
show-overflow-tooltip
/>
</el-table>
<!-- 盘车 -->
<el-table
ref="multipleUserRef"
:data="list.tableData"
border
width="100%"
height="100%"
v-else
>
<el-table-column
label="序号"
type="index"
align="center"
width="80"
/>
<el-table-column prop="hphm" align="center" label="号牌号码" />
<el-table-column prop="jdcsyr" align="center" label="车主" />
<el-table-column prop="pcclJgmc" align="center" label="盘查结果" />
<el-table-column prop="pcsj" label="盘查时间" align="center" />
<el-table-column prop="pcmjXm" align="center" label="盘查民警姓名" />
<el-table-column prop="pcmjJh" align="center" label="盘查民警警号" />
<el-table-column prop="ssbm" label="所属部门" align="center" />
</el-table>
</div>
<div class="fenye">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
import { timeValidate } from "@/utils/time.js";
import { getPcclList, getPcryList } from "@/api/dpApi/home.js";
import { ref, onMounted, onUnmounted, getCurrentInstance, reactive } from "vue";
const timeRange = ref([])
const { proxy } = getCurrentInstance();
const { D_BZ_XB } = proxy.$dict("D_BZ_XB");
const list = reactive({
tableData: []
});
const title = ref("");
const modelValue = ref(false);
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
ssbmdm: ""
});
onMounted(() => {
emitter.on("showPCGZWindow", (res) => {
title.value = res == "pr" ? '盘查工作-盘人': '盘查工作-盘车'
res == "pr" ? getpcryList(): getpcclList()
modelValue.value = true;
});
});
onUnmounted(() => {
emitter.off("showPCGZWindow");
});
function closeDialog() {
modelValue.value = false;
listQuery.value.ssbmdm = "";
listQuery.value.pageCurrent = 1;
listQuery.value.pageSize = 20;
timeRange.value = []
list.tableData = [];
}
// 搜索
function handleFilter() {
listQuery.value.pageCurrent = 1;
title.value == "盘查工作-盘人" ? getpcryList(): getpcclList()
}
//重置
function reset() {
listQuery.value.ssbmdm = "";
listQuery.value.pageCurrent = 1;
timeRange.value = []
handleFilter()
}
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
title.value == "盘查工作-盘人" ? getpcryList(): getpcclList()
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
title.value == "盘查工作-盘人" ? getpcryList(): getpcclList()
};
// 盘人
function getpcryList() {
let pramas = {
pageCurrent: listQuery.value.pageCurrent,
pageSize: listQuery.value.pageSize,
ssbmdm:listQuery.value.ssbmdm
};
if(timeRange.value.length > 0){
pramas.startTime = timeRange.value[0]
pramas.endTime = timeRange.value[1]
}
getPcryList(pramas).then((res) => {
list.tableData = res.records;
total.value = res.total;
listQuery.value.pageCurrent = res.current;
});
}
//盘车
function getpcclList() {
let pramas = {
pageCurrent: listQuery.value.pageCurrent,
pageSize: listQuery.value.pageSize,
ssbmdm:listQuery.value.ssbmdm
};
getPcclList(pramas).then((res) => {
list.tableData = res.records;
total.value = res.total;
listQuery.value.pageCurrent = res.current;
});
}
</script>
<style lang="scss" scoped>
.bigBox {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 99;
.container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 80%;
height: 80vh;
background: #052342;
padding: 0 20px;
.header {
width: 100%;
height: 60px;
line-height: 60px;
.title {
float: left;
font-size: 16px;
}
.close {
float: right;
font-size: 16px;
cursor: pointer;
}
}
.datalist {
height: 60vh;
}
.fenye {
height: 60px;
}
}
}
.el-form {
display: flex;
}
.serchBtn {
margin-left: 20px;
}
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-form-item{
align-items: center;
}
::v-deep .el-input__inner{
margin: 0 !important;
}
</style>

View File

@ -0,0 +1,249 @@
<template>
<div class="bigBox" v-if="modelValue">
<div class="container">
<div class="header">
<span class="title">{{ title }}</span>
<span class="close" @click="closeDialog">
<el-icon :size="22"><CircleClose /></el-icon>
</span>
</div>
<div class="search">
<el-form ref="formRef" :model="listQuery">
<el-form-item label="所属部门">
<MOSTY.Department
width="200px"
clearable
v-model="listQuery.ssbmdm"
/>
</el-form-item>&nbsp;&nbsp;
<el-form-item label=" 时间段">
<el-date-picker
v-model="timeRange"
popper-class="jl-time"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
range-separator=""
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开始时间"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button class="serchBtn" @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="datalist">
<el-table
ref="multipleUserRef"
:data="list.tableData"
border
width="100%"
height="100%"
>
<el-table-column label="序号" type="index" align="center" width="80"/>
<el-table-column label="部门名称" align="center" prop="ssbm" show-overflow-tooltip />
<el-table-column label="巡组名称" align="center" prop="jzMc" >
<template #default="{ row }">
{{ row.jzMc|| row.fzrXm }}
</template>
</el-table-column>
<el-table-column label="报备类型" align="center">
<template #default="{ row }">
<dict-tag :options="D_BZ_BBFS" :value="row.bblx" :tag="false" />
</template>
</el-table-column>
<el-table-column label="计划巡逻时间" align="center" prop="kssj">
<template #default="{ row }">
<span v-show="row.bblx != '02'">{{ row.kssj + "至" + row.jssj }}</span>
</template>
</el-table-column>
<el-table-column label="实际巡逻时间" align="center" prop="bbkssj" />
<el-table-column label="巡逻车辆" align="center" prop="">
<template #default="{ row }">
<el-tag v-for="(item, index) in row.pbcl" :key="index">
{{ item.jdchphm }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="负责人" align="center" prop="fzrXm" />
<el-table-column label="巡逻时长" align="center" prop="xfsc" />
<el-table-column label="巡逻里程" align="center" prop="xflc" />
</el-table>
</div>
<div class="fenye">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
import { timeValidate } from "@/utils/time.js";
import { http } from "@/api/service";
import {
defineProps,
watch,
ref,
onMounted,
nextTick,
onUnmounted,
getCurrentInstance,
reactive
} from "vue";
const timeRange = ref([])
const { proxy } = getCurrentInstance();
const { D_BZ_BBFS} = proxy.$dict("D_BZ_BBFS");
const list = reactive({
tableData: []
});
const modelValue = ref(false);
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
ssbmdm: ""
});
const title = ref("");
onMounted(() => {
emitter.on("showXLSCWindow", (res) => {
title.value = res == "xs" ? "巡逻时长-小时(h)" : "巡逻时长-里程(km)"
getList_Mj();
modelValue.value = true;
});
});
onUnmounted(() => {
emitter.off("showXLSCWindow");
});
// page改变触发
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getList_Mj();
};
// pageSize 改变触发
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getList_Mj();
};
// 关闭弹窗
function closeDialog() {
modelValue.value = false;
listQuery.value.ssbmdm = "";
listQuery.value.pageCurrent = 1;
listQuery.value.pageSize = 20;
list.tableData = [];
timeRange.value = []
}
// 搜索
function handleFilter() {
listQuery.value.pageCurrent = 1;
getList_Mj();
}
//重置
function reset() {
listQuery.value.ssbmdm = "";
timeRange.value = []
handleFilter()
}
// 在线
function getList_Mj() {
let pramas = {
pageNum: listQuery.value.pageCurrent,
pageSize: listQuery.value.pageSize,
ssbmdm: listQuery.value.ssbmdm
};
if(timeRange.value.length > 0){
pramas.startTime = timeRange.value[0]
pramas.endTime = timeRange.value[1]
}
pramas.xzlx = "02";
http.selectSjjmxzList(pramas).then((res) => {
if (res.records) {
res.records.forEach((item) => {
if (item.xfsc != 0) item.xfsc = (item.xfsc / 3600).toFixed(2) + "/h";
if (item.xflc != 0) item.xflc = (item.xflc / 1000).toFixed(2) + "/KM";
item.pbcl = item.pbcl?JSON.parse(item.pbcl):[]
});
list.tableData = res.records;
}
total.value = res.total;
});
}
</script>
<style lang="scss" scoped>
.bigBox {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 99;
.container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 80%;
height: 80vh;
background: #052342;
padding: 0 20px;
.header {
width: 100%;
height: 60px;
line-height: 60px;
.title {
float: left;
font-size: 16px;
}
.close {
float: right;
font-size: 16px;
cursor: pointer;
}
}
.datalist {
height: 60vh;
}
.fenye {
height: 60px;
}
}
}
.el-form {
display: flex;
}
.serchBtn {
margin-left: 20px;
}
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-form-item{
align-items: center;
}
::v-deep .el-input__inner{
margin: 0 !important;
}
</style>

View File

@ -0,0 +1,244 @@
<template>
<div class="bigBox" v-if="modelValue">
<div class="container">
<div class="header">
<span class="title">{{ title }}</span>
<span class="close" @click="closeDialog">
<el-icon :size="22"><CircleClose/></el-icon>
</span>
</div>
<div class="search">
<el-form ref="formRef" :model="listQuery">
<el-form-item label="所属部门">
<MOSTY.Department
width="200px"
clearable
v-model="listQuery.ssbmdm"
/>
</el-form-item>&nbsp;&nbsp;
<el-form-item label=" 时间段">
<el-date-picker
v-model="timeRange"
popper-class="jl-time"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
range-separator=""
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开始时间"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button class="serchBtn" @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="datalist">
<el-table
ref="multipleUserRef"
:data="list.tableData"
border
width="100%"
height="100%"
>
<el-table-column
label="序号"
type="index"
align="center"
width="80"
/>
<el-table-column label="所属部门" show-overflow-tooltip align="center" prop="ssbm"></el-table-column>
<el-table-column label="指令标题" show-overflow-tooltip align="center" prop="zlbt"></el-table-column>
<el-table-column label="指令内容" show-overflow-tooltip align="center" prop="zlnr"></el-table-column>
<el-table-column label="接收警情数" show-overflow-tooltip align="center" width="100">0</el-table-column>
<el-table-column label="处置警情数" show-overflow-tooltip align="center" width="100">0</el-table-column>
<el-table-column label="接收指令数" show-overflow-tooltip align="center" width="100">0</el-table-column>
<el-table-column label="执行指令数" show-overflow-tooltip align="center" width="100">0</el-table-column>
<el-table-column label="盘查人员数" show-overflow-tooltip align="center" width="100">0</el-table-column>
<el-table-column label="盘查车辆数" show-overflow-tooltip align="center" width="100">0</el-table-column>
</el-table>
</div>
<div class="fenye">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
import { dateFormat } from "@/utils/auth.js";
import { http } from "@/api/service";
import { getSelectLiist } from "@/api/dpApi/home.js";
import {
defineProps,
watch,
ref,
onMounted,
onUnmounted,
nextTick,
getCurrentInstance,
reactive
} from "vue";
const timeRange = ref([])
const { proxy } = getCurrentInstance();
const { D_BZ_XB } = proxy.$dict("D_BZ_XB");
const list = reactive({
tableData: []
});
const title = ref("");
onMounted(() => {
emitter.on("showZlzxWindow", (res) => {
if (res == "zs") {
title.value = "指令执行情况-总数";
}
if (res == "zx") {
title.value = "指令执行情况-执行";
}
getList();
modelValue.value = true;
});
});
onUnmounted(() => {
emitter.off("showZlzxWindow");
});
const modelValue = ref(false);
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
ssbmdm: ""
});
const form = ref({
current: 1,
size: 20,
zblx: "",
ssbm: "",
gzsj: ""
});
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getList();
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getList();
};
function closeDialog() {
modelValue.value = false;
listQuery.value.ssbmdm = "";
listQuery.value.pageCurrent = 1;
listQuery.value.pageSize = 20;
timeRange.value = []
list.tableData = [];
}
// 搜索
function handleFilter() {
listQuery.value.pageCurrent = 1;
getList();
}
//重置
function reset() {
listQuery.value.ssbmdm = "";
listQuery.value.pageCurrent = 1;
timeRange.value = []
getList();
}
// 警力情况 - 民警 - 全部
function getList() {
let pramas = {
pageNum: listQuery.value.pageCurrent,
pageSize: listQuery.value.pageSize,
ssbmdm: listQuery.value.ssbmdm,
startTime: dateFormat(new Date(), "YY-MM-DD")+ ' 00:00:00',
};
if(timeRange.value.length > 0){
pramas.startTime = timeRange.value[0]
pramas.endTime = timeRange.value[1]
}
if (title.value == "指令执行情况-执行") {
pramas.zlwjzt = "91";
}
getSelectLiist(pramas).then((res) => {
list.tableData = res.records;
total.value = res.total;
listQuery.value.pageCurrent = res.current;
});
}
</script>
<style lang="scss" scoped>
.bigBox {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 99;
.container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 80%;
height: 80vh;
background: #052342;
padding: 0 20px;
.header {
width: 100%;
height: 60px;
line-height: 60px;
.title {
float: left;
font-size: 16px;
}
.close {
float: right;
font-size: 16px;
cursor: pointer;
}
}
.datalist {
height: 60vh;
}
.fenye {
height: 60px;
}
}
}
.el-form {
display: flex;
}
.serchBtn {
margin-left: 20px;
}
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-form-item{
align-items: center;
}
::v-deep .el-input__inner{
margin: 0 !important;
}
</style>

View File

@ -0,0 +1,131 @@
<!--
* @Author: your name
* @Date: 2022-09-20 10:22:51
* @LastEditTime: 2024-02-19 11:40:22
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \rs-web\src\views\situationPresentation\dialog\gzyInfo.vue
-->
<template>
<div class="dialogBox" >
<div class="title">
<span class="mc">感知源</span>
<span @click="close" class="close"><el-icon><Close /></el-icon> </span>
</div>
<div class="videoLIstBox">
<div v-for="(item, index) in info" :key="index">
<div class="infoBox">
<div class="content">{{ item.sbmc }}</div>
<div class="other">
<p>设备编号{{ item.sbbh }}</p>
<p>所属部门{{ item.ssbm }}</p>
<p class="itemBox">
<span>厂商名称{{ item.csmc }}</span>
<button class="dp-default small" v-if="item.isPlay" @click="closePlay(item.id)"> 关闭 </button>
<button v-else class="dp-default small" @click="openVideo(item)">播放 </button>
</p>
<div class="videoBox" :id="'id_'+item.sbbh" v-if="item.isPlay">
</div>
</div>
<div class="addressBox">
<div class="ddd">
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ item.dzmc }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, getCurrentInstance, watch } from "vue";
// import VideoPay from "@/components/wsVideoSenior/wsPlayOne/index"; //ws播放高阶
// import VideoPay from "@/components/videoOne/index"; //ws播放
import VideoPay from "@/components/wsVideoSenior/wsIframe/index"; //iframe播放
import emitter from "@/utils/eventBus.js";
const { proxy } = getCurrentInstance();
const props = defineProps({
data:{
type:Array,
default:[]
}
})
const info = ref([])
watch(()=>props.data,(val)=>{
info.value = val
},{
immediate:true
})
// 打开视频
function openVideo(item) {
if (!item.sbbh) return proxy.$message({ type: "info", message: "暂无视频" });
SPPUC.rdCard(item.sbbh, 1, ["10%", "40%"]);
}
//关闭视频
function closePlay(id) {
info.value.forEach((item) => {
if (item.id == id) item.isPlay = false;
});
}
//关闭弹窗
function close() {
emitter.emit("deletePointArea", "lang");
emitter.emit("showGzy", false);
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.dialogBox{
padding: 0 0 10px 0;
box-sizing: border-box;
.title {
border-bottom: 1px solid #275288;
margin-bottom: 6px;
.mc { margin-left: 10px; }
}
.videoLIstBox {
max-height: 680px;
padding: 4px 10px;
box-sizing: border-box;
overflow: hidden;
overflow-y: auto;
.infoBox {
position: relative;
padding: 4px 10px;
box-sizing: border-box;
border-bottom: 1px solid #20557c;
.content {
padding: 10px 10px 0 10px;
font-size: 14px;
}
.other {
margin: 0 10px;
padding: 0px;
color: #779dcd;
list-style: none;
.itemBox {
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
span {
display: inline-block;
}
}
.videoBox {
height: 160px;
background: #000;
}
p { margin: 5px 0; }
}
}
}
}
.ddd{
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<div class="ingBigBox" v-if="isShowBigImg">
<div class="demo-image__preview">
<el-image
style="width: 100px; height: 100px"
:src="imgUrl"
:preview-src-list="srcList"
:initial-index="0"
fit="cover"
/>
</div>
</div>
</template>
<script setup>
import { ref, defineEmits, onMounted, onUnmounted } from "vue";
import emitter from "@/utils/eventBus.js";
const isShowBigImg = ref(false);
const imgUrl = "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg";
const srcList = ["https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg"];
onMounted(() => {
emitter.on("showImg", (res) => {
isShowBigImg.value = res.show;
imgUrl.value = res.url;
});
});
onUnmounted(() => {
emitter.off("showImg");
});
</script>
<style lang="scss" scoped>
.ingBigBox {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
background: rgba(0, 0, 0, 0.6);
z-index: 99;
display: flex;
justify-content: center;
align-items: center;
.cnt-box {
width: 500px;
height: 500px;
background: #00143d;
padding: 10px 20px 20px;
.close {
width: 100%;
height: 20px;
text-align: right;
margin-bottom: 10px;
}
.imgBox {
width: 100%;
height: calc(100% - 30px);
border: 1px solid #275288;
display: flex;
justify-content: center;
align-items: center;
img {
max-width: 100%;
max-height: 100%;
}
}
}
}
.demo-image__error .image-slot {
font-size: 30px;
}
.demo-image__error .image-slot .el-icon {
font-size: 30px;
}
.demo-image__error .el-image {
width: 100%;
height: 200px;
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<div class="dialogBox">
<div class="title">
<span class="mc">指令信息</span
><span @click="close" class="close">
<el-icon><Close /></el-icon>
</span>
</div>
<ul style="padding: 4px 10px; box-sizing: border-box;">
<li v-for="(item, index) in props.data" :key="index">
<div class="infoBox">
<ZlItm :data="item" :isDetail="true" :dic="{ zlzt: D_BZ_ZXZTAI }"/>
</div>
<div class="btnBox">
<button class="dp-default small" @click="policeGroupShowFn(item)" v-if="item.zlly != '03'">
推荐处警巡组
</button>
<button class="dp-default small" @click="videoShowSs(item)" v-if="item.zlly != '03'">
实时视频
</button>
<button class="dp-default small" @click="warningListShowYjgj(item)" v-if="item.zlly != '03'">
预警轨迹
</button>
<button class="dp-default small" @click="CKDTShowFn(item)">
查看动态
</button>
</div>
</li>
</ul>
<MessageLoad
v-if="activeMessage"
v-model="activeMessage"
:data="zlxxInfo"
@upData="activeMessage = false"
/>
</div>
</template>
<script setup>
import ZlItm from "@/views/largeScreen/home/components/zlItem.vue";
import MessageLoad from "./MessageLoad.vue";
import { ref, defineProps, getCurrentInstance } from "vue";
import emitter from "@/utils/eventBus.js";
import { ElMessage } from "element-plus";
import { getDetailZl } from "@/api/dpApi/home.js";
const props = defineProps({
data: {
type: Array,
default: []
}
});
const zlInfo = ref(false);
const activeMessage = ref(false);
const zlxxInfo = ref(null);
const { proxy } = getCurrentInstance();
const { D_BZ_ZXZTAI } = proxy.$dict("D_BZ_ZXZTAI");
// 显示周边巡组
function policeGroupShowFn(item) {
if(item.jd && item.wd){
emitter.emit("showZbxz", item);
}else{
ElMessage({ message: "暂无巡组信息", type: "warning" });
}
}
//显示实时视频
function videoShowSs(item) {
emitter.emit("closeVideo", false);
if (item.zlly == "01") {
if (item.sbbh !== null) {
let params = { ...item, splitNum: 1 };
emitter.emit("openGzyVideo", params);
} else {
ElMessage({ message: "没有设备编号,无法播放视频", type: "warning" });
}
} else {
ElMessage({
message: "非预警指令,无感知源信息,无法播放视频",
type: "warning"
});
}
}
//查看动态按钮
function CKDTShowFn(item) {
zlxxInfo.value = item;
activeMessage.value = true;
}
//显示预警轨迹
function warningListShowYjgj(item) {
if (item.ywId) {
getDetailZl(item.ywId).then((res) => {
if (res) {
emitter.emit("showCcyj", res);
} else {
ElMessage({ message: "暂无预警轨迹信息", type: "warning" });
}
});
} else {
ElMessage({ message: "暂无预警轨迹信息", type: "warning" });
}
}
//关闭弹窗
function close() {
emitter.emit("showYjzl", false);
emitter.emit("deletePointArea", "zl");
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.btnBox{
display: flex;
justify-content: center;
.dp-default{
margin: 0 4px;
}
}
</style>

View File

@ -0,0 +1,127 @@
<template>
<div
:style="{ top: props.topDistance }"
:class="['box',isButtom ? 'isButtom' : '',title == '圈层设置' ? 'bigbox1' : '']"
v-if="show"
>
<div class="title_box">
<span>{{ title }}{{ props.topDistance }}</span>
<el-icon size="16px" style="cursor: pointer" @click="handleGroup">
<Close />
</el-icon>
</div>
<!-- 自定义内容 -->
<slot />
<div class="address_box" v-if="showAddress">
<el-icon size="18px" color="#779DCD">
<LocationFilled />
</el-icon>
<span>四川省眉山市仁寿县红星路29号</span>
</div>
<div class="but_box" v-if="showbut">
<span
:class="['but', butList.length == 1 ? 'oneBut' : '']"
v-for="(item, index) in butList"
:key="item"
@click="onClickBut(index)"
>{{ item }}</span
>
</div>
</div>
</template>
<script setup>
import { reactive, getCurrentInstance, defineEmits } from "vue";
const emit = defineEmits(["handleIdentity"]);
const { proxy } = getCurrentInstance();
//参数
const props = defineProps({
//是否显示
show: Boolean,
//是否显示详情
//是否显示地址
showAddress: Boolean,
//是否显示按钮
showbut: Boolean,
//按钮数据
butList: Array,
//是否显示在底部
isButtom: Boolean,
//标题
title: String,
topDistance: String
});
//关闭弹窗
function handleGroup() {
emit("handleIdentity", false);
}
function onClickBut(index) {
proxy.mittBus.emit("dialogClickBut", {
index,
count: props.butList.length
});
}
</script>
<style lang="scss" scoped>
.box {
position: absolute;
width: 364px;
background: rgba(5, 35, 66, 0.98);
padding: 10px;
border-radius: 5px;
z-index: 11;
left: 388px;
top: 100px;
.but_box {
display: flex;
justify-content: center;
> span {
margin: 0 4px;
}
}
.address_box {
color: #779dcd;
display: flex;
align-items: center;
justify-content: center;
padding: 10px 0;
> span {
margin-left: 5px;
}
}
.title_box {
display: flex;
justify-content: space-between;
}
}
// 按钮样式
.but {
padding: 3px 7px;
background: rgba(37, 202, 255, 0);
border: 1px solid #3180ea;
box-shadow: 0px 0px 17px 1px rgba(43, 140, 230, 0.26);
border-radius: 4px;
color: #fff;
cursor: pointer;
}
.oneBut {
padding: 3px 25px;
}
.isButtom {
top: unset;
bottom: 0px !important;
}
::v-deep .el-form-item__label {
color: #fff;
}
</style>

View File

@ -0,0 +1,207 @@
<template>
<div class="dialogBox">
<div class="title">
<span class="mc">{{ title }}</span>
<span class="close" @click="close">
<el-icon :size="22"><CircleClose /></el-icon>
</span>
</div>
<ul class="shebeiList" ref="scollVideo">
<li v-for="item in videoList.list" :key="item.id">
<div> {{ item.sbmc }} </div>
<div class="top">
<span class="other">{{ item.distance ? item.distance.toFixed(0) : 0 }}m</span>
<span>
<button class="dp-default small" v-if="!item.isPlay" @click="handlePlay(item)"> 播放 </button>
<button class="dp-default small" v-if="item.isPlay" @click="closePlay(item.id)" > 关闭 </button>
</span>
</div>
<div class="address">
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ item.dzmc }}</span>
</div>
<div class="videoBox" v-if="item.isPlay">
<VideoPay key="item.id" :vId="'sb_'+index" :sbbh="item.sbbh"></VideoPay>
</div>
</li>
<el-empty
description="没有数据"
:image-size="0.1"
v-if="!loading && videoList.list.length <= 0"
/>
</ul>
</div>
</template>
<script setup>
import { http } from "@/api/service";
// import VideoPay from "@/components/wsVideoSenior/wsPlayOne/index"; //ws播放高阶
// import VideoPay from "@/components/videoOne/index"; //ws播放
import VideoPay from "@/components/wsVideoSenior/wsIframe/index"; //iframe播放
import { getZbVideoList, getVideoSdList } from "@/api/dpApi/video.js";
import {
ref,
defineEmits,
onMounted,
reactive,
onUnmounted,
defineProps,
getCurrentInstance
} from "vue";
const { proxy } = getCurrentInstance();
import emitter from "@/utils/eventBus.js";
const loading = ref(false);
const page = ref(1);
const total = ref(0);
//周边视频列表
const videoList = reactive({
list: []
});
const scollVideo = ref(null);
const props = defineProps({
//某条预警详情
info: Object,
//弹框标题
title: String
});
const emit = defineEmits(["close"]);
onMounted(() => {
//打开周边视频
_getZbVideoList(props.info);
scroll();
emitter.on("closeVideo", (res) => {
emit("close", res);
});
});
onUnmounted(() => {
emitter.off("closeVideo");
});
//关闭
function close() {
emit("close", false);
}
// 获取地址
function getws(item) {
let pramas = {
cameraIndexCode: item.sbbh
};
http.getSpWs(pramas).then((res) => {
item.src = "http://80.75.112.18:56233?ws=" + res.url;
});
}
//获取视频列表
function _getZbVideoList(info) {
if (info.jd && info.wd) {
let data = {
jd: info.jd,
wd: info.wd,
radius: 300,
sblx: "01"
};
loading.value = true;
if (props.title == "周边视频") {
getZbVideoList(data).then((res) => {
videoList.list = res || [];
loading.value = false; })
.catch(() => {
loading.value = false;
});
} else {
//获取视频随动列表
data.pageSize = 4;
data.pageNum = 1;
getVideoSdList(data).then((res) => {
videoList.list = res.records ? res.records : [];
videoList.list.forEach(item=> { v.isPlay = false; });
loading.value = false;
}).catch(() => {
loading.value = false;
});
}
} else {
proxy.$message({type: "warning", message: "获取经纬度失败"});
}
}
// 处理播放
function handlePlay(item) {
if (!item.sbbh) return proxy.$message({ type: "info", message: "暂无视频" });
SPPUC.rdCard(item.sbbh, 1, ["60%", "40%"]);
}
// 关闭播放
function closePlay(id) {
videoList.list.forEach((item) => {
if (item.id == id) {
item.isPlay = false;
}
});
}
//触底加载
function scroll() {
let scrollTargetBox = scollVideo.value;
scrollTargetBox.onscroll = (e) => {
var scrollHeight = scrollTargetBox.scrollHeight; //251
var scrollTop = scrollTargetBox.scrollTop; //0-18
var clientHeight = scrollTargetBox.clientHeight; //233
if (scrollHeight - clientHeight == scrollTop) {
//滚动条滚到最底部
if (videoList.list.length < total.value) {
page.value++;
_getZbVideoList(props.info);
}
}
};
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.dialogBox{
padding: 0 0 10px 0;
box-sizing: border-box;
.title {
border-bottom: 1px solid #275288;
margin-bottom: 6px;
.mc { margin-left: 10px; }
}
.shebeiList {
padding: 4px 10px;
box-sizing: border-box;
max-height: 700px;
overflow: hidden;
overflow-y: auto;
li{
border: 1px solid #275288;
padding: 4px 10px;
box-sizing: border-box;
margin-bottom: 4px;
.top{
display: flex;
justify-content: space-between;
align-items: center;
}
.address{
line-height: 30px;
img{
margin-right: 10px;
}
}
}
}
.videoBox{
margin: 0 10px;
border: 1px solid#2b4462;
background: #000;
height: 200px;
margin-bottom: 8px;
>img {
width: 100%;
height: 100%;
}
}
}
</style>

View File

@ -0,0 +1,192 @@
<template>
<div class="dialogBox" v-if="show">
<div class="title">
<span class="mc">巡组列表</span>
<span class="close" @click="show = false">×</span>
</div>
<div class="search">
<el-input v-model="keyWord" clearable placeholder="请输入部门或者负责人姓名">
<template #append>
<el-button icon="Search" @click="_ggetSelectDeckList('0,1,2')"></el-button>
</template>
</el-input>
</div>
<ul class="groupList noScollLine" v-loading="loading">
<li v-for="item in xzList.list" :key="item.id" @click="item.isChecked = !item.isChecked" :class="item.isChecked?'isChecked':''">
<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.mjsl }}辅警{{ item.fjsl }}</span ><br />
<span class="other">联系电话{{ item.fzrLxdh }}</span ><br />
<span>巡逻时长{{ item.xfsc ? item.xfsc : 0 }} h<br />巡逻里程{{ item.xflc ? item.xflc : 0 }}km</span>
</div>
<div class="imgBtn">
<img src="@/assets/images/situationPresentation/shipin.png" />
<img src="@/assets/images/situationPresentation/tel.png" />
</div>
</div>
<div class="address">
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ item.dqwz }}</span>
</div>
</li>
<el-empty description="没有数据" :image-size="0.1" v-if="!loading && xzList.list.length <= 0" />
</ul>
<div class="btnBox">
<button class="dp-default" @click="buttonSubmit">确定</button>
</div>
</div>
</template>
<script setup>
import { qcckGet } from "@/api/qcckApi.js";
import { ref, reactive, onMounted, onUnmounted, getCurrentInstance } from "vue";
import emitter from "@/utils/eventBus.js";
import { getSelectDeckList } from "@/api/dpApi/home.js";
const show = ref(false);
const { proxy } = getCurrentInstance();
let xzList = reactive({ list: [] }); //巡组数据
const loading = ref(true); //警组加载
const pageSize = ref(500);
const pageCurrent = ref(1);
const totalPage = ref(0);
const type = ref("");
const dataObj = ref({});
const keyWord = ref('') //输入关键字
onMounted(() => {
emitter.on("showXZBtn", (res) => {
show.value = true;
type.value = res.type;
dataObj.value = res.data;
xzList.list = []
_ggetSelectDeckList('0,1,2');
});
emitter.on("closeAllDialog", (res) => {
show.value = false;
});
});
onUnmounted(() => {
emitter.off("closeAllDialog");
emitter.off("showXZBtn");
});
//巡组列表
function _ggetSelectDeckList(xfzt) {
let data = {
xfzt,
pageSize: pageSize.value,
pageCurrent: pageCurrent.value,
keyword:keyWord.value,
};
getSelectDeckList(data).then((res) => {
loading.value = false;
totalPage.value = res.records.length;
xzList.list = []
if (res.records.length > 0) {
for (let i = 0; i < res.records.length; i++) {
res.records[i].isChecked = false
let num = Number(res.records[i].xfsc) || 0
res.records[i].xfsc = (num/3600).toFixed(1)
let lc = Number(res.records[i].xflc) || 0
res.records[i].xflc = (lc/1000).toFixed(2)
xzList.list.push(res.records[i]);
}
}
}).catch(() => {
loading.value = false;
});
}
// 下发指令
function buttonSubmit() {
let list = xzList.list.filter((item) => { return item.isChecked; });
let ids = list.map((res) => { return res.id; }).join(",");
if (ids.length <= 0) return proxy.$message({ type: "info", message: "请选择下发数据!" });
proxy.$confirm("确定要要下发指令", "警告", { type: "warning" }).then(() => {
let prams = { bbids: ids };
if (type.value == "jq") {
prams.jqid = dataObj.value.id;
qcckGet(prams, "/mosty-yjzl/tbZl/andJqZl").then((res) => {
proxy.$message({ type: "success", message: "下发成功" });
});
}
if (type.value == "yj") {
prams.yjid = dataObj.value.id;
qcckGet(prams, "/mosty-yjzl/tbZl/andYjZl").then((res) => {
proxy.$message({ type: "success", message: "下发成功" });
});
}
});
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.dialogBox {
padding: 0 0 10px 0;
box-sizing: border-box;
.title {
border-bottom: 1px solid #275288;
.mc { margin-left: 10px; }
}
.search{
padding: 0 8px;
box-sizing: border-box;
}
ul.groupList {
height: calc(100vh - 570px);
overflow: hidden;
overflow-y: auto;
padding: 4px 10px;
box-sizing: border-box;
li{
border: 1px solid #275288;
padding: 4px 10px;
box-sizing: border-box;
margin-bottom: 10px;
.top{
display: flex;
justify-content: space-between;
align-items: center;
}
.imgBtn{
display: flex;
img{ margin: 0 4px; }
}
.address{
line-height: 30px;
img{ margin-right: 10px; }
}
}
.isChecked{
border: 1px solid #cd6907;
box-shadow: inset 0 0 10px #ff6c00;
}
}
}
//加载时 取消背景
::v-deep .el-loading-mask {
background-color: transparent !important;
}
.dialogBox > .btnBox{
margin-bottom: 0px;
padding-top: 0px;
}
::v-deep .el-input-group--append .el-input__inner{
background-color: #062a48;
border: 1px solid #114260;
color: #fff;
}
::v-deep .el-input-group__append{
background: transparent;
border: 1px solid #0c4e77;
border-left: none;
}
</style>

View File

@ -0,0 +1,182 @@
<template>
<div class="dialogBox">
<!-- v-if="show" -->
<div class="title">
<span class="mc">推荐警力</span>
<span class="close" @click="closeDialog">×</span>
</div>
<ul class="groupList">
<li class="groupList-item" v-for="item in xzList" :key="item.id">
<div class="top">
<div @click="handelClick">
<span class="dian" title="离线" v-if="item.xfzt == 3"></span>
<span class="dian online" title="巡逻中" v-if="item.xfzt == 0"></span>
<span class="dian busy" title="处警中" v-if="item.xfzt == 1"></span>
<span class="name">{{ item.jzMc ? item.jzMc : item.fzrXm +'巡组'}}</span> <br />
<span>负责人{{ item.fzrXm }}({{ item.fzrLxdh }})</span><br />
</div>
</div>
<div class="address">
<div class="distance">
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span>距离{{ item.distance || 0 }}km</span>
</div>
<div class="numbPopljgh" @click="clickXfzl(item)">
<span>下发指令</span>
</div>
</div>
</li>
<el-empty
description="没有数据"
:image-size="0.1"
v-if="xzList.length <= 0"
/>
</ul>
</div>
</template>
<script setup>
import { qcckGet } from "@/api/qcckApi.js";
import emitter from "@/utils/eventBus.js";
import { ElMessage } from "element-plus";
import { selectDeckList } from "@/api/dpApi/zzzh.js";
import { ref, getCurrentInstance, watch } from "vue";
const { proxy } = getCurrentInstance();
const props = defineProps({
data: {
type: Object,
default: {}
}
});
const show = ref(false); //显示组件
const xzList = ref([]); //巡组列表
const pageSize = ref(10);
const pageCurrent = ref(1);
const type = ref("");
const dataObj = ref({});
watch(
() => props.data,
(res) => {
type.value = res.type;
dataObj.value = res.data ? res.data : res;
_getSelectDeckList(dataObj.value);
},
{
immediate: true
}
);
//获取巡组信息,
function _getSelectDeckList(val) {
let data = {
pageSize: pageSize.value,
pageCurrent: pageCurrent.value,
jd: val.jd,
wd: val.wd,
radius: 3000
};
selectDeckList(data).then((res) => {
xzList.value = res.records || [];
if (res.records.length > 0) {
show.value = true;
xzList.value.forEach((item, index) => {
let km = item.distance ? item.distance : 0;
item.distance = (km / 1000).toFixed(2);
let qd = `${val.jd},${val.wd}`;
let zd = `${item.jd},${item.wd}`;
if (val.jd && val.wd && item.jd && item.wd){
getRouteLine(qd, zd, { jd: item.jd, wd: item.wd });
}
});
} else {
ElMessage({ message: "暂无巡组信息", type: "warning" });
}
});
}
// 获取路径
function getRouteLine(qd, zd, obj) {
qcckGet({ qd, zd }, "/mosty-base/other/getLjgh").then((res) => {
emitter.emit("drawLine", { coord: res[0].points.coordinates, flag: "route" });
let km = res[0].distance ? res[0].distance : 0;
res[0].distance = (km / 1000).toFixed(2);
let prams = { jd: obj.jd, wd: obj.wd, distance: res[0].distance };
emitter.emit("showSquire", prams);
});
}
// 关闭弹窗
function closeDialog() {
emitter.emit("showZbxz", false);
emitter.emit("clearLine");
emitter.emit("clearmakerSqure");
emitter.emit("deletePointArea", "xzlxIcon");
emitter.emit("drawLineAnimation", "route");
}
//点击下发指令
function clickXfzl(item) {
proxy.$confirm("确定要要下发指令", "警告", { type: "warning" }).then(() => {
let prams = { jqid: dataObj.value.id, bbids: item.id };
if (type.value == "jq") {
qcckGet(prams, "/mosty-yjzl/tbZl/andJqZl").then((res) => {
proxy.$message({ type: "success", message: "下发成功" });
});
}
if (type.value == "yj") {
qcckGet(prams, "/mosty-yjzl/tbZl/andYjZl").then((res) => {
proxy.$message({ type: "success", message: "下发成功" });
});
}
});
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.dialogBox {
padding: 0 0 10px 0;
box-sizing: border-box;
.title {
border-bottom: 1px solid #275288;
margin-bottom: 6px;
.mc {
margin-left: 10px;
}
}
.groupList {
height: calc(100vh - 580px);
padding: 10px 20px;
box-sizing: border-box;
overflow: hidden;
overflow-y: auto;
.groupList-item {
padding: 10px;
box-sizing: border-box;
line-height: 20px;
font-size: 14px;
background: #052955;
margin-top: 4px;
box-shadow: inset 0 0 10px 10px #104675;
.address {
display: flex;
justify-content: space-between;
align-items: center;
.distance {
img {
margin-right: 4px;
}
}
.numbPopljgh {
padding: 1px 10px;
box-sizing: border-box;
background: rgba(5, 35, 66, 0.5);
border: 1px solid #00fcff;
border-radius: 5px;
font-size: 12px;
color: #fff;
font-weight: 700;
}
}
}
}
}
</style>

View File

@ -0,0 +1,74 @@
<!--
* @Author: your name
* @Date: 2022-09-20 10:22:51
* @LastEditTime: 2022-09-22 10:51:44
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
*
-->
<template>
<div class="dialogBox">
<div class="title">
<span class="mc">社会资源</span>
<span @click="close" class="close">
<el-icon><Close /></el-icon>
</span>
</div>
<div class="listBox">
<div v-for="(item, index) in props.data" :key="index">
<div class="infoBox">
<div class="content">{{ item.ysmc }}</div>
<div class="other">所属部门{{ item.ssbm }}</div>
<div class="address">
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ item.yswzXz }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, defineProps } from "vue";
// 左右折叠状态
import emitter from "@/utils/eventBus.js";
const props = defineProps({
data: {
type: Array,
default: []
}
});
//关闭弹窗
function close() {
emitter.emit("showShzy", false);
emitter.emit("deletePointArea", "lang");
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.dialogBox {
.listBox {
padding: 4px 10px;
box-sizing: border-box;
.infoBox {
padding: 4px 10px;
.other {
margin: 5 10px;
color: #779dcd;
}
}
.address {
margin-top: 10px;
border-top: 1px solid #34334c;
padding-top: 6px;
img {
margin-right: 10px;
}
}
}
}
</style>

View File

@ -0,0 +1,136 @@
<template>
<div class="dialogBox">
<div class="title">
<span class="mc">预警信息</span
><span @click="close" class="close">
<el-icon><Close /></el-icon>
</span>
</div>
<div class="containerBox">
<div v-for="(item, index) in props.data" :key="index">
<div class="infoBox">
<YjItem :data="item" :isDetail="true" />
</div>
<div class="btnBox">
<button class="dp-default small" @click="policeGroupShowFn(item)">
推荐处警巡组
</button>
<button class="dp-default small" @click="videoShowSs(item)">
实时视频
</button>
<button class="dp-default small" @click="XZBtnShowFn(item)">
指定处置
</button>
<button class="dp-default small" @click="warningListShowYjgj(item)">
预警轨迹
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import {
ref,
getCurrentInstance,
onMounted,
onBeforeUpdate,
defineProps,
defineEmits
} from "vue";
import YjItem from "@/views/largeScreen/home/components/yjItem.vue";
import people from "@/assets/images/peo.png";
import car from "@/assets/images/car.png";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import emitter from "@/utils/eventBus.js";
import { getVideoById, getVideoById2 } from "@/api/dpApi/video.js";
const props = defineProps({
data: Array
});
const emits = defineEmits(["showYjxq"]);
const router = useRouter();
onMounted(() => {});
//关闭弹窗
function close() {
emitter.emit("showYjxq", false);
emitter.emit("deletePointArea", "yj");
}
// 显示周边巡组
function policeGroupShowFn(item) {
if (item.jd && item.wd) {
emitter.emit("showZbxz", item);
} else {
ElMessage({ message: "暂无巡组信息", type: "warning" });
}
}
//显示预警轨迹
function warningListShowYjgj(item) {
emitter.emit("showCcyj", item);
}
// 转为指令
function XZBtnShowFn(item) {
let obj = { type: "yj", data: item };
emitter.emit("showXZBtn", obj);
}
// 显示视频回放
function videoShowFn() {
ElMessage({
message: "暂无视频信息",
type: "warning"
});
}
//显示实时视频
function videoShowSs(item) {
let id = item.yjGzyid;
getVideoById2(id).then((res) => {
if (res) {
let params = {
...item,
splitNum: 1,
sbbh: res.sbbh
};
emitter.emit("openGzyVideo", params);
} else {
videoShowFn();
}
});
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.dialogBox {
padding: 0 0 10px 0;
box-sizing: border-box;
.title {
border-bottom: 1px solid #275288;
margin-bottom: 6px;
.mc {
margin-left: 10px;
}
}
.containerBox {
max-height: 696px;
overflow: hidden;
overflow-y: auto;
padding: 4px 10px;
box-sizing: border-box;
.infoBox {
position: relative;
border: none;
padding: 10px 0;
}
.btnBox {
text-align: center;
button.dp-default.small {
margin: 0 4px;
}
}
}
}
</style>

View File

@ -0,0 +1,159 @@
<template>
<div class="dialogBox" v-loading="loading">
<div class="title">
<span class="mc">{{ title }}</span>
<span class="close" @click="close">×</span>
</div>
<ul class="warningList" ref="gjyjList">
<li v-for="item in warningList" :key="item.id">
<YjItem :data="item"/>
</li>
<el-empty
description="没有数据"
:image-size="0.1"
v-if="!loading && warningList.length <= 0"
/>
</ul>
</div>
</template>
<script setup>
import YjItem from "@/views/largeScreen/home/components/yjItem.vue";
import { getSelectTrack } from "@/api/dpApi/zzzh.js";
import { getSelectVigilantList } from "@/api/dpApi/home.js";
import { ElMessage } from "element-plus";
import {
ref,
reactive,
onMounted,
getCurrentInstance,
onUnmounted,
defineEmits,
defineProps,
watch
} from "vue";
import people from "@/assets/images/peo.png";
import car from "@/assets/images/car.png";
import emitter from "@/utils/eventBus.js";
const { proxy } = getCurrentInstance();
const { D_BZ_YJLX } = proxy.$dict("D_BZ_YJLX");
const warningList = ref([]); //预警列表数据
const pageSize = ref(4);
const pageCurrent = ref(1);
const pageTotal = ref(0);
const yjInfo = ref(null); //预警信息
const gjyjList = ref(null); //预警列表数据
const loading = ref(false);
//参数传递
const props = defineProps({
//某条预警详情
info: {
type:Object,
default:{}
},
//标题数据
title: String
});
const emit = defineEmits(["close"]);
onMounted(() => {
yjInfo.value = props.info;
_getSelectTrack(props.info);
scroll();
});
// 监听视频地址变化
watch(
() => props.info,
(val) => {
pageCurrent.value = 1;
yjInfo.value = val;
_getSelectTrack(val);
},
{ immediate: true, deep: true }
);
//关闭
function close() {
emit("close", false);
}
//获取轨迹预警列表
function _getSelectTrack(yjInfo) {
loading.value = true;
let data = {
pageSize: pageSize.value,
pageCurrent: pageCurrent.value,
yjRyxm: yjInfo.yjRyxm ? yjInfo.yjRyxm : "",
yjRysfzh: yjInfo.yjRysfzh ? yjInfo.yjRysfzh : "",
yjHplx: yjInfo.yjHplx ? yjInfo.yjHplx : "",
yjClcph: yjInfo.yjClcph ? yjInfo.yjClcph : ""
};
if (props.title == "轨迹预警") {
getSelectTrack(data).then((res) => {
loading.value = false;
if (pageCurrent.value == 1) {
warningList.value = res.records ? res.records : [];
} else {
let arr = res.records ? res.records : [];
warningList.value = warningList.value.concat(arr);
}
pageTotal.value = res.total;
});
} else {
//周边预警
data.radius = 300;
data.jd = props.info.jd;
data.wd = props.info.wd;
data.pageNum = pageCurrent.value;
getSelectVigilantList(data).then((res) => {
loading.value = false;
if (pageCurrent.value == 1) {
warningList.value = res.records ? res.records : [];
} else {
let arr = res.records ? res.records : [];
warningList.value = warningList.value.concat(arr);
}
pageTotal.value = res.total;
});
}
}
//触底加载
function scroll() {
let scrollTargetBox = gjyjList.value;
scrollTargetBox.onscroll = (e) => {
var scrollHeight = scrollTargetBox.scrollHeight; //251
var scrollTop = scrollTargetBox.scrollTop; //0-18
var clientHeight = scrollTargetBox.clientHeight; //233
if (scrollHeight - clientHeight == scrollTop) {
//滚动条滚到最底部
if (warningList.value.length < pageTotal.value) {
pageCurrent.value++;
_getSelectTrack(yjInfo.value);
}
}
};
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.dialogBox {
ul.warningList{
height: calc(100vh - 198px);
overflow: hidden;
overflow-y: auto;
padding: 7px 10px;
box-sizing: border-box;
.photo {
width: 60px;
height: 80px;
img {
width: 100%;
height: 100%;
}
}
}
}
//加载时 取消背景
::v-deep .el-loading-mask {
background-color: transparent !important;
}
</style>

View File

@ -0,0 +1,353 @@
<template>
<!--下发指令 -->
<SizeDialog @handleIdentity="close" :show="showAddEvent" :butList="['提交']" :showContent="true" :showbut="false"
title="下发指令">
<div class="form_box">
<el-form label-width="100px" :model="formInfo" :inline="true" label-position="top" :rules="rules" ref="elform">
<el-form-item label="指令标题" style="width: 100%" prop="zlbt">
<el-input v-model="formInfo.zlbt" placeholder="请输入指令标题" clearable />
</el-form-item>
<el-form-item label="指令类型" style="width: 100%" prop="zllx">
<el-select style="width: 100%" v-model="formInfo.zllx" placeholder="请选择指令类型">
<el-option v-for="dict in D_BZ_RGZLLX" :key="dict.value + 'zllx'" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="指令等级" style="width: 100%" prop="zldj">
<el-select style="width: 100%" v-model="formInfo.zldj" placeholder="请选择指令等级">
<el-option v-for="dict in D_BZ_TYJB" :key="dict.value + 'zldj'" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="指令接收对象" style="width: 100%" prop="zljsdx">
<el-select @change="checkJsdx" style="width: 100%" v-model="formInfo.zljsdx" placeholder="请选择指令接收对象">
<el-option v-for="dict in D_BZ_ZLJSDX" :key="dict.value + 'zljsdx'" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="事件坐标" style="width: 100%" prop="jwd">
<el-input v-model="formInfo.jwd" placeholder="请选择坐标" clearable style="width: 80%" />
<el-button type="info" @click="selectLocation">选点</el-button>
</el-form-item>
<el-form-item label="指令内容" style="width: 100%" prop="zlnr">
<el-input v-model="formInfo.zlnr" placeholder="请输入指令内容" clearable />
</el-form-item>
<el-form-item label="附件上传" style="width: 100%" prop="fjmc">
<el-input v-model="formInfo.fjmc" placeholder="请选择上传文件" style="width: 80%" />
<el-upload :limit="1" action="/mosty-api/mosty-base/minio/image/upload/id" :on-change="upImgFile"
:on-success="upImg" :show-file-list="false">
<el-button type="primary" style="padding: 0 14px">上传</el-button>
</el-upload>
</el-form-item>
<div class="mapQx">
<span>地图圈选 - 圈选人员</span>
<el-button type="primary" style="padding: 0 14px" @click="selectLoop">空间查询</el-button>
</div>
<div class="tagbox" placeholder="请选择人员">
<el-tag :key="tag" v-for="tag in qxList" closable :disabled-transitions="false" @close="handClose(tag)">
{{ tag }}
</el-tag>
</div>
</el-form>
<div style="text-align: right">
<el-button type="primary" @click="submit">发送</el-button>
</div>
</div>
</SizeDialog>
<MjLoad v-model="visible" @choosedUsers="hanlderChooseMj" />
</template>
<script setup>
import { dateFormat } from "@/utils/auth.js";
import { ElMessage } from "element-plus";
import SizeDialog from "./minDialog.vue";
import MjLoad from "@/components/MyComponents/ChooseJz/MjLoad.vue";
import emitter from "@/utils/eventBus.js";
import * as MOSTY from "@/components/MyComponents/index";
import { reactive, ref, onMounted, getCurrentInstance, onUnmounted } from "vue";
import { getXfbbList, addZl } from "@/api/situationPresentation/zlXf.js";
import { getSelectDeckList } from "@/api/dpApi/home.js";
import { getAddressApi } from "@/utils/tools.js";
const { proxy } = getCurrentInstance();
const { D_BZ_ZLLX, D_BZ_RGZLLX, D_BZ_ZLJSDX, D_BZ_TYJB } = proxy.$dict(
"D_BZ_ZLLX",
"D_BZ_RGZLLX",
"D_BZ_ZLJSDX",
"D_BZ_TYJB"
);
const visible = ref(false);
//巡组搜索参数
const xzQuery = reactive({
xfzt: "0,1,2",
pageCurrent: 1,
pageSize: 20,
jzMc: "",
xfzt: "0,1,2"
});
//巡组数据
const xzList = ref([]);
const qxList = ref([]);
const inputValue = ref("");
//巡组加载状态
const selectLoading = ref(false);
const showAddEvent = ref(false);
const formInfo = ref({
zxrDtoList: [],
zlfsdd: "",
zlbt: "抓捕疑似在逃人员",
zllx: "05",
zldj: "10",
zljsdx: "03",
zlnr: "抓捕疑似在逃人员"
});
const xzTotal = ref(0);
const elform = ref(null);
const rules = reactive({
zlbt: [{ required: true, message: "请填写指令标题" }],
zllx: [{ required: true, message: "请选择指令类型" }],
zlly: [{ required: true, message: "请选择指令来源" }],
zldj: [{ required: true, message: "请选择指令等级" }],
zljsdx: [{ required: true, message: "请选择指令接收对象" }],
jwd: [{ required: true, message: "请选择点位" }]
});
const fjmc = ref("");
onMounted(() => {
emitter.on("showZlxf", (res) => {
showAddEvent.value = true;
});
emitter.on("closeAllDialog", (res) => {
showAddEvent.value = false;
});
getXz();
// 圈选撒点
emitter.on("coordString", (res) => {
if (res.type == 'point') {
formInfo.value.jwd = res.coord[0] + "," + res.coord[1];
formInfo.value.jd = res.coord[0];
formInfo.value.wd = res.coord[1];
let data = { jd: res.coord[0], wd: res.coord[1] };
let img = require("@/assets/point/jq.png");
emitter.emit("deletePointArea", "jq");
emitter.emit("addPointArea", { coords: [data], icon: img, flag: "jq" });
}
if (res.type == 'circle') {
let data = {
pageCurrent: 1,
pageSize: 20,
radius: parseInt(res.data.radius) * 1000,
jd: res.data.centerPoint[0],
wd: res.data.centerPoint[1]
};
formInfo.value.jwd = res.data.centerPoint[0] + "," + res.data.centerPoint[1];
formInfo.value.jd = res.data.centerPoint[0];
formInfo.value.wd = res.data.centerPoint[1];
circleData(data);
}
});
});
onUnmounted(() => {
emitter.off("getcoord");
});
function handClose(tag) {
qxList.value.splice(qxList.value.indexOf(tag), 1);
}
function remoteMethod(query) {
if (query) {
xzQuery.jzMc = query;
xzQuery.pageCurrent = 1;
getXz();
}
}
//选择民警
function hanlderChooseMj(arr) {
const jzryList = arr.map((item) => {
return {
jsrid: item.ryid,
jsrmc: item.xm,
jsrsfzh: item.sfzh,
jsrlxdh: item.lxdh,
jsrlx: item.fl,
xm: item.xm
};
});
formInfo.value.zxrDtoList = jzryList;
}
function getXz() {
getSelectDeckList(xzQuery).then((res) => {
xzTotal.value = res.total;
xzList.value = res.records;
});
}
function checkJsdx() {
formInfo.value.zxrDtoList = [];
}
//懒加载
function selectLoad() {
if (xzTotal.value > xzList.value.length) {
xzQuery.pageCurrent++;
getXfbbList(xzQuery).then((res) => {
xzTotal.value = res.total;
xzList.value.push(...res.records);
});
} else {
return false;
}
}
//关闭弹窗
function close() {
showAddEvent.value = false;
qxList.value = [];
formInfo.value = { zxrDtoList: [] };
emitter.emit("removePlot", "PIO");
emitter.emit("deletePointArea", "jq");
emitter.emit("deletePointArea", "jqMap");
emitter.emit("deletePointArea", "yjMap");
emitter.emit("deletePointArea", "sp");
emitter.emit("deletePointArea", "kk");
emitter.emit("deletePointArea", "centerpoint");
emitter.emit("removePlot", 'quanXuan'); //移除绘制工具
}
function submit() {
elform.value.validate((valid) => {
if (!valid) return false;
const data = { ...formInfo.value, zllx: '06' };
data.zxrDtoList = formInfo.value.zxrDtoList.map((item) => {
return {
zxrXzid: item.id,
zxrLx: "03",
zxrXzmc: item.jzMc
};
});
addZl(data).then(() => {
close();
proxy.$message({ type: "success", message: "指令下发成功" });
});
});
}
//选择点位
function selectLocation() {
emitter.emit("removePlot", "PIO");
emitter.emit("drawShape", { flag: "PIO", type: 'point' });
}
function upImgFile(row) {
fjmc.value = row.name;
}
function upImg(row) {
formInfo.value.fjId = row.data;
formInfo.value.fjmc = fjmc.value;
}
function handleClose(tag) {
formInfo.value.zxrDtoList.splice(formInfo.value.zxrDtoList.indexOf(tag), 1);
}
//地图圈选
function selectLoop() {
emitter.emit("deletePointArea", "jqMap");
emitter.emit("deletePointArea", "yjMap");
emitter.emit("deletePointArea", "sp");
emitter.emit("deletePointArea", "kk");
emitter.emit("deletePointArea", "jq");
qxList.value = []
formInfo.value.zxrDtoList = []
emitter.emit("deletePointArea", "centerpoint");
emitter.emit("drawShape", { flag: "quanXuan", type: 'circle', isclear: true });
}
//获取圈选数据
function circleData(data) {
getSelectDeckList(data).then((res) => {
if (res.records.length > 0) {
qxList.value = res.records.map((item, index) => {
return item.jzMc ? item.jzMc : item.fzrXm + "巡组";
});
formInfo.value.zxrDtoList = res.records.map((item, index) => {
return item;
});
} else {
ElMessage({ message: "暂无巡组信息", type: "warning" });
}
});
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.form_box {
padding: 10px;
max-height: 84vh;
overflow-y: auto;
}
::v-deep .el-form-item__content {
flex-wrap: nowrap;
}
.ipt {
min-height: 32px;
border: 1px solid #fff;
background: #fff;
border-radius: 4px;
box-sizing: border-box;
padding: 0 12px;
cursor: pointer;
width: 100%;
position: relative;
.el-tag {
margin-right: 12px;
background: #434449;
}
}
.tagbox {
min-height: 32px;
border: 1px solid #409eff;
border-radius: 4px;
box-sizing: border-box;
padding: 4px 12px;
cursor: pointer;
width: 100%;
position: relative;
margin-bottom: 4px;
max-height: 100px;
overflow: hidden;
overflow: auto;
}
.ipt:hover {
border-color: rgb(62, 127, 247);
}
.ts::after {
content: "请选择指令接收对象";
position: absolute;
top: 0;
right: 0;
left: 12px;
line-height: 32px;
bottom: 0;
color: rgb(177, 177, 177);
}
.mapQx {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 13px;
}
::v-deep .el-tag--default.is-closable {
margin-bottom: 4px;
margin-right: 4px;
}
::v-deep .el-form--inline.el-form--label-top {
max-height: 78vh;
overflow: hidden;
overflow-y: auto;
}
</style>

View File

@ -0,0 +1,13 @@
<template>
<div></div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@ -0,0 +1,257 @@
<template>
<div class="jqItm" :class="props.isDetail?'':'jqItmline'">
<div class="time" v-if="!props.isDetail">
<span>{{ props.data.bjsj }}</span>
<span style="display:flex;align-items: center;">
<el-popover placement="left" width="400" trigger="click">
<template #reference>
<span @click="get_cjd_detail" style="font-size:17px;cursor: pointer;margin-right:10px;"><el-icon style="margin-top:4px;" color="#58a4fa" ><WarningFilled/></el-icon></span>
</template>
<div class="detail_cnt_box">
<el-timeline>
<el-timeline-item color="#409eff" :timestamp="it.time" placement="top" v-for="(it,idx) in detailList" :key="idx">
<el-card>
<div class="detailinfo">{{it.mode1}}</div>
<div class="detailinfo">{{it.units}}{{it.jjyxm}}</div>
<audio :id="'radius_' + it.id">
<source :src="it.lyh" />
</audio>
<div class="address">
<div style="text-align:right;" v-if="it.lyh">
<img class="playImg" v-if="!it.isPlay" src="@/assets/my/play.png" @click.stop="playRadio(it)" />
<img class="playImg" v-else src="@/assets/my/pause.png" @click.stop="closeRadio(it)" />
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
<el-empty description="暂无数据" :image-size="0.1" v-if="detailList.length <= 0"/>
</div>
</el-popover>
<span style="color: #58a4fa;cursor: pointer;" @click.stop="changePoint( props.data)">重新定位</span>
</span>
</div>
<div class="card" :class="changeBorder(props.data.color)" @click="getDetaill(props.data)">
<div class="title">{{ props.data.bjnr }}</div>
<div class="text">
报警人<span class="info">{{ props.data.bjrXm || '未知'}} <span v-if="!props.isDetail">({{props.data.bjrLxdh}})</span></span>
</div>
<div class="text">
报警时间<span class="info">{{ props.data.bjsj }}</span>
</div>
<div class="text">
警情类别<span class="info">{{ props.data.bjlbmc }}</span>
</div>
<div class="text">
警情类型<span class="info">{{ props.data.bjlxmc }}</span>
</div>
<div class="text">
警情细类<span class="info">{{ props.data.bjxlmc || "未知"}}</span>
</div>
<div class="text" v-if="props.isDetail">
报警人电话<span class="info">{{ props.data.bjrLxdh}}</span>
<span class="checkInfo">核查身份</span>
</div>
<audio :id="'radius_' + props.data.id">
<source :src="props.data.jjlyh" />
</audio>
<div class="address">
<span>
<img class="addImg" src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ props.data.sfdz }}</span>
</span>
<span v-if="!props.isDetail">
<img class="playImg" v-if="!props.data.isPlay" src="@/assets/my/play.png" @click.stop="playRadio(props.data)" />
<img class="playImg" v-else src="@/assets/my/pause.png" @click.stop="closeRadio(props.data)" />
</span>
</div>
</div>
</div>
</template>
<script setup>
import { qcckGet } from "@/api/qcckApi.js";
import emitter from "@/utils/eventBus.js";
import { reactive, ref,defineProps,defineEmits } from "vue";
const props = defineProps({
data: Object,
isDetail:Boolean,
dic:{
type:Object,
default:{}
}
});
const changeItemPoint = ref({}); //切换警情的经纬度
const detailList = ref([])
const isOpen = ref(false)
const emit = defineEmits(['lookDetail','changePoint'])
// 查看详情
function getDetaill(item){
emit('lookDetail',item)
}
// 播放语音
function playRadio(item) {
item.isPlay = true;
let ID = "radius_"+item.id;
let dom = document.getElementById(ID);
dom.load();
dom.play();
}
// 切换定位
function changePoint(item) {
emit('changePoint',item)
emitter.emit("removePlot", "PIOT");
emitter.emit("drawShape", {flag:"PIOT" , type:'point' });
}
// 改变边框
function changeBorder(val){
switch(val){
case '1':
return 'red'
break;
case '2':
return 'orange'
break;
case '3':
return 'yellow'
break;
case '4':
return 'blue'
break;
default:
return 'blue'
}
}
// 关闭语音
function closeRadio(item) {
item.isPlay = false;
let ID = "radius_" + item.id;
let dom = document.getElementById(ID);
dom.pause();
}
// 获取详情
function get_cjd_detail(){
isOpen.value = !isOpen.value;
if(isOpen.value){
qcckGet({jjdbh:props.data.gljjdbh},'/mosty-other/lzJq/getListCzxx').then(res=>{
detailList.value = res || [];
detailList.value.forEach(v=>{
if(v.lyh) v.lyh = '/data/rec' + v.lyh;
v.isPlay = false;
})
})
}
}
</script>
<style lang="scss" scoped>
.jqItm {
position: relative;
padding: 0 10px 10px 14px;
box-sizing: border-box;
.time {
margin-bottom: 10px;
padding-left: 10px;
display: flex;
justify-content: space-between;
}
.card {
padding: 10px 10px 0 10px;
box-sizing: border-box;
line-height: 20px;
font-size: 14px;
background: #052955;
.text {
font-size: 12px;
color: #6585af;
span {
color: #0093ed;
}
.checkInfo{
padding: 4px 6px;
color: #fff;
border-radius: 4px;
box-shadow: inset 0 0px 2px 2px #2B8BE5;
margin-left: 10px;
cursor: pointer;
}
}
.address {
display: flex;
justify-content: space-between;
margin-top: 12px;
padding-top: 4px;
padding-bottom: 4px;
box-sizing: border-box;
border-top: 1px solid #2d2f4e;
.addImg {
margin-right: 4px;
vertical-align: text-top;
}
.playImg{
width: 20px;
}
}
}
.red{
border-top: 2px solid #ff0526;
}
.orange{
border-top: 2px solid #FF7E00;
}
.yellow{
border-top: 2px solid #FFE21F;
}
.blue{
border-top: 2px solid #1C97FF;
}
.time::before {
position: absolute;
content: "";
width: 26px;
height: 26px;
background: url("~@/assets/my/icon.png") no-repeat;
top: -7px;
left: -14px;
z-index: 22;
}
}
.jqItmline{
border-left: 1px solid rgb(46, 67, 116);
margin-left: 10px;
}
.detail_cnt_box{
max-width: 600px;
max-height: 60vh;
overflow: hidden;
overflow-y: auto;
}
.detail_cnt_box .el-card{
color: #ffffff;
border: 1px solid #19408d;
background-color: #052955;
}
::v-deep .el-timeline-item__timestamp{
color: #fff;
}
</style>
<style>
.el-popper.is-light{
background: #072b64;
border: 1px solid #1e4eac;
}
.el-popper.is-light .el-popper__arrow::before{
background: #072b64;
border: 1px solid #1e4eac;
}
</style>

View File

@ -0,0 +1,146 @@
<template>
<div
class="all-dialog noScollLine"
:style="{ left: props.isPosition ? '0px' : '388px' }"
style="transition: all 0.5s"
>
<!-- 预警信息弹框 -->
<WarningInfo v-if="isShow.showYj" :data="list.yjxqInfo" />
<!--警情弹框 -->
<AjInfo v-show="isShow.showJq" :data="list.jqxqList" />
<!-- 指令信息弹框 -->
<InstructionsInfo v-if="isShow.showZl" :data="list.zlxqList" />
<!-- 公安资源弹窗 -->
<GazyInfo v-show="isShow.showGazy" :data="list.gzjgxqList" />
<!-- 社会资源弹窗 -->
<ShzyInfo v-if="isShow.showShzy" :data="list.shzyxqList" />
<!-- 感知源弹窗 -->
<GzyInfo v-if="isShow.showGzy" :data="list.gzyxqList" />
<!-- 周边巡组 -->
<PoliceGroupList v-if="isShow.showZbxz" :data="list.zbxzxqList" />
<!--转为指令 -->
<PoliceGroupBtnList />
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import GzyInfo from "./dialog/gzyInfo.vue";
import PoliceGroupList from "./dialog/policeGroupList.vue";
import PoliceGroupBtnList from "./dialog/policeGroupBtnList.vue";
import ShzyInfo from "./dialog/shzyInfo.vue";
import WarningInfo from "./dialog/warningInfo.vue";
import AjInfo from "./dialog/ajInfo.vue";
import GazyInfo from "./dialog/gazyInfo.vue";
import InstructionsInfo from "./dialog/instructionsInfo.vue";
import { ref, defineProps, onMounted, onUnmounted, reactive } from "vue";
const props = defineProps({
isPosition: Boolean
});
const isShowDefault = ref({});
const isShow = ref({
showYj: false, //预警弹窗
showJq: false, //警情弹窗
showZl: false, //指令弹窗
showGazy: false, //公安机关弹窗
showShzy: false, //社会资源关弹窗
showGzy: false, //社会资源关弹窗
showZbxz: false //周边巡组弹窗
});
const list = reactive({
yjxqInfo: [], //预警数据
jqxqList: [], //警情数据
zlxqList: [], //指令数据
gzjgxqList: {}, //公安机关数据
shzyxqList: [], //社会资源数据
gzyxqList: [], //感知元数据
zbxzxqList: Object //周边巡组数据
});
onMounted(() => {
isShowDefault.value = JSON.parse(JSON.stringify(isShow.value));
// 展示预警
emitter.on("showYjxq", (res) => {
isShow.value.showYj = res ? true : false;
if (res) list.yjxqInfo = res;
});
// 展示警情
emitter.on("showAj", (res) => {
isShow.value.showJq = res ? true : false;
if (res) list.jqxqList = res;
});
// 展示指令
emitter.on("showYjzl", (res) => {
isShow.value.showZl = res ? true : false;
if (res) list.zlxqList = res;
});
// 展示公安机关
emitter.on("showGazy", (res) => {
isShow.value.showGazy = res ? true : false;
if (!isShow.value.showGazy) emitter.emit("deleteText"); //清除巡防区文字
if (res) list.gzjgxqList = res;
});
// 社会资源
emitter.on("showShzy", (res) => {
isShow.value.showShzy = res ? true : false;
if (res) list.shzyxqList = res;
});
// 感知源
emitter.on("showGzy", (res) => {
isShow.value.showGzy = res ? true : false;
if (res) {
list.gzyxqList = res.map((item) => {
item.isPlay = false;
return item;
});
}
});
// 周边巡组
emitter.on("showZbxz", (res) => {
isShow.value.showZbxz = res ? true : false;
if (res) list.zbxzxqList = res;
});
// 关闭所有弹窗
emitter.on("closeAllDialog", (res) => {
isShow.value = JSON.parse(JSON.stringify(isShowDefault.value));
emitter.emit("deletePointArea", "xzlxIcon");
emitter.emit("drawLineAnimation", "route");
emitter.emit("clearLine");
});
});
onUnmounted(() => {
emitter.off("showCcyj");
emitter.off("videoClick");
emitter.off("clickZbyj");
emitter.off("closeVideo");
emitter.off("showGzy");
emitter.off("showGazy");
emitter.off("showShzy");
emitter.off("showAj");
emitter.off("showYjxq");
emitter.off("showYjzl");
emitter.off("showZbxz");
emitter.off("closeAllDialog");
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.all-dialog {
position: absolute;
width: 370px;
top: 90px;
max-height: 90vh;
overflow: hidden;
overflow-y: auto;
padding-right: 10px;
box-sizing: border-box;
}
</style>

View File

@ -0,0 +1,104 @@
<template>
<div class="rightDilog noScollLine" :style="{ right: props.isPosition ? '0px' : '388px' }" style="transition: all 0.5s" >
<!-- 周边视频更多视频三个视频列表的时候 -->
<MoreVideo
@close="onVideoClose('zb')"
:info="jqDetail"
:title="'周边视频'"
v-if="showVideoWindow"
/>
<!--视频随动 -->
<MoreVideo
@close="onVideoClose('sd')"
:info="xzDetail"
:title="'视频随动'"
v-if="showVideoSpsdWindow"
/>
<!-- 轨迹预警 -->
<DialogWarningList
@close="onClose('gj')"
:info="yjDetail"
:title="'轨迹预警'"
v-if="showYjWindow"
/>
<!-- 周边预警 -->
<DialogWarningList
@close="onClose('zb')"
:info="zbyjDetail"
:title="'周边预警'"
v-if="showZbyjWindow"
/>
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import MoreVideo from "./dialog/moreVideo.vue";
import DialogWarningList from "./dialog/warningList.vue";
import { ref, defineProps, onMounted, onUnmounted } from "vue";
const props = defineProps({
isPosition: Boolean
});
const zbyjDetail = ref(null); //周边预警详情
const yjDetail = ref(null); //某条预警详情
const showZbyjWindow = ref(false); //是否显示周边预警
const jqDetail = ref(null); // 某条警情详情
const showVideoWindow = ref(false); //是否显示周边视频
const xzDetail = ref(null); //巡组详情
const showVideoSpsdWindow = ref(false); //吃否显示视频随动
const showYjWindow = ref(false); //是否显示预警轨迹弹窗
onMounted(()=>{
emitter.on("videoClick", (res) => {
jqDetail.value = res;
showVideoWindow.value = true;
});
emitter.on("closeVideo", (res) => {
showVideoWindow.value = false;
showVideoSpsdWindow.value = false;
});
emitter.on("clickZbyj", (res) => {
zbyjDetail.value = res;
showZbyjWindow.value = true;
});
emitter.on("showCcyj", (res) => {
yjDetail.value = res;
showYjWindow.value = true;
});
// 视频随动
emitter.on("clickSpsd", (res) => {
xzDetail.value = res;
showVideoSpsdWindow.value = true;
});
})
//关闭周边视频 || 视频随动
function onVideoClose(type) {
if (type == "zb") {
showVideoWindow.value = false;
} else {
showVideoSpsdWindow.value = false;
}
}
//关闭轨迹预警 || 周边预警
function onClose(type) {
if (type == "gj") {
showYjWindow.value = false;
} else {
showZbyjWindow.value = false;
}
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.rightDilog {
position: absolute;
top: 91px;
width: 360px;
right: 380px ;
z-index:9;
max-height: 90vh;
overflow: hidden;
overflow-y: auto;
box-sizing: border-box;
}
</style>

View File

@ -0,0 +1,135 @@
<template>
<div class="searchBox">
<el-form :model="listQuery">
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
style="width: 100%"
v-model="listQuery.startTime"
type="datetime"
placeholder="请选择日期时间"
format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
style="width: 100%"
v-model="listQuery.endTime"
type="datetime"
placeholder="请选择日期时间"
format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item prop="ssbmid" v-if="props.type == '01'" label="所属辖区">
<MOSTY.Department
placeholder="请选择所属辖区"
width="100%"
clearable
filterable
v-model="listQuery.ssbmid"
/>
</el-form-item>
<el-form-item prop="zdjqtjlx" v-if="props.type == '01'" label="警情类型">
<el-select v-model="listQuery.zdjqtjlx">
<el-option
v-for="(dict, index) in D_BZ_ZDJQTJLX"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="yjlx" v-if="props.type == '02'" label="预警类型">
<el-select clearable style="width: 100%" v-model="listQuery.yjLx">
<el-option
v-for="(dict, index) in D_BZ_YJLX"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="yjdj" v-if="props.type == '02'" label="预警等级">
<el-select v-model="listQuery.yjJb">
<el-option
v-for="(dict, index) in D_BZ_tyjb"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="zlczzt" v-if="props.type == '03'" label="处置状态">
<el-select v-model="listQuery.zlczzt">
<el-option
v-for="(dict, index) in D_BZ_CZZT"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<div class="footer">
<el-button @click="handleFilter">筛选</el-button>
<el-button @click="reset()"> 重置 </el-button>
</div>
</el-form>
</div>
</template>
<script setup>
import { ref, getCurrentInstance, defineProps, defineEmits, watch } from "vue";
import * as MOSTY from "@/components/MyComponents/index";
const props = defineProps({
type: String,
searchForm: Object
});
const emit = defineEmits(["handelSearch", "resetSearch"]);
const { proxy } = getCurrentInstance();
const { D_BZ_tyjb, D_BZ_CZZT, D_BZ_ZDJQTJLX,D_BZ_YJLX } = proxy.$dict(
"D_BZ_tyjb",
"D_BZ_CZZT",
"D_BZ_ZDJQTJLX",
"D_BZ_YJLX"
);
const listQuery = ref({});
watch(
() => props.searchForm,
(val) => {
listQuery.value = val;
},
{ immediate: true }
);
// 筛选
function handleFilter() {
let params = {
...listQuery.value,
lx: props.type
};
emit("handelSearch", params);
}
// 重置
function reset() {
listQuery.value = {};
emit("resetSearch", props.type);
}
</script>
<style lang="scss" scoped>
.searchBox {
// width: 340px;
background: #000;
padding: 10px 8px;
box-sizing: border-box;
.el-form {
width: 100%;
height: 100%;
.footer {
text-align: center;
}
}
}
</style>

View File

@ -0,0 +1,212 @@
<template>
<div class="yjItm" :class="props.isDetail?'':'yjItmline'">
<div class="time" v-if="!props.isDetail">{{ props.data.yjSj }}</div>
<div class="card">
<div class="card-cnt">
<div class="leftImg">
<el-image
style="width: 100%"
:src="props.data.yjTp"
:preview-src-list="[props.data.yjTp,props.data.yjXtp]"
:hide-on-click-modal="true"
close-on-press-escape
fit="cover"
lazy
>
<template #error>
<div class="image-slot">
<el-image
v-if="props.data.yjLx == 1"
:src="people"
:preview-src-list="[people,props.data.yjXtp]"
fit="cover"
></el-image>
<el-image v-else :src="car" :preview-src-list="[car,props.data.yjXtp]" fit="cover"></el-image>
</div>
</template>
</el-image>
</div>
<div class="rightInfo" @click="getDetaill(props.data)">
<div class="title">
<span>
<span class="xinxi">{{ props.data.yjRyxm }}</span>
<span class="xinxi" v-if="props.data.yjRysfzh">{{ IdCard(props.data.yjRysfzh,2) }}</span>
</span>
<span class="status">{{ props.data.yjbq }}</span>
</div>
<div>
<span class="zjhm" v-if="props.data.yjRysfzh">{{ IdCard(props.data.yjRysfzh,3) }} </span>
<span class="zjhm">{{ props.data.yjRysfzh }}</span>
</div>
<div class="text textflex" v-if="!props.isDetail">
<span>车牌号码<span class="info">{{ props.data.yjClcph }}</span></span >
<span>车牌类型<span class="info">{{ props.data.yjHplx }}</span></span>
</div>
<div class="text">
抓拍时间<span class="info">{{ props.data.yjFssj }}</span>
</div>
<div class="text">
抓拍地点<span class="info">{{ props.data.yjGzymc }}</span>
</div>
<div class="text">
预警时间<span class="info">{{ props.data.yjSj }}</span>
</div>
<div style="color:yellow ;" v-if="props.isDetail">
研判结果<span class="info">相似度{{ props.data.xsd }}%</span>
</div>
</div>
</div>
<!-- <div class="phtos">
<el-carousel indicator-position="outside" :autoplay="isAutoplay">
<el-carousel-item v-for="v in 1" :key="v">
<div v-for="it in 4" :key="it" class="imgList">
<img :src="people" alt="" />
</div>
</el-carousel-item>
</el-carousel>
</div> -->
<div class="address">
<img
class="addImg"
src="@/assets/images/situationPresentation/dingwei.png"
/>
<span>{{ props.data.yjDz }}</span>
</div>
</div>
</div>
</template>
<script setup>
import { IdCard } from '@/utils/validate.js'
import people from "@/assets/images/peo.png";
import car from "@/assets/images/car.png";
import { reactive, ref, defineProps ,defineEmits} from "vue";
const emit = defineEmits(['lookDetail'])
const isAutoplay = ref(false);
const props = defineProps({
data: Object,
isDetail:Boolean
});
// 查看详情
function getDetaill(item){
emit('lookDetail',item)
}
</script>
<style lang="scss" scoped>
.yjItm {
position: relative;
padding: 0 10px 10px 14px;
box-sizing: border-box;
.time {
margin-bottom: 10px;
padding-left: 10px;
}
.card {
padding: 10px 10px 4px 10px;
box-sizing: border-box;
border-top: 2px solid #00bfff;
line-height: 20px;
font-size: 14px;
background: #052955;
.card-cnt {
display: flex;
.leftImg {
width: 60px;
margin-right: 10px;
.el-image{
width: 100%;
max-height: 90px;
}
}
.rightInfo {
flex: 1;
.title {
width: 100%;
.xinxi {
color: #01e9ed;
margin-right: 10px;
}
.status {
padding: 1px 6px;
border-radius: 4px;
background: #ab0f0a;
}
}
.zjhm {
color: #25c9ff;
margin-right: 10px;
}
.textflex {
display: flex;
justify-content: space-between;
}
.text {
font-size: 12px;
color: #6585af;
.info {
color: #fff;
}
}
.newinfo {
color: yellow;
}
}
}
.address {
justify-content: space-between;
margin-top: 4px;
padding-top: 6px;
box-sizing: border-box;
border-top: 1px solid #3b3737;
.addImg {
margin-right: 4px;
vertical-align: text-top;
}
}
.phtos {
height: 110px;
padding-top: 10px;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
width: 100%;
border-top: 1px dashed #3d3d3d;
margin-top: 6px;
box-sizing: border-box;
::v-deep .el-carousel {
width: 100%;
height: 100%;
.el-carousel__container {
height: 72%;
}
.el-carousel__item {
height: 100%;
display: flex;
justify-content: space-between;
}
}
img {
width: 60px;
height: 70px;
}
}
}
.time::before {
position: absolute;
content: "";
width: 26px;
height: 26px;
background: url("~@/assets/my/icon.png") no-repeat;
top: -7px;
left: -14px;
z-index: 22;
}
}
.yjItmline{
border-left: 1px solid rgb(151, 147, 147);
margin-left: 10px;
}
</style>

View File

@ -0,0 +1,203 @@
<template>
<div class="zlItm" :class="!isDetail ? 'zlItmLine' : ''">
<div class="time" v-if="!isDetail">{{ props.data.zlfqsj }}</div>
<div class="card">
<div class="card-cnt">
<div class="leftImg">
<el-image style="width: 100%" :src="props.data.zltp" :preview-src-list="[props.data.zltp]"
:hide-on-click-modal="true" close-on-press-escape fit="cover" lazy>
<template #error>
<div class="image-slot">
<el-image :src="people" fit="cover"></el-image>
</div>
</template>
</el-image>
</div>
<div class="rightInfo" @click="getDetaill(props.data)">
<div class="title">
<span>
<span class="xinxi">{{ props.data.zlfqr }}</span>
<span class="xinxi" v-if="props.data.zlfqrSfzh">{{
IdCard(props.data.zlfqrSfzh, 2)
}}</span>
</span>
<span class="status">{{ handelZt(props.data.zlzxzt) }}</span>
</div>
<div>
<!-- <span class="zjhm">{{ IdCard(props.data.zlfqrSfzh, 3) }}</span>
<span class="zjhm">{{ props.data.zlfqrSfzh }}</span> -->
</div>
<div class="text text_detail">
内容
<el-tooltip :placement="isDetail ? 'right' : 'left'">
<template #content>
<div style="max-width:400px;">{{ props.data.zlnr }}</div>
</template>
{{ props.data.zlnr }}
</el-tooltip>
</div>
<div class="newinfo">
<div class="text_detail"> 最新动态
<el-tooltip :placement="isDetail ? 'right' : 'left'">
<template #content>
<div style="max-width:400px;">{{ props.data.zlzxqk }}</div>
</template>
{{ props.data.zlzxqk }}
</el-tooltip>
</div>
</div>
</div>
</div>
<div class="address">
<img class="addImg" src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ props.data.zlfsdd }}</span>
</div>
</div>
</div>
</template>
<script setup>
import { IdCard } from "@/utils/validate.js";
import people from "@/assets/images/peo.png";
import { reactive, ref, defineProps, defineEmits, onMounted } from "vue";
const emit = defineEmits(["lookDetail"]);
const props = defineProps({
data: Object,
dic: Object,
isDetail: Boolean
});
// 获取指令状态
function handelZt(val) {
let obj = props.dic.zlzt.find((item) => {
return item.value == val;
});
return obj ? obj.label : "";
}
// 查看详情
function getDetaill(item) {
emit("lookDetail", item);
}
</script>
<style lang="scss" scoped>
.zlItm {
position: relative;
padding: 0 10px 10px 14px;
box-sizing: border-box;
.time {
margin-bottom: 10px;
padding-left: 10px;
}
.card {
padding: 10px 10px 4px 10px;
box-sizing: border-box;
border-top: 2px solid #00bfff;
line-height: 20px;
font-size: 14px;
background: #052955;
.card-cnt {
display: flex;
.leftImg {
width: 60px;
margin-right: 10px;
.el-image {
width: 100%;
max-height: 90px;
}
}
.rightInfo {
flex: 1;
.title {
display: flex;
justify-content: space-between;
width: 100%;
.xinxi {
color: #01e9ed;
margin-right: 10px;
}
.status {
padding: 1px 6px;
border: 1px solid #347fe9;
border-radius: 4px;
color: #25c9ff;
}
}
.zjhm {
color: #25c9ff;
margin-right: 10px;
font-size: 13px;
}
.text {
font-size: 13px;
color: #6585af;
line-height: 22px;
span {
color: #0093ed;
}
}
.newinfo {
font-size: 13px;
line-height: 22px;
color: yellow;
}
}
}
.address {
justify-content: space-between;
margin-top: 4px;
padding-top: 6px;
box-sizing: border-box;
border-top: 1px solid #3b3737;
color: #6486ae;
.addImg {
margin-right: 4px;
vertical-align: text-top;
}
}
}
.time::before {
position: absolute;
content: "";
width: 26px;
height: 26px;
background: url("~@/assets/my/icon.png") no-repeat;
top: -7px;
left: -14px;
z-index: 22;
}
}
.zlItmLine {
border-left: 1px solid rgb(151, 147, 147);
margin-left: 10px;
}
.ss-content:hover {
.toolTips::after {
@include ShowToolTips;
}
}
.newinfo:hover {
.toolTips::after {
@include ShowToolTips;
}
}
// </style>

View File

@ -0,0 +1,467 @@
<!--
* @Author: ZR
* @Date: 2023-11-06 09:43:52
* @LastEditTime: 2024-07-04 09:47:16
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
-->
<template>
<div class="bigScrenn">
<GdMap :isShow="true" />
<!-- 头部 -->
<Header></Header>
<!-- <div class="upload_home">
<el-button type="primary" @click="">上传</el-button>
<el-button type="primary">下载</el-button>
</div> -->
<div class="leftSiecle transition" :style="{ left: showClassL ? '-20px' : '370px' }"
@click="showClassL = !showClassL"></div>
<div class="asideBox transition" :style="{ left: showClassL ? '-386px' : '0px' }">
<!-- 工作情况 -->
<div class="boder-small">
<WorkCondition />
</div>
<!-- 街面巡组 -->
<div class="boder-middle">
<StreetGroup />
</div>
</div>
<div class="rightSiecle transition" :style="{ right: showClassR ? '-20px' : '370px' }"
@click="showClassR = !showClassR"></div>
<div class="asideBox transition" :style="{ right: showClassR ? '-386px' : '0px' }">
<div class="boder-big">
<StreetCondition />
</div>
</div>
<!-- 中间统计数据 -->
<el-tooltip :content="isShowCount ? '关闭统计' : '展示统计'" placement="top">
<span class="Rank" @click="isShowCount = !isShowCount"><el-icon>
<Rank />
</el-icon></span>
</el-tooltip>
<div class="statisModel" :class="isShowCount ? 'showCount' : 'heddenCount'">
<CountModel />
</div>
<!-- 底部按钮 -->
<!-- <BottomBtn /> -->
<div class="footBox">
<ul>
<li v-for="(item, index) in btnTatol" :key="item">
<div class="text_total">{{ item.total }}</div>
<div class="img_total" :class="'img_total' + index"></div>
<div class="text_total bg_text">{{ item.text }}</div>
</li>
</ul>
</div>
<!-- 指令时间按钮 -->
<div class="addBox transition" :style="{ right: showClassR ? '0px' : '394px' }">
<div @click="clickXfzl" class="imgBox">
<span>下发指令</span>
</div>
</div>
<!-- 左边弹窗 -->
<LeftDialog :isPosition="showClassL" />
<!-- 中间边弹窗 -->
<CenterDialog />
<!-- 右边弹窗 -->
<RightDialog :isPosition="showClassR" />
<!-- 警组弹框弹框 -->
<PoliceGroupInfo v-if="isShowJzGroup" :data="jzxqList" />
<!-- 下发指令 -->
<XiafaZl />
<!-- 犯罪预测 -->
<FzycDialog v-if="isShowFZYC" :data="fzycInfo" />
</div>
</template>
<script setup>
import { queryListfzyc } from "@/api/dpApi/home.js";
import { getRecentDay, getThistWeekDare } from "@/utils/tools.js";
import * as MOSTY from "@/components/MyComponents/index";
import { qcckGet } from "@/api/qcckApi.js";
import emitter from "@/utils/eventBus.js";
import router from "@/router/index.js";
import { getSelectVigilant } from "@/api/dpApi/home.js";
import GdMap from "@/components/Map/GdMap/index.vue";
import Header from "./layout/header.vue";
import CheckBox from "@/components/checkBox/index";
import XiafaZl from "./components/dialog/xiafaZl.vue";
import WorkCondition from "./layout/workCondition.vue";
import StreetGroup from "./layout/streetGroup.vue";
import StreetCondition from "./layout/streetCondition.vue";
import CountModel from "./layout/statisticsModel.vue";
import LeftDialog from "./components/leftDialog.vue";
import CenterDialog from "./components/centerDialog.vue";
import RightDialog from "./components/rightDialog.vue";
import BottomBtn from "./layout/bottomBtn.vue";
import PoliceGroupInfo from "./layout/streetInfo.vue";
import FzycDialog from "./layout/fzycDialog.vue";
import { onMounted, ref, onUnmounted, watch, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_SF } = proxy.$dict("D_BZ_SF");
const showVisible = ref(false)
const selectTime_yc = ref('今日') //犯罪预测时间类型
const listQuery = ref({});
const fzycTime = ref([getRecentDay(0), getRecentDay(0)]);
const circleList = ref([]);
const showClassL = ref(false); //左列折叠
const showClassR = ref(false); //右列折叠
const isShowJzGroup = ref(false) //展示警组弹窗
const isShowFZYC = ref(false) //展示犯罪预测
const jzxqList = ref({}) //警组列表详情
const fzycInfo = ref({}) //犯罪预测
const btnTatol = ref([
{
text: '报备统计',
total: 0
},
{
text: '盘查人员',
total: 0
},
{
text: '盘查车辆',
total: 0
},
{
text: '打卡统计',
total: 0
},
{
text: '指令统计',
total: 0
},
{
text: '需求统计',
total: 0
},
{
text: '处警统计',
total: 0
},
])
const timeList = ref({
list: ['09:00-13:00', '13:00-17:00', '17:00-21:00', '21:00-01:00', '01:00-09:00'],
hasChoose: [],
})
const isShowCount = ref(false) //是否展示统计
watch(() => showClassR.value,
(val) => { emitter.emit("followUp", !val); }
);
onMounted(() => {
getBtnTotal()
window.openTk = openTk;
// getListData();
// 融合通迅
let idEntityCard = window.localStorage.getItem("idEntityCard");
let sfrh = window.localStorage.getItem("SFRH");
if (sfrh == 1 && idEntityCard) {
try {
SPPUC.init(idEntityCard, "",
function () { },
function (device_id, type, [lng, lat, speed]) { }
);
} catch { }
}
// 展示犯罪预测
emitter.on("showFzycInfo", (res) => {
isShowFZYC.value = res.type ? true : false
fzycInfo.value = res.info;
})
// 展示警组
emitter.on("showJzInfo", (res) => {
isShowJzGroup.value = res ? true : false;
if (res) {
res.txzb = typeof res.txzb == "string" ? JSON.parse(res.txzb) : res.txzb ? res.txzb : [];
res.pbmj = typeof res.pbmj == "string" ? JSON.parse(res.pbmj) : res.pbmj ? res.pbmj : [];
res.pbfj = typeof res.pbfj == "string" ? JSON.parse(res.pbfj) : res.pbfj ? res.pbfj : [];
res.jyqx = typeof res.jyqx == "string" ? JSON.parse(res.jyqx) : res.jyqx ? res.jyqx : [];
res.pbcl = typeof res.pbcl == "string" ? JSON.parse(res.pbcl) : res.pbcl ? res.pbcl : [];
jzxqList.value = res;
jzxqList.value.openJyqx = [];
}
if (!isShowJzGroup.value) {
emitter.emit("deleteText"); //清除巡防区文字
emitter.emit("deletePointArea", "xfq"); //清除巡防区
}
});
});
const openTk = (id) => {
let obj = circleList.value.find((item) => { return item.id == id; });
if (obj) emitter.emit("showAj", [obj]);
};
// 获取列表
function getListData() {
let data = { pageSize: 1000, pageNum: 1, zdjqtjlx: "03", czzt: "0,1" };
getSelectVigilant(data).then((res) => {
circleList.value = res.records;
for (let i = 0; i < res.records.length; i++) {
const el = res.records[i];
emitter.emit("SsCircle", el);
let { jd, wd } = el;
emitter.emit("addPointArea", { coords: [{ jd, wd }], icon: require("@/assets/point/sos.png"), flag: "sosPoint" });
}
});
}
const getBtnTotal = async () => {
btnTatol.value[0].total = await getTotal("/mosty-qwzx/tbQwXfbb/getBbCount");
let prInfo = await getTotal("/mosty-hczx/tbHcCount/selectRCCount")
btnTatol.value[1].total = prInfo.bpcryCount;
btnTatol.value[2].total = prInfo.bpcclCount;
btnTatol.value[3].total = await getTotal("/mosty-qwzx/jlqk/xfbb/dk/selectXfbbDkCount");
let zlInfo = await getTotal("/mosty-yjzl/tbZlxxtj/selectRgzlCount")
btnTatol.value[4].total = zlInfo.rgzlCount;
btnTatol.value[5].total = zlInfo.sjqzCount;
btnTatol.value[6].total = await getTotal("/mosty-qwzx/tbQwCjbs/selectCountToday");
}
// 获取统计数量
const getTotal = (url) => {
return new Promise(ok => {
qcckGet({}, url).then(res => {
ok(res);
})
});
}
//点击下发指令
function clickXfzl() {
emitter.emit("closeAllDialog");
emitter.emit("showZlxf");
}
//点击犯罪预测
function clickAddEvent() {
showVisible.value = !showVisible.value
if (!showVisible.value) calcelFzyc('')
}
// 犯罪预测时间选择
function changeYcTime(val) {
let time = []
switch (val) {
case '今日':
time = [getRecentDay(0), getRecentDay(0)]
break;
case '昨日':
time = [getRecentDay(-1), getRecentDay(-1)]
break;
case '本周':
time = getThistWeekDare('week')
break;
case '本月':
time = getThistWeekDare('month')
break;
case '近30日':
time = [getRecentDay(-30), getRecentDay(0)]
break;
case '本季度':
time = getThistWeekDare('quarter')
break;
case '近半年':
time = [getRecentDay(-181), getRecentDay(0)]
break;
case '近一年':
time = [getRecentDay(-365), getRecentDay(0)]
break;
}
fzycTime.value = time
}
// 取消犯罪预测
function calcelFzyc(val) {
// if(val) emitter.emit("deletePointArea", "zdxl_fzyc");
fzycTime.value = [getRecentDay(0), getRecentDay(0)];
listQuery.value.ssbmdm = '';
listQuery.value.sfxl = '';
listQuery.value.keyWord = '';
selectTime_yc.value = '今日';
showVisible.value = false
timeList.value.hasChoose = []
}
// 选择班次
function changeDataBC(val) {
timeList.value.hasChoose = val;
}
// 犯罪预测
function handleFzyc() {
emitter.emit("deletePointArea", "zdxl_fzyc");
let list = timeList.value.hasChoose.map(item => {
return item.slice(0, 2) + item.slice(5, 8)
})
let params = {
...listQuery.value,
bcList: list,
kssj: fzycTime.value[0],
jssj: fzycTime.value[1],
}
queryListfzyc(params).then((res) => {
if (res.length == 0) return false;
let cc = []
let list = res.map((el, index) => {
let centerPoint = [el.zxX, el.zxY]
if (index == 0) cc = centerPoint;
let position = [[Number(el.x1), Number(el.y1)], [Number(el.x2), Number(el.y2)]]
let text = el.realDate + ' ' + el.bc
let obj = { position: position, text, id: el.id, userData: el, sfxl: el.sfxl }
return obj;
});
let arr1 = list.filter(v => { return v.sfxl == 1 })
let arr2 = list.filter(v => { return v.sfxl != 1 })
let params1 = { fontColor: '#12fdb8', coords: arr2, type: 'rectangle', flag: 'zdxl_fzyc', color: 'rgba(2,20,51,0.5)', linecolor: '#f51616' }
let params2 = { fontColor: '#12fdb8', coords: arr1, type: 'rectangle', flag: 'zdxl_fzyc', color: 'rgba(2,20,51,0.5)', linecolor: '#1C97FF' }
emitter.emit("echoPlane", params1);
emitter.emit("echoPlane", params2);
emitter.emit("setMapCenter", { location: cc, zoomLevel: 14 });
});
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
// 中间统计数据
.statisModel {
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
overflow: hidden;
}
.Rank {
left: 500px;
position: absolute;
z-index: 999;
color: #010f30;
font-size: 20px;
top: 100px;
left: 390px;
cursor: pointer;
}
.showCount {
width: 1100px;
height: 90px;
transition: height 1s;
-webkit-transition: height 1s;
}
.heddenCount {
width: 1100px;
height: 0px;
transition: height 1s;
-webkit-transition: height 1s;
}
.transition {
transition: all 0.5s;
}
.depBox {
display: flex;
align-items: center;
color: #00BFFF;
margin-bottom: 10px;
}
.addBox {
::v-deep .el-radio {
width: 74px;
margin-right: 15px;
color: #fff;
}
}
.footerBtns {
margin-top: 10px;
text-align: center;
}
::v-deep .el-input__inner {
background-color: transparent;
border: 1px solid #224ab5;
color: #fff;
margin-right: 10px;
}
::v-deep .el-range-editor .el-range-input {
background: transparent;
color: #fff;
}
::v-deep .el-date-editor .el-range-separator {
color: #fff;
}
::v-deep .el-checkbox {
color: #fff;
}
.upload_home {
position: absolute;
top: 10%;
right: 21%;
}
.footBox {
bottom: 80px !important;
ul {
display: flex;
justify-content: space-between;
align-items: center;
li {
text-align: center;
border-radius: 50%;
.text_total {
font-size: 16px;
font-weight: 600;
color: #0072FF;
}
.bg_text{
background-color: #2D598F;
color: #fff;
}
}
}
}
.img_total {
height: 80px;
width: 100px;
margin-top: -16px;
}
.img_total0 {
background: url('~@/assets/home/bb_total.png')no-repeat;
background-size: 100% 100%;
}
.img_total1 {
background: url('~@/assets/home/rc_total.png')no-repeat;
background-size: 100% 100%;
}
.img_total2 {
background: url('~@/assets/home/rc_total.png')no-repeat;
background-size: 100% 100%;
}
.img_total3 {
background: url('~@/assets/home/dk_total.png')no-repeat;
background-size: 100% 100%;
}
.img_total4 {
background: url('~@/assets/home/zl_total.png')no-repeat;
background-size: 100% 100%;
}
.img_total5 {
background: url('~@/assets/home/zl_total.png')no-repeat;
background-size: 100% 100%;
}
.img_total6 {
background: url('~@/assets/home/cj_total.png')no-repeat;
background-size: 100% 100%;
}
</style>

View File

@ -0,0 +1,366 @@
<template>
<div class="footBox">
<ul class="btnsBox">
<li class="btnsItem" v-for="(item, index) in footBtnImg" :key="index" @click="chooseIcon(item)">
<img :src="item.isChecked ? item.iconActive : item.icon" :title="item.title" style="max-width:66px" />
<div class="resourceBox" v-if="item.hastc">
<div class="contant" :class="item.type == 'across' ? 'contantAcross' : ''">
<!-- 巡防区 -->
<div style="width: 250px;padding-left: 20px;box-sizing: border-box;" v-if="item.title == '巡防区'">
<el-radio-group v-model="radioValue" @change="chooseTag">
<el-radio v-for="it in D_BZ_BMYWLX" :label="it.label" :value="it" :key="it.value" />
</el-radio-group>
</div>
</div>
</div>
</li>
</ul>
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import { ElMessage } from "element-plus";
import { qcckGet } from "@/api/qcckApi.js";
import { ref, defineEmits, onMounted, getCurrentInstance, watch, reactive } from "vue";
import { getGazyPointList } from "@/api/dpApi/home.js";
const { proxy } = getCurrentInstance();
const { D_BZ_BMYWLX } = proxy.$dict("D_BZ_BMYWLX");
const emit = defineEmits(["myClick"]);
const radioValue = ref('')
const footBtnImg = ref([
{
hastc: false,
isChecked: false,
iconActive: require('@/assets/my/icon-gazy-active.png'),
icon: require("@/assets/my/icon-gazy.png"),
title: "公安局",
type: 'vertical'
},
{
hastc: false,
isChecked: false,
iconActive: require('@/assets/my/icon-jq-active.png'),
icon: require("@/assets/my/icon-jq.png"),
title: "派出所",
type: 'vertical'
},
{
hastc: false,
isChecked: false,
iconActive: require('@/assets/my/icon-shzy-active.png'),
icon: require("@/assets/my/icon-shzy.png"),
title: "警务站",
type: 'vertical'
},
{
hastc: true,
isChecked: false,
iconActive: require('@/assets/my/icon-sb-active.png'),
icon: require("@/assets/my/icon-sb.png"),
title: "巡防区",
type: 'vertical'
},
{
hastc: false,
isChecked: false,
iconActive: require('@/assets/my/icon-kfd-active.png'),
icon: require("@/assets/my/icon-kfd.png"),
title: "快反点",
type: 'vertical'
},
{
hastc: false,
isChecked: false,
iconActive: require('@/assets/my/icon-zdfk-active.png'),
icon: require("@/assets/my/icon-zdfk.png"),
title: "重点防控点",
type: 'vertical'
},
{
hastc: false,
iconActive: require("@/assets/my/icon-clearn.png"),
icon: require("@/assets/my/icon-clearn.png"),
title: "清除",
type: 'vertical'
}
]);
onMounted(() => {
window.openTExt = openTExt;
})
// 高亮巡防区域
function openTExt(id) {
qcckGet({}, '/mosty-jcgl/tbJcglXfqy/selectById?id=' + id).then(res => {
if (!res) return false
let ddat = { arr: res.pgis, flag: 'xfqJS', color: '#b9332e', opacity: 0.6, isclear: true }
handleArr(ddat)
})
}
// 判断是否选择按钮
function chooseIcon(item) {
item.isChecked = !item.isChecked;
switch (item.title) {
case '公安局':
if (item.isChecked) showGazyMarker('公安局');
else emitter.emit("deletePointArea", "gaj"); //清除公安局
break;
case '派出所':
if (item.isChecked) showGazyMarker('派出所');
else emitter.emit("deletePointArea", "pcs"); //清除派出所
break;
case '警务站':
if (item.isChecked) showGazyMarker('警务站');
else emitter.emit("deletePointArea", "jwz"); //清除警务站
break;
case '重点防控点':
if (item.isChecked) showGazyMarker('重点防控点');
else emitter.emit("deletePointArea", "zdfkd"); //清除重点防控点
break;
case '快反点':
if (item.isChecked) {
showGazyMarker('快反点');
} else {
emitter.emit("deletePointArea", "kfd");//清除快反点
emitter.emit("deletePointArea", "kfdArea");
}
break;
case '清除':
clearAll()
break;
}
}
//一键清除
function clearAll() {
emitter.emit("deletePointArea", "xfq");
emitter.emit("bd_closeOverlay", true);
emitter.emit("closeAllDialog");
emitter.emit("deletePointArea", "xfqJS"); //清除巡防区高亮
emitter.emit("deletePointArea", "centerpoint");
radioValue.value = ''
footBtnImg.value.forEach(v => { v.isChecked = false })
}
// 选择巡防区域
function chooseTag(val) {
footBtnImg.value[3].isChecked = true;
emitter.emit("deletePointArea", "xfq");
emitter.emit("deleteText");
let obj = D_BZ_BMYWLX.value.find(item => {
return item.label == val
})
if(obj) showGazyMarker('巡防区', obj.dm)
}
// 显示公安资源信息
function showGazyMarker(val, dm) {
if (val == "公安局") {
let data = { ysdl: "001", yszl: "001001", ysxl: "001001003" };
getGazyPointList(data).then((res) => {
let arr = res.records ? res.records : [];
let icon = require("@/assets/point/gaj.png");
handlePoint(arr, icon, "gaj");
});
} else if (val == "派出所") {
let data = { ysdl: "001", yszl: "001001", ysxl: "001001004" };
getGazyPointList(data).then((res) => {
let arr = res.records ? res.records : [];
let icon = require("@/assets/point/pcs.png");
handlePoint(arr, icon, "pcs");
});
} else if (val == "警务站") {
let data = { ysdl: "001", yszl: "001001", ysxl: "001001007" };
getGazyPointList(data).then((res) => {
let arr = res.records ? res.records : [];
let icon = require("@/assets/point/jwz.png");
emitter.emit("showPoint", { coords: arr, icon, flag: 'jwz' });
});
} else if (val == "快反点") {
let data = { ysdl: "001", yszl: "001001", ysxl: "001001008" };
getGazyPointList(data).then((res) => {
if (res) {
let icon = require("@/assets/point/f.png")
emitter.emit("showPoint", { coords: res.records, icon, flag: 'kfd' });
} else {
ElMessage({ message: "暂无快反点数据", type: "warning" });
}
});
} else if (val == "重点防控点") {
let data = { ysdl: "001", yszl: "001001", ysxl: "001001011" };
getGazyPointList(data).then((res) => {
let arr = res.records ? res.records : [];
let icon = require("@/assets/point/kfd.png");
handlePoint(arr, icon, "zdfkd");
});
} else if (val == "巡防区") {
let data = { ysdl: "001", yszl: "001001", ysxl: "001001006" };
if (dm) data.bz = dm
getGazyPointList(data).then((res) => {
console.log(res);
if ( res && res.records.length > 0) {
let color = { stops: [], property: 'FID', }
let linecolor = { stops: [] }
let arrs = res.records.map((item, idx) => {
let ys = changeColor(item.color, 0.4)
linecolor.stops.push(ys.replace(0.4, 1))
color.stops.push([idx + 1, ys])
let obj = { position: [item.dtm], FID: idx + 1, text: item.gajgmc, id: item.id }
if (item.dtm) return obj;
})
let params = { coords: arrs, type: 'polygon', flag: 'xfq', color }
emitter.emit("echoPlane", params);
} else {
ElMessage({ message: "暂无巡防区数据", type: "warning" });
}
});
}
}
// 颜色转换成rgba格式
function changeColor(hex, opacity) {
return 'rgba(' + parseInt('0x' + hex.slice(1, 3)) + ',' + parseInt('0x' + hex.slice(3, 5)) + ',' + parseInt('0x' + hex.slice(5, 7)) + ',' + opacity + ')'
}
// 处理撒点
function handlePoint(arr, icon, flag, scale) {
let list = arr.filter((item) => { return item.jd && item.wd; });
if (list.length > 0) emitter.emit("addPoint", { coords: list, icon: icon, flag: flag, scale });
}
// 处理1-3-5数据
function handleArr(obj) {
let brr = [];
let crr = [];
obj.arr.forEach((val1) => { brr.push(...val1); });
let str = brr.toString();
crr.push(str);
let params = { coords: crr, flag: obj.flag, color: obj.color, opacity: obj.opacity, isclear: obj.isclear || false }
emitter.emit("polygonFigure", params);
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.search_gzy_box {
position: relative;
.search_key_outBox {
width: 100%;
bottom: 52px;
position: absolute;
.search_key {
width: 100%;
padding: 10px;
background: #041f6e;
border-radius: 4px;
max-height: 60vh;
overflow: hidden;
overflow-y: auto;
.key_item {
line-height: 30px;
border-bottom: 1px solid #565656;
padding-left: 10px;
}
.key_item:hover {
background: #0d4a62;
color: #12d2b0;
}
}
}
.search_key_outBox::after {
// position:absolute;
// content:'';
// width:0;
// height:0;
// bottom:-20px;
// left:50%;
// transform: tanslateX(-50%);
// border:10px solid;
// border-color:#041f6e transparent transparent transparent;
}
}
.depBox {
display: flex;
align-items: center;
padding-left: 20px;
color: #00bfff;
}
::v-deep .el-radio {
margin-right: 15px;
color: #fff;
}
::v-deep .el-range-editor.el-input__inner {
width: 100%;
}
::v-deep .el-radio-group {
width: 100%;
// padding-left:20px;
}
::v-deep .el-input__inner {
background-color: transparent;
border: 1px solid #224ab5;
color: #fff;
margin: 10px 0;
margin-right: 10px;
}
::v-deep .el-range-editor .el-range-input {
background: transparent;
color: #fff;
}
::v-deep .el-checkbox__label {
color: #fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label {
color: #01e9ed;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #01e9ed;
border-color: #01e9ed;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: #01e9ed;
border-color: #01e9ed;
}
::v-deep .el-date-editor .el-range-separator {
color: #fff;
}
::v-deep .el-input-group__append {
background-color: transparent;
border: none;
padding: 0 12px;
}
.jqTimeBox {
::v-deep .el-date-range-picker {
width: 500px;
}
::v-deep .el-input__inner {
color: #000;
}
::v-deep .el-time-panel {
left: -52px;
}
}
</style>

View File

@ -0,0 +1,110 @@
<!--
* @Author: your name
* @Date: 2023-01-05 16:04:29
* @LastEditTime: 2023-01-30 15:44:49
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \lz_web_new\src\views\lz\home\layout\dialogModular.vue
-->
<template>
<div class="modelDialogBox">
<el-dialog v-model="dialogVisible" title="系统模块" width="800px" :show-close="false" :center="true"
:before-close="handleClose">
<ul class="modularList">
<li @click="gotoPage('/serviceManagement')">
<div class="itemBG">
<div>
<img src="@/assets/images/ydImg/qwzx.png" />
</div>
<div>勤务中心</div>
</div>
</li>
<li @click="gotoPage('/warningCenters')">
<div class="itemBG">
<div>
<img src="@/assets/images/ydImg/yjzx.png" />
</div>
<div>预警中心</div>
</div>
</li>
<li @click="gotoPage('/taskCenters')">
<div class="itemBG">
<div>
<img src="@/assets/images/ydImg/rwzx.png" />
</div>
<div>任务中心</div>
</div>
</li>
<li @click="gotoPage('/editPassword')">
<div class="itemBG">
<div>
<img src="@/assets/images/ydImg/ht.png" />
</div>
<div>前往后台</div>
</div>
</li>
</ul>
</el-dialog>
</div>
</template>
<script setup>
import { ref } from "vue";
import { defineEmits } from "vue";
import { useRoute, useRouter } from "vue-router";
const emit = defineEmits(["modularShowFn"]);
const dialogVisible = ref(true);
const router = useRouter();
function handleClose() {
emit("modularShowFn", false);
}
// 跳转页面
function gotoPage(url) {
router.replace(url);
handleClose()
}
</script>
<style lang="scss" scoped>
.dialog-footer button:first-child {
margin-right: 10px;
}
ul.modularList {
overflow: hidden;
li {
text-align: center;
float: left;
width: 25%;
font-size: 14px;
color: #fff;
line-height: 24px;
height: 180px;
.itemBG {
margin: 0 auto;
width: 140px;
height: 180px;
background: url("~@/assets/images/ydImg/bg.png") no-repeat center center;
background-size: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
}
}
</style>
<style>
.modelDialogBox .el-dialog {
margin-top: 20vh;
}
.modelDialogBox .el-dialog__header {
border-bottom: 2px solid;
border-top: 2px solid;
border-image: linear-gradient(90deg, rgba(0, 216, 247, 0) 0%, #2FD5FE 50%, rgba(0, 216, 247, 0) 99%) 2 2 2 2;
background: linear-gradient(90deg, rgba(7, 28, 76, .3), rgba(3, 70, 156, .9), rgba(7, 28, 76, .3));
border-radius: 5px;
}
</style>

View File

@ -0,0 +1,366 @@
<template>
<div class="dialogBox" :style="`right:${elRight}px;bottom:${elBottom}px`" draggable="true" ref="dialogBoxYpfx"
@dragstart="dragstart($event)" @dragend="dragend($event)">
<div class="title">
<span class="mc">犯罪预测</span>
<span @click="close" class="close"><el-icon>
<Close />
</el-icon></span>
</div>
<div class="info-Big-Box">
<!-- <el-radio-group v-model="radioTime" @change="handleRadio">
<el-radio-button label="今日" />
<el-radio-button label="昨日" />
<el-radio-button label="本周" />
<el-radio-button label="本月" />
<el-radio-button label="近30日" />
<el-radio-button label="本季度" />
<el-radio-button label="近半年" />
<el-radio-button label="近一年" />
<el-popover :width="400" trigger="click" placement="bottom" v-model:visible="showVisible">
<template #reference><el-radio-button label="自定义" /></template>
<el-date-picker v-model="daterangeTime" type="daterange" unlink-panels style="width:100%;" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期" :teleported="false" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
</el-popover>
</el-radio-group> -->
<div class="tableBox noScollLine" v-loading="loading">
<!-- 标题 -->
<el-row>
<el-col :span="4" class="grid-content-top">所属部门</el-col>
<el-col :span="5" class="grid-content-top">时间</el-col>
<el-col :span="15">
<el-row style="width:100%;">
<el-col :span="3" class="grid-content-top">巡逻警组</el-col>
<el-col :span="3" class="grid-content-top">巡逻时长</el-col>
<el-col :span="3" class="grid-content-top">巡逻里程</el-col>
<el-col :span="3" class="grid-content-top">警情数</el-col>
<el-col :span="3" class="grid-content-top">签收状态</el-col>
<el-col :span="3" class="grid-content-top">盘查人员</el-col>
<el-col :span="3" class="grid-content-top">盘查车辆</el-col>
<el-col :span="3" class="grid-content-top">操作</el-col>
</el-row>
</el-col>
</el-row>
<div class="null" v-if="list.length <= 0 && !loading">
<el-empty description="没有数据" />
</div>
<!-- 循环数据 -->
<el-row v-for="(item, index) in list" :key="index">
<el-col :span="4" class="grid-content-nr">
<el-tooltip :content="item.ssbm" placement="bottom">
<div class="flexTool">
<div class="w-78">{{ item.ssbm }}</div>
</div>
</el-tooltip>
</el-col>
<el-col :span="20" v-if="item.children && item.children.length > 0">
<el-row style="width:100%;" v-for="(it, idx) in item.children" :key="idx + 0.1">
<el-col :span="6" class="grid-content-nr">
<el-tooltip :content="it.xlkssj + ' ~ ' + it.xlkssj" placement="bottom">
<div class="flexTool">
<div class="w-115">{{ it.xlkssj }} ~ {{ it.xlkssj }}</div>
</div>
</el-tooltip>
</el-col>
<el-col :span="18">
<el-row style="width:100%;">
<el-col :span="3" class="grid-content-nr">{{ it.xzmc }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ (it.xfsc / 3600).toFixed(2) }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ (it.xflc / 1000).toFixed(2) }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ props.data.prob }}</el-col>
<el-col :span="3" class="grid-content-nr"> <el-text type="warning">{{ it.sfqsmc }}</el-text> </el-col>
<el-col :span="3" class="grid-content-nr">{{ it.pcry }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ it.pccl }}</el-col>
<el-col :span="3" class="grid-content-top" @click="ganhdleGJHF(it)">轨迹回放</el-col>
</el-row>
</el-col>
</el-row>
</el-col>
<el-col :span="20" v-else>
<el-row style="width:100%;">
<el-col :span="6" class="grid-content-nr">
<el-tooltip :content="item.xlkssj + ' ~ ' + item.xlkssj" placement="bottom">
<div class="flexTool">
<div class="w-115">{{ item.xlkssj }} ~ {{ item.xlkssj }}</div>
</div>
</el-tooltip>
</el-col>
<el-col :span="18">
<el-row style="width:100%;">
<el-col :span="3" class="grid-content-nr">{{ item.xzmc }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ (item.xfsc / 3600).toFixed(2) }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ (item.xflc / 1000).toFixed(2) }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ props.data.prob }}</el-col>
<el-col :span="3" class="grid-content-nr"> <el-text type="warning">{{ item.sfqsmc }}</el-text> </el-col>
<el-col :span="3" class="grid-content-nr">{{ item.pcry }}</el-col>
<el-col :span="3" class="grid-content-nr">{{ item.pccl }}</el-col>
<el-col :span="3" class="grid-content-top" @click="ganhdleGJHF(item)">轨迹回放</el-col>
</el-row>
</el-col>
</el-row>
</el-col>
</el-row>
<!-- 统计数据 -->
<!-- <el-row>
<el-col :span="4" class="grid-content-nr">合计</el-col>
<el-col :span="5" class="grid-content-nr">-</el-col>
<el-col :span="15">
<el-row style="width:100%;">
<el-col :span="3" class="grid-content-top">-</el-col>
<el-col :span="3" class="grid-content-top">11'45''</el-col>
<el-col :span="3" class="grid-content-top">136公里</el-col>
<el-col :span="3" class="grid-content-top">12</el-col>
<el-col :span="3" class="grid-content-top">-</el-col>
<el-col :span="3" class="grid-content-top">89</el-col>
<el-col :span="3" class="grid-content-top">90</el-col>
<el-col :span="3" class="grid-content-top">-</el-col>
</el-row>
</el-col>
</el-row> -->
</div>
</div>
</div>
</template>
<script setup>
import { queryQfzxl } from "@/api/dpApi/home.js";
import { getRecentDay, getThistWeekDare } from "@/utils/tools.js";
import MyTable from "@/components/aboutTable/DarkTable.vue";
import { qcckPost } from "@/api/qcckApi.js";
import { ref, onMounted, onUnmounted, reactive, defineProps, getCurrentInstance, watch } from "vue";
import { timeValidate } from "@/utils/time.js";
import emitter from "@/utils/eventBus.js";
const { proxy } = getCurrentInstance();
const props = defineProps({
data: {
type: Object,
default: {}
}
});
const showVisible = ref(false)
const daterangeTime = ref([])
const radioTime = ref('今日')
const dialogBoxYpfx = ref();
const initWidth = ref(0); //父元素宽度
const initHeight = ref(0); //父元素高度
const startClientX = ref(0); //元素拖拽前距离浏览器X轴位置
const startClientY = ref(0); //元素拖拽前距离浏览器Y轴位置
const elRight = ref(10); //元素右偏移量
const elBottom = ref(120); //元素底偏移量
const dateRange = ref([getRecentDay(0), getRecentDay(0)])
const list = ref([])
const loading = ref(false)
watch(() => props.data, (val) => {
if (val) fzyjcJL(val.id);
}, { immediate: true, deep: true });
onMounted(() => {
initBodySize();
});
function fzyjcJL(id) {
loading.value = true
queryQfzxl({ id }).then((res) => {
loading.value = false
let arr = res || []
let brr = [];
let dms = []
arr.forEach((item) => {
if (!dms.includes(item.ssbmdm)) {
dms.push(item.ssbmdm);
let obj = { ...item }
obj.children = [item];
brr.push(obj)
} else {
let inx = dms.findIndex(val => val == item.ssbmdm)
brr[inx].children.push(item)
}
});
list.value = brr;
}).catch(() => { loading.value = false });
};
// 处理时间单选
function handleRadio(val) {
showVisible.value = val == '自定义' ? true : false;
let time = []
switch (val) {
case '今日':
time = [getRecentDay(0), getRecentDay(0)]
break;
case '昨日':
time = [getRecentDay(-1), getRecentDay(-1)]
break;
case '本周':
time = getThistWeekDare('week')
break;
case '本月':
time = getThistWeekDare('month')
break;
case '近30日':
time = [getRecentDay(-30), getRecentDay(0)]
break;
case '本季度':
time = getThistWeekDare('quarter')
break;
case '近半年':
time = [getRecentDay(-181), getRecentDay(0)]
break;
case '近一年':
time = [getRecentDay(-365), getRecentDay(0)]
break;
}
dateRange.value = time;
}
//初始化
const initBodySize = () => {
initWidth.value = dialogBoxYpfx.value.clientWidth;
initHeight.value = dialogBoxYpfx.value.clientHeight;
};
//拖拽开始
const dragstart = (e) => {
startClientX.value = e.clientX;
startClientY.value = e.clientY;
};
//拖拽结束
const dragend = (e) => {
let x = e.clientX - startClientX.value;
let y = e.clientY - startClientY.value;
elRight.value -= x;
elBottom.value -= y;
};
// 轨迹回放
function ganhdleGJHF(item) {
emitter.emit("deletePointArea", "routeGj");;
let arr = item.zbList || [];
if (arr.length > 0) {
emitter.emit("drawLineAnimation", { coords: arr, isClear: true, flag: 'routeGj' });
} else {
proxy.$message({ type: "warning", message: `没有轨迹数据` });
}
}
//关闭弹窗
function close() {
emitter.emit("showFzycInfo", { type: false });
emitter.emit("deletePointArea", "routeGj");
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.dialogBox {
position: absolute;
padding: 0;
box-sizing: border-box;
width: 1000px !important;
.title {
border-bottom: 1px solid #275288;
margin-bottom: 6px;
margin-left: 11px;
margin-right: 20px;
.mc {
margin-left: 10px;
}
}
.info-Big-Box {
padding: 4px 10px;
box-sizing: border-box;
.tableBox {
padding: 10px 20px;
box-sizing: border-box;
height: 57vh;
overflow: hidden;
overflow-y: auto;
.grid-content-top {
background: #052466;
border: 1px solid #013995;
text-align: center;
padding: 4px 0;
box-sizing: border-box;
}
.grid-content-nr {
border: 1px solid #013995;
text-align: center;
padding: 4px 0;
box-sizing: border-box;
}
}
}
}
.el-radio-group {
margin-left: 20px;
}
.el-radio-button {
margin: 0 2px;
}
::v-deep .el-collapse {
width: 100%;
--el-collapse-header-height: auto;
--el-collapse-header-bg-color: transparent;
--el-collapse-border-color: transparent;
}
::v-deep .el-collapse-item__header {
color: #00bfff;
}
::v-deep .el-collapse-item__wrap {
background-color: transparent;
}
::v-deep .el-collapse-item__content {
color: #fff;
}
::v-deep .el-popper.is-light {
transform: translate(5px, 336px) !important;
}
.flexTool {
height: 100%;
display: flex;
align-items: center;
}
.w-78 {
width: 150px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-left: 4px;
}
.w-115 {
width: 188px;
white-space: nowrap;
overflow: hidden;
margin-left: 4px;
text-overflow: ellipsis;
}
.null {
text-align: center;
}
:v-deep .el-loading-mask {
background-color: rgba(0, 0, 0, .5) !important;
}
</style>
<style>
.el-loading-mask {
background-color: rgba(0, 0, 0, .5) !important;
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<div class="headBox">
<div class="top">
<div class="top-left">
<div class="qwbg"></div>
<div class="time">
<div class="timer">{{ hour + ":" + minute + ":" + second }}</div>
<div class="week">{{ weekenday }} {{ datatime }}</div>
</div>
</div>
<div class="top-right">
<div class="info">
<img class="photo" src="@/assets/my/photo.png" />
<div class="text">
<div>姓名{{ username }}</div>
<div class="dept" :tabindex="deptName">
单位<el-tooltip :content="deptName">{{ deptName }}</el-tooltip>
</div>
</div>
<el-dropdown :hide-on-click="false">
<span class="el-dropdown-link">
<el-icon :size="20" color="#fff">
<CaretBottom />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu class="loginOut" @click="logout">
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<div class="meun" @click="modularShowFn" title="后台">
<img src="@/assets/my/meun.png" />
</div>
<el-popover trigger="click" placement="bottom" v-model:visible="showVisible" :append-to-body="false">
<template #reference>
<span class="el-dropdown-tools" @click="showVisible = !showVisible">
<span class="el-dropdown-tools-n">
<el-icon :size="26" color="#28426a">
<Tools />
</el-icon>
</span>
</span>
</template>
<div @click="handleRhtx" class="settingItem"><el-icon>
<Notification />
</el-icon>融合通信 </div>
<div @click="handleJxkh" class="settingItem"><el-icon>
<Notification />
</el-icon>绩效考核</div>
</el-popover>
</div>
</div>
<Performance v-model="modelValue" />
</div>
</template>
<script setup>
import { getRecentDay } from "@/utils/tools.js";
import { useRouter, useRoute, onBeforeRouteLeave } from "vue-router";
import { useStore } from "vuex";
import { ref, onMounted, defineEmits, onUnmounted } from "vue";
import Performance from './performance.vue'
const modelValue = ref(false)
const showVisible = ref(false)
const store = useStore();
const router = useRouter();
const route = useRoute();
const username = ref("");
const weekenday = ref('') //星期几
const datatime = ref(getRecentDay(0));
const minute = ref("00"); //分
const second = ref("00"); //秒
const hour = ref("00"); //时
const day = ref(0);
const deptName = ref(JSON.parse(localStorage.getItem("deptId"))[0].deptName);
const modularShow = ref(false);
const timersfm = ref(null);
onMounted(() => {
getWeek()
username.value = localStorage.getItem("USERNAME");
timersfm.value = setInterval(() => {
CurrentTime();
}, 1000);
});
// 打开融合通信页面
function handleRhtx(params) {
const DDZHhref = router.resolve({
name: "rhtx", //这里是跳转页面的name
path: "/rhtx"
});
window.open(DDZHhref.href, "_blank");
}
// 打开绩效考核
function handleJxkh() {
modelValue.value = true;
showVisible.value = false
}
function getWeek() {
let week = new Date().getDay()
switch (week) {
case 0:
return weekenday.value = '星期日'
break;
case 1:
return weekenday.value = '星期一'
break;
case 2:
return weekenday.value = '星期二'
break;
case 3:
return weekenday.value = '星期三'
break;
case 4:
return weekenday.value = '星期四'
break;
case 5:
return weekenday.value = '星期五'
break;
case 6:
return weekenday.value = '星期六'
break;
}
}
// 获取时分秒
function CurrentTime() {
const date = new Date();
hour.value = date.getHours();
minute.value = date.getMinutes();
second.value = date.getSeconds();
day.value = day.value < 10 ? "0" + day.value : day.value;
hour.value = hour.value < 10 ? "0" + hour.value : hour.value;
minute.value = minute.value < 10 ? "0" + minute.value : minute.value;
second.value = second.value < 10 ? "0" + second.value : second.value;
}
// 打开菜单弹窗
function modularShowFn(val) {
router.replace('/editPassword');
}
// 退出
const logout = () => {
store.dispatch("user/logout");
store.commit("app/clearTag", null, { immediate: true });
store.commit("permission/deleteRouter", { immediate: true });
store.commit("user/deleteKeepLiiveRoute", "lz/home");
};
onUnmounted(() => {
clearInterval(timersfm.value)
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
::v-deep .el-dialog {
--el-dialog-bg-color: #10295b;
}
::v-deep .el-dialog__title {
color: #fff;
}
.settingItem {
color: #fff;
display: flex;
align-items: center;
height: 30px;
border-bottom: 1px solid #143d91;
padding-left: 10px;
box-sizing: border-box;
cursor: pointer;
.el-icon {
margin-right: 10px;
}
}
.settingItem:hover {
background: #143d91;
}
</style>

View File

@ -0,0 +1,275 @@
<template>
<div>
<div class="pubTitle">
<div class="text">街面巡组</div>
</div>
<div style="padding-top: 8px; overflow: hidden">
<div style="float: left">
<el-checkbox label="1" v-for="(item, index) in checkList" :key="item.value" v-model="item.checked"
@change="onChangeXfzt(index)">
<span class="dian online" v-if="item.value == 0"></span>
<span class="dian busy" v-if="item.value == 1"></span>
<span class="dian" v-if="item.value == 2"></span>
{{ item.label }}
</el-checkbox>
</div>
<div style="float: right">
<button class="dp-default small">全部呼叫</button>
</div>
</div>
<ul class="groupList" v-loading="loading">
<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.mjsl }}辅警{{ item.fjsl }}联系电话{{
item.fzrLxdh
}}</span><br />
<span>巡逻时长{{
item.xfsc != "" && item.xfsc > 0
? (item.xfsc / 3600).toFixed(2)
: 0
}}
h <br />巡逻里程{{
item.xflc ? (item.xflc / 1000).toFixed(2) : 0
}}
m
</span>
</div>
</div>
<div class="address" style="display: flex; justify-content: space-between">
<span>
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span>{{ item.dqwz }}</span>
</span>
<span>
<img style="width: 20px" src="@/assets/images/situationPresentation/light-gray.png" />
</span>
</div>
</li>
<el-empty description="没有数据" :image-size="0.1" v-if="!loading && xzList.list.length <= 0" />
</ul>
</div>
</template>
<script setup>
import { getSelectDeckList } from "@/api/dpApi/home.js";
import emitter from "@/utils/eventBus.js";
import openWebSocket from "@/utils/webSocket.js";
import { ref, reactive, onMounted, defineEmits } from "vue";
//状态数据
const checkList = reactive([
{
value: 0,
label: "巡逻中",
checked: true
},
{
value: 1,
label: "处警中",
checked: true
},
{
value: 2,
label: "离线",
checked: true
}
]);
let xzList = reactive({
list: []
}); //巡组数据
const loading = ref(true); //警组加载
const pageSize = ref(500);
const pageCurrent = ref(1);
const totalPage = ref(0);
const status = ref([]); //巡组状态
const jd = ref(104.14637342);
onMounted(() => {
checkList.forEach((item) => {
if (item.checked === true) {
status.value.push(item.value);
}
});
// 查询巡逻中数据
_ggetSelectDeckList("0,1,2");
scroll();
getWebSocketData();
});
// 获取WebSocket数据
function getWebSocketData() {
let dws = openWebSocket.getInstance();
dws.connect((res) => {
// 接收发送消息
dws.ws.onmessage = (e) => {
let dataInfo = JSON.parse(e.data).data;
if (e && e.data) {
let newsDate = JSON.parse(e.data);
switch (newsDate.type) {
case "03":
if (typeof status.value == "string") { status.value = status.value.split(","); }
status.value.forEach((item, index) => {
if (item == dataInfo.xfzt) {
xzList.list.unshift(JSON.parse(e.data).data);
addPointMaker(dataInfo); //撒点
}
});
break;
case "04":
xzList.list.forEach((value, index) => {
if (value.id == dataInfo.id) {
delPointMaker(dataInfo); //清除原来的撒点
xzList.list.splice(index, 1);
xzList.list.unshift(dataInfo);
addPointMaker(dataInfo); //撒点
emitter.emit("setMapCenter", {
location: [dataInfo.jd, dataInfo.wd],
zoomLevel: '10'
});
}
});
break;
case "05":
xzList.list.forEach((value, index) => {
if (value.id == dataInfo.id) {
delPointMaker(dataInfo); //清除原来的撒点
xzList.list.splice(index, 1);
addPointMaker(dataInfo); //撒点
}
});
break;
}
}
};
});
}
const addPointMaker = (data) => {
emitter.emit("addPointTakeTittle", {
coords: [data],
icon: require(`@/assets/mapIcon/specialPolice.png`),
flag: "rx",
undel: true
});
};
const delPointMaker = (data) => {
emitter.emit("deletePointAreaPolice", { flag: "rx", id: data.id });
};
//选择巡防状态
function onChangeXfzt(e) {
let xfztList = [];
checkList.forEach((item) => {
if (item.checked === true) {
xfztList.push(item.value);
}
});
status.value = xfztList.join(",");
pageCurrent.value = 1;
_ggetSelectDeckList(status.value);
scroll();
}
//查看警组信息
function handelClick(item) {
emitter.emit("closeAllDialog");
emitter.emit("showJzInfo", item);
emitter.emit("closeVideo");
if (item.jd && item.wd) {
emitter.emit("setMapCenter", {
location: [item.jd, item.wd],
zoomLevel: 14
});
}
}
//巡组列表
function _ggetSelectDeckList(xfzt) {
let data = {
xfzt,
pageSize: pageSize.value,
pageCurrent: pageCurrent.value
};
getSelectDeckList(data)
.then((res) => {
loading.value = false;
if (res.records.length > 0) {
let newArry = [];
for (let i = 0; i < res.records.length; i++) {
if (res.records[i].pbfj != null) {
res.records[i].pbfj = JSON.parse(res.records[i].pbfj);
}
if (res.records[i].pbmj != null) {
res.records[i].pbmj = JSON.parse(res.records[i].pbmj);
}
xzList.list = res.records;
if (res.records[i].jd && res.records[i].wd) {
} else {
res.records[i].queryAddress = "没有经纬度";
}
}
let sdList = xzList.list.filter((v) => {
return v.jd && v.wd;
});
emitter.emit("addPointTakeTittle", {
coords: sdList,
icon: require(`@/assets/mapIcon/police-car-bx.png`),
flag: "rx"
});
emitter.emit("setMapCenter", {
location: [sdList[0].jd, sdList[0].wd],
zoomLevel: '10'
});
// 结尾
totalPage.value = res.records.length;
} else if (res.records.length === 0) {
xzList.list = res.records;
emitter.emit("deletePointArea", "cx");
emitter.emit("deletePointArea", "rx");
}
})
.catch(() => {
loading.value = false;
});
}
//触底加载
function scroll() {
let scrollTargetBox = document.querySelector(".groupList");
scrollTargetBox.onscroll = (e) => {
var scrollHeight = scrollTargetBox.scrollHeight; //251
var scrollTop = scrollTargetBox.scrollTop; //0-18
var clientHeight = scrollTargetBox.clientHeight; //233
if (scrollHeight - clientHeight == scrollTop) {
//滚动条滚到最底部
if (totalPage.value < pageSize.value) return;
pageCurrent.value++;
_ggetSelectDeckList(status.value);
}
};
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
//加载时 取消背景
::v-deep .el-loading-mask {
background-color: transparent !important;
}
::v-deep .el-checkbox {
height: 24px;
font-size: 12px;
}
::v-deep .el-checkbox__label {
font-size: 12px;
}
</style>

View File

@ -0,0 +1,97 @@
<template>
<div>
<el-dialog v-model="modelValue" title="系统模块" width="100%" :before-close="handleClose" :append-to-body="false">
<div class="cntBox">
<CntBox />
</div>
</el-dialog>
</div>
</template>
<script setup>
import CntBox from "@/views/backOfficeSystem/performanceMenu/achievements/index.vue";
import { ref, defineEmits, defineProps } from "vue";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
});
const emits = defineEmits(["update:modelValue"]);
function handleClose() {
emits("update:modelValue", false);
}
</script>
<style lang="scss" scoped>
::v-deep .el-dialog {
background: #000;
margin: 0;
--el-dialog-width: 100% !important;
}
::v-deep .el-dialog__body {
padding: 10px;
box-sizing: border-box;
}
.cntBox {
height: calc(100vh - 74px);
overflow: hidden;
overflow-y: auto;
}
::v-deep .el-table--border::after,
.el-table--group::after,
.el-table::before {
background-color: #20606d !important;
}
::v-deep .el-table__border-left-patch {
background-color: #20606d !important;
}
::v-deep .el-table {
--el-table-border-color: #20606d !important;
}
::v-deep .margin-bt-10 {
align-items: center;
}
::v-deep .el-input__inner {
margin: 0 !important;
}
::v-deep .el-dialog__headerbtn .el-dialog__close {
color: #fff;
font-size: 20px;
}
::v-deep .el-table tr {
background-color: #060537;
}
::v-deep .el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
background-color: rgba(34, 83, 140, 0.7);
}
::v-deep .popBody {
height: 70vh;
.el-table {
background-color: #060537;
}
.el-table__body-wrapper {
height: 64vh;
}
}
::v-deep .qs-box {
.popBody {
height: 88vh !important;
max-height: 88vh !important;
}
}
</style>

View File

@ -0,0 +1,215 @@
<template>
<!-- 地图上方翻转框 -->
<div class="m-midN">
<div class="turn-box">
<!-- 正面 -->
<div class="front">
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.wsztry" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.ztry }}</span>
<span class="text-title">网上在逃人员</span>
</div>
</div>
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.sjgzqjry" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.sjgzdjry }}</span>
<span class="text-title">收缴管制器具人员 </span>
</div>
</div>
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.xzlqca" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.xzlqcaj }}</span>
<span class="text-title">行政类侵财案件</span>
</div>
</div>
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.xslqcaj" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.xslqcaj }}</span>
<span class="text-title">刑事类侵财案件</span>
</div>
</div>
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.jzzs" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.jzzs }}</span>
<span class="text-title">救助自杀</span>
</div>
</div>
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.jzzslret" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.jzzslret }}</span>
<span class="text-title">救助走失老人儿童</span>
</div>
</div>
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.mdjf" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.mdjf }}</span>
<span class="text-title">成功化解矛盾纠纷</span>
</div>
</div>
<div class="fornt-item" style="opacity: 1">
<img :src="imgList.other" alt="" width="55" height="75" />
<div class="text-box">
<span class="text-num">{{ fzList.qtaj }}</span>
<span class="text-title">其他类刑事案件</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { getYjCount, getXfbbCount, getPcryCount, getPcclCount } from '@/api/instructCenter.js'
import { ref, onMounted } from "vue";
const cardIndex = ref(0)
const titleList = ref([])
const imgList = ref({
wsztry: require(`../../../../assets/images/wsztry.png`),
sjgzqjry: require(`../../../../assets/images/sjgzqjry.png`),
xzlqca: require(`../../../../assets/images/xzlqca.png`),
xslqcaj: require(`../../../../assets/images/xslqcaj.png`),
jzzs: require(`../../../../assets/images/jzzs.png`),
jzzslret: require(`../../../../assets/images/jzzslret.png`),
mdjf: require(`../../../../assets/images/mdjf.png`),
other: require(`../../../../assets/images/other.png`),
})
const fzList = ref({
ztry: 0,//网上在逃人员
sjgzdjry: 0,//收缴管制器具人员
xzlqcaj: 0,//行政类侵财案件
xslqcaj: 0,//刑事类侵财案件
jzzs: 0,//救助自杀
jzzslret: 0,//救助走失老人儿童
mdjf: 0,//成功化解矛盾纠纷
qtaj: 0,//其他类刑事案件
})
const timer = ref(null)
onMounted(() => {
// _getPcryCount() //获取大屏被盘查统计
})
//获取大屏被盘查人员统计
function _getPcryCount() {
getPcryCount({}).then(res => {
fzList.value.ztry = res.zt //在逃
fzList.value.sdry = res.sd //涉毒
fzList.value.pcry = res.all //盘查人员
})
}
</script>
<style lang="scss" scoped>
.m-midN {
position: absolute;
width: 100%;
height: 100%;
top: 0;
color: #eee;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.turn-box {
width: 100%;
height: 100%;
background: linear-gradient(to right,
rgba(36, 55, 102, 0.3) 0%,
rgba(17, 29, 59, 0.8) 50%,
rgba(36, 55, 102, 0.3) 100%);
position: relative;
transition: all 80s;
transform-style: preserve-3d;
/* 3d呈现让背后盒子立体呈现不然永远是前面一个盒子朝向我们 */
cursor: pointer;
// animation: rotate 10s linear infinite alternate forwards;
}
.turn-box>div {
position: absolute;
top: 0;
/* 让子盒子重叠一起 */
width: 100%;
height: 100%;
// border-radius: 50%;
/* 背面是不可见的 */
backface-visibility: hidden;
}
.front {
z-index: 1;
display: flex;
justify-content: space-between;
}
.back {
transform: rotateX(180deg);
display: flex;
justify-content: space-between;
/* 这里让back盒的先翻转180在front的后面 */
}
.turn-box:hover {
animation-play-state: paused;
/* 悬停事件,使得整个父盒子旋转动画停止 */
}
// @keyframes rotate {
// 0% {
// transform: rotateX(0);
// }
// 25% {
// transform: rotateX(0);
// }
// 50% {
// transform: rotateX(180deg);
// }
// 75% {
// transform: rotateX(180deg);
// }
// 100% {
// transform: rotateX(180deg);
// }
// }
.fornt-item {
flex: 1;
padding: 10px;
display: flex;
justify-content: center;
align-items: center;
.text-box {
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 10px;
.text-num {
font-size: 26px;
margin-bottom: 6px;
color: rgba(58, 173, 231, 1);
@supports (-webkit-background-clip: text) or (background-clip: text) {
background: linear-gradient(to bottom,
rgb(193, 217, 252),
rgba(58, 173, 231, 1));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
}
.text-title {
font-size: 12px;
}
}
}
</style>

View File

@ -0,0 +1,492 @@
<template>
<div class="boxContent">
<!-- 警情推送提示 -->
<audio ref="audioRef">
<source :src="src" />
</audio>
<div class="box-title box-jmqk">
<span>街面情况</span>
<el-tooltip class="media" effect="dark" :content="isPlay ? '关闭警情推送提示音' : '打开警情推送提示音'" placement="top-start">
<el-switch v-model="isPlay" inline-prompt style="--el-switch-on-color:#13ce66;--el-switch-off-color:#ff4949"
active-text="" @change="changeSwitch" inactive-text="">
</el-switch>
</el-tooltip>
</div>
<div class="boxInfo">
<div class="buttonBox">
<img src="@/assets/my/up.png" />
<span class="btnsItem" :class="isActive == item ? 'isActiveBg' : ''" @click="changeDate(item)"
v-for="item in btns" :key="item">{{ item }}</span>
</div>
<div class="choose_Box" v-show="isActive == '预警'">
<el-radio-group v-model="radioyj">
<el-radio v-for="item in radioList1" :key="item" :label="item" @change="changeData">{{ item }}</el-radio>
</el-radio-group>
</div>
<div class="choose_Box" v-show="isActive == '警情'">
<div class="SxBox">
<el-radio-group v-model="radio">
<el-radio v-for="item in radioList" :key="item" :label="item" @change="changeDataJQ">{{ item }}</el-radio>
</el-radio-group>
<el-popover placement="left" :visible="visible" width="460px">
<template #reference>
<el-icon @click="openSearch" title="筛选">
<Grid />
</el-icon>
</template>
<div class="detail_cnt_box">
<el-form :model="listQuery" :inline="true" label-width="80px">
<el-form-item label="报警时间" style="width:100%;">
<el-date-picker v-model="listQuery.bjsj" type="datetimerange" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-M-D HH:mm:ss"
format="YYYY-M-D HH:mm:ss" @change="handelTime" />
</el-form-item>
<el-form-item label="报警内容" style="width:100%;">
<el-input v-model="listQuery.bjnr" placeholder="请输入报警内容"></el-input>
</el-form-item>
<el-form-item label="报警人" style="width:100%;">
<el-input v-model="listQuery.bjrXm" placeholder="请输入报警人"></el-input>
</el-form-item>
<div class="footBtm">
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset"> 重置 </el-button>
</div>
</el-form>
</div>
</el-popover>
</div>
<div class="SxBox">
<el-radio-group v-model="colors">
<el-radio v-for="item in colorList" :key="item" :label="item"
@change="changeDataJQColor">{{ item }}</el-radio>
</el-radio-group>
</div>
</div>
<ul class="cntBox" :class="isActive == '预警' ? 'cntBox-yj' : isActive == '警情' ? 'cntBox-jq' : ''"
v-loading="loading" ref="jmxzScroll">
<li class="cntBox-item" v-for="item in dataList" :key="item.id">
<!-- 指令 -->
<ZlItem v-if="isActive == '指令' || isActive == '需求'" :data="item" @lookDetail="lookDetail" :dic="{ zlzt: D_BZ_ZXZTAI }" />
<!-- 指引 -->
<ZlItem v-if="isActive == '指引'" :data="item" @lookDetail="lookDetail" :dic="{ zlzt: D_BZ_ZXZTAI }" />
</li>
<el-empty description="没有数据" :image-size="0.1" v-if="!loading && dataList.length <= 0" />
</ul>
</div>
</div>
</template>
<script setup>
import CheckBox from "@/components/checkBox/index";
import people from "@/assets/images/peo.png";
import emitter from "@/utils/eventBus.js";
import { qcckPost, qcckGet, qcckPut } from "@/api/qcckApi.js";
import { getSelectVigilant, getSelectVigilantList, getSelectInstructList } from "@/api/dpApi/home.js";
import JqItm from "../components/jqIem.vue";
import YjItem from "../components/yjItem.vue";
import ZlItem from "../components/zlItem.vue";
import { onMounted, reactive, ref, getCurrentInstance, onBeforeUnmount } from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_ZXZTAI, D_BZ_CZZT } = proxy.$dict("D_BZ_ZXZTAI", "D_BZ_CZZT");
const jmxzScroll = ref(null);
const btns = reactive(["指令","需求"]);
const isActive = ref("指令");
const dataList = ref([]);
const loading = ref(false);
const total = ref(0);
const pageNum = ref(1)
const src = require("@/assets/sound.wav")
const listQuery = ref({ bjsj: '' })
const changeItemPoint = ref({})
const visible = ref(false)
const isPlay = ref(true)
const radio = ref('全部')
const radioList = ref(['全部', "特巡警", "交通警情", "其他"])
const radioyj = ref('全部')
const radioList1 = ref(['全部', "视觉", "融合", "在逃", '侵财'])
const colorList = ref(['全部', "红", "橙", "黄", '蓝'])
const colors = ref('全部');
const zlly=ref('01,02,03,04,05,06,07,08,09');
const audioRef = ref()
const timer = ref(null)
onMounted(() => {
// _getSelectVigilant();//警情
_getSelectInstructList();
scroll();
emitter.on("coordString", (res) => {
if (res.type === "point") {
changeItemPoint.value.jd = res.coord[0];
changeItemPoint.value.wd = res.coord[1];
proxy.$confirm("确定要修改点位吗?", "警告", { type: "warning" }).then(() => {
qcckPut(changeItemPoint.value, "/mosty-sjzx/tbJq").then((res) => {
proxy.$message({ type: "success", message: "修改成功" });
emitter.emit("removePlot", "PIOT");
emitter.emit("deletePointArea", "jq");
dataList.value = dataList.value.map(v => {
if (v.id == changeItemPoint.value.id) v = changeItemPoint.value
return v
})
});
}).catch(() => {
proxy.$message.info("已取消");
emitter.emit("deletePointArea", "jq");
emitter.emit("removePlot", "PIOT");
});
}
});
emitter.on('socketJQ', (val) => {
if (isActive.value == '警情') dataList.value.unshift(val);
// 警情推送播放
let count = 0
if (isPlay.value && val.color == '1') {
audioRef.value.play();
timer.value = setInterval(() => {
if (count < 2) audioRef.value.play();
count++
}, 0.2e3);
if (count > 2) { clearInterval(timer.value); }
}
})
})
// change播放
function changeSwitch(val) {
isPlay.value = val
if (!val) clearInterval(timer.value);
}
// 打开警情搜索
function openSearch() {
if (!visible.value) listQuery.value = { bjsj: '' }
if (isActive.value == '警情') visible.value = !visible.value;
}
// 模拟数据
function handleModel() {
qcckGet({}, '/mosty-other/lzJq/ysJq').then(res => { })
}
// 时间处理
function handelTime(val) {
listQuery.value.startTime = val ? val[0] : ''
listQuery.value.endTime = val ? val[1] : ''
}
// 搜索
function handleFilter() {
pageNum.value = 1
_getSelectVigilant();//警情
}
// 重置
function reset() {
listQuery.value = { bjsj: '' };
visible.value = false;
_getSelectVigilant();//警情
}
// 警情切换经纬度
function changePoint(val) {
changeItemPoint.value = JSON.parse(JSON.stringify(val));
}
// 切换数据
function changeDate(val) {
visible.value = false;
isActive.value = val;
pageNum.value = 1;
emitter.emit("deletePointArea", "yj");
emitter.emit("deletePointArea", "jq");
emitter.emit("deletePointArea", "zl");
emitter.emit("closeAllDialog");
dataList.value = []; //清空列表
total.value = 0; // 总数
listQuery.value = { bjsj: '' };
getList(val);
}
// 根据不同类型掉接口
function getList(val) {
switch (val) {
case "警情":
_getSelectVigilant();
break;
case "预警":
_getSelectVigilantList();
break;
case "指令":
case "指引":
case "需求":
if(val=='指令'){
zlly.value='01,02,03,04,05,06,07,08,09'
}else if(val=='需求'){
zlly.value='10'
}
_getSelectInstructList();
break;
}
}
// 警情类型
function changeDataJQ(val) {
pageNum.value = 1;
dataList.value = [];
colors.value = '全部';
_getSelectVigilant();//警情
}
// 警情颜色
function changeDataJQColor(val) {
pageNum.value = 1;
dataList.value = [];
_getSelectVigilant();//警情
}
//获取警情数据列表
function _getSelectVigilant() {
loading.value = true;
let data = { pageSize: 10, pageNum: pageNum.value, ...listQuery.value };
delete data.bjsj;
switch (radio.value) {
case '交通警情':
data.type = '01';
break;
case '特巡警':
data.type = '02';
break;
case '其他':
data.type = '03';
break;
case '重大':
data.sfzdjq = 1;
break;
case '街面':
data.sfjmjq = 1;
break;
}
switch (colors.value) {
case '红':
data.color = '1';
break;
case '橙':
data.color = '2';
break;
case '黄':
data.color = '3';
break;
case '蓝':
data.color = '4';
break;
}
getSelectVigilant(data).then((res) => {
let arr = res.records ? res.records : [];
handleDate(arr, res.total);
}).catch(() => {
loading.value = false;
});
}
// 预警类型
function changeData(val) {
pageNum.value = 1;
emitter.emit("removePlot", "PIOT");
_getSelectVigilantList()
}
//获取预警数据列表
function _getSelectVigilantList() {
loading.value = true;
let data = { pageSize: 10, pageNum: pageNum.value };
switch (radioyj.value) {
case '视觉':
data.yjlyids = '01'
break;
case '融合':
data.yjlyids = '02'
break;
case '在逃':
data.bqfl = '01'
break;
case '侵财':
data.bqfl = '02'
break;
}
getSelectVigilantList(data).then((res) => {
let arr = res.records ? res.records : [];
arr.forEach((item) => {
item.bqlist = item.yjlyBqmc ? item.yjlyBqmc.split(",") : [];
});
handleDate(arr, res.total);
}).catch(() => {
loading.value = false;
});
}
//获取指令数据列表
function _getSelectInstructList() {
loading.value = true;
let data = { pageSize: 10, pageNum: pageNum.value,zlly:zlly.value };
if (isActive.value == '指引') data.zlxflx = 3
getSelectInstructList(data).then((res) => {
let arr = res.records ? res.records : [];
handleDate(arr, res.total);
})
.catch(() => {
loading.value = false;
});
}
// 获取接口返回的数据
function handleDate(arr, all) {
loading.value = false;
dataList.value = pageNum.value == 1 ? arr : dataList.value.concat(arr);
total.value = all;
}
// 查看详情
function lookDetail(item) {
emitter.emit("closeAllDialog");
emitter.emit("closeVideo");
emitter.emit("deletePointArea", 'jq');
emitter.emit("deletePointArea", 'yj');
emitter.emit("deletePointArea", 'zl');
emitter.emit("removePlot", "PIOT");
switch (isActive.value) {
case "警情":
_setPointsAndShowModle(item, 'jq', "showAj", 0.8);
break;
case "预警":
_setPointsAndShowModle(item, 'yj', "showYjxq");
break;
case "指令":
case "需求":
case "指引":
_setPointsAndShowModle(item, "zl", "showYjzl");
break;
}
}
///显示详情及撒点
const _setPointsAndShowModle = (item, flag, modle, scale) => {
console.log(item, flag, modle, scale,'item, flag, modle, scale');
if (item.jd && item.wd) {
emitter.emit("addPoint", { coords: [item], icon: require(`@/assets/point/${flag}.png`), flag, scale });
emitter.emit("setMapCenter", { location: [item.jd, item.wd], zoomLevel: 15 });
}
emitter.emit(modle, [item]);
};
//触底加载
function scroll() {
let scrollTargetBox = jmxzScroll.value;
scrollTargetBox.onscroll = (e) => {
var scrollHeight = scrollTargetBox.scrollHeight; //251
var scrollTop = scrollTargetBox.scrollTop; //0-18
var clientHeight = scrollTargetBox.clientHeight; //233
if (scrollHeight - clientHeight == scrollTop) {
//滚动条滚到最底部
if (dataList.value.length < total.value) {
pageNum.value++;
console.log(isActive.value,'isActive.value')
getList(isActive.value); //根据不同类型掉接口
}
}
};
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.boxInfo {
.buttonBox {
display: flex;
align-items: center;
.btnsItem {
display: inline-block;
width: 110px;
height: 43px;
text-align: center;
line-height: 43px;
background: url("~@/assets/my/btn.png") no-repeat;
background-size: 110px 43px;
}
.isActiveBg {
width: 110px;
height: 43px;
background: url("~@/assets/my/btnActive.png") no-repeat;
background-size: 110px 43px;
}
}
.cntBox {
height: calc(100% - 48px);
padding-top: 10px;
box-sizing: border-box;
overflow: hidden;
overflow-y: auto;
}
.cntBox-yj {
height: calc(100% - 73px);
}
.cntBox-jq {
height: calc(100% - 100px);
}
}
::v-deep .el-loading-mask {
background: rgba(0, 0, 0, .3);
}
::v-deep .el-checkbox__label {
color: #fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label {
color: yellow;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #b2be0d;
border-color: #b2be0d;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: #b2be0d;
border-color: #b2be0d;
}
::v-deep .el-checkbox {
margin-right: 14px;
}
::v-deep .el-radio {
margin-right: 16px;
color: #fff;
}
.footBtm {
text-align: center;
}
::v-deep .el-form-item__label {
color: #fff;
}
.box-jmqk {
display: flex;
justify-content: space-between;
align-items: center;
.media {
font-size: 12px;
text-shadow: none;
}
}
.SxBox {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>

View File

@ -0,0 +1,427 @@
<!--
* @Author: your name
* @Date: 2023-11-15 15:05:40
* @LastEditTime: 2024-06-26 09:24:03
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \my_web_new\src\views\lz\home\layout\streetGroup.vue
-->
<template>
<div class="boxContent">
<div class="box-title">街面巡组</div>
<div class="searchInfo-xf">
<el-popover placement="left" width="300px" :append-to-body="false" :visible="visible" trigger="click">
<template #reference>
<Search size="20" @click="visible = !visible" />
</template>
<template #default>
<el-form :model="dataForm" :inline="true">
<el-form-item label="关键字" label-width="68px">
<el-input v-model="dataForm.keyword" placeholder="请输入关键字" clearable />
</el-form-item>
<el-form-item label="所属部门" label-width="68px">
<MOSTY.Department width="176px" placeholder="请输入所属部门" clearable v-model="dataForm.ssbmdm" />
</el-form-item>
<el-form-item label="负责人" label-width="68px">
<el-input v-model="dataForm.fzrXm" placeholder="请输入负责人" clearable />
</el-form-item>
<el-form-item label="警组" label-width="68px">
<el-input v-model="dataForm.jzMc" placeholder="请输入警组" clearable />
</el-form-item>
<div style="text-align: center;">
<el-button type="success" @click="handleFilter">查询</el-button>
<el-button type="info" @click="reset"> 重置 </el-button>
</div>
</el-form>
</template>
</el-popover>
</div>
<div class="boxInfo">
<div class="checkBox">
<CheckBox :data="checkData" @changeData="changeData"></CheckBox>
</div>
<ul class="groupList" v-loading="loading">
<li :class="item.isChecked ? 'active' : ''" v-for="item in xzList.list" :key="item.id" @click="handelClick(item)">
<div class="leftInfo">
<div class="top-cnt">
<div class="top-cnt-title">
<img :src="item.lx == '02' ? JJ : item.lx == '03' ? PCSMJ : TJ" />
<span>{{ item.jzMc ? item.jzMc : item.fzrXm + "巡组" }}</span>
</div>
<div class="text">
负责人{{ item.fzrXm }} {{ item.fzrLxdh }}
</div>
</div>
<div class="address">
<img src="@/assets/images/situationPresentation/dingwei.png" />
<span class="tools"><el-tooltip :content="item.dqwz" placement="top">{{ item.dqwz }}</el-tooltip></span>
</div>
</div>
<div class="sxt"><img src="@/assets/my/sxt.png" /></div>
<div class="xlStatus" :class="item.xfzt == 1 ? 'lineing' : item.xfzt == 2 ? 'unline' : 'line'">
{{ item.xfzt == 1 ? '处警中' : item.xfzt == 2 ? '离线' : '巡逻中' }}
</div>
</li>
<el-empty description="没有数据" :image-size="0.1" v-if="!loading && xzList.list.length <= 0" />
</ul>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import emitter from "@/utils/eventBus.js";
import CheckBox from "@/components/checkBox/index";
import { getSelectDeckList } from "@/api/dpApi/home.js";
import openWebSocket from "@/utils/webSocket.js";
import { useStore } from "vuex";
import { ref, reactive, onMounted, defineEmits, onBeforeUnmount } from "vue";
const checkData = reactive({
list: ["巡逻中", "离线"],
hasChoose: ["巡逻中", "便衣"]
});
const TJ = require(`@/assets/mapIcon/specialPolice.png`);
const JJ = require(`@/assets/mapIcon/trafficPolice.png`);
const PCSMJ = require(`@/assets/mapIcon/peoplePolice.png`);
const store = useStore();
const loading = ref(false); //警组加载
let xzList = reactive({
list: []
}); //巡组数据
const pageSize = ref(500);
const pageCurrent = ref(1);
const totalPage = ref(0);
const status = ref([0, 1, 2]); //巡组状态
const jd = ref(104.14637342);
const dataForm = ref({})
const visible = ref(false)
const isTootChange = ref(false)
let timer;
onMounted(() => {
_ggetSelectDeckList("0,1,2");// 查询巡逻中数据
getWebSocketData();//websoket
handelscroll()//滚动加载
emitter.on("showGroupPoint", val => {
isTootChange.value = true
_ggetSelectDeckList("0,1,2");// 查询巡逻中数据
})
});
onBeforeUnmount(() => {
openWebSocket.close()
emitter.off("showGroupPoint")
})
// 获取WebSocket数据
function getWebSocketData() {
let dws = openWebSocket.getInstance();
dws.connect((res) => {
// 接收发送消息
dws.ws.onmessage = (e) => {
let dataInfo = JSON.parse(e.data).data;
if (e && e.data) {
let newsDate = JSON.parse(e.data);
switch (newsDate.type) {
//一键报警
case "01":
let { jd, wd } = newsDate.data;
emitter.emit("addPointArea", { coords: [{ jd, wd }], icon: require("@/assets/point/sos.png"), flag: "sosPoint" });
emitter.emit("SsCircle", JSON.parse(e.data).data);
break;
//一键报警处置完成
case "02":
emitter.emit("clearCircle", JSON.parse(e.data).data);
let ids = document.getElementById(JSON.parse(e.data).data);
ids.parentElement.removeChild(ids);
break;
// 新增报备
case "03":
if (typeof status.value == "string") { status.value = status.value.split(","); }
status.value.forEach((item, index) => {
if (item == dataInfo.xfzt && isShowGroupPoint) {
xzList.list.unshift(JSON.parse(e.data).data);
addPointMaker([dataInfo]); //撒点
}
});
break;
//报备位置更新
case "04":
xzList.list.forEach((value, index) => {
if (value.id == dataInfo.id && isShowGroupPoint) {
delPointMaker(dataInfo); //清除原来的撒点
xzList.list.splice(index, 1);
if (dataInfo.xfzt != 2) {
xzList.list.unshift(dataInfo);
addPointMaker([dataInfo]); //撒点
}
}
});
break;
// 结束报备
case "05":
xzList.list.forEach((value, index) => {
if (value.id == dataInfo.id && isShowGroupPoint) {
delPointMaker(dataInfo); //清除原来的撒点
xzList.list.splice(index, 1);
}
});
break;
case "06": //警情
emitter.emit("socketJQ", dataInfo);
break;
}
}
};
});
}
function handleFilter() {
changeData(checkData.hasChoose)
visible.value = false
}
function reset() {
dataForm.value = {}
visible.value = false
handleFilter()
}
//选择巡防状态
function changeData(val) {
pageCurrent.value = 1;
checkData.hasChoose = val;
isTootChange.value = false;
let scrollTargetBox = document.querySelector(".groupList");
scrollTargetBox.scrollTop = 0
if (val.length == 0) {
emitter.emit("deletePointZBAll"); ////清除装备-人员
status.value = ''
xzList.list = []
} else {
let arr = []
val.forEach(item => {
if (item == '巡逻中') arr.push(0)
if (item == '离线') arr.push(2)
})
status.value = arr.join(',')
_ggetSelectDeckList(status.value);
}
}
//巡组列表
function _ggetSelectDeckList(staus) {
if (!isTootChange.value) loading.value = true;
let data = {
xfzt: staus,
pageSize: pageSize.value,
pageCurrent: pageCurrent.value,
fzrXm: dataForm.value.fzrXm,
jzMc: dataForm.value.jzMc,
ssbmdm: dataForm.value.ssbmdm,
keyword: dataForm.value.keyword,
};
getSelectDeckList(data).then((res) => {
emitter.emit("deletePointZBAll"); //清除装备-人员
loading.value = false;
let arr = res.records ? res.records : [];
xzList.list = pageCurrent.value == 1 ? arr : xzList.list.concat(arr);
let icon = require(`@/assets/mapIcon/police-car-bx.png`)
let brrSd = xzList.list.filter((v) => { return v.jd && v.wd; });
if (isShowGroupPoint) {
addPointMaker(brrSd) //撒点
emitter.emit("setMapCenter", { location: [brrSd[0].jd, brrSd[0].wd], zoomLevel: 10 });
}
}).catch(() => { loading.value = false; });
}
// 删除点位
const delPointMaker = (data) => {
emitter.emit("deletePointAreaOne", { flag: "rx", id: data.id });
};
// 撒点
const addPointMaker = (data) => {
let pramas = { coords: data, isBounds: true, showTitle: true, flag: "rx" }
emitter.emit("addPointArea", pramas);
};
//查看警组信息
function handelClick(item) {
emitter.emit("deletePointArea", "xfq");
emitter.emit("deletePointArea", "route");
emitter.emit("deletePointArea", "kfdArea");
emitter.emit("deletePointArea", "kfd");
xzList.list.forEach(v => { if (v.id != item.id) v.isChecked = false })
item.isChecked = !item.isChecked
emitter.emit("showJzInfo", item);
if (item.jd && item.wd) {
store.commit("user/setActiveId", item.id);
emitter.emit("setMapCenter", { location: [item.jd, item.wd], zoomLevel: 12 });
}
}
//触底加载
function handelscroll() {
let scrollTargetBox = document.querySelector(".groupList");
scrollTargetBox.onscroll = (e) => {
var scrollHeight = scrollTargetBox.scrollHeight; //251
var scrollTop = scrollTargetBox.scrollTop; //0-18
var clientHeight = scrollTargetBox.clientHeight; //233
if (scrollHeight - clientHeight == scrollTop) {
isTootChange.value = false;
//滚动条滚到最底部
if (totalPage.value < pageSize.value) return;
pageCurrent.value++;
_ggetSelectDeckList(status.value);
}
};
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
::v-deep .el-checkbox__label {
color: #fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label {
color: yellow;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #b2be0d;
border-color: #b2be0d;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: #b2be0d;
border-color: #b2be0d;
}
.boxContent {
position: relative;
// z-index:99;
.searchInfo-xf {
position: absolute;
top: 32px;
right: 20px;
::v-deep .icon {
width: 20px;
height: 20px;
}
::v-deep .el-popper.is-light {
background: #0a1d43;
border: 1px solid #4565a4;
}
::v-deep .el-popper.is-light .el-form-item__label {
color: #fff;
}
::v-deep .el-popper.is-light .el-popper__arrow::before {
border: 1px solid #4565a4;
background: #0a1d43;
}
}
}
ul.groupList {
height: calc(100% - 67px);
overflow-y: auto;
margin-top: 8px;
li {
position: relative;
display: flex;
margin-top: 8px;
padding-bottom: 3px;
border: 1px solid #0d5897;
box-shadow: inset 0 0 10px #0d5897;
border-radius: 2px;
&:hover {
box-shadow: inset 0px 0px 15px #0474c3;
}
.leftInfo {
flex: 1;
.top-cnt {
padding: 0 12px;
padding-top: 8px;
line-height: 22px;
padding-bottom: 6px;
.top-cnt-title {
width: 80%;
font-size: 14px;
img {
vertical-align: bottom;
margin-right: 4px;
width: 15px;
}
}
.text {
color: #00bfff;
line-height: 33px;
}
.bz {
color: #fff;
}
}
.address {
margin: 0 14px;
border-top: 1px solid #162f55;
height: 30px;
line-height: 30px;
color: #6486ae;
display: flex;
align-items: center;
img {
margin-right: 6px;
vertical-align: text-top;
}
.tools {
display: inline-block;
max-width: 270px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.sxt {
position: relative;
width: 30px;
margin-left: 10px;
img {
position: absolute;
bottom: 20px;
right: 10px;
}
}
}
li.active {
border: 1px solid #108fe7;
box-shadow: inset 0 0 10px #108fe7;
}
}
::v-deep .el-loading-mask {
background: rgba(0, 0, 0, 0.3);
}
::v-deep .el-checkbox {
margin-right: 11px;
}
</style>

View File

@ -0,0 +1,446 @@
<template>
<div
class="dialogBox"
:style="`left:${elLeft}px;top:${elTop}px`"
draggable="true"
ref="dialogBoxYpfx"
@dragstart="dragstart($event)"
@dragend="dragend($event)"
>
<div class="title">
<span class="mc">{{ props.data.jzMc ? props.data.jzMc : props.data.fzrXm + "巡组" }}</span>
<span @click="close" class="close">
<el-icon><Close /></el-icon>
</span>
</div>
<div class="info-Big-Box noScollLine">
<div class="infoBox">
<div class="xlStatus" :class="props.data.xfzt == 1 ? 'lineing' : props.data.xfzt == 2 ? 'unline': 'line'">
{{props.data.xfzt == 1? "处警中": props.data.xfzt == 2? "离线": "巡逻中"}}
</div>
<div class="text">
负责人<span class="tag mj">民警</span>
<el-tooltip :content=" '身份证号: ' + props.data.fzrSfzh + ' 警号: ' + props.data.fzrId " placement="bottom">
<span class="name">{{ props.data.fzrXm }} ({{ props.data.fzrLxdh }})</span>
</el-tooltip>
</div>
<div class="text">
开始时间<span class="name">{{ props.data.bbkssj }}</span>
</div>
<div class="time">
(计划 ( {{ props.data.kssj }} ~ {{ props.data.jssj }} )
</div>
<div class="text">
组员
<span v-for="(item, index) in props.data.pbmj" :key="index" class="jc_box">
<span class="tag mj">民警</span>
<span class="name">{{ item.jlxm }}</span>
</span>
<span v-for="(item, index) in props.data.pbfj" :key="index" class="jc_box">
<span class="tag fj">辅警</span>
<span class="name">{{ item.jlxm }}</span>
</span>
</div>
<div class="text">
单位<span class="name">{{ props.data.ssbm }}</span>
</div>
<div class="text zblist">
通讯装备
<span class="zb-item" v-for="(item, index) in props.data.txzb" :key="index">
<span class="sbinfo">{{ item.sbmc }}</span>
<el-tooltip :content="'呼叫(' + item.hh + ')'" placement="bottom">
<img style="width: 22px" src="@/assets/my/sxt.png" @click="getZFJLY(item)"/>
</el-tooltip>
</span>
<span v-if="props.data.txzb.length <= 0">暂无</span>
</div>
<div class="text zblist" v-if="props.data.jyqx.length <= 0">
警用器械<span>暂无数据</span>
</div>
<div class="text zblist" v-else>
<el-collapse v-model="props.data.openJyqx">
<el-collapse-item title="警用器械:" name="1">
<span class="zb-item" v-for="(item, index) in props.data.jyqx" :key="index">
<span class="qxinfo">{{ item.qxmc }}{{ item.qxsl }}</span>
</span>
</el-collapse-item>
</el-collapse>
</div>
<div class="text zblist">
警用车辆
<span class="zb-item" v-for="(item, index) in props.data.pbcl" :key="index">
<span class="qxinfo">{{ item.jdchphm }}</span>
</span>
<span v-if="props.data.pbcl.length <= 0">暂无</span>
</div>
<div class="text" v-if="props.data.bz != ''">
备注 <span class="name">{{ props.data.bz }}</span>
</div>
</div>
</div>
<div class="btnBox">
<button class="dp-default small" v-if="props.data.xffwlx == 1" @click="getXfqData">巡防区</button>
<button class="dp-default small" v-else-if="props.data.xffwlx == 2" @click="getKfdData">快反点</button>
<button class="dp-default small" v-else @click="getKfdData">检查站</button>
<button class="dp-default small" @click="onClickZbyj">周边预警</button>
<button class="dp-default small" @click="onClickSpsd">视频随动</button>
<el-popover placement="bottom" :visible="visible" :width="476" :append-to-body="false">
<template #reference>
<button class="dp-default small" @click="visible = !visible">轨迹回放</button>
</template>
<div class="timeBox">
<div class="time1">{{ dateRange[0] }}</div>
<el-slider
class="playtime-slider"
v-model="playTime"
id="playtimeSlider"
:range="true"
:min="sliderMIn"
:max="sliderMax"
:format-tooltip="playTimeFormat"
@change="playTimeChange"
:key="videoTndex"
>
</el-slider>
<div class="time1">{{ dateRange[1] }}</div>
</div>
<div style="text-align: center; width: 100%">
<el-button @click.stop="chooseTime">确定</el-button>
<el-button @click.stop="onClickGjhf">回放</el-button>
</div>
</el-popover>
</div>
</div>
</template>
<script setup>
import Axios from "axios";
import { spliceArray, spliceString } from "@/utils/auth.js";
import { qcckPost } from "@/api/qcckApi.js";
import { ref, onMounted, onUnmounted, defineProps, getCurrentInstance, watch } from "vue";
import { timeValidate } from "@/utils/time.js";
import emitter from "@/utils/eventBus.js";
import { getTbWzXfwzSelectTrack } from "@/api/dpApi/zzzh.js";
import { getTbJcglXfqySelectById, getTpJcglKfdSelectByid, queryListfzyc } from "@/api/dpApi/home.js";
import { getXfgj } from "@/api/yjCenter.js";
import { ElMessage } from "element-plus";
import { useRouter } from "vue-router";
import { all } from "ol/events/condition";
const { proxy } = getCurrentInstance();
const props = defineProps({
data: {
type: Object,
default: {}
}
});
const visible = ref(false);
const times = ref(null);
const router = useRouter();
const zbList = ref(); //犯罪坐标
const fzycFlag = ref(false);
const dialogBoxYpfx = ref();
const initWidth = ref(0); //父元素宽度
const initHeight = ref(0); //父元素高度
const startClientX = ref(0); //元素拖拽前距离浏览器X轴位置
const startClientY = ref(0); //元素拖拽前距离浏览器Y轴位置
const elLeft = ref(400); //元素左偏移量
const elTop = ref(120); //元素右偏移量
const dateRange = ref([]); //时间
const playTime = ref();
const sliderMIn = ref(0)
const sliderMax = ref(0)
const videoTndex = ref(1)
watch(
() => props.data,
(val) => {
visible.value = false;
let ks = val.bbkssj
let js = val.bbjssj ? val.bbjssj : timeValidate(new Date())
dateRange.value = [ks,js]
let start = new Date(ks).getTime()
let end = new Date(js).getTime()
sliderMIn.value = start
sliderMax.value = end
playTime.value = [start,end]
},{
immediate:true,
deep:true
}
);
onMounted(() => {
initBodySize();
});
onUnmounted(() => {
emitter.emit("clearLine");
});
//初始化
const initBodySize = () => {
initWidth.value = dialogBoxYpfx.value.clientWidth;
initHeight.value = dialogBoxYpfx.value.clientHeight;
};
//拖拽开始
const dragstart = (e) => {
startClientX.value = e.clientX;
startClientY.value = e.clientY;
};
//拖拽结束
const dragend = (e) => {
let x = e.clientX - startClientX.value;
let y = e.clientY - startClientY.value;
elLeft.value += x;
elTop.value += y;
};
// 执法记录仪呼叫
function getZFJLY(item) {
if (item.sfrh == "1") SPPUC.rdCard(item.hh, 6, ["60%", "40%"]);
}
//关闭弹窗
function close() {
emitter.emit("deletePointArea", "largeIcon");
visible.value = false;
emitter.emit("showJzInfo", false);
emitter.emit("deletePointArea", "xfq");
emitter.emit("deletePointArea", "route");
emitter.emit("deletePointArea", "kfdArea");
emitter.emit("deletePointArea", "kfd");
}
// 滑块提示
function playTimeFormat(val) {
let time = new Date(val)
return timeValidate(time)
}
//选中时间
function playTimeChange(val) {
let kssj = timeValidate(val[0])
let jssj = timeValidate(val[1])
dateRange.value = [kssj,jssj]
}
//获取轨迹回放数据
function _getTbWzXfwzSelectTrack() {
getTbWzXfwzSelectTrack().then((res) => {});
}
// 根据时间来画轨迹
function chooseTime() {
let params = {
bbId: props.data.id,
kssj: dateRange.value.length > 0 ? dateRange.value[0] : "",
jssj: dateRange.value.length > 0 ? dateRange.value[1] : ""
};
emitter.emit("deletePointArea", "route");
qcckPost(params, "/mosty-wzzx/tbWzXfwz/selectLswz").then((res) => {
let arr = res || [];
let points = [];
arr.forEach((item) => { points.push([item.jd, item.wd]) });
if (points.length > 0) {
emitter.emit("drawLineAnimation", {coords:points,isClear:true,flag:'route'});
} else {
proxy.$message({ type: "warning", message: `没有轨迹数据` });
}
});
}
// 巡防轨迹
function onClickGjhf() {
emitter.emit("deletePointArea", "route");
getXfgj({ bbid: props.data.id }).then((res) => {
if (res.zbList && res.zbList.length > 0) {
emitter.emit("drawLineAnimation", {coords:res.zbList,isClear:true,flag:'route'});
} else {
proxy.$message({ type: "warning", message: `没有轨迹数据` });
}
});
}
// 巡防轨迹-把数据拆分个多个-模拟动态加载
function handleAnimation(arr, subLen) {
let newAarry = [];
let index = 0;
while (index < arr.length) {
newAarry.push(arr.slice(index, (index += subLen)));
}
return newAarry;
}
//获取巡防区数据
function getXfqData() {
emitter.emit("deletePointArea", "xfq");
emitter.emit("deletePointArea", "kfd");
let ids = props.data.xffwid.split(",");
if (ids.length > 0) {
ids.forEach((el) => {
getTbJcglXfqySelectById({id: el }).then((res) => {
if (!res) return ElMessage({ message: "暂无巡防区数据", type: "warning" });
if (res.jd && res.wd) emitter.emit("setMapCenter", { location: [res.jd, res.wd], zoomLevel: 14 });
if (res.pgis.length <= 0) return;
let obj = { position:[res.pgis], text:res.xfqMc, id: res.id}
emitter.emit("echoPlane", { type:'polygon', coords: [obj], flag: "xfq",isclear: true });
});
});
} else {
ElMessage({ message: "暂无巡防区数据", type: "warning" });
}
}
// 获取范围中心的
function getCenterPoint(dm, text) {
qcckPost(dm, "/mosty-base/other/getZxd").then((res) => {
let points = [res.x, res.y];
emitter.emit("addTEXT", { points, text });
});
}
//获取快反点数据
function getKfdData() {
emitter.emit("deletePointArea", "xfq");
getTpJcglKfdSelectByid({ id: props.data.xffwid }).then((res) => {
if (res) {
console.log('点击巡防去');
//点位数据
if (!res.jd || !res.wd) return;
//一分钟范围
if (res.yfzfw.length > 0) {
let obj = { position:[res.yfzfw], text:'', id: '11'}
emitter.emit("echoPlane", { type:'polygon', coords: [obj], flag: "kfdArea", color: "rgba(255,0,0,0.6)", linecolor:'#ff0000'});
}
//三分钟范围
if (res.sfzfw.length > 0) {
let obj1 = { position:[res.sfzfw], text:'', id: '211'}
emitter.emit("echoPlane", { type:'polygon', coords: [obj1], flag: "kfdArea", color: "rgba(253,174,46,0.5)",linecolor:'#fdae2e'});
}
//五分钟范围
if (res.wfzfw.length > 0) {
let obj2 = { position:[res.wfzfw], text:'', id: '131'}
emitter.emit("echoPlane", { type:'polygon', coords: [obj2], flag: "kfdArea", color: "rgba(0,102,255,0.4)", linecolor:'#0066ff'});
}
let icon = require("@/assets/point/f.png");
emitter.emit("showPoint", { coords: [res], icon: icon, flag: "kfd" });
emitter.emit("setMapCenter", { location: [res.jd, res.wd], zoomLevel: 14 });
} else {
ElMessage({ message: "暂无快反点数据", type: "warning" });
}
});
}
//点击视频随动
function onClickSpsd() {
emitter.emit("closeVideo");
let { jd, wd } = props.data;
emitter.emit("clickSpsd", { jd, wd });
}
//点击周边预警
function onClickZbyj() {
emitter.emit("closeVideo");
let { jd, wd } = props.data;
emitter.emit("clickZbyj", { jd, wd });
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/largeScreen.scss";
@import "@/assets/css/homeScreen.scss";
.dialogBox {
position: absolute;
padding: 0;
width: 484px !important;
.title {
border-bottom: 1px solid #275288;
margin-bottom: 6px;
.mc {
margin-left: 10px;
}
}
.info-Big-Box {
max-height: 70vh;
overflow: hidden;
overflow: auto;
padding: 4px 10px;
box-sizing: border-box;
}
.infoBox {
position: relative;
padding: 10px !important;
.text {
color: #00bfff;
line-height: 26px;
}
.tag {
margin: 0 4px;
}
.name {
color: #fff;
}
.time {
color: #3ad2d4;
}
.jc_box {
margin: 0 4px;
}
.zblist {
display: flex;
flex-wrap: wrap;
.zb-item {
margin-right: 10px;
.sbinfo {
color: yellow;
}
img {
margin-left: 4px;
cursor: pointer;
}
.qxinfo {
color: rgb(127, 177, 217);
padding: 2px 4px;
border: 1px solid rgb(61, 116, 219);
border-radius: 4px;
display: inline;
white-space: nowrap;
}
}
}
}
}
.all-dialog .dialogBox > .btnBox {
padding-top: 0;
padding-bottom: 0;
}
.timeBox{
width: 100%;
display: flex;
align-items: center;
.time1{
margin: 0 10px;
text-align: center;
color: #fff;
}
}
::v-deep .el-collapse{
width: 100%;
--el-collapse-header-height:auto;
--el-collapse-header-bg-color:transparent;
--el-collapse-border-color:transparent;
}
::v-deep .el-collapse-item__header{
color: #00bfff;
}
::v-deep .el-collapse-item__wrap{
background-color:transparent;
}
::v-deep .el-collapse-item__content {
color: #fff;
}
.null{
text-align: center;
}
::v-deep .el-popper.is-light{
transform: translate(5px, 336px) !important;
}
</style>

View File

@ -0,0 +1,172 @@
<!--
* @Author: your name
* @Date: 2023-11-15 11:21:20
* @LastEditTime: 2024-02-19 11:17:14
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \my_web_new\src\views\lz\home\components\workCondition.vue
-->
<template>
<div class="boxContent">
<div class="box-title">工作情况</div>
<ul class="boxInfo cntinfo">
<!-- <li class="item">
<div class="bt">在岗警力</div>
<span class="label" @click="show_Dialog('zgjl','mj')"><span class="xbt">民警</span><span :title="jl.zgmjsl || 0" class="num-one">{{ jl.zgmjsl || 0 }}</span></span>
<span class="label" @click="show_Dialog('zgjl','fj')"><span class="xbt">辅警</span><span :title="jl.zgfjsl || 0" class="num-two">{{ jl.zgfjsl || 0 }}</span></span>
</li> -->
<li class="item">
<div class="bt">街面巡组</div>
<span class="label" @click="show_Dialog('jmxz', 'jh')"><span class="xbt">计划</span><span :title="xz.jhsl || 0"
class="num-one">{{ xz.jhsl || 0 }}</span></span>
<span class="label" @click="show_Dialog('jmxz', 'sj')"><span class="xbt">实际</span><span :title="xz.sjsl || 0"
class="num-two">{{ xz.sjsl || 0 }}</span></span>
</li>
<li class="item">
<div class="bt">街面力量</div>
<span class="label" @click="show_Dialog('jmll', 'mj')"><span class="xbt">民警</span><span :title="xz.jmmjsl || 0"
class="num-one">{{ xz.jmmjsl || 0 }}</span></span>
<span class="label" @click="show_Dialog('jmll', 'fj')"><span class="xbt">辅警</span><span :title="xz.jmfjsl || 0"
class="num-two">{{ xz.jmfjsl || 0 }}</span></span>
</li>
<!-- <li class="item">
<div class="bt">当日巡逻</div>
<span class="label" @click="show_Dialog('xlsc', 'xs')"><span class="xbt">时长(h)</span><span :title="xz.xfsc || 0"
class="num-one">{{ xz.xfsc || 0 }}</span></span>
<span class="label" @click="show_Dialog('xlsc', 'lc')"><span class="xbt">里程(km)</span><span :title="xz.xflc || 0"
class="num-two">{{ xz.xflc || 0 }}</span></span>
</li>
<li class="item">
<div class="bt">任务情况</div>
<span class="label" @click="show_Dialog('zlzx', 'zs')"><span class="xbt">总数</span><span class="num-one">{{
zlzx.zlzs || 0 }}</span></span>
<span class="label" @click="show_Dialog('zlzx', 'zx')"><span class="xbt">执行</span><span class="num-two">{{
zlzx.zlzxs || 0 }}</span></span>
</li> -->
</ul>
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import { getZgjlData, getSelectDeck, getSelectCarCount, getSelectInstructCount } from "@/api/dpApi/home.js";
import { ref, onMounted } from "vue";
const jl = ref({}); //左上方统计数据 警力
const xz = ref({}); //左上方统计数据 巡组
const pc = ref(0); //左上方统计数据 盘车
const pr = ref(0); //左上方统计数据 盘人
const zlzx = ref({}); //左上方统计数据 指令执行状况
onMounted(() => {
_getZgjlData();
_getSelectDeck();
});
// 在岗警力
function _getZgjlData() {
getZgjlData().then((res) => {
jl.value = res;
});
}
// 街面巡组 | 巡逻时长里程 |街面力量
function _getSelectDeck() {
getSelectDeck().then((res) => {
if (res.xfsc != 0) res.xfsc = (res.xfsc / 3600).toFixed(2);
if (res.xflc != 0) res.xflc = (res.xflc / 1000).toFixed(2);
xz.value = res;
});
}
// 展示弹窗
function show_Dialog(val, type) {
switch (val) {
case 'zgjl':
emitter.emit("showJLWindow", type); //展示在岗警力的弹框
break;
case 'jmxz':
emitter.emit("showJMXZWindow", type); //展示在巡组的弹框
break;
case 'jmll':
emitter.emit("showJMLLWindow", type); //展示街面力量的弹框
break;
case 'xlsc':
emitter.emit("showXLSCWindow", type); //巡逻时长的弹框
break;
case 'pcgz':
emitter.emit("showPCGZWindow", type); //展示盘查工作的弹框
break;
case 'zlzx':
emitter.emit("showZlzxWindow", type); //点击打开指令弹窗
break;
}
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.cntinfo {
display: flex;
flex-direction: column;
justify-content: space-between;
.item {
display: flex;
align-items: center;
padding: 0 6px;
box-sizing: border-box;
flex: 1;
line-height: 35px;
font-size: 14px;
>span {
flex: 1;
}
.bt {
color: #01E9ED;
display: inline-block;
width: 80px;
font-size: 16px;
font-weight: 700;
}
.xbt {
display: inline-block;
width: 70px;
cursor: pointer;
}
.num-one {
color: #00BFFF;
font-size: 16px;
cursor: pointer;
}
.num-two {
color: #01E9ED;
font-size: 16px;
cursor: pointer;
}
.label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.label:nth-child(1) .xbt {
width: 60px;
}
}
.item:nth-child(2n+1) {
background-image: linear-gradient(to right, rgba(1, 127, 216, 1), rgba(4, 56, 131, .5), rgba(1, 130, 218, .0));
}
}
</style>