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

View File

@ -1,21 +1,115 @@
<template>
<router-view v-slot="{ Component }" v-if="isRouterAlive">
<keep-alive :include="store.getters.keepLiiveRoute">
<Watermark :text="content" :color="'rgba(0, 0, 0, .15)'">
<Component :is="Component"></Component>
</Watermark>
</keep-alive>
</router-view>
<Fxq :initial-position="{ x: position.x, y: position.y }">
<el-badge value="0" class="item badge-top-left">
<div class="badge-container">
<!-- :class="{ 'expanded': isExpanded }" -->
<div class="badge-content expanded">
<div class='fxq fxq1' @click.stop="opneMsg('xtxx')">
<div class="title"> <img src="@/assets/images/xtxx.png" /> 系统消息</div>
</div>
<!-- <div class='fxq fxq2'>
<div class="title" @click.stop="opneMsg('tztg')"> <img src="@/assets/images/tztg.png" /> 通知通报</div>
</div>
<div class='fxq fxq3'>
<div class="title"> <img src="@/assets/images/xxxt.png" /> 消息协同</div>
</div> -->
<div style="margin-bottom: 8px;" title="蜂群"
@click.stop="skipIframe('https://fqxt.lz.dsj.xz:9020/index.html?source=other')">
<img src="@/assets/images/logo-1.png" alt="" srcset="">
</div>
<div title="林小警"
@click.stop="skipIframe(`https://tyyy.lz.dsj.xz/embed/home?userId=${userId}&clientKey=${clientKey}&avatar=''`)">
<img src="@/assets/images/lxj.png" alt="" srcset="" style="width: 34px;height: 38px">
</div>
<div title="三视图" @click.stop="SwitchSysDialogShow = true">
<img src="@/assets/images/sst.png" alt="" srcset="" style="width: 34px;height: 38px">
</div>
</div>
</div>
</el-badge>
</Fxq>
<Iframe v-model='showIframe' :src='src' />
<Information v-model='showDialog' :title='title'>
<systemMessages :dict="{ BD_D_XXLX, BD_D_XXLY }" :idEntityCard='idEntityCard' :xxlx="showMsgLx" />
</Information>
<SwitchSysDialog v-model="SwitchSysDialogShow"/>
</template>
<script setup>
import * as ocr from "@paddlejs-models/ocr";
import Watermark from "@/components/Watermark.vue";
import { ref, nextTick, provide, onMounted,getCurrentInstance } from "vue";
import { ref, reactive, nextTick, provide, onMounted, getCurrentInstance, onBeforeUnmount } from "vue";
import { useStore } from "vuex";
import { getItem, setItem} from "@/utils/storage";
import { queryXxTj } from '@/api/commit.js'
import { getItem, setItem } from "@/utils/storage";
import { generateNewStyle, writeNewStyle } from "@/utils/theme";
import {timeValidate} from "@/utils/tools";
import { timeValidate } from "@/utils/tools";
import Information from '@/views/home/model/information.vue'
import SwitchSysDialog from '@/components/SwitchSysDialog.vue'
import systemMessages from '@/views/home/model/mesgSwitch/systemMessages.vue'
import Fxq from '@/views/home/model/fxq.vue'
import Iframe from '@/views/home/model/iframe.vue'
import { getCookie } from '@/utils/cookie'
const { proxy } = getCurrentInstance();
const idEntityCard = getItem('idEntityCard')
const { BD_D_XXLX, BD_D_XXLY } = proxy.$dict('BD_D_XXLX', 'BD_D_XXLY'); //获取字典数据
const SwitchSysDialogShow=ref(false)
const userId = getItem('USERID')
const clientKey = getCookie('clientKey')
const showMsgLx = ref('')
const showDialog = ref(false)
//消息
const position = reactive({
x: window.innerWidth - 120,
y: window.innerHeight - 140
})
const title = ref('系统消息')
const opneMsg = (val) => {
showDialog.value = true
showMsgLx.value = val
switch (val) {
case 'xtxx':
title.value = '系统消息'
break;
case 'tztg':
title.value = '通知通告'
break;
case 'xxxt':
title.value = '消息协同'
break;
}
}
const src = ref()
const showIframe = ref(false)
const skipIframe = (val) => {
src.value = val
showIframe.value = true
}
// 展开收缩状态
const isExpanded = ref(false)
const toggleExpand = () => {
isExpanded.value = !isExpanded.value
}
const queryXxTjList = () => {
queryXxTj({}).then((res) => {
console.log(res);
}).catch((err) => {
});
}
queryXxTjList()
const store = useStore();
generateNewStyle(store.getters.mainColor).then((newStyle) => {
@ -29,12 +123,51 @@ const reload = () => {
});
};
provide("reload", reload);
// 处理页面可见性变化的函数
const handleVisibilityChange = () => {
// 只在页面变得可见时触发
if (document.visibilityState === 'visible') {
// 获取会话信息 - 带上所有cookies
fetch('https://pcs.lz.dsj.xz:9020/getSession', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
// 确保发送所有cookies包括跨域cookies
credentials: 'include',
})
.then((response) => {
// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
console.log('会话信息:', data);
// 这里可以根据返回的数据进行后续处理
})
.catch((error) => {
console.error('获取会话信息失败:', error);
// 可以添加错误通知或重试逻辑
})
}
};
onMounted(() => {
window.addEventListener("visibilitychange", handleVisibilityChange);
document.title = "林芝";
frashJs()
// initPage()
});
// 在组件卸载前移除事件监听器
onBeforeUnmount(() => {
window.removeEventListener("visibilitychange", handleVisibilityChange);
})
/**
*@Descripttion:图片页面初始化
*@Author: PengShuai
@ -43,35 +176,40 @@ const initPage = async () => {
try {
await ocr.init();// 模型初始化
imgIsLoad = true;
proxy.$message({ type: "success", message: "加载成功" });
proxy.$message({ type: "success", message: "加载成功" });
} catch (err) {
proxy.$message({ type: "error", message: "加载失败,请刷新页面" });
proxy.$message({ type: "error", message: "加载失败,请刷新页面" });
imgIsLoad = false;
}
}
const content=ref([])
const content = ref([])
const frashJs = () => {
const sfzh= getItem("idEntityCard")
const userName= getItem("USERNAME")
const sfzh = getItem("idEntityCard")
const userName = getItem("USERNAME")
const time = timeValidate()
content.value=[userName,sfzh,time,"林芝哨岗系统","禁止泄露公民个人信息和警务工作秘密"]
content.value = [userName, sfzh, time, "林芝哨岗系统", "禁止泄露公民个人信息和警务工作秘密"]
}
// 监听标签页切换
</script>
<style lang="scss">
@import "./styles/index.scss";
body {
margin: 0px;
padding: 0px;
font-size: 14px;
}
ul {
margin: 0px;
padding: 0px;
}
li {
list-style-type: none;
}
#app {
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
Microsoft YaHei, SimSun, sans-serif;
@ -91,6 +229,7 @@ li {
overflow: hidden;
text-overflow: ellipsis;
}
//只显示二排内容
.two_text_detail {
display: -webkit-box;
@ -99,6 +238,7 @@ li {
overflow: hidden;
text-overflow: ellipsis;
}
//只显示三排内容
.text_detail {
display: -webkit-box;
@ -123,18 +263,21 @@ v-deep .el-loading-mask {
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "HANYILINGXINTIJIAN";
src: url("~@/assets/font/HANYILINGXINTIJIAN-1.TTF");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "YSBTH";
src: url("~@/assets/font/YSBTH.ttf");
font-weight: normal;
font-style: normal;
}
.bk_drawer_box {
.el-drawer__header {
background: #fff !important;
@ -144,8 +287,98 @@ v-deep .el-loading-mask {
line-height: 22px;
text-align: left;
text-transform: none;
margin-bottom:0;
height:40px;
margin-bottom: 0;
height: 40px;
}
}
.fxq {
border-radius: 35px;
width: 35px;
transition: transform 0.5s ease, width 0.5s ease;
background-color: rgb(1, 127, 245);
transform-origin: left center;
overflow: hidden;
margin-bottom: 10px;
.icon {
display: flex;
align-items: center;
width: 35px;
height: 35px;
justify-content: center;
line-height: 35px;
font-size: 30px;
}
.title {
height: 35px;
line-height: 35px;
img {
margin-left: 9.5px;
width: 16px;
margin-right: 10px;
margin-top: -3px;
vertical-align: middle;
height: 16px;
}
}
}
.fxq2 {
background-color: #9d88f9;
}
.fxq1:hover {
width: 120px;
}
.fxq2:hover {
width: 120px;
// background-color: red;
}
.fxq3:hover {
width: 120px;
}
::v-deep .badge-top-left .el-badge__content {
top: 0;
right: auto;
left: -10px;
transform: translateY(-50%) translateX(-50%);
}
.badge-content {
display: flex;
flex-direction: column;
overflow: hidden;
transition: all 0.3s ease;
max-height: 200px;
/* 默认展开的最大高度 */
min-height: 45px;
/* 确保收缩时有足够空间显示第一个图标 */
}
.badge-content:not(.expanded) {
max-height: 45px;
}
/* 收缩时只显示第一个图标,隐藏其他内容 */
.badge-content:not(.expanded)> :not(:first-child) {
opacity: 0;
max-height: 0;
margin: 0;
padding: 0;
overflow: hidden;
}
.badge-container {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
</style>

52
src/api/Intelligence.js Normal file
View File

@ -0,0 +1,52 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
// 查询
export const qbcjSelectPage = (params) => {
return request({
url: api + "/qbcj/selectPage",
method: "get",
params
});
};
// 新增
export const qbcjAdd = (data) => {
return request({
url: api + "/qbcj/add",
method: "POST",
data
});
};
// 删除
export const qbcjDeletes = (data) => {
return request({
url: api + "/qbcj/deletes",
method: "POST",
data
});
};
// 修改
export const qbcjUpdate = (data) => {
return request({
url: api + "/qbcj/update",
method: "POST",
data
});
};
// 根据id查询详情
export const qbcjSelectByid = (params) => {
return request({
url: api + "/qbcj/selectByid",
method: "get",
params
});
};
// 根据id查询详情
export const qbcjimportRyData = (data) => {
return request({
url: api + "/qbcj/importRyData",
method: "post",
data
});
};

View File

@ -48,6 +48,16 @@ export const updateBkgzl = (params) => {
params
});
};
export const tbGsxtBkId = (id) => {
return request({
url: gsxtApi + `/tbGsxtBk/${id}`,
method: "get",
});
};
// 签收
export const qsXx = (data) => {
return request({
@ -91,3 +101,12 @@ export function upImageFileInfo(data) {
data
})
}
export function upImageUploadId(data) {
return request({
url: api + '/minio/image/upload/id',
method: 'post',
data
})
}

View File

@ -163,3 +163,27 @@ export const getYjxxPageList = (params) => {
params
});
}
// 预警详情
export const mxglYjxqgetPageList = (params) => {
return request({
url: gsxtApi + `/mxglYjxq/getPageList`,
method: "get",
params
});
}
// 预警详情
export const mxglJqxqPageList = (params) => {
return request({
url: gsxtApi + `/mxglJqxq/getPageList`,
method: "get",
params
});
}
// 不分页查询预警详情列表
export const mxglYjxqSelectList = (params) => {
return request({
url: gsxtApi + `/mxglYjxq/selectList`,
method: "get",
params
});
}

View File

@ -1,7 +1,7 @@
import request from "@/utils/request";
import axios from "axios";
import qs from 'qs'; // 或者使用 URLSearchParams
const api = "/bpm";
const api = "/jgpt/bpm";
const flowApproval = "/flowApproval";
const orgOrganization = '/orgOrganization'
// 解析数据
@ -40,9 +40,10 @@ export const splGet = (params = {}, url) => {
//post 请求
export const splPost = (data = {}, url) => {
return request({
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
url: api + url,
method: "post",
data
data: qs.stringify(data)
});
};
//put 请求

35
src/api/tbGsxtMgjd.js Normal file
View File

@ -0,0 +1,35 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
export const tbGsxtMgjdSave = (data) => {
return request({
url: api + "/tbGsxtMgjd/save",
method: "POST",
data
});
};
// 查询敏感事件
export const tbGsxtMgjdSelectList = (params) => {
return request({
url: api + "/tbGsxtMgjd/selectList",
method: "get",
params
});
};
// 更新敏感事件
export const tbGsxtMgjdUpdate = (data) => {
return request({
url: api + "/tbGsxtMgjd/update",
method: "POST",
data
});
};
// 删除敏感事件
export const tbGsxtMgjdDelete = (data) => {
return request({
url: api + "/tbGsxtMgjd/deletes",
method: "POST",
data
});
};

78
src/api/tbGsxtXxltHf.js Normal file
View File

@ -0,0 +1,78 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
// 新增
export const tbGsxtXxltSave = (data) => {
return request({
url: api + "/tbGsxtXxlt/save",
method: "POST",
data
});
};
// 分页查询
export const tbGsxtXxltSelectPage = (params) => {
return request({
url: api + "/tbGsxtXxlt/selectPage",
method: "get",
params
});
};
// 更新
export const tbGsxtXxltUpdate = (data) => {
return request({
url: api + "/tbGsxtXxlt/update",
method: "POST",
data
});
};
export const tbGsxtXxltDelete = (id) => {
return request({
url: api + `/tbGsxtXxlt/${id}`,
method: "DELETE",
});
};
// 根据身份证号查询
export const tbGsxtXxltTxTxQueryBySfzh = (params) => {
return request({
url: api + "/TbGsxtXxltTxTx/queryBySfzh",
method: "get",
params
});
};
// 新增
export const tbGsxtXxltTxTxSave = (data) => {
return request({
url: api + "/TbGsxtXxltTxTx/save",
method: "POST",
data
});
};
// 分页查询
export const tbGsxtXxltHfSelectPage = (params) => {
return request({
url: api + "/tbGsxtXxltHf/selectPage",
method: "get",
params
});
};
// 新增
export const tbGsxtXxltHfSave = (data) => {
return request({
url: api + "/tbGsxtXxltHf/save",
method: "POST",
data
});
};
export const tbGsxtXxltHfid = (id) => {
return request({
url: api + `/tbGsxtXxlt/${id}`,
method: "get",
});
};
// 分页查询
export const tbGsxtXxltHfSelectList = (params) => {
return request({
url: api + "/tbGsxtXxltHf/selectList",
method: "get",
params
});
};

View File

@ -1,5 +1,6 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-base";
const api2 = "/lzsg/mosty-api/mosty-base";
/*
* 登录
* return promise 实例对象
@ -628,3 +629,19 @@ export const getSessionForSfzh = (params) => {
params
});
};
// 身份证号登录
export const idCardNoLoginPcs = (data) => {
return request({
url: api2 + `/idCardNoLogin`,
method: "POST",
data
});
}
// 通过身份证号获取会话信息
export const getSessionForSfzhPcs = (params) => {
return request({
url: api2 + `/getSessionForSfzh`,
method: "GET",
params
});
};

View File

@ -23,3 +23,11 @@ export const tbYjxxQueryYjxx = (params) => {
params
})
}
// 警情查询
export const tbJqGetPageList = (params) => {
return request({
url: api + `/tbJq/getPageList`,
method: "get",
params
})
}

26
src/api/yszx.js Normal file
View File

@ -0,0 +1,26 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-yszx";
/*
* 查询摄像头列表
* return promise 查询摄像头列表
*/
export const ysSxtGetList = (data = {}) => {
return request({
url: api + "/tbYsSxt/getList",
method: "POST",
data
});
};
/**
* 获取摄像头列表
* @param {*} data
*/
export const ysSxtgetPageList = (data = {}) => {
return request({
url: api + "/tbYsSxt/getPageList",
method: "POST",
data
});
};

View File

@ -173,3 +173,10 @@ export const tbGsxtZdrySelectList = (params) => {
params,
});
}
export function tbGsxtBqglSelectList(params) {
return request({
url: api + '/tbGsxtBqgl/selectList',
method: 'get',
params
})
}

View File

@ -1,5 +1,3 @@
:v-deep .el-card {
border: 1px solid #146bbe;
background: #00143d;
@ -41,9 +39,10 @@
--el-table-row-hover-bg-color: #f5f7fa;
}
::v-deep .el-table__inner-wrapper{
::v-deep .el-table__inner-wrapper {
background: #fff;
}
::v-deep .el-table th.el-table__cell {
background: #ffffff;
color: #000;
@ -88,7 +87,7 @@
// }
::v-deep .is-focusable {
background:transparent !important;
background: transparent !important;
}
::v-deep .el-tree-node__label {
@ -103,6 +102,7 @@
::v-deep .el-dialog__title {
color: #000;
}
::v-deep .el-dialog__header,
::v-deep .el-dialog__body,
::v-deep .el-dialog__footer,
@ -111,6 +111,7 @@
// background: #02163b;
// background: #02163b;
}
::v-deep .user-main-wrap {
border: 1px solid #07376d;
}
@ -129,39 +130,49 @@
box-shadow: 0px 0px 8px #0a6bfc;
}
}
::v-deep .el-input .el-input__count .el-input__count-inner {
background: transparent;
color: #fff;
}
::v-deep .el-textarea .el-input__count {
background: transparent;
color: #fff;
}
::v-deep .el-select__popper.el-popper {
background: #16284c;
border: #16284c;
}
::v-deep .el-range-input {
background: transparent;
color: #fff;
// color: #fff;
}
::v-deep .el-range-separator {
color: #fff;
}
::v-deep .el-button--danger {
background: #f56c6c;
border: 1px solid #f56c6c;
}
::v-deep .el-tree {
--el-tree-node-hover-bg-color: #083960;
}
::v-deep .el-tree-node__label {
background: transparent !important;
}
::v-deep .el-card {
border: 1px solid #07539a;
color: #fff;
}
::v-deep .el-collapse {
background: transparent;
color: #fff;
@ -171,21 +182,26 @@
--el-collapse-content-text-color: #fff;
--el-collapse-border-color: #0d3f6e;
}
::v-deep .el-tabs__item {
color: rgb(206, 208, 220);
}
::v-deep .el-tabs__nav-wrap::after {
background: #0d3f6e;
}
::v-deep .el-upload--picture-card {
// background-color: #112b63;
border: 1px dashed #4579b5;
}
::v-deep .el-upload-list--picture-card .el-upload-list__item {
background-color: #10295b;
border: 1px solid #19538a;
color: #ced0dc;
}
.toastui-editor-defaultUI {
position: relative;
border: 1px solid #dadde6;
@ -201,10 +217,12 @@
::v-deep .el-dialog__body {
padding: 10px 20px;
}
::v-deep .el-pagination__total,
::v-deep .el-pagination__jump {
color: #bdc7da;
}
::v-deep .el-radio {
color: rgb(206, 208, 220);
}
@ -215,6 +233,7 @@
border: 1px solid #19538a;
margin: 0 0.2rem;
}
::v-deep .el-select .el-select__tags .el-tag--info {
background: transparent;
border: 1px solid #19538a;
@ -227,12 +246,15 @@
::v-deep .el-overlay .el-overlay-dialog .el-dialog .el-dialog__body .tabBox {
height: 450px;
}
::v-deep .el-date-editor .el-range-separator {
color: #fcfcfc;
}
::v-deep .el-date-editor .el-range-input {
// color: #ffffff;
}
::v-deep .el-input.is-disabled .el-input__inner {
background-color: #ffffff;
border: 1px solid #e9e9e9;
@ -243,7 +265,6 @@
width: 100%;
}
::v-deep .el-link{
margin: 5px;
}
::v-deep .el-link {
margin: 5px;
}

View File

@ -15,7 +15,7 @@
height: 100%;
height: calc(100vh - 72px);
overflow: hidden;
z-index: 10;
// z-index: 10;
.asideTitle {
display: flex;
@ -63,6 +63,7 @@
height: 70px;
background: rgba(0, 0, 0, 0.8);
z-index: 2;
.headBoxBg {
width: 100%;
height: 100%;
@ -219,6 +220,7 @@
.asideR {
position: absolute;
right: 0px;
z-index: 10;
.commom-aside-small {
height: calc(((100% - 146px) /3) - 6px);

BIN
src/assets/images/fk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="30px" height="34px" viewBox="0 0 30 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 58 (84663) - https://sketch.com -->
<title>编组</title>
<desc>Created with Sketch.</desc>
<defs>
<polygon id="path-1" points="0 0.0325052879 12.5373778 0.0325052879 12.5373778 24.1761162 0 24.1761162"></polygon>
<polygon id="path-3" points="0 0.0324150789 12.5373778 0.0324150789 12.5373778 23.5403835 0 23.5403835"></polygon>
</defs>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="蜂群系统-首页" transform="translate(-40.000000, -14.000000)">
<g id="logo" transform="translate(28.000000, 8.000000)">
<g id="编组" transform="translate(12.000000, 6.000000)">
<path d="M30,9.87641882 L30,21.1561825 C30,21.9153863 29.4802422,22.1891529 28.8441948,21.763528 L20.693552,16.2916214 C20.0575489,15.8643716 20.1631137,15.5663199 20.9294108,15.6275375 L21.2812489,15.6555114 C21.2828886,15.6555114 21.2860795,15.6555114 21.2874977,15.6570485 L21.9637855,15.7107566 L22.2990931,15.7367543 L22.5145657,15.7536616 C22.5935842,15.7600732 22.6711401,15.7600732 22.7471449,15.7521685 C23.4031353,15.6939371 23.9056092,15.1650239 23.9056092,14.4827593 L23.9056092,12.7874176 C23.9056092,12.0265889 23.4511314,10.9738127 22.8976478,10.4464805 L14.3311279,2.31902901 C13.7772455,1.79340943 13.7974987,1.09098775 14.3760217,0.760570696 C14.5435426,0.66531889 14.7483789,0.599314527 14.9701889,0.565412086 C15.5144544,0.480787729 16.1659244,0.577620478 16.6391043,0.848181278 L18.5328433,1.93182976 L19.5457683,2.51115748 C19.5503774,2.51427545 19.5549864,2.51585639 19.5596397,2.51884262 L21.1650922,3.43811696 L28.7914567,7.80147527 C29.4554686,8.18103329 30,9.11550225 30,9.87641882" id="Fill-1" fill="#FFBA69"></path>
<path d="M19.2857143,0.535714286 L20.3571429,1.60714286 C19.9534352,1.22639262 19.5974017,0.871063632 19.2857143,0.535714286" id="Fill-3" fill="#27AAE1"></path>
<path d="M30,9.87641882 L30,21.1561825 C30,21.9153863 29.4812731,22.1891529 28.8464873,21.763528 L20.712011,16.2916214 C20.0772694,15.8643716 20.1826248,15.5663199 20.9474019,15.6275375 L21.2985422,15.6555114 C21.3001787,15.6555114 21.3033632,15.6555114 21.3047786,15.6570485 L21.9797251,15.7107566 C22.0944571,15.7215597 22.2057835,15.7306501 22.3143676,15.7367543 C22.4689949,15.7477331 22.6172532,15.7521685 22.7615307,15.7521685 C26.0029103,15.7768049 26.8560586,13.7049354 26.6404826,11.6346907 C26.4084974,9.41219252 20.6360685,4.2202006 15,0.565412086 C15.543186,0.480787729 16.1933638,0.577620478 16.6656052,0.848181278 L18.555588,1.93182976 L19.5665039,2.51115748 C19.5711038,2.51427545 19.5757037,2.51585639 19.5803478,2.51884262 L21.1826159,3.43811696 L28.7938538,7.80147527 C29.4565487,8.18103329 30,9.11550225 30,9.87641882" id="Fill-5" fill="#FA6400"></path>
<path d="M13.3202184,33.4482714 L3.68384739,27.6378717 C3.03535278,27.2468674 3.06167786,26.6572056 3.74351465,26.3276652 L12.498388,22.110659 C13.1817938,21.781563 13.383416,22.026174 12.9475704,22.6562339 L12.7475609,22.9458206 C12.7468199,22.9469317 12.7452509,22.9496871 12.743246,22.9503537 L12.3586995,23.5063282 L12.168758,23.7820488 L12.046329,23.9594629 C12.0013497,24.0245266 11.962603,24.0915902 11.9309606,24.1609203 C11.6524117,24.7576485 11.8526828,25.4635716 12.4356698,25.815111 L13.8840282,26.6884931 C14.5337431,27.0803862 15.6608833,27.2306015 16.3883968,27.0238555 L27.619701,23.8160917 C28.345994,23.6089901 28.9359545,23.9884394 28.9285714,24.6579642 C28.9260608,24.8513775 28.8801663,25.0622567 28.7980094,25.2709582 C28.5978691,25.7847124 28.1889153,26.2969111 27.721035,26.5661876 L25.8471607,27.6428048 L24.8452825,28.2183784 C24.8403138,28.2209116 24.8366091,28.2241559 24.8317277,28.2265558 L23.2428527,29.1389139 L15.6974508,33.4743147 C15.0409802,33.8516751 13.9701077,33.8403423 13.3202184,33.4482714" id="Fill-7" fill="#047D62"></path>
<path d="M13.3717922,33.4482714 L3.68624372,27.6378717 C3.03443963,27.2468674 3.06089905,26.6572056 3.74621547,26.3276652 L12.5457677,22.110659 C13.2326612,21.781563 13.4353123,22.026174 12.9972425,22.6562339 L12.7962123,22.9458206 C12.7954675,22.9469317 12.7938905,22.9496871 12.7918754,22.9503537 L12.4053664,23.5063282 C12.3385169,23.5997906 12.2743835,23.6916086 12.2144555,23.7820488 C12.126973,23.9103541 12.0482957,24.0364372 11.9754446,24.1609203 C10.3202854,26.9519032 11.6691462,28.7570647 13.5553873,29.6371132 C15.5807155,30.5813809 22.9487432,28.2629985 28.9285714,25.2709582 C28.7274098,25.7847124 28.3163689,26.2969111 27.8461009,26.5661876 L25.9626635,27.6428048 L24.9556724,28.2183784 C24.9506784,28.2209116 24.9469548,28.2241559 24.9420485,28.2265558 L23.3450649,29.1389139 L15.7611564,33.4743147 C15.1013356,33.8516751 14.0249981,33.8403423 13.3717922,33.4482714" id="Fill-9" fill="#44D7B6"></path>
<g transform="translate(0.000000, 1.607143)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-12"></g>
<path d="M1.53628037,5.72765334 L11.4444977,0.186972623 C12.1111997,-0.185916053 12.600452,0.139740356 12.5307663,0.911752883 L11.625337,10.8146804 C11.5544188,11.5875884 11.2421319,11.6404169 10.9293169,10.932112 L10.7851912,10.6066794 C10.7844429,10.6052915 10.7828141,10.6025606 10.7835625,10.6005011 L10.507153,9.97537873 L10.3696746,9.66615288 L10.2814119,9.4669715 C10.2490123,9.39372791 10.2117263,9.32518516 10.1688056,9.26174618 C9.80320899,8.7095092 9.0984286,8.52443034 8.49894708,8.85971228 L7.01001598,9.69243282 C6.34159716,10.0660826 5.63443963,10.9855225 5.43625591,11.7347023 L2.39702808,23.3100103 C2.20025304,24.0584739 1.57365442,24.3856972 1.00644047,24.0356412 C0.842637363,23.9343269 0.6868021,23.7856012 0.550732383,23.6058947 C0.215862654,23.1655378 -0.0108028174,22.5411765 0.000378582841,21.9894767 L0.0458525451,19.7807974 L0.0701963022,18.599543 C0.0706805361,18.5939916 0.0695800046,18.5892012 0.0700642384,18.5836049 L0.109199139,16.7108343 L0.291799328,7.81648357 C0.307602961,7.04236686 0.867861545,6.10134788 1.53628037,5.72765334" id="Fill-11" fill="#006996" mask="url(#mask-2)"></path>
</g>
<g transform="translate(0.000000, 0.535714)">
<mask id="mask-4" fill="white">
<use xlink:href="#path-3"></use>
</mask>
<g id="Clip-14"></g>
<path d="M1.53628037,5.71175791 L11.4444977,0.186453735 C12.1111997,-0.185400097 12.600452,0.139352548 12.5307663,0.909222579 L11.625337,10.7846675 C11.5544188,11.5554304 11.2421319,11.6081123 10.9293169,10.9017731 L10.7851912,10.5772436 C10.7844429,10.5758596 10.7828141,10.5731362 10.7835625,10.5710825 L10.507153,9.94769498 C10.461591,9.84121504 10.4162931,9.73803888 10.3696746,9.63932729 C10.3050073,9.49713082 10.2377869,9.36337237 10.1688056,9.2360429 C8.63576515,6.35688793 6.40692471,6.61717222 4.69172433,7.82175719 C2.85084325,9.11572281 1.05838556,16.7646878 0.550732383,23.5403835 C0.215862654,23.1012486 -0.0108028174,22.47862 0.000378582841,21.9284513 L0.0458525451,19.7259016 L0.0701963022,18.5479254 C0.0706805361,18.5423894 0.0695800046,18.5376123 0.0700642384,18.5320316 L0.109199139,16.6644583 L0.291799328,7.7947912 C0.307602961,7.02282282 0.867861545,6.08441537 1.53628037,5.71175791" id="Fill-13" fill="#00CAFC" mask="url(#mask-4)"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
src/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
src/assets/images/lxj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
src/assets/images/mr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
src/assets/images/pcs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
src/assets/images/sst.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
src/assets/images/ty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

View File

@ -1,5 +1,5 @@
<template>
<el-dialog width="1400px" :model-value="modelValue" append-to-body @close="closed">
<el-dialog width="1400px" :model-value="props.modelValue" append-to-body @close="closed">
<template #title>
<span class="mr10 f16">选择布控车辆</span>
<el-button type="primary" size="small" @click="zdyaddPerson">添加其他车辆</el-button>

View File

@ -0,0 +1,156 @@
<template>
<el-dialog v-model="props.modelValue" width="60%" custom-class="container" @close="close" :title="title" align-center>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData" >
<template #sblx="{ row }">
<dict-tag :options="D_BZ_SBLX" :value="row.sblx" :tag="false" />
</template>
<template #sblxdm="{ row }">
<dict-tag :options="D_BZ_GZSBLX" :value="row.sblxdm" :tag="false" />
</template>
</MyTable>
<div class="footInfoBtn flex just-between align-center">
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="550"
:pageConfiger="{...pageData.pageConfiger,
total: pageData.total}" />
<el-button type="primary" @click="submitDate">确定选择</el-button>
</div>
</el-dialog>
</template>
<script setup>
import { reactive, ref,watch,getCurrentInstance } from 'vue'
import MyTable from '@/components/aboutTable/MyTable.vue'
import Pages from "@/components/aboutTable/Pages.vue";
import { ysSxtgetPageList } from "@/api/yszx";
const { proxy } = getCurrentInstance();
const { D_BZ_SBLX,D_BZ_GZSBLX } = proxy.$dict(
"D_BZ_SBLX",
"D_BZ_GZSBLX"
);
const props = defineProps({
modelValue: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '选择感知源'
},roleIds:{
type: Array,
default: () => [],
}
})
const emit = defineEmits(["update:modelValue", "choose"])
const dataLsit= ref();
const pageData = reactive({
tableData: [], //表格数据
keyCount: 0,
tableHeight: 500,
tableConfiger: {
rowHeight: 61,
showSelectType: "checkBox",
loading: false,
haveControls: false,
rowKey: "id", // 设置行的唯一标识为id
defaultSelectKeys: [] // 用于存储默认选中的ID
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
controlsWidth: 180, //操作栏宽度
tableColumn: [
{ label: "所属部门", prop: "ssbm", showOverflowTooltip: true },
{ label: "设备名称", prop: "sbmc", showOverflowTooltip: true },
{ label: "设备编码", prop: "sbbh", showOverflowTooltip: true },
{ label: "厂商名称", prop: "csmc", showOverflowTooltip: true },
{ label: "地址", prop: "dzmc", showOverflowTooltip: true },
{ label: "感知源类型", prop: "sblx", showOverflowTooltip: true, showSolt: true, },
{ label: "摄像机类型", prop: "sblxdm", showOverflowTooltip: true,showSolt: true, },
]
})
// 监听roleIds变化更新默认选中的ID
watch(() => props.roleIds, (newVal) => {
if (newVal && newVal.length > 0) {
pageData.tableConfiger.defaultSelectKeys = [...newVal];
// 如果表格数据已加载根据选中的ID设置dataLsit
if (pageData.tableData.length > 0) {
dataLsit.value = pageData.tableData.filter(item => newVal.includes(item.id));
}
} else {
pageData.tableConfiger.defaultSelectKeys = [];
}
}, { immediate: true })
// 监听表格数据变化当数据加载后根据默认选中的ID设置dataLsit
watch(() => pageData.tableData, (newVal) => {
if (newVal && newVal.length > 0 && props.roleIds.length > 0) {
dataLsit.value = newVal.filter(item => props.roleIds.includes(item.id));
}
})
const getList = () => {
pageData.tableConfiger.loading = true;
const promes={
// ssbm: propsGzyList.ssbm,
pageSize: pageData.pageConfiger.pageSize,
pageCurrent: pageData.pageConfiger.pageCurrent,
}
ysSxtgetPageList(promes).then((res) => {
pageData.tableData = res.records || []
pageData.total = res.total || 0
// 数据加载完成后更新key以触发表格重新渲染确保选中状态正确显示
pageData.keyCount++;
}).finally(() => {
pageData.tableConfiger.loading = false;
})
}
// 监听对话框显示状态变化
watch(() => props.modelValue, (newVal) => {
if (newVal) {
// 每次打开对话框时,重新获取数据
getList();
} else {
// 关闭对话框时清空选中数据
dataLsit.value = null;
}
})
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent=val
getList()
}
const changeSize = (val) => {
pageData.pageConfiger.pageSize=val
getList()
}
const chooseData = (val) => {
dataLsit.value = val;
}
const close = () => {
emit("update:modelValue", false);
}
const submitDate = () => {
emit("choose", dataLsit.value);
close()
}
</script>
<style lang="scss" scoped>
.container {
color: #000000;
}
</style>

View File

@ -0,0 +1,395 @@
<template>
<div :id="mapid" class="map"></div>
<div class="changeMap_box" v-if="props.isShow">
<el-switch v-model="conditionRoute" @change="handleSwitch" active-text="打开路况" inactive-text="关闭路况" style="--el-switch-color:#13ce66;--el-switch-off-color:#ff4949;" />
<!-- <el-carousel type="card" height="75px" :autoplay="false" indicator-position="none" :initial-index="3" @change="onMapImageChange">
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/slt.jpg')" alt="" />
<div>栅格浅色</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/yxt.jpg')" alt="" />
<div>影像图</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/yst.jpg')" alt="" />
<div>栅格深色</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/shy.png')" alt="" />
<div>三合一</div>
</div>
</el-carousel-item>
</el-carousel> -->
<!-- 地图缩放 -->
<div class="zoomTargetBox">
<el-input-number :min="7" :max="18" v-model="zoomTarget" :step="1" step-strictly @change="handleZoom">
</el-input-number>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, defineProps, nextTick, computed } from "vue";
import { MapUtil } from "./mapUtil";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
const conditionRoute = ref(true); //路况
const mMap = ref(null); //地图对象
const mapUtil = ref(null); //地图工具对象
const zoomTarget = ref(6);
const props = defineProps({
mapid: {
type: String,
default: "mapDiv"
},
//是否显示可以切换地图底图
isShow: {
type: Boolean,
default: false
},
//是否显示实时路况
isShowMvt: {
type: Boolean,
default: false
},
//是否显示地图层级
isShowZoom: {
type: Boolean,
default: false
},
//是否显示绘制控件
isShowDraw: {
type: Boolean,
default: false
},
// 地图唯一标识,用于隔离不同地图实例的操作
mapKey: {
type: String,
default: null
}
});
// 计算地图唯一标识如果没有传入则使用mapid
const uniqueMapKey = computed(() => props.mapKey || props.mapid);
try {
const userInfo = getItem("deptId")[0].deptCode;
} catch (error) {}
let map;
let mapLayer;
let mapLayer1;
onMounted(() => {
emitter.on("followUp", (res) => {
let box = document.getElementsByClassName("changeMap_box");
if (!box) return;
box[0].style.right = !res ? "4px" : "398px";
box[0].style.transition = "0.5s";
});
map = new EliMap({
id: props.mapid,
crs: "EPSG:4490",
style: {
glyphs: "./fonts/{fontstack}/{range}.pbf",
center: [94.36057012, 29.64276831],
zoom: 15
},
minZoom: 7,
maxZoom: 18,
});
// 移除全局挂载,避免不同地图实例冲突
// window.map = map;
// 将地图实例存储在组件内
mMap.value = map;
map.mapboxGLMap.on("load", () => {
map.addWMTSLayer(
"/PGIS_S_TileMapServer/Maps/XZDJ_DJ/EzMap"
,
{
Service: "getImage",
Type: "RGB",
ZoomOffset: "0",
V: "0.3",
Zoom: "{z}",
Row: "{y}",
Col: "{x}"
},
{
tileSize: 300
}
);
zoomTarget.value = map.mapboxGLMap.getZoom();
});
mapUtil.value = new MapUtil(map);
mapUtil.value.Drawplot(); //初始化加载绘制工具
// 为每个事件添加唯一标识过滤,确保只处理与当前地图实例相关的操作
// 设置地图中心点及图层
emitter.on(`setMapCenter_${uniqueMapKey.value}`, (res) => {
mapUtil.value.setMapCenter(res.location, res.zoomLevel);
});
// 也保留原始事件,但添加条件判断
emitter.on("setMapCenter", (res) => {
// 如果事件包含flag并且与当前地图的唯一标识匹配或者没有指定flag则处理
if (!res.flag || res.flag === uniqueMapKey.value) {
mapUtil.value.setMapCenter(res.location, res.zoomLevel);
}
});
emitter.on("removePlot", (flag) => {
mapUtil.value.removePlot(flag);
});
emitter.on("removeAll", (flag) => {
mapUtil.value.removeAll(flag);
});
// 撒点
emitter.on("addPointArea", (obj) => {
// 只处理与当前地图相关的标记点
if (!obj.baseFlag || obj.baseFlag === uniqueMapKey.value ||
obj.flag && obj.flag.includes(uniqueMapKey.value)) {
mapUtil.value.makerSki(obj);
}
});
// 鼠标滑过提示文字的点位
emitter.on("showPoint", (obj) => {
mapUtil.value.showPoint(obj);
});
// 清除覆盖物
emitter.on("deletePointArea", (res) => {
// 只清除与当前地图相关的覆盖物
if (typeof res === 'object' && res.baseFlag) {
if (res.baseFlag === uniqueMapKey.value) {
mapUtil.value.removeElement(res.baseFlag);
}
} else if (typeof res === 'string') {
if (res === uniqueMapKey.value || res.includes(uniqueMapKey.value)) {
mapUtil.value.removeElement(res);
}
}
});
// 清除某个覆盖物的单个
emitter.on("deletePointAreaOne", (obj) => {
if (obj.flag === uniqueMapKey.value || obj.flag.includes(uniqueMapKey.value)) {
mapUtil.value.removeElementOne(obj.flag, obj.id);
}
});
// 清除某个覆盖物的单个
emitter.on("showSquire", (obj) => {
mapUtil.value.zdySquire(obj);
});
// 绘制图形 - 回显区域
emitter.on("drawShape", (res) => {
mapUtil.value.plot(res, resFun);
});
emitter.on("removeEara", (flag) => {
mapUtil.value.removeEara(flag);
});
// 回显图形
emitter.on("echoPlane", (res) => {
mapUtil.value.echoPlane(res);
});
//移除绘制区域
emitter.on("removeEara", (flag) => {
mapUtil.value.removeEara(flag);
});
// 回显线
emitter.on("echoLine", (res) => {
mapUtil.value.createLine(res, res.flag);
});
//创建边界面geojson
emitter.on("setBoundarys", (res) => {
mapUtil.value.createBoundarys(res);
});
// 移除边界
emitter.on("removeBj", (res) => {
mapUtil.value.removeBj(res);
});
// 轨迹回放
emitter.on("drawLineAnimation", (res) => {
mapUtil.value.displayLineAnimation(res);
});
// 聚合撒点
emitter.on("addPoint", (obj) => {
mapUtil.value.aggregateScatteringPoint(obj);
});
// 热力图显示
emitter.on("thermodynamicChart", (res) => {
mapUtil.value.showHeatDrawing(res);
});
// 扩散圆
emitter.on("diffusionCircle", (res) => {
mapUtil.value.diffusionCircle(res);
});
// 展示盘曲
emitter.on("showGapText", (obj) => {
mapUtil.value.gapText(obj);
});
// 获取当前地图中心点
emitter.on("getCurrentCenter", (res) => {
let centerPoint = map.mapboxGLMap.getCenter();
let coords = [centerPoint.lng, centerPoint.lat];
emitter.emit("getcentercoord", coords);
});
});
//切换地图底图
const onMapImageChange = (val) => {
//清除已经存在胡地图图层
if (map.mapboxGLMap.getLayer("SGQS_ID"))
map.mapboxGLMap.removeLayer("SGQS_ID");
if (map.mapboxGLMap.getLayer("YX_ID")) map.mapboxGLMap.removeLayer("YX_ID");
if (map.mapboxGLMap.getLayer("SGSG_ID"))
map.mapboxGLMap.removeLayer("SGSG_ID");
if (map.mapboxGLMap.getLayer("TDT_TITLE_ID"))
map.mapboxGLMap.removeLayer("TDT_TITLE_ID");
if (map.mapboxGLMap.getLayer("TDT_ROAD_ID"))
map.mapboxGLMap.removeLayer("TDT_ROAD_ID");
if (map.mapboxGLMap.getLayer("TDT_POI_ID"))
map.mapboxGLMap.removeLayer("TDT_POI_ID");
//设置图层
switch (val) {
case 0:
mapSetLayer("SGQS_ID", "SGQS");
break;
case 1:
mapSetLayer("YX_ID", "YX");
break;
case 2:
mapSetLayer("SGSG_ID", "SGSG");
break;
case 3:
mapSetLayer("TDT_TITLE_ID", "TDT_TITLE_SOURCES");
mapSetLayer("TDT_ROAD_ID", "TDT_ROAD_SOURCES");
mapSetLayer("TDT_POI_ID", "TDT_POI_SOURCES");
break;
}
if (map.mapboxGLMap.getLayer("realTimeTrafficlevelOne"))
map.mapboxGLMap.moveLayer("realTimeTrafficlevelOne");
if (map.mapboxGLMap.getLayer("map_id")) map.mapboxGLMap.moveLayer("map_id");
if (map.mapboxGLMap.getLayer("map_ids")) map.mapboxGLMap.moveLayer("map_ids");
};
//设置图层函数
const mapSetLayer = (id, source) => {
map.mapboxGLMap.addLayer({ id, type: "raster", source });
};
//获取地图绘制的数据
const resFun = (coord, type, flag, data) => {
emitter.emit("coordString", {
coord: coord,
type: type,
flag: flag,
data: data
});
};
// 地图层级
const handleZoom = (val) => {
map.mapboxGLMap.setZoom(val);
};
// 是否打开或者关闭路况
const handleSwitch = (val) => {
if (val) {
// 打开
} else {
// 关闭
}
};
onUnmounted(() => {
emitter.off("removePlot");
emitter.off("setMapCenter");
emitter.off("addPointArea");
emitter.off("showPoint");
emitter.off("deletePointArea");
emitter.off("deletePointAreaOne");
emitter.off("drawShape");
emitter.off("echoPlane");
emitter.off("removeEara");
emitter.off("echoLine");
emitter.off("addPoint");
emitter.off("thermodynamicChart");
emitter.off("drawLineAnimation");
emitter.off("aggregateScatteringPoint");
emitter.off("hotmap");
emitter.off("setBoundarys");
emitter.off("diffusionCircle");
emitter.off("SsCircle");
emitter.off("ClearssCircle");
});
</script>
<style lang="scss" scoped>
.map {
width: 100%;
height: 100%;
background-color: aliceblue;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
z-index: 1;
}
.changeMap_box {
position: absolute;
right: 398px;
bottom: 4px;
z-index: 9;
.mapImageItem {
border: 1px solid #08aae8;
background: rgb(9, 26, 70);
& > img {
width: 100%;
height: 50px;
}
& > div {
text-align: center;
position: relative;
top: -3px;
}
}
.zoomTargetBox {
margin-top: 10px;
margin-left: 23px;
}
::v-deep .el-input-number__decrease,
::v-deep .el-input-number__increase {
background: #133362;
color: #fff;
border: none;
}
::v-deep .el-input__inner {
background: #0c1641;
}
}
</style>

View File

@ -0,0 +1,359 @@
<template>
<div :id="mapid" class="map"></div>
<div class="changeMap_box" v-if="props.isShow">
<el-switch v-model="conditionRoute" @change="handleSwitch" active-text="打开路况" inactive-text="关闭路况"
style="--el-switch-color: #13ce66; --el-switch-off-color: #ff4949" />
<!-- <el-carousel type="card" height="75px" :autoplay="false" indicator-position="none" :initial-index="3" @change="onMapImageChange">
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/slt.jpg')" alt="" />
<div>栅格浅色</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/yxt.jpg')" alt="" />
<div>影像图</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/yst.jpg')" alt="" />
<div>栅格深色</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/shy.png')" alt="" />
<div>三合一</div>
</div>
</el-carousel-item>
</el-carousel> -->
<!-- 地图缩放 -->
<div class="zoomTargetBox">
<el-input-number :min="7" :max="18" v-model="zoomTarget" :step="1" step-strictly @change="handleZoom"></el-input-number>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, defineProps, nextTick } from "vue";
import { MapUtil } from "./mapUtil";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
const conditionRoute = ref(true); //路况
const mMap = ref(null); //地图对象
const mapUtil = ref(null); //地图工具对象
const zoomTarget = ref(6);
const props = defineProps({
mapid: {
type: String,
default: "mapDiv"
},
//是否显示可以切换地图底图
isShow: {
type: Boolean,
default: false
},
//是否显示实时路况
isShowMvt: {
type: Boolean,
default: false
},
//是否显示地图层级
isShowZoom: {
type: Boolean,
default: false
},
//是否显示绘制控件
isShowDraw: {
type: Boolean,
default: false
}
});
try {
const userInfo = getItem("deptId")[0].deptCode;
} catch (error) { }
let map;
let mapLayer;
let mapLayer1;
onMounted(() => {
emitter.on("followUp", (res) => {
let box = document.getElementsByClassName("changeMap_box");
if (!box) return;
box[0].style.right = !res ? "4px" : "398px";
box[0].style.transition = "0.5s";
});
map = new EliMap({
id: props.mapid,
crs: "EPSG:4490",
style: {
glyphs: "./fonts/{fontstack}/{range}.pbf",
center: [94.36057012, 29.64276831],
zoom: 15
},
minZoom: 5,
maxZoom: 18,
});
window.map = map;
map.mapboxGLMap.on("load", () => {
map.addWMTSLayer(
"/PGIS_S_TileMapServer/Maps/XZDJ_DJ/EzMap"
,
{
Service: "getImage",
Type: "RGB",
ZoomOffset: "0",
V: "0.3",
Zoom: "{z}",
Row: "{y}",
Col: "{x}"
},
{
tileSize: 300
}
);
zoomTarget.value = map.mapboxGLMap.getZoom();
});
mapUtil.value = new MapUtil(map);
mapUtil.value.Drawplot(); //初始化加载绘制工具
// 设置地图中心点及图层
emitter.on("setMapCenter", (res) => {
mapUtil.value.setMapCenter(res.location, res.zoomLevel);
});
emitter.on("removePlot", (flag) => {
mapUtil.value.removePlot(flag);
});
emitter.on("removeAll", (flag) => {
mapUtil.value.removeAll(flag);
});
// 撒点
emitter.on("addPointArea", (obj) => {
mapUtil.value.makerSki(obj);
});
// 鼠标滑过提示文字的点位
emitter.on("showPoint", (obj) => {
mapUtil.value.showPoint(obj);
});
// 清除覆盖物
emitter.on("deletePointArea", (res) => {
mapUtil.value.removeElement(res);
});
// 清除某个覆盖物的单个
emitter.on("deletePointAreaOne", (obj) => {
mapUtil.value.removeElementOne(obj.flag, obj.id);
});
// 清除某个覆盖物的单个
emitter.on("showSquire", (obj) => {
mapUtil.value.zdySquire(obj);
});
// 绘制图形 - 回显区域
emitter.on("drawShape", (res) => {
mapUtil.value.plot(res, resFun);
});
emitter.on("removeEara", (flag) => {
mapUtil.value.removeEara(flag);
});
// 回显图形
emitter.on("echoPlane", (res) => {
mapUtil.value.echoPlane(res);
});
//移除绘制区域
emitter.on("removeEara", (flag) => {
mapUtil.value.removeEara(flag);
});
// 回显线
emitter.on("echoLine", (res) => {
mapUtil.value.createLine(res, res.flag);
});
//创建边界面geojson
emitter.on("setBoundarys", (res) => {
mapUtil.value.createBoundarys(res);
});
// 移除边界
emitter.on("removeBj", (res) => {
mapUtil.value.removeBj(res);
});
// 轨迹回放
emitter.on("drawLineAnimation", (res) => {
mapUtil.value.displayLineAnimation(res);
});
// 聚合撒点
emitter.on("addPoint", (obj) => {
mapUtil.value.aggregateScatteringPoint(obj);
});
// 热力图显示
emitter.on("thermodynamicChart", (res) => {
mapUtil.value.showHeatDrawing(res);
});
// 扩散圆
emitter.on("diffusionCircle", (res) => {
mapUtil.value.diffusionCircle(res);
});
// 展示盘曲
emitter.on("showGapText", (obj) => {
mapUtil.value.gapText(obj);
});
// 获取当前地图中心点
emitter.on("getCurrentCenter", (res) => {
let centerPoint = map.mapboxGLMap.getCenter();
let coords = [centerPoint.lng, centerPoint.lat];
emitter.emit("getcentercoord", coords);
});
});
//切换地图底图
const onMapImageChange = (val) => {
//清除已经存在胡地图图层
if (map.mapboxGLMap.getLayer("SGQS_ID"))
map.mapboxGLMap.removeLayer("SGQS_ID");
if (map.mapboxGLMap.getLayer("YX_ID")) map.mapboxGLMap.removeLayer("YX_ID");
if (map.mapboxGLMap.getLayer("SGSG_ID"))
map.mapboxGLMap.removeLayer("SGSG_ID");
if (map.mapboxGLMap.getLayer("TDT_TITLE_ID"))
map.mapboxGLMap.removeLayer("TDT_TITLE_ID");
if (map.mapboxGLMap.getLayer("TDT_ROAD_ID"))
map.mapboxGLMap.removeLayer("TDT_ROAD_ID");
if (map.mapboxGLMap.getLayer("TDT_POI_ID"))
map.mapboxGLMap.removeLayer("TDT_POI_ID");
//设置图层
switch (val) {
case 0:
mapSetLayer("SGQS_ID", "SGQS");
break;
case 1:
mapSetLayer("YX_ID", "YX");
break;
case 2:
mapSetLayer("SGSG_ID", "SGSG");
break;
case 3:
mapSetLayer("TDT_TITLE_ID", "TDT_TITLE_SOURCES");
mapSetLayer("TDT_ROAD_ID", "TDT_ROAD_SOURCES");
mapSetLayer("TDT_POI_ID", "TDT_POI_SOURCES");
break;
}
if (map.mapboxGLMap.getLayer("realTimeTrafficlevelOne"))
map.mapboxGLMap.moveLayer("realTimeTrafficlevelOne");
if (map.mapboxGLMap.getLayer("map_id")) map.mapboxGLMap.moveLayer("map_id");
if (map.mapboxGLMap.getLayer("map_ids")) map.mapboxGLMap.moveLayer("map_ids");
};
//设置图层函数
const mapSetLayer = (id, source) => {
map.mapboxGLMap.addLayer({ id, type: "raster", source });
};
//获取地图绘制的数据
const resFun = (coord, type, flag, data) => {
emitter.emit("coordString", {
coord: coord,
type: type,
flag: flag,
data: data
});
};
// 地图层级
const handleZoom = (val) => {
map.mapboxGLMap.setZoom(val);
};
// 是否打开或者关闭路况
const handleSwitch = (val) => {
if (val) {
// 打开
} else {
// 关闭
}
};
onUnmounted(() => {
emitter.off("removePlot");
emitter.off("setMapCenter");
emitter.off("addPointArea");
emitter.off("showPoint");
emitter.off("deletePointArea");
emitter.off("deletePointAreaOne");
emitter.off("drawShape");
emitter.off("echoPlane");
emitter.off("removeEara");
emitter.off("echoLine");
emitter.off("addPoint");
emitter.off("thermodynamicChart");
emitter.off("drawLineAnimation");
emitter.off("aggregateScatteringPoint");
emitter.off("hotmap");
emitter.off("setBoundarys");
emitter.off("diffusionCircle");
emitter.off("SsCircle");
emitter.off("ClearssCircle");
});
</script>
<style lang="scss" scoped>
.map {
width: 100%;
height: 100%;
background-color: aliceblue;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
z-index: 1;
}
.changeMap_box {
position: absolute;
right: 398px;
bottom: 4px;
z-index: 9;
.mapImageItem {
border: 1px solid #08aae8;
background: rgb(9, 26, 70);
&>img {
width: 100%;
height: 50px;
}
&>div {
text-align: center;
position: relative;
top: -3px;
}
}
.zoomTargetBox {
margin-top: 10px;
margin-left: 23px;
}
::v-deep .el-input-number__decrease,
::v-deep .el-input-number__increase {
background: #133362;
color: #fff;
border: none;
}
::v-deep .el-input__inner {
background: #0c1641;
}
}
</style>

View File

@ -94,7 +94,7 @@ onMounted(() => {
center: [94.36057012, 29.64276831],
zoom: 15
},
minZoom: 7,
minZoom: 5,
maxZoom: 18,
});
window.map = map;

View File

@ -37,7 +37,7 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted, defineProps, nextTick } from "vue";
import { ref, onMounted, onUnmounted, defineProps, nextTick, computed } from "vue";
import { MapUtil } from "./mapUtil";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
@ -70,8 +70,16 @@ const props = defineProps({
isShowDraw: {
type: Boolean,
default: false
},
// 地图唯一标识,用于隔离不同地图实例的操作
mapKey: {
type: String,
default: null
}
});
// 计算地图唯一标识如果没有传入则使用mapid
const uniqueMapKey = computed(() => props.mapKey || props.mapid);
try {
const userInfo = getItem("deptId")[0].deptCode;
} catch (error) {}
@ -104,7 +112,12 @@ onMounted(() => {
}
});
window.map = map;
// 移除全局挂载,避免不同地图实例冲突
// window.map = map;
// 将地图实例存储在组件内
mMap.value = map;
map.mapboxGLMap.on("load", () => {
map.addGaudLayer({
url: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
@ -113,56 +126,42 @@ onMounted(() => {
// 地图加载完成后发出事件
// emit('mapLoaded')
});
mapUtil.value = new MapUtil(map);
// map = new EliMap({
// id: props.mapid,
// crs: "EPSG:4490",
// style: {
// glyphs: "./fonts/{fontstack}/{range}.pbf",
// center: [94.36057012, 29.64276831],
// zoom: 15
// },
// minZoom: 7,
// maxZoom: 18,
// });
// window.map = map;
// map.mapboxGLMap.on("load", () => {
// map.addWMTSLayer(
// "/PGIS_S_TileMapServer/Maps/XZDJ_SL/EzMap"
// ,
// {
// Service: "getImage",
// Type: "RGB",
// ZoomOffset: "0",
// V: "0.3",
// Zoom: "{z}",
// Row: "{y}",
// Col: "{x}"
// },
// {
// tileSize: 300
// }
// );
// zoomTarget.value = map.mapboxGLMap.getZoom();
// });
// mapUtil.value = new MapUtil(map);
mapUtil.value.Drawplot(); //初始化加载绘制工具
// 为每个事件添加唯一标识过滤,确保只处理与当前地图实例相关的操作
// 设置地图中心点及图层
emitter.on("setMapCenter", (res) => {
emitter.on(`setMapCenter_${uniqueMapKey.value}`, (res) => {
mapUtil.value.setMapCenter(res.location, res.zoomLevel);
});
// 也保留原始事件,但添加条件判断
emitter.on("setMapCenter", (res) => {
// 如果事件包含flag并且与当前地图的唯一标识匹配或者没有指定flag则处理
if (!res.flag || res.flag === uniqueMapKey.value) {
mapUtil.value.setMapCenter(res.location, res.zoomLevel);
}
});
emitter.on("removePlot", (flag) => {
mapUtil.value.removePlot(flag);
});
emitter.on("removeAll", (flag) => {
mapUtil.value.removeAll(flag);
});
// 撒点
emitter.on("addPointArea", (obj) => {
mapUtil.value.makerSki(obj);
// 只处理与当前地图相关的标记点
if (!obj.baseFlag || obj.baseFlag === uniqueMapKey.value ||
obj.flag && obj.flag.includes(uniqueMapKey.value)) {
mapUtil.value.makerSki(obj);
}
});
// 鼠标滑过提示文字的点位
emitter.on("showPoint", (obj) => {
mapUtil.value.showPoint(obj);
@ -170,11 +169,23 @@ onMounted(() => {
// 清除覆盖物
emitter.on("deletePointArea", (res) => {
mapUtil.value.removeElement(res);
// 只清除与当前地图相关的覆盖物
if (typeof res === 'object' && res.baseFlag) {
if (res.baseFlag === uniqueMapKey.value) {
mapUtil.value.removeElement(res.baseFlag);
}
} else if (typeof res === 'string') {
if (res === uniqueMapKey.value || res.includes(uniqueMapKey.value)) {
mapUtil.value.removeElement(res);
}
}
});
// 清除某个覆盖物的单个
emitter.on("deletePointAreaOne", (obj) => {
mapUtil.value.removeElementOne(obj.flag, obj.id);
if (obj.flag === uniqueMapKey.value || obj.flag.includes(uniqueMapKey.value)) {
mapUtil.value.removeElementOne(obj.flag, obj.id);
}
});
// 清除某个覆盖物的单个

View File

@ -71,7 +71,7 @@ export function MapUtil(map) {
*/
MapUtil.prototype.makerSki = (res) => {
let { coords, icon, flag, showTitle } = res
let { coords, icon, flag, showTitle, size, offset } = res
if (!coords) return;
if (!_that._self[flag]) _that._self[flag] = []; //存储地图标识的容器
if (!_that.idsBox[flag]) _that.idsBox[flag] = []; //存储id的容器
@ -81,9 +81,9 @@ export function MapUtil(map) {
coords.forEach(item => {
let el = document.createElement("img");
el.src = item.icon || icon;
el.style.width = flag == 'kfd' ? '32px' : "25px";
el.style.width = size ? size : "25px";
if (flag.includes('jczMap_')) el.style.width = '45px';
if (showTitle) _that.makerShowTitle(item, [item.jd, item.wd], flag) //展示标题
if (showTitle) _that.makerShowTitle(item, [item.jd, item.wd], flag, '', offset) //展示标题
const marker = map.Marker(el, [item.jd, item.wd], { anchor: 'bottom', offset: [0, 0] })
el.addEventListener("click", () => {
_that.openInfoDetail(flag, item) //点击打开详情
@ -141,7 +141,8 @@ export function MapUtil(map) {
}
// 信息框展示
MapUtil.prototype.makerShowTitle = (item, points, flag, text) => {
MapUtil.prototype.makerShowTitle = (item, points, flag, text, offset) => {
let T = flag == 'rx' ? 'rxTitle' : 'Title'
let flagT = flag + T;
if (!_that._self[flagT]) _that._self[flagT] = [];
@ -150,11 +151,25 @@ export function MapUtil(map) {
let textTitle = item.jzMc ? item.jzMc : item.fzrXm + '警组';
if (flag == 'sbwz_car' || flag == 'sbwz_sb' || flag == 'sbwz_zfjly') textTitle = item.sbmc;
if (flag == 'gapText') textTitle = text;
if (flag == 'bxd' || flag == "search_bxd") textTitle = item.bxdMc;
// 设置样式
const el = document.createElement('div');
if (flag == 'hm') {
// 直接设置元素样式属性,避免对象赋值的兼容性问题
el.style.fontSize = '12px';
el.style.color = '#ffffffff';
el.style.fontWeight = 'bold';
el.style.textAlign = 'center';
el.style.backgroundColor = '#1891ff82';
el.style.padding = '2px';
// 添加额外的样式属性以确保良好的显示效果
el.style.borderRadius = '4px';
el.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.3)';
el.style.zIndex = '1000';
}
el.className = 'makerTitle';
if (flag == 'sbwz_car' || flag == 'sbwz_sb' || flag == 'sbwz_zfjly') el.className = 'makerTitlezb';
if (flag == 'sbwz_car' || flag == 'sbwz_sb' || flag == 'sbwz_zfjly' || flag == 'bxd' || flag == "search_bxd") el.className = 'makerTitlezb';
if (flag == 'rx') {
if (item.xfzt == '0') el.classList.add('makerTitleLine');
else if (item.xfzt == '1') el.classList.add('makerTitlecj');
@ -164,7 +179,7 @@ export function MapUtil(map) {
// 渲染
el.innerHTML = textTitle;
const marker = map.Marker(el, points, { anchor: 'bottom', offset: [0, -50] })
const marker = map.Marker(el, points, { anchor: 'bottom', offset: offset ? offset : [0, -50] })
_that._self[flagT].push(marker)
}
@ -186,7 +201,7 @@ export function MapUtil(map) {
let list = []
let cl = (pbcl && pbcl.length > 0) ? true : false; // 车辆
let zb = (txzb && txzb.length > 0) ? true : false; // 智能装备
let qx = (jyqx && jyqx.length > 0) ? true : false; // 警用器械
let qx = (jyqx && jyqx.length > 0) ? true : false; // 常用装备
if (zb) {
let el = document.createElement("img");
el.style.width = "15px"
@ -316,11 +331,14 @@ export function MapUtil(map) {
// 清除所有
MapUtil.prototype.removeAll = () => {
for (let key in _that._self) {
console.log(key, 'key');
if (key != 'rx' && key != 'gpsZb' && !key.includes('rxTitle')) {
let list = _that._self[key]
for (let i = 0; i < list.length; i++) {
const el = list[i];
console.log(el, 'el');
if (el && typeof el == 'object') el.destroy() //destory()销毁 , show(false) false:隐藏 true :展示
else _that.removePlot(key)
}
_that._self[key] = [];
}
@ -686,31 +704,90 @@ export function MapUtil(map) {
* ]
};
*/
// MapUtil.prototype.createBoundarys = (res) => {
// let { data } = res
// if (!data) return false;
// if (_that.polygonGeo) _that.removeBj();
// _that.polygonGeo = map.createPolygon(data, {
// color: 'rgba(20,237,245,0.3)',
// outLineColor: '#cf1010',
// outLineWidth: 6,
// highlightColor: 'red',
// type: 'solid',
// labelOption: {
// pixelOffset: [2, 0],
// allShow: false,
// fontColor: '#ffffff'
// }
// })
// _that.polygonGeo.flyTo()
// }
// 移除边界
MapUtil.prototype.createBoundarys = (res) => {
let { data } = res
let { data, color, fillColor, borderColor, label, text, labelPosition } = res
if (!data) return false;
if (_that.polygonGeo) _that.removeBj();
_that.polygonGeo = map.createPolygon(data, {
color: 'rgba(20,237,245,0.3)',
outLineColor: '#cf1010',
outLineWidth: 6,
highlightColor: 'red',
// 使用传入的颜色参数,如果没有则使用默认值
const fillColorValue = fillColor || 'rgba(27, 205, 211, 0.3)';
const borderColorValue = borderColor || '#cf1010';
const highlightColorValue = color || 'red';
// 创建多边形
const polygon = map.createPolygon(data, {
color: fillColorValue,
outLineColor: borderColorValue,
outLineWidth: 5,
highlightColor: highlightColorValue,
type: 'solid',
labelOption: {
content: label || text || '222222', // 标签文字内容
position: labelPosition || 'center', // 标签位置
pixelOffset: [2, 0],
allShow: false,
fontColor: '#ffffff'
allShow: true, // 设置为true以显示所有标签
fontColor: '#ffffff',
fontSize: 14,
fontWeight: 'bold',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
padding: [5, 10],
borderRadius: 4
}
})
_that.polygonGeo.flyTo()
// 将多边形添加到已创建的边界列表中
if (!_that.boundaryList) {
_that.boundaryList = [];
}
_that.boundaryList.push(polygon);
// 如果是第一个添加的区域,则飞过去
if (_that.boundaryList.length === 1) {
polygon.flyTo();
}
}
// 移除边界
MapUtil.prototype.removeBj = (res) => {
_that.polygonGeo.destroy()
// 移除单个polygonGeo为了向后兼容
if (_that.polygonGeo) {
_that.polygonGeo.destroy();
_that.polygonGeo = null;
}
// 移除所有添加到boundaryList中的多边形
if (_that.boundaryList && _that.boundaryList.length > 0) {
_that.boundaryList.forEach(polygon => {
polygon.destroy();
});
_that.boundaryList = [];
}
}
// 打开详情弹窗
MapUtil.prototype.openInfoDetail = (flag, data) => {
console.log(flag, data);
switch (flag) {
case 'home_yj_map':
console.log(data);
@ -720,6 +797,14 @@ export function MapUtil(map) {
console.log(data);
emitter.emit("showHomeWarning", data);
break;
case 'jczMap_hm':
console.log(data);
emitter.emit("showJcz", data);
break;
case 'sp':
console.log(data);
emitter.emit("showGzyInfo", data);
break;
}
}
}

View File

@ -1,20 +1,33 @@
<template>
<div class="form-item-box" :class="props.showBtn ? 'showBtn-upload' : ''" :style="{ width: width }">
<el-upload v-bind="$attrs" :headers="headers" :multiple="false" class="avatar-uploader" :limit="props.limit"
:action="actionUrl" :list-type="props.showBtn ? '' : 'picture-card'" :file-list="fileList" show-file-list
:on-exceed="handleExceed" :on-success="handlerSuccess" :before-upload="beforeImgUpload">
<el-upload
v-bind="$attrs"
:headers="headers"
:multiple="false"
class="avatar-uploader"
:limit="props.limit"
:action="actionUrl"
:list-type="props.showBtn ? '' : 'picture-card'"
:file-list="fileList"
show-file-list
:before-remove="beforeRemove"
:on-exceed="handleExceed"
:on-success="handlerSuccess"
:before-upload="beforeImgUpload">
<template #default>
<el-button v-if="props.showBtn" size="small" type="primary">上传文件</el-button>
<el-icon v-else>
<Plus />
</el-icon>
<el-icon v-else><Plus /></el-icon>
</template>
<template #file="{ file }" v-if="!props.showBtn">
<div v-if="props.isImg">
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)"><el-icon> <zoom-in /></el-icon></span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file, fileList)"><el-icon><Delete /></el-icon></span>
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<el-icon> <zoom-in /></el-icon>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file, fileList)">
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
<div v-else>
@ -24,14 +37,10 @@
</div>
<span class="el-upload-list__item-actions">
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownload(file)">
<el-icon>
<Download />
</el-icon>
<el-icon><Download /></el-icon>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file, fileList)">
<el-icon>
<Delete />
</el-icon>
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
@ -45,7 +54,7 @@
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import { ref, defineProps, defineEmits, computed, watch, onMounted } from "vue";
import { ref, defineProps, defineEmits, computed, watch, onMounted, onUnmounted } from "vue";
import { ElMessage } from "element-plus";
import { useStore } from "vuex";
const props = defineProps({
@ -72,9 +81,30 @@ const props = defineProps({
},
isAll: {
type: Boolean,
default: false
default: true //所有类型都可以用这个接口接口返回的是id
}
});
const emits = defineEmits(["update:modelValue"]);
const store = useStore();
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const disabled = ref(false);
const headers = ref({
Authorization: store.getters.token
});
const fileList = ref([]);
watch(() => props.modelValue,(val) => {
let arr = val ? (Array.isArray(val) ? val :[val]): [];
if(arr.length == 0 ) return fileList.value = [];
fileList.value = arr.map((el) => {
if (Object.prototype.toString.call(el) === "[object Object]") {
return props.isAll ? { url: `/mosty-api/mosty-base/minio/image/download/` + el.id, name: el.name ,id : el } : { url:el,name:el.name , id : el};
} else {
return { url: `/mosty-api/mosty-base/minio/image/download/` + el,id : el };
}
});
},{ immediate: true,deep:true });
const actionUrl = computed(() => {
if (props.isAll) {
@ -84,8 +114,6 @@ const actionUrl = computed(() => {
}
});
const emits = defineEmits(["update:modelValue", "handleChange"]);
//获取后缀
const getSuffix = (fileName) => {
let suffix = "";
@ -108,101 +136,37 @@ const getSuffix = (fileName) => {
//excel XLS
const excelist = ["xls", "xlsx"];
if (excelist.includes(suffix)) return "XLS";
// 匹配 word
var wordlist = ["doc", "docx"];
if (wordlist.includes(suffix)) return "DOC";
//pdf
if (suffix === "pdf") return "PDF";
//视频 音频
var videolist = [
"mp4",
"m2v",
"mkv",
"rmvb",
"wmv",
"avi",
"flv",
"mov",
"m4v"
];
var videolist = ["mp4","m2v","mkv","rmvb","wmv","avi","flv","mov","m4v"];
if (videolist.includes(suffix)) return "VIDEO";
var musiclist = ["mp3", "wav", "wmv"];
if (musiclist.includes(suffix)) return "MUSIC";
var pptlist = ["ppt", "pptx"];
if (pptlist.includes(suffix)) return "PPT";
//压缩包
var yslist = ["7z", "rar", "zip", "apz", "ar", "hpk", "hyp", "hbc2"];
if (yslist.includes(suffix)) return "YS";
//否则返回other
return "OTHER";
};
const store = useStore();
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const disabled = ref(false);
const headers = ref({
Authorization: store.getters.token
});
const fileList = ref([]);
watch(
() => props.modelValue,
(val) => {
let arr = val ? val : [];
if (arr && arr.length > 0) {
if (!props.sfUrl) {
if (Array.isArray(arr)) {
fileList.value = arr.map((el) => {
if (Object.prototype.toString.call(el) === "[object Object]") {
return {
url: `/mosty-api/mosty-base/minio/image/download/` + el,
name: el.name
};
} else {
return { url: `/mosty-api/mosty-base/minio/image/download/` + el };
}
});
} else {
const fjListData=arr.split(',')
fileList.value = fjListData.map((el) => {
if (Object.prototype.toString.call(el) === "[object Object]") {
return {
url: `/mosty-api/mosty-base/minio/image/download/` + el,
name: el.name
};
} else {
return { url: `/mosty-api/mosty-base/minio/image/download/` + el };
}
});
}
} else {
fileList.value = arr.map((el) => {
if (Object.prototype.toString.call(el) === "[object Object]") {
return { url: el, name: el.name };
} else {
return { url: el };
}
});
}
}
},
{ immediate: true }
);
const handlerSuccess = (res, file) => {
file.url = `/mosty-api/mosty-base/minio/image/download/` + res.data;
// file.url = `/mosty-api/mosty-base/minio/image/download/` + res.data;
file.id = res.data;
fileList.value.push(file);
let arr = props.modelValue ? props.modelValue : [];
arr.push(res.data);
let arr = []
if(props.isImg){
arr = fileList.value.map((el) => el.id)
}else{
arr = fileList.value.map((el) => ({ id:el.id, name:el.name}))
}
emits("update:modelValue", arr);
emits("handleChange", props.modelValue);
};
const handleExceed = (files, fileList) => {
@ -212,16 +176,10 @@ const handleExceed = (files, fileList) => {
const beforeImgUpload = (file) => {
if (props.isImg) {
let isIMG = false;
if (getSuffix(file.name) === "IMG") {
isIMG = true;
}
if (getSuffix(file.name) === "IMG") isIMG = true;
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isIMG) {
ElMessage.error("上传图片只能是jpg/png/jpeg/bmp/gif格式!");
}
if (!isLt5M) {
ElMessage.error("上传图片大小不能超过 5MB!");
}
if (!isIMG) ElMessage.error("上传图片只能是jpg/png/jpeg/bmp/gif格式!");
if (!isLt5M) ElMessage.error("上传图片大小不能超过 5MB!");
return isIMG && isLt5M;
} else {
return true;
@ -235,16 +193,25 @@ const handlePictureCardPreview = (file) => {
const handleDownload = (file) => {
window.open(file.response.data);
};
// 删除文件 触发父组件更新
const beforeRemove = (file) => {
let index = fileList.value.findIndex(function (item) {
return item.id === file.id;
});
props.modelValue.splice(index, 1);
emits("update:modelValue", props.modelValue);
}
const handleRemove = (file) => {
let index = fileList.value.findIndex(function (item) {
return item.url === file.url;
return item.id === file.id;
});
fileList.value.splice(index, 1);
props.modelValue.splice(index, 1);
emits("handleChange", props.modelValue);
emits("update:modelValue", props.modelValue);
};
const propsModelValue = ref();
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,201 @@
<!--
* @Date: 2025-08-06 14:49:49
* @Description: 系统切换窗口
-->
<template>
<el-dialog
v-model="model"
class="switch-sys-dialog"
modal-class="switch-sys-dialog-modal"
:show-close="false"
width="1600"
align-center
append-to-body
destroy-on-close
custom-class="switch-sys-dialog-modal"
>
<div class="switch-sys-dialog__content">
<div class="nav prev" @click="prev">
<el-icon>
<ArrowLeftBold />
</el-icon>
</div>
<div class="carousel">
<div
:class="['card-item', { active: currentIndex === index }]"
v-for="(item, index) in list"
:key="item.value"
:style="getCardStyle(index)"
@click="goPage(item, index)"
>
<img :src="item.icon" class="card-item__img" />
<div class="card-item__label">{{ item.label }}</div>
</div>
</div>
<div class="nav next" @click="next">
<el-icon>
<ArrowRightBold />
</el-icon>
</div>
</div>
</el-dialog>
</template>
<script setup>
import {ref} from 'vue'
// 引入的本地图片
import fk from '@/assets/images/fk.png'
import ty from '@/assets/images/ty.png'
import pcs from '@/assets/images/pcs.png'
// 控制弹框显示或者隐藏
// const model = defineModel({ type: Boolean, default: false })
const props = defineProps({
model: {
type:Boolean,
default:false
}
})
const emit=defineEmits(['update:model'])
const list = [
{ label: '俯瞰系统', value: 1, url: `https://tyyy.lz.dsj.xz/overlooking/home`, icon: fk },
{ label: '统一门户', value: 2, url: 'https://tyyy.lz.dsj.xz/portal/home', icon: ty },
{ label: '智慧派出所', value: 3, url: 'https://pcs.lz.dsj.xz:9020/index.html', icon: pcs },
]
const currentIndex = ref(1)
const prev = () => {
currentIndex.value = (currentIndex.value - 1 + list.length) % list.length
}
const next = () => {
currentIndex.value = (currentIndex.value + 1) % list.length
}
const getCardStyle = index => {
const total = list.length
const offset = index - currentIndex.value
let style = {
opacity: 1,
zIndex: 1,
transform: '',
left: '50%',
}
// 循环时计算偏移
let relativeOffset = offset
if (offset < -1) relativeOffset += total
if (offset > 1) relativeOffset -= total
if (relativeOffset === 0) {
// 中间
style.zIndex = 3
style.transform = 'translateX(0) translateY(-50%) scale(1) rotateY(0deg) translateX(-50%)'
} else if (relativeOffset === -1) {
// 左边
style.zIndex = 2
style.transform = 'translateX(-500px) translateY(-50%) scale(0.8) rotateY(25deg) translateX(-50%)'
} else if (relativeOffset === 1) {
// 右边
style.zIndex = 2
style.transform = 'translateX(360px) translateY(-50%) scale(0.8) rotateY(-25deg) translateX(-50%)'
} else {
style.opacity = 0
style.transform = 'translate(-50%, -50%) scale(0.5)'
}
return style
}
const goPage = (item, index) => {
if (index === currentIndex.value) {
if (item.url) {
window.open(item.url, '_blank')
}
}
}
</script>
<style lang="scss">
.switch-sys-dialog {
--el-bg-color: transparent;
--el-box-shadow: none;
}
.switch-sys-dialog-modal {
background-color: #ffffff00 ;
}
</style>
<style lang="scss" scoped>
.switch-sys-dialog {
&__content {
display: grid;
grid-template-columns: auto 1fr auto;
width: inherit;
height: 335px;
align-items: center;
.carousel {
position: relative;
width: 100%;
height: 100%;
.card-item {
position: absolute;
top: 50%;
transition: all 0.5s ease;
transform-origin: center center;
opacity: 0;
border-radius: 10px;
overflow: hidden;
user-select: none;
cursor: pointer;
&.active {
box-shadow: 0 0 80px 50px rgba(var(--text-color-black-rgb), 0.6);
.card-item__label {
padding: 5px 0;
color: var(--theme-text-color);
font-weight: bold;
}
}
&__img {
width: 520px;
height: 293px;
object-fit: cover;
}
&__label {
background-color: #ffffff;
text-align: center;
color: var(--text-color-black);
transition: all 0.5s ease;
}
}
}
.nav {
display: flex;
justify-content: center;
align-items: center;
font-size: 32px;
color: var(--text-color);
cursor: pointer;
}
}
}
.iframe-container {
::v-deep .el-dialog__header {
background-color: rgb(4 35 74) !important;
height: 50px;
padding: 0 !important;
}
::v-deep .el-dialog__body {
padding: 0 !important;
}
}
</style>

View File

@ -20,7 +20,7 @@
</template>
<!-- 上传 upload -->
<MOSTY.Upload v-else-if="item.type == 'upload'" width="100%" v-model="listQuery[item.prop]" :isImg="item.isImg" :disabled="item.disabled" />
<MOSTY.Upload v-else-if="item.type == 'upload'" width="100%" v-model="listQuery[item.prop]" :isImg="item.isImg" :limit="item.limit" :disabled="item.disabled" />
<!--选择checkbox -->
<MOSTY.CheckBox v-else-if="item.type == 'checkbox'" width="100%" clearable v-model="listQuery[item.prop]" :checkList="item.options" :placeholder="`请选择${item.label}`" :disabled="item.disabled" />

View File

@ -8,7 +8,8 @@
:highlight-current-row="getConfiger.showSelectType === 'radio'"
:row-style="{ height: getConfiger.rowHeight === 'auto' ? getConfiger.rowHeight : getConfiger.rowHeight + 'px' }">
<el-table-column style="width: 55px" type="selection" width="55" v-if="getConfiger.showSelectType" :class="getConfiger.showSelectType === 'radio' ? 'tabBoxRadio' : ''" />
<!-- 修改v-if条件让showSelectType为null时也能显示选择列默认为复选框 -->
<el-table-column style="width: 55px" type="selection" width="55" v-if="getConfiger.showSelectType !='null'" :class="getConfiger.showSelectType === 'radio' ? 'tabBoxRadio' : ''" />
<el-table-column type="index" label="序号" v-if="getConfiger.showIndex" width="60" :align="getConfiger?.align" />

View File

@ -1,5 +1,5 @@
<template>
<el-dialog :title="titleValue" width="1500px" :model-value="modelValue" append-to-body @close="closed">
<el-dialog :title="titleValue" width="1500px" :model-value="props.modelValue" append-to-body @close="closed">
<div class="table_class">
<div style="width: 48%">
<el-tabs v-model="activeTab" type="card" @tab-click="handleTabClick">

View File

@ -1,5 +1,5 @@
<template>
<el-dialog v-model="modelValue" :destroy-on-close="true" :title="title+'人员'" @close="close" :close-on-click-modal="false">
<el-dialog v-model="props.modelValue" :destroy-on-close="true" :title="title+'人员'" @close="close" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform" :rules="rules">
<template #bqList>
<div class="marks pointer" @click="chooseMarksVisible = true">

View File

@ -241,7 +241,6 @@ const qcckPostList = async () => {
const data = {}
const listError = []
for (let i = 0; i < checkListData.value.length; i++) {
if (Array.isArray(checkListData.value[i].userList)) {
for (let j = 0; j < checkListData.value[i].userList.length; j++) {
const item = checkListData.value[i].userList[j]
@ -318,7 +317,6 @@ const endpoints = [
const queryModel = async () => {
try {
loading.value = true
// 查询模型信息
const params = {
modelId: props.radioData,
@ -341,8 +339,11 @@ const queryModel = async () => {
const eventNode = resData[1].rows.find(item =>
item.nodeType === '1' && item.nodeId === sequenceNode.targetNodeId
)
const orgId = 'a8aa5ed229724b278faa7abd0f0cceb6'
// getItem('userOrg').parentid
const orgId = getItem('deptId')[0].fzOrgId
if (!orgId) {
proxy.$message({ type: "error", message: "查询模型失败,请重试" })
return
}
if (eventNode) {
// 处理事件节点
await handleEventNode(eventNode, orgId)
@ -360,7 +361,6 @@ const queryModel = async () => {
const optional=ref(false)
// 处理事件节点
const handleEventNode = async (eventNode, orgId) => {
const nodeExtension = JSON.parse(eventNode.nodeExtension)
modelData.value = [eventNode]
checkList.value = [eventNode.nodeId]
@ -372,13 +372,20 @@ const handleEventNode = async (eventNode, orgId) => {
orgid: ""
}
if (nodeExtension.flwsUserNode.orgType == 'brothers') {
console.log(1);
orgData = await queryListByEntity({ id: orgId })
} else if (nodeExtension.flwsUserNode.orgType == 'parent') {
console.log(2);
orgData = await querysingleByEntity({ id: orgId })
} else if (nodeExtension.flwsUserNode.orgType == 'parents') {
console.log(3);
orgData = await queryUporgsByEntity({ id: orgId })
} else if (nodeExtension.flwsUserNode.orgType == 'appoint') {
console.log(4);
// orgData = await queryUporgsByEntity({ orgcode: orgId })
console.log(orgData);
}
if (nodeExtension.flwsUserNode.orgType == 'appoint') {
promes.roles = roles
@ -424,7 +431,6 @@ const handleEventNode = async (eventNode, orgId) => {
// 处理普通节点
const handleNormalNodes = async (resData, sequenceNode, orgId) => {
const targetNodeIds = resData[2].rows
.filter(item => item.sourceNodeId === sequenceNode.targetNodeId)
.map(item => item.targetNodeId)
@ -468,6 +474,7 @@ const handleNormalNodes = async (resData, sequenceNode, orgId) => {
})
promesList[modelData.value[i].nodeId] = list
} else if (str.flwsUserNode.orgType == 'appoint') {
list = [{
posts: str.flwsUserNode.post[0] ? str.flwsUserNode.post[0] : '',
roles: str.flwsUserNode.role[0] ? str.flwsUserNode.role[0] : '',
@ -543,14 +550,11 @@ function filterUsersWithOrgInfo(orgsData, checkList) {
const sendMessage = (gzlid) => {
let letDataCheck = []
let userList = []
console.log(checkListData.value);
for (let i = 0; i < checkListData.value.length; i++) {
letDataCheck = [...letDataCheck, ...checkListData.value[i].checkList]
userList.push(checkListData.value[i].userList)
}
console.log(letDataCheck);
console.log(userList);
const bkshrSfzh = filterUsersWithOrgInfo(userList, letDataCheck).map(item => {
return {
bkshrXm: item.username,

View File

@ -67,7 +67,6 @@ const lyquery = reactive({
promes: {
page: 1,
rows: 100,
// orgCode:deptId[0].orgCode
modelName: props.userData.modelName
}
@ -78,7 +77,7 @@ const qcckGetList = () => {
const prrmes = {
...lyquery.promes
}
splGet(prrmes, '/model/queryModel').then(res => {
splPost(prrmes, '/model/queryModel').then(res => {
lyquery.rows = lyquery.promes.page == 1 ? res.rows : lyquery.rows.concat(res.rows)
lyquery.total = res.total
})
@ -87,12 +86,18 @@ const Sfzh = getItem('idEntityCard')
const qcckGetCount = () => {
if (!getItem('cookie')) {
qcckGet({ sfzh: Sfzh }, '/mosty-base/fzmsg/getCokie', true).then(res => {
setCookie('clientKey', res.cookie.substring(10, res.length))
if (res.cookie) {
setCookie('clientKey', res.cookie.substring(10, res.length))
} else {
setCookie('clientKey', res.substring(10, res.length))
}
qcckGetList()
})
} else { qcckGetList() }
}
watch(() => props.modelValue, (newVal) => {
if (newVal) {
qcckGetCount()
@ -102,8 +107,8 @@ const createProcess = ref({})
const radioData = ref('')
// const InterfaceAddress = 'http://192.168.0.231:8006/mosty-api/mosty-gsxt/'
// const InterfaceAddress = 'http://192.168.0.231:8006/mosty-api/mosty-gsxt/'
// const InterfaceAddress = 'http://155.540.22.30:50037/mosty-api/mosty-gsxt/'
const InterfaceAddress = 'http://192.168.1.32:8006/mosty-api/mosty-gsxt/'
const InterfaceAddress = 'http://155.540.22.30:50037/mosty-api/mosty-gsxt/'
// const InterfaceAddress = 'http://192.168.1.32:8006/mosty-api/mosty-gsxt/'
const changeRadio = (e) => {
radioData.value = e
const item = lyquery.rows.find(item => item.modelId == e)

View File

@ -7,7 +7,7 @@
<Editor :style="`height: ${props.heightNumber}px; overflow-y: hidden`" v-model="textContent" :defaultConfig="editorConfig" :mode="mode" @onCreated="handleCreated" @onChange="handChange" />
</div>
<template #footer>
<el-button type="primary" @click="SaveReport">保存</el-button>
<!-- <el-button type="primary" @click="SaveReport">保存</el-button> -->
<!-- <el-button type="primary" @click="downloadWithStyles">历史报告</el-button> -->
<el-button type="primary" @click="downloadWithStyles">下载</el-button>
<el-button type="primary" @click="close">取消</el-button>

View File

@ -56,12 +56,13 @@ onMounted(() => {
active.value = "LZ";
});
const logout = () => {
window.opener = null;
window.open('', '_self');
window.close();
store.commit("app/clearTag", null, { immediate: true });
store.commit("permission/deleteRouter", { immediate: true });
store.commit("user/deleteKeepLiiveRoute", "home");
store.dispatch("user/logout");
// window.opener = null;
// window.open('', '_self');
// window.close();
// store.commit("app/clearTag", null, { immediate: true });
// store.commit("permission/deleteRouter", { immediate: true });
// store.commit("user/deleteKeepLiiveRoute", "home");
};
</script>

View File

@ -1,19 +1,8 @@
<template>
<el-menu
class="el-menu-vertical-demo"
:collapse="!$store.getters.sidebarOpened"
:default-active="activeMenu"
:unique-opened="true"
background-color="rgba(0, 0, 0, 0)"
:text-color="$store.getters.cssVar.menuText"
:active-text-color="$store.getters.cssVar.menuActiveText"
router
>
<SideBarItem
v-for="item in routes"
:key="item.path"
:route="item"
></SideBarItem>
<el-menu class="el-menu-vertical-demo" :collapse="!$store.getters.sidebarOpened" :default-active="activeMenu"
:unique-opened="true" background-color="rgba(0, 0, 0, 0)" :text-color="$store.getters.cssVar.menuText"
:active-text-color="$store.getters.cssVar.menuActiveText" router>
<SideBarItem v-for="item in routes" :key="item.path" :route="item"></SideBarItem>
</el-menu>
</template>
@ -27,7 +16,19 @@ const store = useStore();
const router = useRouter();
const routes = computed(() => {
const fRoutes = filterRoutes(router.getRoutes());
return generateMenus(fRoutes);
const data = fRoutes.filter(item => {
if (item.name != "warningLists"
&& item.name != "behaviorWarnings"
&& item.name != "identityWarnings"
&& item.name != "combinedWarnings"
&& item.name != "DeploymentAreas"
&& item.name != "mpvPeos"
&& item.name != "myControls") {
return item;
}
}
)
return generateMenus(data);
});
if (!store.getters.token) {
router.push("/login");
@ -50,27 +51,28 @@ const activeMenu = computed(() => {
::v-deep .el-menu-item {
height: 48px;
}
::v-deep .el-sub-menu__title {
height: 48px;
color: rgb(255, 255, 255);
background-color: rgb(20, 46, 78);
}
::v-deep .el-menu-item.is-active {
background-image: linear-gradient(to right,#2356d4 0% ,#8efbde 100%);
background-image: linear-gradient(to right, #2356d4 0%, #8efbde 100%);
margin: 0 14px;
border-radius: 4px;
// padding-left: 46px !important;
}
::v-deep .el-sub-menu .el-menu-item {
height: 48px;
line-height: 48px;
}
</style>
<style>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 281px;
min-height: 400px;
}
</style>

View File

@ -1,5 +1,6 @@
import * as ElIcons from "@element-plus/icons-vue";
import Axios from 'axios'
import {
createApp
} from "vue";
@ -11,6 +12,7 @@ import plugins from "./plugins";
import "./assets/css/element-plus.scss";
import "./assets/css/layout.scss";
import "./assets/css/pulic.scss";
import "vue3-emoji/dist/style.css";
import ELMessage from 'element-plus'
import InfiniteScroll from './utils/lazyLoad'
import Directive from './utils/directive';

View File

@ -174,6 +174,58 @@ export const publicRoutes = [
name: "focusExploration",
component: () => import("@/views/backOfficeSystem/ApprovalInformation/FocusExploration/index.vue"),
},
//开放到派出所路由
{
path: "/warningLists",
name: "warningLists",
component: () => import("@/views/backOfficeSystem/fourColorManage/warningList/index"),
meta: {
title: "布控预警",
icon: "article"
}
}, {
path: "/behaviorWarnings",
name: "behaviorWarnings",
meta: { title: "行为预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/behaviorWarning/index"),
},
{
path: "/identityWarnings",
name: "identityWarnings",
meta: { title: "身份预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/identityWarning/index"),
},
{
path: "/combinedWarnings",
name: "combinedWarnings",
meta: { title: "组合预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/combinedWarning/index"),
},
{
path: "/mpvPeos",
name: "mpvPeos",
component: () => import("@/views/backOfficeSystem/DeploymentDisposal/mpvPeo/index"),
meta: {
title: "重点人管理",
icon: "article"
}
}, {
path: "/myControls",
name: "myControls",
component: () => import("@/views/backOfficeSystem/IntelligentControl/myControl/index"),
meta: {
title: "我的布控",
icon: "article"
}
}, {
path: "/DeploymentAreas",
name: "DeploymentAreas",
component: () => import("@/views/backOfficeSystem/IntelligentControl/DeploymentArea/index"),
meta: {
title: "布控区域",
icon: "article"
}
},
{
path: "/editPassword", // 注意:带有路径“/”的记录中的组件“默认”是一个不返回 Promise 的函数
redirect: "/IdentityManage",
@ -229,12 +281,13 @@ export const publicRoutes = [
meta: { title: "组合预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/combinedWarning/index"),
},
// {
// path: "/modelWarning",
// name: "modelWarning",
// meta: { title: "模型预警", icon: "article" },
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/modelWarning/index"),
// },
{
path: "/modelWarning",
name: "modelWarning",
meta: { title: "模型预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/modelWarning/index"),
}, {
path: "/tsypHome",
name: "tsypHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/tsypHome/index"),
@ -244,7 +297,6 @@ export const publicRoutes = [
}
},
]
},
{
path: "/IdentityManage",
@ -426,14 +478,29 @@ export const publicRoutes = [
{
path: "/CollectCrculate",
name: "CollectCrculate",
component: () =>
import(
"@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"
),
meta: {
title: "人力情报管理",
icon: "article"
}
meta: { title: "人力情报信息报送", icon: "article" },
redirect: "/CollectCrculate",
children: [
{
path: "/CollectCrculate",
name: "CollectCrculate",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"),
meta: { title: "警务工作报送", icon: "article" },
},
{
path: "/socialInformationCrculate",
name: "socialInformationCrculate",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"),
meta: { title: "社会信息员报送", icon: "article" },
},
{
path: "/lamCrculate",
name: "lamCrculate",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"),
meta: { title: "林安码报送", icon: "article" },
}
]
},
{
path: "/RlStatisticalAnalysis",
@ -468,7 +535,7 @@ export const publicRoutes = [
"@/views/backOfficeSystem/HumanIntelligence/ConstructionManagement/index"
),
meta: {
title: "社会信息人员建设管理",
title: "力量建设管理",
icon: "article"
}
},
@ -481,15 +548,15 @@ export const publicRoutes = [
icon: "article"
}
},
{
path: "/MakeAcomment",
name: "MakeAcomment",
component: () => import("@/views/backOfficeSystem/MakeAcomment/index"),
meta: {
title: "情报评一评",
icon: "article"
}
}
// {
// path: "/MakeAcomment",
// name: "MakeAcomment",
// component: () => import("@/views/backOfficeSystem/MakeAcomment/index"),
// meta: {
// title: "情报评一评",
// icon: "article"
// }
// }
]
},
{
@ -564,15 +631,15 @@ export const publicRoutes = [
icon: "article"
}
},
{
path: "/analysisReport",
name: "AnalysisReport",
component: () => import("@/views/backOfficeSystem/AnalysisReport/index"),
meta: {
title: "研判报告",
icon: "article"
}
},
// {
// path: "/analysisReport",
// name: "AnalysisReport",
// component: () => import("@/views/backOfficeSystem/AnalysisReport/index"),
// meta: {
// title: "研判报告",
// icon: "article"
// }
// },
{
path: "/MeetingRoom",
name: "MeetingRoom",
@ -670,16 +737,16 @@ export const publicRoutes = [
// icon: "article"
// }
// },
{
path: "/experienceShare",
name: "experienceShare",
component: () =>
import("@/views/backOfficeSystem/BasicManagement/experienceShare/index"),
meta: {
title: "经验分享",
icon: "article"
}
},
// {
// path: "/experienceShare",
// name: "experienceShare",
// component: () =>
// import("@/views/backOfficeSystem/BasicManagement/experienceShare/index"),
// meta: {
// title: "经验分享",
// icon: "article"
// }
// },
{
path: "/policeReport",
@ -690,7 +757,23 @@ export const publicRoutes = [
icon: "article"
}
},
{
path: "/calendar",
name: "calendar",
component: () => import("@/views/backOfficeSystem/calendar/index.vue"),
meta: {
title: "敏感节点",
icon: "article"
}
}, {
path: "/forumPost",
name: "forumPost",
component: () => import("@/views/forumPost/index.vue"),
meta: {
title: "情报论坛",
icon: "article"
}
},
]
}
]

View File

@ -224,11 +224,11 @@ export default {
this.commit("permission/deleteRouter");
removeAllItem();
// 待补充 清理权限相关的配置
if (isOatuh) {
window.location.href = `http://155.240.22.102:40992`;
} else {
router.push("/login");
}
// if (isOatuh) {
window.location.href = `https://tyyy.lz.dsj.xz/portal/home`;
// } else {
// router.push("/login");
// }
}
}
}

View File

@ -7,6 +7,7 @@ import { tansParams, blobValidate } from "@/utils/ruoyi";
let downloadLoadingInstance;
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
withCredentials: true,
timeout: 100000,
});

View File

@ -105,6 +105,12 @@ export function timeValidate(date, type) {
if (type == 'yd') {
return `${yyyy}`
}
if (type == 'ym') {
return MM
}
if (type == 'rm') {
return dd
}
if (type == 'mm') {
return `${yyyy}${MM}${dd}${hh}${mm}${ss}`
}
@ -344,3 +350,15 @@ export function setAddress(val) {
const url = '/mosty-api/mosty-base/minio/image/download/'
return url + val
}
export function getUUid() {
var list = [];
var hexDigits = "0123456789abcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < 32; i++) {
list[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
list[14] = "4";
list[19] = hexDigits.substr((list[19] & 0x3) | 0x8, 1);
list[8] = list[13] = list[18] = list[23];
let uuid = list.join("");
return uuid;
}

View File

@ -24,7 +24,7 @@
<div style="background-color: #fff;color: black;padding: 15px;overflow: auto;" :style="{ height: tabHeight + 'px' }"
ref="tableBox">
<div style="border-bottom: 1px #ccc solid;padding-bottom: 30px;">
<h1 class="headline">{{ nd }}年度西藏公安执法数据分析</h1>
<h1 class="headline">{{ nd }}年度西藏公安战术研判报告</h1>
<div style="display: flex;align-items: center;justify-content: space-between; color: red;margin-top: 30px;padding: 0 30px;">
<div>{{ deptId.name }}</div>
<div>{{ deptId?.ord }}</div>

View File

@ -26,6 +26,7 @@
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary">导入</el-button>
<el-button type="primary" size="small" @click="addEdit('add', null)">
<el-icon style="vertical-align: middle">
<CirclePlus />
@ -40,12 +41,12 @@
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
@chooseData="chooseData"
>
@ -62,7 +63,7 @@
</template>
<template #bqList="{ row }">
<ul >
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} ) </li>
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} ) </li>
</ul>
</template>
<template #bgxx="{ row }">

View File

@ -27,6 +27,7 @@
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary" >导入</el-button>
<el-button type="primary" size="small" @click="addEdit('add', null)">
<el-icon style="vertical-align: middle">
<CirclePlus />

View File

@ -25,6 +25,7 @@
</el-popover>
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary" >导入</el-button>
<el-button type="primary" size="small" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle">
<CirclePlus />

View File

@ -1,191 +0,0 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">人力情报信息采集流转详情</span>
<div>
<el-button @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage disabled v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
<template #gapdive>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">基础信息</el-divider>
</div>
</template>
<template #gapline>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">情报内容</el-divider>
</div>
</template>
<template #scfj>
<div style="width: 100%;padding-left: 50px;">
<div>上传附件:<span class="f12">可附电子表格Word文档图像音视频文件</span> </div>
<div><MOSTY.Upload :showBtn="true" :isAll="true" :isImg="true" disabled :limit="10" v-model="fjdz" /> </div>
</div>
</template>
</FormMessage>
<el-divider content-position="left"><span class="mr20">相关人员</span> </el-divider>
<MyTable
:tableData="pageForm.tableData"
:tableColumn="pageForm.tableColumn"
:tableHeight="pageForm.tableHeight"
:key="pageForm.keyCount"
:tableConfiger="pageForm.tableConfiger"
:controlsWidth="pageForm.controlsWidth"
>
<template #xb="{row}">
<DictTag :value="row.xb" :tag="false" :options="props.dic.D_BZ_XB" />
</template>
<template #bqList="{row}">
<div v-if="row.bqList">
<el-tag type="success" v-for="(it,idx) in row.bqList" :key="idx">{{ it.bqMc }}</el-tag >
</div>
</template>
<!-- 操作 -->
<template #controls="{ row,index }">
<el-link size="small" type="success" @click="addEdit('detail', row,index)">详情</el-link>
</template>
</MyTable>
</div>
<!-- 人员 -->
<AddPeo ref="showAdd" v-if="showPerson" v-model="showPerson" :dic="props.dic" ></AddPeo>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import AddPeo from '@/components/addPerson/index.vue'
import MyTable from "@/components/aboutTable/MyTable.vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet } from "@/api/qcckApi.js";
import { ref, defineExpose, reactive, onMounted, defineEmits, getCurrentInstance, nextTick } from "vue";
const emit = defineEmits(["change"]);
const props = defineProps({
dic: Object
});
const { proxy } = getCurrentInstance();
const dialogForm = ref(false); //弹窗
const rules = reactive({
xsMc: [{ required: true, message: "请输入情报名称", trigger: "blur" }],
xlLx: [{ required: true, message: "请选择情报类型", trigger: "change" }],
qbLy: [{ required: true, message: "请选择情报来源", trigger: "change" }],
});
const formData = ref([
{ prop: "gapdive", type: "slot",width:'100%' },
{ label: "情报名称", prop: "xsMc", type: "input" },
{ label: "情报类型", prop: "xlLx", type: "select", options:props.dic.D_GS_XS_LX },
{ label: "情报来源", prop: "qbLy", type: "select", options:props.dic.D_GS_XS_LY},
{ label: "情报上报时间", prop: "zxkssj", type: "datetime"},
// { label: "指向结束时间", prop: "zxjssj", type: "datetime"},
{ label: "指向地点", prop: "zxdz", type: "input"},
{ label: "所属专题", prop: "sszt", type: "select",options:props.dic.D_BZ_SSZT},
{ prop: "gapline", type: "slot",width:'100%' },
{ prop: "scfj", type: "slot",width:'100%'},
{ label: "情报内容", prop: "xsNr", type: "textarea",width:'100%'},
{ label: "群体类型", prop: "qtlx", type: "select",options:props.dic.D_GS_XS_QTLX },
{ label: "群体名称", prop: "qtmc", type: "input"},
{ label: "涉及人数", prop: "sjrs", type: "inputNumber"},
{ label: "情报报送单位", prop: "ssbmdm", type: "department"},
]);
const fjdz = ref()
const listQuery = ref({}); //表单
const loading = ref(false);
const elform = ref();
const pageForm = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false
},
controlsWidth: 220,
tableColumn: [
{ label: "姓名", prop: "xm" },
{ label: "性别", prop: "xb",showSolt:true },
{ label: "身份证号", prop: "sfzh" },
{ label: "户籍地", prop: "hjdz" },
{ label: "户籍地派出所", prop: "hjdpcs" },
{ label: "标签", prop: "bqList",showSolt:true }
]
});
const showAdd = ref()
const showPerson = ref(false)
onMounted(()=>{
tabHeightFn()
})
// 初始化数据
const init = (type, row) => {
fjdz.value = []
tabHeightFn()
dialogForm.value = true;
// 初始化表单数据,并根据详情页设置禁用状态
if (row) getDataById(row.id);
};
// 根据id查询详情
const getDataById = (id) => {
qcckGet({id}, "/mosty-gsxt/qbcj/selectByid").then((res) => {
fjdz.value = res.ossList || [];
listQuery.value = res;
pageForm.tableData = res.ryList || [];
});
};
// 打开弹窗
const addEdit = (type,row,index) =>{
showPerson.value = true;
nextTick(()=>{
showAdd.value.init(type,row,index)
})
}
// 关闭
const close = () => {
fjdz.value = []
listQuery.value = {};
dialogForm.value = false;
loading.value = false;
};
// 表格高度计算
const tabHeightFn = () => {
pageForm.tableHeight = window.innerHeight - 720;
window.onresize = function () {
tabHeightFn();
};
};
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
color: #0072ff;
background: rgba(0, 114, 255, 0.3);
}
.boxlist {
width: 99%;
height: 225px;
margin-top: 10px;
overflow: hidden;
}
::v-deep .avatar-uploader{
display: flex;
align-items: center;
}
::v-deep .el-upload-list{
margin-left: 20px;
display: flex;
align-items: center;
}
::v-deep .el-upload-list__item-name .el-icon{
top: 3px;
}
</style>

View File

@ -1,147 +1,148 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">人力情报信息采集流转详情</span>
<span class="title">警务工作{{ title }}</span>
<div>
<el-button @click="submitForm()" type="primary">保存</el-button>
<el-button @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage disabled v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
<template #gapdive>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">基础信息</el-divider>
</div>
</template>
<template #gapline>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">情报内容</el-divider>
</div>
</template>
<template #scfj>
<div style="width: 100%;padding-left: 50px;">
<div>上传附件:<span class="f12">可附电子表格Word文档图像音视频文件</span> </div>
<div><MOSTY.Upload :showBtn="true" :isAll="true" :isImg="true" disabled :limit="10" v-model="fjdz" /> </div>
</div>
</template>
</FormMessage>
<el-divider content-position="left"><span class="mr20">相关人员</span> </el-divider>
<MyTable
:tableData="pageForm.tableData"
:tableColumn="pageForm.tableColumn"
:tableHeight="pageForm.tableHeight"
:key="pageForm.keyCount"
:tableConfiger="pageForm.tableConfiger"
:controlsWidth="pageForm.controlsWidth"
>
<template #xb="{row}">
<DictTag :value="row.xb" :tag="false" :options="props.dic.D_BZ_XB" />
</template>
<template #bqList="{row}">
<div v-if="row.bqList">
<el-tag type="success" v-for="(it,idx) in row.bqList" :key="idx">{{ it.bqMc }}</el-tag >
</div>
</template>
<!-- 操作 -->
<template #controls="{ row,index }">
<el-link size="small" type="success" @click="addEdit('detail', row,index)">详情</el-link>
</template>
</MyTable>
<div style="display: flex;width: 100%;" v-loading="loading">
<div class="form_cnt">
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
<template #gapdive>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">基础信息</el-divider>
</div>
</template>
<template #gapline>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">情报内容</el-divider>
</div>
</template>
<template #scfj>
<div style="width: 100%;padding-left: 50px;">
<div>上传附件:<span class="f12">可附电子表格Word文档图像音视频文件</span> </div>
<div>
<MOSTY.Upload :showBtn="true" :isAll="true" :isImg="true" disabled :limit="10" v-model="fjdz" />
</div>
</div>
</template>
</FormMessage>
<el-divider content-position="left"><span class="mr20">活跃人员</span> </el-divider>
<Personnel :dict="props.dict" ref="personnel" :perList="listQuery.ryList"/>
<el-divider content-position="left"><span class="mr20">车辆信息</span> </el-divider>
<VehicleCar :dict="props.dict" ref="vehicleCar" :clList="listQuery.clList"/>
<el-divider content-position="left"><span class="mr20">关联群体</span> </el-divider>
<Group :dict="props.dict" ref="group" :qtList="listQuery.qtList" />
</div>
<div class="person" v-if="showPj">
<AddForm ref="addForm" :dict="props.dict" :msgeDat="msgeDat" />
</div>
</div>
<!-- 人员 -->
<AddPeo ref="showAdd" v-if="showPerson" v-model="showPerson" :dic="props.dic" ></AddPeo>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import AddPeo from '@/components/addPerson/index.vue'
import MyTable from "@/components/aboutTable/MyTable.vue";
import Personnel from '../components/personnel/index.vue'
import VehicleCar from '../components/vehicleCar/index.vue'
import Group from '../components/group/index.vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet } from "@/api/qcckApi.js";
import { ref, defineExpose, reactive, onMounted, defineEmits, getCurrentInstance, nextTick } from "vue";
const emit = defineEmits(["change"]);
import { qbcjAdd, qbcjUpdate, qbcjSelectByid } from "@/api/Intelligence.js";
import { ref, defineExpose, onMounted, defineEmits, watch } from "vue";
import AddForm from '@/views/backOfficeSystem/MakeAcomment/components/a/addForm.vue'
const emit = defineEmits(["getList"]);
const props = defineProps({
dic: Object
dict: Object
});
const { proxy } = getCurrentInstance();
const loading=ref(false)
const dialogForm = ref(false); //弹窗
const rules = reactive({
xsMc: [{ required: true, message: "请输入情报名称", trigger: "blur" }],
xlLx: [{ required: true, message: "请选择情报类型", trigger: "change" }],
qbLy: [{ required: true, message: "请选择情报来源", trigger: "change" }],
});
const formData = ref([
{ prop: "gapdive", type: "slot",width:'100%' },
{ label: "情报名称", prop: "xsMc", type: "input" },
{ label: "情报类型", prop: "xlLx", type: "select", options:props.dic.D_GS_XS_LX },
{ label: "情报来源", prop: "qbLy", type: "select", options:props.dic.D_GS_XS_LY},
{ label: "情报上报时间", prop: "zxkssj", type: "datetime"},
// { label: "指向结束时间", prop: "zxjssj", type: "datetime"},
{ label: "指向地点", prop: "zxdz", type: "input"},
{ label: "所属专题", prop: "sszt", type: "select",options:props.dic.D_BZ_SSZT},
{ prop: "gapline", type: "slot",width:'100%' },
{ prop: "scfj", type: "slot",width:'100%'},
{ label: "情报内容", prop: "xsNr", type: "textarea",width:'100%'},
{ label: "群体类型", prop: "qtlx", type: "select",options:props.dic.D_GS_XS_QTLX },
{ label: "群体名称", prop: "qtmc", type: "input"},
{ label: "涉及人数", prop: "sjrs", type: "inputNumber"},
{ label: "情报报送单位", prop: "ssbmdm", type: "department"},
]);
const formData = ref();
watch(() => dialogForm.value, (val) => {
if (val) {
formData.value = [
{ prop: "gapdive", type: "slot", width: '100%' },
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' },
{ label: "情报类型", prop: "qblx", type: "select", options: props.dict.D_GS_XS_LX, width: '45%' },
{ label: "情报密级", prop: "qbmj", type: "select", options: props.dict.D_BZ_BMJB, width: '45%' },
{ label: "情报来源", prop: "qbly", type: "select", options: props.dict.D_GS_XS_LY, width: '45%' },
{ label: "情报上报时间", prop: "sxsbsj", type: "datetime", width: '45%' },
{ label: "指向时间", prop: "zxkssj", type: "datetime", width: '45%' },
{ label: "指向地址", prop: "zxdz", type: "input", width: '45%' },
{ label: "附件上传", prop: "fjdz", type: "upload", width: '100%' },
{ label: "情报内容", prop: "qbnr", type: "textarea", width: '100%' },
]
}
}, { deep: true })
const fjdz = ref()
const listQuery = ref({}); //表单
const loading = ref(false);
const elform = ref();
const pageForm = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false
},
controlsWidth: 220,
tableColumn: [
{ label: "姓名", prop: "xm" },
{ label: "性别", prop: "xb",showSolt:true },
{ label: "身份证号", prop: "sfzh" },
{ label: "户籍地", prop: "hjdz" },
{ label: "户籍地派出所", prop: "hjdpcs" },
{ label: "标签", prop: "bqList",showSolt:true }
]
});
const showAdd = ref()
const showPerson = ref(false)
onMounted(()=>{
tabHeightFn()
onMounted(() => {
})
const addForm = ref()
const msgeDat = ref()
const title = ref("")
const showPj = ref(false)
const disabled = ref(false)
// 初始化数据
const init = (type, row) => {
title.value = type == "add" ? "新增" : type == "info" ? "详情" : "编辑"
disabled.value = type == 'info' ? true : false
fjdz.value = []
tabHeightFn()
dialogForm.value = true;
// 初始化表单数据,并根据详情页设置禁用状态
if (row) getDataById(row.id);
if (type == 'info' || type == 'edit') {
showPj.value = true
msgeDat.value = row
// 初始化表单数据,并根据详情页设置禁用状态
if (row) getDataById(row.id);
} else {
showPj.value = false
}
};
// 根据id查询详情
const getDataById = (id) => {
qcckGet({id}, "/mosty-gsxt/qbcj/selectByid").then((res) => {
qbcjSelectByid({ id }).then((res) => {
fjdz.value = res.ossList || [];
listQuery.value = res;
pageForm.tableData = res.ryList || [];
});
};
// 打开弹窗
const addEdit = (type,row,index) =>{
showPerson.value = true;
nextTick(()=>{
showAdd.value.init(type,row,index)
// 获取人员信息
const personnel = ref(null)
const vehicleCar = ref(null)
const group = ref(null)
// 新增
const submitForm = () => {
loading.value = true
elform.value.submit(valid => {
if (valid) {
const promes = {
...listQuery.value,
fjdz: fjdz.value.length > 0 ? fjdz.value.join(',') : '',
ryList: personnel.value.listData() || [],
clList: vehicleCar.value.listData() || [],
qtList:group.value.listData() || [],
}
if (title.value == '新增') {
qbcjAdd(promes).then((res) => {
emit("getList")
close()
}).finally(() => {
loading.value = false
})
} else if (title.value == '编辑') {
qbcjUpdate(promes).then((res) => {
emit("getList")
close()
}).finally(() => {
loading.value = false
})
}
}
})
}
// 关闭
const close = () => {
fjdz.value = []
@ -149,25 +150,18 @@ const close = () => {
dialogForm.value = false;
loading.value = false;
};
// 表格高度计算
const tabHeightFn = () => {
pageForm.tableHeight = window.innerHeight - 720;
window.onresize = function () {
tabHeightFn();
};
};
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
color: #0072ff;
background: rgba(0, 114, 255, 0.3);
}
.boxlist {
width: 99%;
height: 225px;
@ -175,17 +169,29 @@ defineExpose({ init });
overflow: hidden;
}
::v-deep .avatar-uploader{
::v-deep .avatar-uploader {
display: flex;
align-items: center;
}
::v-deep .el-upload-list{
::v-deep .el-upload-list {
margin-left: 20px;
display: flex;
align-items: center;
}
::v-deep .el-upload-list__item-name .el-icon{
::v-deep .el-upload-list__item-name .el-icon {
top: 3px;
}
.form_cnt {
// width: 75%;
flex: 1;
}
.person {
padding-left: 20px;
width: 25%;
// height: 100vh;
}
</style>

View File

@ -0,0 +1,8 @@
<!-- 批量导入 -->
<template>
</template>
<script setup>
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,159 @@
<!--文件导出 -->
<template>
<el-dialog v-model="modelValue" :title="title" :width="width" top="5vh" @close="close" append-to-body>
<div style="height: 70vh;">
<MyTable ref="tableData" :tableData="pageForm.tableData" :tableColumn="pageForm.tableColumn"
:tableHeight="pageForm.tableHeight" :key="pageForm.keyCount" :tableConfiger="pageForm.tableConfiger"
:controlsWidth="pageForm.controlsWidth">
<template #[item.prop]="{ row }" v-for="(item, index) in soltData">
<template v-if="item.zd">
<DictTag :tag="false" :value="row[item.prop]" :options="props.dict[item.zd]" />
</template>
<template v-else>
<slot :name="item.prop" :row="row"></slot>
</template>
</template>
</MyTable>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="exportCurrentTable">导出 </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import * as XLSX from 'xlsx'
import { onMounted, reactive, watch, ref } from 'vue'
import MyTable from "@/components/aboutTable/MyTable.vue";
import { template } from 'lodash';
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
width: {
type: String,
default: '50%'
}, tableColumn: {
type: Array,
default: () => []
}, dict: {
type: Object,
default: () => ({})
},
title: {
type: String,
default: '导出数据'
}, dataModel: {
type: Array,
default: () => ([])
}
})
onMounted(() => {
{ { props.dict } }
})
watch(() => props.modelValue, (newVal, oldVal) => {
if(newVal){
pageForm.tableData = props.dataModel
}
})
const emit = defineEmits(['update:modelValue'])
const pageForm = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false,
haveControls: false
},
controlsWidth: 220,
tableColumn: [
],
});
const soltData = ref([])
// 当对话框显示时处理表格列配置
watch(() => props.modelValue, (newVal) => {
if (newVal) {
pageForm.tableColumn = props.tableColumn.map(item => ({
...item,
showSolt: item.showSolt || false,
showOverflowTooltip: item.showOverflowTooltip || false,
prop: item.prop || item.key,
label: item.title || item.label || item.name,
zd: item.zd
}))
soltData.value = props.tableColumn.filter(item => item.showSolt)
}
}, { deep: true })
const close = () => {
emit('update:modelValue', false)
}
const tableData = ref(null)
// 导出当前表格的数据
const exportCurrentTable = () => {
try {
// 创建工作簿
const wb = XLSX.utils.book_new();
// 检查表格列配置是否存在
if (pageForm.tableColumn && pageForm.tableColumn.length > 0) {
// 准备导出数据使用表格列配置中的label作为表头
const exportData = pageForm.tableData.map(row => {
const formattedRow = {};
// 遍历表格列配置
pageForm.tableColumn.forEach(col => {
// 使用列的label作为Excel的表头对应的值为行中该属性的值
if (col.prop && row.hasOwnProperty(col.prop)) {
// 处理带字典的列
let cellValue = row[col.prop];
if (col.zd && props.dict[col.zd] && cellValue !== undefined) {
// 查找字典中的对应文本值
const dictItem = props.dict[col.zd].find(d => d.value === cellValue);
if (dictItem) {
cellValue = dictItem.zdmc || dictItem.label || cellValue;
}
}
formattedRow[col.label || col.prop] = cellValue;
}
});
return formattedRow;
});
// 使用格式化后的数据创建工作表
const ws = XLSX.utils.json_to_sheet(exportData);
// 添加工作表到工作簿
XLSX.utils.book_append_sheet(wb, ws, props.title);
// 导出文件
XLSX.writeFile(wb, props.title + '.xlsx');
} else {
// 如果没有表格列配置,使用原始数据
const exportData = pageForm.tableData.map(row => {
const exportRow = { ...row };
// 处理带字典的列
soltData.value.forEach(item => {
if (item.zd && props.dict[item.zd] && exportRow[item.prop] !== undefined) {
// 查找字典中的对应文本值
const dictItem = props.dict[item.zd].find(d => d.value === exportRow[item.prop]);
if (dictItem) {
exportRow[item.prop] = dictItem.zdmc || dictItem.label || exportRow[item.prop];
}
}
});
return exportRow;
});
const ws = XLSX.utils.json_to_sheet(exportData);
XLSX.utils.book_append_sheet(wb, ws, props.title);
XLSX.writeFile(wb, props.title + '.xlsx');
}
} catch (error) {
console.error('导出文件失败:', error);
}
}
</script>

View File

@ -0,0 +1,81 @@
<template>
<el-dialog v-model="modelValue" :destroy-on-close="true" title="新增群体" @close="close" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform">
</FormMessage>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submitForm">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { ref, watch } from 'vue';
import { getUUid } from '@/utils/tools'
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dict: {
type: Object,
default: () => ({})
},
dialogValue: {
type: Object,
default: () => ({})
}
})
watch(() => props.dialogValue, (val) => {
if (val) {
listQuery.value = { ...props.dialogValue }
}
})
const elform = ref()
const emit = defineEmits(['update:modelValue', 'changePersonnel'])
const listQuery = ref({})
const formData = ref()
watch(() => props.dict, () => {
formData.value=[
{ label: "群体名称", prop: "qtmc", type: "input", width: "45%" },
{
label: "群体类别",
prop: "qtlb",
type: "select",
options: props.dict.D_GS_ZDQT_LB, width: "45%"
},
{ label: "预警规模", prop: "yjgm", type: "input", width: "45%" },
{ label: "活跃人数", prop: "hyrs", type: "number", width: "45%" },
{ label: "备注", prop: "bz", type: "textarea", width: "100%" },
]
},{deep:true,immediate:true})
const submitForm = () => {
if (listQuery.value.id) {
emit('changePersonnel', listQuery.value)
} else {
const promes = {
id: getUUid(),
...listQuery.value
}
emit('changePersonnel', promes)
}
close()
}
const close = () => {
emit('update:modelValue', false)
}
</script>
<style lang="scss" scoped>
.marks {
width: 100%;
min-height: 32px;
border: 1px solid #e9e9e9;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<div>
<div class="controls">
<el-button type="primary" @click="addEdit()">
<el-icon class="icon">
<CirclePlus />
</el-icon>
<span class="icon" >新增</span>
</el-button>
</div>
<MyTable :tableData="pageForm.tableData" :tableColumn="pageForm.tableColumn" :tableHeight="pageForm.tableHeight"
:key="pageForm.keyCount" :tableConfiger="pageForm.tableConfiger" :controlsWidth="pageForm.controlsWidth">
<!-- 操作 -->
<template #qtlb="{ row}">
<DictTag :tag="false" :value="row.qtlb" :options="props.dict.D_GS_ZDQT_LB" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link size="small" type="success" @click="addEdit(row)">修改</el-link>
<el-link size="small" type="danger" @click="del(row)">删除</el-link>
</template>
</MyTable>
</div>
<AddPersonnel :dialogValue="dialogValue" v-model="showDialog" :dict="props.dict" @changePersonnel="changePersonnel" />
</template>
<script setup>
import { reactive ,ref,watch} from "vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import AddPersonnel from "./addPersonnel.vue";
const props = defineProps({
dict: {
type: Object,
default: () => ({})
},
qtList: {
type: Array,
default: () => []
}
});
watch(() => props.qtList, val => {
pageForm.value.tableData=val
},{deep:true})
const showDialog = ref(false)
const pageForm = ref({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
controlsWidth: 220,
tableColumn: [
{ label: "群体名称", prop: "qtmc",showOverflowTooltip:true },
{ label: "群体类别", prop: "qtlb",showOverflowTooltip:true ,showSolt: true},
{ label: "预警规模", prop: "yjgm",showOverflowTooltip:true },
{ label: "活跃人数", prop: "hyrs",showOverflowTooltip:true },
{ label: "备注", prop: "bz" ,showOverflowTooltip:true},
]
});
watch(() => props.perList, (val) => {
pageForm.value.tableData=val
},{deep:true})
const changePersonnel = (val) => {
const index = pageForm.value.tableData.findIndex(it => it.id == val.id)
if (index != -1) {
pageForm.value.tableData[index] = val
} else {
pageForm.value.tableData.push(val)
}
}
const dialogValue=ref()
const addEdit = (val) => {
showDialog.value = true
dialogValue.value=val
}
const listData = () => {
return pageForm.value.tableData
}
const del = (val) => {
const index = pageForm.value.tableData.findIndex(it => it.id == val.id)
if (index != -1) {
pageForm.value.tableData.splice(index, 1)
ElMessage.success('删除成功')
}
}
defineExpose({ listData });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.controls {
display: flex;
justify-content: end;
margin-bottom: 10px;
padding: 0 20px;
.icon {
vertical-align: middle
}
}
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
color: #0072ff;
background: rgba(0, 114, 255, 0.3);
}
::v-deep .avatar-uploader {
display: flex;
align-items: center;
}
::v-deep .el-upload-list {
margin-left: 20px;
display: flex;
align-items: center;
}
::v-deep .el-upload-list__item-name .el-icon {
top: 3px;
}
.form_cnt {
// width: 75%;
flex: 1;
}
.person {
padding-left: 20px;
width: 25%;
// height: 100vh;
}
</style>

View File

@ -0,0 +1,54 @@
<!-- 使用示例在父组件中集成文件导入组件 -->
<script setup>
// 导入刚才创建的文件导入组件
import ToChannel from './components/toChannel.vue'
// 响应式数据
const importDialogVisible = ref(false)
// 表格列配置(用于导入预览和模板生成)
const tableColumns = ref([
{ label: '姓名', prop: 'xm' },
{ label: '身份证号', prop: 'sfzh' },
{ label: '手机号', prop: 'sjhm' },
{ label: '地址', prop: 'dz' },
{ label: '群体类别', prop: 'qtlb' }
])
// 打开导入对话框
const openImportDialog = () => {
importDialogVisible.value = true
}
// 处理导入成功
const handleImportSuccess = (result) => {
console.log('导入成功的数据:', result)
}
// 处理导入失败
const handleImportError = (error) => {
console.error('导入失败:', error)
}
</script>
<template>
<div>
<!-- 导入按钮 -->
<el-button type="primary" @click="openImportDialog">
<el-icon><upload-filled /></el-icon>
导入数据
</el-button>
<!-- 文件导入组件 -->
<ToChannel
v-model="importDialogVisible"
:title="'导入人员数据'"
:table-columns="tableColumns"
:upload-action="'/api/upload/excel'"
:template-url="'/api/download/template'"
:file-size-limit="5"
@import-success="handleImportSuccess"
@import-error="handleImportError"
/>
</div>
</template>

View File

@ -0,0 +1,76 @@
<template>
<el-dialog v-model="modelValue" :destroy-on-close="true" title="新增人员" @close="close" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform">
</FormMessage>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submitForm">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { ref, watch } from 'vue';
import { getUUid } from '@/utils/tools'
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dict: {
type: Object,
default: () => ({})
},
dialogValue: {
type: Object,
default: () => ({})
}
})
const listQuery = ref({})
watch(() => props.dialogValue, (val) => {
if (val) {
listQuery.value = { ...props.dialogValue }
}
})
const elform = ref()
const emit = defineEmits(['update:modelValue', 'changePersonnel'])
const formData = ref([
{ label: "姓名", prop: "xm", type: "input", width: "45%" },
{ label: "身份证号", prop: "sfzh", type: "input", width: "45%" },
{ label: "角色", prop: "js", type: "input", width: "45%" },
{ label: "手机号", prop: "sjh", type: "input", width: "45%" },
{ label: "管辖单位", prop: "gxdwdm",depMc:"gxdw", type: "department", width: "45%" },
{ label: "人员属地", prop: "rysd", type: "select", width: "45%",options:props.dict.D_BZ_XZQHDM },
{ label: "居住地址", prop: "jzdz", type: "input", width: "100%" },
{ label: "备注", prop: "bz", type: "textarea", width: "100%" },
])
const submitForm = (val) => {
if (listQuery.value.id) {
emit('changePersonnel', listQuery.value)
} else {
const promes = {
id: getUUid(),
...listQuery.value
}
emit('changePersonnel', promes)
}
close()
}
const close = () => {
emit('update:modelValue', false)
}
</script>
<style lang="scss" scoped>
.marks {
width: 100%;
min-height: 32px;
border: 1px solid #e9e9e9;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,226 @@
<template>
<div>
<div class="controls">
<div>
<div>
录入总数{{ dataStatistics.TotalNumber }}
异常次数{{ dataStatistics.ExceptionNumber }}
<span @click="repeatingDataShow()">异常数据{{ dataStatistics.ExceptionDataNumber }}</span>
</div>
</div>
<div>
<el-button type="primary" @click="addEdit()">
<el-icon class="icon">
<CirclePlus />
</el-icon>
<span class="icon">新增</span>
</el-button>
<el-button type="primary" @click="openImportDialog">
<el-icon class="icon">
<Edit />
</el-icon>
<span class="icon">批量导入</span>
</el-button>
</div>
</div>
<MyTable :tableData="pageForm.tableData" :tableColumn="pageForm.tableColumn" :tableHeight="pageForm.tableHeight"
:key="pageForm.keyCount" :tableConfiger="pageForm.tableConfiger" :controlsWidth="pageForm.controlsWidth">
<template #rysd="{ row }">
<DictTag :tag="false" :value="row.rysd" :options="props.dict.D_BZ_XZQHDM" />
</template>
<!-- 操作 -->
<template #controls="{ row, index }">
<el-link size="small" type="success" @click="addEdit(row)">修改</el-link>
<el-link size="small" type="danger" @click="del(row)">删除</el-link>
</template>
</MyTable>
</div>
<AddPersonnel :dialogValue="dialogValue" v-model="showDialog" :dict="props.dict" @changePersonnel="changePersonnel" />
<ToChannel @import-success="pushqbcjimportRyData" v-model="importDialogVisible" :title="'导入人员数据'"
aiconUrl="/mosty-gsxt/qbcj/importRyData" :file-size-limit="5" :isUrl="true" />
<RepeatingData v-model="repeatingDataVisible" :dict="props.dict" :dialogValue="repeatingData" />
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import AddPersonnel from "./addPersonnel.vue";
import ToChannel from '../toChannel.vue'
import { ElMessage } from "element-plus";
import RepeatingData from "../personnel/repeatingData.vue";
const props = defineProps({
dict: {
type: Object,
default: () => ({})
}, perList: {
type: Array,
default: () => []
}
});
watch(() => props.perList, val => {
pageForm.value.tableData = val
dataStatistics.value.TotalNumber = val.length
}, { deep: true })
const showDialog = ref(false)
const pageForm = ref({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHeight: 61, // 修正拼写错误
showSelectType: 'null', // 设置为false以隐藏所有选择框
loading: false
},
controlsWidth: 220,
tableColumn: [
{ label: "姓名", prop: "xm", showOverflowTooltip: true },
{ label: "身份证", prop: "sfzh", showOverflowTooltip: true },
{ label: "角色", prop: "js", showOverflowTooltip: true },
{ label: "手机号码", prop: "sjh", showOverflowTooltip: true },
{ label: "居住地址", prop: "jzdz", showOverflowTooltip: true },
{ label: "管辖单位", prop: "gxdw", showOverflowTooltip: true },
{ label: "人员属地", prop: "rysd", showOverflowTooltip: true, showSolt: true },
{ label: "备注", prop: "bz", showOverflowTooltip: true },
]
});
const changePersonnel = (val) => {
const index = pageForm.value.tableData.findIndex(it => it.id == val.id)
if (index != -1) {
pageForm.value.tableData[index] = val
} else {
pageForm.value.tableData.push(val)
}
dataStatistics.value.TotalNumber = pageForm.value.tableData.length
}
const dataStatistics = ref({
TotalNumber: 0,
ExceptionNumber: 0,
ExceptionDataNumber: 0,
})
const dialogValue = ref()
const addEdit = (val) => {
showDialog.value = true
dialogValue.value = val
}
const del = (val) => {
const index = pageForm.value.tableData.findIndex(it => it.id == val.id)
if (index != -1) {
pageForm.value.tableData.splice(index, 1)
ElMessage.success('删除成功')
}
}
const listData = () => {
return pageForm.value.tableData
}
const repeatingData=ref([])
// 导入
const importDialogVisible = ref(false)
const openImportDialog = () => {
importDialogVisible.value = true
}
const pushqbcjimportRyData = (val) => {
if (!val) {
dataStatistics.value.ExceptionNumber++
ElMessage.error('请求异常,导入失败,重新导入')
return
}
if (val.length == 0) {
dataStatistics.value.ExceptionNumber++
ElMessage.error('导入数据不能为空')
return
} else {
const transformedData = val.map(item => {
return {
...item,
rysd: props.dict.D_BZ_XZQHDM.filter(items => item.rysd == items.zdmc)[0]?.dm || '',
}
})
const existingChpSet = new Set(pageForm.value.tableData.map(item => item.sfzh))
const filteredData = transformedData.filter(item => {
if (!existingChpSet.has(item.sfzh)) {
return item
} else {
repeatingData.value.push(item)
}
}
)
// 更新数据统计
const duplicateCount = transformedData.length - filteredData.length
if (duplicateCount > 0) {
dataStatistics.value.ExceptionNumber++
dataStatistics.value.ExceptionDataNumber += duplicateCount
ElMessage.warning(`成功导入${filteredData.length}条数据,发现${duplicateCount}条车牌号重复的数据已跳过`)
} else {
ElMessage.success(`成功导入${filteredData.length}条数据`)
}
// 添加过滤后的数据
if (filteredData.length > 0) {
if (pageForm.value.tableData.length > 0) {
pageForm.value.tableData = [...pageForm.value.tableData, ...filteredData]
} else {
pageForm.value.tableData = filteredData
}
}
dataStatistics.value.TotalNumber = pageForm.value.tableData.length
}
}
// 重复数据
const repeatingDataVisible = ref(false)
const repeatingDataShow = () => {
repeatingDataVisible.value = true
}
defineExpose({ listData });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.controls {
padding: 0 20px;
display: flex;
justify-content:space-between;
margin-bottom: 10px;
.icon {
vertical-align: middle
}
}
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
color: #0072ff;
background: rgba(0, 114, 255, 0.3);
}
::v-deep .avatar-uploader {
display: flex;
align-items: center;
}
::v-deep .el-upload-list {
margin-left: 20px;
display: flex;
align-items: center;
}
::v-deep .el-upload-list__item-name .el-icon {
top: 3px;
}
.form_cnt {
// width: 75%;
flex: 1;
}
.person {
padding-left: 20px;
width: 25%;
// height: 100vh;
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<el-dialog v-model="modelValue" :destroy-on-close="true" title="人员异常数据" @close="close" :close-on-click-modal="false">
<MyTable :tableData="pageForm.tableData" :tableColumn="pageForm.tableColumn" tableHeight="50vh"
:key="pageForm.keyCount" :tableConfiger="pageForm.tableConfiger" :controlsWidth="pageForm.controlsWidth">
<template #rysd="{ row }">
<DictTag :tag="false" :value="row.rysd" :options="props.dict.D_BZ_XZQHDM" />
</template>
<!-- 操作 -->
<template #controls="{ row, index }">
<el-link size="small" type="success" @click="addEdit(row)">修改</el-link>
<el-link size="small" type="danger" @click="del(row)">删除</el-link>
</template>
</MyTable>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, watch } from 'vue';
import MyTable from "@/components/aboutTable/MyTable.vue";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dict: {
type: Object,
default: () => ({})
},
dialogValue: {
type: Object,
default: () => ({})
}
})
watch(() => props.modelValue, (val) => {
if (val) {
pageForm.value.tableData =props.dialogValue
}
})
const emit = defineEmits(['update:modelValue'])
const pageForm = ref({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false,
haveControls: false
},
controlsWidth: 220,
tableColumn: [
{ label: "姓名", prop: "xm", showOverflowTooltip: true },
{ label: "身份证", prop: "sfzh", showOverflowTooltip: true },
{ label: "角色", prop: "js", showOverflowTooltip: true },
{ label: "手机号码", prop: "sjh", showOverflowTooltip: true },
{ label: "居住地址", prop: "jzdz", showOverflowTooltip: true },
{ label: "管辖单位", prop: "gxdw", showOverflowTooltip: true },
{ label: "人员属地", prop: "rysd", showOverflowTooltip: true, showSolt: true },
{ label: "备注", prop: "bz", showOverflowTooltip: true },
]
});
const close = () => {
emit('update:modelValue', false)
}
</script>
<style lang="scss" scoped>
.marks {
width: 100%;
min-height: 32px;
border: 1px solid #e9e9e9;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,298 @@
<!-- 文件上传导入组件 -->
<template>
<el-dialog v-model="modelValue" :title="title" :width="width" top="5vh" @close="close" append-to-body>
<!-- 上传区域 -->
<div class="upload-section">
<el-upload class="upload-demo" drag :auto-upload="false" :limit="1" :file-list="fileList"
:before-upload="beforeUpload" :on-change="handleFileChange" :on-exceed="handleExceed">
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
<em>点击或拖拽文件到此处上传</em>
</div>
<template #tip>
<div class="el-upload__tip">
只能上传 xlsx/xls 文件且不超过 {{ fileSizeLimit }}MB
</div>
</template>
</el-upload>
<!-- 操作按钮 -->
<div class="upload-actions">
<el-button type="primary" @click="handleImport" :disabled="!canImport">导入数据</el-button>
<el-button @click="handleTemplate">下载模板</el-button>
</div>
</div>
<!-- 数据预览区域 -->
<div v-if="previewData.length > 0" class="preview-section">
<h4 style="margin-bottom: 16px;">数据预览</h4>
<el-table :data="previewData" style="width: 100%;" :max-height="300">
<el-table-column v-for="col in tableColumns" :key="col.prop" :prop="col.prop" :label="col.label"
show-overflow-tooltip></el-table-column>
</el-table>
</div>
<!-- 加载状态 -->
<!-- <el-dialog v-model="loadingVisible" title="导入中" :show-close="false">
<div style="text-align: center; padding: 20px;">
<el-loading :fullscreen="false" text="正在处理数据,请稍候..." :visible="true"></el-loading>
</div>
</el-dialog> -->
<!-- <template #footer>
<div class="dialog-footer">
<el-button @click="close">关闭</el-button>
</div>
</template> -->
</el-dialog>
</template>
<script setup>
import * as XLSX from 'xlsx'
import { ref, computed, defineProps, defineEmits } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { qcckPost } from '@/api/qcckApi'
// Props 定义
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
width: {
type: String,
default: '30%'
},
title: {
type: String,
default: '导入数据'
},
// 文件大小限制(MB)
fileSizeLimit: {
type: Number,
default: 10
},
// 表格列配置
tableColumns: {
type: Array,
default: () => []
},
// 模板下载地址
templateUrl: {
type: String,
default: ''
},
// 图标地址
aiconUrl: {
type: String,
default: ''
},
isUrl: {
type: Boolean,
default: false
}
})
// Emits 定义
const emit = defineEmits(['update:modelValue', 'import-success', 'import-error', 'vSocial'])
// 响应式数据
const fileList = ref([])
const previewData = ref([])
const loadingVisible = ref(false)
// 计算属性:是否可以导入
const canImport = computed(() => {
return fileList.value.length > 0 && !loadingVisible.value
})
// 关闭对话框
const close = () => {
resetState()
emit('update:modelValue', false)
}
// 重置状态
const resetState = () => {
fileList.value = []
previewData.value = []
loadingVisible.value = false
}
// 处理文件选择变化
const handleFileChange = (file) => {
// 清空之前的预览数据
previewData.value = []
// 只保留最后一个文件
fileList.value = [file]
// 读取文件内容进行预览
const reader = new FileReader()
reader.onload = (e) => {
try {
const data = e.target.result
const workbook = XLSX.read(data, { type: 'binary' })
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
// 转换为JSON数据
const jsonData = XLSX.utils.sheet_to_json(worksheet)
// 如果有表格列配置,过滤和格式化数据
if (props.tableColumns && props.tableColumns.length > 0) {
previewData.value = jsonData.slice(0, 10).map(row => {
const formattedRow = {}
props.tableColumns.forEach(col => {
formattedRow[col.prop] = row[col.label] !== undefined ? row[col.label] : row[col.prop]
})
return formattedRow
})
} else {
// 否则直接使用前10条数据作为预览
previewData.value = jsonData.slice(0, 10)
}
} catch (error) {
ElMessage.error('文件解析失败,请检查文件格式')
console.error('文件解析错误:', error)
}
}
reader.readAsBinaryString(file.raw)
}
// 上传前校验
const beforeUpload = (file) => {
const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
file.type === 'application/vnd.ms-excel'
const isLtLimit = file.size / 1024 / 1024 < props.fileSizeLimit
if (!isExcel) {
ElMessage.error('只能上传 Excel 文件!')
return false
}
if (!isLtLimit) {
ElMessage.error(`文件大小不能超过 ${props.fileSizeLimit}MB`)
return false
}
return true
}
// 处理文件超出限制
const handleExceed = () => {
ElMessage.error('只能上传一个文件')
}
// 处理导入
const handleImport = async () => {
if (!fileList.value[0]) {
ElMessage.warning('请先选择文件')
return
}
loadingVisible.value = true
try {
// 创建FormData对象
const formData = new FormData()
formData.append('file', fileList.value[0].raw)
if (props.isUrl && props.aiconUrl) {
// 调用上传接口
qcckPost(formData, props.aiconUrl).then(res => {
emit('import-success', res)
close()
}).catch(error => {
ElMessage.error(error.message || '文件上传失败')
emit('import-success', null)
loadingVisible.value = false
})
} else {
// 如果没有配置上传接口,只解析文件并返回数据
const reader = new FileReader()
reader.onload = (e) => {
try {
const data = e.target.result
const workbook = XLSX.read(data, { type: 'binary' })
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
const jsonData = XLSX.utils.sheet_to_json(worksheet)
emit('import-success', { data: jsonData })
close()
} catch (error) {
throw error
}
}
reader.readAsBinaryString(fileList.value[0].raw)
}
} catch (error) {
ElMessage.error(error.message || '导入失败')
emit('import-error', error)
loadingVisible.value = false
}
}
// 处理模板下载
const handleTemplate = () => {
if (props.templateUrl) {
window.open(props.templateUrl, '_blank')
} else {
// 如果没有提供模板下载地址,根据列配置生成简单模板
try {
const wb = XLSX.utils.book_new()
// 创建表头数据
const headerData = []
if (props.tableColumns && props.tableColumns.length > 0) {
const headerRow = {}
props.tableColumns.forEach(col => {
headerRow[col.prop] = col.label
})
headerData.push(headerRow)
}
const ws = XLSX.utils.json_to_sheet(headerData)
XLSX.utils.book_append_sheet(wb, ws, '模板')
// 下载模板
XLSX.writeFile(wb, '导入模板.xlsx')
} catch (error) {
ElMessage.error('模板生成失败')
}
}
}
</script>
<style scoped>
.upload-section {
padding: 20px 0;
display: flex;
flex-direction: column;
align-items: center;
}
.upload-demo {
width: 100%;
max-width: 600px;
}
.upload-actions {
margin-top: 20px;
text-align: center;
}
.upload-actions .el-button {
margin: 0 10px;
}
.preview-section {
margin-top: 20px;
border-top: 1px solid #ebeef5;
padding-top: 20px;
width: 100%;
max-width: 1000px;
align-self: center;
margin-left: auto;
margin-right: auto;
}
.el-table {
font-size: 14px;
}
</style>

View File

@ -0,0 +1,99 @@
<template>
<el-dialog v-model="modelValue" :destroy-on-close="true" title="新增车辆" @close="close" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform">
</FormMessage>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submitForm">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { ref, watch } from 'vue';
import { getUUid } from '@/utils/tools'
import { ElMessage } from "element-plus";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dict: {
type: Object,
default: () => ({})
},
dialogValue: {
type: Object,
default: () => ({})
}
})
watch(() => props.dialogValue, (val) => {
if (val) {
listQuery.value = { ...props.dialogValue }
}
})
const elform = ref()
const emit = defineEmits(['update:modelValue', 'change'])
const listQuery = ref({})
const formData = ref([])
watch(() => props.dict, (val) => {
if (val) {
formData.value = [
{ label: "车牌号", prop: "chp", type: "input", width: "45%" },
{ label: "车主姓名", prop: "czxm", type: "input", width: "45%" },
{ label: "证件号码", prop: "zjhm", type: "input", width: "45%" },
{ label: "车主联系方式", prop: "lxfs", type: "input", width: "45%" },
{
label: "车辆品牌",
prop: "clpp",
type: "select",
options: val.D_BZ_CLPP, width: "45%"
},
{
label: "车身颜色",
prop: "csys",
type: "select",
options: props.dict.D_BZ_CLYS, width: "45%"
},
{
label: "车辆类型",
prop: "cllx",
type: "select",
options: props.dict.D_BZ_CLLX, width: "45%"
},
{ label: "备注", prop: "bz", type: "textarea", width: "100%" },
]
}
}, { deep: true, immediate: true })
const submitForm = (val) => {
if (listQuery.value.id) {
emit('changePersonnel', listQuery.value)
} else {
const promes = {
id: getUUid(),
...listQuery.value
}
emit('changePersonnel', promes)
}
close()
}
const close = () => {
emit('update:modelValue', false)
}
</script>
<style lang="scss" scoped>
.marks {
width: 100%;
min-height: 32px;
border: 1px solid #e9e9e9;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,232 @@
<template>
<div>
<div class="controls">
<div>
录入总数{{ dataStatistics.TotalNumber }}
异常次数{{ dataStatistics.ExceptionNumber }}
<span @click="repeatingDataShow()">异常数据{{ dataStatistics.ExceptionDataNumber }}</span>
</div>
<div>
<el-button type="primary" @click="addEdit()">
<el-icon class="icon">
<CirclePlus />
</el-icon>
<span class="icon">新增</span>
</el-button>
<el-button type="primary" @click="openImportDialog">
<el-icon class="icon">
<Edit />
</el-icon>
<span class="icon">批量导入</span>
</el-button>
</div>
</div>
<MyTable :tableData="pageForm.tableData" :tableColumn="pageForm.tableColumn" :tableHeight="pageForm.tableHeight"
:key="pageForm.keyCount" :tableConfiger="pageForm.tableConfiger" :controlsWidth="pageForm.controlsWidth">
<template #clpp="{ row }">
<DictTag :value="row.clpp" :tag="false" :options="props.dict.D_BZ_CLPP" />
</template>
<template #csys="{ row }">
<DictTag :value="row.csys" :tag="false" :options="props.dict.D_BZ_CLYS" />
</template>
<template #cllx="{ row }">
<DictTag :value="row.cllx" :tag="false" :options="props.dict.D_BZ_CLLX" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link size="small" type="success" @click="addEdit(row)">修改</el-link>
<el-link size="small" type="danger" @click="del(row)">删除</el-link>
</template>
</MyTable>
</div>
<AddPersonnel v-model="showDialog" :dict="props.dict" :dialogValue="dialogValue" @changePersonnel="changePersonnel" />
<ToChannel @import-success="pushqbcjimportRyData" v-model="importDialogVisible" :title="'导入人员数据'"
aiconUrl="/mosty-gsxt/qbcj/importClData" :file-size-limit="5" :isUrl="true" />
<RepeatingData v-model="repeatingDataVisible" :dict="props.dict" :dialogValue="repeatingData" />
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import ToChannel from '../toChannel.vue'
import MyTable from "@/components/aboutTable/MyTable.vue";
import AddPersonnel from "./addPersonnel.vue";
import RepeatingData from "../vehicleCar/repeatingData.vue";
import { ElMessage } from "element-plus";
const showDialog = ref(false)
const props = defineProps({
dict: Object,
clList: {
type: Array,
default: () => []
}
});
watch(() => props.clList, val => {
pageForm.value.tableData = val
dataStatistics.value.TotalNumber = val.length
}, { deep: true })
const pageForm = ref({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
controlsWidth: 220,
tableColumn: [
{ label: "车主姓名", prop: "czxm", showOverflowTooltip: true },
{ label: "车牌号", prop: "chp", showOverflowTooltip: true },
{ label: "车主联系方式", prop: "lxfs", showOverflowTooltip: true },
{ label: "证件号码", prop: "zjhm", showOverflowTooltip: true },
{ label: "车辆品牌", prop: "clpp", showOverflowTooltip: true, showSolt: true },
{ label: "车身颜色", prop: "csys", showOverflowTooltip: true, showSolt: true },
{ label: "车辆类型", prop: "cllx", showOverflowTooltip: true, showSolt: true },
{ label: "备注", prop: "bz", showOverflowTooltip: true },
]
});
const dataStatistics = ref({
TotalNumber: 0,
ExceptionNumber: 0,
ExceptionDataNumber: 0,
})
const dialogValue = ref()
const addEdit = (val) => {
showDialog.value = true
dialogValue.value = val
}
const changePersonnel = (val) => {
const index = pageForm.value.tableData.findIndex(it => it.chp == val.chp)
if (index != -1) {
pageForm.value.tableData[index] = val
} else {
pageForm.value.tableData.push(val)
}
dataStatistics.value.TotalNumber = pageForm.value.tableData.length
}
const listData = () => {
return pageForm.value.tableData
}
const repeatingData = ref([])
// 导入
const importDialogVisible = ref(false)
const openImportDialog = () => {
importDialogVisible.value = true
}
const pushqbcjimportRyData = (val) => {
if (!val) {
dataStatistics.value.ExceptionNumber++
ElMessage.error('请求异常,导入失败,重新导入')
return
}
if (val.length == 0) {
dataStatistics.value.ExceptionNumber++
ElMessage.error('导入数据不能为空')
return
} else {
// 转换数据格式
const transformedData = val.map(item => {
return {
...item,
csys: props.dict.D_BZ_CLYS.filter(items => item.csys == items.zdmc)[0]?.dm || '',
cllx: props.dict.D_BZ_CLLX.filter(items => item.cllx == items.zdmc)[0]?.dm || '',
clpp: props.dict.D_BZ_CLPP.filter(items => item.clpp == items.zdmc)[0]?.dm || '',
}
})
// 过滤掉车牌号重复的数据
const existingChpSet = new Set(pageForm.value.tableData.map(item => item.chp))
const filteredData = transformedData.filter(item => {
if (!existingChpSet.has(item.chp)) {
return item
} else {
repeatingData.value.push(item)
}
}
)
// 更新数据统计
const duplicateCount = transformedData.length - filteredData.length
if (duplicateCount > 0) {
dataStatistics.value.ExceptionNumber++
dataStatistics.value.ExceptionDataNumber += duplicateCount
ElMessage.warning(`成功导入${filteredData.length}条数据,发现${duplicateCount}条车牌号重复的数据已跳过`)
} else {
ElMessage.success(`成功导入${filteredData.length}条数据`)
}
// 添加过滤后的数据
if (filteredData.length > 0) {
if (pageForm.value.tableData.length > 0) {
pageForm.value.tableData = [...pageForm.value.tableData, ...filteredData]
} else {
pageForm.value.tableData = filteredData
}
}
dataStatistics.value.TotalNumber = pageForm.value.tableData.length
}
}
// 重复数据
const repeatingDataVisible = ref(false)
const repeatingDataShow = () => {
repeatingDataVisible.value = true
}
const del = (val) => {
const index = pageForm.value.tableData.findIndex(it => it.id == val.id)
if (index != -1) {
pageForm.value.tableData.splice(index, 1)
ElMessage.success('删除成功')
}
}
defineExpose({ listData });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.controls {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
padding: 0 20px;
.icon {
vertical-align: middle
}
}
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
color: #0072ff;
background: rgba(0, 114, 255, 0.3);
}
::v-deep .avatar-uploader {
display: flex;
align-items: center;
}
::v-deep .el-upload-list {
margin-left: 20px;
display: flex;
align-items: center;
}
::v-deep .el-upload-list__item-name .el-icon {
top: 3px;
}
.form_cnt {
// width: 75%;
flex: 1;
}
.person {
padding-left: 20px;
width: 25%;
// height: 100vh;
}
</style>

View File

@ -0,0 +1,87 @@
<template>
<el-dialog v-model="modelValue" :destroy-on-close="true" title="车辆异常数据" @close="close" :close-on-click-modal="false">
<MyTable :tableData="pageForm.tableData" :tableColumn="pageForm.tableColumn" tableHeight="50vh"
:key="pageForm.keyCount" :tableConfiger="pageForm.tableConfiger" :controlsWidth="pageForm.controlsWidth">
<template #clpp="{ row }">
<DictTag :value="row.clpp" :tag="false" :options="props.dict.D_BZ_CLPP" />
</template>
<template #csys="{ row }">
<DictTag :value="row.csys" :tag="false" :options="props.dict.D_BZ_CLYS" />
</template>
<template #cllx="{ row }">
<DictTag :value="row.cllx" :tag="false" :options="props.dict.D_BZ_CLLX" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link size="small" type="success" @click="addEdit(row)">修改</el-link>
<el-link size="small" type="danger" @click="del(row)">删除</el-link>
</template>
</MyTable>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, watch } from 'vue';
import MyTable from "@/components/aboutTable/MyTable.vue";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dict: {
type: Object,
default: () => ({})
},
dialogValue: {
type: Object,
default: () => ({})
}
})
watch(() => props.modelValue, (val) => {
if (val) {
pageForm.value.tableData =props.dialogValue
}
})
const emit = defineEmits(['update:modelValue'])
const pageForm = ref({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false,
haveControls: false
},
controlsWidth: 220,
tableColumn: [
{ label: "车主姓名", prop: "czxm", showOverflowTooltip: true },
{ label: "车牌号", prop: "chp", showOverflowTooltip: true },
{ label: "车主联系方式", prop: "lxfs", showOverflowTooltip: true },
{ label: "证件号码", prop: "zjhm", showOverflowTooltip: true },
{ label: "车辆品牌", prop: "clpp", showOverflowTooltip: true, showSolt: true },
{ label: "车身颜色", prop: "csys", showOverflowTooltip: true, showSolt: true },
{ label: "车辆类型", prop: "cllx", showOverflowTooltip: true, showSolt: true },
{ label: "备注", prop: "bz", showOverflowTooltip: true },
]
});
const close = () => {
emit('update:modelValue', false)
}
</script>
<style lang="scss" scoped>
.marks {
width: 100%;
min-height: 32px;
border: 1px solid #e9e9e9;
border-radius: 4px;
}
</style>

View File

@ -1,16 +1,24 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="人力情报数据采集管理">
<!-- <el-button type="primary">
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon>
<span style="vertical-align: middle">导出</span>
</el-button> -->
<el-button type="primary" @click="dologShowFn()">
<PageTitle title="警务工作管理">
<el-button type="primary" @click="addEdit('add')">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">全域搜索</span>
<span style="vertical-align: middle">新增</span>
</el-button>
<el-button type="primary" @click="dologCancel()">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">导出</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="delDictItem(ids)">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量删除</span>
</el-button>
</PageTitle>
</div>
@ -18,17 +26,17 @@
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData">
<template #xlLx="{ row }">
<DictTag :tag="false" :value="row.xlLx" :options="D_GS_XS_LX" />
<template #qblx="{ row }">
<DictTag :tag="false" :value="row.qblx" :options="D_GS_XS_LX" />
</template>
<template #qbLy="{ row }">
<DictTag :tag="false" :value="row.qbLy" :options="D_GS_XS_LY" />
<template #qbly="{ row }">
<DictTag :tag="false" :value="row.qbly" :options="D_GS_XS_LY" />
</template>
<!-- <template #czzt="{row}">
<DictTag :tag="false" :value="row.czzt" :options="D_GS_XS_CZZT" />
@ -39,9 +47,10 @@
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link size="small" type="primary" @click="addEdit('edit', row)">详情</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
<el-link size="small" type="primary" @click="addEdit('edit', row)">修改</el-link>
<!-- <el-link size="small" type="primary" @click="addEdit('edit', row)">下发指令</el-link> -->
<el-popconfirm title="是否进行发布?" @confirm="confirm(row)">
<el-popconfirm title="是否进行发布?" @confirm="confirm(row)">
<template #reference>
<el-link size="small" type="primary">发布</el-link>
</template>
@ -82,31 +91,42 @@
}"></Pages>
</div>
<!-- 新增 -->
<AddForm ref="detailDiloag" @change="change" v-if="isShow"
:dic="{ D_BZ_SF, D_BZ_XB, D_GS_XS_LY, D_BZ_SSZT, D_GS_XS_LX, D_GS_XS_QTLX }" />
<DialogDragger title="全域搜索" top="30px" v-model="dologShow" coumClass="zdy-model-dialogs" @close="close" width="80%">
<iframe style="width: 100%; height: 1000px" src="https://www.baidu.com" frameborder="0">
xxxxx
</iframe>
</DialogDragger>
<AddForm ref="detailDiloag" @getList="getList" :dict="{
D_BZ_SF,
D_GS_XS_LY,
D_BZ_SSZT,
D_GS_XS_LX,
D_GS_XS_QTLX,
D_GS_ZDQT_LB,
D_BZ_BMJB,
D_BZ_CLPP,
D_BZ_CLYS,
D_BZ_CLLX,
D_BZ_XZQHDM
}" />
</div>
<ExportFile v-model="exportFileModel" :tableColumn="tableColumn" :dict="{ D_GS_XS_LY ,D_GS_XS_LX}" :dataModel="pageData.tableData"/>
</template>
<script setup>
import { download } from "@/utils/request";
import * as MOSTY from "@/components/MyComponents/index";
import DialogDragger from "@/views/home/layout/dialogDragger.vue";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import AddForm from "./components/addForm.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
// import {updateBkgzl} from '@/api/'
import { qbcjSelectPage, qbcjDeletes } from "@/api/Intelligence.js";
import { reactive, ref, onMounted, getCurrentInstance, nextTick, watch } from "vue";
import ExportFile from './components/exportFile.vue'
const { proxy } = getCurrentInstance();
const { D_GS_XS_CZZT, D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX, D_GS_XS_QTLX, D_BZ_XB, D_BZ_XSSHZT } = proxy.$dict("D_GS_XS_CZZT", "D_GS_XS_LY", "D_BZ_SSZT", "D_BZ_SF", "D_GS_XS_LX", "D_GS_XS_QTLX", "D_BZ_XB", "D_BZ_XSSHZT"); //获取字典数据
const { D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX,
D_GS_XS_QTLX, D_BZ_XSSHZT, D_GS_ZDQT_LB,
D_BZ_BMJB, D_BZ_CLPP, D_BZ_CLYS, D_BZ_CLLX, D_BZ_XZQHDM, D_GS_XS_CZZT } =
proxy.$dict("D_BZ_BMJB", "D_GS_XS_CZZT", "D_GS_XS_LY",
"D_BZ_SSZT", "D_BZ_SF", "D_GS_XS_LX", "D_GS_XS_QTLX",
"D_BZ_XSSHZT", "D_GS_ZDQT_LB", "D_BZ_CLPP", "D_BZ_CLYS", "D_BZ_CLLX", "D_BZ_XZQHDM", "D_GS_XS_CZZT"); //获取字典数据
const detailDiloag = ref();
const searchBox = ref(); //搜索框
const chooseRow = ref({})
@ -114,19 +134,27 @@ const rules = reactive({
bhyy: false,
shzt: false,
})
const ids = ref([])
const chooseData = (val) => {
ids.value = val.map(item => {
return item.id
})
}
const isShow = ref(false)
const searchConfiger = ref([
{ label: "情报名称", prop: 'xsMc', placeholder: "请输入情报名称", showType: "input" },
{ label: "内容关键字", prop: 'xsNr', placeholder: "请输入语义关键字", showType: "input" },
{ label: "情报类型", prop: 'xlLx', placeholder: "请选择情报类型", showType: "select", options: D_GS_XS_LX },
{ label: "情报来源", prop: 'qbLy', placeholder: "请选择情报来源", showType: "select", options: D_GS_XS_LY },
{ label: "情报上报时间", prop: 'kssj', placeholder: "请选择开始时间", showType: "date" },
// { label: "结束时间", prop: 'jssj', placeholder: "请选择结束时间", showType: "date" },
{ label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" },
{ label: "姓名", prop: 'sjryxm', placeholder: "请输入姓名", showType: "input" },
{ label: "身份证号", prop: 'sjrysfzh', placeholder: "请输入身份证号", showType: "input" },
{ label: "群体名称", prop: 'qtmc', placeholder: "请输入群体名称", showType: "input" },
{ label: "指向地点", prop: 'zxdz', placeholder: "请输入指向地点", showType: "input" },
{ label: "指向时间", prop: 'zxkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
{ label: "录入时间", prop: 'lrkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
{ label: "情报类型", prop: 'qblx', placeholder: "请选择情报类型", showType: "select", options: D_GS_XS_LX },
{ label: "情报来源", prop: 'qbly', placeholder: "请选择情报来源", showType: "select", options: D_GS_XS_LY },
{ label: "情报处置状态", prop: 'czzt', placeholder: "请选择处置状态", showType: "select", options: D_GS_XS_CZZT },
{ label: "来源单位", prop: 'gxdwdm', placeholder: "请选择来源单位", showType: "department" },
{ label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" },
]);
const pageData = reactive({
tableData: [],
keyCount: 0,
@ -143,27 +171,26 @@ const pageData = reactive({
controlsWidth: 240,
tableColumn: [
{ label: "上报人姓名", prop: "xssbr" },
// { label: "上报人电话", prop: "xssbrdh" },
{ label: "情报编号", prop: "xsBh" },
{ label: "情报名称", prop: "xsMc" },
{ label: "情报类型", prop: "xlLx", showSolt: true },
{ label: "情报来源", prop: "qbLy", showSolt: true },
{ label: "情报上报时间", prop: "zxkssj" },
// { label: "结束时间", prop: "zxjssj" },
{ label: "情报标题", prop: "qbmc" },
{ label: "情报类型", prop: "qblx", showSolt: true },
{ label: "情报来源", prop: "qbly", showSolt: true },
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "指向地点", prop: "zxdz" },
{ label: "情报内容", prop: "xsNr" },
// { label: "处置状态", prop: "czzt",showSolt: true},
{ label: "附件", prop: "fjdz", showSolt: true },
// { label: "关联任务", prop: "xssbrdh" },//没有字段
{ label: "审核状态", prop: "shzt", showSolt: true },
{ label: "情报内容", prop: "qbnr" },
]
});
const queryFrom = ref({});
onMounted(() => {
getList()
tabHeightFn();
tabHeightFn()
});
@ -189,7 +216,17 @@ const handleSumbit = (row) => {
// 搜索
const onSearch = (val) => {
queryFrom.value = { ...val }
const { lrkssj, zxkssj } = val
console.log(lrkssj, zxkssj);
const promes = {
...pageData.pageConfiger,
lrkssj: lrkssj ? lrkssj[0] : '',
lrjssj: lrkssj ? lrkssj[1] : '',
zxkssj: zxkssj ? zxkssj[0] : '',
zxjssj: zxkssj ? zxkssj[1] : '',
}
queryFrom.value = { ...promes }
pageData.pageConfiger.pageCurrent = 1;
getList()
}
@ -206,8 +243,8 @@ const changeSize = (val) => {
// 获取列表
const getList = () => {
pageData.tableConfiger.loading = true;
let data = { ...pageData.pageConfiger, ...queryFrom.value, cjLx: '1' };
qcckGet(data, '/mosty-gsxt/qbcj/selectPage').then(res => {
let data = { ...pageData.pageConfiger, ...queryFrom.value };
qbcjSelectPage(data).then(res => {
pageData.tableData = res.records || [];
pageData.total = res.total;
pageData.tableConfiger.loading = false;
@ -216,17 +253,25 @@ const getList = () => {
// 删除
const delDictItem = (id) => {
proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
qcckPost({ id }, '/mosty-gsxt/qbcj/delete').then(() => {
qbcjDeletes({ ids: Array.isArray(id) ? id : [id] }).then((res) => {
proxy.$message({ type: "success", message: "删除成功" });
getList();
}).catch(() => {
})
}).catch(() => { });
}
// 导出
const exportFile = () => {
window.open('/mosty-api/mosty-gsxt/qbcj/exportQbsjcjDc?cjLx=1', '_self')
}
// 导出数据
const tableColumn = reactive([
{ label: "上报人姓名", prop: "xssbr" },
{ label: "情报编号", prop: "xsBh" },
{ label: "情报标题", prop: "qbmc" },
{ label: "情报类型", prop: "qblx", showSolt: true,zd:'D_GS_XS_LX' },
{ label: "情报来源", prop: "qbly", showSolt: true,zd:'D_GS_XS_LY' },
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "指向地点", prop: "zxdz" },
{ label: "情报内容", prop: "qbnr",showOverflowTooltip: true },
])
// 详情
const addEdit = (type, row) => {
@ -237,7 +282,7 @@ const addEdit = (type, row) => {
};
//发布
const confirm = (item) => {
qcckPost({id:item.id,sffb:1}, '/mosty-gsxt/qbcj/qbfb').then(res => {
qcckPost({ id: item.id, sffb: 1 }, '/mosty-gsxt/qbcj/qbfb').then(res => {
proxy.$message({ type: "success", message: "发布成功" });
getList();
})
@ -250,9 +295,10 @@ const tabHeightFn = () => {
tabHeightFn();
};
};
const dologShow = ref(false)
const dologShowFn = (val) => {
dologShow.value = true;
const exportFileModel = ref(false)
const dologCancel = () => {
exportFileModel.value = true;
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">社会信息人员建设管理{{ title }} </span>
<span class="title">力量建设管理{{ title }} </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
@ -121,21 +121,25 @@ const validateIdentity = () => {
const { proxy } = getCurrentInstance();
const dialogForm = ref(false); //弹窗
const formData = ref([
{ label: "管辖部门", prop: "gxbmDm", type: "department" },
{ label: "姓名", prop: "ryXm", type: "input" },
{ label: "联系电话", prop: "ryLxdh", type: "input" },
{ label: "身份证号", prop: "rySfzh", type: "input" },
{ label: "出生日期", prop: "ryCsrq", type: "date" },
{ label: "性别", prop: "ryXb", type: "select", options: props.dic.D_BZ_XB },
{ label: "民族", prop: "ryMz", type: "select", options: props.dic.D_BZ_MZ },
{ label: "学历", prop: "ryXl", type: "select", options: props.dic.D_BZ_WHCD },
// { label: "力量编号", prop: "bh", type: "input", width: "30%" },
{ label: "管辖部门", prop: "gxbmDm", type: "department", width: "30%" },
{ label: "姓名", prop: "ryXm", type: "input", width: "30%" },
{ label: "联系电话", prop: "ryLxdh", type: "input", width: "30%" },
{ label: "身份证号", prop: "rySfzh", type: "input", width: "30%" },
{ label: "出生日期", prop: "ryCsrq", type: "date", width: "30%" },
{ label: "性别", prop: "ryXb", type: "select", options: props.dic.D_BZ_XB, width: "30%" },
{ label: "民族", prop: "ryMz", type: "select", options: props.dic.D_BZ_MZ, width: "30%" },
{ label: "学历", prop: "ryXl", type: "select", options: props.dic.D_BZ_WHCD, width: "30%" },
{
label: "政治面貌",
prop: "ryZzmm",
type: "select",
options: props.dic.D_BZ_ZZMM
options: props.dic.D_BZ_ZZMM, width: "30%"
},
{ label: "所在单位", prop: "rySzdw", type: "input" },
{ label: "所在单位", prop: "rySzdw", type: "input", width: "30%" },
{ label: "工作阵地", prop: "gzzd", type: "input" , width: "45%"},
{ label: "作用发挥", prop: "zyfh", type: "input", width: "45%" },
{ label: "居住地地址", prop: "jzdDz", type: "textarea", width: "100%" }
]);
const listQuery = ref({}); //表单
@ -144,15 +148,15 @@ const elform = ref();
const title = ref("");
const rules = reactive({
gxbmDm: [{ required: true, message: "请选择管辖部门", trigger: "change" }],
ryXm: [{ required: true, message: "请输入人员姓名", trigger: "blur" }],
rySfzh: [
{
required: true,
message: "请输入人员身份证号",
trigger: ["blur", "change"]
},
{ trigger: ["blur", "change"], validator: validateIdentity() }
],
// ryXm: [{ required: true, message: "请输入人员姓名", trigger: "blur" }],
// rySfzh: [
// {
// required: true,
// message: "请输入人员身份证号",
// trigger: ["blur", "change"]
// },
// { trigger: ["blur", "change"], validator: validateIdentity() }
// ],
...rule.phoneRule({ require: true, validator: true }, "ryLxdh") // 是否必填 是否进行校验 可以传第二个参数
});
onMounted(() => { });

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="社会信息人员建设管理">
<PageTitle title="力量建设管理">
<el-button type="primary" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle">
<CirclePlus />
@ -83,11 +83,14 @@ const pageData = reactive({
},
controlsWidth: 120,
tableColumn: [
{ label: "编号", prop: "bh" },
{ label: "姓名", prop: "ryXm" },
{ label: "联系电话", prop: "ryLxdh" },
{ label: "身份证号", prop: "rySfzh" },
{ label: "工作阵地", prop: "gzzd",showOverflowTooltip: true },
{ label: "发挥作用", prop: "zyfh" ,showOverflowTooltip: true},
{ label: "民族", prop: "ryMz", showSolt: true },
{ label: "居住地址", prop: "jzdDz" }
{ label: "居住地址", prop: "jzdDz",showOverflowTooltip: true }
]
});

View File

@ -1,42 +1,53 @@
<template>
<el-dialog :title="title" width="800px" :model-value="modelShow" append-to-body @close="closed" :destroy-on-close="true" :close-on-click-modal="false">
<el-form :model="listQuery" inline :rules="rules" ref="formRef" :label-width="130" >
<el-form-item label="区域名称" prop="qymc">
<MOSTY.Other width="100%" clearable v-model="listQuery.qymc" placeholder="请输入区域名称"/>
</el-form-item>
<el-form-item label="区域类型" prop="qylx">
<MOSTY.Select v-model="listQuery.qylx" filterable :dictEnum="props.dic.D_ZDY_QYLX" width="100%" clearable placeholder="请选择区域类型"/>
</el-form-item>
<el-form-item label="区域级别" prop="qyjb">
<MOSTY.Select v-model="listQuery.qyjb" filterable :dictEnum="props.dic.D_ZDY_QYJB" width="100%" clearable placeholder="请选择区域类型"/>
</el-form-item>
<el-form-item label="行政区划" prop="xzqhdm" v-if="listQuery.qylx == 'xzqh'">
<MOSTY.Select v-model="listQuery.xzqhdm" filterable :dictEnum="props.dic.D_BZ_XZQHDM" width="100%" clearable placeholder="请选择行政区划"/>
</el-form-item>
<el-form-item label="地图范围" prop="pgis" class="ww100">
<div class="flex ww100">
<el-input v-model="listQuery.pgis" readonly placeholder="请输入地图范围" style="flex: 1;"></el-input>
<el-button type="primary" style="width: 136px;" class="ml10" @click="chooseMap">
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon>
<span style="vertical-align: middle">选择地图范围</span>
</el-button>
</div>
</el-form-item>
<el-form-item label="感知源信息" class="ww100">
<div class="flex ww100">
<div class="boo">
<span v-if="!listQuery.sxts || listQuery.sxts.length == 0" class="f14 ml10" style="color: #e1e1e1;">感知源信息</span>
<el-tag class="ml4 mr4" v-for="(it,idx) in listQuery.sxts" :key="idx">{{ it.sbmc }}</el-tag>
</div>
</div>
</el-form-item>
<div class="mapbox" v-if="showMap" v-loading="disabled"><GdMap></GdMap></div>
<div class="mt10 flex just-center">
<el-button @click="closed"> </el-button>
<el-button type="primary" @click="submit" v-loading="loading"> </el-button>
</div>
</el-form>
</el-dialog>
<el-dialog :title="title" width="800px" :model-value="modelShow" append-to-body @close="closed"
:destroy-on-close="true" :close-on-click-modal="false">
<el-form :model="listQuery" inline :rules="rules" ref="formRef" :label-width="130">
<el-form-item label="区域名称" prop="qymc">
<MOSTY.Other width="100%" clearable v-model="listQuery.qymc" placeholder="请输入区域名称" />
</el-form-item>
<el-form-item label="区域类型" prop="qylx">
<MOSTY.Select @change="changeMap" v-model="listQuery.qylx" filterable :dictEnum="props.dic.D_ZDY_QYLX"
width="100%" clearable placeholder="请选择区域类型" />
</el-form-item>
<el-form-item label="区域级别" prop="qyjb">
<MOSTY.Select v-model="listQuery.qyjb" filterable :dictEnum="props.dic.D_ZDY_QYJB" width="100%" clearable
placeholder="请选择区域类型" />
</el-form-item>
<el-form-item label="行政区划" prop="xzqhdm" v-if="listQuery.qylx == 'xzqh'">
<MOSTY.Select @change="changeXzqh" v-model="listQuery.xzqhdm" filterable :dictEnum="props.dic.D_BZ_XZQHDM"
width="100%" clearable placeholder="请选择行政区划" />
</el-form-item>
<el-form-item label="地图范围" prop="pgis" class="ww100">
<div class="flex ww100">
<el-input v-model="listQuery.pgis" readonly placeholder="请输入地图范围" style="flex: 1;"></el-input>
<el-button :disabled="listQuery.qylx == 'xzqh'" type="primary" style="width: 136px;" class="ml10" @click="chooseMap">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">选择地图范围</span>
</el-button>
</div>
</el-form-item>
<el-form-item label="感知源信息" class="ww100">
<div class="flex ww100">
<div class="boo" @click="openDialog = true">
<span v-if="!listQuery.sxts || listQuery.sxts.length == 0" class="f14 ml10"
style="color: #e1e1e1;">感知源信息</span>
<el-tag class="ml4 mr4" v-for="(it, idx) in listQuery.sxts" :key="idx">{{ it.sbmc }}</el-tag>
</div>
</div>
</el-form-item>
<div class="mapbox" v-if="showMap" v-loading="disabled">
<GdMap></GdMap>
</div>
<div class="mt10 flex just-center">
<el-button @click="closed"> </el-button>
<el-button type="primary" @click="submit" v-loading="loading"> </el-button>
</div>
</el-form>
</el-dialog>
<ChooseGzy v-model="openDialog" @choose="chooseDataGzy" :roleIds="roleIds"/>
</template>
<script setup>
@ -44,137 +55,209 @@ import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import emitter from "@/utils/eventBus.js";
import GdMap from "@/components/GdMap/index.vue";
import * as MOSTY from "@/components/MyComponents/index";
import { ref, defineProps, onMounted, nextTick ,onUnmounted} from "vue";
import { ref, defineProps, onMounted, nextTick, onUnmounted } from "vue";
import ChooseGzy from "@/components/ChooseList/ChooseGzy/index.vue";
import { bm } from '../xzqh'
const props = defineProps({
dic: {
type: Object,
default: () => ({})
},
dic: {
type: Object,
default: () => ({})
},
});
const disabled = ref(false)
const loading = ref(false)
const modelShow = ref(false);
const emit = defineEmits(["change"]);
const title = ref("新增区域");
const listQuery = ref({sxts:[],pgis:[]});
const listQuery = ref({ sxts: [], pgis: [] });
const formRef = ref();
const showMap = ref(false);
const rules = {
qymc: [{ required: true, message: "请输入区域名称", trigger: "blur" }],
qylx: [{ required: true, message: "请选择区域类型", trigger: "change" }],
qyjb: [{ required: true, message: "请选择区域级别", trigger: "change" }],
xzqhdm: [{ required: true, message: "请选择行政区划", trigger: "change" }],
pgis: [{ required: true, message: "请输入地图范围", trigger: ['change','blur'] }],
sxts: [{ required: true, message: "请输入感知元信息", trigger: "blur" }],
qymc: [{ required: true, message: "请输入区域名称", trigger: "blur" }],
qylx: [{ required: true, message: "请选择区域类型", trigger: "change" }],
qyjb: [{ required: true, message: "请选择区域级别", trigger: "change" }],
xzqhdm: [{ required: true, message: "请选择行政区划", trigger: "change" }],
pgis: [{ required: true, message: "请输入地图范围", trigger: ['change', 'blur'] }],
sxts: [{ required: true, message: "请输入感知元信息", trigger: "blur" }],
};
onMounted(()=>{
emitter.on('coordString',val=>{
if(val.flag == 'bkqy_ht') {
listQuery.value.pgis = val.coord;
emitter.emit('deletePointArea','gzy_ht');
disabled.value = true;
qcckPost({pgis:val.coord[0]},'/mosty-gsxt/tbGsxtBkQy/getSxtList').then(res=>{
listQuery.value.sxts = res || [];
let icon = require('@/assets/point/sp.png');
emitter.emit('addPointArea',{flag:'gzy_ht',icon,coords:listQuery.value.sxts});
disabled.value = false;
}).catch(()=>{
disabled.value = false;
})
}
})
onMounted(() => {
emitter.on('coordString', val => {
if (val.flag == 'bkqy_ht') {
listQuery.value.pgis = val.coord;
emitter.emit('deletePointArea', 'gzy_ht');
disabled.value = true;
qcckPost({ pgis: val.coord[0] }, '/mosty-gsxt/tbGsxtBkQy/getSxtList').then(res => {
listQuery.value.sxts = res || [];
let icon = require('@/assets/point/sp.png');
emitter.emit('addPointArea', { flag: 'gzy_ht', icon, coords: listQuery.value.sxts });
disabled.value = false;
}).catch(() => {
disabled.value = false;
})
}
})
})
// 初始化
const init = (type,row) => {
listQuery.value = {sxts:[],pgis:[]};
title.value = type === "add" ? "新增区域" : "编辑区域";
modelShow.value = true;
nextTick(() => {
showMap.value = true;
});
if(type === "edit") getDateById(row.id)
const init = (type, row) => {
listQuery.value = { sxts: [], pgis: [] };
title.value = type === "add" ? "新增区域" : "编辑区域";
modelShow.value = true;
nextTick(() => {
showMap.value = true;
});
if (type === "edit") getDateById(row.id)
};
// 更具id获取数据
const getDateById = (id) =>{
qcckGet({id},'/mosty-gsxt/tbGsxtBkQy/selectByid').then(res=>{
res.pgis = res.pgis ? [res.pgis]:[[[]]]
let icon = require('@/assets/point/sp.png');
nextTick(()=>{
if(res.sxts && res.sxts.length > 0) emitter.emit('addPointArea',{flag:'gzy_ht',icon,coords:res.sxts});
if(res.pgis){
let obj = { position: res.pgis, text:'', id: res.id };
emitter.emit("echoPlane", { coords: [obj], flag: "bkqy", type: "polygon" });
}
})
listQuery.value = res || {};
const getDateById = (id) => {
qcckGet({ id }, '/mosty-gsxt/tbGsxtBkQy/selectByid').then(res => {
res.pgis = res.pgis ? [res.pgis] : [[[]]]
let icon = require('@/assets/point/sp.png');
nextTick(() => {
if (res.qylx=='xzqh') {
emitter.emit('setBoundarys', {
data: {
type: "FeatureCollection",
features: [
{
geometry: {
type: "Polygon", // 多边形类型
coordinates: res.pgis // 坐标数组
},
properties: {}, // 属性信息
type: "Feature", // 特征类型
}
]
}
})
} else {
if (res.sxts && res.sxts.length > 0) emitter.emit('addPointArea', { flag: 'gzy_ht', icon, coords: res.sxts });
if (res.pgis) {
let obj = { position: res.pgis, text: '', id: res.id };
emitter.emit("echoPlane", { coords: [obj], flag: "bkqy", type: "polygon" });
}
}
})
listQuery.value = res || {};
})
}
// 地图选择
const chooseMap = () =>{
listQuery.value.pgis = [];
listQuery.value.sxts = [];
emitter.emit('removeEara','bkqy_ht')
emitter.emit('deletePointArea','bkqy')
emitter.emit('deletePointArea','gzy_ht')
emitter.emit('drawShape',{type:'polygon',flag:'bkqy_ht'})
const chooseMap = () => {
listQuery.value.pgis = [];
listQuery.value.sxts = [];
emitter.emit('removeEara', 'bkqy_ht')
emitter.emit('deletePointArea', 'bkqy')
emitter.emit('deletePointArea', 'gzy_ht')
emitter.emit('drawShape', { type: 'polygon', flag: 'bkqy_ht' })
}
// 提交
const submit = () => {
formRef.value.validate(valid => {
if(!valid) return false;
loading.value = true;
let params = { ...listQuery.value }
params.pgis = params.pgis[0]
let url = title.value == '新增区域' ? '/mosty-gsxt/tbGsxtBkQy/add' :'/mosty-gsxt/tbGsxtBkQy/update'
qcckPost(params,url).then(res=>{
loading.value = false;
emit('change');
closed();
}).catch(()=>{
loading.value = false;
})
});
formRef.value.validate(valid => {
if (!valid) return false;
loading.value = true;
let params = { ...listQuery.value }
if (params.qylx == 'xzqh') {
params.pgis = params.pgis
} else {
params.pgis = params.pgis[0]
}
let url = title.value == '新增区域' ? '/mosty-gsxt/tbGsxtBkQy/add' : '/mosty-gsxt/tbGsxtBkQy/update'
qcckPost(params, url).then(res => {
loading.value = false;
emit('change');
closed();
}).catch(() => {
loading.value = false;
})
});
};
const closed = () => {
emitter.emit('removeEara','bkqy_ht')
emitter.emit('deletePointArea','gzy_ht')
showMap.value = false;
formRef.value.resetFields();
modelShow.value = false;
emitter.emit('removeEara', 'bkqy_ht')
emitter.emit('deletePointArea', 'gzy_ht')
showMap.value = false;
roleIds.value=[]
formRef.value.resetFields();
modelShow.value = false;
};
const changeXzqh = (val) => {
emitter.emit('removeBj')
listQuery.value.pgis=bm[val]
emitter.emit('setBoundarys', {
data: {
type: "FeatureCollection",
features: [
{
geometry: {
type: "Polygon", // 多边形类型
coordinates: [bm[val]] // 坐标数组
},
properties: {}, // 属性信息
type: "Feature", // 特征类型
}
]
}
onUnmounted(()=>{
emitter.off("coordString");
})
}
const changeMap = (val) => {
if (val == 'xzqh') {
emitter.emit('removeEara', 'bkqy_ht')
emitter.emit('deletePointArea', 'bkqy')
} else {
emitter.emit('removeBj')
}
}
// 感知源弹窗
const openDialog = ref(false);
const roleIds=ref([])
const chooseDataGzy = (val) => {
roleIds.value = val.map(item => item.id)
listQuery.value.sxts = val.map(item => {
return {
sbbh:item.sbbh,
sblx:item.sblx,
sbmc:item.sbmc,
}}
)
}
onUnmounted(() => {
emitter.off("coordString");
})
defineExpose({
init
init
});
</script>
<style scoped lang="scss">
.mapbox{
position: relative;
margin-left: 40px;
width: calc(100% - 40px);
height: 320px;
background: red;
.mapbox {
position: relative;
margin-left: 40px;
width: calc(100% - 40px);
height: 320px;
background: red;
}
.boo{
width: 100%;
min-height: 32px;
max-height: 74px;
overflow: hidden;
overflow-y: auto;
border: 1px solid #e9e9e9;
border-radius: 4px;
padding: 4px;
box-sizing: border-box;
letter-spacing: 1px;
.boo {
width: 100%;
min-height: 32px;
max-height: 74px;
overflow: hidden;
overflow-y: auto;
border: 1px solid #e9e9e9;
border-radius: 4px;
padding: 4px;
box-sizing: border-box;
letter-spacing: 1px;
}
</style>
</style>

View File

@ -74,6 +74,7 @@ import Search from "@/components/aboutTable/Search.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { ElMessage } from "element-plus";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import { bs } from './xzqh'
const { proxy } = getCurrentInstance();
const { D_BZ_SF, D_ZDY_QYJB, D_ZDY_QYLX,D_BZ_XZQHDM } = proxy.$dict("D_BZ_SF","D_ZDY_QYJB","D_ZDY_QYLX","D_BZ_XZQHDM"); //获取字典数据
const searchBox = ref(); //搜索框
@ -133,6 +134,19 @@ const pageData = reactive({
{ label: "是否启用", prop: "qyzt", showSolt: true }
]
});
function stringTo2DArray(text) {
const items = text.split(',').map(item => parseFloat(item));
console.log(items);
return items.reduce((result, item, index) => {
if (index % 2 === 0) {
result.push([item]);
} else {
result[result.length - 1].push(item);
}
return result;
}, []);
}
onMounted(() => {
getList();

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
</div>
</div>
<div class="flex">
<div :class="dataOrge.gzlid?'ww80':'ww100'">
<div :class="dataOrge.gzlid ? 'ww80' : 'ww100'">
<div class="form_cnt">
<el-form :model="listQuery" :rules="rules" :disabled="disabled" ref="elform" inline :label-width="100"
label-position="left">
@ -56,14 +56,29 @@
</template>
</MyTable>
</div>
<div class="smallTitle">布控范围</div>
<div class=" mapSearch flex">
<el-select v-model="hzfs" placeholder="请选择布控范围" clearable @change="qhhzfs">
<el-option label="区域选择" value="1"></el-option>
<el-option label="自定义范围" value="2"></el-option>
</el-select>
<el-select multiple style="margin-left: 10px;" v-model="bkqyList" placeholder="请选择布控范围" clearable
@change="hzfsChage" v-if="hzfs == '1'">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in bkqyArr" :key="index">{{
item.label
}}</el-option>
</el-select>
<!-- <MOSTY.Select v-model="listQuery.bkqyList" filterable multiple :dictEnum="bkqyArr" style="width:350px"
placeholder="请选择布控范围" clearable /> -->
<el-button type="primary" @click="drawQy" style="margin-left: 10px;" v-else>
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">自定义区域</span>
</el-button>
</div>
<div class="ww100 relative mb10"
style="height: 250px;border: 1px solid #dcdfe6;border-radius: 4px;overflow: hidden;">
<div class="absolute mapSearch flex">
<MOSTY.Select v-model="listQuery.bkqyList" filterable multiple :dictEnum="bkqyArr" style="width:350px"
placeholder="请选择布控范围" clearable />
</div>
<GdMap></GdMap>
</div>
<!-- <el-form-item prop="bkBt" label="布控要素" style="width: 100%;">
@ -110,37 +125,7 @@
</div>
</div>
<div class="ww20" v-if="dataOrge.gzlid">
<!-- <div class="smallTitle">审批信息</div>
<div class="ww100">
<el-steps :active="listQuery.wccz" space="500" finish-status="success" direction="vertical" status=''>
<el-step :title="item.eventType == '0' ? '发起申请' : item.eventType == '1' ? '审批结束' : item.nodeName"
v-for="(item, index) in workflow" :key="index">
<template #description>
<div class="ww100 mt10 mb20 nodeBox" v-if="item.eventType == '0'||item.eventType == '1'">
<div class="nodeorgNameTg">{{ item.log.userData.orgname }}</div>
<div class="flex just-between nameTag">
<div>{{ item.log.userName }}</div>
<div class="fontColor">{{ item.eventType == '0' ? '发起' : '结束' }}</div>
</div>
<div>{{ item.log.xtLrsj }}</div>
</div>
<div v-else class="ww100 mt10 mb20 nodeBox">
<div :class="item.taskStatus=='2'?'nodeorgNameTg':'nodeorgNameDd'">{{ item.orgNameData.orgname }}</div>
<div v-for="(items, indexs) in item.log" :key="indexs">
<div class="flex just-between nameTag" >
<div>{{ items.userName }}</div>
<div :class="item.taskStatus=='2'?'fontColor':'fontColorDd'">审批中</div>
</div>
<div>{{ items.xtLrsj }}</div>
</div>
</div>
</template>
</el-step>
</el-steps>
</div> -->
<ApprovalEcho ref="approvalEcho"/>
<ApprovalEcho ref="approvalEcho" />
</div>
</div>
@ -168,11 +153,12 @@ import GdMap from "@/components/GdMap/index.vue";
import * as MOSTY from "@/components/MyComponents/index";
import MyTable from "@/components/aboutTable/MyTable.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { tableColumnList,Zd } from '@/views/backOfficeSystem/ApprovalInformation/tableRow.js'
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, nextTick, watch } from "vue";
import { tableColumnList, Zd } from '@/views/backOfficeSystem/ApprovalInformation/tableRow.js'
import emitter from "@/utils/eventBus.js";
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, nextTick, watch, onMounted } from "vue";
import { queryProcessNode, queryProcessNodeLog, queryProcess } from '@/api/spl'
import ApprovalEcho from "@/components/flowPath/ApprovalEcho.vue";
import { tbGsxtBkId } from "@/api/commit.js";
const emit = defineEmits(["change"]);
const props = defineProps({
dic: Object
@ -228,6 +214,7 @@ let tableDate = reactive({
{ label: "标签", prop: "bqList", showSolt: true, showOverflowTooltip: true }
]
});
const title = ref('')
const disabled = ref(false)
// 初始化数据
@ -237,11 +224,7 @@ const init = (type, row) => {
tableDate.tableConfiger.haveControls = true;
disabled.value = false;
listQuery.value.bkfqrXm = getItem("USERNAME");
console.log(getItem("USERNAME"));
listQuery.value.bkfqrSfzh = getItem("idEntityCard");
console.log( getItem("USERID"));
console.log( getItem("idEntityCard"));
listQuery.value.bkfqrSsbmmc = getItem("deptId")[0].deptName;;
listQuery.value.bkfqrSsbmdm = getItem("deptId")[0].deptCode;;
}
@ -249,7 +232,7 @@ const init = (type, row) => {
disabled.value = type == 'detail' ? true : false;
dialogForm.value = true;
if (row) tableDate.tableConfiger.haveControls = false;
Zd({D_GS_BK_DJ:props.dic.D_GS_BK_DJ,BD_BK_CLYJBQ:props.dic.BD_BK_CLYJBQ})
Zd({ D_GS_BK_DJ: props.dic.D_GS_BK_DJ, BD_BK_CLYJBQ: props.dic.BD_BK_CLYJBQ })
get_bkqy_list(row)
};
@ -264,32 +247,23 @@ const get_bkqy_list = (row) => {
if (row) getDataById(row.id);
})
}
const dataOrge=ref({})
const dataOrge = ref({})
const approvalEcho = ref()
watch(() => approvalEcho.value, (val) => {
if (val) {
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
}
},{deep:true})
}, { deep: true })
// 根据id获取详情
const getDataById = (id) => {
qcckGet({}, '/mosty-gsxt/tbGsxtBk/selectVoById/' + id).then(res => {
res.bkfj = res.ossList || [];
res.bkqyList = res.qyList ? res.qyList.map(v => v.id) : [];
listQuery.value = res || {}
dataOrge.value=res
tableDate.tableColumn = tableColumnList[res.bkDx ? res.bkDx : '01']
})
}
watch(() => approvalEcho.value, (val) => {
if (val) {
console.log(approvalEcho.value);
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
}
},{deep:true})
}, { deep: true })
const shangeDx = () => {
@ -342,7 +316,7 @@ const choosed = (val) => {
id: item.id, fjZp: item.fjZp, ryXm: item.ryXm, ryXb: item.ryXb,
rySfzh: item.rySfzh, ryHjd: item.hjdXz, ryXjd: item.xzdXz,
rySjhm: item.ryLxdh, qtXnsf: item.qtXnsf, clCjh: item.clCjh,
clCph: item.clCph, qtTzms: item.qtTzms, bqList: bqs, yjdj: item.zdrYjdj,ssbmdm:item.zrSsbmdm
clCph: item.clCph, qtTzms: item.qtTzms, bqList: bqs, yjdj: item.zdrYjdj, ssbmdm: item.zrSsbmdm
}
})
listQuery.value.bkdxList = [...addPerson.value, ...arr];
@ -352,7 +326,7 @@ const choosed = (val) => {
return {
clCph: item.hphm, clCjh: item.clCjh, clSyr: item.clSyr, clSyrsfzh: item.clSyrsfzh,
clYs: item.clYs, gxSsbmmc: item.gxSsbmmc,yjbq: item.yjbq, yjdj: item.yjdj,ssbmdm:item.zrSsbmdm
clYs: item.clYs, gxSsbmmc: item.gxSsbmmc, yjbq: item.yjbq, yjdj: item.yjdj, ssbmdm: item.zrSsbmdm
}
})
listQuery.value.bkdxList = [...addPerson.value, ...arr];
@ -374,7 +348,7 @@ const choosed = (val) => {
rySfzh: item.rySfzh, ryHjd: item.hjdXz, ryXjd: item.xzdXz,
rySjhm: item.ryLxdh, qtXnsf: item.qtXnsf, clCjh: item.clCjh,
clCph: item.clCph, qtTzms: item.qtTzms, bqList: bqs,
yjdj: item.zdrYjdj,ssbmdm:item.zrSsbmdm
yjdj: item.zdrYjdj, ssbmdm: item.zrSsbmdm
}
})
listQuery.value.bkdxList = brrPeo;
@ -427,7 +401,13 @@ const submit = () => {
});
});
};
onMounted(() => {
emitter.on("coordString", (res) => {
listQuery.value.bkqyList = [{
pgis: res.coord[0],
}]
});
});
// 关闭
const close = () => {
listQuery.value = {};
@ -435,7 +415,7 @@ const close = () => {
loading.value = false;
addPerson.value = [];
roleIds.value = []
dataOrge.value={}
dataOrge.value = {}
};
// 选择身份证
const chooseVisible_SFZ = ref(false)
@ -468,11 +448,103 @@ const getWorkflow = async (id) => {
log: log
}
}
})
};
const drawQy = () => {
emitter.emit("drawShape", {
flag: "select_point",
type: "polygon",
isclear: true
});
}
const hzfs = ref('1')
const bkqyList = ref()
const qhhzfs = () => {
listQuery.value.bkqyList = []
bkqyList.value = []
emitter.emit('removeBj')
emitter.emit('removeEara', "select_point")
}
const hzfsChage = (val) => {
const qyList = []
console.log(val);
listQuery.value.bkqyList = val.map((item, index) => {
const data = bkqyArr.value.filter(items => items.id == item)[0]
console.log(data);
if (data) {
qyList.push(data.pgis)
}
console.log(item);
return {
bkQyid: data.id,
pgis: data.pgis
}
})
setTimeout(() => {
changeXzqh(qyList)
}, 2000)
}
const changeXzqh = (val) => {
// 先移除已有的边界
emitter.emit('removeBj')
// 如果传入的是多个区域数据(二维数组)
const features = val.map((area, index) => ({
geometry: {
type: "Polygon",
coordinates: [area] // 确保格式正确
},
properties: {
},
type: "Feature"
}))
// 循环为每个区域创建单独的多边形,这样可以设置不同的样式
features.forEach((feature, index) => {
emitter.emit('setBoundarys', {
data: {
type: "FeatureCollection",
features: [feature]
},
color: '#cf1010',
fillColor: 'rgba(255, 255, 255,0)',
})
})
}
// 根据id获取详情
const getDataById = (id) => {
qcckGet({}, '/mosty-gsxt/tbGsxtBk/selectVoById/' + id).then(res => {
res.bkfj = res.ossList || [];
listQuery.value = res || {}
dataOrge.value = res
if (res.bkqyList) {
bkqyList.value = res.bkqyList ? res.bkqyList.map(v => {
{
if (v.bkQyid) {
hzfs.value = '1'
} else {
hzfs.value = '2'
}
return v.bkQyid
}
}) : [];
const data = res.bkqyList.map(item => {
return item.pgis
})
setTimeout(() => {
console.log(data);
changeXzqh(data)
// listQuery.value.bkDxxx = data.join(',')
}, 2000);
}
tableDate.tableColumn = tableColumnList[res.bkDx ? res.bkDx : '01']
})
}
defineExpose({ init });
</script>
@ -489,9 +561,8 @@ defineExpose({ init });
}
.mapSearch {
left: 10px;
top: 10px;
z-index: 100;
margin-bottom: 10px;
}
.dialog {
@ -538,9 +609,11 @@ defineExpose({ init });
color: #000000 !important;
border-color: #000000 !important;
}
::v-deep .el-step__description{
::v-deep .el-step__description {
padding: 0 !important;
}
::v-deep .el-step__description.is-wait {
color: #000000 !important;
@ -584,7 +657,9 @@ defineExpose({ init });
.fontColor {
color: #1abe20;
} .fontColorDd {
}
.fontColorDd {
color: #18a2dd;
}
}

View File

@ -0,0 +1,195 @@
<template>
<!-- 直接使用box作为根元素减少嵌套层级 -->
<div class="box" ref="chartDom" style="width: 100%; margin: 0; padding: 0;"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from "vue";
import * as echarts from "echarts";
let chartDom = ref(null); //注意变量名 和 ref名字要对应
const props = defineProps({
title: {
type: String,
default: '2023年1月1日至2023年12月31日'
},
xAxisData: {
type: Array,
default: () => ['A', 'B', 'C', 'D', 'E', 'F']
},
seriesData: {
type: Array,
default: () => [[2549], [12421], [2637],[ 3146],[ 15189], [9562]]
},
// yAxisData: {
// type: Array,
// default: () => [2549, 12421, 2637, 3146, 15189, 9562]
// },
});
// 保存图表实例的引用
const myChart = ref(null);
let resizeTimer = null;
const chartInstance = ref(null);
onMounted(() => {
// 确保DOM渲染完成后再初始化图表
setTimeout(() => {
initChart();
}, 0);
// 监听窗口大小变化,确保图表能正确调整大小
window.addEventListener('resize', handleResize);
});
// 组件卸载时清理监听器
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
if (resizeTimer) {
clearTimeout(resizeTimer);
}
// 销毁图表实例
if (myChart.value) {
myChart.value.dispose();
}
});
// 处理窗口大小变化的函数
const handleResize = () => {
// 防抖处理,避免频繁调用
if (resizeTimer) {
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(() => {
// 如果图表实例存在调用resize方法
if (myChart.value) {
myChart.value.resize();
}
}, 200);
};
watch([
() => props.seriesData,
() => props.xAxisData,
], () => {
initChart();
},{deep:true});
const initChart = () => {
chartInstance.value = props.seriesData.map((item, index) => {
return {
name: props.xAxisData[index],
data: item,
type: "bar",
barWidth: "20",
// barGap: 20, // 系列之间的间距
barCategoryGap: '20%', // 使用百分比更适应不同宽度
label: {
show: true,
position: 'top',
formatter: function (params) {
// 值为0或null时不显示
if (params.value === 0 || params.value === null) {
return '';
}
// 格式化数值显示
return params.value.toLocaleString();
},
color: '#2c3e50',
fontSize: 12,
fontWeight: 'bold',
distance: 10 // 标签与柱子的距离
},
}
})
// 保存图表实例以便后续调用resize
myChart.value = echarts.init(chartDom.value);
// 重置容器大小确保占满
chartDom.value.style.width = '100%';
var option = {
title: {
text: props.title,
left: 'center'
},
tooltip: {
// 鼠标悬浮提示数据
trigger: "axis",
backgroundColor: "rgba(32, 33, 36,.7)",
borderColor: "rgba(32, 33, 36,0.20)",
borderWidth: 15,
textStyle: {
// 文字提示样式
color: "#fff",
fontSize: "12",
},
axisPointer: {
// 坐标轴虚线
type: "cross",
label: {
backgroundColor: "#6a7985",
},
},
},
legend: {
right: 0
},
// },
grid: {
// 控制图表的位置,设置为最紧凑以占满整个容器
left: "2%",
right: "2%",
top: "15%",
bottom: "3%",
containLabel: true,
},
xAxis: {
data: props.xAxisData,
},
yAxis: {
// axisLabel: {
// // y轴线 标签修改
// textStyle: {
// color: "white", //坐标值得具体的颜色
// },
// },
// data: props.xAxisData,
},
series: chartInstance.value
};
myChart.value.setOption(option);
// 初始时强制调整大小,确保完全适应容器
setTimeout(() => {
if (myChart.value) {
myChart.value.resize();
}
}, 100);
};
</script>
<style scoped>
/* 根容器样式,确保完全占满父容器 */
.box {
width: 100% !important;
height: 60vh;
margin: 0 !important;
padding: 0 !important;
box-sizing: border-box !important;
display: block !important;
position: relative !important;
}
/* 确保ECharts实例占满容器 */
:deep(.echarts) {
width: 100% !important;
height: 100% !important;
min-width: 0 !important;
max-width: none !important;
}
/* 为父级元素设置样式,确保没有额外的内边距 */
:deep(.el-dialog__body) {
padding: 0 !important;
}
/* 防止任何默认的边距或内边距影响 */
* {
box-sizing: border-box !important;
}
</style>

View File

@ -0,0 +1,200 @@
<template>
<!-- 将固定id改为ref引用 -->
<div ref="chartContainer" style="height: 100%;"></div>
</template>
<script setup>
import * as echarts from 'echarts';
import { onMounted, onUnmounted, ref, watch, defineProps } from 'vue';
// 定义组件的属性,使其可复用
const props = defineProps({
// 图表数据
chartData: {
type: Array,
default: () => [
{ value: 40, name: 'rose 1' },
{ value: 38, name: 'rose 2' },
{ value: 32, name: 'rose 3' },
{ value: 30, name: 'rose 4' },
{ value: 28, name: 'rose 5' },
{ value: 26, name: 'rose 6' },
{ value: 22, name: 'rose 7' },
{ value: 18, name: 'rose 8' }
]
},
// 图表标题
chartName: {
type: String,
default: 'Nightingale Chart'
},
// 是否显示工具箱
showToolbox: {
type: Boolean,
default: true
},
// 是否显示图例
showLegend: {
type: Boolean,
default: true
},
// 内半径
innerRadius: {
type: Number,
default: 0
},
// 外半径
outerRadius: {
type: Number,
default: 200
},
// 扇形间距
padAngle: {
type: Number,
default: 0
},
title: {
type: Object,
default: () => ({
text: 'Nightingale Chart',
left: 'center'
})
},
roseType: {
type: String,
default: 'radius'
}
});
// 图表容器引用
const chartContainer = ref(null);
// 图表实例引用
const chartInstance = ref(null);
// 初始化图表
const initChart = () => {
const chartDom = chartContainer.value;
if (!chartDom) return;
// 如果已经存在实例,先销毁
if (chartInstance.value) {
chartInstance.value.dispose();
}
// 创建新实例
chartInstance.value = echarts.init(chartDom);
// 设置图表选项
const option = {
title: props.title,
legend: props.showLegend ? {
top: 'bottom'
} : false,
toolbox: props.showToolbox ? {
show: true,
feature: {
mark: { show: true },
dataView: { show: true, readOnly: false },
restore: { show: true },
saveAsImage: { show: true }
}
} : false,
series: [
{
name: props.chartName,
type: 'pie',
radius: [props.innerRadius, props.outerRadius],
center: ['50%', '50%'],
roseType: props.roseType,
// 在 ECharts 5.3.3 中,当 roseType 为 'area' 时padAngle 需要特殊处理
// 为了确保间距生效我们需要添加一个小的非零值来替代0
// padAngle: props.padAngle === 0 ? 0.1 : props.padAngle,
itemStyle: {
borderColor: '#fff',
borderWidth:props.padAngle
},
// 显示百分比
label: {
show: true,
formatter: function(params) {
// 对于值为0的项显示0%而不是极小值计算出的百分比
if (props.chartData.find(d => d.name === params.name && d.value === 0)) {
return params.name + ': 0%';
}
return params.name + ': ' + params.percent + '%';
}
},
// 鼠标悬停时的样式
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'bold',
formatter: function(params) {
// 对于值为0的项显示0%而不是极小值计算出的百分比
if (props.chartData.find(d => d.name === params.name && d.value === 0)) {
return params.name + ': 0%';
}
return params.name + ': ' + params.percent + '%';
}
}
},
// 处理数据确保值为0的项也能显示
data: props.chartData.map(item => ({
...item,
// 对于值为0的数据设置一个极小值来确保它在饼图中显示
value: item.value === 0 ? 0.0000001 : item.value
}))
}
]
};
// 应用选项
chartInstance.value.setOption(option);
};
// 处理窗口大小变化,自动调整图表大小
const handleResize = () => {
if (chartInstance.value) {
chartInstance.value.resize();
}
};
// 组件挂载时初始化图表
onMounted(() => {
initChart();
window.addEventListener('resize', handleResize);
});
// 组件卸载时销毁图表实例并移除事件监听
onUnmounted(() => {
if (chartInstance.value) {
chartInstance.value.dispose();
}
window.removeEventListener('resize', handleResize);
});
// 监听数据变化,更新图表
watch(() => props.chartData, () => {
initChart();
}, { deep: true });
// 监听其他配置变化,更新图表
watch([
() => props.chartName,
() => props.showToolbox,
() => props.showLegend,
() => props.innerRadius,
() => props.outerRadius,
() => props.padAngle,
()=> props.roseType,
], () => {
initChart();
});
</script>
<style scoped>
:deep(div) {
width: 100%;
height: 100%;
/* min-height: 400px; */
}
</style>

View File

@ -0,0 +1,441 @@
<template>
<div>
<!-- <div class="titleBox">
<PageTitle title="警情分析报告">
<el-button type="primary" @click="generatePDF()">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">导出</span>
</el-button>
</PageTitle>
</div> -->
<!-- 搜索 -->
<!-- <div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch">
<template #defaultSlot>
<el-select v-model="bjlbList" placeholder="请选择情报类型" multiple collapse-tags>
<el-option v-for="item in dictItemList" :key="item.dm" :label="item.zdmc" :value="item.dm" />
</el-select>
</template>
</Search>
</div> -->
<div style="background-color: #fff;color: black;padding: 15px;overflow: auto;" :style="{ height: tabHeight + 'px' }"
ref="tableBox">
<div style="border-bottom: 1px #ccc solid;padding-bottom: 30px;">
<h1 class="headline">{{ nd }}年度西藏公安战术研判报告</h1>
<div style="display: flex;align-items: center;justify-content: space-between; color: red;margin-top: 30px;padding: 0 30px;font-size: 18px;font-weight: 700;">
<div>{{ deptId.name }}</div>
<div>{{ deptId?.ord }}</div>
<div>{{ deptId?.time }}</div>
</div>
</div>
<p>为全面客观准确掌握全区公安机关的执法状况自治区
公安厅基于数据统计对全区公安机关{{ nd }}年度的执法状况作
了客观分析</p>
<h2>执法状况总体分析</h2>
<h2>1.接处警情况</h2>
<h2>1.1接报警情</h2>
<p>
{{ timeValidate(TimeValue.startTime, 'td') }}{{ timeValidate(TimeValue.endTime, 'td') }}
全区公安机关共
接报各类警情{{ dataList.XsfxTj.total }},同比{{ `${dataList.XsfxTj.tbbsb > 0 ? "下降" : "上升"}
${dataList.XsfxTj.tbbsb}%,同比${dataList.XsfxTj.tbbsb > 0 ? "下降" : "上升"}${dataList.XsfxTj.tbbsb}%` }}</p>
<h2>1.1.1类型维度</h2>
<p>
从警情类型来看{{ sortingRatioValue.Ydfx[0]?.name }}警情最多占到{{ sortingRatioValue.Ydfx[0]?.ratio }}其次为{{
sortingRatioValue.Ydfx[1]?.name }}警情占到{{ sortingRatioValue.Ydfx[1]?.ratio }}
</p>
<MaleNightingalePicture roseType="area" style="height: 550px;" :title="{ text: '接警情类型', left: 'center' }"
:chartData="dataList.jqlxTj" :chartName="'接警情类型'" :innerRadius="0" :padAngle="4" />
<h2>1.1.2来源维度</h2>
<p>
从警情来源来看{{ sortingRatioValue.Jqlx[0]?.name }}警情最多占到{{ sortingRatioValue.Jqlx[0]?.ratio }}其次为{{
sortingRatioValue.Jqlx[1]?.name }}警情占到{{ sortingRatioValue.Jqlx[1]?.ratio }}
</p>
<MaleNightingalePicture roseType="area" :title="{ text: '警情来源', left: 'center' }" style="height: 550px;"
:chartData="dataList.jqlyTj" :innerRadius="50" :outerRadius="150" :padAngle="4" />
<h2>1.1.3地域维度</h2>
<p>从地市分布地市来看{{ sortingRatioValue.Dywdtj[0]?.ssbm }}警情量最大占到全区警情总
量的{{ sortingRatioValue.Dywdtj[0]?.ratio }}
<span v-if="sortingRatioValue.Dywdtj.length > 1">
其次为{{ sortingRatioValue.Dywdtj[1]?.ssbm }}
<span v-if="sortingRatioValue.Dywdtj.length > 2">
<span v-if="sortingRatioValue.Dywdtj.length > 3">
{{ sortingRatioValue.Dywdtj[3]?.ssbm }}两市警情量较为接近
</span>
<span>
警情量最少的为{{ sortingRatioValue.Dywdtj[sortingRatioValue.Dywdtj.length - 1]?.ssbm }}
</span>
</span>
</span>
</p>
<Histogram title="地市分布" :xAxisData="dataList.dyTj.xAxisData" :seriesData="dataList.dyTj.seriesData" />
<h2>1.1.4时间维度</h2>
<p>
我们将所有警情按照月份划分进行统计发现每月警情分布
较为平均最高月份为
{{ sortingRatioValue.Ydfx[0]?.month }}占到{{ sortingRatioValue.Ydfx[0]?.ratio }}
<span v-if="sortingRatioValue.Ydfx.length > 1">
最低月份为{{ sortingRatioValue.Ydfx[sortingRatioValue.Ydfx.length - 1]?.month }}
占到{{ sortingRatioValue.Ydfx[sortingRatioValue.Ydfx.length - 1]?.ratio }}
考虑是因为{{ sortingRatioValue.Ydfx[0]?.month }}月为我区传统旅游旺季进藏人员较多
<!-- {{sortingRatioValue.Ydfx[sortingRatioValue.Ydfx.length-1]?.month}}月一般春节及藏历新年期间在藏人员较少 -->
</span>
</p>
<MaleNightingalePicture :title="{ text: '警情分布', left: 'center' }" style="height: 550px;"
:chartData="dataList.ydTj" :innerRadius="10" :outerRadius="150" :padAngle="2" />
<!-- <p>
按照24小时每小时时段进行划分后发现警情多发时段集
中在9时至20时每小时均在1000起以上
</p> -->
<h2>1.2警情处置</h2>
<h2>1.2.1结果维度</h2>
<p>
从警情处置结果来看
<span v-for="(item, index) in sortingRatioValue.Cljgf">
{{ `${item.name}占到${item.ratio}` }}
</span>
</p>
<MaleNightingalePicture :title="{ text: '警情处置', left: 'center' }" style="height: 550px;"
:chartData="dataList.CljgfTj" :innerRadius="0" :outerRadius="150" :padAngle="2" />
<h2>1.2.2效率维度</h2>
<p>从处警效率来看{{ sortingRatioValue.Czlfx[1]?.name }}处警的占到{{ sortingRatioValue.Czlfx[0]?.ratio
}}表明我区公安机关在接警之后能够在第一时间处警
</p>
<MaleNightingalePicture :title="{ text: '效率维度', left: 'center' }" style="height: 550px;"
:chartData="dataList.withinTj" :innerRadius="0" :outerRadius="150" :padAngle="0" />
</div>
</div>
<AddForm ref="addForm" :dict="{ D_GS_XS_LX }" />
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Search from "@/components/aboutTable/Search.vue";
import MaleNightingalePicture from './components/maleNightingalePicture.vue'
import Histogram from './components/histogram.vue'
import { timeValidate } from '@/utils/tools.js'
import { getItem, setItem } from '@/utils/storage'
import { fxbgDywdtj, getDictItem, fxbgJqlxtj, fxbgJqlytj, fxbgYdfx, fxbgXsfx, fxgbCljgf, fxgbCzlfx, fxbgTj } from '@/api/semanticAnalysis'
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { reactive, ref, onMounted, getCurrentInstance, nextTick, computed, watch } from "vue";
const props = defineProps({
// 数据
search: {
type: Array,
default: null
}
})
const { proxy } = getCurrentInstance();
const { D_GS_XS_LX } = proxy.$dict("D_GS_XS_LX"); //获取字典数据
const dictItemList = ref([])
const searchConfiger = reactive([
{
label: "时间",
showType: "daterange",
prop: "startTime",
placeholder: "请输入警情名称",
},
{
showType: "defaultSlot",
// prop: "bjlbList",
placeholder: "请选择情报类型",
label: "警情类别"
},
])
const bjlbList = ref([])
onMounted(() => {
tabHeightFn()
})
const tabHeight = ref(0)
// 表格高度计算
const tabHeightFn = () => {
tabHeight.value = window.innerHeight - 300
window.onresize = function () {
tabHeightFn();
};
};
const pageData = reactive({
parameter: {},
total: 0,
loading: false,
tableData: []
})
const onSearch = (val) => {
const promes = {
startTime: val.startTime ? val.startTime[0] : '',
endTime: val.startTime ? val.startTime[1] : '',
}
const bjlbLists = bjlbList.value ? bjlbList.value.join(',') : ""
pageData.parameter = { bjlbList: bjlbLists, ...promes }
funAll()
}
// 数据处理
const dataList = reactive({
dyTj: {
xAxisData: [],
seriesData: [],
},
jqlxTj: [],
jqlyTj: [],
CljgfTj: [],
XsfxTj: [],
})
const sortingRatioValue = reactive({
Dywdtj: [],
Ydfx: [],
Cljgf: [],
Czlfx: [],
Lyfx: [],
Jqlx: []
})
const sortingRatio = (data) => {
// 提取所有number值
// 计算总数
const total = data.reduce((sum, item) => sum + item.number, 0);
// 找出第一大和第二大的值及其对应的name
const sortedData = [...data].sort((a, b) => b.number - a.number);
const dataValue = sortedData.map(item => {
return {
...item,
ratio: total > 0 ? (item.number / total * 100).toFixed(2) + '%' : '0%',
}
})
return dataValue
}
// 地域统计
const getfxbgDywdtj = () => {
let params = {
...pageData.parameter,
}
fxbgDywdtj(params).then(res => {
dataList.dyTj.xAxisData = res.map(it => it.ssbm)
dataList.dyTj.seriesData = [];
for (let i = 0; i < res.length; i++) {
dataList.dyTj.seriesData[i] = [];
for (let j = 0; j < res.length; j++) {
dataList.dyTj.seriesData[i][j] = 0;
}
}
for (let i = 0; i < dataList.dyTj.seriesData.length; i++) {
dataList.dyTj.seriesData[i][i] = res[i].number
}
sortingRatioValue.Dywdtj = sortingRatio(res)
})
}
// 警情类型统计
const getfxbgJqlxtj = () => {
let params
if (pageData.parameter.bjlbList) {
params = {
...pageData.parameter,
}
} else {
params = {
...pageData.parameter,
bjlbList: dictItemList.value.map(item => item.dm).join(',')
}
}
fxbgJqlxtj(params).then(res => {
sortingRatioValue.Jqlx = sortingRatio(res)
dataList.jqlxTj = res.map(item => {
return {
name: item.name,
value: item.number
}
})
})
}
// 警情来源统计
const getfxbgJqlytj = () => {
let params = {
...pageData.parameter,
}
fxbgJqlytj(params).then(res => {
sortingRatioValue.Lyfx = sortingRatio(res)
dataList.jqlyTj = res.map(item => {
return {
name: item.name,
value: item.number
}
})
})
}
//分析报告-时间维度-月分析
const getfxbgYdfx = () => {
let params = {
...pageData.parameter,
}
fxbgYdfx(params).then(res => {
sortingRatioValue.Ydfx = sortingRatio(res)
dataList.ydTj = res.map(item => {
return {
name: item.month,
value: item.number
}
})
})
}
// 分析报告-处理结果分析
const getfxgbCljgf = () => {
let params = {
...pageData.parameter,
}
fxgbCljgf(params).then(res => {
sortingRatioValue.Cljgf = sortingRatio(res)
dataList.CljgfTj = res.map(item => {
return {
name: item.name,
value: item.number
}
})
})
}
// 分析报告-处置率分析
const getfxgbCzlfx = () => {
let params = {
...pageData.parameter,
}
fxgbCzlfx(params).then(res => {
dataList.withinTj = [{
name: "超时分流(超过24小时)",
value: res.within24h ? res.within24h : 0
}, {
name: "按时分流(24小时内)",
value: res.over24h ? res.over24h : 0
}]
sortingRatioValue.Czlfx = sortingRatio(dataList.withinTj)
})
}
const getfxbgTj = () => {
let params = {
...pageData.parameter,
}
fxbgTj(params).then(res => {
console.log(res, "xxx");
dataList.XsfxTj = res
})
}
const TimeValue = ref({
startTime: '',
endTime: ''
})
const nd = ref()
watch(() => pageData.parameter, (newVal) => {
if (newVal.startTime) {
TimeValue.value.startTime = newVal.startTime
TimeValue.value.endTime = newVal.endTime
if (timeValidate(newVal.startTime, 'yd') == timeValidate(newVal.endTime, 'yd')) {
nd.value = timeValidate(newVal.startTime, 'yd')
} else {
nd.value = `${timeValidate(newVal.startTime, 'yd')}${timeValidate(newVal.endTime, 'yd')}`
}
}
}, { deep: true })
const deptId = ref({
name: ''
})
const Time = () => {
const currentYear = new Date().getFullYear();
const startOfYear = new Date(currentYear, 0, 1); // 今年1月1日
const endOfYear = new Date(currentYear, 11, 31, 23); // 今年12月31日23:59:59.999
const year = startOfYear.getFullYear();
const month = String(startOfYear.getMonth() + 1).padStart(2, '0');
const day = String(startOfYear.getDate()).padStart(2, '0');
const endYear = endOfYear.getFullYear();
const endMonth = String(endOfYear.getMonth() + 1).padStart(2, '0');
const endDay = String(endOfYear.getDate()).padStart(2, '0');
const devt = getItem('deptId')
deptId.value.name = devt[0].deptName
nd.value = timeValidate('', 'yd')
deptId.value.time = timeValidate('', 'ydm')
deptId.value.ord=timeValidate('', 'mm')
TimeValue.value.startTime = `${year}-${month}-${day}`
TimeValue.value.endTime = `${endYear}-${endMonth}-${endDay}`
}
Time()
const funAll = () => {
getfxbgDywdtj()
getfxbgJqlxtj()
getfxbgJqlytj()
getfxgbCljgf()
getfxbgYdfx()
getfxgbCzlfx()
getfxbgTj()
}
const getDictItemList = () => {
const promes = {
startTime: props.search.startTime ,
endTime: props.search.endTime,
}
if (props.search.lx) {
const bjlbLists = props.search.lx ? props.search.lx.join(',') : ""
pageData.parameter = { bjlbList: bjlbLists, ...promes }
funAll()
} else {
const promesing = {
dictCode: "00000000"
}
getDictItem(promesing).then(res => {
const bjlbLists = res.map(item=>item.dm).join(',')?res.map(item=>item.dm).join(','):""
pageData.parameter = { bjlbList: bjlbLists, ...promes }
funAll()
})
}
}
const data = ref()
watch(() => dictItemList.value, (val) => {
data.value = val
}, { deep: true })
getDictItemList()
const tableBox = ref(null);
</script>
<style lang="scss" scoped>
.headline {
text-align: center;
color: red;
}
p {
text-indent: 2em;
/* 首行缩进2个汉字 */
margin: 1em 0;
/* 段落间距 */
line-height: 1.6;
/* 行高 */
font-size: 16px;
/* 字体大小 */
text-align: justify;
/* 两端对齐 */
}
/* 特殊情况处理 */
p.no-indent {
text-indent: 0;
/* 不需要缩进的段落 */
}
p.first-no-indent:first-of-type {
text-indent: 0;
/* 第一个段落不缩进 */
}
</style>

View File

@ -0,0 +1,28 @@
<template>
<el-dialog :title="title" v-model="visible" width="80%" destroy-on-close>
<JudgmentReport :search="search"/>
</el-dialog>
</template>
<script setup>
import { ref, reactive ,watch} from 'vue'
import JudgmentReport from './AnalysisReport/index.vue'
const title = ref('详情')
const props = defineProps({
visible: {
type: Boolean,
default: false
},
search: {
type: Object,
default: null
}
})
const opebg = ref(false)
watch(() => props.visible, (val) => {
opebg.value = val
},{immediate:true})
const emit=defineEmits(['update:visible'])
</script>

View File

@ -14,7 +14,6 @@
<MoreBarEcharts echartsId="cztjEcharts" :data="obj.data_lxtj"></MoreBarEcharts>
</div>
</div>
<div class="hh50">
<div class="comm-title">会商统计</div>
<div class="echartsBox">
@ -35,10 +34,10 @@
<div ref="searchBox">
<el-form :model="searchList" ref="searchFormRef" :inline="true">
<el-form-item label="类型">
<el-cascader ref="cascaRef" @change="changeCascader" :disabled="readonly_lx" v-model="searchList.lx" clearable
:options="cascaderList" :props="{ checkStrictly: true,multiple: true }" placeholder="请选择类型" />
<el-cascader ref="cascaRef" v-model="searchList.lx" @change="changeCascader" collapse-tags
:disabled="readonly_lx" :options="cascaderList" :props="{ multiple: true }" placeholder="请选择类型" />
</el-form-item>
<el-form-item label="人员">
<!-- <el-form-item label="人员">
<el-input @change="changeRy" v-model="searchList.ry" :disabled="readonly_ry" clearable
placeholder="请输入姓名或身份证"></el-input>
</el-form-item>
@ -52,10 +51,11 @@
<el-input @change="changeRy" :disabled="readonly_dd" v-model="searchList.xxdz" clearable
placeholder="请输入详细地址"></el-input>
</div>
</el-form-item>
</el-form-item> -->
<el-form-item label="时间">
<el-date-picker v-model="searchList.datetimes" type="datetimerange" unlink-panels :range-separator="'至'"
start-placeholder="开始日期时间" end-placeholder="结束日期时间" value-format="YYYY-MM-DD HH:mm:ss" />
<el-date-picker v-model="searchList.datetimes" type="daterange" unlink-panels :range-separator="'至'"
start-placeholder="开始日期时间" end-placeholder="结束日期时间" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSearch">查询</el-button>
@ -67,9 +67,9 @@
<li class="list-item" ref="listBoxRef" v-for="(it, idx) in list" :key="idx">
<div class="comm-title title-s">{{ it.title }}</div>
<div class="list-table">
<MyTable :tableData="it.tableList" :tableColumn="it.tableColumn" :key="idx + '' + it.keyCount" :fixed="false"
:tableHeight="pageData.tableHeight" :tabelModel="it.title" :tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth">
<MyTable :tableData="it.tableList" :tableColumn="it.tableColumn" :key="idx + '' + it.keyCount"
:fixed="false" :tableHeight="pageData.tableHeight" :tabelModel="it.title"
:tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #jqlbdm="{ row }">
<DictTag :tag="false" :value="row.jqlbdm" :options="JQLB" />
</template>
@ -85,22 +85,26 @@
</div>
</div>
</div>
<YpModel v-model="showModel" :textContent="textContent"></YpModel>
<!-- <YpModel v-model="showModel" :textContent="textContent"></YpModel> -->
<!-- 弹窗 -->
<DetailDialog ref="detaileRef"></DetailDialog>
<!-- <DetailDialog ref="detaileRef"></DetailDialog> -->
<!-- 研判报告弹窗 -->
<JudgmentReport v-model="visible" :search="search"></JudgmentReport>
</template>
<script setup>
import { lzJcjPjdbSelectPage } from '@/api/semanticAnalysis.js'
import { ElMessage } from "element-plus";
import DetailDialog from './components/detailDialog.vue'
import YpModel from '@/components/ypModel/index.vue'
// import DetailDialog from './components/detailDialog.vue'
import JudgmentReport from './components/judgmentReport.vue'
// import YpModel from '@/components/ypModel/index.vue'
import { qcckPost, qcckGet } from "@/api/qcckApi.js";
import MoreBarEcharts from "@/views/home/echarts/moreBarEcharts.vue";
import LineEcharts from "@/views/home/echarts/moreLineEcharts.vue";
import MyTable from "@/components/aboutTable/DarkTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { useRoute, useRouter } from 'vue-router';
import {tbJqGetPageList } from '@/api/yj.js'
const router = useRouter();
import { nextTick, onMounted, reactive, getCurrentInstance, ref, watch } from 'vue';
const { proxy } = getCurrentInstance();
@ -108,9 +112,9 @@ const { JQLB } = proxy.$dict("JQLB"); //获取字典数据
const readonly_lx = ref(false)
const readonly_ry = ref(false)
const readonly_dd = ref(false)
const cascaRef=ref()
const cascaRef = ref()
const showModel = ref(false);
const detaileRef = ref();
// const detaileRef = ref();
const searchBox = ref();
const listBoxRef = ref();
const textContent = ref('');
@ -319,34 +323,50 @@ const getJqList = () => {
const handleHs = (val) => {
router.push({ path: '/MeetingRoom', query: { tsypid: val.id } })
}
const visible = ref(false)
const search = ref({})
const handleYP = () => {
let arr=cascaRef.value.getCheckedNodes()
searchForm.value.jqlbdms=arr.map((el)=>{
return el.value
})
let params = {
hskssj: searchForm.value.kssj,
hsjssj: searchForm.value.jssj,
jqlbdms:searchForm.value.jqlbdms
console.log(searchList.value);
visible.value = true
let data = []
if (searchList.value.lx) {
data = searchList.value.lx.map(item => {
return item[item.length - 1]
})
}
qcckPost(params, '/mosty-gsxt/lzJcjPjdb/getJqDcypbg').then(res => {
let data = res || {};
let html = `<p class="html_bt">${data.bt}</p>`
html += `<p>${data.head}</p>`
html += `<p>${data.nr}</p>`
html += `<p>${data.bc}</p>`
html += `<p>${data.end}</p>`
textContent.value = html;
showModel.value = true;
})
search.value = {
lx: searchList.value.lx ? data : '',
startTime: searchList.value.datetimes ? searchList.value.datetimes[0] : '',
endTime: searchList.value.datetimes ? searchList.value.datetimes[1] : '',
}
// let arr=cascaRef.value.getCheckedNodes()
// searchForm.value.jqlbdms=arr.map((el)=>{
// return el.value
// })
// let params = {
// hskssj: searchForm.value.kssj,
// hsjssj: searchForm.value.jssj,
// jqlbdms:searchForm.value.jqlbdms
// }
// qcckPost(params, '/mosty-gsxt/lzJcjPjdb/getJqDcypbg').then(res => {
// let data = res || {};
// let html = `<p class="html_bt">${data.bt}</p>`
// html += `<p>${data.head}</p>`
// html += `<p>${data.nr}</p>`
// html += `<p>${data.bc}</p>`
// html += `<p>${data.end}</p>`
// textContent.value = html;
// showModel.value = true;
// })
}
// 选择类型
const changeCascader = (val) => {
console.log(val,'val');
console.log(cascaRef.value.getCheckedNodes(),'++++++++');
console.log(val, 'val');
console.log(cascaRef.value.getCheckedNodes(), '++++++++');
readonly_lx.value = false;
readonly_ry.value = val ? true : false
readonly_dd.value = val ? true : false
@ -372,6 +392,7 @@ const changeBm = (val) => {
}
// 重置
const resetForm = () => {
searchList.value = {}
searchForm.value = {}
readonly_lx.value = false
readonly_ry.value = false
@ -381,7 +402,25 @@ const resetForm = () => {
// 搜索
const onSearch = () => {
if (searchList.value.lx || searchList.value.ry || searchList.value.dd) {
detaileRef.value.init(searchList.value)
const data= searchList.value.lx.map(item => {
return item[item.length - 1]
})
console.log(searchList.value);
const promes = {
startTime: searchList.value.datetimes ? searchList.value.datetimes[0] : '',
endTime: searchList.value.datetimes ? searchList.value.datetimes[1] : '',
bjlbs: searchList.value.lx ? data.join(',') : '',
}
console.log(promes);
tbJqGetPageList(promes).then(res => {
list[1].tableList = res.records || [];
list[1].pageConfiger.total = res.total;
})
} else {
ElMessage.warning('请选择查询条件')
}

View File

@ -1,5 +1,5 @@
<template>
<el-dialog v-model="modelValue" center width="1000px" :destroy-on-close="true" title="网上会商" @close="close"
<el-dialog v-model="props.modelValue" center width="1000px" :destroy-on-close="true" title="网上会商" @close="close"
:close-on-click-modal="false">
<div class="cntBox">
<div class="form_item flex">

View File

@ -79,11 +79,11 @@ const pageData = reactive({
tableColumn: [
{
label: "研判标题",
prop: "ypbt"
prop: "jymc"
},
{
label: "研判时间",
prop: "ypsj"
prop: "fbsj"
},
]
});

View File

@ -1,107 +0,0 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">{{ title }}模型 </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit" v-show="title != '详情'">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage :formList="formData" v-model="listQuery" ref="elform" :rules="rules" :disabled="editAdd">
</FormMessage>
</div>
</div>
</template>
<script setup>
import { reactive, ref, getCurrentInstance } from 'vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { addEntity,editEntity } from '@/api/model.js'
import { ElMessage } from "element-plus";
const proxy = getCurrentInstance()
const props = defineProps({
dict: {
type: Array,
default: () => [],
}
})
const dialogForm = ref(false)
const emit = defineEmits(['getLits'])
// 判断是否增删改
const editAdd = ref(false)
const title = ref("新增")
const formData = ref()
const listQuery = ref({})
const elform = ref()
const rules = ref({
mxmc: [
{ required: true, message: '请输入模型名称', trigger: 'blur' },
],
mxlx: [
{ required: true, message: '请选择模型类型', trigger: 'change' },
],
})
const init = (type, row) => {
dialogForm.value = true
editAdd.value = false
formData.value = [
{ label: "模型名称", prop: "mxmc", type: "input", width: "40%" },
{
label: "模型类型", prop: "mxlx", type: "select",
width: "40%", options: props.dict.D_MXGL_MXLX
},
]
listQuery.value = { ...row }
if (type == 'edit') {
title.value = "编辑"
} else if (type == 'add') {
title.value = "新增"
} else {
editAdd.value = true
title.value = "详情"
}
}
// 表单内容
const loading = ref(false)
// 新增
const submit = () => {
elform.value.submit((data) => {
loading.value = true
if (title.value == '新增') {
addEntity(listQuery.value).then((res) => {
ElMessage.success("新增成功");
emit('getLits')
dialogForm.value = false
}).catch((err) => {
console.log(err);
}).finally(() => {
loading.value = false
});
} else {
editEntity(listQuery.value).then((res) => {
ElMessage.success("修改成功");
emit('getLits')
dialogForm.value = false
}).finally(() => {
loading.value = false
});
}
})
}
// 关闭
const close = () => {
dialogForm.value = false
}
defineExpose({
init
})
</script>
<style lang="scss" scoped></style>

View File

@ -1,290 +0,0 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="预警规则">
<el-button type="primary" size="small" @click="openAddRule('add', item)">新增</el-button>
<el-button type="primary" size="small" :disabled="ids.length == 0" @click="deleteRule(ids)">批量删除</el-button>
<el-button size="small" @click="retenHome()">返回</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData">
<template #tjName="{ row }">
<div class="flex one_text_detail" v-if="row.tj">{{ ` ${row.tj} ${row.cs}` }} </div>
</template>
<template #zz="{ row }">
<template v-if="row.zz">
<span v-for="(item, index) in jsonParse(row.zz)" :key="index">{{ item.zzmc }}
<span v-if="index < jsonParse(row.zz).length - 1"></span>
</span>
</template>
</template>
<template #sfbq="{ row }">
<template v-if="row.sfbq">
<span v-for="(item, index) in jsonParse(row.sfbq)" :key="index">{{ item.bqmc }}
<span v-if="index < jsonParse(row.sfbq).length - 1"></span>
</span>
</template>
</template>
<template #xwbq="{ row }">
<template v-if="row.xwbq">
<span v-for="(item, index) in jsonParse(row.xwbq)" :key="index">{{ item.bqmc }}
<span v-if="index < jsonParse(row.xwbq).length - 1"></span>
</span>
</template>
</template>
<template #dd="{ row }">
<template v-if="row.dd">
<span v-for="(item, index) in jsonParse(row.dd)" :key="index">{{ item.dz }}
<span v-if="index < jsonParse(row.dd).length - 1"></span>
</span>
</template>
</template>
<template #ryxx="{ row }">
<template v-if="row.ryxx">
<span v-for="(item, index) in jsonParse(row.ryxx)" :key="index">{{ item.xm }}
<span v-if="index < jsonParse(row.ryxx).length - 1"></span>
</span>
</template>
</template>
<template #jqlx="{ row }">
<template v-if="row.jqlx">
<span v-for="(item, index) in jsonParse(row.jqlx)" :key="index">{{ item.lxmc }}
<span v-if="index < jsonParse(row.jqlx).length - 1"></span>
</span>
</template>
</template>
<template #sjlx="{ row }">
<template v-if="row.sjlx">
<span v-for="(item, index) in jsonParse(row.sjlx)" :key="index">{{ item.lxmc }}
<span v-if="index < jsonParse(row.sjlx).length - 1"></span>
</span>
</template>
</template>
<template #wp="{ row }">
<template v-if="row.wp">
<span v-for="(item, index) in jsonParse(row.wp)" :key="index">{{ item.wpmc }}
<span v-if="index < jsonParse(row.wp).length - 1"></span>
</span>
</template>
</template>
<template #controls="{ row }">
<el-link type="primary" size="small" @click="yzSsyjpzMxgzxl( row.id)">运行规则</el-link>
<el-link type="primary" size="small" @click="openAddRule('edit',item, row)">修改</el-link>
<el-link type="primary" size="small" @click="openAddRule('detail',item, row)">详情</el-link>
<!-- <el-link type="primary" size="small" @click="openAddRule('detail',item, row)">预警列表</el-link> -->
<el-link type="danger" size="small" @click="deleteRule(row.id)">删除</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
</div>
<List ref="regulation" :dict="{ D_BB_AJLB,D_BZ_WPLX }" @getList="getList" />
</template>
<script setup>
import { ElMessage } from "element-plus";
import List from "../list";
import emitter from "@/utils/eventBus.js";
import { deleteYjgzpz,getYjgzpzMxgzxl,getYjgzpzPageList } from "@/api/model";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import { template } from "lodash";
const props = defineProps({
item: {
type: Object,
default: () => ({})
}
})
const { proxy } = getCurrentInstance();
const { D_BB_AJLB,D_BZ_WPLX} = proxy.$dict("D_BB_AJLB","D_BZ_WPLX")
const regulation = ref(null)
const queryFrom = ref({})
const searchBox = ref(); //搜索框
const searchConfiger = ref([
{
label: "规则名称",
prop: "gzmc",
placeholder: "请输入规则名称",
showType: "input"
},
{
label: "时间",
prop: "startTime",
placeholder: "请选择时间",
showType: "daterange"
},
]);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 300,
tableColumn: [
{ label: "规则名称", prop: "gzmc", showOverflowTooltip: true },
{ label: "开始时间", prop: "jssj", showOverflowTooltip: true },
{ label: "结束时间", prop: "kssj", showOverflowTooltip: true },
{ label: "条件", prop: "tjName", showOverflowTooltip: true, showSolt: true },
{ label: "组织", prop: "zz", showOverflowTooltip: true, showSolt: true },
{ label: "人员信息", prop: "ryxx", showOverflowTooltip: true, showSolt: true },
{ label: "警情类型", prop: "jqlx", showOverflowTooltip: true, showSolt: true },
{ label: "事件类型", prop: "sjlx", showOverflowTooltip: true, showSolt: true },
{ label: "物品", prop: "wp", showOverflowTooltip: true, showSolt: true },
{ label: "地址", prop: "dd", showOverflowTooltip: true, showSolt: true },
]
});
onMounted(() => {
getList();
tabHeightFn();
});
// 搜索
const onSearch = (val) => {
queryFrom.value = { ...val };
queryFrom.value.startTime = val.startTime&&val.startTime.length > 0 ? val.startTime[0] : '';
queryFrom.value.endTime = val.startTime&&val.startTime.length > 0 ? val.startTime[1] : '';
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
//
// 获取列表
const getList = () => {
const promes = {
...pageData.pageConfiger,
...queryFrom.value,
mxid:props.item.id,
}
getYjgzpzPageList(promes).then((res) => {
pageData.tableData = res.records
pageData.total = res.total
});
};
const retenHome = () => {
emitter.emit('changeModel', { name: '研判首页', row: {} });
}
const openAddRule = (type, item, row) => {
regulation.value.init(type, item, row)
}
const ids = ref([])
const chooseData = (val) => {
ids.value = val.map(item => item.id)
}
const deleteRule = (row) => {
proxy.$confirm('是否删除该规则, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let list
if (Array.isArray(row)) {
list = ids.value
} else {
list =[row]
}
deleteYjgzpz({ids:list}).then(() => {
ElMessage.success("删除成功");
getList()
})
}).catch((err) => {
proxy.$message({
type: 'info',
message: '已取消删除'
});
});
}
const yzSsyjpzMxgzxl = (params) => {
getYjgzpzMxgzxl({id:params}).then((res) => {
console.log(res);
})
}
const jsonParse = (val) => {
if (val) {
return JSON.parse(val)
}
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style lang="scss" scoped>
.checkbox-group {
display: flex;
gap: 20px;
}
.basic-info {
display: flex;
gap: 15px;
.avatar {
width: 80px;
height: 80px;
overflow: hidden;
border-radius: 4px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.info-list {
display: flex;
flex-direction: column;
gap: 5px;
}
}
.control-buttons {
display: flex;
gap: 10px;
}
</style>

View File

@ -1,696 +0,0 @@
<template>
<!-- 可用条件类型列表 -->
<div class="regulation-wrapper">
<div class="rule-name-section flex align-center">
<div class="rule-name-label">规则名称</div>
<el-input v-model="gzmc" :disabled="disabled" placeholder="请输入规则名称" class="search-input" clearable></el-input>
</div>
<!-- 可用条件区域 -->
<div class="condition-section">
<div class="available-conditions">
<VueDraggable class="flex-wrap" v-model="dataList" ghostClass="ghost"
:group="{ name: 'people', pull: 'clone', put: false }" :clone="clone">
<el-button v-for="item in dataList" :key="item.name" class="condition-button" size="small">
<i class="el-icon-document-add"></i>
{{ item.name }}
</el-button>
</VueDraggable>
</div>
</div>
<!-- 拖拽提示 -->
<div class="drag-hint">
<i class="el-icon-arrow-down"></i>
<span>拖拽条件到下方区域</span>
</div>
<!-- 已选条件区域 -->
<div class="selected-section">
<div class="section-title">
<i class="el-icon-check-square"></i>
<span>已选条件</span>
<span class="selected-count">{{ copyList.length }}</span>
</div>
<div class="selected-container">
<VueDraggable v-model="copyList" :group="{ name: 'people', pull: !disabled, put: !disabled }" ghostClass="ghost"
class="selected-list" itemKey="name">
<div v-for="(item, indexs) in copyList" :key="item" class="draggable-item">
<div class="item-content">
<div v-if="!disabled" class="item-remove-btn" @click="romes(item)"><el-icon :size="16">
<Close />
</el-icon></div>
<span class="item-text">{{ item.name }}{{}}</span>
</div>
<div v-if="item[item['key']]">
<template v-if="item.key == 'dd'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
</div>
</div>
</template>
<template v-if="item.key == 'cs'">
<div class="count-condition-container">
<el-select v-model="item[item['key']].tj" placeholder="请选择条件" class="condition-select">
<el-option :label="item" :value="item" v-for="(item, index) in dataConst" :key="index"></el-option>
</el-select>
<el-input-number v-model="item[item['key']].cs" :min="1" :max="1000" />
</div>
</template>
<template v-if="item.key == 'zz'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
</div>
</div>
</template>
<template v-if="item.key == 'kssj'">
<div class="condition-input-container flex just-between">
<div>
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
type="date" :placeholder="`请选择${item.name}`" />
</div>
</div>
</template>
<template v-if="item.key == 'jssj'">
<div class="condition-input-container flex just-between">
<div>
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
type="date" :placeholder="`请选择${item.name}`" />
</div>
</div>
</template>
<template v-if="item.key == 'sjlx'">
<div class="condition-input-container flex just-between">
<el-select v-model="item[item['key']]" multiple :placeholder="`请选择${item.name}`">
<el-option v-for="item in dict.D_BB_AJLB" :key="item.dm" :label="item.zdmc" :value="item.dm" />
</el-select>
</div>
</template>
<template v-if="item.key == 'wp'">
<div class="condition-input-container flex just-between">
<el-select v-model="item[item['key']]" multiple :placeholder="`请选择${item.name}`" style="width: 240px">
<el-option v-for="item in dict.D_BZ_WPLX" :key="item.dm" :label="item.zdmc" :value="item.dm" />
</el-select>
</div>
</template>
<template v-if="item.key == 'ryxx'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input v-model="item[item['key']][index].xm" :placeholder="`请输入姓名`" clearable></el-input>
</div>
<div>
<el-input v-model="item[item['key']][index].sfzh" :placeholder="`请输入身份证号`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
</div>
</div>
</template>
<template v-else-if="item.key == 'jqlx'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input @click="chooseMarksVisible = true" v-model="item[item['key']][index].lxmc"
:placeholder="`请输入${item.name}`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" @click="removeItem(item['key'], index)" type="danger"
size="mini">-</el-button>
</div>
</div>
</template>
</div>
</div>
</VueDraggable>
<!-- 空状态提示 -->
<div v-if="copyList.length === 0" class="empty-state">
<i class="el-icon-tickets"></i>
<p>暂无已选条件</p>
<p class="empty-tip">从上方拖拽条件到此处</p>
</div>
</div>
</div>
</div>
<ChooseIdeJqlb v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" />
</template>
<script setup>
import { reactive, ref, watch } from 'vue'
import { ElMessage } from "element-plus";
import ChooseIdeJqlb from '@/components/ChooseList/ChooseIdeJqlb/index.vue'
import { VueDraggable } from 'vue-draggable-plus'//npm install vue-draggable-plus
const props = defineProps({
dict: {
type: Object,
default: () => { },
},
list: {
type: Array,
default: () => [
'Joao',
'Jean',
'Johanna',
'Juan',
],
}, defaultData: {
type: Object,
default: () => { },
}, disabled: {
type: Boolean,
default: false
}
})
const dataConst = reactive([
">",
"<",
"="
])
const gzmc = ref('')
const dataList = ref(props.list)
const copyList = ref([])
const clone = (val) => {
if (val.key == 'jqlx') {
dataList.value = dataList.value.filter(item => item.key != 'sjlx')
}
if (val.key == 'sjlx') {
dataList.value = dataList.value.filter(item => item.key != 'jqlx')
}
const data = copyList.value.find(item => item.name == val.name)
if (data) {
console.log("已存在")
} else {
switch (val.key) {
case 'cs':
return {
name: val.name,
key: val.key,
[val["key"]]: {}
}
case "wp":
return {
name: val.name,
key: val.key,
[val["key"]]: []
}
case 'ryxx':
return {
name: val.name,
key: val.key,
[val["key"]]: [{
xm: "",
sfzh: ""
}]
}
case 'kssj':
case 'jssj':
return {
name: val.name,
key: val.key,
[val["key"]]: []
}
case 'sjlx':
return {
name: val.name,
key: val.key,
[val["key"]]: []
}
default:
return {
name: val.name,
key: val.key,
[val["key"]]: [""]
}
}
}
}
watch(() => props.defaultData, (val) => {
if (val) {
gzmc.value = val.gzmc
const data = props.list.map(item => {
switch (item.key) {
case 'cs':
return {
name: item.name,
key: item.key,
[item["key"]]: val.cs && val.tj ? {
cs: val.cs,
tj: val.tj
} : null
}
case 'jssj':
case 'kssj':
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? val[item.key] : null,
}
case 'zz':
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.zzmc) : null,
}
case 'dd':
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.dz) : null,
}
default:
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]) : null
}
}
})
copyList.value = data.filter(item => item[item.key] != null)
}
}, { deep: true, immediate: true })
const addInput = (key, index) => {
if (key == 'ryxx') {
copyList.value[index][key].push({
xm: "",
sfzh: ""
})
} else {
copyList.value[index][key].push("")
}
}
// 移除项目
const removeItem = (key, index) => {
const data = copyList.value.findIndex(item => item.key == key)
if (copyList.value[data][key].length == 1) {
return
}
copyList.value[data][key].splice(index, 1)
}
const chooseMarksVisible = ref(false)
const roleIds = ref([])
const choosed = (val) => {
roleIds.value = val.map(item => item.id)
copyList.value.find(item => item.key == 'jqlx')['jqlx'] = val.map(item => {
return {
lxmc: item.zdmc,
lxdm: item.dm
}
})
}
const romes = (val) => {
copyList.value = copyList.value.filter(item => item.key !== val.key)
if (val.key == 'jqlx' || val.key == 'sjlx') {
dataList.value = props.list
}
}
const promes = ref({})
// 新增
const retValue = () => {
if (gzmc.value == '') {
return
}
const data = copyList.value.map(item => {
return {
[item.key]: item[item.key]
}
})
promes.value = data.reduce((acc, cur) => {
return { ...acc, ...cur }
}, {})
promes.value = { ...promes.value, ...promes.value.cs, gzmc: gzmc.value }
if (promes.value.dd && promes.value.dd.length > 0) {
const dd = promes.value.dd.map(item => {
return { dz: item }
})
promes.value.dd = JSON.stringify(dd)
}
if (promes.value.zz && promes.value.zz.length > 0) {
const zz = promes.value.zz.map(item => {
return { zzmc: item }
})
promes.value.zz = JSON.stringify(zz)
}
const sjlx = copyList.value.find(item => item.key == 'sjlx')
if (sjlx) {
const data = props.dict.D_BB_AJLB.filter(item => {
if (sjlx['sjlx'].includes(item.dm)) {
return item
}
}).map(item => {
return {
lxmc: item.zdmc,
lxdm: item.dm
}
})
promes.value.sjlx = JSON.stringify(data)
}
const wplx = copyList.value.find(item => item.key == 'wp')
if (wplx) {
const data = props.dict.D_BZ_WPLX.filter(item => {
if (wplx['wp'].includes(item.dm)) {
return item
}
}).map(item => {
return {
wpmc: item.zdmc,
wpdm: item.dm
}
})
promes.value.wp = JSON.stringify(data)
}
if (promes.value.ryxx && promes.value.ryxx.length > 0) {
promes.value.ryxx = JSON.stringify(promes.value.ryxx)
}
if (promes.value.jqlx && promes.value.jqlx.length > 0) {
promes.value.jqlx = JSON.stringify(promes.value.jqlx)
}
return promes.value
}
defineExpose({
retValue
})
</script>
<style lang="scss" scoped>
.regulation-wrapper {
padding: 20px;
background: #f5f7fa;
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}
// 条件区域通用样式
.condition-section,
.selected-section {
background: white;
border-radius: 10px;
padding: 10px;
// margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.condition-section:hover,
.selected-section:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
// 区域标题
.section-title {
display: flex;
align-items: center;
margin-bottom: 16px;
color: #303133;
font-weight: 600;
font-size: 16px;
padding-bottom: 12px;
border-bottom: 2px solid #e6f7ff;
i {
color: #409eff;
margin-right: 8px;
font-size: 18px;
}
.selected-count {
margin-left: 10px;
font-size: 14px;
font-weight: normal;
color: #606266;
background: #f0f9ff;
padding: 2px 8px;
border-radius: 12px;
min-width: 24px;
text-align: center;
}
}
// 可用条件区域
.available-conditions {
// min-height: 100px;
}
.flex-wrap {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.condition-button {
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
color: white !important;
border: none !important;
border-radius: 8px !important;
padding: 8px 16px !important;
font-size: 14px !important;
transition: all 0.3s ease !important;
min-width: 120px;
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
&:hover {
background: linear-gradient(135deg, #66b1ff 0%, #409eff 100%) !important;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
}
i {
margin-right: 6px;
}
}
// 拖拽提示
.drag-hint {
display: flex;
align-content: flex-start;
// align-items: center;
justify-content: center;
padding: 20px;
color: #909399;
font-size: 14px;
i {
margin-right: 8px;
font-size: 16px;
animation: bounce 1.5s infinite;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-10px);
}
60% {
transform: translateY(-5px);
}
}
}
// 已选条件区域
.selected-container {
min-height: 120px;
border: 2px dashed #dcdfe6;
border-radius: 8px;
padding: 20px;
transition: all 0.3s ease;
background-color: #dcdfe670;
&:hover {
border-color: #409eff;
background: #f0f9ff;
}
}
.selected-list {
display: flex;
min-height: 100px;
width: 100%;
flex-wrap: wrap;
}
// 拖拽项样式
.draggable-item {
position: relative;
padding: 3px;
margin: 8px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: table-cell;
justify-content: space-between;
text-align: center;
flex-wrap: wrap;
&:hover {
transform: translateY(-2px) scale(1.02);
box-shadow: 0 6px 16px rgba(103, 194, 58, 0.4);
}
&.ghost {
opacity: 0.6;
transform: rotate(5deg);
}
}
.item-content {
background: white;
border-radius: 8px;
padding: 20px 12px 12px 12px;
display: flex;
align-items: center;
justify-content: space-between;
min-width: 140px;
position: relative;
}
.item-text {
font-size: 14px;
color: #303133;
font-weight: 500;
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 10px;
}
.item-remove {
color: #c0c4cc;
font-size: 18px;
cursor: pointer;
transition: all 0.3s ease;
padding: 4px;
border-radius: 50%;
&:hover {
color: #f56c6c;
background: #fef0f0;
transform: rotate(90deg);
}
}
/* 规则名称区域 */
.rule-name-section {
margin-bottom: 10px;
}
.rule-name-label {
width: 100px;
}
/* 项目删除按钮 */
.item-remove-btn {
position: absolute;
top: 5px;
right: 10px;
}
/* 条件输入容器 */
.condition-input-container {
flex-wrap: nowrap;
margin-top: 10px;
}
/* 计数条件容器 */
.count-condition-container {
margin-top: 10px;
display: flex;
}
/* 条件选择框 */
.condition-select {
width: 100px;
}
/* 按钮右侧边距 */
.btn-margin-right {
margin-right: 5px;
}
// 空状态样式
.empty-state {
text-align: center;
padding: 40px 20px;
color: #909399;
i {
font-size: 48px;
margin-bottom: 16px;
color: #dcdfe6;
transition: color 0.3s ease;
}
p {
margin: 0;
font-size: 14px;
}
.empty-tip {
font-size: 12px;
color: #c0c4cc;
margin-top: 8px;
}
&:hover i {
color: #409eff;
}
}
// 拖拽效果
.ghost {
opacity: 0.6;
background-color: #e6f7ff;
border: 2px dashed #409eff;
border-radius: 8px;
}
// 响应式设计
@media (max-width: 768px) {
.regulation-wrapper {
padding: 15px;
}
.condition-section,
.selected-section {
padding: 15px;
}
.condition-button {
min-width: 100px;
font-size: 13px !important;
}
.item-content {
min-width: 120px;
padding: 10px 12px;
}
}
:v-deep .el-select {
width: 59%;
}
</style>

View File

@ -1,257 +0,0 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="四色预警规则">
<el-button type="primary" size="small" @click="openAddRule('add', item)">新增</el-button>
<el-button type="primary" size="small" :disabled="ids.length == 0" @click="deleteRule(ids)">批量删除</el-button>
<el-button size="small" @click="retenHome()">返回</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData">
<!-- <template #tjName="{ row }">
<div class="flex one_text_detail">{{ ` ${row.tj} ${row.cs}` }} </div>
</template> -->
<!-- <template #fxDj="{ row }">
<DictTag :tag="false" :value="row.fxDj" :options="D_GS_RQFJ_FXDJ"/>
</template> -->
<template #zz="{ row }">
<template v-if="row.zz">
<span v-for="(item, index) in jsonParse(row.zz)" :key="index">{{ item.zzmc }}
<span v-if="index < jsonParse(row.zz).length - 1"></span>
</span>
</template>
</template>
<template #sfbq="{ row }">
<template v-if="row.sfbq">
<span v-for="(item, index) in jsonParse(row.sfbq)" :key="index">{{ item.bqmc }}
<span v-if="index < jsonParse(row.sfbq).length - 1"></span>
</span>
</template>
</template>
<template #xwbq="{ row }">
<template v-if="row.xwbq">
<span v-for="(item, index) in jsonParse(row.xwbq)" :key="index">{{ item.bqmc }}
<span v-if="index < jsonParse(row.xwbq).length - 1"></span>
</span>
</template>
</template>
<template #dd="{ row }">
<template v-if="row.dd">
<span v-for="(item, index) in jsonParse(row.dd)" :key="index">{{ item.dz }}
<span v-if="index < jsonParse(row.dd).length - 1"></span>
</span>
</template>
</template>
<template #controls="{ row }">
<el-link type="primary" size="small" @click="yzSsyjpzMxgzxl( row.id)">运行规则</el-link>
<el-link type="primary" size="small" @click="openAddRule('edit',item, row)">修改</el-link>
<el-link type="primary" size="small" @click="openAddRule('detail',item, row)">详情</el-link>
<!-- <el-link type="primary" size="small" @click="openAddRule('detail',item, row)">预警列表</el-link> -->
<el-link type="danger" size="small" @click="deleteRule(row.id)">删除</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
</div>
<List ref="regulation" :dict="{ D_BZ_RYBQ }" @getList="getList" />
</template>
<script setup>
import { ElMessage } from "element-plus";
import List from "../list";
import emitter from "@/utils/eventBus.js";
import { getSsyjpzPageList, deleteSsyjpz,getSsyjpzMxgzxl } from "@/api/model";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import { template } from "lodash";
const props = defineProps({
item: {
type: Object,
default: () => ({})
}
})
const { proxy } = getCurrentInstance();
const { D_BZ_RYBQ } = proxy.$dict("D_BZ_RYBQ")
const regulation = ref(null)
const queryFrom = ref({})
const searchBox = ref(); //搜索框
const searchConfiger = ref([
{
label: "规则名称",
prop: "gzmc",
placeholder: "请输入规则名称",
showType: "input"
},
{
label: "时间",
prop: "startTime",
placeholder: "请选择时间",
showType: "daterange"
},
]);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 300,
tableColumn: [
{ label: "规则名称", prop: "gzmc", showOverflowTooltip: true },
{ label: "开始时间", prop: "jssj", showOverflowTooltip: true },
{ label: "结束时间", prop: "kssj", showOverflowTooltip: true },
// { label: "条件", prop: "tjName", showOverflowTooltip: true, showSolt: true },
{ label: "组织", prop: "zz", showOverflowTooltip: true, showSolt: true },
{ label: "身份标签", prop: "sfbq", showOverflowTooltip: true, showSolt: true },
{ label: "行为标签", prop: "xwbq", showOverflowTooltip: true, showSolt: true },
{ label: "地址", prop: "dd", showOverflowTooltip: true, showSolt: true },
]
});
onMounted(() => {
getList();
tabHeightFn();
});
// 搜索
const onSearch = (val) => {
queryFrom.value.startTime = val.startTime&&val.startTime.length > 0 ? val.startTime[0] : '';
queryFrom.value.endTime = val.startTime&&val.startTime.length > 0 ? val.startTime[1] : '';
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
//
// 获取列表
const getList = () => {
const promes = {
...pageData.pageConfiger,
...queryFrom.value,
mxid:props.item.id
}
getSsyjpzPageList(promes).then((res) => {
pageData.tableData = res.records
pageData.total = res.total
});
};
const retenHome = () => {
emitter.emit('changeModel', { name: '研判首页', row: {} });
}
const openAddRule = (type, item, row) => {
regulation.value.init(type, item, row)
}
const ids = ref([])
const chooseData = (val) => {
ids.value = val.map(item => item.id)
}
const deleteRule = (row) => {
proxy.$confirm('是否删除该规则, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let list
if (Array.isArray(row)) {
list = ids.value
} else {
list =[row]
}
deleteSsyjpz({ids:list}).then(() => {
ElMessage.success("删除成功");
getList()
})
}).catch((err) => {
proxy.$message({
type: 'info',
message: '已取消删除'
});
});
}
const yzSsyjpzMxgzxl = (params) => {
getSsyjpzMxgzxl({id:params}).then((res) => {
console.log(res);
})
}
const jsonParse = (val) => {
if (val) {
return JSON.parse(val)
}
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style lang="scss" scoped>
.checkbox-group {
display: flex;
gap: 20px;
}
.basic-info {
display: flex;
gap: 15px;
.avatar {
width: 80px;
height: 80px;
overflow: hidden;
border-radius: 4px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.info-list {
display: flex;
flex-direction: column;
gap: 5px;
}
}
.control-buttons {
display: flex;
gap: 10px;
}
</style>

View File

@ -1,638 +0,0 @@
<template>
<!-- 可用条件类型列表 -->
<div class="regulation-wrapper">
<div class="rule-name-section flex align-center">
<div class="rule-name-label">规则名称</div>
<el-input v-model="gzmc" :disabled="disabled" placeholder="请输入规则名称" class="search-input" clearable></el-input>
</div>
<!-- 可用条件区域 -->
<div class="condition-section">
<div class="available-conditions">
<VueDraggable class="flex-wrap" v-model="dataList" ghostClass="ghost"
:group="{ name: 'people', pull: 'clone', put: false }" :clone="clone">
<el-button v-for="item in dataList" :key="item.name" class="condition-button" size="small">
<i class="el-icon-document-add"></i>
{{ item.name }}
</el-button>
</VueDraggable>
</div>
</div>
<!-- 拖拽提示 -->
<div class="drag-hint">
<i class="el-icon-arrow-down"></i>
<span>拖拽条件到下方区域</span>
</div>
<!-- 已选条件区域 -->
<div class="selected-section">
<div class="section-title">
<i class="el-icon-check-square"></i>
<span>已选条件</span>
<span class="selected-count">{{ copyList.length }}</span>
</div>
<div class="selected-container">
<VueDraggable v-model="copyList" :group="{ name: 'people', pull: !disabled, put: !disabled }" ghostClass="ghost"
class="selected-list" itemKey="name">
<div v-for="(item, indexs) in copyList" :key="item" class="draggable-item">
<div class="item-content">
<div v-if="!disabled" class="item-remove-btn" @click="romes(item)"><el-icon :size="16">
<Close />
</el-icon></div>
<span class="item-text">{{ item.name }}</span>
</div>
<div v-if="item[item['key']]">
<template v-if="item.key == 'dd'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
</div>
</div>
</template>
<template v-else-if="item.key == 'sfbq'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input @click="chooseIdentityVisible = true" v-model="item[item['key']][index].bqmc"
:placeholder="`请输入${item.name}`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" @click="removeItem(item['key'], index)" type="danger"
size="mini">-</el-button>
</div>
</div>
</template>
<!-- <template v-if="item.key == 'cs'">
<div class="count-condition-container">
<el-select v-model="item[item['key']].tj" placeholder="请选择条件" class="condition-select">
<el-option :label="item" :value="item" v-for="(item, index) in dataConst" :key="index"></el-option>
</el-select>
<el-input-number v-model="item[item['key']].cs" :min="1" :max="1000" />
</div>
</template> -->
<template v-if="item.key == 'xwbq'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input @click="chooseMarksVisible = true" v-model="item[item['key']][index].bqmc"
:placeholder="`请输入${item.name}`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" @click="removeItem(item['key'], index)" type="danger"
size="mini">-</el-button>
</div>
</div>
</template>
<template v-if="item.key == 'zz'">
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
<div>
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
</div>
<div>
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
</div>
</div>
</template>
<template v-if="item.key == 'kssj'">
<div class="condition-input-container flex just-between">
<div>
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
type="date" :placeholder="`请选择${item.name}`" />
</div>
</div>
</template>
<template v-if="item.key == 'jssj'">
<div class="condition-input-container flex just-between">
<div>
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
type="date" :placeholder="`请选择${item.name}`" />
</div>
</div>
</template>
</div>
</div>
</VueDraggable>
<!-- 空状态提示 -->
<div v-if="copyList.length === 0" class="empty-state">
<i class="el-icon-tickets"></i>
<p>暂无已选条件</p>
<p class="empty-tip">从上方拖拽条件到此处</p>
</div>
</div>
</div>
</div>
<ChooseMarks v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" />
<ChooseIdentity v-model="chooseIdentityVisible" @choosed="choosedIdentity" :roleIds="roleIdsIdentity" />
</template>
<script setup>
import { reactive, ref, watch } from 'vue'
import ChooseMarks from "@/components/ChooseList/ChooseMarks/index.vue";
import ChooseIdentity from "@/components/ChooseList/ChooseIdentity/index.vue";
import { ElMessage } from "element-plus";
import { VueDraggable } from 'vue-draggable-plus'//npm install vue-draggable-plus
const props = defineProps({
dict: {
type: Array,
default: () => [],
},
list: {
type: Array,
default: () => [
'Joao',
'Jean',
'Johanna',
'Juan',
],
}, defaultData: {
type: Object,
default: () => { },
}, disabled: {
type: Boolean,
default: false
}
})
const dataConst = reactive([
">",
"<",
"="
])
const gzmc = ref('')
const dataList = ref(props.list)
const copyList = ref([])
const clone = (val) => {
const data = copyList.value.find(item => item.name == val.name)
if (data) {
console.log("已存在")
} else {
// if (val.key == 'cs') {
// return {
// name: val.name,
// key: val.key,
// [val["key"]]: {}
// }
// } else {
if (val.key == 'cs') {
return {
name: val.name,
key: val.key,
[val["key"]]: []
}
} else {
return {
name: val.name,
key: val.key,
[val["key"]]: [""]
}
}
}
}
watch(() => props.defaultData, (val) => {
if (val) {
gzmc.value = val.gzmc
const data = props.list.map(item => {
switch (item.key) {
// case 'cs':
// return {
// name: item.name,
// key: item.key,
// [item["key"]]: {
// cs: val.cs,
// tj: val.tj
// }
// }
case 'jssj':
case 'kssj':
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? val[item.key] : null,
}
case 'zz':
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.zzmc) : null,
}
case 'dd':
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.dz) : null,
}
default:
return {
name: item.name,
key: item.key,
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]) : null
}
}
})
copyList.value = data.filter(item => {
return item[item.key] != null
})
}
}, { deep: true, immediate: true })
const addInput = (key, index) => {
copyList.value[index][key].push("")
}
// 移除项目
const removeItem = (key, index) => {
const data = copyList.value.findIndex(item => item.key == key)
if (copyList.value[data][key].length == 1) {
return
}
copyList.value[data][key].splice(index, 1)
}
// 选择预警标签
const roleIds = ref([])
const chooseMarksVisible = ref()
const choosed = (val) => {
roleIds.value = val.map(item => item.id)
copyList.value.find(item => item.key == 'xwbq')['xwbq'] = val.map(item => {
return {
bqdm: item.bqDm,
bqmc: item.bqMc
}
})
}
// 选择身份标签
const chooseIdentityVisible = ref()
const roleIdsIdentity = ref([])
const choosedIdentity = (val) => {
roleIdsIdentity.value = val.map(item => item.id)
copyList.value.find(item => item.key == 'sfbq')['sfbq'] = val.map(item => {
return {
bqdm: item.bqDm,
bqmc: item.bqMc
}
})
}
const romes = (val) => {
copyList.value = copyList.value.filter(item => item.key !== val.key)
}
const promes = ref({})
// 新增
const retValue = () => {
if (gzmc.value == '') {
return
}
const data = copyList.value.map(item => {
return {
[item.key]: item[item.key]
}
})
promes.value = data.reduce((acc, cur) => {
console.log(cur);
return { ...acc, ...cur }
}, {})
promes.value = { ...promes.value, gzmc: gzmc.value }
if (promes.value.dd && promes.value.dd.length > 0) {
promes.value.dd = promes.value.dd.map(item => {
return { dz: item }
})
}
if (promes.value.zz && promes.value.zz.length > 0) {
promes.value.zz = promes.value.zz.map(item => {
return { zzmc: item }
})
}
promes.value.kssj = promes.value.kssj ? promes.value.kssj.toString() : null
promes.value.jssj = promes.value.jssj ? promes.value.jssj.toString() : null
const retData = {
...promes.value,
dd: promes.value.dd ? JSON.stringify(promes.value.dd) : null,
sfbq: promes.value.sfbq ? JSON.stringify(promes.value.sfbq) :null,
xwbq: promes.value.xwbq ? JSON.stringify(promes.value.xwbq) :null,
zz: promes.value.zz ? JSON.stringify(promes.value.zz) :null,
}
return retData
}
defineExpose({
retValue
})
</script>
<style lang="scss" scoped>
.regulation-wrapper {
padding: 20px;
background: #f5f7fa;
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}
// 条件区域通用样式
.condition-section,
.selected-section {
background: white;
border-radius: 10px;
padding: 10px;
// margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.condition-section:hover,
.selected-section:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
// 区域标题
.section-title {
display: flex;
align-items: center;
margin-bottom: 16px;
color: #303133;
font-weight: 600;
font-size: 16px;
padding-bottom: 12px;
border-bottom: 2px solid #e6f7ff;
i {
color: #409eff;
margin-right: 8px;
font-size: 18px;
}
.selected-count {
margin-left: 10px;
font-size: 14px;
font-weight: normal;
color: #606266;
background: #f0f9ff;
padding: 2px 8px;
border-radius: 12px;
min-width: 24px;
text-align: center;
}
}
// 可用条件区域
.available-conditions {
// min-height: 100px;
}
.flex-wrap {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.condition-button {
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
color: white !important;
border: none !important;
border-radius: 8px !important;
padding: 8px 16px !important;
font-size: 14px !important;
transition: all 0.3s ease !important;
min-width: 120px;
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
&:hover {
background: linear-gradient(135deg, #66b1ff 0%, #409eff 100%) !important;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
}
i {
margin-right: 6px;
}
}
// 拖拽提示
.drag-hint {
display: flex;
align-content: flex-start;
// align-items: center;
justify-content: center;
padding: 20px;
color: #909399;
font-size: 14px;
i {
margin-right: 8px;
font-size: 16px;
animation: bounce 1.5s infinite;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-10px);
}
60% {
transform: translateY(-5px);
}
}
}
// 已选条件区域
.selected-container {
min-height: 120px;
border: 2px dashed #dcdfe6;
border-radius: 8px;
padding: 20px;
transition: all 0.3s ease;
background-color: #dcdfe670;
&:hover {
border-color: #409eff;
background: #f0f9ff;
}
}
.selected-list {
min-height: 100px;
}
// 拖拽项样式
.draggable-item {
position: relative;
// background: rgba(103, 194, 58, 0.3);
padding: 3px;
margin: 8px;
// box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: table-cell;
justify-content: space-between;
// cursor: move;
text-align: center;
&:hover {
transform: translateY(-2px) scale(1.02);
box-shadow: 0 6px 16px rgba(103, 194, 58, 0.4);
}
&.ghost {
opacity: 0.6;
transform: rotate(5deg);
}
}
.item-content {
background: white;
border-radius: 8px;
padding: 20px 12px 12px 12px;
display: flex;
align-items: center;
justify-content: space-between;
min-width: 140px;
position: relative;
}
.item-text {
font-size: 14px;
color: #303133;
font-weight: 500;
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 10px;
}
.item-remove {
color: #c0c4cc;
font-size: 18px;
cursor: pointer;
transition: all 0.3s ease;
padding: 4px;
border-radius: 50%;
&:hover {
color: #f56c6c;
background: #fef0f0;
transform: rotate(90deg);
}
}
/* 规则名称区域 */
.rule-name-section {
margin-bottom: 10px;
}
.rule-name-label {
width: 100px;
}
/* 项目删除按钮 */
.item-remove-btn {
position: absolute;
top: 5px;
right: 10px;
}
/* 条件输入容器 */
.condition-input-container {
flex-wrap: nowrap;
margin-top: 10px;
}
/* 计数条件容器 */
.count-condition-container {
margin-top: 10px;
display: flex;
}
/* 条件选择框 */
.condition-select {
width: 100px;
}
/* 按钮右侧边距 */
.btn-margin-right {
margin-right: 5px;
}
// 空状态样式
.empty-state {
text-align: center;
padding: 40px 20px;
color: #909399;
i {
font-size: 48px;
margin-bottom: 16px;
color: #dcdfe6;
transition: color 0.3s ease;
}
p {
margin: 0;
font-size: 14px;
}
.empty-tip {
font-size: 12px;
color: #c0c4cc;
margin-top: 8px;
}
&:hover i {
color: #409eff;
}
}
// 拖拽效果
.ghost {
opacity: 0.6;
background-color: #e6f7ff;
border: 2px dashed #409eff;
border-radius: 8px;
}
// 响应式设计
@media (max-width: 768px) {
.regulation-wrapper {
padding: 15px;
}
.condition-section,
.selected-section {
padding: 15px;
}
.condition-button {
min-width: 100px;
font-size: 13px !important;
}
.item-content {
min-width: 120px;
padding: 10px 12px;
}
}
:v-deep .el-select {
width: 59%;
}
</style>

View File

@ -1,234 +0,0 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">{{ title }}规则 </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit" v-show="title != '详情'">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<EarlyWarning :list="listData" v-if=" listQuery.mxlx=='01'" ref="regulationRef" :dict="props.dict" :defaultData="defaultData"
:disabled="title == '详情'" />
<Regulation :list="listData" v-if=" listQuery.mxlx=='02'" ref="regulationRef" :dict="props.dict" :defaultData="defaultData"
:disabled="title == '详情'" />
</div>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { ElMessage } from "element-plus";
import { addSsyjpz, editSsyjpz,addYjgzpz,editYjgzpz } from '@/api/model'
import Regulation from "../components/FourColor/regulation.vue";
import EarlyWarning from "../components/EarlyWarning/regulation.vue";
const props = defineProps({
dict: {
type: Array,
default: () => [],
}
})
const dialogForm = ref(false)
const title = ref("新增")
const emit = defineEmits(['getList'])
const typeData = {
'02': [{
name: "地点",
key: "dd",
id: 1
}, {
name: "身份标签",
key: "sfbq",
id: 2
},
// {
// name: "次数",
// key: "cs",
// id: 3
// },
{
name: "行为标签",
key: "xwbq",
id: 4
}, {
name: "组织",
key: "zz",
id: 5
}, {
name: "开始时间",
key: "kssj",
id: 6
}, {
name: "结束时间",
key: "jssj",
id: 7
}],
'01': [{
name: "地点",
key: "dd",
}, {
name: '警情类型',
key: 'jqlx',
}, {
name: '人员信息',
key: 'ryxx',
}, {
name: '事件类型',
key: 'sjlx',
}, {
name: '物品',
key: 'wp',
}, {
name: '组织',
key: 'zz',
}, {
name: '开始时间',
key: 'kssj',
}, {
name: '结束时间',
key: 'jssj',
}, {
name: '次数',
key: 'cs',
}],
}
const listData = ref([])
const listQuery = ref()
const defaultData = ref({})
const mxlx=ref()
const init = (type, item, row) => {
dialogForm.value = true
listQuery.value = item
listData.value = typeData[item.mxlx]
if (type == 'edit') {
defaultData.value = row
title.value = "编辑"
} else if (type == 'add') {
defaultData.value={}
title.value = "新增"
} else {
title.value = "详情"
defaultData.value = row
}
}
const regulationRef = ref(null)
const loading = ref(false)
// 新增
const submit = () => {
switch (listQuery.value.mxlx) {
case '01':
addYjgzpzs()
break;
case '02':
addSsyj()
break;
default:
break;
}
}
const addSsyj = () => {
const data = regulationRef.value.retValue()
if (!data||!data.gzmc) {
ElMessage.warning('请填写规则名称')
return
}
if (title.value == "新增") {
const promes = {
mxid: listQuery.value.id,
...data
}
addSsyjpz(promes).then((result) => {
ElMessage.success('新增成功')
emit('getList')
close()
}).catch((err) => {
ElMessage.error(err.message)
});
} else {
editSsyjpz({
id: defaultData.value.id,
...data
}).then((result) => {
ElMessage.success('编辑成功')
emit('getList')
close()
}).catch((err) => {
ElMessage.error(err.message)
});
}
}
const addYjgzpzs = () => {
const data = regulationRef.value.retValue()
if (!data||!data.gzmc) {
ElMessage.warning('请填写规则名称')
return
}
if (title.value == "新增") {
const promes = {
mxid: listQuery.value.id,
...data
}
addYjgzpz(promes).then((result) => {
ElMessage.success('新增成功')
emit('getList')
close()
}).catch((err) => {
ElMessage.error(err.message)
});
} else {
editYjgzpz({
id: defaultData.value.id,
...data
}).then((result) => {
ElMessage.success('编辑成功')
emit('getList')
close()
}).catch((err) => {
ElMessage.error(err.message)
});
}
}
const close = () => {
dialogForm.value = false
}
defineExpose({
init,
})
</script>
<style lang="scss" scoped>
::v-deep .el-button+.el-button {
margin-left: 0px;
}
.flex {
display: flex;
}
.flex-wrap {
flex-wrap: wrap;
}
.just-between {
justify-content: space-between;
}
.mb-10 {
margin-bottom: 10px;
}
.mr-10 {
margin-right: 10px;
}
</style>

View File

@ -1,273 +0,0 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="预警列表">
<el-button type="primary" size="small" @click="openAddRule('add', item)">新增</el-button>
<el-button type="primary" size="small" :disabled="ids.length == 0" @click="deleteRule(ids)">批量删除</el-button>
<el-button size="small" @click="retenHome()">返回</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData">
<template #tjName="{ row }">
<div class="flex one_text_detail" v-if="row.tj">{{ ` ${row.tj} ${row.cs}` }} </div>
</template>
<template #zz="{ row }">
<template v-if="row.zz">
<span v-for="(item, index) in jsonParse(row.zz)" :key="index">{{ item.zzmc }}
<span v-if="index < jsonParse(row.zz).length - 1"></span>
</span>
</template>
</template>
<template #sfbq="{ row }">
<template v-if="row.sfbq">
<span v-for="(item, index) in jsonParse(row.sfbq)" :key="index">{{ item.bqmc }}
<span v-if="index < jsonParse(row.sfbq).length - 1"></span>
</span>
</template>
</template>
<template #xwbq="{ row }">
<template v-if="row.xwbq">
<span v-for="(item, index) in jsonParse(row.xwbq)" :key="index">{{ item.bqmc }}
<span v-if="index < jsonParse(row.xwbq).length - 1"></span>
</span>
</template>
</template>
<template #dd="{ row }">
<template v-if="row.dd">
<span v-for="(item, index) in jsonParse(row.dd)" :key="index">{{ item.dz }}
<span v-if="index < jsonParse(row.dd).length - 1"></span>
</span>
</template>
</template>
<template #ryxx="{ row }">
<template v-if="row.ryxx">
<span v-for="(item, index) in jsonParse(row.ryxx)" :key="index">{{ item.xm }}
<span v-if="index < jsonParse(row.ryxx).length - 1"></span>
</span>
</template>
</template>
<template #jqlx="{ row }">
<template v-if="row.jqlx">
<span v-for="(item, index) in jsonParse(row.jqlx)" :key="index">{{ item.lxmc }}
<span v-if="index < jsonParse(row.jqlx).length - 1"></span>
</span>
</template>
</template>
<template #sjlx="{ row }">
<template v-if="row.sjlx">
<span v-for="(item, index) in jsonParse(row.sjlx)" :key="index">{{ item.lxmc }}
<span v-if="index < jsonParse(row.sjlx).length - 1"></span>
</span>
</template>
</template>
<template #wp="{ row }">
<template v-if="row.wp">
<span v-for="(item, index) in jsonParse(row.wp)" :key="index">{{ item.wpmc }}
<span v-if="index < jsonParse(row.wp).length - 1"></span>
</span>
</template>
</template>
<template #controls="{ row }">
<el-link type="primary" size="small" @click="yzSsyjpzMxgzxl( row.id)">运行规则</el-link>
<el-link type="primary" size="small" @click="openAddRule('edit',item, row)">修改</el-link>
<el-link type="primary" size="small" @click="openAddRule('detail',item, row)">详情</el-link>
<!-- <el-link type="primary" size="small" @click="openAddRule('detail',item, row)">预警列表</el-link> -->
<el-link type="danger" size="small" @click="deleteRule(row.id)">删除</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import emitter from "@/utils/eventBus.js";
import { deleteYjgzpz,getYjgzpzMxgzxl,getYjxxPageList } from "@/api/model";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import { template } from "lodash";
const props = defineProps({
item: {
type: Object,
default: () => ({})
}
})
const { proxy } = getCurrentInstance();
const { D_BB_AJLB,D_BZ_WPLX} = proxy.$dict("D_BB_AJLB","D_BZ_WPLX")
const regulation = ref(null)
const queryFrom = ref({})
const searchBox = ref(); //搜索框
const searchConfiger = ref([
{
label: "时间",
prop: "startTime",
placeholder: "请选择时间",
showType: "daterange"
},
]);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 300,
tableColumn: [
{ label: "预警时间", prop: "gzmc", showOverflowTooltip: true },
{ label: "类型", prop: "jssj", showOverflowTooltip: true, showSolt: true },
{ label: "内容", prop: "kssj", showOverflowTooltip: true, showSolt: true },
]
});
onMounted(() => {
getList();
tabHeightFn();
});
// 搜索
const onSearch = (val) => {
queryFrom.value.startTime = val.startTime&&val.startTime.length > 0 ? val.startTime[0] : '';
queryFrom.value.endTime = val.startTime&&val.startTime.length > 0 ? val.startTime[1] : '';
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
//
// 获取列表
const getList = () => {
const promes = {
...pageData.pageConfiger,
...queryFrom.value,
mxid:props.item.id,
}
getYjxxPageList(promes).then((res) => {
pageData.tableData = res.records
pageData.total = res.total
});
};
const retenHome = () => {
emitter.emit('changeModel', { name: '研判首页', row: {} });
}
const openAddRule = (type, item, row) => {
regulation.value.init(type, item, row)
}
const ids = ref([])
const chooseData = (val) => {
ids.value = val.map(item => item.id)
}
const deleteRule = (row) => {
proxy.$confirm('是否删除该规则, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let list
if (Array.isArray(row)) {
list = ids.value
} else {
list =[row]
}
deleteYjgzpz({ids:list}).then(() => {
ElMessage.success("删除成功");
getList()
})
}).catch((err) => {
proxy.$message({
type: 'info',
message: '已取消删除'
});
});
}
const yzSsyjpzMxgzxl = (params) => {
getYjgzpzMxgzxl({id:params}).then((res) => {
console.log(res);
})
}
const jsonParse = (val) => {
if (val) {
return JSON.parse(val)
}
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style lang="scss" scoped>
.checkbox-group {
display: flex;
gap: 20px;
}
.basic-info {
display: flex;
gap: 15px;
.avatar {
width: 80px;
height: 80px;
overflow: hidden;
border-radius: 4px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.info-list {
display: flex;
flex-direction: column;
gap: 5px;
}
}
.control-buttons {
display: flex;
gap: 10px;
}
</style>

View File

@ -1,321 +0,0 @@
<template>
<!-- 研判类型 -->
<div class="content">
<div class="titleBox">
<PageTitle title="模型平台">
<el-button type="primary" @click="openAddModel('add')" :icon="CirclePlus">
新增模型
</el-button>
</PageTitle>
</div>
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch"> </Search>
</div>
<ul class="cntlsit mb10" v-if="show" v-infinite-scroll="load" :style="{ height: listHeight + 'px' }"
v-loading="loading">
<li class="model-card" v-for="(it, idx) in list" :key="idx">
<div class="model-info">
<div class="model-name">
<strong>模型名称</strong>{{ it.mxmc }}
</div>
<div class="model-type flex">
<strong>模型类型</strong> <DictTag :tag="false" :value="it.mxlx" :options="D_MXGL_MXLX" />
</div>
</div>
<div class="model-image-container" @click="openYjList">
<img class="model-image"
src="@/assets/images/mxbg.jpg" alt="">
</div>
<div class="model-actions">
<span class="action-btn action-btn-view" @click.stop="openAddRule('', it)">
<el-icon class="action-icon"><Document /></el-icon>查看规则
</span>
<span class="action-btn action-btn-edit" @click.stop="openAddModel('edit', it)">
<el-icon class="action-icon"><ChatDotSquare /></el-icon>编辑
</span>
<span class="action-btn action-btn-edit" @click.stop="openAddModel('detail', it)">
<el-icon class="action-icon"><Edit /></el-icon>详情
</span>
<span class="action-btn action-btn-delete" @click.stop="delDictItem(it.id)">
<el-icon class="action-icon"><Files /></el-icon>删除
</span>
</div>
</li>
<div class="empty-container">
<MOSTY.Empty :show="!loading && list.length <= 0"></MOSTY.Empty>
</div>
<div class="no-more-data" v-if="total == list.length && total > 0">暂时没有数据了</div>
</ul>
</div>
<!-- <AddModel ref="addModel" :dict="{ D_MXGL_MXLX }" @getLits="getLits" /> -->
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import { getPageList, deleteEntity } from '@/api/model.js'
import emitter from "@/utils/eventBus.js";
import { CirclePlus } from '@element-plus/icons-vue'
import * as MOSTY from "@/components/MyComponents/index";
import Search from "@/components/aboutTable/Search.vue";
import { reactive, ref, onMounted, getCurrentInstance, watch, defineEmits } from "vue";
// import AddModel from "../components/AddModel/addModel";
const emit = defineEmits(['change'])
const { proxy } = getCurrentInstance();
const { D_MXGL_MXLX ,D_BZ_RYBQ} = proxy.$dict("D_MXGL_MXLX","D_BZ_RYBQ")
const searchBox = ref(); //搜索框
const show = ref(false)
const listHeight = ref()
const searchConfiger = ref([
{ label: "模型名称", prop: "mxmc", placeholder: "请输入模型名称", showType: "input" },
{
label: "模型类型",
prop: "mxlx",
placeholder: "请选择模型类型",
showType: "select",
options: D_MXGL_MXLX
},
]);
const PaginationConfig = reactive({
pageCurrent: 1,
pageSize: 8,
});
const total = ref(0)
const list = ref([])
const loading = ref(false);
const formData = ref({})
onMounted(() => {
show.value = true;
tabHeightFn();
getLits()
})
const onSearch = (val) => {
formData.value = { ...formData.value, ...val, };
PaginationConfig.pageCurrent = 1;
getLits();
}
const load = () => {
if (total.value == list.value.length) return;
PaginationConfig.pageCurrent++;
// getLits();
}
const getLits = () => {
let params = {
...PaginationConfig,
...formData.value
}
loading.value = true;
getPageList(params).then(res => {
let arr = res.records || [];
list.value = PaginationConfig.pageCurrent == 1 ? arr : list.value.concat(arr);
total.value = res.total;
loading.value = false;
}).catch(() => {
loading.value = false;
})
}
// 表格高度计算
const tabHeightFn = () => {
listHeight.value = window.innerHeight - searchBox.value.offsetHeight - 230;
window.onresize = function () {
tabHeightFn();
};
};
const delDictItem = (id) => {
proxy.$confirm('是否删除该模型, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteEntity({ ids: [id] }).then(res => {
proxy.$message.success("删除成功!")
getLits()
})
}).catch(() => {
proxy.$message({
type: 'info',
message: '已取消删除'
});
});
}
// 打开弹窗
const addModel = ref(null)
const openAddModel = (type, row) => {
addModel.value.init(type, row)
}
// 打开规则弹窗
const openAddRule = (type, row) => {
switch (row.mxlx) {
case '02':
emitter.emit('changeModel', {row,name:'四色预警规则'})
break;
case '01':
emitter.emit('changeModel', {row,name:'预警规则'})
break;
default:
break;
}
}
const openYjList = (row) => {
emitter.emit('changeModel', {row,name:'预警列表'})
}
</script>
<style lang="scss" scoped>
.content {
width: 100%;
height: 100%;
margin-top: 20px;
margin-left: 10px;
border-radius: 8px;
box-sizing: border-box;
.btnsBox {
background: #fff;
padding: 10px 5px;
border-radius: 4px;
margin-bottom: 10px;
}
.cntlsit {
display: flex;
flex-wrap: wrap;
align-content: start;
gap: 20px;
overflow: hidden;
overflow-y: auto;
background: #fff;
padding: 16px;
box-sizing: border-box;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
// 模型卡片样式
.model-card {
width: 300px;
border: 1px solid #e4e7ed;
border-radius: 8px;
overflow: hidden;
background: #fff;
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
&:hover {
transform: translateY(-4px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
border-color: #409eff;
}
// 模型信息区域
.model-info {
padding: 16px;
background-color: #fafafa;
border-bottom: 1px solid #f0f0f0;
.model-name,
.model-type {
margin-bottom: 8px;
font-size: 14px;
color: #606266;
strong {
color: #303133;
font-weight: 500;
}
}
.model-type {
margin-bottom: 0;
}
}
// 模型图片区域
.model-image-container {
cursor: pointer;
overflow: hidden;
transition: all 0.3s ease;
.model-image {
width: 100%;
height: 168px;
object-fit: cover;
transition: transform 0.3s ease;
&:hover {
transform: scale(1.05);
}
}
}
// 操作按钮区域
.model-actions {
text-align: right;
padding: 12px 0px;
border-top: 1px solid #f0f0f0;
background-color: #fafafa;
.action-btn {
// margin-left: 12px;
justify-content: space-between;
font-size: 13px;
cursor: pointer;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
padding: 4px 8px;
border-radius: 4px;
.action-icon {
margin-right: 4px;
font-size: 14px;
}
&:hover {
opacity: 0.8;
}
}
.action-btn-view,
.action-btn-edit {
color: #409eff;
&:hover {
background-color: #ecf5ff;
}
}
.action-btn-delete {
color: #f4ac47;
&:hover {
background-color: #fff7e6;
}
}
}
}
// 空状态和无更多数据样式
.empty-container {
width: 100%;
display: flex;
justify-content: center;
padding: 40px 0;
}
.no-more-data {
width: 100%;
text-align: center;
margin-bottom: 16px;
color: #a29f9f;
font-size: 13px;
}
}
</style>

View File

@ -0,0 +1,97 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<div>详情</div>
<div><el-button @click="close">关闭</el-button></div>
</div>
<div class="form_cnt">
<FormMessage v-model="listQuery" disabled :formList="formData" ref="elform">
<template #yjTp="{ row }">
<template v-if="!listQuery.yjTp || listQuery.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="listQuery.yjlx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</template>
<el-image v-else style="width: 80px; height:120px" :src="listQuery.yjTp" :preview-src-list="[row.yjTp]"
show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="listQuery.yjlx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</div>
</template>
</el-image>
</template>
</FormMessage>
</div>
</div>
</template>
<script setup>
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { ref, defineExpose } from "vue";
const props = defineProps({
dict: {
type: Object,
default: () => ({})
}
});
const dialogForm = ref(false); //弹窗
const formData = ref([
{ label: "预警照片", prop: "yjTp", type: "slot", width: '100%' },
{ label: "预警名称", prop: "yjBt", type: "input" },
{ label: "预警人员姓名", prop: "yjRyxm", type: "input" },
{ label: "车牌号", prop: "yjClcph", type: "input" },
{ label: "身份证号", prop: "yjRysfzh", type: "input" },
{ label: "预警地址", prop: "yjDz", type: "input" },
{ label: "预警时间", prop: "yjsj", type: "date" },
{ label: "预警类型", prop: "yjlx", type: "select", options: props.dict.D_BZ_YJLX },
{ label: "预警内容", prop: "yjnr", type: "textarea", width: '100%' },
]);
const listQuery = ref({}); //表单
const elform = ref();
// 初始化数据
const init = (row) => {
dialogForm.value = true;
listQuery.value = row;
};
// 关闭
const close = () => {
listQuery.value = {};
dialogForm.value = false;
};
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
color: #0072ff;
background: rgba(0, 114, 255, 0.3);
}
.boxlist {
width: 99%;
height: 225px;
margin-top: 10px;
overflow: hidden;
}
::v-deep .avatar-uploader {
display: flex;
align-items: center;
}
::v-deep .el-upload-list {
margin-left: 20px;
display: flex;
align-items: center;
}
::v-deep .el-upload-list__item-name .el-icon {
top: 3px;
}
</style>

View File

@ -0,0 +1,195 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="预警详情">
<!-- <el-button type="primary" size="small" @click="yzSsyjpzMxgzxl()">测试</el-button> -->
<el-button size="small" @click="retenHome()">返回</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #yjTp="{ row }">
<template v-if="!row.yjTp || row.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjlx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</template>
<el-image v-else style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]"
show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjlx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</div>
</template>
</el-image>
</template>
<template #yjlx="{ row }">
<DictTag :tag="false" :value="row.yjlx" :options="dict.D_BZ_YJLX" />
</template>
<template #controls="{ row }">
<el-link type="primary" size="small" @click="openYjdict(row)">详情</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
</div>
<DetailsFollows ref="yjdict" :dict="dict" />
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import { mxglJqxqPageList } from "@/api/model";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import { reactive, ref, onMounted, getCurrentInstance, watch } from "vue";
import DetailsFollows from './detailsFollows.vue'
const props = defineProps({
item: {
type: Object,
default: () => ({})
}, dict: {
type: Object,
default: () => ({})
}
})
const queryFrom = ref({})
const searchBox = ref(); //搜索框
const yjdict = ref(null)//详情弹窗
const ItemData = ref()//模型数据
const searchConfiger = ref([
{
label: "时间",
prop: "startTime",
placeholder: "请选择时间",
showType: "daterange"
},
]);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 150,
tableColumn: [
// { label: "预警名称", prop: "", showOverflowTooltip: true },
// { label: "预警图片", prop: "yjTp", showOverflowTooltip: true, showSolt: true },
{ label: "报警人", prop: "bjrmc", showOverflowTooltip: true },
{ label: "接警单号", prop: "bjh", showOverflowTooltip: true },
// { label: "车牌号", prop: "yjClcph", showOverflowTooltip: true },
// { label: "身份证号", prop: "yjRysfzh", showOverflowTooltip: true },
{ label: "报警时间", prop: "bjsj", showOverflowTooltip: true },
{ label: "报警地址", prop: "bjdz", showOverflowTooltip: true },
{ label: "类型", prop: "yjlx", showSolt: true },
{ label: "报警内容", prop: "bjnr", showOverflowTooltip: true },
]
});
onMounted(() => {
getList();
tabHeightFn();
});
const openYjdict = (val) => {
yjdict.value.init(val)
}
watch(() => props.item, (val) => {
ItemData.value = val
}, { deep: true })
// 获取列表
const getList = () => {
const promes = {
...pageData.pageConfiger,
...queryFrom.value,
yjid: props.item.id,
}
mxglJqxqPageList(promes).then((res) => {
pageData.tableData = res.records || []
pageData.total = res.total
});
};
// 搜索
const onSearch = (val) => {
queryFrom.value.startTime = val.startTime && val.startTime.length > 0 ? val.startTime[0] : '';
queryFrom.value.endTime = val.startTime && val.startTime.length > 0 ? val.startTime[1] : '';
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
//返回
const retenHome = () => {
emitter.emit('changeModel', { name: '预警列表', row: {} });
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style lang="scss" scoped>
.checkbox-group {
display: flex;
gap: 20px;
}
.basic-info {
display: flex;
gap: 15px;
.avatar {
width: 80px;
height: 80px;
overflow: hidden;
border-radius: 4px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.info-list {
display: flex;
flex-direction: column;
gap: 5px;
}
}
.control-buttons {
display: flex;
gap: 10px;
}
</style>

View File

@ -19,7 +19,8 @@
<DictTag :tag="false" :value="row.yjlx" :options="dict.D_BZ_TPYJLX" />
</template>
<template #controls="{ row }">
<el-link type="primary" size="small" @click="opneModel">打开研判报告</el-link>
<el-link type="primary" size="small" @click="opneModel(row)">打开研判报告</el-link>
<el-link type="primary" size="small" @click="warningDetails(row)">预警详情</el-link>
<el-link type="primary" size="small" @click="openYjdict(row)">详情</el-link>
</template>
</MyTable>
@ -36,12 +37,13 @@
<script setup>
import YpModel from '@/components/ypModel/index.vue'
import emitter from "@/utils/eventBus.js";
import { getYjxxPageList,getSsyjpzMxgzxl } from "@/api/model";
import { getYjxxPageList,getSsyjpzMxgzxl,mxglYjxqSelectList } from "@/api/model";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import {timeValidate} from '@/utils/tools'
import { timeValidate } from '@/utils/tools'
import { completions } from '@/api/semanticAnalysis'
import { reactive, ref, onMounted, getCurrentInstance, watch } from "vue";
import { textStyle, Firstlevelheading, Subheading, BiheadlinegTitle, newTotitle,BigTitle,fbtool, headTitle, report, signature } from '../content.js'
import Yjdict from './yjdict.vue'
@ -62,14 +64,41 @@ const showModel = ref(false)
const textContent=ref('')//报告数据
const SaveReport = () => {
}
const opneModel = () => {
const opneModel = (row) => {
showModel.value = true
textContent.value=''
textContent.value += BigTitle("林芝市公安局情指中心") + BigTitle("研判专刊(初稿)") + newTotitle({
textContent.value = ''
mxglYjxqSelectList({
yjid: row.id,
}).then((res) => {
let str = {
model: "deepseek-32b",
prompt: `# 角色定位\n你是一名资深警务人员尤其擅长对警情、案件、线索等非结构化文本数据进行阅读理解并从中提取各种对象特征信息进行结构化并总结各种对象之间的关联关系。\n`,
max_tokens: 1000,
}
res.forEach(item => {
const lx = props.dict.D_BZ_YJLX.find(items => {
return items.value == item.yjlx
}).zdmc
str.prompt+=`预警名称:${item.yjBt},预警人员姓名:${item.yjRyxm},身份证号:${item.yjRysfzh},车牌号:${item.yjClcph},预警地址:${item.yjDz},预警类型:${lx},预警内容:${item.yjnr},预警时间:${item.yjsj}\n`
})
str.prompt += `根据以上预警信息,总结出一个解决方案`
let jsonMatch
completions(str).then(reslve => {
jsonMatch = reslve.choices[0].text
textContent.value += BigTitle("林芝市公安局情指中心") + BigTitle("研判专刊(初稿)") + newTotitle({
org: "市公安局情指中心编",
time: timeValidate()
})+fbtool('同类事件发生3次以上预警')+textStyle("2025年9月2日164525,产生同类事件3次以上预警,刑事案件中的置充身份诈美发生3起同七上升30%、环比比下健5%")
+ Subheading('1.警情内容') + Subheading('2.警情内容') + Subheading('3.警情内容')
}) + fbtool(`同类事件发生${res.length}次以上预警`)
res.forEach((item,index) => {
const lx = props.dict.D_BZ_YJLX.find((items) => {
return items.value == item.yjlx
}).zdmc
textContent.value +=Subheading(`${index+1}.警情内容`)+textStyle(`预警名称:${item.yjBt},预警人员姓名:${item.yjRyxm},身份证号:${item.yjRysfzh},车牌号:${item.yjClcph},预警地址:${item.yjDz},预警类型:${lx},预警内容:${item.yjnr},预警时间:${item.yjsj}\n`)
})
textContent.value+=Subheading(`解决方案`)+textStyle(jsonMatch?jsonMatch:'暂无解决方案')
})
})
}
const searchConfiger = ref([
@ -86,7 +115,7 @@ const pageData = reactive({
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
// loading: false
},
total: 0,
pageConfiger: {
@ -159,9 +188,10 @@ const yzSsyjpzMxgzxl = (params) => {
// })
getSsyjpzMxgzxl({id:'88c166e670da48e59324906648794b05'}).then((res) => {
})
}
const warningDetails = (row) => {
emitter.emit('changeModel', { row, name: '预警详情' })
}
</script>
<style lang="scss" scoped>

View File

@ -1,25 +1,20 @@
<template>
<div>
<YpHome v-if="showModel == '研判首页'"></YpHome>
<!-- <ModeList v-if="showModel == '四色预警规则'" :item="itemData" ></ModeList>
<EarlyWarning v-if="showModel == '预警规则'" :item="itemData" ></EarlyWarning> -->
<!-- <YjList v-if="showModel == '预警列表'" :item="itemData" ></YjList> -->
<List v-if="showModel == '四色预警规则' || showModel == '预警规则'" :item="itemData"></List>
<YjDetail v-if="showModel == '预警列表'" :item="itemData" :dict="{D_BZ_TPYJLX}"></YjDetail>
<YjDetail v-if="showModel == '预警列表'" :item="itemData" :dict="{ D_BZ_TPYJLX,D_BZ_YJLX }"></YjDetail>
<WarningList v-if="showModel == '预警详情'" :item="itemData" :dict="{ D_BZ_YJLX }"/>
</div>
</template>
<script setup>
import YpHome from "./components/ypHome.vue";
// import YjList from "./components/yjList.vue";
import YjDetail from './components/AddModel/yjList.vue'
import List from "./components/list.vue";
// import ModeList from "./components/FourColor/modeList.vue";
// import EarlyWarning from "./components/EarlyWarning/modeList.vue";
import WarningList from "./components/AddModel/warningList.vue"
const { proxy } = getCurrentInstance();
import emitter from "@/utils/eventBus.js";
import { onMounted, ref, getCurrentInstance } from "vue";
const { D_BZ_TPYJLX} = proxy.$dict("D_BZ_TPYJLX")
const { D_BZ_TPYJLX,D_BZ_YJLX } = proxy.$dict("D_BZ_TPYJLX","D_BZ_YJLX")
const showModel = ref('研判首页')
const itemData = ref({})

View File

@ -1,9 +1,10 @@
<template>
<div class="dialog" v-if="dialogForm" v-infinite-scroll="load" :infinite-scroll-disabled="disabled">
<!-- v-if="dialogForm" -->
<div v-infinite-scroll="load" :infinite-scroll-disabled="disabled">
<!-- class="head_box" -->
<div style="position: sticky;top: 0;float: right;">
<!-- <div style="position: sticky;top: 0;float: right;">
<el-button size="small" @click="close">关闭</el-button>
</div>
</div> -->
<div class="content_box">
<div>
<div class="title_box">{{ listQuery.xsMc }}</div>
@ -35,8 +36,11 @@
</div>
<div class="title_box virtual">评论列表</div>
<CommentList v-for="(item, index) in pagesData.listData" :key="index" :index="index" :item="item"
<div style="height: 38vh;overflow: auto;">
<CommentList v-for="(item, index) in pagesData.listData" :key="index" :index="index" :item="item"
@postReply="postReply" @delComment="delComment" :userInfo="userInfo" @cjpjZan="cjpjZan"/>
</div>
<div class="sticky">
<div class="title_box virtual">发表评论</div>
<div class="flex flex-column ">
@ -58,36 +62,35 @@ import { ref, reactive, toRaw, watch, onMounted, onUnmounted } from "vue";
import CommentList from '../itemXs/commentList.vue'
import { getItem } from '@/utils/storage.js'
import { ElMessage, ElMessageBox } from 'element-plus'
import emitter from "@/utils/eventBus.js";
const emit = defineEmits(["updateDate"]);
const props = defineProps({
dict: {
type: Object,
default: () => ({})
}, msgeDat: {
type: Object,
default: () => ({})
}
});
const dialogForm = ref(false); //弹窗
const listQuery = ref({})
// 初始化数据
const commentInit = (row) => {
// 根据id查询详情
qcckGet({ id: row }, "/mosty-gsxt/qbcj/selectByid").then((res) => {
listQuery.value = res;
cjpjSelectPage()
}).catch((err) => {
console.log(err);
});
};
watch(() => props.msgeDat, (newVal) => {
commentInit(newVal.id)
},{deep: true,immediate: true})
const textarea2 = ref()
const userInfo = ref(getItem('idEntityCard'))
// 初始化数据
const init = (row) => {
dialogForm.value = true;
// 根据id查询详情
if (row) {
qcckGet({ id: row }, "/mosty-gsxt/qbcj/selectByid").then((res) => {
listQuery.value = res;
});
cjpjSelectPage()
}
};
// 关闭
const close = () => {
dialogForm.value = false;
pagesData.pagebreak.pageCurrent = 1
};
const pagesData = reactive({
total: 0,
pagebreak: {
@ -184,8 +187,6 @@ const cjpjZan = (val,data) => {
const disabled = ref(false)
defineExpose({ init });
const load = () => {
if (pagesData.pagebreak.pageCurrent < pagesData.total) {
pagesData.pagebreak.pageCurrent++
@ -281,7 +282,7 @@ const load = () => {
}
.itemXs_Xs {
width: 18%;
// width: 18%;
font-size: 14px;
color: #6c6c6c;
line-height: 20px;

View File

@ -187,7 +187,7 @@ const handleLike = (item) => {
.itemXs_time {
justify-content: space-between;
width: 23%;
// width: 23%;
align-items: center;
color: #000;

View File

@ -1,11 +1,9 @@
<template>
<div>
<CommentList v-for="(item, index) in pagesData.listData" :key="index" :item="item" @delComment="cjhfRemove" :userInfo="userInfo"/>
<el-pagination v-if="pagesData.total > 10" v-model:current-page="pagesData.pagebreak.pageCurrent"
v-model:page-size="pagesData.pagebreak.pageSize" :size="10" :disabled="false" :total="pagesData.total"
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
<div style="text-align: center;width: 100%;height: 20px;" v-if="pagesData.total == 0">暂无回复</div>
</div>
</template>
<script setup>
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";

View File

@ -320,17 +320,13 @@ function simpleExtractJSON(text) {
// 找到第一个 [
const startIndex = text.indexOf('[');
if (startIndex === -1) return null;
// 找到最后一个完整的 }
let lastBraceIndex = text.lastIndexOf('}');
if (lastBraceIndex === -1) return null;
// 确保 } 后面没有其他字符(除了空格和换行)
let endIndex = lastBraceIndex + 1;
// 截取从 [ 到最后一个 } 的内容,然后加上 ]
let jsonString = text.substring(startIndex, endIndex) + ']';
try {
return JSON.parse(jsonString);
} catch (error) {

View File

@ -0,0 +1,496 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="敏感节点"> </PageTitle>
</div>
<div class="tabBox contentBox">
<div class="leftBox">
<el-calendar ref="calendar" v-model="currentDate">
<template #header="{ date }">
<div style="display: flex;">
<el-select @change="goToSelectedMonth" v-model="selectedYear" style="margin-right: 10px;">
<el-option v-for="year in years" :key="year" :label="year + '年'" :value="year" />
</el-select>
<el-select @change="goToSelectedMonth" v-model="selectedMonth">
<el-option v-for="month in months" :key="month.value" :label="month.label" :value="month.value" />
</el-select>
</div>
<div style="color: #000;display: flex;align-items: center;">
<div style="margin-right: 10px;"> {{ dateVal }}</div> <el-button
@click="selectDate('today')">今天</el-button>
</div>
</template>
<template #dateCell="{ data }">
<div @click="chooseDay(data)" class="dayonChage"
:class="{ 'day': dateVal == data.day,
'special': dataIntegration.includes(data.day)}"
>
<div> {{ data.day.split("-")[2] }}</div>
<div v-for="(item, index) in getAllFestivals(data.day)" :key="index"> {{ item.name }}</div>
<div v-if="getWorkdayType(data.day)" class="holiday-badge"
:class="getWorkdayType(data.day) == '班' ? 'holiday-work' : 'holiday-rest'">
{{ getWorkdayType(data.day) }}
</div>
<div> {{ getLunarMonthDay(data.date) }}</div>
</div>
</template>
</el-calendar>
</div>
<div class="riteBox">
<div class="sensitive-list-header">
<h3>敏感时间节点</h3>
<div class="add-form">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
<el-form-item prop="jdbt">
<el-input v-model="ruleForm.jdbt" placeholder="请输入敏感事件名称" />
</el-form-item>
<el-form-item prop="jdnr">
<el-input v-model="ruleForm.jdnr" type="textarea" placeholder="请输入敏感事件内容" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(ruleFormRef)">
{{ submitZt ? '新增' : '修改' }}
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
<div class="sensitive-list">
<div v-for="(item, index) in sensitiveNodes" :key="index" class="sensitive-item">
<div class="sensitive-date">{{ item.date }}</div>
<div class="sensitive-content">{{ item.jdbt }}</div>
<el-button type="text" @click="modification(item)" size="small">修改</el-button>
<el-button type="text" @click="deleteSensitiveNode(item.id)" size="small">删除</el-button>
</div>
<div v-if="sensitiveNodes.length === 0" class="empty-tip">暂无敏感时间节点</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import { ref, computed, onMounted } from "vue";
import { Solar, HolidayUtil } from 'lunar-javascript'
import { timeValidate } from "@/utils/tools";
import { ElMessage, ElMessageBox } from 'element-plus';
import { tbGsxtMgjdSave, tbGsxtMgjdSelectList, tbGsxtMgjdUpdate, tbGsxtMgjdDelete } from "@/api/tbGsxtMgjd";
const dateVal = ref();
const ruleFormRef = ref()
// 获取工作日类型
const getWorkdayType = (date) => {
try {
const time = new Date(date)
const year = time.getFullYear()
const month = time.getMonth() + 1 // JavaScript月份从0开始
const day = time.getDate()
// 正确调用HolidayUtil.getHoliday方法传入数值类型的年、月、日
const holiday = HolidayUtil.getHoliday(year, month, day)
if (holiday) {
// 如果是调休需要上班
if (holiday.isWork()) {
return '班'
}
// 如果是法定节假日放假
return '休'
}
return null
} catch (error) {
console.error('获取节假日信息失败:', error)
return null
}
}
// 获取农历月日
const getLunarMonthDay = (date) => {
if (!date) return ''
const solar = Solar.fromDate(date)
const lunar = solar.getLunar()
return lunar.getJieQi() ? lunar.getJieQi() : lunar.getDayInChinese()
}
const getAllFestivals = (date) => {
const time = new Date(date)
const solar = Solar.fromDate(time)
const lunar = solar.getLunar()
const result = []
// 获取农历节日
const lunarFestivals = lunar.getFestivals()
lunarFestivals.forEach(festival => {
result.push({
type: '农历节日',
name: festival,
})
})
// 获取公历节日
const solarFestivals = solar.getFestivals()
solarFestivals.forEach(festival => {
result.push({
type: '公历节日',
name: festival,
})
})
// 获取其他纪念日
const otherFestivals = solar.getOtherFestivals()
otherFestivals.forEach(festival => {
result.push({
type: '纪念日',
name: festival,
})
})
return result
}
const selectedYear = ref();
const selectedMonth = ref('');
const calendar = ref(null)
// 生成年份选项前后10年
const years = computed(() => {
const currentYear = new Date().getFullYear();
const years = [];
for (let i = currentYear - 10; i <= currentYear + 10; i++) {
years.push(i);
}
return years;
});
// 月份选项
const months = ref([
{ label: '1月', value: 0 },
{ label: '2月', value: 1 },
{ label: '3月', value: 2 },
{ label: '4月', value: 3 },
{ label: '5月', value: 4 },
{ label: '6月', value: 5 },
{ label: '7月', value: 6 },
{ label: '8月', value: 7 },
{ label: '9月', value: 8 },
{ label: '10月', value: 9 },
{ label: '11月', value: 10 },
{ label: '12月', value: 11 }
]);
// 切换日期
const chooseDay = (data) => {
dateVal.value = data.day
ruleForm.value.jdrq = data.day
querySensitiveNodes()
submitZt.value = true
ruleForm.value = {}
ruleForm.value.jdrq = dateVal.value
}
const currentDate = ref(new Date());
// 敏感时间节点数据
const sensitiveNodes = ref([]);
onMounted(() => {
initialize()
gettingData()
})
// 获取选项初始值
const initialize = () => {
const year = timeValidate(currentDate.value, 'yd')
const month = timeValidate(currentDate.value, 'ym')
dateVal.value = timeValidate(currentDate.value, 'ymd')
selectedYear.value = parseFloat(year)
selectedMonth.value = parseFloat(month) - 1
ruleForm.value.jdrq = dateVal.value
querySensitiveNodes()
}
const goToSelectedMonth = () => {
if (selectedYear.value && selectedMonth.value !== '') {
const newDate = new Date(selectedYear.value, selectedMonth.value, 1);
currentDate.value = newDate;
dateVal.value = timeValidate(currentDate.value, 'ymd')
gettingData()
}
};
const ruleForm = ref({})
const rules = {
jdrq: [
{ required: true, message: '请选择日期', trigger: 'blur' }
],
jdnr: [
{ required: true, message: '请输入敏感事件内容', trigger: 'blur' }
],
jdbt: [
{ required: true, message: '请输入敏感事件名称', trigger: 'blur' }
]
}
const selectDate = (val) => {
if (!calendar.value) return
calendar.value.selectDate(val)
dateVal.value = timeValidate(currentDate.value, 'ymd')
initialize()
gettingData()
}
const submitZt = ref(true)
// 提交表单
const submitForm = async (formEl) => {
if (!formEl) return
try {
await formEl.validate()
const promes = { ...ruleForm.value }
console.log(promes);
if (submitZt.value) {
tbGsxtMgjdSave(promes).then(() => {
ElMessage.success('新增成功')
querySensitiveNodes()
// 在API调用成功后再重置表单
resetForm(formEl)
})
} else {
tbGsxtMgjdUpdate(promes).then(() => {
ElMessage.success('修改成功')
querySensitiveNodes()
// 在API调用成功后再重置表单
resetForm(formEl)
})
}
} catch (error) {
console.log('验证失败:', error)
}
}
// 查询敏感事件
const querySensitiveNodes = () => {
tbGsxtMgjdSelectList({ jdrq: dateVal.value }).then((res) => {
sensitiveNodes.value = res && res.length > 0 ? res : []
})
}
// 重置表单
const resetForm = (formEl) => {
if (!formEl) return
try {
formEl.resetFields()
} catch (error) {
// 手动重置表单数据
ruleForm.value = { jdrq: dateVal.value || '', jdbt: '', jdnr: '' }
}
// 重置提交状态为新增
submitZt.value = true
}
// 删除敏感时间节点
const deleteSensitiveNode = (id) => {
ElMessageBox.confirm('确定要删除这个敏感时间节点吗?', '确认删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
tbGsxtMgjdDelete({ ids: [id] }).then(() => {
ElMessage.success('删除成功')
querySensitiveNodes()
})
}).catch(() => {
ElMessage.info('已取消删除')
})
}
// 修改
const modification = (item) => {
ruleForm.value = { ...item }
submitZt.value = false
}
const dataIntegration = ref([])
// 获取当前月份的所有信息
const gettingData = () => {
const date = new Date(dateVal.value);
date.setDate(1)
const startTime = timeValidate(date.toLocaleDateString(), 'ymd')
date.setMonth(date.getMonth() + 1);
date.setDate(0);
const endTime = timeValidate(date.toLocaleDateString(), 'ymd')
const params = { startTime, endTime }
tbGsxtMgjdSelectList(params).then(res => {
if (res&&res.length>0) {
dataIntegration.value=[...new Set(res.map(item => item.jdrq))]?[...new Set(res.map(item => item.jdrq))] : []
}
})
}
</script>
<style scoped lang="scss">
.contentBox {
height: calc(100vh - 190px);
display: flex;
justify-content: space-between;
padding: 10px;
color: #000;
.leftBox {
width: calc(100% - 20px - 20%)
}
.riteBox {
width: calc(100% - 20px - 80%);
background-color: #fff;
border-radius: 4px;
padding: 15px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.sensitive-list-header {
margin-bottom: 15px;
}
.sensitive-list-header h3 {
margin: 0 0 10px 0;
font-size: 16px;
}
.add-form {
// display: flex;
// align-items: center;
gap: 5px;
margin-bottom: 10px;
}
.sensitive-list {
flex: 1;
overflow-y: auto;
}
.sensitive-item {
padding: 10px;
margin-bottom: 8px;
background-color: #f5f5f5;
border-radius: 4px;
display: flex;
align-items: flex-start;
justify-content: space-between;
}
.sensitive-date {
font-weight: bold;
margin-bottom: 5px;
}
.sensitive-content {
font-size: 14px;
color: #666;
flex: 1;
margin-left: 10px;
}
.empty-tip {
text-align: center;
color: #999;
padding: 20px;
}
}
// ::v-deep .el-calendar__header {
// padding: 4px 20px !important;
// color: #fff;
// }
// ::v-deep .el-calendar__body {
// padding: 3px 20px 35px !important;
// }
::v-deep .el-calendar-table thead th {
// padding: 4px 0 !important;
color: #fff;
}
::v-deep .el-calendar-table td.is-today {
color: #35ff02;
}
::v-deep .el-calendar-table thead th {
color: #000000;
}
::v-deep .el-calendar {
background-color: #fff;
}
::v-deep .el-calendar-day {
background-color: #fff;
text-align: center !important;
padding: 0 !important;
}
::v-deep .el-calendar-table:not(.is-range) td.prev {
color: #bbbbbb8f !important;
}
::v-deep .el-calendar-table:not(.is-range) td.next,
.el-calendar-table:not(.is-range) td.prev {
color: #bbbbbb8f !important;
}
::v-deep .el-calendar-table td {
color: #000 !important;
}
.dayonChage.special.day {
background-color: #e6a23c;
color: white;
}
.day {
background-color: rgb(76, 134, 243);
color: #35ff02;
}
.special{
background-color: rgba(253, 112, 112, 0.856);
color: #ffffff;
}
// 敏感日期样式
.sensitive-day {
background-color: rgba(255, 214, 0, 0.3);
border: 1px solid #ffd600;
}
.dayonChage {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
/* 水平居中 */
justify-content: center;
/* 垂直居中 */
position: relative;
}
/* 节假日徽章样式 */
.holiday-badge {
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: bold;
position: absolute;
top: 4px;
right: 4px;
}
/* 调休上班样式 - 红底白字 */
.holiday-work {
background-color: red;
color: white;
}
/* 法定节假日样式 - 绿底白字 */
.holiday-rest {
background-color: green;
color: white;
}
</style>

View File

@ -2,9 +2,9 @@
<div>
<div class="titleBox">
<PageTitle title="行为预警">
<el-button type="primary" @click="exportExcel">
<!-- <el-button type="primary" @click="exportExcel">
<span style="vertical-align: middle">导出</span>
</el-button>
</el-button> -->
</PageTitle>
</div>
<!-- 搜索 -->
@ -13,37 +13,31 @@
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
>
<template #xwcs="{ row }">
<span style="color: #0072ff;" @click="handleClick(row)">{{ row.xwcs }}</span>
</template>
<template #bqYs="{ row }">
<DictTag :value="row.bqys" :tag="false" :options="D_GS_SSYJ" />
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger">
<template #xwcs="{ row }">
<span style="color: #0072ff;" @click="handleClick(row)">{{ row.xwcs }}</span>
</template>
<template #bqYs="{ row }">
<!-- <div :style="{
backgroundColor: bqYs(row.bqys)
}"></div> -->
<DictTag :value="row.bqys" :tag="false" :color="bqYs(row.bqys)" :options="D_GS_SSYJ" />
</template>
<template #controls="{ row }">
<el-link type="primary">下发指令</el-link>
<el-link type="success">查看反馈</el-link>
</template>
</MyTable>
<Pages
@changeNo="changeNo"
@changeSize="changeSize"
:tableHeight="pageData.tableHeight"
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
</div>
<!-- 详情 -->
<Detail ref="detailRef"></Detail>
<Detail ref="detailRef"></Detail>
</template>
<script setup>
@ -54,16 +48,26 @@ import Search from "@/components/aboutTable/Search.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { qcckGet } from "@/api/qcckApi.js";
import { reactive, ref, onMounted,getCurrentInstance } from "vue";
import { tbGsxtBqglSelectList } from '@/api/zdr'
import { reactive, ref, onMounted, getCurrentInstance, computed, watch } from "vue";
const { proxy } = getCurrentInstance();
const { D_GS_SSYJ } = proxy.$dict("D_GS_SSYJ"); //获取字典数据
const searchBox = ref(); //搜索框
const bqLbData = ref({
bqXl: []
})
const searchConfiger = ref(
[
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input"},
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input"},
{ label: "电话号码", prop: 'dh', placeholder: "请输入电话号码", showType: "input"},
]);
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input" },
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input" },
{ label: "电话号码", prop: 'dh', placeholder: "请输入电话号码", showType: "input" },
{
label: "标签小类", prop: 'bqxl', placeholder: "请选择标签小类",
showType: "select", options: []
},
]);
const detailRef = ref()
const queryFrom = ref({});
const pageData = reactive({
@ -81,42 +85,70 @@ const pageData = reactive({
pageCurrent: 1
}, //分页
tableColumn: [
{ label: "姓名", prop: "xm"},
{ label: "姓名", prop: "xm" },
{ label: "身份证号", prop: "sfzh" },
{ label: "电话", prop: "dh" },
{ label: "行为大类", prop: "xldlmc"},
{ label: "行为子类", prop: "xwzlmc", showOverflowTooltip: true },
{ label: "行为描述", prop: "xwms", showOverflowTooltip: true },
{ label: "行为大类", prop: "xldlmc" },
{ label: "行为子类", prop: "xwzlmc", showOverflowTooltip: true },
{ label: "行为描述", prop: "xwms", showOverflowTooltip: true },
{ label: "行为次数", prop: "xwcs", showSolt: true },
{ label: "行为颜色", prop: "bqYs",showSolt: true },
{ label: "行为分值", prop: "xwfz",},
{ label: "行为颜色", prop: "bqYs", showSolt: true },
{ label: "行为分值", prop: "xwfz", },
]
});
const gettbGsxtBqglSelectList = (val) => {
tbGsxtBqglSelectList({ bqLx: '02', bqlb: val, bqDlId: '241cc7b69a50428287cc79445e310180' }).then((res) => {
bqLbData.value.bqXl = res.map(item => {
return {
label: item.bqMc,
value: item.id
}
}) || []
})
}
watch(() => bqLbData.value.bqXl, (res) => {
searchConfiger.value.push({
label: "标签小类", prop: 'bqxl', placeholder: "请选择标签小类",
showType: "select", options: res
},)
}, { deep: true })
onMounted(() => {
tabHeightFn();
getList()
gettbGsxtBqglSelectList('02')
});
// 搜索
const onSearch = (val) =>{
queryFrom.value = {...val}
const onSearch = (val) => {
queryFrom.value = { ...val }
pageData.pageConfiger.pageCurrent = 1;
getList()
}
const changeNo = (val) =>{
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList()
}
const changeSize = (val) =>{
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList()
}
const getList = () =>{
const getList = () => {
pageData.tableConfiger.loading = true;
qcckGet(queryFrom.value,'/mosty-gsxt/yjzxXwyj/getPageList').then((res)=>{
const promes = {
...queryFrom.value,
pageCurrent: pageData.pageConfiger.pageCurrent,
pageSize: pageData.pageConfiger.pageSize
}
qcckGet(promes, '/mosty-gsxt/yjzxXwyj/getPageList').then((res) => {
pageData.total = res.total || 0;
pageData.tableConfiger.loading = false;
// pageData.tableData = res.records || [];
}).catch(()=>{
pageData.tableData = res.records.map(item => {
return {...item,bqys: '01'}
}) || [];
}).catch(() => {
pageData.tableConfiger.loading = false;
})
}
@ -126,7 +158,7 @@ const handleClick = (row) => {
}
const exportExcel = () => {
if (pageData.tableData.length === 0) return ElMessage({ message: "暂无数据", type: "warning" });
if (pageData.tableData.length === 0) return ElMessage({ message: "暂无数据", type: "warning" });
const headers = pageData.tableColumn.map(item => item.label);
const data = pageData.tableData.map(item => {
return [item.xm, item.sfzh, item.dh, item.xldlmc, item.xwzlmc, item.xwms, item.xwcs, item.xwfz];
@ -136,11 +168,21 @@ const exportExcel = () => {
XLSX.utils.book_append_sheet(workbook, worksheet, "sheet1");
XLSX.writeFile(workbook, "行为预警.xlsx");
}
const bqYs = (val) => {
if (val == '01') {
return '#ff0202'
} else if (val == '02') {
return '#ff8c00'
} else if (val == '03') {
return '#ffff00'
} else if (val == '04') {
return '#0000ff'
}
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () { tabHeightFn(); };
window.onresize = function () { tabHeightFn(); };
};
</script>

View File

@ -6,7 +6,12 @@
<span>{{ changetText(props.item.yjJb) }}</span>
</div>
<div>
<el-image :preview-teleported="true" style="width: 80px; height: 110px" :src="item.yjTp"
<template v-if="!item.yjTp || item.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</template>
<el-image v-else :preview-teleported="true" style="width: 80px; height: 110px" :src="item.yjTp"
:preview-src-list="[item.yjTp]" show-progress>
<template #error>
<div class="image-slot error">
@ -15,7 +20,6 @@
</div>
</template>
</el-image>
</div>
<div>
<span class="smallbtn" @click.stop="() => { }">全息档案</span>

View File

@ -2,9 +2,9 @@
<div>
<div class="titleBox">
<PageTitle title="组合预警">
<el-button>
<!-- <el-button>
<span style="vertical-align: middle">导出</span>
</el-button>
</el-button> -->
</PageTitle>
</div>
<!-- 搜索 -->
@ -134,4 +134,4 @@ const tabHeightFn = () => {
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>
</style>

View File

@ -2,9 +2,9 @@
<div>
<div class="titleBox">
<PageTitle title="身份预警">
<el-button>
<!-- <el-button>
<span style="vertical-align: middle">导出</span>
</el-button>
</el-button> -->
</PageTitle>
</div>
<!-- 搜索 -->

Some files were not shown because too many files have changed in this diff Show More