更新页面

This commit is contained in:
2025-09-20 17:29:35 +08:00
parent 9f503c7069
commit c565736d49
26 changed files with 1398 additions and 106 deletions

View File

@ -1,156 +0,0 @@
<template>
<div ref="echart" class="echartDiv"></div>
</template>
<script setup>
import { choseRbgb } from '@/utils/tools'
import * as echarts from "echarts";
import { defineExpose, onMounted, ref } from "vue";
let vehicleChart = null
const echart = ref()
onMounted(() => {
window.addEventListener('resize', handleResize)
});
const initCharts = (data) => {
vehicleChart = echarts.init(echart.value)
const colors =['#ff1818', '#0066ff', '#ff9900', '#00cc66']
const countData = [
{
value: 0,
name: '红色预警',
colorType: 'red',
color: ['#ff1818', '#ff6c6c'],
color1: [choseRbgb('#ff1818', 0.3), choseRbgb('#ff6c6c', 0.3)]
},
{
value: 0,
name: '橙色预警',
colorType: 'orange',
color: ['#ff9900', '#cc7a00'],
color1: [choseRbgb('#ff9900', 0.3), choseRbgb('#cc7a00', 0.3)]
},
{
value: 0,
name: '黄色预警',
colorType: 'yellow',
color: ['#ece403', '#f6f064'],
color1: [choseRbgb('#ece403', 0.3), choseRbgb('#f6f064', 0.3)]
},
{
value: 0,
name: '蓝色预警',
colorType: 'blue',
color: ['#0066ff', '#0044cc'],
color1: [choseRbgb('#0066ff', 0.3), choseRbgb('#0044cc', 0.3)]
},
];
data.forEach(item => {
if(item.yj_jb == '10') countData[0].value = item.count;
if(item.yj_jb == '20') countData[1].value = item.count;
if(item.yj_jb == '30') countData[2].value = item.count;
if(item.yj_jb == '40') countData[3].value = item.count;
});
vehicleChart.setOption(createChartOption(countData, colors))
}
const createChartOption = (data, colors) => {
let total = data.reduce((sum, item) => sum + item.value, 0)
return {
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: '60%',
top: 'center',
textStyle: {
color: '#fff',
rich: {
value: {
color: '#fff'
},
percentage: {
padding: [0, 0, 0, 10]
},
red: {
color: colors[0]
},
orange: {
color: colors[2]
},
yellow: {
color: colors[3]
},
blue: {
color: colors[1]
},
}
},
formatter: (name) => {
const item = data.find(d => d.name === name);
let percentage = ((item.value / total) * 100).toFixed(2);
return `${name} ${item.value} {${item.colorType}|(${percentage}%)}`
}
},
series: [
{
type: 'pie',
radius: ['55%', '70%'],
center: ['28%', '50%'],
data: data.map(item => ({
...item,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: item.color[0] },
{ offset: 1, color: item.color[1] }
])
}
})),
label: {
show: false
},
emphasis: {
scale: false,
focus: 'none'
},
z: 2
},
{
type: 'pie',
radius: ['65%', '85%'],
center: ['28%', '50%'],
data: data.map(item => ({
...item,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: item.color1[0] },
{ offset: 1, color: item.color1[1] }
])
}
})),
label: {
show: false
},
emphasis: {
scale: false,
focus: 'none'
},
z: 1,
silent: true
}
]
}
}
const handleResize = () => {
vehicleChart?.resize()
}
defineExpose({initCharts})
</script>
<style lang='scss' scoped>
.echartDiv {
width: 100%;
height: 100%;
}
</style>

View File

@ -1,66 +0,0 @@
<template>
<div class="count-container">
<div class="count-item">
<div class="count-title">布控总数</div>
<div class="count-number"><Statis :count="dataform.bkzs" :len="7" /></div>
</div>
<div class="count-item">
<div class="count-title">已处置数</div>
<div class="count-number"><Statis :count="dataform.czs" :len="7" /></div>
</div>
</div>
</template>
<script setup>
import Statis from "@/components/statis.vue";
import { reactive } from "vue";
const dataform = reactive({
bkzs: 287,
czs: 123
});
</script>
<style scoped lang="scss">
.count-container {
display: flex;
padding: 10px 5px;
background: rgba(0, 29, 75, 0.4);
gap: 4px;
}
.count-item {
flex: 1;
display: flex;
align-items: center;
border-radius: 4px;
padding: 6px;
background: url("~@/assets/images/bg12.png") no-repeat center center;
background-size: 100% 100%;
}
.count-title {
color: #fff;
font-size: 14px;
text-align: center;
margin-right: 4px;
background: url("~@/assets/images/bg13.png") no-repeat center center;
background-size: 100% 100%;
}
.count-number {
font-family: "Digital-7", monospace;
font-size: 32px;
background: #1e3799;
color: #00ffff;
padding: 8px;
border-radius: 4px;
text-align: center;
letter-spacing: 2px;
width: 150px;
height: 33px;
background: url("~@/assets/images/statis.png") no-repeat center center;
background-size: 100% 100%;
padding: 0 10px;
box-sizing: border-box;
}
</style>

View File

@ -1,142 +0,0 @@
<template>
<el-dialog v-model="showDialog" :append-to-body="true" :destroy-on-close="true" :title="title" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :disabled="title == '反馈' ? false : true" :formList="formData" labelWidth="160px" ref="elform" :rules="rules">
<template #mbzrmjxm>
<MOSTY.Other width="100%" @click="handleChoose('mbzrmjxm')" clearable v-model="listQuery.mbzrmjxm" placeholder="请选择民警" :readonly="true" />
</template>
<template #czzrmj>
<MOSTY.Other width="100%" @click="handleChoose('czzrmj')" clearable v-model="listQuery.czzrmj" placeholder="请选择民警" :readonly="true" />
</template>
</FormMessage>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="loading" v-if="title == '反馈'">确认</el-button>
</div>
</template>
</el-dialog>
<ChooseUser v-model="chooseUserVisible" v-if="chooseUserVisible" @choosedUsers="handleUserSelected" :roleIds="roleIds" :Single="true" />
</template>
<script setup>
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue"
import * as MOSTY from "@/components/MyComponents/index";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import emitter from "@/utils/eventBus.js";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { onMounted, reactive, ref ,getCurrentInstance} from 'vue';
const emit = defineEmits(['change'])
const { proxy } = getCurrentInstance();
const { D_BZ_SF ,D_YJXX_CZCSLX,D_YJXX_CZSSXZ,D_YJXX_CKCZJG,D_YJXX_CKZYLX } = proxy.$dict('D_YJXX_CKZYLX','D_BZ_SF','D_YJXX_CZCSLX','D_YJXX_CZSSXZ','D_YJXX_CKCZJG')
const chooseUserVisible = ref(false)
const roleIds = ref([])
const elform = ref()
const showDialog = ref(false)
const loading = ref(false)
const choosetype = ref('')
const listQuery = ref({})
const formData = ref([
{ label: "发现目标状态", prop: "mbzt", type: "select",options: D_BZ_SF },
{ label: "发现目标责任单位", prop: "mbzrdwdm", type: "department" ,depMc:'mbzrdw'},
{ label: "发现目标责任民警", prop: "mbzrmjxm", type: "slot"},
{ label: "是否本人", prop: "sfbr", type: "select",options: D_BZ_SF },
{ label: "处置时间", prop: "czsj", type: "datetime" },
{ label: "处置地址", prop: "czdz", type: "textarea",width:'100%'},
{ label: "详细地址", prop: "xxdz", type: "textarea",width:'100%' },
{ label: "处置责任单位", prop: "czzrdwdm", type: "department",depMc:'czzrdw' },
{ label: "处置责任民警", prop: "czzrmj", type: "slot" },
{ label: "常控处置措施类型", prop: "ckczcslx", type: "select" ,options: D_YJXX_CZCSLX},
{ label: "常控处置措施细类", prop: "ckczcsxl", type: "select",options: D_YJXX_CZSSXZ},
{ label: "常控处置结果", prop: "ckczjg", type: "select",options: D_YJXX_CKCZJG },
{ label: "常控立线侦察评估", prop: "cklxzcpg", type: "input" },
{ label: "常控立线侦察依据", prop: "cklxzcpgyj", type: "input" },
{ label: "常控从事职业类型", prop: "ckzylx", type: "select",options: D_YJXX_CKZYLX },
{ label: "是否尿检", prop: "sfnj", type: "radio",options: D_BZ_SF },
{ label: "常控不尿检理由", prop: "ckbnjly", type: "textarea",width:'100%' },
{ label: "常控处置反馈补充信息", prop: "ckczbcxx", type: "textarea",width:'100%' },
])
const rules = reactive({
mbzt: [{ required: true, message: "请选择发现目标状态", trigger: "change" }],
fxmbzedw: [{ required: true, message: "请选择发现目标责任单位", trigger: "change" }],
mbzrmjxm: [{ required: true, message: "请选择发现目标责任民警", trigger: "change" }],
sfbr:[{ required: true, message: "请选择是否本人", trigger: "change" }],
czsj:[{ required: true, message: "请选择处置时间", trigger: "change" }],
czdz:[{ required: true, message: "请选择处置地址", trigger: "blur" }],
xxdz:[{ required: true, message: "请选择详细地址", trigger: "blur" }],
czzrdwdm:[{ required: true, message: "请选择处置责任单位", trigger: "change" }],
czzrmj:[{ required: true, message: "请选择处置责任民警", trigger: "change" }],
ckczcslx:[{ required: true, message: "请选择常控处置措施类型", trigger: "change" }],
ckczcsxl:[{ required: true, message: "请选择常控处置措施细类", trigger: "change" }],
ckczjg:[{ required: true, message: "请输入常控处置结果", trigger: "blur" }],
cklxzcpg:[{ required: true, message: "请输入常控立线侦察评估", trigger: "blur" }],
cklxzcpgyj:[{ required: true, message: "请输入常控立线侦察依据", trigger: "blur" }],
ckzylx:[{ required: true, message: "请选择常控从事职业类型", trigger: "change" }],
sfnj:[{ required: true, message: "请选择是否尿检", trigger: "change" }],
})
const title = ref('')
onMounted(() => {
emitter.on("openFkDialog", (val) => {
showDialog.value = true;
listQuery.value = {yjid:val.id}
title.value = val.type;
if(val.type == '查看反馈'){
qcckGet({}, "/mosty-gsxt/tbYjxx/getInfo/"+val.id).then((res) => {
let list = res.fkList || []
listQuery.value = list.length > 0 ? list[0] : {};
});
}
})
})
const handleChoose = (type)=>{
chooseUserVisible.value = true,
choosetype.value = type;
}
// 选取角色
const handleUserSelected = (val) => {
switch(choosetype.value){
case 'mbzrmjxm':
listQuery.value.mbzrmjxm = val[0].userName
listQuery.value.mbzrmjsfzh = val[0].inDustRialId
break;
case 'czzrmj':
listQuery.value.czzrmj = val[0].userName
listQuery.value.czzrmjsfzh = val[0].inDustRialId
break;
}
}
const submitForm = () =>{
elform.value.submit((val)=>{
loading.value = true;
qcckPost(val, "/mosty-gsxt/tbYjxx/yjfk").then(() => {
loading.value = false;
proxy.$message({ type: "success", message: "反馈成功" });
emit('change')
close()
}).catch(() => {
loading.value = false;
})
})
}
const close = () => {
elform.value.reset();
listQuery.value = {}
showDialog.value = false;
}
</script>
<style lang="scss" scoped>
.el-form{
max-height: 60vh;
overflow: hidden;
overflow-y: auto;
}
</style>

View File

@ -1,328 +0,0 @@
<template>
<div class="historical-route-container" v-if="modelValue">
<!-- 头部标题 -->
<div class="header flex align-center just-between">
<span>轨迹历史</span>
<el-icon size="20px" @click="close" class="close-icon">
<Close />
</el-icon>
</div>
<!-- 筛选区域 -->
<div class="filter-section">
<div class="flex align-center just-between">
<el-date-picker class="date-picker" v-model="dateRange" type="datetimerange" range-separator="至"
start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" />
<el-button type="primary" size="small" @click="search" class="search-btn">
查询
</el-button>
</div>
</div>
<!-- 轨迹列表区域 -->
<div class="track-list-container">
<div v-for="(item, index) in trackList" :key="index" class="track-item">
<div class="track-location">{{ item.yjNr }}</div>
</div>
<!-- 空状态 -->
<MOSTY.Empty :show="trackList.length <= 0" :imgSize="150"></MOSTY.Empty>
</div>
<!-- 底部按钮 -->
<div class="bottom-section">
<el-button type="primary" size="small" @click="showOnMap" class="show-map-btn">
轨迹上图
</el-button>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import { tbYjxxGsgj } from '@/api/yj.js'
import { ref, defineProps, onMounted, watch } from "vue";
import emitter from "@/utils/eventBus.js";
import { ElMessage } from "element-plus";
import { Close } from '@element-plus/icons-vue';
// 参数传递
const props = defineProps({
// 某条预警详情
data: {
type: Array,
default: () => []
},
modelValue: {
type: Boolean,
default: false
},
});
const emit = defineEmits(["update:modelValue"]);
// 日期范围
const dateRange = ref([null, null]);
// 轨迹列表数据
const trackList = ref([]);
// 关闭窗口
function close() {
dateRange.value = [null, null];
emit("update:modelValue", false);
}
// 查询轨迹数据
function search() {
mockTrackData();
}
const mapData = ref([])
// 轨迹上图
function showOnMap() {
if (trackList.value.length === 0) {
ElMessage({ message: '暂无轨迹数据', type: 'warning' });
return;
}
for (let i = 0; i < 2; i++) {
let coords = mapData.value[i].list.map(item => {
return [item.jd, item.wd]
})
// const coords =[ [
// [
// 94.354613,
// 22.658568
// ],
// [
// 94.354613,
// 23.658568
// ],
// [
// 94.354613,
// 24.658568
// ],
// [
// 94.354613,
// 25.658568
// ],
// [
// 94.354613,
// 26.658568
// ],
// [
// 94.354613,
// 27.658568
// ],
// [
// 94.354613,
// 28.658568
// ],
// [
// 94.354613,
// 29.658568
// ]
// ],[
// [
// 89.354613,
// 22.658568
// ],
// [
// 90.354613,
// 23.658568
// ],
// [
// 91.354613,
// 24.658568
// ],
// [
// 92.354613,
// 25.658568
// ],
// [
// 93.354613,
// 26.658568
// ],
// [
// 94.354613,
// 27.658568
// ],
// [
// 95.354613,
// 28.658568
// ],
// [
// 96.354613,
// 29.658568
// ]
// ]]
emitter.emit('drawLineAnimation', {
type: "solid",
coords: coords,
isclear: true,
flag: "yjLine"
})
}
// const coords = mapData.value.map(item => {
// console.log(item);
// return item.list.map(items => {
// return [items.jd, items.wd]
// })
// })
// emitter.emit('drawLineAnimation',
// {
// type: "solid",
// coords: coords,
// isclear: true,
// flag: "yjLine"
// }
// // { coords: coords, flag: 'yjLine' }
// );
}
// mapUtil.value.createLine(res, res.flag);
// 模拟轨迹数据
function mockTrackData() {
const promes = {
yjRysfzh: props.data.yjRysfzh,
startTime: dateRange.value[0] ? dateRange.value[0] : null,
endTime: dateRange.value[1] ? dateRange.value[1] : null,
}
tbYjxxGsgj(promes).then(res => {
mapData.value = res
trackList.value = []
for (let i = 0; i < res.length; i++) {
trackList.value = [...trackList.value, ...res[i].list]
}
});
}
watch(() => props.data, (newVal) => {
if (newVal.length > 0) {
mockTrackData();
}
})
// 组件挂载时获取默认数据
// onMounted(() => {
// mockTrackData();
// });
// 监听modelValue变化
watch(() => props.modelValue, (newVal) => {
if (newVal) {
mockTrackData();
}
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
// 容器样式
.historical-route-container {
position: absolute;
top: 80%;
left: 100%;
z-index: 2;
width: 300px;
height: 400px;
}
// 头部样式
.header {
width: 100%;
background: #1d5db4e3;
padding: 8px 5px;
}
// 关闭图标样式
.close-icon {
cursor: pointer;
}
// 筛选区域样式
.filter-section {
background: rgba(10, 49, 88, 0.6);
padding: 10px;
}
// 日期选择器样式
.date-picker {
width: 80%;
}
// 查询按钮样式
.search-btn {
font-size: 12px;
background: #1890ff;
border-color: #1890ff;
}
// 轨迹列表区域样式
.track-list-container {
background: rgba(10, 49, 88, 0.6);
box-shadow: inset 0px 0px 10px 0px rgba(56, 119, 242, 0.5);
height: 280px;
overflow-y: auto;
}
// 列表项样式
.track-item {
border-bottom: 1px solid rgba(56, 119, 242, 0.3);
padding: 8px;
}
// 轨迹时间样式
.track-time {
color: #b7e4ff;
font-size: 12px;
line-height: 1.5;
}
// 轨迹位置样式
.track-location {
color: white;
font-size: 12px;
line-height: 1.5;
}
// 空状态样式
.empty-state {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #b7e4ff;
font-size: 12px;
}
// 底部按钮区域样式
.bottom-section {
background: rgba(10, 49, 88, 0.6);
padding: 10px;
}
// 轨迹上图按钮样式
.show-map-btn {
width: 100%;
font-size: 12px;
background: #1890ff;
border-color: #1890ff;
}
// 自定义滚动条样式
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: rgba(56, 119, 242, 0.1);
}
::-webkit-scrollbar-thumb {
background: rgba(56, 119, 242, 0.5);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(56, 119, 242, 0.8);
}
::v-deep .el-range-input {
color: #000 !important;
}
</style>

View File

@ -1,122 +0,0 @@
<template>
<FormMessage v-model="listQuery" :formList="formData" labelWidth="100px" ref="elform" :rules="rules">
<template #zrSsbmdm>
<MOSTY.Department filterable v-model="listQuery.receivingUnitCode" width="100%" @getDepValue="getDepValue"
clearable placeholder="请选择所属部门" :multiple="true" />
</template>
<template #ry>
<el-input readonly v-model="ryStr" @click="chooseUserVisible = true" placeholder="请选择民警"></el-input>
</template>
</FormMessage>
<ChooseUser v-model="chooseUserVisible" @choosedUsers="handleUserSelected" :roleIds="roleIds" :Single="false" />
</template>
<script setup>
import { reactive, ref, onMounted, watch } from "vue";
import { sendFqzl } from '@/api/commit'
import { getItem } from '@/utils/storage'
import * as MOSTY from "@/components/MyComponents/index";
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue"
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { ElMessage } from "element-plus";
const props = defineProps({
itemData: {
type: Object,
default: () => { }
}
})
const emit = defineEmits(['handleClose'])
// 表单数据
const listQuery = ref({}); //表单
// 选择人员
const ryStr = ref('')
const elform = ref()
const personnelEntity = ref()
const formData = ref([
{ label: "标题", prop: "title", type: "input", width: "40%" },
{ label: "接收单位", prop: "zrSsbmdm", type: "slot", width: "40%" },
{ label: "指令状态", prop: "status", type: "input", width: "40%" },
{ label: "人员选择", prop: "ry", type: "slot", width: "40%" },
{ label: "附件", prop: "attachmentPath", type: "upload" },
{ label: "指令内容", prop: "instructionContent", type: "textarea", width: "100%" },
])
const rules = reactive({
title: [{ required: true, message: "请输入指令标题", trigger: "blur" }],
zrSsbmdm: [{ required: true, message: "请选择接收单位", trigger: "blur" }],
instructionContent: [{ required: true, message: "请输入指令内容", trigger: "blur" }],
ry: [{ required: true, message: "请选择人员", trigger: "blur" }]
});
const deptId = getItem('deptId')
const getsendFqzl = () => {
elform.value.submit((val)=>{
elform.value.validate().then(res => {
if (res) {
const data = { ...listQuery.value }
delete data.ry
const promes = {
instructionsEntity: {
unitCode: deptId[0].deptCode,
unitName: deptId[0].deptName,
...data,
receivingUnitCode: listQuery.value.receivingUnitCode.toString(),
receivingUnit: listQuery.value.receivingUnit.toString(),
attachmentPath: JSON.stringify(listQuery.value.attachmentPath)
}, id: props.itemData.id,
personnelEntity: personnelEntity.value
}
sendFqzl(promes).then((result) => {
const res = JSON.parse(result)
if (res.code == 200) {
ElMessage.success('发送成功')
emit('handleClose')
} else {
ElMessage.error(res.msg)
}
}).catch((err) => {
console.log(err);
});
}
})
})
}
const itemData=ref(props.itemData)
watch(() =>itemData.value, (val) => {
listQuery.value.title = val.yjBt
listQuery.value.instructionContent = val.yjNr
}, { deep: true, immediate: true })
const chooseUserVisible = ref(false)
const roleIds = ref([])
// 选取角色
const handleUserSelected = (val) => {
personnelEntity.value = val.map((item, index) => {
return {
name: item.userName,
idNumber: item.idEntityCard,
phoneNumber: item.mobile,
personTypeId: "",
personTypeName: "",
domicilePlace: "",
orderId: index + 1
}
})
ryStr.value = personnelEntity.value.map(item => item.name)
}
// 选取部门
const getDepValue = (e) => {
listQuery.value.receivingUnit = e.map(item => item.orgName)
}
defineExpose({
getsendFqzl
})
</script>
<style scoped lang="scss"></style>

View File

@ -1,326 +0,0 @@
<template>
<div class="personCard relative mb10 pointer">
<div class="flex nowrap align-center just-between boderBox">
<div class="avatarBox relative">
<div class="marks f12 absolute" :class="changeBg(props.item.yjJb)">
<span>{{ changetText(props.item.yjJb) }}</span>
</div>
<div>
<el-image :preview-teleported="true" style="width: 80px; height: 110px" :src="props.item.yjTp"
:preview-src-list="[props.item.yjTp]" />
</div>
<div>
<span class="smallbtn" @click.stop="() => { }">全息档案{{ props.item.id }}</span>
</div>
</div>
<div class="infoBox">
<div style="height: 110px">
<div class="flex nowrap align-center just-between linItem">
<div class="wichAlian3">{{ props.item.yjRyxm }}</div>
<div>|</div>
<div class="wichAlian">{{ IdCard(props.item.yjRysfzh, 2) }}</div>
<div>|</div>
<div class="wichAlian2"> {{ IdCard(props.item.yjRysfzh, 3) }}</div>
<div>|</div>
<div class="wichAlian3"> <span class="bqbox ml6">{{ props.item.yjbq }}</span></div>
</div>
<div class="linItem">身份证号{{ props.item.yjRysfzh }}</div>
<div class="linItem">预警时间{{ props.item.yjSj }}</div>
<div class="linItem flex nowrap align-center just-between">预警次数{{ props.item.yjCs }}<div></div>
<div>相似度90%</div>
</div>
</div>
<div class="infoItem flex nowrap" style="margin-top: 6px;">
<span class="smllbtn" @click.stop="handleQsFk(props.item, '签收')"
v-if="props.item.yjJb != 10 && props.item.czzt == '01' && deptLevel == '40'">签收</span>
<span class="smllbtn" @click.stop="handleQsFk(props.item, '反馈')"
v-if="props.item.yjJb != 10 && props.item.czzt == '02' && deptLevel == '40'"> 反馈 </span>
<span class="smllbtn" @click.stop="handleQsFk(props.item, '查看反馈')"
v-if="props.item.yjJb != 10 && props.item.czzt == '03'"> 查看反馈 </span>
<div>
<span class="smllbtn" v-if="track" @click.stop="showDetail(props.item)">发送指令</span>
<span class="smllbtn" v-else @click.stop="openTrack(props.item)">历史轨迹</span>
</div>
</div>
<!-- <div class="items">
<div class="infoItem flex nowrap mb10">{{ props.item.yjRyxm }} <span class="bqbox ml6">{{ props.item.yjbq }}</span></div>
<div class="infoItem ellipsis">性别<span class="value">{{ IdCard(props.item.yjRysfzh , 2 )}}</span></div>
<div class="infoItem ellipsis">身份证号<span class="value">{{ props.item.yjRysfzh }}</span></div>
<div class="infoItem ellipsis">出生日期<span class="value">{{ IdCard(props.item.yjRysfzh , 1 )}}</span></div>
<div class="infoItem ellipsis">相似度<span class="value">{{ props.item.xsd * 100 }}%</span></div>
<div class="infoItem ellipsis">预警次数<span class="value"><span class="num">{{ props.item.yjCs }}</span> </span></div>
<div class="infoItem flex nowrap">
<span class="smllbtn" @click.stop="handleQsFk(props.item,'签收')" v-if="props.item.yjJb != 10 && props.item.czzt == '01' && deptLevel=='40' ">签收</span>
<span class="smllbtn" @click.stop="handleQsFk(props.item,'反馈')" v-if="props.item.yjJb != 10 && props.item.czzt == '02' && deptLevel=='40'"> 反馈 </span>
<span class="smllbtn" @click.stop="handleQsFk(props.item,'查看反馈')" v-if="props.item.yjJb != 10 && props.item.czzt == '03'"> 查看反馈 </span>
</div>
</div>
<div class="items">
<div class="infoItem ellipsis">预警级别<span class="value">{{ props.item.yjJb }}</span></div>
<div class="infoItem ellipsis">预警标题:<span class="value">{{ props.item.yjBt }}</span></div>
<div class="infoItem ellipsis">预警内容<span class="value">{{ props.item.yjNr }}</span></div>
<div class="infoItem ellipsis">预警地址<span class="value">{{ props.item.yjDz }}</span></div>
<div class="infoItem ellipsis">预警时间<span class="value">{{ props.item.yjSj }}</span></div>
<div class="infoItem ellipsis">签收时间<span class="value">{{ props.item.qssj }}</span></div>
<div class="infoItem ellipsis">反馈时间<span class="value">{{ props.item.fksj }}</span></div>
</div> -->
</div>
</div>
<div class="infoItem ellipsis flex align-center">
<img src="@/assets/images/ddtb.png" />
<span class="value">{{ props.item.yjDz }}</span>
</div>
</div>
<HistoricalRoute v-model="showTrack" :data="props.item" />
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { IdCard } from '@/utils/validate.js'
import HistoricalRoute from './historicalRoute.vue'
import { defineProps, ref, reactive, getCurrentInstance, onMounted, watch } from "vue";
const { proxy } = getCurrentInstance();
const props = defineProps({
item: {
type: Object,
default: () => ({})
},
dic: {
type: Object,
default: () => ({})
},
type: {
type: String,
default: ""
}, track: {
type: Boolean,
default: true
}
});
watch(() => props.item, (newVal) => {
if (newVal) {
console.log(newVal);
}
},{deep:true})
const deptLevel = ref(null)
const emit = defineEmits(['showDetail'])
const showDetail = (val) => {
emit('showDetail', val)
}
// 处理签收
const handleQsFk = (val, type) => {
switch (type) {
case '签收':
proxy.$confirm("是否确定要签收?", "警告", { type: "warning" }).then(() => {
qcckPost({ id: val.id }, "/mosty-gsxt/tbYjxx/yjqs").then(() => {
val.czzt = '02'
proxy.$message({ type: "success", message: "签收成功" });
});
})
break;
case '反馈':
case '查看反馈':
emitter.emit("openFkDialog", { id: val.id, type });
break;
}
}
// 切换背景
const changeBg = (type) => {
switch (type) {
case "10":
return "marks_red";
case "20":
return "marks_orange";
case "30":
return "marks_yellow";
case "40":
return "marks_blue";
default:
return "marks_blue";
}
};
const changetText = (type) => {
switch (type) {
case "10":
return "处置";
case "20":
return "关注";
case "30":
return "提醒";
case "40":
return "不关注";
default:
return "不关注";
}
};
const showTrack=ref(false)
const openTrack = () => {
showTrack.value=true
};
// <!-- 虚拟触发 -->
// <!-- <el-popover ref="popoverRef" :visible="isShowVisble" :width="400" :virtual-ref="buttonRef" trigger="click" title="反馈" virtual-triggering >
// <el-form :model="chooseRow" ref="elRowForm" :inline="true" label-width="100px" :rules="rules">
// <el-form-item label="反馈内容" prop="fknr" style="width: 100%;">
// <MOSTY.Other style="width: 100%;" clearable v-model="chooseRow.fknr" type="textarea" placeholder="请输入不通过原因"/>
// </el-form-item>
// </el-form>
// <div class="flex just-center mt10">
// <el-button @click.stop="cancelRowSp">取消</el-button>
// <el-button type="primary" @click.stop="handleSendSp(props.item)" v-loading="btnloading">确定</el-button>
// </div>
// </el-popover> -->
// const showDetail = () => {
// emit('showDetail',props.item)
// }
// const buttonRef = ref()
// const popoverRef = ref()
// const elRowForm = ref()
// const isShowVisble = ref(false)
// const chooseRow = ref({})
// const rules = reactive({
// fknr: [{ required: true, message: "请输入反馈内容", trigger: "blur" }],
// })
// onMounted(() => {
// deptLevel.value = localStorage.getItem("deptId") ? JSON.parse(localStorage.getItem("deptId"))[0].deptLevel : null;
// });
</script>
<style lang="scss" scoped>
.personCard {
position: relative;
background: rgba(10, 49, 88, 0.6);
box-shadow: inset 0px 0px 10px 0px rgba(56, 119, 242, 0.5);
border-radius: 0px 0px 0px 0px;
border: 1px solid #0072ff;
padding: 10px;
box-sizing: border-box;
transition: all 0.3s;
.boderBox {
border-bottom: 1px solid #217ce1;
padding-bottom: 10px;
}
.infoItem {
font-size: 13px;
margin-bottom: 2px;
color: #fff;
margin-top: 4px;
.value {
color: #89afcf;
}
.smllbtn {
display: inline-block;
padding: 4px 8px;
box-sizing: border-box;
border-radius: 4px;
background: #0072ff;
border-radius: 5px 5px 5px 5px;
margin-right: 6px;
margin-top: 4px;
cursor: pointer;
}
}
&:hover {
background: rgba(17, 66, 96, 0.8);
}
::v-deep .el-button {
span {
color: #fff;
}
}
.avatarBox {
margin-right: 5px;
overflow: hidden;
width: 80px;
.marks {
width: 70px;
height: 32px;
line-height: 40px;
text-align: center;
background: rgba(255, 62, 62, 0.75);
top: -4px;
left: -24px;
transform: rotate(-45deg);
z-index: 1;
}
.marks_red {
background: rgba(255, 62, 62, 0.35);
}
.marks_orange {
background: rgba(255, 155, 62, 0.35);
}
.marks_yellow {
background: rgba(255, 239, 62, 0.35);
}
.marks_blue {
background: rgba(0, 114, 255, 0.35);
}
}
.bqbox {
color: #ff0000;
padding: 0px 6px;
background: rgba(255, 0, 0, 0.3);
border-radius: 1px 1px 1px 1px;
border: 1px solid #ff0000;
border-radius: 4px;
}
.infoBox {
width: calc(100% - 90px);
// display: flex;
// justify-content: space-between;
.linItem {
line-height: 28px;
}
.wichAlian {
// width: 10%;
text-align: center;
}
.wichAlian3 {
// width: 40%;
}
.wichAlian2 {
// width: 10%;
text-align: center;
}
}
}
.smallbtn {
display: inline-block;
padding: 4px 10px;
border-radius: 4px;
background: #0072ff;
border-radius: 5px 5px 5px 5px;
margin-top: 6px;
}
.num {
color: #00ffff;
}
</style>

View File

@ -1,349 +0,0 @@
<template>
<div class="systemBox">
<GdMap></GdMap>
<!-- 头部筛选 -->
<div class="topSearch">
<el-form v-model="listQuery">
<MOSTY.Select v-model="listQuery.sd" :dictEnum="search.xd" />
<MOSTY.Select v-model="listQuery.zs" :dictEnum="search.zs" />
<MOSTY.Select v-model="listQuery.qy" :dictEnum="search.qy" />
<MOSTY.Select v-model="listQuery.dz" :dictEnum="search.dz" />
</el-form>
<el-button type="primary">搜索</el-button>
</div>
<div class="systemBox">
<!-- 左边列表 -->
<div class="leftList">
<div class="hed flex just-between align center">
<span class="f14">预警列表</span>
<span style="color: #00b7ff" class="pointer" @click="seeMoreFn">查看更多</span>
</div>
<div class="ml10 mr10 mt10">
<el-input v-model="keyword" placeholder="姓名、证件号码搜索">
<template #append>
<el-button type="primary" @click="getKeyword">搜索</el-button>
<!-- <div >
<el-icon >
<Search />
</el-icon>
</div> -->
</template>
</el-input>
</div>
<ul class="listContent noScollLine mt10" v-infinite-scroll="loadList" style="overflow: auto"
v-loading="loading">
<!-- @click.stop="showDetail(item)" -->
<li v-for="(item, index) in personList" :key="index" @click="markAbove(item)">
<YjItem :item="item" type="yj" :dic="{ D_BZ_YJCZZT }" @showDetail="showDetail"></YjItem>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0"></MOSTY.Empty>
</ul>
</div>
<!-- 右边模块 -->
<div class="rightList">
<!-- 第一部门 -->
<div class="model-commom">
<div class="hed flex align-center">预警处置统计</div>
<div class="comm-cnt" v-loading="list.YjczDate.loading">
<BarHatEcharts echartsId="qylxEcharts" :data="list.YjczDate"></BarHatEcharts>
</div>
</div>
<!-- 第二部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">布控区域统计</div>
<div class="comm-cnt" v-loading="list.RylxDate.loading">
<BarHatEcharts echartsId="rylxEcharts" :data="list.RylxDate"></BarHatEcharts>
</div>
</div>
<!-- 第三部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">感知源统计</div>
<div class="comm-cnt" v-loading="list.GzyDate.loading">
<BarHatEcharts echartsId="gzyEcharts" :data="list.GzyDate"></BarHatEcharts>
</div>
</div>
<!-- 第四部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">预警等级统计</div>
<div class="comm-cnt" v-loading="loadingyj">
<WarningCount ref="yjjbRef"></WarningCount>
</div>
</div>
</div>
</div>
</div>
<Information v-model="showDialog" title="发送指令" @submit='submit' @close='close'>
<SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj"
:tacitly="tacitly" />
</Information>
<!-- 反馈按钮 -->
<FkDialog @change="getList"></FkDialog>
<LeftDialog></LeftDialog>
</template>
<script setup>
import LeftDialog from '@/views/home/dialog/leftDialog.vue'
import FkDialog from './components/fkDialog.vue'
import * as MOSTY from "@/components/MyComponents/index";
import { qcckPost, qcckGet } from "@/api/qcckApi.js";
import GdMap from "@/components/GdMap/index.vue";
import emitter from "@/utils/eventBus.js";
import YjItem from "./components/yjItem.vue";
import WarningCount from "./components/WarningCount.vue";
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted, reactive, ref, getCurrentInstance } from "vue";
import { useRouter } from "vue-router";
import Information from "@/views/home/model/information.vue";
import SemdFqzl from '@/components/instructionHasBeen/sendFqzl.vue'
const { proxy } = getCurrentInstance();
const { D_BZ_YJCZZT } = proxy.$dict('D_BZ_YJCZZT')
const router = useRouter()
const listQuery = ref({});
const keyword = ref('');
const yjjbRef = ref()
const search = reactive({
xd: [
{ label: "吸毒", value: "10" },
{ label: "贩毒", value: "20" }
],
zs: [
{ label: "酒店", value: "10" },
{ label: "名宿", value: "20" }
],
qy: [
{ label: "县城", value: "10" },
{ label: "市区", value: "20" }
],
dz: [
{ label: "网吧", value: "10" },
{ label: "酒馆", value: "20" }
]
});
const loading = ref(false)
const loadingyj = ref(false)
const list = reactive({
// 预警处置统计
YjczDate: {
loading: false,
xDate: [],
list: [],
},
// 布控区域统计
RylxDate: {
loading: false,
xDate: [],
list: [],
},
// 感知源
GzyDate: {
xDate: [],
list: [],
loading: false,
},
})
const personList = ref([]);
const pageNum = ref(1)
const total = ref(0)
onMounted(() => {
getList()
init()
})
// 触底加载
const loadList = () => {
if (personList.value.length == total.value) return;
pageNum.value++;
getList()
}
const getList = () => {
let params = { pageSize: 10, pageNum: pageNum.value,keyword:keyword.value };
loading.value = true;
qcckPost(params, '/mosty-gsxt/tbYjxx/getPageList').then(res => {
loading.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(() => {
loading.value = false;
})
}
const getKeyword = () => {
pageNum.value=1
getList()
}
const init = () => {
// 预警处置统计
list.YjczDate.loading = true;
qcckGet({}, '/mosty-gsxt/tbYjxx/getYjCzztTj').then(res => {
list.YjczDate.loading = false;
list.YjczDate.xDate = res.map(item => item.zdmc);
list.YjczDate.list = [{
value: res.map(item => item.count),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
})
// 布控区域统计
list.RylxDate.loading = true;
qcckGet({}, '/mosty-gsxt/tbGsxtBkQy/getBkQytj').then(res => {
list.RylxDate.loading = false;
list.RylxDate.xDate = res.map(item => item.qymc);
list.RylxDate.list = [{
value: res.map(item => item.num),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
})
// 感知元统计
list.GzyDate.loading = true;
qcckGet({}, '/mosty-gsxt/tbYjxx/getGzyTj').then(res => {
list.GzyDate.loading = false;
list.GzyDate.xDate = res.map(item => item.yj_gzymc);
list.GzyDate.list = [{
value: res.map(item => item.num),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
})
// 预警级别
loadingyj.value = true;
qcckGet({}, '/mosty-gsxt/tbYjxx/getYjxxTj').then(res => {
loadingyj.value = false;
yjjbRef.value.initCharts(res)
})
}
const seeMoreFn = () => {
router.push('/ControlApproval')
}
const showDialog = ref(false)
const itemData = ref()
const showDetail = (item) => {
showDialog.value = true;
itemData.value = item
}
const handleClose = () => {
showDialog.value = false;
}
const semdFqzlRef = ref()
const tacitly = {
title: 'yjBt',
instructionContent: 'yjNr'
}
const submit = () => {
semdFqzlRef.value.getsendFqzl()
}
const close = () => {
semdFqzlRef.value.close()
}
// 标点上图
const markAbove = (val) => {
const icon = require('@/assets/point/yj.png')
emitter.emit('setMapCenter', { location: [val.jd, val.wd], zoomLevel: 15 });
emitter.emit("addPointArea", { flag: 'home_yj_detail', icon, coords: [val] })
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.systemBox {
position: relative;
left: -20px;
top: 0;
width: calc(100% + 40px);
height: calc(100% + 20px);
background: #e9edf6;
.topSearch {
position: absolute;
top: 10px;
right: 500px;
width: 600px;
height: 60px;
display: flex;
align-items: center;
z-index: 9;
.el-form {
display: flex;
::v-deep .el-input__inner {
background: rgba(0, 22, 83, 0.4);
border: 1px solid #0072ff;
color: #fff;
}
}
}
.leftList {
position: absolute;
left: 20px;
top: 10px;
width: 427px;
height: calc(100% - 20px);
border-radius: 6px 6px 6px 6px;
background: rgba(0, 29, 75, 0.4);
z-index: 9;
.listContent {
height: calc(100% - 96px);
overflow: hidden;
overflow-y: auto;
padding: 10px 10px 0;
box-sizing: border-box;
}
::v-deep .el-input__inner {
background: rgba(0, 22, 83, 0.4);
border: 1px solid #0072ff;
}
::v-deep .el-input-group__append {
background: #0386fb;
color: #fff;
border: 1px solid #0072ff;
}
}
.rightList {
position: absolute;
right: 30px;
top: 10px;
width: 427px;
height: calc(100% - 20px);
z-index: 9;
.model-commom {
height: calc((100% / 4) - 10px);
}
.comm-cnt {
height: calc(100% - 40px);
background: rgba(0, 29, 75, 0.6);
}
}
.hed {
height: 40px;
line-height: 40px;
padding-left: 10px;
background: linear-gradient(90deg, #124cb3 0%, rgba(18, 76, 179, 0.23) 77%, rgba(18, 76, 179, 0) 100%);
}
}
</style>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>