This commit is contained in:
13684185576
2025-09-22 15:38:50 +08:00
558 changed files with 186824 additions and 22633 deletions

View File

@ -56,6 +56,7 @@ const userName= getItem("USERNAME")
const time = timeValidate()
content.value=[userName,sfzh,time,"林芝哨岗系统","禁止泄露公民个人信息和警务工作秘密"]
}
</script>
<style lang="scss">
@import "./styles/index.scss";

25
src/api/yj.js Normal file
View File

@ -0,0 +1,25 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
// 预警轨迹
export const tbYjxxGsgj = (data) => {
return request({
url: api + `/tbYjxx/gsgj`,
method: "POST",
data
})
}
export const tbYjxxGetPageList = (data) => {
return request({
url: api + `/tbYjxx/getPageList`,
method: "post",
data
})
}
export const tbYjxxQueryYjxx = (params) => {
return request({
url: api + `/tbYjxx/getList`,
method: "get",
params
})
}

View File

@ -1,6 +1,5 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-gsxt";
// 群体性质新增
export const tbGsxtZdrySelectVoById = (params) => {
return request({
url: api + `/tbGsxtZdry/getZyryById`,
@ -16,7 +15,14 @@ export const tbGsxtZdryUpdate = (data) => {
data,
});
}
// 重点人员新增
export const tbGsxtZdrySave = (data) => {
return request({
url: api + `/tbGsxtZdry/save `,
method: "post",
data,
});
}
// 重点人员车辆信息-(新增)
export const tbZdryClxxAdd = (data) => {
return request({
@ -68,14 +74,20 @@ export const tbGsxtZdryLxrselectLxrBy = (params) => {
});
}
// 密切联系人新增或者修改接口
export const tbGsxtZdryLxrsaveOrUpdateLxr = (params) => {
export const tbGsxtZdryLxrsaveOrUpdateLxr = (data) => {
return request({
url: api + `/tbGsxtZdryLxr/saveOrUpdateLxr`,
method: "post",
params,
data,
});
}
// 密切联系人新增或者修改接口
export const tbGsxtZdryLxr = (id) => {
return request({
url: api + `/tbGsxtZdryLxr/${id}`,
method: "delete",
});
}
// 走访记录查询接口
export const tbGsxtZdryZfjlselectZfjl = (params) => {
return request({
@ -84,6 +96,21 @@ export const tbGsxtZdryZfjlselectZfjl = (params) => {
params,
});
}
// 新增或修改走访记录信息
export const tbGsxtZdryZfjlsaveOrUpdateZfjl = (data) => {
return request({
url: api + `/tbGsxtZdryZfjl/saveOrUpdateZfjl`,
method: "post",
data,
});
}
export const tbGsxtZdryZfjl = (id) => {
return request({
url: api + `/tbGsxtZdryZfjl/${id}`,
method: "delete",
});
}
// 案件信息查询接口
export const tbGsxtZdryAjxxselectAjxx = (params) => {
return request({
@ -92,3 +119,57 @@ export const tbGsxtZdryAjxxselectAjxx = (params) => {
params,
});
}
// 新增或修改案件信息
export const tbGsxtZdryAjxxSaveOrUpdateAjxx = (data) => {
return request({
url: api + `/tbGsxtZdryAjxx/saveOrUpdateAjxx`,
method: "post",
data,
});
}
export const tbGsxtZdryAjxx = (id) => {
return request({
url: api + `/tbGsxtZdryAjxx/${id} `,
method: "delete",
});
}
// 新增或修改现实表现
export const tbGsxtZdryXsbxSaveOrUpdateXsbx = (data) => {
return request({
url: api + `/tbGsxtZdryXsbx/saveOrUpdateXsbx`,
method: "post",
data,
});
}
// 查询走访记录信息
export const tbGsxtZdryXsbxSelectZfjl = (params) => {
return request({
url: api + `/tbGsxtZdryXsbx/selectXsbx`,
method: "get",
params,
});
}
// 删除走访记录信息
export const tbGsxtZdryXsbx = (id) => {
return request({
url: api + `/tbGsxtZdryXsbx/${id}`,
method: "delete",
});
}
// 查询操作日志
export const tbGsxtZdryCzrzSelectCzrz = (params) => {
return request({
url: api + `/tbGsxtZdryCzrz/selectCzrz`,
method: "get",
params,
});
}
// 不分页查询
export const tbGsxtZdrySelectList = (params) => {
return request({
url: api + `/tbGsxtZdry/selectList`,
method: "get",
params,
});
}

View File

@ -63,7 +63,6 @@
height: 70px;
background: rgba(0, 0, 0, 0.8);
z-index: 2;
.headBoxBg {
width: 100%;
height: 100%;

View File

@ -242,7 +242,7 @@ function multipleUser() {
multipleUserRef.value.toggleRowSelection(item, false);
});
}
// 根据 roleIds 进行回显
tableData.value.forEach((item) => {
if (props.roleIds.some((id) => id == item.id)) {

View File

@ -1,7 +1,8 @@
<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-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">
@ -30,8 +31,7 @@
</el-carousel> -->
<!-- 地图缩放 -->
<div class="zoomTargetBox">
<el-input-number :min="7" :max="18" v-model="zoomTarget" :step="1" step-strictly @change="handleZoom">
</el-input-number>
<el-input-number :min="7" :max="18" v-model="zoomTarget" :step="1" step-strictly @change="handleZoom"></el-input-number>
</div>
</div>
</template>
@ -74,13 +74,11 @@ const props = defineProps({
});
try {
const userInfo = getItem("deptId")[0].deptCode;
} catch (error) {}
} catch (error) { }
let map;
let mapLayer;
let mapLayer1;
onMounted(() => {
console.log("xxxxxxx");
emitter.on("followUp", (res) => {
let box = document.getElementsByClassName("changeMap_box");
if (!box) return;
@ -88,34 +86,6 @@ onMounted(() => {
box[0].style.transition = "0.5s";
});
map = new EliMap({
id: props.mapid,
crs: "EPSG:3857",
style: {
glyphs: "./fonts/{fontstack}/{range}.pbf",
center: [94.36,29.65],
zoom: 10
},
transformRequest: (url) => {
if (url.indexOf("TileMatrix=") != -1) {
const arr = url.split("TileMatrix=");
const arr1 = arr[1].split("&");
const nurl = `${arr[0]}&TileMatrix=${Number(arr1[0])}&${arr1[1]}&${arr1[2]}`;
}
}
});
// window.map = 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}',
// })
// zoomTarget.value = map.mapboxGLMap.getZoom();
// // 地图加载完成后发出事件
// emit('mapLoaded')
// });
// mapUtil.value = new MapUtil(map);
map = new EliMap({
id: props.mapid,
crs: "EPSG:4490",
@ -148,6 +118,7 @@ onMounted(() => {
zoomTarget.value = map.mapboxGLMap.getZoom();
});
mapUtil.value = new MapUtil(map);
mapUtil.value.Drawplot(); //初始化加载绘制工具
// 设置地图中心点及图层
@ -288,7 +259,6 @@ const mapSetLayer = (id, source) => {
//获取地图绘制的数据
const resFun = (coord, type, flag, data) => {
emitter.emit("coordString", {
coord: coord,
type: type,
@ -353,29 +323,35 @@ onUnmounted(() => {
right: 398px;
bottom: 4px;
z-index: 9;
.mapImageItem {
border: 1px solid #08aae8;
background: rgb(9, 26, 70);
& > img {
&>img {
width: 100%;
height: 50px;
}
& > div {
&>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;
}

View File

@ -1,359 +0,0 @@
<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: 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) => {
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

@ -9,7 +9,7 @@ export function MapUtil(map) {
_that.idsBox = {} //存放id的容器需要某个标记单个删除的时候存储
_that.isCheck = false
/**
* 设置地图中心点以
* 设置地图中心点以
* @param {*} location 中心坐标 [jd,wd]
* @param {*} zoomLevel 层级 10
*/
@ -141,10 +141,10 @@ export function MapUtil(map) {
}
// 信息框展示
MapUtil.prototype.makerShowTitle = (item,points,flag,text) =>{
let T = flag == 'rx' ? 'rxTitle' :'Title'
let flagT = flag+T;
if(!_that._self[flagT]) _that._self[flagT] = [];
MapUtil.prototype.makerShowTitle = (item, points, flag, text) => {
let T = flag == 'rx' ? 'rxTitle' : 'Title'
let flagT = flag + T;
if (!_that._self[flagT]) _that._self[flagT] = [];
// 展示名字
let textTitle = item.jzMc ? item.jzMc : item.fzrXm + '警组';
@ -242,7 +242,7 @@ export function MapUtil(map) {
}
/**
* 聚合撒点
* 聚合撒点
* @param {*} coords 点位数据 geojson lng lat
* @param {*} icon 点位图
*/
@ -287,9 +287,9 @@ export function MapUtil(map) {
* @param {*} coords 数组
*/
MapUtil.prototype.showHeatDrawing = (res) => {
let { coords, flag,isclear ,color} = res;
if(!_that._self[flag]) _that._self[flag] = [];
if(isclear) _that.removeElement(flag) //清除热力
let { coords, flag, isclear, color } = res;
if (!_that._self[flag]) _that._self[flag] = [];
if (isclear) _that.removeElement(flag) //清除热力
let data = {
type: 'FeatureCollection',
features: []
@ -315,12 +315,12 @@ export function MapUtil(map) {
// 清除所有
MapUtil.prototype.removeAll = () => {
for(let key in _that._self){
if(key != 'rx' && key !='gpsZb' && !key.includes('rxTitle')){
for (let key in _that._self) {
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];
if(el && typeof el == 'object') el.destroy() //destory()销毁 , show(false) false:隐藏 true :展示
if (el && typeof el == 'object') el.destroy() //destory()销毁 , show(false) false:隐藏 true :展示
}
_that._self[key] = [];
}
@ -342,7 +342,7 @@ export function MapUtil(map) {
}
}
}
if(layer == 'rx') _that.idsBox[layer] = [];
if (layer == 'rx') _that.idsBox[layer] = [];
// 其他图层
if (!_that._self[layer]) return false;
@ -354,8 +354,8 @@ export function MapUtil(map) {
_that._self[layer] = [];
// d带标题的撒点
let T = layer == 'rx' ? 'rxTitle' :'Title'
let flagT = layer+T;
let T = layer == 'rx' ? 'rxTitle' : 'Title'
let flagT = layer + T;
if (!_that._self[flagT]) return false;
for (let i = 0; i < _that._self[flagT].length; i++) {
const el = _that._self[flagT][i];
@ -376,9 +376,9 @@ export function MapUtil(map) {
_that.idsBox[layer].splice(index, 1);
if (_that._self[layer][index]) _that._self[layer][index].destroy()
_that._self[layer].splice(index, 1)
if(layer == 'rx'){
let flagT = layer +'rxTitle';
if(_that._self[flagT][index]) _that._self[flagT][index].destroy()
if (layer == 'rx') {
let flagT = layer + 'rxTitle';
if (_that._self[flagT][index]) _that._self[flagT][index].destroy()
_that._self[flagT].splice(index, 1)
_that.removeGpsZbOverlayById(id) //删除图标
}
@ -417,12 +417,12 @@ export function MapUtil(map) {
* (point 点, line 线, circle 圆, polygon 多边形, rectangle 矩形) ,
* geoJson:根据geojson回显图
*/
MapUtil.prototype.plot = (res,resFun) => {
let {flag ,color,linecolor, type ,coords} = res
if(!_that._self[flag]) _that._self[flag] = [];
if(res.isclear) _that.removePlot(flag); //移除绘制工具
if(res.isclear && (res.type == 'polygon' || res.type == 'line')) _that.removeEara(flag); //移除回显的面和线条
switch(type){
MapUtil.prototype.plot = (res, resFun) => {
let { flag, color, linecolor, type, coords } = res
if (!_that._self[flag]) _that._self[flag] = [];
if (res.isclear) _that.removePlot(flag); //移除绘制工具
if (res.isclear && (res.type == 'polygon' || res.type == 'line')) _that.removeEara(flag); //移除回显的面和线条
switch (type) {
case 'point':
_that._CustomDraw.point((val) => { _that.handlePlot(val, type, flag, resFun) })
break;
@ -486,7 +486,7 @@ export function MapUtil(map) {
})
}
/**
* 移除绘制面
* 移除绘制面
* @param {*} flag 唯一标识
*/
MapUtil.prototype.removeEara = (flag) => {
@ -499,11 +499,11 @@ export function MapUtil(map) {
* (solid 实线, dash 虚线, FlowColor 彩虹线, RoadLine 流线
*/
MapUtil.prototype.createLine = (res) => {
let { type , coords , isclear ,flag ,color,width } = res;
if(!coords) return false; // coords 是数组对象,可以同时撒多条数据
if(!_that._self[flag]) _that._self[flag] = [] ;
if(isclear) _that.removeElement(flag); //移除回显的线条
let data = coords.map((item,index)=>{
let { type, coords, isclear, flag, color, width } = res;
if (!coords) return false; // coords 是数组对象,可以同时撒多条数据
if (!_that._self[flag]) _that._self[flag] = [];
if (isclear) _that.removeElement(flag); //移除回显的线条
let data = coords.map((item, index) => {
return {
position: item.coords[0], //二维数组
text: '',
@ -670,22 +670,22 @@ export function MapUtil(map) {
}
/**geojson 创建边界
* let data = {
* type: "FeatureCollection",
* features: [
* {
geometry: {
type: "Polygon",
coordinates: [it.coordinates]
},
properties: {
},
type: "Feature",
}
* ]
};
*/
/**geojson 创建边界
* let data = {
* type: "FeatureCollection",
* features: [
* {
geometry: {
type: "Polygon",
coordinates: [it.coordinates]
},
properties: {
},
type: "Feature",
}
* ]
};
*/
MapUtil.prototype.createBoundarys = (res) => {
let { data } = res
if (!data) return false;
@ -713,8 +713,13 @@ export function MapUtil(map) {
MapUtil.prototype.openInfoDetail = (flag, data) => {
switch (flag) {
case 'home_yj_map':
console.log(data);
emitter.emit("showHomeYJ", data);
break;
case 'home_yj_detail':
console.log(data);
emitter.emit("showHomeWarning", data);
break;
}
}
}

View File

@ -4,7 +4,7 @@
<el-form-item v-for="(item, idx) in props.formList" :style="item.width && { width: item.width }" :prop="item.prop" :label="item.label" :label-width="item.labelWidth" :key="idx">
<!-- input表单 input-->
<MOSTY.Other v-if="item.type == 'input'" width="100%" clearable v-model="listQuery[item.prop]" :placeholder="`请输入${item.label}`" :disabled="item.disabled" :readonly="item.readonly" />
<el-input v-model="listQuery[item.prop]" v-else-if="item.type == 'textarea'" type="textarea" :rows="3" :placeholder="`请输入${item.label}`" :disabled="item.disabled" />
<!-- 数值 inputNumber-->
<el-input type="number" v-model="listQuery[item.prop]" v-else-if="item.type == 'inputNumber'" :placeholder="`请输入${item.label}`" :disabled="item.disabled" />

View File

@ -7,8 +7,9 @@
:load="load" :tree-props="treePros" style="width: 100%" :header-cell-class-name="() => 'HeadBgColor'"
: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 === 'radio' ? 'tabBoxRadio' : ''" />
<el-table-column style="width: 55px" type="selection" width="55" v-if="getConfiger.showSelectType" :class="getConfiger.showSelectType === 'radio' ? 'tabBoxRadio' : ''" />
<el-table-column type="index" label="序号" v-if="getConfiger.showIndex" width="60" :align="getConfiger?.align" />
<el-table-column v-for="(item, index) in tableColumn" :align="getConfiger?.align" :prop="item.prop" :key="index"

View File

@ -6,7 +6,6 @@
<!---循环渲染--->
<SideBarItem v-for="item in route.children" :key="item.path" :route="item"></SideBarItem>
</el-sub-menu>
<el-menu-item v-else :index="route.path">
<MenuItem :title="route.meta.title" :icon="route.meta.icon"></MenuItem>
</el-menu-item>

View File

@ -59,7 +59,7 @@ const activeMenu = computed(() => {
background-image: linear-gradient(to right,#2356d4 0% ,#8efbde 100%);
margin: 0 14px;
border-radius: 4px;
padding-left: 26px !important;
// padding-left: 46px !important;
}
::v-deep .el-sub-menu .el-menu-item {
height: 48px;

View File

@ -3,7 +3,6 @@
<div class="meunAside noScollLine">
<div style="height:100px"></div>
<div style="height: calc(100% - 100px);"><SideBarMenu></SideBarMenu></div>
</div>
</el-scrollbar>
</template>

View File

@ -36,8 +36,7 @@ export const publicRoutes = [
{
path: "/user/department-ist",
name: "departmentList",
component: () =>
import("@/views/backOfficeSystem/systemConfig/department-list/index"),
component: () => import("@/views/backOfficeSystem/systemConfig/department-list/index"),
meta: {
title: "部门管理",
icon: "article-ranking"
@ -172,14 +171,59 @@ export const publicRoutes = [
},
{
path: "/editPassword", // 注意:带有路径“/”的记录中的组件“默认”是一个不返回 Promise 的函数
component: layout,
redirect: "/IdentityManage",
component: layout,
children: [
{
{
path: "/FourColorWarning",
name: "FourColorWarning",
meta: { title: "四色预警管理", icon: "article" },
children: [
{
path: "/warningControl",
name: "warningControl",
meta: { title: "预警中心", icon: "article" },
redirect: "/warningControl/centerHome",
children: [
{
path: "/centerHome",
name: "centerHome",
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/index"),
meta: { title: "预警中心大屏", icon: "article" },
},
{
path: "/warningBk",
name: "warningBk",
meta: { title: "布控预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/warningBk/index"),
},
{
path: "/behaviorWarning",
name: "behaviorWarning",
meta: { title: "行为预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/behaviorWarning/index"),
},
{
path: "/identityWarning",
name: "identityWarning",
meta: { title: "身份预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/identityWarning/index"),
},
{
path: "/combinedWarning",
name: "combinedWarning",
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: "/IdentityManage",
name: "IdentityManage",
@ -217,37 +261,25 @@ export const publicRoutes = [
}
},
{
path: "/warningControl",
name: "warningControl",
component: () => import("@/views/backOfficeSystem/IntelligentControl/warningControl/index"),
path: "/warningList",
name: "warningList",
component: () => import("@/views/backOfficeSystem/fourColorManage/warningList/index"),
meta: {
title: "预警中心",
icon: "article"
}
},
{
path: "/WarningModel",
name: "WarningModel",
component: () =>
import(
"@/views/backOfficeSystem/ExcavationResearch/WarningModel/index"
),
meta: {
title: "重点人员预警模型",
icon: "article"
}
}, {
path: "/policeReport",
name: "policeReport",
component: () =>
import(
"@/views/backOfficeSystem/policeReport/index.vue"
),
meta: {
title: "警情管理",
title: "布控预警列表",
icon: "article"
}
},
// 暂时取消
// {
// path: "/WarningModel",
// name: "WarningModel",
// component: () =>import("@/views/backOfficeSystem/ExcavationResearch/WarningModel/index"),
// meta: {
// title: "重点人员预警模型",
// icon: "article"
// }
// },
]
},
{
@ -308,15 +340,24 @@ export const publicRoutes = [
}
},
{
path: "/MoralAnalysis",
name: "MoralAnalysis",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/MoralAnalysis/index"),
path: "/ssemanticAnalysis",
name: "semanticAnalysis",
component: () => import( "@/views/backOfficeSystem/SemanticAnalysis/index.vue"),
meta: {
title: "情报语义分析",
title: "语义分析",
icon: "article"
}
},
// 暂时不要
// {
// path: "/MoralAnalysis",
// name: "MoralAnalysis",
// component: () => import("@/views/backOfficeSystem/ResearchJudgment/MoralAnalysis/index"),
// meta: {
// title: "情报语义分析",
// icon: "article"
// }
// },
{
path: "/IntelligenceManagement",
name: "IntelligenceManagement",
@ -440,8 +481,17 @@ export const publicRoutes = [
{
path: "/ExcavationResearch",
name: "ExcavationResearch",
meta: { title: "重点人发掘研判", icon: "article" },
meta: { title: "重点人发掘系统", icon: "article" },
children: [
{
path: "/tsypHome",
name: "tsypHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/tsypHome/index"),
meta: {
title: "重点人员模型管理",
icon: "article"
}
},
{
path: "/PreliminaryExcavations",
name: "PreliminaryExcavations",
@ -494,25 +544,17 @@ export const publicRoutes = [
name: "ResearchHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/ResearchHome/index"),
meta: {
title: "专题研判",
icon: "article"
}
},
{
path: "/tsypHome",
name: "tsypHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/tsypHome/index"),
meta: {
title: "模型管理",
title: "战术研判",
icon: "article"
}
},
{
path: "/situationHome",
name: "situationHome",
component: () => import("@/views/backOfficeSystem/JudgmentHome/situationHome/index"),
meta: {
title: "研判态势",
title: "战略研判",
icon: "article"
}
},
@ -609,7 +651,7 @@ export const publicRoutes = [
icon: "article"
},
children: [
// {
// path: "/surveillanceControl",
// name: "surveillanceControl",
@ -626,22 +668,19 @@ export const publicRoutes = [
path: "/experienceShare",
name: "experienceShare",
component: () =>
import(
"@/views/backOfficeSystem/BasicManagement/experienceShare/index"
),
import("@/views/backOfficeSystem/BasicManagement/experienceShare/index"),
meta: {
title: "经验分享",
icon: "article"
}
}, {
path: "/ssemanticAnalysis",
name: "semanticAnalysis",
component: () =>
import(
"@/views/backOfficeSystem/SemanticAnalysis/index.vue"
),
},
{
path: "/policeReport",
name: "policeReport",
component: () =>import("@/views/backOfficeSystem/policeReport/index.vue"),
meta: {
title: "语义分析",
title: "警情管理",
icon: "article"
}
},

View File

@ -35,9 +35,7 @@ const rules = reactive({
{ required: true, message: "请输入经验内容", trigger: "blur" }
]
});
const formData = ref([
]);
const formData = ref([]);
const listQuery = ref({}); //表单
const loading = ref(false);
const elform = ref();

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="headClass" style="">
<h3>管控信息</h3>
<h3>{{title}}管控信息</h3>
<el-button type="primary" :disabled="disabled" @click="chooseMarksVisible = true">选择</el-button>
</div>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
@ -37,6 +37,10 @@ const props = defineProps({
type: Boolean,
default: false
},
title: {
type: String,
default: "群体"
}
})
const { D_BZ_RYJZLB } = proxy.$dict('D_BZ_RYJZLB')
const pageData = reactive({
@ -75,7 +79,6 @@ const pageData = reactive({
})
onMounted(() => {
console.log('ControlInfo 组件已挂载!')
})
const listData = ref({})
watch(() => props.dataList, (val) => {

View File

@ -0,0 +1,70 @@
<template>
<!-- 添加 -->
<el-dialog v-model="modelValue" :title="title" width="40%" :before-close="handleClose">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform" :rules="rules">
</FormMessage>
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="submitForm">确认</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { defineProps, defineEmits, ref, watch, reactive, getCurrentInstance } from 'vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
const { proxy } = getCurrentInstance();
const props = defineProps({
data: {
type: Object,
default: () => { }
},
modelValue: {
type: Boolean,
default: false
},
title: {
type: String,
default: '走访信息'
},
dict: {
type: Object,
default: () => { }
}
})
const emit = defineEmits(['update:modelValue', 'comfirm'])
const listQuery = ref({})
const formData = ref([
{ label: "案件名称", prop: "ajmc", type: "input", width: '100%' },
{ label: "案件时间", prop: "sasj", type: "date", width: '100%' },
{ label: "案件编码", prop: "ajbm", type: "input", width: '100%' },
])
const rules = reactive({
ajmc: [{ required: true, message: "请输入案件名称", trigger: "blur" }],
sasj: [{ required: true, message: "请输入案件时间", trigger: "change" }],
ajbm: [{ required: true, message: "请输入案件编码", trigger: "blur" }],
})
const elform=ref(null)
const submitForm = () => {
elform.value.submit((val) => {
if (val) {
emit('comfirm', val)
handleClose()
}
})
}
watch(
() => props.data,
(val) => {
listQuery.value = val ? { ...val } : {}
},
{ deep: true }
)
// 取消:关闭弹窗
const handleClose = () => {
listQuery.value = {}
emit('update:modelValue', false)
}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,86 @@
<template>
<!-- 添加 -->
<el-dialog v-model="modelValue" :title="title" width="40%" :before-close="handleClose">
<el-form ref="historyForm" style="max-width: 600px" :model="diaLogRuleForm" :rules="rules">
<el-form-item label-width="160px" label="姓名" prop="ryXm" style="width: 100%;">
<el-input v-model="diaLogRuleForm.ryXm" :placeholder="`请输入联系人姓名`" />
</el-form-item>
<el-form-item label-width="160px" label="人员身份证号" prop="rySfzh" style="width: 100%;">
<el-input v-model="diaLogRuleForm.rySfzh" :placeholder="`请输入人员身份证号`" />
</el-form-item>
<el-form-item label-width="160px" label="对应关系" prop="dygx" style="width: 100%;">
<el-select v-model="diaLogRuleForm.dygx" placeholder="请选择对应关系">
<el-option v-for="item in dict.D_BZ_QSGXDM" :key="item.dm" :label="item.zdmc" :value="item.dm" />
</el-select>
</el-form-item>
<el-form-item label-width="160px" label="联系人电话" prop="lxrDh" style="width: 100%;">
<el-input v-model="diaLogRuleForm.lxrDh" :placeholder="`请输入联系人电话`" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="onSubmit">
确认
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { defineProps, defineEmits, ref, watch, reactive } from 'vue'
import { generateRandom10Digits } from '@/utils/tools'
const props = defineProps({
data: {
type: Object,
default: () => { }
},
modelValue: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
dict: {
type: Object,
default: () => { }
}
})
const historyForm = ref(null)
const emit = defineEmits(['update:modelValue', 'submit'])
const diaLogRuleForm = ref({})
const rules = reactive({
ryXm: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
rySfzh: [{ required: true, message: '请输入身份证号', trigger: 'blur' }],
dygx: [{ required: true, message: '请选择对应关系', trigger: 'change' }],
})
watch(
() => props.data,
(val) => {
diaLogRuleForm.value = val ? { ...val } : {}
},
{ deep: true }
)
// 取消:关闭弹窗
const handleClose = () => {
diaLogRuleForm.value = {}
emit('update:modelValue', false)
}
// 提交
const onSubmit = () => {
historyForm.value.validate().then((valid) => {
if (valid) {
emit('submit', { ...diaLogRuleForm.value }) // 提交数据
handleClose()
}
}).catch((err) => {
console.log(err);
});
}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,91 @@
<template>
<!-- 添加 -->
<el-dialog v-model="modelValue" :title="title" width="40%" :before-close="handleClose">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform" :rules="rules">
<template #zfmjXm>
<el-input v-model="listQuery.zfmjXm" :placeholder="`请输入民警姓名`" readonly @click="changeShow" />
</template>
</FormMessage>
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="submitForm">确认</el-button>
</template>
</el-dialog>
<ChooseUser :Single="true" v-model="chooseMarksVisible" @choosedUsers="addMarks" :roleIds="roleIds" />
</template>
<script setup>
import { defineProps, defineEmits, ref, watch, reactive, getCurrentInstance } from 'vue'
import { generateRandom10Digits } from '@/utils/tools'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue";
const { proxy } = getCurrentInstance();
const { D_ZFNR_MBLX } = proxy.$dict("D_ZFNR_MBLX")
const props = defineProps({
data: {
type: Object,
default: () => { }
},
modelValue: {
type: Boolean,
default: false
},
title: {
type: String,
default: '走访信息'
},
dict: {
type: Object,
default: () => { }
}
})
const emit = defineEmits(['update:modelValue', 'comfirm'])
const historyForm = ref(null)
const chooseMarksVisible = ref(false)
const listQuery = ref({})
const formData = ref([
{ label: "民警姓名", prop: "zfmjXm", type: "slot", width: '100%' },
{ label: "走访时间", prop: "zfsj", type: "date", width: '100%' },
{ label: "走访地址", prop: "zfdz", type: "input", width: '100%' },
{ label: "走访方式", prop: "zffs", type: "input", width: '100%' },
{ label: "走访情况", prop: "zfqk", type: "textarea", width: '100%' },
])
const rules = reactive({
zfmjXm: [{ required: true, message: "请选择民警姓名", trigger: "blur" }],
zfsj: [{ required: true, message: "请输入走访时间", trigger: "change" }],
zfdz: [{ required: true, message: "请输入走访地址", trigger: "blur" }],
zffs: [{ required: true, message: "请输入走访方式", trigger: "blur" }],
zfqk: [{ required: true, message: "请输入走访情况", trigger: "blur" }],
})
const changeShow = () => {
chooseMarksVisible.value = true
}
const addMarks = (val) => {
listQuery.value.zfmjXm = val[0].userName
listQuery.value.zfmjSfzh=val[0].idEntityCard
}
const elform=ref(null)
const submitForm = () => {
elform.value.submit((val) => {
if (val) {
emit('comfirm', val)
handleClose()
}
})
}
watch(
() => props.data,
(val) => {
console.log(val);
listQuery.value = val ? { ...val } : {}
},
{ deep: true }
)
// 取消:关闭弹窗
const handleClose = () => {
listQuery.value = {}
emit('update:modelValue', false)
}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,306 @@
<template>
<el-dialog :title="titleValue" width="800px" :model-value="modelValue" append-to-body @close="closed">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform" :rules="rules">
<template #rrry>
<el-input v-model="listQuery.rrry" :placeholder="`请输入民警姓名`" readonly @click="changeShow" />
</template>
<template #fjxx>
<!-- 文件列表区域 -->
<div class="file-attachment-section">
<div class="section-title">相关附件</div>
<div class="file-list-container">
<div v-if="listQuery.fileList.length === 0" class="empty-file-list">暂无附件</div>
<div v-else class="file-list">
<div v-for="(file, index) in listQuery.fileList" :key="index" class="file-item">
<div class="file-info">
<span class="file-name">{{ file.originalName }}</span>
<span class="file-time">{{ file.uploadTime }}</span>
</div>
<div class="file-actions">
<el-button type="text" size="small" @click="downloadFile(file)" title="下载文件" :disabled="disabled">
<el-icon>
<Download />
</el-icon>
</el-button>
<el-button type="text" size="small" @click="deleteFile(index)" title="删除文件" class="delete-btn"
:disabled="disabled">
<el-icon>
<Delete />
</el-icon>
</el-button>
</div>
</div>
</div>
</div>
<!-- 上传按钮区域 -->
<div class="upload-btn-container">
<el-upload v-model:file-list="listQuery.fileList" class="upload-demo" :show-file-list="false" multiple
:http-request="handleUploadRequest" :on-remove="handleRemove" :limit="3" :on-exceed="handleExceed">
<el-button type="primary" :disabled="disabled">上传文件</el-button>
</el-upload>
</div>
</div>
</template>
</FormMessage>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
<ChooseUser :Single="true" v-model="chooseMarksVisible" @choosedUsers="addMarks" :roleIds="roleIds" />
</template>
<script setup>
import { ref, onMounted, reactive, watch, getCurrentInstance } from "vue";
import { generateRandom10Digits } from '@/utils/tools'
import { uploadMultipleFiles } from '@/views/backOfficeSystem/DeploymentDisposal/mpvGroup/model/fileUp.js'
import { ElMessage } from 'element-plus';
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue";
const { proxy } = getCurrentInstance()
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
titleValue: {
type: String,
default: "研判记录"
},
data: {
type: Object,
default: () => { }
}
});
const emits = defineEmits(["update:modelValue", "comfirm"]);
const formData = ref([
{ label: "录入人员", prop: "rrry", type: "slot", width: '100%' },
{ label: "录入时间", prop: "lrsj", type: "date", width: '100%' },
{ label: "表现内容", prop: "bxnr", type: "textarea", width: '100%' },
{ label: "附件信息", prop: "fjxx", type: "slot", width: '100%' },
])
const rules = reactive({
rrry: [{ required: true, message: "请选择民警姓名", trigger: "blur" }],
lrsj: [{ required: true, message: "请输入录入时间", trigger: "change" }],
bxnr: [{ required: true, message: "请输入表现内容", trigger: "blur" }],
})
const listQuery = ref({fileList:[]})
const roleIds=ref([])
const chooseMarksVisible=ref(false)
const changeShow = () => {
chooseMarksVisible.value = true
}
const addMarks = (val) => {
listQuery.value.rrry = val[0].userName
roleIds.value = val.map(item => item.id)
}
const closed = () => {
listQuery.value={}
listQuery.value.fileList = []
emits("update:modelValue", false);
};
const onComfirm = () => {
emits("comfirm", {...listQuery.value,fjxx:listQuery.value.fileList.length>0?JSON.stringify(listQuery.value.fileList):null });
emits("update:modelValue", false);
}
watch(() => props.data, (val) => {
if (val) {
listQuery.value={...val,fileList:val.fjxx}
}
},{deep: true})
// 下载文件
const downloadFile = (file) => {
// 实际项目中这里应该调用下载API
console.log('下载文件:', file.name)
// 示例window.open(file.url)
}
// 删除文件
const deleteFile = (index) => {
// 实际项目中这里应该先调用删除API成功后再从列表中移除
listQuery.value.fileList.splice(index, 1)
ElMessage.success('文件已删除')
}
// 上传相关方法
const handleUploadRequest = async (options) => {
try {
// 调用uploadMultipleFiles进行文件上传
const result = await uploadMultipleFiles(options.file, {
uploadedFiles: listQuery.value.fileList,
fjIds: [], // 如果需要保存文件ID列表可以在这里传递
compressImage: null // 可选的图片压缩函数
});
// 更新文件列表,添加上传时间信息
const index = listQuery.value.fileList.findIndex(f => f.originalName === options.file.name);
if (index !== -1) {
listQuery.value.fileList[index].uploadTime = new Date().toLocaleString('zh-CN');
}
// 调用成功回调
if (options.onSuccess) {
options.onSuccess(result);
}
} catch (error) {
console.error('文件上传失败:', error);
// 调用失败回调
if (options.onError) {
options.onError(error);
}
}
}
const handleRemove = (uploadFile, uploadFiles) => {
// 实际项目中这里应该先调用删除API成功后再从列表中移除
const index = listQuery.value.fileList.findIndex(f => f.name === uploadFile.name);
if (index !== -1) {
listQuery.value.fileList.splice(index, 1);
}
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
</style>
<style>
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
.file-attachment-section {
margin-top: 15px;
width: 100%;
}
.section-title {
font-size: 14px;
font-weight: 500;
color: #303133;
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px solid #ebeef5;
}
.file-list-container {
max-height: 100px;
overflow-y: auto;
border: 1px solid #ebeef5;
border-radius: 4px;
background-color: #ffffff;
margin-bottom: 10px;
}
/* 自定义滚动条样式 */
.file-list-container::-webkit-scrollbar {
width: 6px;
}
.file-list-container::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.file-list-container::-webkit-scrollbar-thumb {
background: #c0c4cc;
border-radius: 3px;
}
.file-list-container::-webkit-scrollbar-thumb:hover {
background: #909399;
}
.empty-file-list {
padding: 20px;
text-align: center;
color: #909399;
font-size: 12px;
}
.file-list {
padding: 5px;
}
.file-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 10px;
margin-bottom: 2px;
background-color: #f8f9fa;
border-radius: 4px;
transition: all 0.3s ease;
cursor: pointer;
}
.file-item:hover {
background-color: #e6f7ff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.file-info {
flex: 1;
display: flex;
align-items: center;
gap: 15px;
min-width: 0;
}
.file-name {
flex: 1;
font-size: 12px;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.file-size {
font-size: 11px;
color: #909399;
min-width: 60px;
}
.file-time {
font-size: 11px;
color: #909399;
}
.file-actions {
display: flex;
align-items: center;
gap: 5px;
margin-left: 10px;
}
.file-actions .el-button {
padding: 0 5px;
margin: 0;
color: #606266;
transition: color 0.3s ease;
}
.file-actions .el-button:hover {
color: #409eff;
}
.delete-btn:hover {
color: #f56c6c !important;
}
.upload-btn-container {
display: flex;
justify-content: center;
margin-top: 10px;
}
</style>

View File

@ -8,25 +8,28 @@
<el-input v-model="ruleForm.clsbm" placeholder="请输入车辆识别码" />
</el-form-item>
<el-form-item label="车辆型号" prop="cllx">
<el-select v-model="ruleForm.cllx" placeholder="请选择车辆型号">
<el-option :label="item.zdmc" :value="item.dm" v-for="(item,index) in dict.D_BZ_CLLX" :key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="车辆颜色" prop="clys">
<el-select v-model="ruleForm.clys" placeholder="请选择车辆颜色">
<el-option :label="item.zdmc" :value="item.dm" v-for="(item,index) in dict.D_BZ_CLYS" :key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="车辆品牌" prop="clpp">
<el-select v-model="ruleForm.clpp" placeholder="请选择车辆品牌">
<el-option :label="item.zdmc" :value="item.dm" v-for="(item,index) in dict.D_BZ_CLPP" :key="index"></el-option>
</el-select>
</el-form-item>
<el-select v-model="ruleForm.cllx" placeholder="请选择车辆型号">
<el-option :label="item.zdmc" :value="item.dm" v-for="(item, index) in dict.D_BZ_CLLX"
:key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="车辆颜色" prop="clys">
<el-select v-model="ruleForm.clys" placeholder="请选择车辆颜色">
<el-option :label="item.zdmc" :value="item.dm" v-for="(item, index) in dict.D_BZ_CLYS"
:key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="车辆品牌" prop="clpp">
<el-select v-model="ruleForm.clpp" placeholder="请选择车辆品牌">
<el-option :label="item.zdmc" :value="item.dm" v-for="(item, index) in dict.D_BZ_CLPP"
:key="index"></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
<el-button type="primary" @click="onComfirm()">确认</el-button>
</div>
</template>
</el-dialog>
@ -66,18 +69,22 @@ const rules = reactive({
});
const onComfirm = () => {
const promes = {...ruleForm.value,
id: ruleForm.value.id ? ruleForm.value.id : generateRandom10Digits(),
}
console.log(promes);
emits("comfirm", { ...promes });
closed()
historyForm.value.validate((valid, fields) => {
if (valid) {
const promes = {
...ruleForm.value,
id: ruleForm.value.id ? ruleForm.value.id : generateRandom10Digits(),
}
emits("comfirm", { ...promes });
closed()
} else {
console.log('error submit!', fields)
}
})
}
watch(() => props.modelValue, (val) => {
ruleForm.value = props.data
},{deep: true})
}, { deep: true })
const closed = () => {

View File

@ -10,30 +10,32 @@
<div class="form_cnt flex just-between">
<div class="left_box">
<ul class="anchor-list">
<li @click="scrollToSection('info-section')" :class="activeSection === 'info-section' ? 'active' : ''">基本信息
<li @click="scrollToSection('info-section')" :class="activeSection === 'info-section' ? 'active' : ''">人员信息
</li>
<li @click="scrollToSection('backinfo-section')"
:class="activeSection === 'backinfo-section' ? 'active' : ''">人员标签</li>
<li @click="scrollToSection('groupLabels-section')"
:class="activeSection === 'groupLabels-section' ? 'active' : ''">群体标签</li>
:class="activeSection === 'groupLabels-section' ? 'active' : ''" v-if="!butShow">关联车辆</li>
<li @click="scrollToSection('character-section')"
:class="activeSection === 'character-section' ? 'active' : ''">群体性质</li>
:class="activeSection === 'character-section' ? 'active' : ''">背景信息</li>
<li @click="scrollToSection('controlInfo-section')"
:class="activeSection === 'controlInfo-section' ? 'active' : ''">管控信息</li>
:class="activeSection === 'controlInfo-section' ? 'active' : ''" v-if="!butShow">管控信息</li>
<li @click="scrollToSection('featinfo-section')"
:class="activeSection === 'featinfo-section' ? 'active' : ''">群体特征</li>
:class="activeSection === 'featinfo-section' ? 'active' : ''" v-if="!butShow">全要素布控</li>
<li @click="scrollToSection('demandsInfo-section')"
:class="activeSection === 'demandsInfo-section' ? 'active' : ''">主要诉求</li>
:class="activeSection === 'demandsInfo-section' ? 'active' : ''" v-if="!butShow">密切联系人</li>
<li @click="scrollToSection('requestInfo-section')"
:class="activeSection === 'requestInfo-section' ? 'active' : ''">诉求信息</li>
:class="activeSection === 'requestInfo-section' ? 'active' : ''" v-if="!butShow">动态轨迹</li>
<li @click="scrollToSection('personnel-section')"
:class="activeSection === 'personnel-section' ? 'active' : ''">重点人员</li>
:class="activeSection === 'personnel-section' ? 'active' : ''" v-if="!butShow">行为信息</li>
<li @click="scrollToSection('judgmentRecord-section')"
:class="activeSection === 'judgmentRecord-section' ? 'active' : ''">研判记录</li>
:class="activeSection === 'judgmentRecord-section' ? 'active' : ''" v-if="!butShow">走访记录</li>
<li @click="scrollToSection('historyAssembly-section')"
:class="activeSection === 'historyAssembly-section' ? 'active' : ''">历史汇集</li>
:class="activeSection === 'historyAssembly-section' ? 'active' : ''" v-if="!butShow">案件信息</li>
<li @click="scrollToSection('joblogging-section')"
:class="activeSection === 'joblogging-section' ? 'active' : ''">工作记录</li>
:class="activeSection === 'joblogging-section' ? 'active' : ''" v-if="!butShow">显示表现</li>
<li @click="scrollToSection('joblogging-joblog')"
:class="activeSection === 'joblogging-joblog' ? 'active' : ''" v-if="!butShow">操作日志</li>
</ul>
</div>
<div class="right_box" ref="rightBox">
@ -43,97 +45,89 @@
<div id="backinfo-section">
<PersonnelTags ref="personnelTags" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="groupLabels-section">
<div id="groupLabels-section" v-if="!butShow">
<Vehicle ref="vehicle" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="character-section">
<BackInfo ref="backInfo" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="controlInfo-section">
<controlInfo ref="controlInfo" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="deployment-section">
<deployment ref="deployment" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="contact-section">
<contact ref="contact" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
<div id="controlInfo-section" v-if="!butShow">
<ControlInfo ref="controlInfo" title="重点人" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="dynamicTrajectory-section">
<dynamicTrajectory ref="dynamicTrajectory" :disabled="disabled" :showBut="showBut" />
</div>
<div class="behaviorInfo" style="">
<h3>行为信息</h3>
<!-- <el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button> -->
</div>
<div>
<div class="textContent">
基站认证信息2022-3-33&ensp;123030出现在乃宁市
</div>
<div class="textContent">
基站认证信息2022-3-33&ensp;123030出现在乃宁市
</div>
<div class="textContent">
基站认证信息2022-3-33&ensp;123030出现在乃宁市
</div>
<div class="textContent">
基站认证信息2022-3-33&ensp;123030出现在乃宁市
</div>
</div>
<div id="visitRecord-section">
<visitRecord ref="visitRecord" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="caseInfo-section">
<caseInfo ref="caseInfo" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="actualPerformance-section">
<actualPerformance ref="actualPerformance" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div class="behaviorInfo" style="">
<h3>操作日志</h3>
<!-- <el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button> -->
</div>
<!-- 滚动列表容器 -->
<div class="list-container">
<!-- 固定标题行 -->
<div class="list-header">
<span>账号名称</span>
<span>操作时间</span>
<span>操作记录</span>
</div>
<!-- 可滚动内容 -->
<div class="list-body">
<div class="list-item" v-for="i in 30" :key="i">
<span>张三</span>
<span>2020-3030-2202</span>
<span>新增操作记录</span>
</div>
</div>
<div id="featinfo-section" v-if="!butShow">
<Deployment ref="deployment" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="demandsInfo-section" v-if="!butShow">
<Contact ref="contact" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="requestInfo-section" v-if="!butShow">
<DynamicTrajectory ref="dynamicTrajectory" :disabled="disabled" :showBut="showBut" />
</div>
<div id="personnel-section" v-if="!butShow">
<BehaviorInfo ref="behaviorInfo" :disabled="disabled" :showBut="showBut" />
</div>
<div id="judgmentRecord-section" v-if="!butShow">
<VisitRecord ref="visitRecord" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="historyAssembly-section" v-if="!butShow" >
<CaseInfo ref="caseInfo" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="joblogging-section" v-if="!butShow">
<ActualPerformance ref="actualPerformance" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
<div id="joblogging-joblog" v-if="!butShow" >
<CzModel ref="czModel" :disabled="disabled" :showBut="showBut" :dataList="listQuery" />
</div>
</div>
</div>
</div>
<!-- <ChooseMarks v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" /> -->
</template>
<script setup>
import { getItem } from "@/utils/storage";
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
import { tbGsxtZdrySelectVoById } from "@/api/zdr.js";
import controlInfo from '../../mpvGroup/model/controlInfo.vue'
import { tbGsxtZdrySelectVoById, tbGsxtZdrySave } from "@/api/zdr.js";
import ControlInfo from '../../mpvGroup/model/controlInfo.vue'
import Info from "../model/info.vue";
import PersonnelTags from '../model/personnelTags.vue'
import Vehicle from '../model/vehicle.vue'
import BackInfo from '../model/bakInfo.vue'
import deployment from '../model/deployment.vue'
import contact from '../model/contact.vue'
import dynamicTrajectory from '../model/dynamicTrajectory.vue'
import visitRecord from '../model/visitRecord.vue'
import caseInfo from '../model/caseInfo.vue'
import actualPerformance from '../model/actualPerformance.vue'
import Deployment from '../model/deployment.vue'
import Contact from '../model/contact.vue'
import DynamicTrajectory from '../model/dynamicTrajectory.vue'
import BehaviorInfo from '../model/behaviorInfo.vue'
import VisitRecord from '../model/visitRecord.vue'
import CaseInfo from '../model/caseInfo.vue'
import ActualPerformance from '../model/actualPerformance.vue'
import CzModel from '../model/czModel.vue'
import { ref, onUnmounted } from "vue";
const emit = defineEmits(["updateDate"]);
const chooseMarksVisible = ref(false);
@ -144,6 +138,7 @@ const showBut = ref(false)
const listQuery = ref({});
const butShow = ref(false)
const title = ref('新增')
const showData=ref(false)
// 初始化数据
const init = (type, row) => {
dialogForm.value = true;
@ -153,11 +148,10 @@ const init = (type, row) => {
disabled.value = false
showBut.value = false
} else {
butShow.value = false
tbGsxtZdrySelectVoById({ id: row.id }).then(res => {
console.log(res, "dddddddddddddddd");
Object.assign(listQuery.value, res)
listQuery.value = { ...res }
})
if (type == 'edit') {
showBut.value = true
@ -200,7 +194,7 @@ const handleScroll = () => {
'info-section', 'backinfo-section', 'groupLabels-section',
'character-section', 'controlInfo-section', 'featinfo-section',
'demandsInfo-section', 'requestInfo-section', 'personnel-section',
'judgmentRecord-section', 'historyAssembly-section', 'joblogging-section'
'judgmentRecord-section', 'historyAssembly-section', 'joblogging-section', "czModel-section"
];
for (let i = sections.length - 1; i >= 0; i--) {
@ -235,8 +229,15 @@ const submit = async () => {
// 使用Promise.all处理所有子组件的验证和数据获取
const [infoData, personnelTagsData] = await Promise.all([
info.value.throwData(),
personnelTags.value.throwData(),
// personnelTags.value.throwData(),
]);
tbGsxtZdrySave(infoData).then(res => {
console.log(res);
})
console.log(infoData);
};

View File

@ -1,65 +0,0 @@
<template>
{{ visible }}
<!-- 添加 -->
<el-dialog v-model="visible" :title="Tips" width="40%" :before-close="handleClose">
<el-form ref="historyForm" style="max-width: 600px" :model="diaLogRuleForm" :rules="diaLogRules">
<div v-for="item in diaLogRuleForm" :key="item.props">
<el-form-item label-width="80px" :label="item.label" :prop="item.props" style="width: 100%;">
<el-input v-model="item.value" :placeholder="`请输入${item.label}`" />
</el-form-item>
</div>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">
确认
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { defineProps, defineEmits, ref, watch } from 'vue'
// 接收 v-model:visible
const props = defineProps({
visible: Boolean,
Tips: String,
diaLogRules: Object,
diaLogRuleForm: Object
})
const emit = defineEmits(['update:visible', 'submit'])
const formRef = ref(null)
const formData = ref({})
// 监听外部传入的 formData 变化(如编辑时回显)
watch(
[() => props.diaLogRuleForm, props.visible],
(val) => {
console.log(val, "变化之后的diaLogRuleForm");
formData.value = val ? { ...val } : {}
},
{ immediate: true }
)
// 取消:关闭弹窗
const onCancel = () => {
emit('update:visible', false)
}
// 提交
const onSubmit = () => {
emit('submit', props.diaLogRuleForm) // 提交数据
// formRef.value?.validate((valid) => {
// if (valid) {
// // 不在这里关闭!由父组件决定是否关闭(比如提交失败不关闭)
// }
// })
}
</script>
<style scoped lang="scss"></style>

View File

@ -8,8 +8,7 @@
</template>
<div class="flex just-center">
<el-button size="small" type="primary" v-for="it in D_GS_BK_SQLX" :key="it.dm"
@click="handleApplication(it)">{{
it.zdmc }}</el-button>
@click="handleApplication(it)">{{it.zdmc }}</el-button>
</div>
</el-popover>
<el-popover placement="bottom" :visible="visiblefp" :width="400" trigger="click">
@ -169,7 +168,7 @@ const pageData = reactive({
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 150,
controlsWidth: 250,
tableColumn: [
{ label: "姓名", prop: "ryXm", width: 150 },
{ label: "性别", prop: "ryXb", showSolt: true, width: 100 },

View File

@ -2,23 +2,12 @@
<div>
<div class="headClass" style="">
<h3>现实表现</h3>
<!-- <el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button> -->
</div>
<div class="headSelect">
<el-button @click="add" type="primary">新增</el-button>
<el-button @click="AddPore" type="primary" v-if="showBut">新增</el-button>
</div>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #clys="{ row }">
<DictTag :tag="false" :value="row.clys" :options="D_BZ_CLYS" />
</template>
<template #cllx="{ row }">
<DictTag :tag="false" :value="row.cllx" :options="D_BZ_CLLX" />
</template>
<template #clpp="{ row }">
<DictTag :tag="false" :value="row.clpp" :options="D_BZ_CLPP" />
<template #showSolt="{ row }">
<span v-for="(item,index) in row.fjxx" :key="index">{{ item.originalName }}<span v-if="index < row.fjxx.length - 1"></span></span>
</template>
<!-- 操作 -->
<template #controls="{ row }">
@ -27,20 +16,23 @@
</template>
</MyTable>
</div>
<VehiclDoing v-model="chooseMarksVisible" @comfirm="addMarks" :data="dataModel"
:dict="{ D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP }" />
<!-- <VehiclDoing v-model="JudgmentShow" @comfirm="addMarks" :data="dataModel"
:dict="{ D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP }" /> -->
<JudgmentRecord v-model="JudgmentShow" @comfirm="onComfirm" :data="dataModel" />
</template>
<script setup>
import { identityCardRule } from "@/utils/rules"
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted, onUnmounted } from "vue";
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted, onUnmounted } from "vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import VehiclDoing from "../component/vehiclDoing.vue";
import { tbZdryClxxAdd, tbZdryClxxBatchAdd, tbZdryClxxDelete, tbZdryClxxSelectPage, tbZdryClxxUpdate } from '@/api/zdr.js'
import JudgmentRecord from "../component/judgmentRecord.vue";
import { tbGsxtZdryXsbxSaveOrUpdateXsbx,tbGsxtZdryXsbxSelectZfjl,tbGsxtZdryXsbx } from '@/api/zdr.js'
import { ElMessage, ElMessageBox } from "element-plus";
const { proxy } = getCurrentInstance();
const { D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP } = proxy.$dict("D_BZ_CLLX", "D_BZ_CLYS", "D_BZ_CLPP"); //获取字典数据
const chooseMarksVisible = ref(false)
const JudgmentShow = ref(false)
const props = defineProps({
dataList: {
type: Object,
@ -66,20 +58,17 @@ watch(() => props.dataList, (val) => {
const pageData = reactive({
tableData: [],
tableColumn: [{
prop: 'cph',
prop: 'rrry',
label: '录入人员',
}, {
prop: 'cllx',
prop: 'lrsj',
label: '录入时间',
showSolt: true,
prop: 'clpp',
}, {
showSolt: true,
prop: 'clys',
prop: 'bxnr',
label: '表现内容',
}, {
showSolt: true,
prop: 'clpp',
prop: 'fjxx',
label: '附件信息',
}],
tableHeight: '200px',
@ -97,45 +86,40 @@ const pageData = reactive({
},
controlsWidth: 200,
})
// 表单数据
const formData = reactive({
username: "",
ID: ""
})
const rulesForm = ref(identityCardRule({ validator: true }, 'rySfzh'))
// 修改数据接口
const dataModel = ref()
const addMarks = (val) => {
const onComfirm = (val) => {
const params = {
...val,
zdrid: listData.value.id,
zdryId: listData.value.id,
}
if (props.showBut && !props.disabled) {
if (addUpd.value) {
tbZdryClxxAdd(params).then(res => {
console.log(params);
// if (props.showBut && !props.disabled) {
// if (addUpd.value) {
tbGsxtZdryXsbxSaveOrUpdateXsbx(params).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆添加成功',
type: 'success'
})
})
}
else {
tbZdryClxxUpdate(params).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆修改成功',
type: 'success'
})
})
}
} else {
pageData.tableData.push(val)
}
// }
// else {
// tbZdryClxxUpdate(params).then(res => {
// gettbZdryClxxSelectPage()
// proxy.$message({
// message: '关联车辆修改成功',
// type: 'success'
// })
// })
// }
// } else {
// pageData.tableData.push(val)
// }
}
onMounted(() => {
})
// 删除车辆
const delDictItem = (val) => {
@ -150,10 +134,10 @@ const delDictItem = (val) => {
}
)
.then(() => {
tbZdryClxxDelete({ ids: [val] }).then(res => {
tbGsxtZdryXsbx(val).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆删除成功',
message: '表现信息删除成功',
type: 'success'
})
})
@ -171,24 +155,26 @@ const delDictItem = (val) => {
}
const updDictItem = (val) => {
chooseMarksVisible.value = true
JudgmentShow.value = true
addUpd.value = false
dataModel.value = val
}
const AddPore = () => {
chooseMarksVisible.value = true
dataModel.value = {}
JudgmentShow.value = true
addUpd.value = true
}
// 查询车辆
const gettbZdryClxxSelectPage = () => {
const promes = {
pageCurrent: 1,
pageSize: 20,
zdrid: listData.value.id
}
tbZdryClxxSelectPage(promes).then(res => {
pageData.tableData = res.records
tbGsxtZdryXsbxSelectZfjl(promes).then(res => {
pageData.tableData = res.map(item => {
return {
...item,
fjxx: item.fjxx ? JSON.parse(item.fjxx) : []
}
})
})
}
// 抛出数据并验证标签列表不为空
@ -237,6 +223,9 @@ defineExpose({
}
.headClass {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
font-weight: 600;
color: #303133;

View File

@ -3,14 +3,8 @@
<div class="backinfo-container">
<div class="headClass" style="">
<h3>背景信息</h3>
<el-button type="primary" v-if="showBut" :disabled="disabled" @click="ClickSave">保存</el-button>
<el-button type="primary" v-if="showBut" :disabled="disabled" @click="submitForm(ruleFormRef)">保存</el-button>
</div>
<!-- <div>
<div>拘留记录</div>
<div v-for="(item,index) in jljl" :key="index">
<el-input v-model="jljl[index]" :autosize="{ minRows: 4, maxRows: 10 }" type="textarea" placeholder="请输入背景信息"
class="background-info-input" :disabled="disabled" /></div>
</div> -->
<div>
<!-- 全部输入框 -->
<el-form class="record" ref="ruleFormRef" :model="ruleForm" :rules="rules">
@ -19,17 +13,16 @@
<div>拘留所记录</div>
<div>
<div v-for="(item, i) in ruleForm.detentionCenterRecords" :key="item.id" class="detentionFacilityArr">
<el-form-item :prop="'detentionCenterRecords.' + i + '.str'" :rules="rules.str">
<el-input v-model="ruleForm.detentionCenterRecords[i].str" class="detentionFacilityInput"
placeholder="请输入拘留所记录" />
<el-form-item :prop="'detentionCenterRecords.' + i + '.str'" :rules="rules.str">
<el-input v-model="ruleForm.detentionCenterRecords[i].str" type="textarea"
class="detentionFacilityInput" placeholder="请输入拘留所记录" />
</el-form-item>
<el-button type="primary"
v-if="ruleForm.detentionCenterRecords.length > 1 && i != ruleForm.detentionCenterRecords.length - 1"
@click="decreaseRecord(i, '拘留所')"></el-button>
<el-button type="primary" @click="addRecord(i, '拘留所')"
v-if="ruleForm.detentionCenterRecords.length - 1 == i">+</el-button>
<div style="width: 100px;">
<el-button type="primary" v-if="ruleForm.detentionCenterRecords.length != 1"
@click="decreaseRecord(i, '拘留所')"></el-button>
<el-button type="primary" @click="addRecord(i, '拘留所')"
v-if="i == ruleForm.detentionCenterRecords.length - 1">+</el-button>
</div>
</div>
</div>
</div>
@ -38,21 +31,20 @@
<div>看守所记录</div>
<div>
<div v-for="(item, i) in ruleForm.prison" :key="item.id" class="detentionFacilityArr">
<el-form-item :prop="'prison.' + i + '.str'" :rules="rules.str">
<el-input v-model="ruleForm.prison[i].str"
class="detentionFacilityInput" placeholder="请输入拘留所记录"
@input="changeprison(ruleForm.prison[i].str)"
/>
<el-form-item :prop="'prison.' + i + '.str'" :rules="rules.str">
<el-input v-model="ruleForm.prison[i].str" type="textarea" class="detentionFacilityInput"
placeholder="请输入拘留所记录" />
</el-form-item>
<el-button type="primary" v-if="ruleForm.prison.length > 1 && i != ruleForm.prison.length - 1"
<div style="width: 100px;">
<el-button type="primary" v-if="ruleForm.prison.length != 1"
@click="decreaseRecord(i, '看守所')"></el-button>
<el-button type="primary" @click="addRecord(i, '看守所')" v-if="ruleForm.prison.length - 1 == i">+</el-button>
<el-button type="primary" @click="addRecord(i, '看守所')"
v-if="i == ruleForm.prison.length - 1">+</el-button>
</div>
</div>
</div>
</div>
<div class="sumbitBtnBOX">
<el-button type="primary" @click="submitForm(ruleFormRef)" class="sumbitBtn">确认提交</el-button>
</div>
</el-form>
</div>
@ -60,9 +52,9 @@
</template>
<script setup>
import { reactive, ref, watch, onMounted } from "vue";
import { Delete, Download } from '@element-plus/icons';
// import { tbGsxtZdryUpdate } from '@/api/zdr.js'
import { reactive, ref, watch, onMounted, getCurrentInstance } from "vue";
import { tbGsxtZdryUpdate } from '@/api/zdr.js'
const { proxy } = getCurrentInstance();
const props = defineProps({
dataList: {
type: Object,
@ -76,7 +68,6 @@ const props = defineProps({
default: false
},
})
const jljl = ref([])
const ruleFormRef = ref()
const ruleForm = reactive({
detentionCenterRecords: [{ id: 0, str: "" }],
@ -84,33 +75,28 @@ const ruleForm = reactive({
})
// 表单校验
const rules = reactive({
str: [
{ required: true, message: '请输入具体信息', trigger: 'blur' },
{ min: 3, max: 20, message: '请最少输入3个字,最多输入20个字', trigger: 'blur' },
],
// str: [
// { required: true, message: '请输入具体信息', trigger: 'blur' },
// { min: 3, max: 20, message: '请最少输入3个字,最多输入20个字', trigger: 'blur' },
// ],
})
watch(() => props.dataList, (val) => {
if (val) {
// qtbjxx.value = val.qtBjzl
ruleForm.detentionCenterRecords = val.jlsJl && val.kssJl.length > 0 ? val.jlsJl.map((item, index) => {
return {
id: index,
str: item
}
}) : [{ id: 0, str: "" }],
ruleForm.prison = val.kssJl && val.kssJl.length > 0 ? val.kssJl.map((item, index) => {
return {
id: index,
str: item
}
}) : [{ id: 0, str: "" }]
}
}, { deep: true })
onMounted(() => {
console.log('组件已挂载')
})
const throwData = () => {
return new Promise((resolve) => {
// 基本验证:确保背景信息不为空
if (!qtbjxx.value.trim()) {
throw new Error('请输入群体背景信息');
}
resolve({
qtbjxx: qtbjxx.value,
fileList: fileList.value
});
});
}
// 增加输入记录输入框
const addRecord = (val, type) => {
if (type == '拘留所') {
@ -118,7 +104,6 @@ const addRecord = (val, type) => {
} else {
ruleForm.prison.push({ id: val })
}
}
// 减少输入记录输入框
const decreaseRecord = (val, type) => {
@ -129,25 +114,33 @@ const decreaseRecord = (val, type) => {
}
}
const changeprison=(value)=>{
console.log(value,"jafahfahf");
}
//提交数据校验表单
const submitForm = async (formEl) => {
console.log(formEl,"formElformEl");
if (!formEl) return
await formEl.validate((valid, fields) => {
console.log(valid,fields,"22222222");
if (valid) {
const promes = {
id: props.dataList.id,
jlsJl: ruleForm.detentionCenterRecords.map(item => item.str),
kssJl: ruleForm.prison.map(item => item.str),
}
tbGsxtZdryUpdate(promes).then((res) => {
proxy.$message.success('保存成功')
}).catch((err) => {
proxy.$message.error('保存失败')
});
console.log('submit!')
} else {
console.log('error submit!', fields)
}
})
}
}
const throwData = () => {
return new Promise((resolve) => {
resolve(ruleForm);
});
}
defineExpose({
throwData
})
@ -202,7 +195,7 @@ defineExpose({
.detentionFacilityArr {
display: flex;
margin-top: 20px;
justify-content: space-between;

View File

@ -0,0 +1,268 @@
<template>
<div class="backinfo-container">
<div class="headClass">
<h3>行为信息</h3>
</div>
<!-- 列表区域 -->
<div class="list-container">
<div v-loading="loading" class="behavior-list">
<div class="behavior-list-inner">
<div
v-for="(item, index) in behaviorList"
:key="item.id"
class="behavior-item"
>
<div class="behavior-item-header">
<span class="behavior-index">{{ index + 1 }}.</span>
<el-tag :type="getTagType(item.behaviorType)">{{ item.behaviorTypeName }}</el-tag>
<span class="behavior-time">{{ item.time }}</span>
</div>
<div class="behavior-item-content">
<p class="behavior-description">{{ item.description }}</p>
<p class="behavior-location"><i class="el-icon-location-outline"></i> {{ item.location }}</p>
</div>
</div>
<div v-if="!loading && behaviorList.length === 0" class="empty-state">
<el-empty description="暂无行为记录" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, getCurrentInstance, onMounted } from 'vue'
import GdMap from "@/components/GdMap/index.vue";
const { proxy } = getCurrentInstance();
const { D_BZ_ZJLX } = proxy.$dict("D_BZ_ZJLX")
// 搜索表单
const searchForm = ref({
behaviorType: '',
timeRange: null
})
// 列表数据
const behaviorList = ref([])
const loading = ref(false)
// 获取标签类型
const getTagType = (type) => {
const typeMap = {
'ticket': 'success',
'hotel': 'primary',
'border': 'warning',
'baseStation': 'info'
}
return typeMap[type] || 'default'
}
// 搜索
const handleSearch = () => {
fetchData()
}
// 重置搜索
const resetSearch = () => {
searchForm.value = {
behaviorType: '',
timeRange: null
}
fetchData()
}
// 获取数据
const fetchData = () => {
loading.value = true
// 模拟API请求延迟
setTimeout(() => {
// 模拟数据
const mockData = [
{
id: 1,
behaviorType: 'baseStation',
behaviorTypeName: '基站认证',
description: '2025-5-22 14:30:20出现在南宁市青秀区云网网咖',
location: '广西壮族自治区南宁市青秀区',
time: '2025-05-22 14:30:20'
}
]
// 根据搜索条件过滤数据
let filteredData = [...mockData]
if (searchForm.value.behaviorType) {
filteredData = filteredData.filter(item => item.behaviorType === searchForm.value.behaviorType)
}
if (searchForm.value.timeRange && searchForm.value.timeRange.length === 2) {
const [startTime, endTime] = searchForm.value.timeRange
filteredData = filteredData.filter(item => {
const itemTime = new Date(item.time)
return itemTime >= new Date(startTime) && itemTime <= new Date(endTime)
})
}
behaviorList.value = filteredData
loading.value = false
}, 500)
}
// 页面加载时获取数据
onMounted(() => {
fetchData()
})
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.backinfo-container {
padding: 20px;
width: 100%;
background-color: #f5f7fa;
}
.headClass {
font-size: 18px;
font-weight: 600;
color: #303133;
margin: 0 0 20px 0;
padding-bottom: 15px;
border-bottom: 2px solid #409eff;
position: relative;
}
h3 {
margin: 0;
}
.search-container {
background-color: #fff;
padding: 16px;
border-radius: 6px;
margin-bottom: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.demo-form-inline {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 16px;
}
.list-container {
background-color: #fff;
padding: 16px;
border-radius: 6px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.behavior-list {
max-height: 600px;
overflow: hidden; /* 完全禁止滚动条 */
position: relative;
}
.behavior-list-inner {
max-height: 600px;
overflow-y: auto;
overflow-x: hidden;
padding-right: 10px; /* 为滚动条留出空间但不显示 */
}
.behavior-item {
padding: 16px;
border-bottom: 1px solid #f0f0f0;
transition: all 0.3s ease;
position: relative;
left: 0; /* 初始位置 */
}
.behavior-item:hover {
background-color: #fafafa;
left: 5px; /* 使用left属性代替transform避免触发滚动条 */
}
.behavior-item:last-child {
border-bottom: none;
}
.behavior-item-header {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.behavior-index {
font-weight: 600;
color: #606266;
margin-right: 12px;
min-width: 20px;
}
.behavior-time {
margin-left: auto;
color: #909399;
font-size: 13px;
}
.behavior-item-content {
padding-left: 32px;
}
.behavior-description {
margin: 0 0 8px 0;
color: #303133;
line-height: 1.5;
}
.behavior-location {
margin: 0;
color: #606266;
font-size: 13px;
line-height: 1.5;
}
.empty-state {
padding: 60px 0;
text-align: center;
}
::v-deep .el-tag {
margin-right: 0;
}
::v-deep .el-date-editor .el-range-separator {
color: #606266;
}
@media (max-width: 768px) {
.backinfo-container {
padding: 10px;
}
.demo-form-inline {
flex-direction: column;
align-items: stretch;
}
.demo-form-inline .el-form-item {
margin-bottom: 10px;
}
.pagination-container {
justify-content: center;
}
}
</style>

View File

@ -2,41 +2,28 @@
<div>
<div class="headClass" style="">
<h3>案件信息</h3>
<!-- <el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button> -->
<el-button @click="AddPore" type="primary" v-if="showBut">新增</el-button>
</div>
<div class="headSelect">
<el-button @click="add" type="primary">新增</el-button>
</div>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #clys="{ row }">
<DictTag :tag="false" :value="row.clys" :options="D_BZ_CLYS" />
</template>
<template #cllx="{ row }">
<DictTag :tag="false" :value="row.cllx" :options="D_BZ_CLLX" />
</template>
<template #clpp="{ row }">
<DictTag :tag="false" :value="row.clpp" :options="D_BZ_CLPP" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link type="danger" @click="delDictItem(row.id)">删除</el-link>
<el-link type="danger" @click="updDictItem(row)">修改</el-link>
</template>
</MyTable>
</div>
<VehiclDoing v-model="chooseMarksVisible" @comfirm="addMarks" :data="dataModel"
:dict="{ D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP }" />
<CaseLodig v-model="chooseMarksVisible" @comfirm="addMarks" :data="dataModel" />
</template>
<script setup>
import { identityCardRule } from "@/utils/rules"
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted, onUnmounted } from "vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import VehiclDoing from "../component/vehiclDoing.vue";
import { tbZdryClxxAdd, tbZdryClxxBatchAdd, tbZdryClxxDelete, tbGsxtZdryAjxxselectAjxx, tbZdryClxxUpdate } from '@/api/zdr.js'
import CaseLodig from "../component/caseLodig.vue";
import { tbGsxtZdryAjxxSaveOrUpdateAjxx, tbGsxtZdryAjxx, tbGsxtZdryAjxxselectAjxx } from '@/api/zdr.js'
import { ElMessage, ElMessageBox } from "element-plus";
const { proxy } = getCurrentInstance();
const { D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP } = proxy.$dict("D_BZ_CLLX", "D_BZ_CLYS", "D_BZ_CLPP"); //获取字典数据
@ -66,16 +53,13 @@ watch(() => props.dataList, (val) => {
const pageData = reactive({
tableData: [],
tableColumn: [{
prop: 'cph',
prop: 'ajbm',
label: '案件编号',
}, {
prop: 'cllx',
prop: 'ajmc',
label: '案件名称',
showSolt: true,
prop: 'clpp',
}, {
showSolt: true,
prop: 'clys',
prop: 'sasj',
label: '受案时间',
},],
tableHeight: '200px',
@ -93,51 +77,29 @@ const pageData = reactive({
},
controlsWidth: 200,
})
// 表单数据
const formData = reactive({
username: "",
ID: ""
})
const rulesForm = ref(identityCardRule({ validator: true }, 'rySfzh'))
// 修改数据接口
const dataModel = ref()
const addMarks = (val) => {
const params = {
...val,
zdrid: listData.value.id,
}
if (props.showBut && !props.disabled) {
if (addUpd.value) {
tbZdryClxxAdd(params).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆添加成功',
type: 'success'
})
})
}
else {
tbZdryClxxUpdate(params).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆修改成功',
type: 'success'
})
})
}
} else {
pageData.tableData.push(val)
zdryId: listData.value.id,
}
tbGsxtZdryAjxxSaveOrUpdateAjxx(params).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '案件信息操作成功',
type: 'success'
})
})
}
onMounted(() => {
// console.log(identityCardRule,"dadad1");
})
// 删除车辆
const delDictItem = (val) => {
if (!props.disabled && props.showBut) {
ElMessageBox.confirm(
'是否删除关联车辆',
'是否删除案件信息',
'提示',
{
confirmButtonText: '确认',
@ -146,10 +108,10 @@ const delDictItem = (val) => {
}
)
.then(() => {
tbZdryClxxDelete({ ids: [val] }).then(res => {
tbGsxtZdryAjxx(val).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆删除成功',
message: '案件信息删除成功',
type: 'success'
})
})
@ -179,14 +141,10 @@ const AddPore = () => {
// 查询车辆
const gettbZdryClxxSelectPage = () => {
const promes = {
pageCurrent: 1,
pageSize: 20,
zdrid: listData.value.id
}
tbGsxtZdryAjxxselectAjxx(promes).then(res => {
console.log(res, "案件信息");
pageData.tableData = res.records
pageData.tableData = res
})
}
// 抛出数据并验证标签列表不为空
@ -236,6 +194,9 @@ defineExpose({
.headClass {
font-size: 18px;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 600;
color: #303133;
margin: 20px 0 10px 0;

View File

@ -2,63 +2,45 @@
<div>
<div class="headClass" style="">
<h3>密切联系人</h3>
<!-- <el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button> -->
<el-button type="primary" @click="openDialog('新增密切联系人', {}, true)" v-if="showBut">新增</el-button>
</div>
<div class="headSelect">
<el-form :model="formData" :inline="true" ref="formRef" :rules="rulesForm" class="form-inline">
<!-- 姓名 -->
<el-form-item label="姓名" prop="username" :rules="[
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 4, message: '长度在 2 到 4 个字符', trigger: 'blur' }
]">
<el-input v-model="formData.username" placeholder="请输入姓名" style="width: 120px;" />
<el-form-item label="身份证号码">
<el-input v-model="formData.rySfzh" placeholder="请输入身份证号码" />
</el-form-item>
<!-- 身份证号码 -->
<el-form-item label="身份证号码" prop="cardID" :rules="[
{ required: true, message: '请输入身份证号码', trigger: 'blur' }
]">
<el-input v-model="formData.ID" placeholder="请输入身份证号码" style="width: 200px;" />
</el-form-item>
<!-- 按钮组统一放在一个 item -->
<el-form-item class="form-actions">
<el-button type="primary" @click="check">查询</el-button>
<el-button @click="resetForm">重置</el-button>
<el-button @click="openDialog('新增密切联系人')">新增</el-button>
</el-form-item>
</el-form>
</div>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<!-- <template #ryXm="{ row }">
<DictTag :tag="false" :value="row.clys" :options="D_BZ_CLYS" />
</template> -->
<template #dygx="{ row }">
<DictTag :tag="false" :value="row.dygx" :options="D_BZ_QSGXDM" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link type="danger" @click="delDictItem(row.id)">删除</el-link>
<el-link type="danger" @click="openDialog('修改密切联系人', row)">修改</el-link>
<el-link type="danger" @click="openDialog('修改密切联系人', row, false)">修改</el-link>
</template>
</MyTable>
<diaLogForm v-model:visible="dialogVisible" :diaLogRules="diaLogRules" :diaLogRuleForm="diaLogRuleForm"
@submit="addPersonOrModifica" :Tips="Tips">
<diaLogForm v-model="dialogVisible" :data="diaLogRuleForm" @submit="addPersonOrModifica" :title="Tips"
:dict="{ D_BZ_QSGXDM }">
</diaLogForm>
</div>
</template>
<script setup>
import { identityCardRule } from "@/utils/rules"
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted, onUnmounted } from "vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import diaLogForm from "../components/diaLogForm.vue";
import { tbGsxtZdryLxrsaveOrUpdateLxr, tbZdryClxxBatchAdd, tbZdryClxxDelete, tbGsxtZdryLxrselectLxrBy, tbZdryClxxUpdate } from '@/api/zdr.js'
import diaLogForm from "../component/diaLogForm.vue";
import { tbZdryClxxUpdate, tbGsxtZdryLxrsaveOrUpdateLxr,tbGsxtZdryLxrselectLxrBy ,tbGsxtZdryLxr} from '@/api/zdr.js'
import { ElMessage, ElMessageBox } from "element-plus";
const { proxy } = getCurrentInstance();
const { D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP } = proxy.$dict("D_BZ_CLLX", "D_BZ_CLYS", "D_BZ_CLPP"); //获取字典数据
const chooseMarksVisible = ref(false)
const { D_BZ_QSGXDM } = proxy.$dict("D_BZ_QSGXDM"); //获取字典数据
const props = defineProps({
dataList: {
type: Object,
@ -72,37 +54,25 @@ const props = defineProps({
default: false
},
})
const ruleForm = ref({
name: '',
cardID: '',
relation: '',
phone: '',
})
const dialogVisible = ref(false)
const listData = ref({})
const Tips = ref(false)
const addUpd = ref(true)
const Tips = ref("密切联系人")
// 表格数据
const pageData = reactive({
tableData: [],
tableColumn: [{
prop: 'ryXm',
label: '人员姓名',
}, {
prop: 'rySfzh',
label: '身份证号码',
width: 200
}, {
prop: 'dygx',
label: '关系',
showSolt: true,
}, {
prop: 'lxrDh',
label: '联系电话',
width: 120
}],
tableHeight: '200px',
keyCount: 0,
@ -120,171 +90,104 @@ const pageData = reactive({
controlsWidth: 200,
})
// 表单数据
const formData = reactive({
const formData = ref({
username: "",
ID: ""
})
const touchIn = ref(true)
const rulesForm = ref(identityCardRule({ validator: true }, 'rySfzh'))
const diaLogRuleForm = reactive([{ prop: 'username', label: '姓名', type: 'input', value: '' },
{ prop: 'cardID', label: '身份证号', type: 'input', value: '' },
{ prop: 'relation', label: '关系', type: 'input', value: '' },
{ prop: 'phone', label: '联系电话', type: 'input', value: '' }
])
const diaLogRuleForm = ref({})
watch(() => props.dataList, (val) => {
if (val) {
console.log(val, 'listData.value');
listData.value = val
getContact()
}
}, { deep: true })
// 弹出增加或者修改弹窗
const openDialog = (type, formVal) => {
const openDialog = (type, formVal, bool) => {
touchIn.value = bool
dialogVisible.value = true
Tips.value = type
console.log(formVal, "formVal");
console.log(dialogVisible.value, "dialogVisible.value")
if (type === '新增密切联系人') {
diaLogRuleForm.forEach(item => {
item.value = ''
})
} else {
diaLogRuleForm[0].value = formVal.ryXm
diaLogRuleForm[1].value = formVal.rySfzh
diaLogRuleForm[2].value = formVal.dygx
diaLogRuleForm[3].value = formVal.lxrDh
}
diaLogRuleForm.value = { ...formVal }
}
// 增加或修改数据接口
const dataModel = ref()
const addPersonOrModifica = async (val) => {
console.log('dafafaf', val)
let params = {
id: listData.value.id
}
val.forEach(item => {
switch (item.label) {
case '姓名':
params.ryXm = item.value
break
case '身份证号':
params.rySfzh = item.value
break
case '关系':
params.dygx = item.value
break
case '联系电话':
params.lxrDh = item.value
break
default:
break
// 提交表单
const addPersonOrModifica = (val) => {
if (touchIn.value) {
const item = pageData.tableData.findIndex(item => item.rySfzh == val.rySfzh)
if (item != -1) {
proxy.$message({
message: '该人员已存在',
type: 'warning'
})
return
}
})
console.log(params, "fafafafaff");
if (props.showBut && !props.disabled) {
const res = await tbGsxtZdryLxrsaveOrUpdateLxr(params)
console.log(res, "联系人增加res");
// if (type) {
// if (res.code == 200) {
// gettbZdryClxxSelectPage()
// proxy.$message({
// message: '密切联系人添加成功',
// type: 'success'
// })
// } else {
// proxy.$message({
// message: '密切联系人添加失败',
// type: 'error'
// })
// }
// } else {
// if (res.code == 200) {
// gettbZdryClxxSelectPage()
// proxy.$message({
// message: '密切联系人添加成功',
// type: 'success'
// })
// } else {
// proxy.$message({
// message: '密切联系人添加失败',
// type: 'error'
// })
// }
// }
} else {
pageData.tableData.push(val)
}
}
onMounted(() => {
// console.log(identityCardRule,"dadad1");
})
// 删除车辆
const delDictItem = (val) => {
if (!props.disabled && props.showBut) {
ElMessageBox.confirm(
'是否删除关联车辆',
'提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
tbZdryClxxDelete({ ids: [val] }).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆删除成功',
type: 'success'
})
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消删除',
})
})
} else {
pageData.tableData = pageData.tableData.filter(v => v.id != val)
}
}
const updDictItem = (val) => {
chooseMarksVisible.value = true
addUpd.value = false
dataModel.value = val
}
const AddPore = () => {
chooseMarksVisible.value = true
dataModel.value = {}
addUpd.value = true
}
// 初始化密切联系人
const gettbZdryClxxSelectPage = () => {
const promes = {
pageCurrent: 1,
pageSize: 20,
zdrid: listData.value.id
...val,
zdryId: listData.value.id
}
tbGsxtZdryLxrselectLxrBy(promes).then(res => {
tbGsxtZdryLxrsaveOrUpdateLxr(promes).then((res) => {
proxy.$message({
message: '操作成功',
type: 'success'
})
getContact()
}).catch((err) => {
proxy.$message({
message: '操作失败',
type: 'error'
})
});
}
const delDictItem = (val) => {
ElMessageBox.confirm(
'是否删除该联系人',
'提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
tbGsxtZdryLxr(val).then((res) => {
proxy.$message({
message: '删除成功',
type: 'success'
})
getContact()
}).catch((err) => {
});
})
.catch(() => {
proxy.$message({
message: '删除失败',
type: 'info',
})
})
}
const getContact = () => {
const promes = { zdryId: listData.value.id }
tbGsxtZdryLxrselectLxrBy(promes).then((res) => {
pageData.tableData = res
console.log(pageData.tableData, "表格原生数据");
})
}
const resetForm = () => {
formData.value = {}
getContact()
}
const check = () => {
if (formData.value.rySfzh) {
// 模糊查询:检查身份证号码是否包含输入的内容
pageData.tableData = pageData.tableData.filter(item => item.rySfzh && item.rySfzh.includes(formData.value.rySfzh))
} else {
// 如果输入为空,显示所有数据
getContact()
}
}
// 抛出数据并验证标签列表不为空
const throwData = () => {
return new Promise((resolve) => {
@ -335,7 +238,9 @@ defineExpose({
padding-bottom: 10px;
border-bottom: 2px solid #409eff;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
}
.headSelect {

View File

@ -0,0 +1,222 @@
<template>
<div class="backinfo-container">
<div class="headClass">
<h3>操作日志</h3>
</div>
<!-- 列表区域 -->
<div class="list-container">
<div v-loading="loading" class="behavior-list">
<div class="behavior-list-inner">
<div
v-for="(item, index) in behaviorList"
:key="item.id"
class="behavior-item"
>
<div class="behavior-item-header">
<span class="behavior-index">{{ index + 1 }}.</span>
<el-tag :type="getTagType(item.behaviorType)">{{ item.zhmc }}</el-tag>
<span class="behavior-time">{{ item.czsj }}</span>
</div>
<div class="behavior-item-content">
<p class="behavior-description">{{ item.czjl }}</p>
<p class="behavior-location"><i class="el-icon-location-outline"></i> {{ item.bz }}</p>
</div>
</div>
<div v-if="!loading && behaviorList.length === 0" class="empty-state">
<el-empty description="暂无操作记录" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, getCurrentInstance, onMounted,watch } from 'vue'
import GdMap from "@/components/GdMap/index.vue";
import {tbGsxtZdryCzrzSelectCzrz} from '@/api/zdr'
const { proxy } = getCurrentInstance();
const props = defineProps({
dataList: {
type: Object,
default: () => { },
}, disabled: {
type: Boolean,
default: false
},
showBut: {
type: Boolean,
default: false
},
})
const listData = ref({})
watch(() => props.dataList, (val) => {
if (val) {
listData.value = val
fetchData()
}
}, { deep: true })
// 列表数据
const behaviorList = ref([])
const loading = ref(false)
// 获取数据
const fetchData = () => {
loading.value = true
tbGsxtZdryCzrzSelectCzrz({ zdrid: listData.value.id }).then(res => {
behaviorList.value = res
}).finally(() => {
loading.value = false
})
}
// 页面加载时获取数据
onMounted(() => {
})
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.backinfo-container {
padding-top: 20px;
width: 100%;
background-color: #f5f7fa;
}
.headClass {
font-size: 18px;
font-weight: 600;
color: #303133;
margin: 0 0 20px 0;
padding-bottom: 15px;
border-bottom: 2px solid #409eff;
position: relative;
}
h3 {
margin: 0;
}
.search-container {
background-color: #fff;
padding: 16px;
border-radius: 6px;
margin-bottom: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.demo-form-inline {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 16px;
}
.list-container {
background-color: #fff;
padding: 16px;
border-radius: 6px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.behavior-list {
max-height: 600px;
overflow: hidden; /* 完全禁止滚动条 */
position: relative;
}
.behavior-list-inner {
max-height: 600px;
overflow-y: auto;
overflow-x: hidden;
padding-right: 10px; /* 为滚动条留出空间但不显示 */
}
.behavior-item {
padding: 16px;
border-bottom: 1px solid #f0f0f0;
transition: all 0.3s ease;
position: relative;
left: 0; /* 初始位置 */
}
.behavior-item:hover {
background-color: #fafafa;
left: 5px; /* 使用left属性代替transform避免触发滚动条 */
}
.behavior-item:last-child {
border-bottom: none;
}
.behavior-item-header {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.behavior-index {
font-weight: 600;
color: #606266;
margin-right: 12px;
min-width: 20px;
}
.behavior-time {
margin-left: auto;
color: #909399;
font-size: 13px;
}
.behavior-item-content {
padding-left: 32px;
}
.behavior-description {
margin: 0 0 8px 0;
color: #303133;
line-height: 1.5;
}
.behavior-location {
margin: 0;
color: #606266;
font-size: 13px;
line-height: 1.5;
}
.empty-state {
padding: 60px 0;
text-align: center;
}
::v-deep .el-tag {
margin-right: 0;
}
::v-deep .el-date-editor .el-range-separator {
color: #606266;
}
@media (max-width: 768px) {
.backinfo-container {
padding: 10px;
}
.demo-form-inline {
flex-direction: column;
align-items: stretch;
}
.demo-form-inline .el-form-item {
margin-bottom: 10px;
}
.pagination-container {
justify-content: center;
}
}
</style>

View File

@ -6,11 +6,18 @@
</div>
<div class="marginBox">
<div>身份证号码{{ listData.rySfzh }} <span>({{ listData.zdrBkZt ? '已布控' : '未布控' }})</span></div>
<div>手机号码{{ listData.ryLxdh?.[0] }} <span>({{ listData.zdrBkZt ? '已布控' : '未布控' }})</span>
<div v-if="listData.ryLxdh&&listData.ryLxdh.length>0"> 手机号码
<span style="color: #000;" v-for="(item, index) in listData.ryLxdh" :key="index">{{ item }}
<span v-if="index != listData.ryLxdh.length - 1"></span>
</span>
<div> {{ listData.ryLxdh?.[1] }}<span>({{ listData.zdrBkZt ? '已布控' : '未布控' }})</span></div>
</div>
<div>车牌号码{{ listData.clHm }} <span>({{ listData.zdrBkZt ? '已布控' : '未布控' }})</span></div>
<div v-if="listData.clxxList">车牌号码
<span style="color: #000;" v-for="(item, index) in listData.clxxList" :key="index">{{ item.cph }}
<span v-if="index != listData.clxxList.length - 1"></span>
</span>
<span>({{ listData.zdrBkZt ? '已布控' : '未布控' }})</span>
</div>
</div>
</div>
@ -67,30 +74,28 @@ onMounted(() => {
}
&>:nth-child(1) {
width: 300px;
// width: 300px;
height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
&>:nth-child(2) {
width: 400px;
// width: 400px;
height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
// justify-content: space-between;
}
&>:nth-child(3) {
width: 210px;
// width: 210px;
height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
}
</style>

View File

@ -1,51 +1,41 @@
<template>
<div>
<div class="headClass" style="">
<h3>动态轨迹</h3>
<!-- <el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button> -->
</div>
<div class="headSelect">
<el-select v-model="value" placeholder="身份证号码" style="width: 100px">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="value" placeholder="请输入内容" style="width: 240px">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<div class="demo-datetime-picker">
<div class="block">
<el-date-picker v-model="value2" type="datetimerange" start-placeholder="Start date"
end-placeholder="End date" format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd"
time-format="A hh:mm:ss" />
</div>
</div>
<el-button type="primary" @click="check">查询</el-button>
<el-button @click="resetForm">重置</el-button>
</div>
<div class="mapBox">地图</div>
<div>
<div class="headClass" style="">
<h3>动态轨迹</h3>
</div>
<div class="headSelect">
<el-select v-model="listData.zjlx" placeholder="身份证号码" style="width: 240px">
<el-option v-for="item in D_BZ_ZJLX" :key="item.dm" :label="item.zdmc" :value="item.dm" />
</el-select>
<el-input v-model="listData.msg" placeholder="请输入证件号码" style="width: 300px" />
<div class="demo-datetime-picker">
<div class="block">
<el-date-picker v-model="listData.time" type="datetimerange" start-placeholder="开始时间"
end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd"/>
</div>
</div>
<el-button type="primary" @click="check">查询</el-button>
<el-button @click="resetForm">重置</el-button>
</div>
<div class="mapBox">
<GdMap />
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const value = ref('')
const options = [
{
value: '1',
label: '身份证号码',
},
{
value: '2',
label: '港澳台通行证',
},
{
value: 'Option3',
label: 'Option3',
},
]
import { ref, getCurrentInstance } from 'vue'
import GdMap from "@/components/GdMap/index.vue";
// import
const { proxy } = getCurrentInstance();
const { D_BZ_ZJLX } = proxy.$dict("D_BZ_ZJLX")
const listData= ref({})
const check = () => { }
const resetForm = () => {
listData.value = {}
}
</script>
<style lang="scss" scoped>
@ -53,60 +43,64 @@ const options = [
@import "~@/assets/css/element-plus.scss";
.backinfo-container {
padding: 10px;
padding: 10px;
}
::v-deep(.el-form) {
display: flex;
justify-content: space-between;
display: flex;
justify-content: space-between;
}
.left_box {
width: 200px;
border: 1px solid #c8c8c89a;
border-radius: 5px;
padding: 5px;
width: 200px;
border: 1px solid #c8c8c89a;
border-radius: 5px;
padding: 5px;
}
.right_box {
width: calc(100% - 230px);
overflow-y: auto;
padding: 5px;
width: calc(100% - 230px);
overflow-y: auto;
padding: 5px;
}
::v-deep .el-form-item__content {
display: block !important;
display: block !important;
}
::v-deep .el-range-input{
color: #000 !important;
}
.headClass {
font-size: 18px;
font-weight: 600;
color: #303133;
margin: 0 0 10px 0;
padding-bottom: 10px;
border-bottom: 2px solid #409eff;
position: relative;
font-size: 18px;
font-weight: 600;
color: #303133;
margin: 0 0 10px 0;
padding-bottom: 10px;
border-bottom: 2px solid #409eff;
position: relative;
}
.headSelect {
width: 100%;
margin: 20px 0;
padding:0 16px;
background-color: #fff;
border-bottom: 1px solid #eee;
display: flex;
align-items: baseline;
justify-content: space-between;
width: 100%;
margin: 20px 0;
padding: 0 16px;
background-color: #fff;
border-bottom: 1px solid #eee;
display: flex;
align-items: baseline;
justify-content: space-between;
}
.mapBox{
width: 100%;
height: 300px;
background-color: rgba(0, 123, 255, 0.5);
}
.mapBox {
width: 100%;
height: 300px;
position: relative;
background-color: rgba(0, 123, 255, 0.5);
}
h3 {
margin: 0;
margin: 0;
}
</style>
</style>

View File

@ -1,11 +1,11 @@
<template>
<div>
<div class="headClass">
<h3>群体背景信息</h3>
<h3>人员信息</h3>
<!-- @click="gettbGsxtZdqtUpdate" -->
<el-button type="primary" v-if="showBut" :disabled="disabled" @click="submit">保存</el-button>
</div>
<div class="form_cnt">
<div>
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" labelWidth="100px" ref="elform"
:rules="rules">
<template #ryzp>
@ -18,13 +18,13 @@
<div class="inputGroup" v-for="(item,index) in listQuery.ryLxdh" :key="index">
<el-input v-model="listQuery.ryLxdh[index]" class="group" placeholder="请输入电话号码" />
<div class="flex align-center but">
<el-button type="primary" :icon="Plus" circle @click="addPhone" title="添加电话号码" />
<el-button type="primary" :icon="Plus" circle @click="addPhone" title="添加电话号码" v-if=" listQuery.ryLxdh.length-1 ==index"/>
<el-button type="success" :icon="Minus" circle @click="removePhone(index)" title="删除电话号码" />
</div>
</div>
</div>
</template>
<template #tags>
<!-- <template #tags>
<div style="display: flex; align-items: center;">
<el-button type="primary" :disabled="disabled" @click="chooseMarksVisible = true">
选择标签
@ -33,12 +33,12 @@
已选择 {{ roleIds.length }} 个标签
</div>
</div>
</template>
</template> -->
</FormMessage>
</div>
</div>
<ChooseMarks v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" />
<!-- <ChooseMarks v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" /> -->
</template>
<script setup>
@ -50,8 +50,8 @@ import ChooseMarks from "@/components/ChooseList/ChooseMarks/index.vue";
import { ref, reactive, onMounted, getCurrentInstance, watch } from "vue";
import { tbGsxtZdryUpdate } from "@/api/zdr.js";
const { proxy } = getCurrentInstance();
const { D_BZ_XB, D_BZ_ZZMM, D_BZ_HYZK, D_BZ_MZ, D_BZ_XZQHDM, D_BZ_RCBKZT, D_GS_ZDR_RYJB, D_GS_ZDR_YJDJ, D_GS_BK_SSJZ, D_GS_ZDR_CZZT, D_BZ_WHCD, D_ZDRY_ZYLB } =
proxy.$dict('D_BZ_XB', 'D_BZ_ZZMM', 'D_BZ_HYZK', 'D_BZ_MZ', 'D_BZ_XZQHDM', 'D_BZ_RCBKZT', 'D_GS_ZDR_RYJB', 'D_GS_ZDR_YJDJ', 'D_GS_BK_SSJZ', 'D_GS_ZDR_CZZT', 'D_BZ_WHCD', 'D_ZDRY_ZYLB')
const { D_BZ_XB, D_BZ_ZZMM, D_BZ_HYZK, D_BZ_MZ, D_BZ_XZQHDM, D_ZDRY_RYLX,D_BZ_RCBKZT, D_GS_ZDR_RYJB, D_GS_ZDR_YJDJ, D_GS_BK_SSJZ, D_GS_ZDR_CZZT, D_BZ_WHCD, D_ZDRY_ZYLB } =
proxy.$dict('D_BZ_XB', 'D_BZ_ZZMM', 'D_BZ_HYZK', 'D_BZ_MZ', "D_ZDRY_RYLX",'D_BZ_XZQHDM', 'D_BZ_RCBKZT', 'D_GS_ZDR_RYJB', 'D_GS_ZDR_YJDJ', 'D_GS_BK_SSJZ', 'D_GS_ZDR_CZZT', 'D_BZ_WHCD', 'D_ZDRY_ZYLB')
const props = defineProps({
dataList: {
type: Object,
@ -77,7 +77,8 @@ const rules = reactive({
ryCsrq: [{ required: true, message: "请选择出生日期", trigger: "change" }],
ryJg: [{ required: true, message: "请选择籍贯", trigger: "change" }],
zdrRyjb: [{ required: true, message: "请选择人员级别", trigger: "change" }],
zdrYjdj: [{ required: true, message: "请选择预警等级", trigger: "change" }]
zdrYjdj: [{ required: true, message: "请选择预警等级", trigger: "change" }],
rylx: [{ required: true, message: "请选择人员类型", trigger: "change" }]
});
const listQuery = ref({ryLxdh:[""]}); //表单
const chooseMarksVisible = ref(false); // 控制标签选择弹窗显示
@ -110,11 +111,12 @@ const formData = ref([
{ label: "婚姻状态", prop: "hyzk", type: "select", options: D_BZ_HYZK },
{ label: "处置状态", prop: "zdrCzzt", type: "select", options: D_GS_ZDR_CZZT },
{ label: "布控状态", prop: "zdrBkZt", type: "select", options: D_BZ_RCBKZT },
{ label: "人员类型", prop: "rylx", type: "select", options: D_ZDRY_RYLX },
{ label: "入库开始时间", prop: "zdrRkkssj", type: "datetime" },
{ label: "入库结束时间", prop: "zdrRkjssj", type: "datetime" },
{ label: "Mac地址", prop: "macDz", type: "input" },
{ label: "联系电话", prop: "ryLxdh", type: "slot", width: "100%" },
{ label: "标签选择", prop: "tags", type: "slot", width: "100%" },
// { label: "标签选择", prop: "tags", type: "slot", width: "100%" },
{ label: "管控原因", prop: "zdrLkyy", type: "textarea", width: "100%" },
]);
const loading = ref(false);
@ -147,6 +149,7 @@ watch(() => props.dataList, (val) => {
listQuery.value = deepClone(val);
// 处理照片数据
listQuery.value.ryzp = val.ryzp == null || val.ryzp == '' ? [] : [val.ryzp];
listQuery.value.zdrSjjz = val.zdrSjjz == null || val.zdrSjjz == '' ? [] :JSON.parse(val.zdrSjjz);
// 处理标签ID数据确保数据回显
if (val.tagIds && Array.isArray(val.tagIds) && val.tagIds.length > 0) {
roleIds.value = [...val.tagIds];
@ -155,7 +158,6 @@ watch(() => props.dataList, (val) => {
} else {
roleIds.value = [];
}
// listQuery.value.ryLxdh =listQuery.value.ryLxdh.length>0?listQuery.value.ryLxdh:['11'];
}
}, { deep: true })
// 提交
@ -163,22 +165,13 @@ const submit = () => {
loading.value = true
gettbGsxtZdryUpdate()
};
// 处理标签选择结果
const choosed = (selectedTags) => {
// 存储选择的标签ID用于回显
roleIds.value = selectedTags.map(tag => tag.id);
// 这里可以根据实际需求处理选择的标签数据
};
//
const gettbGsxtZdryUpdate = () => {
const promes = {
...listQuery.value,
ryzp: listQuery.value.ryzp.length > 0 ? listQuery.value.ryzp.toString() : "",
ryLxdh: listQuery.value.ryLxdh,
tagIds: roleIds.value,
bqIds: roleIds.value,
zdrSjjz:JSON.stringify(listQuery.value.zdrSjjz),
}
tbGsxtZdryUpdate(promes).then((res) => {
@ -228,9 +221,8 @@ const throwData = () => {
resolve({
...listQuery.value,
ryzp: listQuery.value.ryzp && listQuery.value.ryzp.length > 0 ? listQuery.value.ryzp.toString() : '',
ryLxdh: JSON.stringify(validPhones),
tagIds: roleIds.value,
bqIds: roleIds.value
ryLxdh: validPhones,
zdrSjjz:JSON.stringify(listQuery.value.zdrSjjz),
});
} else {
reject(new Error('表单验证失败,请检查输入信息'));
@ -246,9 +238,8 @@ const throwData = () => {
resolve({
...listQuery.value,
ryzp: listQuery.value.ryzp && listQuery.value.ryzp.length > 0 ? listQuery.value.ryzp.toString() : '',
ryLxdh: JSON.stringify(validPhones),
tagIds: roleIds.value,
bqIds: roleIds.value
ryLxdh: validPhones,
zdrSjjz:JSON.stringify(listQuery.value.zdrSjjz),
});
}
});

View File

@ -2,7 +2,7 @@
<div>
<div class="headClass" style="">
<h3>关联车辆</h3>
<el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button>
<el-button type="primary" :disabled="disabled" @click="AddPore" v-if="showBut">选择</el-button>
</div>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
@ -30,7 +30,7 @@
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted, onUnmounted } from "vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import VehiclDoing from "../component/vehiclDoing.vue";
import { tbZdryClxxAdd, tbZdryClxxBatchAdd, tbZdryClxxDelete, tbZdryClxxSelectPage, tbZdryClxxUpdate } from '@/api/zdr.js'
import { tbZdryClxxAdd, tbZdryClxxDelete, tbZdryClxxSelectPage, tbZdryClxxUpdate } from '@/api/zdr.js'
import { ElMessage, ElMessageBox } from "element-plus";
const { proxy } = getCurrentInstance();
const { D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP } = proxy.$dict("D_BZ_CLLX", "D_BZ_CLYS", "D_BZ_CLPP"); //获取字典数据

View File

@ -2,24 +2,10 @@
<div>
<div class="headClass" style="">
<h3>走访记录</h3>
<!-- <el-button type="primary" :disabled="disabled" @click="AddPore">选择</el-button> -->
</div>
<div class="headSelect">
<el-button @click="add" type="primary">新增</el-button>
<el-button @click="AddPore" type="primary" v-if="showBut">新增</el-button>
</div>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #clys="{ row }">
<DictTag :tag="false" :value="row.clys" :options="D_BZ_CLYS" />
</template>
<template #cllx="{ row }">
<DictTag :tag="false" :value="row.cllx" :options="D_BZ_CLLX" />
</template>
<template #clpp="{ row }">
<DictTag :tag="false" :value="row.clpp" :options="D_BZ_CLPP" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link type="danger" @click="delDictItem(row.id)">删除</el-link>
@ -27,24 +13,21 @@
</template>
</MyTable>
</div>
<VehiclDoing v-model="chooseMarksVisible" @comfirm="addMarks" :data="dataModel"
:dict="{ D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP }" />
<InterLoding v-model="chooseMarksVisible" @comfirm="addMarks" :data="dataModel" />
</template>
<script setup>
import { identityCardRule } from "@/utils/rules"
import { ref, reactive, watch, toRaw, getCurrentInstance, onMounted, onUnmounted } from "vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import VehiclDoing from "../component/vehiclDoing.vue";
import { tbZdryClxxAdd, tbZdryClxxBatchAdd, tbZdryClxxDelete, tbGsxtZdryZfjlselectZfjl, tbZdryClxxUpdate } from '@/api/zdr.js'
import InterLoding from "../component/interLoding.vue";
import { tbGsxtZdryZfjlsaveOrUpdateZfjl,tbGsxtZdryZfjlselectZfjl,tbGsxtZdryZfjl } from '@/api/zdr.js'
import { ElMessage, ElMessageBox } from "element-plus";
const { proxy } = getCurrentInstance();
const { D_BZ_CLLX, D_BZ_CLYS, D_BZ_CLPP } = proxy.$dict("D_BZ_CLLX", "D_BZ_CLYS", "D_BZ_CLPP"); //获取字典数据
const chooseMarksVisible = ref(false)
const props = defineProps({
dataList: {
type: Object,
default: () => { },
default: () => {},
}, disabled: {
type: Boolean,
default: false
@ -58,9 +41,7 @@ const listData = ref({})
const addUpd = ref(true)
watch(() => props.dataList, (val) => {
if (val) {
listData.value = val
listData.value = {...val}
gettbZdryClxxSelectPage()
}
}, { deep: true })
@ -68,26 +49,21 @@ watch(() => props.dataList, (val) => {
const pageData = reactive({
tableData: [],
tableColumn: [{
prop: 'cph',
prop: 'zfmjXm',
width: 150,
label: '走访民警/辅警',
label: '走访民警',
}, {
prop: 'cllx',
prop: 'zffs',
label: '走访方式',
showSolt: true,
prop: 'clpp',
}, {
showSolt: true,
prop: 'clys',
prop: 'zfsj',
label: '走访时间',
}, {
showSolt: true,
prop: 'clpp',
prop: 'zfdz',
label: '走访地址',
},
{
showSolt: true,
prop: 'clpp',
prop: 'zfqk',
label: '走访情况',
}],
tableHeight: '200px',
@ -105,51 +81,39 @@ const pageData = reactive({
},
controlsWidth: 200,
})
// 表单数据
const formData = reactive({
username: "",
ID: ""
})
const rulesForm = ref(identityCardRule({ validator: true }, 'rySfzh'))
// 修改数据接口
const dataModel = ref()
const addMarks = (val) => {
const params = {
...val,
zdrid: listData.value.id,
zdryId: listData.value.id,
}
if (props.showBut && !props.disabled) {
if (addUpd.value) {
tbZdryClxxAdd(params).then(res => {
tbGsxtZdryZfjlsaveOrUpdateZfjl(params).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆添加成功',
message: '走访记录添加成功',
type: 'success'
})
})
}
else {
tbZdryClxxUpdate(params).then(res => {
tbGsxtZdryZfjlsaveOrUpdateZfjl(params).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆修改成功',
message: '走访记录修改成功',
type: 'success'
})
})
}
} else {
pageData.tableData.push(val)
}
}
onMounted(() => {
})
// 删除车辆
// 删除走访记录
const delDictItem = (val) => {
if (!props.disabled && props.showBut) {
ElMessageBox.confirm(
'是否删除关联车辆',
'是否删除走访记录',
'提示',
{
confirmButtonText: '确认',
@ -158,10 +122,10 @@ const delDictItem = (val) => {
}
)
.then(() => {
tbZdryClxxDelete({ ids: [val] }).then(res => {
tbGsxtZdryZfjl(val).then(res => {
gettbZdryClxxSelectPage()
proxy.$message({
message: '关联车辆删除成功',
message: '走访记录删除成功',
type: 'success'
})
})
@ -188,11 +152,9 @@ const AddPore = () => {
dataModel.value = {}
addUpd.value = true
}
// 查询车辆
// 查询走访记录
const gettbZdryClxxSelectPage = () => {
const promes = {
pageCurrent: 1,
pageSize: 20,
zdrid: listData.value.id
}
tbGsxtZdryZfjlselectZfjl(promes).then(res => {
@ -203,10 +165,6 @@ const gettbZdryClxxSelectPage = () => {
// 抛出数据并验证标签列表不为空
const throwData = () => {
return new Promise((resolve) => {
// // 验证:确保标签列表不为空
// if (!pageData.tableData || pageData.tableData.length === 0) {
// throw new Error('请录入车辆信息');
// }
resolve(pageData.tableData);
});
}
@ -246,13 +204,16 @@ defineExpose({
}
.headClass {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
font-weight: 600;
color: #303133;
margin: 20px 0 10px 0;
padding-bottom: 10px;
border-bottom: 2px solid #409eff;
position: relative;
}

View File

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

View File

@ -0,0 +1,37 @@
<template>
<div>
<YpHome v-if="showModel == '研判首页'" @change="changeModel"></YpHome>
<YjList v-if="showModel == '态势预警列表'" :item="itemYj" @change="changeModel"></YjList>
<YjDetail v-if="showModel == '预警详情'" :item="itemDetail" @change="changeModel"></YjDetail>
</div>
</template>
<script setup>
import YpHome from "./components/ypHome.vue";
import YjList from "./components/yjList.vue";
import YjDetail from "./components/yjDetail.vue";
import { onMounted, ref } from "vue";
const showModel = ref('研判首页')
const itemYj = ref({})
const itemDetail = ref({})
onMounted(()=>{
// route.query.id ? lookDeatl(route.query.id): getLits();
})
function changeModel(val){
showModel.value = val.type ;
if(val.data){
if(val.type == '态势预警列表'){
itemYj.value = val.data
}else if(val.type == '预警详情'){
itemDetail.value = val.data
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,417 @@
<template>
<!-- 研判类型 -->
<div class="content">
<div class="btnsBox" ref="refBtn">
<CheckBox :data="checkData.yplxBtn" @changeData="changeData_yplx"></CheckBox>
</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="cntItem" @click.stop="lookDeatl(it)" v-for="(it, idx) in list" :key="idx">
<div class="ww100"><img class="ww100" style="height: 168px;" src="@/assets/images/mxbg.jpg" alt=""></div>
<div class="f14 lh24 pl4 pr4 one_text_detail">名称{{ it.ypMc }}</div>
<div class="flex ww100 f14 lh24 pl4 pr4 one_text_detail">类型
<DictTag :value="it.ypLx" :tag="false" :options="D_SG_TSYPGZ" />
</div>
<div class="f14 lh24 pl4 pr4 one_text_detail">数量{{ it.num }}</div>
<div class="foot">
<span class="ml10 pointer" @click.stop="openHistoricalReport(it.id)" style="color:#027ff0 ;"><el-icon style="top: 2px;"><Document /></el-icon>历史报告</span>
<span class="ml10 pointer" @click.stop="funAll(it.id)" style="color:#027ff0 ;"><el-icon style="top: 2px;"><Document /></el-icon>报告</span>
<span class="ml10 pointer" @click="handleHs(it)" style="color:#f4ac47 ;"><el-icon style="top: 2px;"><Files /></el-icon>会商</span>
</div>
</li>
<div class="ww100 flex just-center">
<MOSTY.Empty :show="!loading && list.length <= 0"></MOSTY.Empty>
</div>
<div class="tc ww100 mb4" style="color: #a29f9f;" v-if="total == list.length && total > 0">暂时没有数据了</div>
</ul>
</div>
<YpModel v-model="showModel" @SaveReport="SaveReport" :heightNumber="436" v-model:textContent="textContent"></YpModel>
<HistoricalReport v-model="showHistoricalReport" @choosed="getHistory" :chageData="chageData"/>
</template>
<script setup>
import CheckBox from '@/components/checkBox/index.vue'
import YpModel from '@/components/ypModel/index.vue'
import HistoricalReport from './historicalReport.vue'
import * as MOSTY from "@/components/MyComponents/index";
import Search from "@/components/aboutTable/Search.vue";
import { qcckPost } from "@/api/qcckApi.js";
import { timeValidate } from '@/utils/tools.js'
import { getItem } from '@/utils/storage.js'
import { useRoute, useRouter } from 'vue-router';
import { reactive, ref, onMounted, getCurrentInstance, watch, defineEmits } from "vue";
import { jqypDywdtj, jqypfxbgJqlxtj, jqypfxbgYdfx, jqypfxbgJqlytj, jqypfxbgTj, jqypfxbgCljgf, jqypfxbgCzlfx, getDictItem } from '@/api/semanticAnalysis'
import { textStyle, Firstlevelheading, Subheading, BiheadlinegTitle, BigTitle, headTitle, report, signature } from './content.js'
import { ElMessage, ElMessageBox } from 'element-plus'
const router = useRouter();
const { proxy } = getCurrentInstance();
const emit = defineEmits(['change'])
const { D_SG_SJLY, D_SG_TSYPGZ, JQLB, JQLX, JQXL, JQZL, D_BZ_JQLY, D_BZ_JQFL, JQCLJG } = proxy.$dict("D_SG_SJLY", "D_SG_TSYPGZ", "JQLB", "JQLX", "JQXL", "JQZL", "D_BZ_JQLY", "D_BZ_JQFL", "JQCLJG"); //获取字典数据
const searchBox = ref(); //搜索框
const showModel = ref(false);
const textContent = ref('');
const refBtn = ref();
const show = ref(false)
const listHeight = ref()
const searchConfiger = ref([
{ label: "研判名称", prop: "ypMc", placeholder: "请输入研判名称", showType: "input" },
]);
const checkData = reactive({
yplxBtn: {
hasChoose: [],
list: []
},
});
const page = ref(1);
const total = ref(0)
const list = ref([])
const loading = ref(false);
const formData = ref({})
const chageData=ref()
watch(() => D_SG_TSYPGZ.value, val => {
checkData.yplxBtn.list = val.map(v => v.zdmc);
checkData.yplxBtn.hasChoose = val.map(v => v.zdmc);
}, { immediate: true, deep: true });
onMounted(() => {
show.value = true;
Time()
tabHeightFn();
getLits()
})
// 研判类型
const changeData_yplx = (val) => {
checkData.yplxBtn.hasChoose = val;
let dms = [];
D_SG_TSYPGZ.value.forEach(item => {
if (val.includes(item.zdmc)) dms.push(item.dm);
});
formData.value.ypLx = dms;
page.value = 1;
getLits();
}
const onSearch = (val) => {
formData.value = { ...formData.value, ...val, };
page.value = 1;
getLits();
}
const load = () => {
if (total.value == list.value.length) return;
page.value++;
getLits();
}
const getLits = () => {
let params = {
pageCurrent: page.value,
pageSize: 8,
...formData.value
}
loading.value = true;
qcckPost(params, '/mosty-gsxt/tsyp/selectPage').then(res => {
let arr = res.records || [];
list.value = page.value == 1 ? arr : list.value.concat(arr);
total.value = res.total;
loading.value = false;
}).catch(() => {
loading.value = false;
})
}
const handleHs = (val) => {
router.push({ path: '/MeetingRoom', query: { tsypid: val.id } })
}
// 查看详情
const lookDeatl = (val) => {
emit('change', { data:val, type:'态势预警列表' })
}
// 表格高度计算
const tabHeightFn = () => {
listHeight.value = window.innerHeight - searchBox.value.offsetHeight - refBtn.value.offsetHeight - 182;
window.onresize = function () {
tabHeightFn();
};
};
const dataList = reactive({
dyTj: {
xAxisData: [],
seriesData: [],
},
jqlxTj: [],
jqlyTj: [],
CljgfTj: [],
XsfxTj: [],
})
const sortingRatioValue = ref({
jqlx: "",
jqly: "",
dywd: "",
ydfx: "",
xlwdfx: "",
czjgfx: "",
})
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 pageData = reactive({
parameter: { bjlbList: '' }
})
const getDictItemList = () => {
const promes = {
dictCode: "00000000"
}
getDictItem(promes).then(res => {
pageData.parameter.bjlbList = res.map(item => item.dm).join(',')
console.log(pageData.parameter.bjlbList);
})
}
getDictItemList()
const funAll = (val) => {
const dev = getItem('deptId')[0]
sortingRatioValue.value = {}
textContent.value = BigTitle(`${endYears.value}年度西藏公安执法数据分析`) + headTitle({
orgName: dev.deptName,
serialNumber: timeValidate("", "mm"),
time: timeValidate(),
})
const data = `为全面、客观、准确掌握全区公安机关的执法状况,自治区公安厅基于数据统计,对全区公安机关${endYears.value}年度的执法状况作了客观分析。`
textContent.value += BiheadlinegTitle('1.接处警情况') + textStyle(data) + Firstlevelheading('一、执法状况总体分析')
getfxbgYdfx(val)
getfxbgTj(val)
getfxbgJqlxtj(val)
getfxbgJqlytj(val)
getfxbgDywdtj(val)
getfxgbCljgf(val)
getfxgbCzlfx(val)
showModel.value = true;
}
watch(() => sortingRatioValue.value, (val) => {
if (val.jqlx && val.jqly && val.dywd && val.ydfx && val.xlwdfx && val.czjgfx) {
textContent.value += val.jqlx + val.jqly + val.dywd + val.ydfx + val.xlwdfx + val.czjgfx + report() + signature()
}
}, { deep: true })
const getfxbgTj = (val) => {
jqypfxbgTj({ ypid: val }).then(res => {
const data = `${Time()} ,全区公安机关共接报各类警情${res.total}起,同比上升 ${res.tbbsb}%,同比上升${res.hbbsb}%`
textContent.value += BiheadlinegTitle('1.1接报警情') + textStyle(data)
dataList.XsfxTj = res
})
}
// 警情类型统计
const getfxbgJqlxtj = (val) => {
let params = {
...pageData.parameter,
ypid: val
}
jqypfxbgJqlxtj(params).then(res => {
const model = sortingRatio(res)
const data = `按警情类型来看,${model[0].name}最多,占到${model[0].ratio};其次为${model[1].name}最多,占到${model[1].ratio}`
sortingRatioValue.value.jqlx = Subheading('1.1.1类型维度') + textStyle(data)
})
}
// 警情来源统计
const getfxbgJqlytj = (val) => {
jqypfxbgJqlytj({ ypid: val }).then(res => {
const model = sortingRatio(res)
const data = `按警情来源来看,${model[0].name}最多,占到${model[0].ratio};其次为${model[1].name}最多,占到${model[1].ratio}`
sortingRatioValue.value.jqly = Subheading('1.1.2来源维度') + textStyle(data)
})
}
// 地域统计
const getfxbgDywdtj = (val) => {
jqypDywdtj({ ypid: val }).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
}
const model = sortingRatio(res)
let data
if (model.length > 1) {
data = `从地市分布地市来看,${model[0].ssbm}警情量最大,占到全区警情总量的${model[0].number}。其次为${model[1].ssbm}${model[2].ssbm},两市警情量较为接近。警情量最少的为${model[model.length - 1].ssbm}`
} else {
data = `从地市分布地市来看,${model[0].ssbm}警情量最大,占到全区警情总量的${model[0].number}`
}
sortingRatioValue.value.dywd = Subheading('1.1.3地域维度') + textStyle(data)
})
}
//分析报告-时间维度-月分析
const getfxbgYdfx = (val) => {
jqypfxbgYdfx({ ypid: val }).then(res => {
const model = sortingRatio(res)
const data = `我们将所有警情按照月份划分进行统计发现,每月警情分布较为平均。最高月份为${model[0].month}月,占到${model[0].number};最低月份为${model[res.length - 1].month}月,占到${model[res.length - 1].number}。考虑是因为${model[0].month}月为我区传统旅游旺季,进藏人员较多。 ${model[res.length - 1].month}月一般春节及藏历新年期间,在藏人员较少。`
sortingRatioValue.value.ydfx = Subheading('1.1.4时间维度') + textStyle(data)
})
}
// 分析报告-处理结果分析
const getfxgbCljgf = (val) => {
jqypfxbgCljgf({ ypid: val }).then(res => {
// sortingRatioValue.Cljgf =
const model = sortingRatio(res)
let czjgfx = `从警情处置结果来看,`
model.forEach(item => {
czjgfx += `${item.name},占到${item.ratio};`
})
sortingRatioValue.value.xlwdfx = BiheadlinegTitle('1.2警情处置') + Firstlevelheading('1.2.1结果维度') + textStyle(czjgfx)
})
}
// 分析报告-处置率分析
const getfxgbCzlfx = (val) => {
jqypfxbgCzlfx({ ypid: val }).then(res => {
dataList.withinTj = [{
name: "超时分流(超过24小时)",
value: res.within24h ? res.within24h : 0
}, {
name: "按时分流(24小时内)",
value: res.over24h ? res.over24h : 0
}]
const data = `从处警效率来看24小时以内处警的占到${res.over24h}%。表明我区公安机关在接警之后能够在第一时间处警。`
sortingRatioValue.value.czjgfx = Subheading('1.2.2效率维度') + textStyle(data)
})
}
const timeDate = ref()
const endYears = ref()
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');
timeDate.value = `${endYear}${endMonth}${endDay}`
endYears.value = year
return `${year}${month}${day}日 至${endYear}${endMonth}${endDay}`
}
const showHistoricalReport = ref(false)
const openHistoricalReport = (val) => {
chageData.value = val
showHistoricalReport.value = true
}
// const
const getHistory = (val) => {
textContent.value = val
showHistoricalReport.value = false
showModel.value = true
}
const SaveReport = (val) => {
ElMessageBox.prompt('请输入名称', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
// inputPattern:/[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
// inputErrorMessage: 'Invalid Email',
})
.then(({ value }) => {
const promes = {
bgmc:value,
bgnr: val,
ypid:chageData.value
}
qcckPost( promes , "/mosty-gsxt/gsxtYpbg/addEntity")
.then(() => {
ElMessage.success("保存成功");
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消保存',
})
})
.catch(() => { });
}
</script>
<style lang="scss" scoped>
.content {
width: 100%;
height: 100%;
margin-top: 20px;
margin-left: 10px;
border-radius: 4px;
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: 18px;
overflow: hidden;
overflow-y: auto;
background: #fff;
padding: 4px;
box-sizing: border-box;
.cntItem {
width: 300px;
border: 1px solid #ccc;
color: #787878;
border-radius: 4px;
overflow: hidden;
.foot {
text-align: right;
margin-top: 4px;
border-top: 1px solid #ccc;
padding: 4px;
box-sizing: border-box;
}
}
}
}
</style>

View File

@ -0,0 +1,53 @@
<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">
</FormMessage>
</div>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
const dialogForm = ref(false)
const title=ref("新增")
const init = (type,row) => {
dialogForm.value = true
if (type=='edit') {
title.value="编辑"
} else if (type=='add') {
title.value="新增"
} else {
title.value="详情"
}
}
// 表单内容
const formData = reactive([
{ label: "模型名称", prop: "mxmc", type: "input", width: "40%" },
{ label: "模型类型", prop: "mxlx", type: "input", width: "40%"},
])
const loading=ref(false)
// 新增
const submit = () => {
loading.value = true
}
// 关闭
const close = () => {
dialogForm.value = false
}
defineExpose({
init
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,67 @@
<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">
<VueDraggable @update="onUpdate"
@add="onAdd"
@remove="remove">
<el-button type="primary" v-for="(item,index) in listBut" :key="index">{{ item }}</el-button>
</VueDraggable>
<VueDraggable>
<el-button type="primary" v-for="(item,index) in listBut" :key="index">{{ item }}</el-button>
</VueDraggable>
</div>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
// import { VueDraggable } from 'vue-draggable-plus'
const dialogForm = ref(false)
const title = ref("新增")
const init = (type, row) => {
dialogForm.value = true
if (type == 'edit') {
title.value = "编辑"
} else if (type == 'add') {
title.value = "新增"
} else {
title.value = "详情"
}
}
const loading = ref(false)
// 新增
const submit = () => {
loading.value = true
}
const listBut = ref(["物品", "人员", "组织", "次数", "事件", "地点", "整情"])
// 关闭
const close = () => {
dialogForm.value = false
}
const onUpdate = (evt) => {
console.log(evt)
}
// 新增
const onAdd = (evt) => {
console.log(evt)
}
// 删除
const remove = (evt) => {
console.log(evt)
}
defineExpose({
init
})
</script>
<style lang="scss" scoped></style>

View File

@ -1,124 +1,94 @@
<template>
<!-- 研判类型 -->
<div class="content">
<div class="btnsBox" ref="refBtn">
<CheckBox :data="checkData.yplxBtn" @changeData="changeData_yplx"></CheckBox>
</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="cntItem" @click.stop="lookDeatl(it)" v-for="(it, idx) in list" :key="idx">
<div class="ww100"><img class="ww100" style="height: 168px;" src="@/assets/images/mxbg.jpg" alt=""></div>
<div class="f14 lh24 pl4 pr4 one_text_detail">名称{{ it.ypMc }}</div>
<div class="flex ww100 f14 lh24 pl4 pr4 one_text_detail">类型
<DictTag :value="it.ypLx" :tag="false" :options="D_SG_TSYPGZ" />
</div>
<div class="f14 lh24 pl4 pr4 one_text_detail">数量{{ it.num }}</div>
<div class="foot">
<span class="ml10 pointer" @click.stop="openHistoricalReport(it.id)" style="color:#027ff0 ;"><el-icon style="top: 2px;"><Document /></el-icon>历史报告</span>
<span class="ml10 pointer" @click.stop="funAll(it.id)" style="color:#027ff0 ;"><el-icon style="top: 2px;"><Document /></el-icon>报告</span>
<span class="ml10 pointer" @click="handleHs(it)" style="color:#f4ac47 ;"><el-icon style="top: 2px;"><Files /></el-icon>会商</span>
</div>
</li>
<div class="ww100 flex just-center">
<MOSTY.Empty :show="!loading && list.length <= 0"></MOSTY.Empty>
</div>
<div class="tc ww100 mb4" style="color: #a29f9f;" v-if="total == list.length && total > 0">暂时没有数据了</div>
</ul>
<!-- 研判类型 -->
<div class="content">
<div class="titleBox">
<PageTitle title="模型平台">
<el-button type="primary" @click="openAddModel('add')" :icon="CirclePlus">
新增模型
</el-button>
</PageTitle>
</div>
<YpModel v-model="showModel" @SaveReport="SaveReport" :heightNumber="436" v-model:textContent="textContent"></YpModel>
<HistoricalReport v-model="showHistoricalReport" @choosed="getHistory" :chageData="chageData"/>
<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="cntItem" v-for="(it, idx) in 10" :key="idx">
<div class="ww100" @click.stop="openAddModel('detail', it)"><img class="ww100" style="height: 168px;" src="@/assets/images/mxbg.jpg" alt=""></div>
<div class="foot">
<span class="ml10 pointer" style="color:#027ff0 ;" @click="openAddRule"><el-icon style="top: 2px;">
<Document />
</el-icon>查看规则</span>
<span class="ml10 pointer" style="color:#027ff0 ;" @click="openAddModel('edit', it)"><el-icon
style="top: 2px;">
<Edit />
</el-icon>编辑</span>
<span class="ml10 pointer" style="color:#f4ac47 ;"><el-icon style="top: 2px;">
<Files />
</el-icon>删除</span>
</div>
</li>
<div class="ww100 flex just-center">
<MOSTY.Empty :show="!loading && list.length <= 0"></MOSTY.Empty>
</div>
<div class="tc ww100 mb4" style="color: #a29f9f;" v-if="total == list.length && total > 0">暂时没有数据了</div>
</ul>
</div>
<AddModel ref="addModel" />
<Regulation ref="regulation" />
</template>
<script setup>
import CheckBox from '@/components/checkBox/index.vue'
import YpModel from '@/components/ypModel/index.vue'
import HistoricalReport from './historicalReport.vue'
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import { CirclePlus } from '@element-plus/icons-vue'
import * as MOSTY from "@/components/MyComponents/index";
import Search from "@/components/aboutTable/Search.vue";
import { qcckPost } from "@/api/qcckApi.js";
import { timeValidate } from '@/utils/tools.js'
import { getItem } from '@/utils/storage.js'
import { useRoute, useRouter } from 'vue-router';
import { reactive, ref, onMounted, getCurrentInstance, watch, defineEmits } from "vue";
import { jqypDywdtj, jqypfxbgJqlxtj, jqypfxbgYdfx, jqypfxbgJqlytj, jqypfxbgTj, jqypfxbgCljgf, jqypfxbgCzlfx, getDictItem } from '@/api/semanticAnalysis'
import { textStyle, Firstlevelheading, Subheading, BiheadlinegTitle, BigTitle, headTitle, report, signature } from './content.js'
import { ElMessage, ElMessageBox } from 'element-plus'
const router = useRouter();
const { proxy } = getCurrentInstance();
import AddModel from "./addModel.vue";
import Regulation from "./regulation.vue";
const emit = defineEmits(['change'])
const { D_SG_SJLY, D_SG_TSYPGZ, JQLB, JQLX, JQXL, JQZL, D_BZ_JQLY, D_BZ_JQFL, JQCLJG } = proxy.$dict("D_SG_SJLY", "D_SG_TSYPGZ", "JQLB", "JQLX", "JQXL", "JQZL", "D_BZ_JQLY", "D_BZ_JQFL", "JQCLJG"); //获取字典数据
const searchBox = ref(); //搜索框
const showModel = ref(false);
const textContent = ref('');
const refBtn = ref();
const show = ref(false)
const listHeight = ref()
const searchConfiger = ref([
{ label: "研判名称", prop: "ypMc", placeholder: "请输入研判名称", showType: "input" },
{ label: "模型名称", prop: "ypMc", placeholder: "请输入模型名称", showType: "input" },
{ label: "模型类型", prop: "ypLx", placeholder: "请输入模型类型", showType: "input" },
]);
const checkData = reactive({
yplxBtn: {
hasChoose: [],
list: []
},
const PaginationConfig = reactive({
pageCurrent: 1,
pageSize: 8,
});
const page = ref(1);
const total = ref(0)
const list = ref([])
const loading = ref(false);
const formData = ref({})
const chageData=ref()
watch(() => D_SG_TSYPGZ.value, val => {
checkData.yplxBtn.list = val.map(v => v.zdmc);
checkData.yplxBtn.hasChoose = val.map(v => v.zdmc);
}, { immediate: true, deep: true });
onMounted(() => {
show.value = true;
Time()
tabHeightFn();
getLits()
})
// 研判类型
const changeData_yplx = (val) => {
checkData.yplxBtn.hasChoose = val;
let dms = [];
D_SG_TSYPGZ.value.forEach(item => {
if (val.includes(item.zdmc)) dms.push(item.dm);
});
formData.value.ypLx = dms;
page.value = 1;
getLits();
}
const onSearch = (val) => {
formData.value = { ...formData.value, ...val, };
page.value = 1;
PaginationConfig.pageCurrent = 1;
getLits();
}
const load = () => {
if (total.value == list.value.length) return;
page.value++;
getLits();
PaginationConfig.pageCurrent++;
// getLits();
}
const getLits = () => {
let params = {
pageCurrent: page.value,
pageSize: 8,
...PaginationConfig,
...formData.value
}
loading.value = true;
qcckPost(params, '/mosty-gsxt/tsyp/selectPage').then(res => {
let arr = res.records || [];
list.value = page.value == 1 ? arr : list.value.concat(arr);
list.value = PaginationConfig.pageCurrent == 1 ? arr : list.value.concat(arr);
total.value = res.total;
loading.value = false;
}).catch(() => {
@ -126,292 +96,71 @@ const getLits = () => {
})
}
const handleHs = (val) => {
router.push({ path: '/MeetingRoom', query: { tsypid: val.id } })
}
// 查看详情
const lookDeatl = (val) => {
emit('change', { data:val, type:'态势预警列表' })
}
// 表格高度计算
const tabHeightFn = () => {
listHeight.value = window.innerHeight - searchBox.value.offsetHeight - refBtn.value.offsetHeight - 182;
listHeight.value = window.innerHeight - searchBox.value.offsetHeight - 230;
window.onresize = function () {
tabHeightFn();
};
};
const dataList = reactive({
dyTj: {
xAxisData: [],
seriesData: [],
},
jqlxTj: [],
jqlyTj: [],
CljgfTj: [],
XsfxTj: [],
})
const sortingRatioValue = ref({
jqlx: "",
jqly: "",
dywd: "",
ydfx: "",
xlwdfx: "",
czjgfx: "",
})
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 addModel = ref(null)
const openAddModel = (type, row) => {
addModel.value.init(type, row)
}
const pageData = reactive({
parameter: { bjlbList: '' }
})
const getDictItemList = () => {
const promes = {
dictCode: "00000000"
}
getDictItem(promes).then(res => {
pageData.parameter.bjlbList = res.map(item => item.dm).join(',')
console.log(pageData.parameter.bjlbList);
})
}
getDictItemList()
const funAll = (val) => {
const dev = getItem('deptId')[0]
sortingRatioValue.value = {}
textContent.value = BigTitle(`${endYears.value}年度西藏公安执法数据分析`) + headTitle({
orgName: dev.deptName,
serialNumber: timeValidate("", "mm"),
time: timeValidate(),
})
const data = `为全面、客观、准确掌握全区公安机关的执法状况,自治区公安厅基于数据统计,对全区公安机关${endYears.value}年度的执法状况作了客观分析。`
textContent.value += BiheadlinegTitle('1.接处警情况') + textStyle(data) + Firstlevelheading('一、执法状况总体分析')
getfxbgYdfx(val)
getfxbgTj(val)
getfxbgJqlxtj(val)
getfxbgJqlytj(val)
getfxbgDywdtj(val)
getfxgbCljgf(val)
getfxgbCzlfx(val)
showModel.value = true;
}
watch(() => sortingRatioValue.value, (val) => {
if (val.jqlx && val.jqly && val.dywd && val.ydfx && val.xlwdfx && val.czjgfx) {
textContent.value += val.jqlx + val.jqly + val.dywd + val.ydfx + val.xlwdfx + val.czjgfx + report() + signature()
}
}, { deep: true })
const getfxbgTj = (val) => {
jqypfxbgTj({ ypid: val }).then(res => {
const data = `${Time()} ,全区公安机关共接报各类警情${res.total}起,同比上升 ${res.tbbsb}%,同比上升${res.hbbsb}%`
textContent.value += BiheadlinegTitle('1.1接报警情') + textStyle(data)
dataList.XsfxTj = res
})
}
// 警情类型统计
const getfxbgJqlxtj = (val) => {
let params = {
...pageData.parameter,
ypid: val
}
jqypfxbgJqlxtj(params).then(res => {
const model = sortingRatio(res)
const data = `按警情类型来看,${model[0].name}最多,占到${model[0].ratio};其次为${model[1].name}最多,占到${model[1].ratio}`
sortingRatioValue.value.jqlx = Subheading('1.1.1类型维度') + textStyle(data)
})
}
// 警情来源统计
const getfxbgJqlytj = (val) => {
jqypfxbgJqlytj({ ypid: val }).then(res => {
const model = sortingRatio(res)
const data = `按警情来源来看,${model[0].name}最多,占到${model[0].ratio};其次为${model[1].name}最多,占到${model[1].ratio}`
sortingRatioValue.value.jqly = Subheading('1.1.2来源维度') + textStyle(data)
})
}
// 地域统计
const getfxbgDywdtj = (val) => {
jqypDywdtj({ ypid: val }).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
}
const model = sortingRatio(res)
let data
if (model.length > 1) {
data = `从地市分布地市来看,${model[0].ssbm}警情量最大,占到全区警情总量的${model[0].number}。其次为${model[1].ssbm}${model[2].ssbm},两市警情量较为接近。警情量最少的为${model[model.length - 1].ssbm}`
} else {
data = `从地市分布地市来看,${model[0].ssbm}警情量最大,占到全区警情总量的${model[0].number}`
}
sortingRatioValue.value.dywd = Subheading('1.1.3地域维度') + textStyle(data)
})
}
//分析报告-时间维度-月分析
const getfxbgYdfx = (val) => {
jqypfxbgYdfx({ ypid: val }).then(res => {
const model = sortingRatio(res)
const data = `我们将所有警情按照月份划分进行统计发现,每月警情分布较为平均。最高月份为${model[0].month}月,占到${model[0].number};最低月份为${model[res.length - 1].month}月,占到${model[res.length - 1].number}。考虑是因为${model[0].month}月为我区传统旅游旺季,进藏人员较多。 ${model[res.length - 1].month}月一般春节及藏历新年期间,在藏人员较少。`
sortingRatioValue.value.ydfx = Subheading('1.1.4时间维度') + textStyle(data)
})
}
// 分析报告-处理结果分析
const getfxgbCljgf = (val) => {
jqypfxbgCljgf({ ypid: val }).then(res => {
// sortingRatioValue.Cljgf =
const model = sortingRatio(res)
let czjgfx = `从警情处置结果来看,`
model.forEach(item => {
czjgfx += `${item.name},占到${item.ratio};`
})
sortingRatioValue.value.xlwdfx = BiheadlinegTitle('1.2警情处置') + Firstlevelheading('1.2.1结果维度') + textStyle(czjgfx)
})
}
// 分析报告-处置率分析
const getfxgbCzlfx = (val) => {
jqypfxbgCzlfx({ ypid: val }).then(res => {
dataList.withinTj = [{
name: "超时分流(超过24小时)",
value: res.within24h ? res.within24h : 0
}, {
name: "按时分流(24小时内)",
value: res.over24h ? res.over24h : 0
}]
const data = `从处警效率来看24小时以内处警的占到${res.over24h}%。表明我区公安机关在接警之后能够在第一时间处警。`
sortingRatioValue.value.czjgfx = Subheading('1.2.2效率维度') + textStyle(data)
})
}
const timeDate = ref()
const endYears = ref()
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');
timeDate.value = `${endYear}${endMonth}${endDay}`
endYears.value = year
return `${year}${month}${day}日 至${endYear}${endMonth}${endDay}`
}
const showHistoricalReport = ref(false)
const openHistoricalReport = (val) => {
chageData.value = val
showHistoricalReport.value = true
}
// const
const getHistory = (val) => {
textContent.value = val
showHistoricalReport.value = false
showModel.value = true
}
const SaveReport = (val) => {
ElMessageBox.prompt('请输入名称', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
// inputPattern:/[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
// inputErrorMessage: 'Invalid Email',
})
.then(({ value }) => {
const promes = {
bgmc:value,
bgnr: val,
ypid:chageData.value
}
qcckPost( promes , "/mosty-gsxt/gsxtYpbg/addEntity")
.then(() => {
ElMessage.success("保存成功");
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消保存',
})
})
.catch(() => { });
// 打开规则弹窗
const regulation = ref(null)
const openAddRule = (type, row) => {
regulation.value.init(type, row)
}
</script>
<style lang="scss" scoped>
.content {
width: 100%;
height: 100%;
margin-top: 20px;
margin-left: 10px;
width: 100%;
height: 100%;
margin-top: 20px;
margin-left: 10px;
border-radius: 4px;
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: 18px;
overflow: hidden;
overflow-y: auto;
background: #fff;
padding: 4px;
box-sizing: border-box;
.btnsBox {
background: #fff;
padding: 10px 5px;
.cntItem {
width: 300px;
border: 1px solid #ccc;
color: #787878;
border-radius: 4px;
margin-bottom: 10px;
}
.cntlsit {
display: flex;
flex-wrap: wrap;
align-content: start;
gap: 18px;
overflow: hidden;
overflow-y: auto;
background: #fff;
padding: 4px;
box-sizing: border-box;
.cntItem {
width: 300px;
border: 1px solid #ccc;
color: #787878;
border-radius: 4px;
overflow: hidden;
.foot {
text-align: right;
margin-top: 4px;
border-top: 1px solid #ccc;
padding: 4px;
box-sizing: border-box;
}
.foot {
text-align: right;
margin-top: 4px;
border-top: 1px solid #ccc;
padding: 4px;
box-sizing: border-box;
}
}
}
}
</style>

View File

@ -1,33 +1,18 @@
<template>
<div>
<YpHome v-if="showModel == '研判首页'" @change="changeModel"></YpHome>
<YjList v-if="showModel == '态势预警列表'" :item="itemYj" @change="changeModel"></YjList>
<YjDetail v-if="showModel == '预警详情'" :item="itemDetail" @change="changeModel"></YjDetail>
<!-- <YjList v-if="showModel == '态势预警列表'" :item="itemYj" @change="changeModel"></YjList>
<YjDetail v-if="showModel == '预警详情'" :item="itemDetail" @change="changeModel"></YjDetail> -->
</div>
</template>
<script setup>
import YpHome from "./components/ypHome.vue";
import YjList from "./components/yjList.vue";
import YjDetail from "./components/yjDetail.vue";
import { onMounted, ref } from "vue";
const showModel = ref('研判首页')
const itemYj = ref({})
const itemDetail = ref({})
onMounted(()=>{
// route.query.id ? lookDeatl(route.query.id): getLits();
})
function changeModel(val){
showModel.value = val.type ;
if(val.data){
if(val.type == '态势预警列表'){
itemYj.value = val.data
}else if(val.type == '预警详情'){
itemDetail.value = val.data
}
}
}
</script>

View File

@ -94,6 +94,7 @@ const pageData = reactive({
{ label: "标签代码", prop: "bqDm" },
{ label: "标签等级", prop: "bqDj",showSolt:true},
{ label: "标签颜色", prop: "bqYs",showSolt:true},
{ label: "标签说明", prop: "bqSm"},
]
});
onMounted(() => {

View File

@ -93,6 +93,7 @@ const pageData = reactive({
{ label: "标签代码", prop: "bqDm" },
{ label: "标签等级", prop: "bqDj",showSolt:true},
{ label: "标签颜色", prop: "bqYs",showSolt:true},
{ label: "标签说明", prop: "bqSm"},
]
});
onMounted(() => {

View File

@ -0,0 +1,48 @@
<template>
<el-dialog title="行为详情次数详情1" v-model="dialogVisible" width="60%">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
>
</MyTable>
</el-dialog>
</template>
<script setup>
import MyTable from "@/components/aboutTable/MyTable.vue";
import { ref , reactive , defineExpose} from 'vue'
const dialogVisible = ref(false)
const pageData = reactive({
tableData: [{jqbh:'JQBH-43',bjr:'张三',bjrdh:'15665255545',bjrsfzh:'510156565656525565',yjnr:'xxxxxxxxx',jsj:'2023-08-24 15:00:00'}], //表格数据
keyCount: 0,
tableConfiger: {
rowHieght: 61,
loading: false,
haveControls: false,
},
tableHeight:600,
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
tableColumn: [
{ label: "警情编号", prop: "jqbh"},
{ label: "报警人", prop: "bjr" },
{ label: "报警人电话", prop: "bjrdh" },
{ label: "报警人身份证", prop: "bjrsfzh"},
{ label: "预警内容", prop: "yjnr", showOverflowTooltip: true },
{ label: "报警时间", prop: "jsj", showOverflowTooltip: true },
]
});
const init = (row) => {
dialogVisible.value = true
}
defineExpose({
init
})
</script>

View File

@ -0,0 +1,130 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="行为预警">
<el-button type="primary">
<span style="vertical-align: middle">导出</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
</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>
</MyTable>
<Pages
@changeNo="changeNo"
@changeSize="changeSize"
:tableHeight="pageData.tableHeight"
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
</div>
</div>
<!-- 详情 -->
<Detail ref="detailRef"></Detail>
</template>
<script setup>
import Detail from './components/detail.vue'
import PageTitle from "@/components/aboutTable/PageTitle.vue";
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 } from "vue";
const searchBox = ref(); //搜索框
const searchConfiger = ref(
[
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input"},
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input"},
{ label: "电话号码", prop: 'dh', placeholder: "请输入电话号码", showType: "input"},
]);
const detailRef = ref()
const queryFrom = ref({});
const pageData = reactive({
tableData: [
{ xwcs:12 ,xm:'张三' ,sfzh:'510156565656525565',dh:'15665255545',xwfz:'20',xwms:'xxxxxxxxx',xwdl:'xxxxxxx',xwzl:'xxxxxxx'}
], //表格数据
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false,
haveControls: false,
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
tableColumn: [
{ label: "姓名", prop: "xm"},
{ label: "身份证号", prop: "sfzh" },
{ label: "电话", prop: "dh" },
{ label: "行为大类", prop: "xwdl"},
{ label: "行为子类", prop: "xwzl", showOverflowTooltip: true },
{ label: "行为描述", prop: "xwms", showOverflowTooltip: true },
{ label: "行为次数", prop: "xwcs",showSolt: true },
{ label: "行为分值", prop: "xwfz",},
]
});
onMounted(() => {
tabHeightFn();
getList()
});
// 搜索
const onSearch = (val) =>{
queryFrom.value = {...val}
pageData.pageConfiger.pageCurrent = 1;
getList()
}
const changeNo = (val) =>{
pageData.pageConfiger.pageCurrent = val;
getList()
}
const changeSize = (val) =>{
pageData.pageConfiger.pageSize = val;
getList()
}
const getList = () =>{
// pageData.tableConfiger.loading = true;
// qcckGet(queryFrom.value,'/mosty-gsxt/behaviorWarning/selectPage').then((res)=>{
// pageData.total = res.total || 0;
// pageData.tableConfiger.loading = false;
// }).catch(()=>{
// pageData.tableConfiger.loading = false;
// })
}
const handleClick = (row) => {
detailRef.value.init(row)
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () { tabHeightFn(); };
};
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>

View File

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

View File

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

View File

@ -11,77 +11,88 @@
</el-form>
<el-button type="primary">搜索</el-button>
</div>
<div class="systemBox">
<!-- 左边列表 -->
<div class="leftList">
<div class="hed flex just-between align center">
<span class="f14">预警列表</span>
<span style="color: #00b7ff" class="pointer" @click="seeMoreFn">查看更多</span>
</div>
<div class="ml10 mr10 mt10">
<el-input v-model="keyword" placeholder="姓名、证件号码搜索">
<template #append><el-icon><Search /></el-icon></template>
</el-input>
</div>
<ul class="listContent noScollLine mt10" v-infinite-scroll="loadList" style="overflow: auto" v-loading="loading">
<!-- @click.stop="showDetail(item)" -->
<li v-for="(item, index) in personList" :key="index" >
<YjItem :item="item" type="yj" :dic="{D_BZ_YJCZZT}"></YjItem>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0"></MOSTY.Empty>
</ul>
</div>
<!-- 右边模块 -->
<div class="rightList">
<!-- 第一部门 -->
<div class="model-commom">
<div class="hed flex align-center">预警处置统计</div>
<div class="comm-cnt" v-loading="list.YjczDate.loading">
<BarHatEcharts echartsId="qylxEcharts" :data="list.YjczDate"></BarHatEcharts>
<div class="systemBox">
<!-- 左边列表 -->
<div class="leftList">
<div class="hed flex just-between align center">
<span class="f14">预警列表</span>
<span style="color: #00b7ff" class="pointer" @click="seeMoreFn">查看更多</span>
</div>
</div>
<!-- 第二部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">布控区域统计</div>
<div class="comm-cnt" v-loading="list.RylxDate.loading">
<BarHatEcharts echartsId="rylxEcharts" :data="list.RylxDate"></BarHatEcharts>
<div class="ml10 mr10 mt10">
<el-input v-model="keyword" placeholder="姓名、证件号码搜索">
<template #append>
<el-button type="primary" @click="getKeyword">搜索</el-button>
<!-- <div >
<el-icon >
<Search />
</el-icon>
</div> -->
</template>
</el-input>
</div>
<ul class="listContent noScollLine mt10" v-infinite-scroll="loadList" style="overflow: auto"
v-loading="loading">
<!-- @click.stop="showDetail(item)" -->
<li v-for="(item, index) in personList" :key="index" @click="markAbove(item)">
<YjItem :item="item" type="yj" :dic="{ D_BZ_YJCZZT }" @showDetail="showDetail"></YjItem>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0"></MOSTY.Empty>
</ul>
</div>
<!-- 第三部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">感知源统计</div>
<div class="comm-cnt" v-loading="list.GzyDate.loading">
<BarHatEcharts echartsId="gzyEcharts" :data="list.GzyDate"></BarHatEcharts>
<!-- 右边模块 -->
<div class="rightList">
<!-- 第一部门 -->
<div class="model-commom">
<div class="hed flex align-center">预警处置统计</div>
<div class="comm-cnt" v-loading="list.YjczDate.loading">
<BarHatEcharts echartsId="qylxEcharts" :data="list.YjczDate"></BarHatEcharts>
</div>
</div>
</div>
<!-- 第四部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">预警等级统计</div>
<div class="comm-cnt" v-loading="loadingyj">
<WarningCount ref="yjjbRef"></WarningCount>
<!-- 第二部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">布控区域统计</div>
<div class="comm-cnt" v-loading="list.RylxDate.loading">
<BarHatEcharts echartsId="rylxEcharts" :data="list.RylxDate"></BarHatEcharts>
</div>
</div>
<!-- 第三部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">感知源统计</div>
<div class="comm-cnt" v-loading="list.GzyDate.loading">
<BarHatEcharts echartsId="gzyEcharts" :data="list.GzyDate"></BarHatEcharts>
</div>
</div>
<!-- 第四部分 -->
<div class="model-commom mt10">
<div class="hed flex align-center">预警等级统计</div>
<div class="comm-cnt" v-loading="loadingyj">
<WarningCount ref="yjjbRef"></WarningCount>
</div>
</div>
</div>
</div>
</div>
</div>
<Information v-model="showDialog" title="发送指令" @submit='submit' @close='close'>
<SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj" :tacitly="tacitly"/>
<Information v-model="showDialog" title="发送指令" @submit='submit' @close='close'>
<SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj"
:tacitly="tacitly" />
</Information>
<!-- 反馈按钮 -->
<FkDialog @change="getList"></FkDialog>
<LeftDialog></LeftDialog>
</template>
<script setup>
import LeftDialog from '@/views/home/dialog/leftDialog.vue'
import FkDialog from './components/fkDialog.vue'
import * as MOSTY from "@/components/MyComponents/index";
import { qcckPost,qcckGet } from "@/api/qcckApi.js";
import { qcckPost, qcckGet } from "@/api/qcckApi.js";
import GdMap from "@/components/GdMap/index.vue";
import emitter from "@/utils/eventBus.js";
import YjItem from "./components/yjItem.vue";
import WarningCount from "./components/WarningCount.vue";
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted, reactive, ref,getCurrentInstance } from "vue";
import { onMounted, reactive, ref, getCurrentInstance } from "vue";
import { useRouter } from "vue-router";
import Information from "@/views/home/model/information.vue";
import SemdFqzl from '@/components/instructionHasBeen/sendFqzl.vue'
@ -114,13 +125,13 @@ const loadingyj = ref(false)
const list = reactive({
//
YjczDate: {
loading:false,
loading: false,
xDate: [],
list: [],
},
//
RylxDate: {
loading:false,
loading: false,
xDate: [],
list: [],
},
@ -128,68 +139,71 @@ const list = reactive({
GzyDate: {
xDate: [],
list: [],
loading:false,
loading: false,
},
})
const personList = ref([]);
const pageNum = ref(1)
const total = ref(0)
onMounted(()=>{
onMounted(() => {
getList()
init()
})
//
const loadList = () => {
if( personList.value.length == total.value) return;
if (personList.value.length == total.value) return;
pageNum.value++;
getList()
}
const getList = () =>{
let params = { pageSize:10, pageNum:pageNum.value };
const getList = () => {
let params = { pageSize: 10, pageNum: pageNum.value,keyword:keyword.value };
loading.value = true;
qcckPost(params,'/mosty-gsxt/tbYjxx/getPageList').then(res=>{
qcckPost(params, '/mosty-gsxt/tbYjxx/getPageList').then(res => {
loading.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(()=>{
}).catch(() => {
loading.value = false;
})
}
const init = () =>{
const getKeyword = () => {
pageNum.value=1
getList()
}
const init = () => {
//
list.YjczDate.loading = true;
qcckGet({},'/mosty-gsxt/tbYjxx/getYjCzztTj').then(res=>{
qcckGet({}, '/mosty-gsxt/tbYjxx/getYjCzztTj').then(res => {
list.YjczDate.loading = false;
list.YjczDate.xDate = res.map(item=>item.zdmc);
list.YjczDate.xDate = res.map(item => item.zdmc);
list.YjczDate.list = [{
value: res.map(item=>item.count),
value: res.map(item => item.count),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
})
//
list.RylxDate.loading = true;
qcckGet({},'/mosty-gsxt/tbGsxtBkQy/getBkQytj').then(res=>{
qcckGet({}, '/mosty-gsxt/tbGsxtBkQy/getBkQytj').then(res => {
list.RylxDate.loading = false;
list.RylxDate.xDate = res.map(item=>item.qymc);
list.RylxDate.xDate = res.map(item => item.qymc);
list.RylxDate.list = [{
value: res.map(item=>item.num),
value: res.map(item => item.num),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
})
//
list.GzyDate.loading= true;
qcckGet({},'/mosty-gsxt/tbYjxx/getGzyTj').then(res=>{
list.GzyDate.loading = true;
qcckGet({}, '/mosty-gsxt/tbYjxx/getGzyTj').then(res => {
list.GzyDate.loading = false;
list.GzyDate.xDate = res.map(item=>item.yj_gzymc);
list.GzyDate.xDate = res.map(item => item.yj_gzymc);
list.GzyDate.list = [{
value: res.map(item=>item.num),
value: res.map(item => item.num),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
@ -197,35 +211,44 @@ const init = () =>{
//
loadingyj.value = true;
qcckGet({},'/mosty-gsxt/tbYjxx/getYjxxTj').then(res=>{
qcckGet({}, '/mosty-gsxt/tbYjxx/getYjxxTj').then(res => {
loadingyj.value = false;
yjjbRef.value.initCharts(res)
})
}
const seeMoreFn = () => {
router.push('/ControlApproval')
router.push('/warningList')
}
const showDialog = ref(false)
const itemData=ref()
const itemData = ref()
const showDetail = (item) => {
showDialog.value = true;
itemData.value=item
itemData.value = item
}
const handleClose = () => {
showDialog.value = false;
}
const semdFqzlRef = ref()
const tacitly = {
title:'yjBt',
instructionContent:'yjNr'
title: 'yjBt',
instructionContent: 'yjNr'
}
const submit=()=>{
const submit = () => {
semdFqzlRef.value.getsendFqzl()
}
const close = () => {
semdFqzlRef.value.close()
}
//
const markAbove = (val) => {
const icon = require('@/assets/point/yj.png')
emitter.emit('setMapCenter', { location: [val.jd, val.wd], zoomLevel: 15 });
emitter.emit("addPointArea", { flag: 'home_yj_detail', icon, coords: [val] })
}
</script>
<style lang="scss" scoped>
@ -314,13 +337,13 @@ const close = () => {
height: 40px;
line-height: 40px;
padding-left: 10px;
background: linear-gradient(90deg, #124cb3 0%, rgba(18, 76, 179, 0.23) 77%, rgba(18, 76, 179, 0) 100%);
background: linear-gradient(90deg, #124cb3 0%, rgba(18, 76, 179, 0.23) 77%, rgba(18, 76, 179, 0) 100%);
}
}
</style>
<style>
.el-loading-mask{
background: rgba(0,0,0,0.5);
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>

View File

@ -0,0 +1,137 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="组合预警">
<el-button>
<span style="vertical-align: middle">导出</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
>
</MyTable>
<Pages
@changeNo="changeNo"
@changeSize="changeSize"
:tableHeight="pageData.tableHeight"
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
</div>
</div>
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
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";
const { proxy } = getCurrentInstance();
const searchBox = ref();
// 搜索配置
const searchConfiger = ref([
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input"},
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input"},
{ label: "预警等级", prop: 'yjdj', placeholder: "请选择预警等级", showType: "select", options: [
{ label: "一级预警", value: "1" },
{ label: "二级预警", value: "2" },
{ label: "三级预警", value: "3" },
{ label: "四级预警", value: "4" }
]},
]);
const queryFrom = ref({});
// 页面数据
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false,
haveControls: false,
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 160,
tableColumn: [
{ label: "姓名", prop: "xm" },
{ label: "身份证号", prop: "sfzh" },
{ label: "电话", prop: "dh" },
{ label: "组合类型", prop: "zhlx" },
{ label: "预警等级", prop: "yjdj" },
{ label: "预警原因", prop: "yjyy", showOverflowTooltip: true },
{ label: "预警时间", prop: "yjsj" },
{ label: "处理状态", prop: "clzt" },
]
});
onMounted(() => {
tabHeightFn();
getList();
});
const onSearch = (val) => {
queryFrom.value = {...val};
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
const getList = () => {
// pageData.tableConfiger.loading = true;
// TODO: 替换为实际的组合预警API接口
// qcckGet(queryFrom.value, '/mosty-gsxt/combinedWarning/selectPage').then((res) => {
// pageData.tableData = res.records || [];
// pageData.total = res.total || 0;
// pageData.tableConfiger.loading = false;
// }).catch(() => {
// pageData.tableConfiger.loading = false;
// });
};
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>

View File

@ -0,0 +1,137 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="身份预警">
<el-button>
<span style="vertical-align: middle">导出</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
>
</MyTable>
<Pages
@changeNo="changeNo"
@changeSize="changeSize"
:tableHeight="pageData.tableHeight"
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
</div>
</div>
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
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";
const { proxy } = getCurrentInstance();
const searchBox = ref();
// 搜索配置
const searchConfiger = ref([
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input"},
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input"},
{ label: "身份类型", prop: 'sflx', placeholder: "请选择身份类型", showType: "select", options: [
{ label: "重点人员", value: "1" },
{ label: "在逃人员", value: "2" },
{ label: "涉毒人员", value: "3" },
{ label: "涉恐人员", value: "4" }
]},
]);
const queryFrom = ref({});
// 页面数据
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false,
haveControls: false,
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 160,
tableColumn: [
{ label: "姓名", prop: "xm",},
{ label: "身份证号", prop: "sfzh", },
{ label: "电话", prop: "dh", },
{ label: "身份类型", prop: "sflx",},
{ label: "身份等级", prop: "sfdj",},
{ label: "预警原因", prop: "yjyy", showOverflowTooltip: true },
{ label: "预警时间", prop: "yjsj",},
{ label: "处理状态", prop: "clzt",},
]
});
onMounted(() => {
tabHeightFn();
getList();
});
const onSearch = (val) => {
queryFrom.value = {...val};
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
const getList = () => {
// pageData.tableConfiger.loading = true;
// TODO: 替换为实际的身份预警API接口
// qcckGet(queryFrom.value, '/mosty-gsxt/identityWarning/selectPage').then((res) => {
// pageData.tableData = res.records || [];
// pageData.total = res.total || 0;
// pageData.tableConfiger.loading = false;
// }).catch(() => {
// pageData.tableConfiger.loading = false;
// });
};
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="模型预警">
<el-button>
<span style="vertical-align: middle">导出</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
>
</MyTable>
<Pages
@changeNo="changeNo"
@changeSize="changeSize"
:tableHeight="pageData.tableHeight"
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
</div>
</div>
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
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";
const { proxy } = getCurrentInstance();
const searchBox = ref();
// 搜索配置
const searchConfiger = ref([
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input"},
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input"},
{ label: "模型类型", prop: 'mxlx', placeholder: "请选择模型类型", showType: "select", options: [
{ label: "行为模型", value: "1" },
{ label: "身份模型", value: "2" },
{ label: "关系模型", value: "3" },
{ label: "轨迹模型", value: "4" }
]},
]);
const queryFrom = ref({});
// 页面数据
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false,
haveControls: false,
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 160,
tableColumn: [
{ label: "序号", prop: "xh" },
{ label: "姓名", prop: "xm" },
{ label: "身份证号", prop: "sfzh" },
{ label: "电话", prop: "dh", },
{ label: "模型类型", prop: "mxlx" },
{ label: "模型名称", prop: "mxmc", },
{ label: "预警原因", prop: "yjyy", showOverflowTooltip: true },
{ label: "预警时间", prop: "yjsj" },
{ label: "处理状态", prop: "clzt" },
]
});
onMounted(() => {
tabHeightFn();
getList();
});
const onSearch = (val) => {
queryFrom.value = {...val};
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
const getList = () => {
// pageData.tableConfiger.loading = true;
// TODO: 替换为实际的模型预警API接口
// qcckGet(queryFrom.value, '/mosty-gsxt/modelWarning/selectPage').then((res) => {
// pageData.tableData = res.records || [];
// pageData.total = res.total || 0;
// pageData.tableConfiger.loading = false;
// }).catch(() => {
// pageData.tableConfiger.loading = false;
// });
};
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>

View File

@ -0,0 +1,137 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="预警布控">
<el-button>
<span style="vertical-align: middle">导出</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
>
</MyTable>
<Pages
@changeNo="changeNo"
@changeSize="changeSize"
:tableHeight="pageData.tableHeight"
:pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"
></Pages>
</div>
</div>
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
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";
const { proxy } = getCurrentInstance();
const searchBox = ref();
// 搜索配置
const searchConfiger = ref([
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input"},
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input"},
{ label: "身份类型", prop: 'sflx', placeholder: "请选择身份类型", showType: "select", options: [
{ label: "重点人员", value: "1" },
{ label: "在逃人员", value: "2" },
{ label: "涉毒人员", value: "3" },
{ label: "涉恐人员", value: "4" }
]},
]);
const queryFrom = ref({});
// 页面数据
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false,
haveControls: false,
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 160,
tableColumn: [
{ label: "姓名", prop: "xm",},
{ label: "身份证号", prop: "sfzh", },
{ label: "电话", prop: "dh", },
{ label: "身份类型", prop: "sflx",},
{ label: "身份等级", prop: "sfdj",},
{ label: "预警原因", prop: "yjyy", showOverflowTooltip: true },
{ label: "预警时间", prop: "yjsj",},
{ label: "处理状态", prop: "clzt",},
]
});
onMounted(() => {
tabHeightFn();
getList();
});
const onSearch = (val) => {
queryFrom.value = {...val};
pageData.pageConfiger.pageCurrent = 1;
getList();
};
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList();
};
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList();
};
const getList = () => {
// pageData.tableConfiger.loading = true;
// TODO: 替换为实际的身份预警API接口
// qcckGet(queryFrom.value, '/mosty-gsxt/identityWarning/selectPage').then((res) => {
// pageData.tableData = res.records || [];
// pageData.total = res.total || 0;
// pageData.tableConfiger.loading = false;
// }).catch(() => {
// pageData.tableConfiger.loading = false;
// });
};
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>

View File

@ -0,0 +1,324 @@
<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"
>保存</el-button
>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<div class="form_cnt">
<FormMessage
v-model="listQuery"
:formList="formData"
ref="elform"
:rules="rules"
>
<!-- 身份标签细类 -->
<template #sfbqIdList>
<el-button @click="openDialog('01')">选择</el-button>
<div class="boxlist">
<MyTable
:tableData="tableDate.sfbqIdList"
:tableColumn="tableDate.tableColumn"
:tableHeight="tableDate.tableHeight"
:key="tableDate.keyCount"
:tableConfiger="tableDate.tableConfiger"
:controlsWidth="tableDate.controlsWidth"
>
<template #bqLx="{ row }">
<DictTag
:value="row.bqLx"
:tag="false"
:options="props.dic.D_GS_BQ_LX"
/>
</template>
<template #bqLb="{ row }">
<DictTag
:value="row.bqLb"
:tag="false"
:options="props.dic.D_GS_BQ_LB"
/>
</template>
<template #bqYs="{ row }">
<DictTag
:value="row.bqYs"
:tag="false"
:options="props.dic.D_GS_SSYJ"
/>
</template>
<template #bqDj="{ row }">
<DictTag
:tag="false"
:value="row.bqDj"
:options="props.dic.D_GS_BQ_DJ"
/>
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link
type="danger"
@click="delDictItem(row.id, '身份标签细类')"
>删除</el-link
>
</template>
</MyTable>
</div>
</template>
<!-- 行为标签细类 -->
<template #xwbqIdList>
<el-button @click="openDialog('02')">选择</el-button>
<div class="boxlist">
<MyTable
:tableData="tableDate.xwbqIdList"
:tableColumn="tableDate.tableColumn"
:tableHeight="tableDate.tableHeight"
:key="tableDate.keyCount"
:tableConfiger="tableDate.tableConfiger"
:controlsWidth="tableDate.controlsWidth"
>
<template #bqLx="{ row }">
<DictTag
:value="row.bqLx"
:tag="false"
:options="props.dic.D_GS_BQ_LX"
/>
</template>
<template #bqLb="{ row }">
<DictTag
:value="row.bqLb"
:tag="false"
:options="props.dic.D_GS_BQ_LB"
/>
</template>
<template #bqYs="{ row }">
<DictTag
:value="row.bqYs"
:tag="false"
:options="props.dic.D_GS_SSYJ"
/>
</template>
<template #bqDj="{ row }">
<DictTag
:tag="false"
:value="row.bqDj"
:options="props.dic.D_GS_BQ_DJ"
/>
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link
type="danger"
@click="delDictItem(row.id, '行为标签细类')"
>删除</el-link
>
</template>
</MyTable>
</div>
</template>
</FormMessage>
</div>
<!-- 列表弹窗 -->
<DialogList
:Single="false"
:roleIds="roleIds"
v-if="chooseShow"
:dic="props.dic"
@chooseDate="chooseDate"
:titleValue="chooseTitle"
v-model="chooseShow"
:bqLx="chooseType"
bqDl="02"
></DialogList>
</div>
</template>
<script setup>
import MyTable from "@/components/aboutTable/MyTable.vue";
import DialogList from "@/views/backOfficeSystem/fourColorManage/components/dialogList.vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
import {
ref,
defineExpose,
defineProps,
reactive,
defineEmits,
getCurrentInstance
} from "vue";
const emit = defineEmits(["updateDate"]);
const { proxy } = getCurrentInstance();
const props = defineProps({
dic: Object
});
const roleIds = ref([]); //角色id
const chooseType = ref("01"); //选择弹窗类型
const chooseShow = ref(false); //选择弹窗
const chooseTitle = ref(""); //选择弹窗
const dialogForm = ref(false); //弹窗
const formData = reactive([
{ label: "组合标签名称", prop: "bqMc", type: "input" },
{ label: "组合标签代码", prop: "bqDm", type: "input" },
{
label: "标签等级",
prop: "bqDj",
type: "select",
options: props.dic.D_GS_BQ_DJ
},
{
label: "标签颜色",
prop: "bqYs",
type: "select",
options: props.dic.D_GS_SSYJ
},
{ label: "组合标签分值", prop: "bqFz", type: "input" },
{ label: "组合标签说明", prop: "bqSm", type: "input" },
{ label: "身份标签细类", prop: "sfbqIdList", type: "slot", width: "100%" },
{ label: "行为标签细类", prop: "xwbqIdList", type: "slot", width: "100%" }
]);
const rules = reactive({
bqMc: [{ required: true, message: "请输入组合标签名称", trigger: "blur" }],
bqDm: [{ required: true, message: "请输入组合标签代码", trigger: "blur" }],
zhbqjf: [{ required: true, message: "请输入组合标签积分", trigger: "blur" }],
sfbqIdList: [
{ required: true, message: "请选择身份标签细类", trigger: "change" }
],
xwbqIdList: [
{ required: true, message: "请选择行为标签细类", trigger: "change" }
]
});
const tableDate = reactive({
sfbqIdList: [], //表格数据
xwbqIdList: [], //表格数据
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false
},
total: 0,
tableHeight: 225,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
controlsWidth: 90, //操作栏宽度
tableColumn: [
{ label: "标签名称", prop: "bqMc", showOverflowTooltip: true },
{ label: "标签代码", prop: "bqDm" },
{ label: "标签大类名称", prop: "bqDlMc" },
{ label: "标签类型", prop: "bqLx", showSolt: true },
{ label: "标签类别", prop: "bqLb", showSolt: true },
{ label: "标签颜色", prop: "bqYs", showSolt: true },
{ label: "标签等级", prop: "bqDj", showSolt: true }
]
});
const listQuery = ref({}); //表单
const loading = ref(false);
const elform = ref();
const title = ref("");
// 初始化数据
const init = (type, row) => {
dialogForm.value = true;
title.value = type == "add" ? "新增" : "编辑";
if (row) getDataById(row.id);
};
// 根据id查询详情
const getDataById = (id) => {
qcckGet({}, "/mosty-gsxt/tbGsxtBqzh/selectVoById/" + id).then((res) => {
listQuery.value = res;
tableDate.sfbqIdList = res.sfbqList;
listQuery.value.sfbqIdList = res.sfbqList.map((item) => item.id);
tableDate.xwbqIdList = res.xwbqList;
listQuery.value.xwbqIdList = res.xwbqList.map((item) => item.id);
tableDate.keyCount++;
});
};
// 提交
const submit = () => {
elform.value.submit((data) => {
let url =
title.value == "新增"
? "/mosty-gsxt/tbGsxtBqzh/save"
: "/mosty-gsxt/tbGsxtBqzh/update";
let params = { ...data };
loading.value = true;
qcckPost(params, url)
.then((res) => {
proxy.$message({ type: "success", message: title.value + "成功" });
emit("updateDate");
loading.value = false;
close();
})
.catch(() => {
loading.value = false;
});
});
};
// 打开弹窗
const openDialog = (type) => {
chooseShow.value = true;
chooseType.value = type;
chooseTitle.value = type == "01" ? "选择身份标签细类" : "选择行为标签细类";
roleIds.value =
type == "01"
? tableDate.sfbqIdList.map((item) => item.id)
: tableDate.xwbqIdList.map((item) => item.id);
};
// 选择数据
const chooseDate = (data) => {
if (chooseType.value == "01") {
tableDate.sfbqIdList = data;
listQuery.value.sfbqIdList = tableDate.sfbqIdList.map((item) => item.id);
} else {
tableDate.xwbqIdList = data;
listQuery.value.xwbqIdList = tableDate.xwbqIdList.map((item) => item.id);
}
};
// 删除
const delDictItem = (id, type) => {
switch (type) {
case "身份标签细类":
tableDate.sfbqIdList = tableDate.sfbqIdList.filter(
(item) => item.id !== id
);
listQuery.value.sfbqIdList = tableDate.sfbqIdList.map((item) => item.id);
break;
case "行为标签细类":
tableDate.xwbqIdList = tableDate.xwbqIdList.filter(
(item) => item.id !== id
);
listQuery.value.xwbqIdList = tableDate.xwbqIdList.map((item) => item.id);
break;
}
};
// 关闭
const close = () => {
listQuery.value = {};
tableDate.sfbqIdList = [];
tableDate.xwbqIdList = [];
dialogForm.value = false;
loading.value = false;
};
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.boxlist {
width: 99%;
height: 225px;
margin-top: 10px;
overflow: hidden;
}
</style>

View File

@ -0,0 +1,141 @@
<template>
<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 }">
<el-image :preview-teleported="true" style="width: 80px; height: 110px" :src="row.yjTp"
:preview-src-list="[row.yjTp]" />
</template>
<template #nl="{ row }">
{{ IdCard(row.yjRysfzh, 3) }}
</template>
<template #xb="{ row }">
{{ IdCard(row.yjRysfzh, 2) }}
</template>
<template #xsd="{ row }">
90%
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-link type="danger" @click="delDictItem(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 MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js";
import { IdCard } from '@/utils/validate.js'
import { tbYjxxGetPageList } from '@/api/yj.js'
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
const { proxy } = getCurrentInstance();
const detailDiloag = ref();
const queryFrom = ref({});
const pageData = reactive({
tableData: [], //表格数据
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false,
haveControls:false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
controlsWidth: 160, //操作栏宽度
tableColumn: [
{ label: "人像照片", prop: "yjTp", showSolt: true },
{ label: "姓名", prop: "yjRyxm" },
{ label: "年龄", prop: "nl", showSolt: true },
{ label: "性别", prop: "xb", showSolt: true },
{ label: "预警级别", prop: "yjJb" },
{ label: "相似度", prop: "xsd", showSolt: true },
{ label: "预警时间", prop: "yjSj", showOverflowTooltip: true },
{ label: "预警地点", prop: "yjDz", showOverflowTooltip: true },
{ label: "预警次数", prop: "yjCs", showOverflowTooltip: true },
{ label: "布控手机号", prop: "yjRysjh", showOverflowTooltip: true },
{ label: "布控车牌号", prop: "yjClcph", showOverflowTooltip: true },
{ label: "身份证", prop: "yjRysfzh", showOverflowTooltip: true },
]
});
onMounted(() => {
tabHeightFn();
getList()
});
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
getList()
}
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
getList()
}
const getList = (val) => {
pageData.tableConfiger.loading = true;
const promes = {
...val,
pageCurrent: pageData.pageConfiger.pageCurrent,
pageSize: pageData.pageConfiger.pageSize
}
tbYjxxGetPageList(promes).then((res) => {
pageData.tableData = res.records;
pageData.total = res.total;
pageData.tableConfiger.loading = false;
}).catch(() => {
pageData.tableConfiger.loading = false;
})
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - 430;
window.onresize = function () {
tabHeightFn();
};
};
defineExpose({
getList
})
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
</style>

View File

@ -0,0 +1,313 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="预警列表" />
</div>
<!-- 搜索 -->
<div ref="searchBox" class="searchBox">
<el-form :model="listQuery" label-width="auto" :inline="true" ref="searchArr">
<el-form-item label="布控类型" prop="yjlx">
<el-select v-model="listQuery.yjlx" placeholder="请选择预警类型">
<el-option v-for="item in D_BZ_YJLX" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="布控人员" prop="yjRyxm ">
<el-select v-model="listQuery.yjRyxm" filterable remote reserve-keyword placeholder="请选择布控人员"
:remote-method="remoteMethod" :loading="loading" style="width: 240px">
<el-option v-for="item in opentions" :key="item.rySfzh" :label="item.ryXm" :value="item.rySfzh" />
</el-select>
</el-form-item>
<el-form-item label="时间筛选">
<el-date-picker v-model="listQuery.time" type="datetimerange" :shortcuts="shortcuts" range-separator="To"
start-placeholder="开始时间" end-placeholder="结束时间" value-format="YYYY-MM-DD HH:mm:ss"
format="YYYY-MM-DD HH:mm:ss" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSearch">查询</el-button>
<el-button @click="resetForm(searchArr)">重置</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格 -->
<div class="tabBox" :style="{ height: pageData.tableHeight + 'px' }">
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="本地预警" name="local">
<div style="padding:0 10px;"> <el-button type="primary" @click="exportExcel">导出</el-button></div>
<LocalWarning ref="localWarningRef" />
</el-tab-pane>
<el-tab-pane label="区厅预警" name="district">区厅预警</el-tab-pane>
</el-tabs>
</div>
</div>
<el-dialog v-model="showDc" title="导出预警" width="80%" align-center>
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="500"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #yjTp="{ row }">
<el-image :preview-teleported="true" style="width: 80px; height: 110px" :src="row.yjTp"
:preview-src-list="[row.yjTp]" />
</template>
<template #nl="{ row }">
{{ IdCard(row.yjRysfzh, 3) }}
</template>
<template #xb="{ row }">
{{ IdCard(row.yjRysfzh, 2) }}
</template>
<template #xsd="{ row }">
90%
</template>
<!-- 操作 -->
</MyTable>
<template #footer>
<div class="dialog-footer">
<el-button @click="showDc = false">关闭</el-button>
<el-button type="primary" @click="handleExport">
导出
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Search from "@/components/aboutTable/Search.vue";
import * as MOSTY from "@/components/MyComponents/index";
import { IdCard } from '@/utils/validate.js'
import { tbGsxtZdrySelectList } from "@/api/zdr.js"
import { tbYjxxQueryYjxx } from "@/api/yj.js";
import LocalWarning from "./components/localWarning.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
import FileSaver from "file-saver";
import * as XLSX from "xlsx";
const { proxy } = getCurrentInstance();
const { D_BZ_YJLX } = proxy.$dict("D_BZ_YJLX")
const searchBox = ref(); //搜索框
const form = ref({});
const shortcuts = [
{
text: '近一周',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近一月',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
{
text: '近三月',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 3)
return [start, end]
},
},
]
const pageData = reactive({
tableData: [], //表格数据
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "null",
loading: false,
haveControls: false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
controlsWidth: 160, //操作栏宽度
tableColumn: [
{ label: "人像照片", prop: "yjTp", showSolt: true },
{ label: "姓名", prop: "yjRyxm" },
{ label: "年龄", prop: "nl", showSolt: true },
{ label: "性别", prop: "xb", showSolt: true },
{ label: "预警级别", prop: "yjJb" },
{ label: "相似度", prop: "xsd", showSolt: true },
{ label: "预警时间", prop: "yjSj", showOverflowTooltip: true },
{ label: "预警地点", prop: "yjDz", showOverflowTooltip: true },
{ label: "预警次数", prop: "yjCs", showOverflowTooltip: true },
{ label: "布控手机号", prop: "yjRysjh", showOverflowTooltip: true },
{ label: "布控车牌号", prop: "yjClcph", showOverflowTooltip: true },
{ label: "身份证", prop: "yjRysfzh", showOverflowTooltip: true },
]
});
const showDc = ref(false)
const activeName = ref('local')
onMounted(() => {
tabHeightFn();
});
const listQuery = reactive({})
const opentions = ref([])
const localWarningRef = ref(null);
// 搜索
const onSearch = () => {
const promes = {
yjRyxm: listQuery.yjRyxm,
yjlx: listQuery.yjlx,
startTime: listQuery.time ? listQuery.time[0] : '',
endTime: listQuery.time ? listQuery.time[1] : '',
}
localWarningRef.value.getList(promes)
}
const loading = ref(false)
const remoteMethod = (query) => {
if (query) {
loading.value = true
tbGsxtZdrySelectList({ ryXm: query }).then(res => {
opentions.value = res
}).finally(() => {
loading.value = false
})
} else {
opentions.value = []
}
}
const searchArr = ref(null)
const resetForm = (formEl) => {
if (!formEl) return
formEl.resetFields()
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
// 导出
const exportExcel = () => {
const promes = {
yjRyxm: listQuery.yjRyxm,
yjlx: listQuery.yjlx,
startTime: listQuery.time ? listQuery.time[0] : '',
endTime: listQuery.time ? listQuery.time[1] : '',
}
tbYjxxQueryYjxx(promes).then(res => {
pageData.tableData = res
showDc.value = true
})
}
// 处理Excel导出
const handleExport = () => {
// 创建一个临时表格用于导出
const tempTable = document.createElement('table');
// 创建表头
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
// 添加序号列
const indexTh = document.createElement('th');
indexTh.textContent = '序号';
headerRow.appendChild(indexTh);
// 添加其他列头
pageData.tableColumn.forEach(column => {
const th = document.createElement('th');
th.textContent = column.label;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
tempTable.appendChild(thead);
// 创建表体
const tbody = document.createElement('tbody');
// 处理表格数据
pageData.tableData.forEach((row, index) => {
const tr = document.createElement('tr');
// 添加序号
const indexTd = document.createElement('td');
indexTd.textContent = index + 1;
tr.appendChild(indexTd);
// 添加其他单元格数据
pageData.tableColumn.forEach(column => {
const td = document.createElement('td');
// 处理自定义插槽的情况
if (column.showSolt) {
if (column.prop === 'yjTp') {
// 照片字段只显示文字描述
td.textContent = '有照片';
} else if (column.prop === 'nl') {
// 年龄字段
td.textContent = IdCard(row.yjRysfzh, 3);
} else if (column.prop === 'xb') {
// 性别字段
td.textContent = IdCard(row.yjRysfzh, 2);
} else if (column.prop === 'xsd') {
// 相似度字段
td.textContent = '90%';
} else {
// 其他字段
td.textContent = row[column.prop] || '';
}
} else {
// 普通字段
td.textContent = row[column.prop] || '';
}
tr.appendChild(td);
});
tbody.appendChild(tr);
});
tempTable.appendChild(tbody);
// 执行Excel导出
let xlsxParam = { raw: true };
let wb = XLSX.utils.table_to_book(tempTable, xlsxParam);
let wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array"
});
// 保存文件
try {
const exportTime = new Date().toLocaleString('zh-CN').replace(/\//g, '-').replace(/:/g, '-');
FileSaver.saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
`预警数据导出_${exportTime}.xlsx`
);
showDc.value = false;
} catch (e) {
console.error('导出Excel失败:', e);
}
}
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
.searchBox {
background-color: #fff;
margin-bottom: 10px;
}
</style>

View File

@ -104,7 +104,6 @@ function lineChartFn() {
window.onresize = function () {
myChart.resize();
};
document.getElementById("circlecz").setAttribute("_echarts_instance_", "");
}
onMounted(() => {
lineChartFn();

View File

@ -8,7 +8,6 @@
</li>
<MOSTY.Empty :show="props.data.length <= 0" :imgSize="150"></MOSTY.Empty>
</ul>
<!-- :style="{height: `calc(100vh - ${handleHs}px)`}" -->
<div style="position:relative;width: 100%;" :style="{ height: `calc(100vh - ${handleHs}px)` }">

View File

@ -0,0 +1,43 @@
<template>
<div style="position: absolute;top: 34%;left: 42%;transform: translate(-50%, -50%);z-index: 1;" v-if="show">
<div style="width: 100%;background: #1d5db4e3;padding: 8px 5px;" class="flex align-center just-between ">
<span >详情</span><el-icon size="20px" @click="close" style="cursor: pointer;">
<Close />
</el-icon>
</div>
<YjItem :item="data" :track="false" />
</div>
</template>
<script setup>
import YjItem from "@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/components/yjItem.vue";
import { ref, defineProps, onMounted, watch } from "vue";
import emitter from "@/utils/eventBus.js";
//参数传递
const props = defineProps({
//某条预警详情
data: {
type: Array,
default: []
},
show: {
type: Boolean,
default: false
},
});
console.log(props.show);
//关闭
function close() {
emitter.emit('deletePointArea', 'home_yj_detail');
emitter.emit("showHomeWarning", false);
}
onMounted(() => {
})
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
</style>

View File

@ -2,19 +2,23 @@
<div class="noScollLine">
<!-- 预警信息弹框 -->
<Home_YJ v-if="isShow.showYj" :show="isShow.showYj" :data="list.Info_YJ" />
<PopupWarning v-if="isShow.showWarning" :show="isShow.showWarning" :data="list.Info_Warning" />
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import Home_YJ from "./components/home_yj.vue";
import PopupWarning from './components/popupWarning'
import { ref, onMounted, onUnmounted, reactive, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const isShow = ref({
showYj: false, //预警弹窗
showWarning: false
});
const list = reactive({
Info_YJ: [], //预警数据
Info_Warning: [],
});
onMounted(() => {
@ -23,11 +27,16 @@ onMounted(() => {
isShow.value.showYj = res ? true : false;
if (res) list.Info_YJ = res;
});
// 展示预警
emitter.on("showHomeWarning", (res) => {
isShow.value.showWarning = res ? true : false;
if (res) list.Info_Warning = res;
});
});
onUnmounted(() => {
emitter.off("showHomeYJ");
emitter.off("showHomeWarning");
});
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,137 @@
<template>
<div style="height:100%;width:100%" :id="echartsId"></div>
</template>
<script setup>
import * as echarts from "echarts";
import { nextTick , onMounted, watch, defineProps } from "vue";
const props = defineProps({
echartsId:{
type:String,
default:'barHatId'
},
data:{
type:Object,
default:{
xDate: ['巴宜区', '工布江达县', '波密县', '朗县', '墨脱县', '察隅县', '米林县'],
list:[
{ name: "总数", value: [10,20,30,40,50,60,70] ,color:['rgba(0,244,255,1)','rgba(0,77,167,1)'] ,hatColor:'#087df9'},
{ name: "已处置", value: [10,20,30,40,50,60,70],color:['rgba(24, 232, 229, 1)','rgba(3, 110, 83, 1)'],hatColor:'#00FFFF' },
],
}
}
});
watch(()=>props.data,val=>{
nextTick(()=>{ handleDate() })
},{immediate:true,deep:true})
// 处理数据
function handleDate() {
let xDate = props.data.xDate;
let legend = props.data.list.map(v=>{return {name:v.name}})
let series = props.data.list.map((item,i)=>{
let obj = {
name: item.name,
type: "bar",
data: item.value,
barWidth: "10px",
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0,0,0,1,[
{ offset: 0, color: item.color ? item.color[0] : "rgba(0,244,255,1)" },
{ offset: 1, color: item.color ? item.color[1] : "rgba(0,77,167,1)" }],false),
}
},
markPoint: {
symbol: 'path://M62 62h900v900h-900v-900z', // 使用 SVG path 绘制扁圆形状
symbolSize: [11, 4], // 设置扁圆的宽和高
itemStyle: { color: item.hatColor || '#087df9' },// 圆盘颜色
data: item.value.map((obj, index) => ({
xAxis: index, // 对应柱子的横坐标
yAxis: obj + 0 // 柱子的值加上一些偏移量
}))
},
}
return obj
})
lineChartFn(xDate,legend,series)
}
function lineChartFn(xDate,legend,series) {
var myChart = echarts.init(document.getElementById(props.echartsId));
var option = {
legend: {
type: "plain",
show: true,
right: 0,
textStyle: { color: "#ddd" },
data: legend
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow"
}
},
grid: {
top: "25%",
right: "8%",
left: "10%",
bottom: "22%"
},
xAxis: [
{
type: "category",
data: xDate,
axisLine: {
lineStyle: {
color: "rgba(255,255,255,0.12)"
}
},
axisLabel: {
margin: 10,
color: "#e2e9ff",
textStyle: {
fontSize: 14
}
}
}
],
yAxis: [
{
// name: '单位:万元',
axisLabel: {
formatter: "{value}",
color: "#e2e9ff"
},
axisLine: {
show: false,
lineStyle: {
color: "rgba(255,255,255,1)"
}
},
splitLine: {
lineStyle: {
color: "rgba(255,255,255,0.12)"
}
}
}
],
series: series
};
option && myChart.setOption(option);
window.onresize = function () { myChart.resize(); };
}
onMounted(() => {
lineChartFn();
});
</script>
<style lang="scss" scoped>
.circlecz {
height: 100%;
background: rgba(0,29,75,0.6);
border-radius: 0 0 4px 4px;
}
</style>

View File

@ -4,33 +4,179 @@
<script setup>
import * as echarts from "echarts";
import { nextTick , onMounted, watch, defineProps } from "vue";
import { nextTick, onMounted, onUnmounted, watch, defineProps, ref } from "vue";
const props = defineProps({
echartsId:{
type:String,
default:'barHatId'
echartsId: {
type: String,
default: 'barHatId'
},
data:{
type:Object,
default:{
data: {
type: Object,
default: {
xDate: ['巴宜区', '工布江达县', '波密县', '朗县', '墨脱县', '察隅县', '米林县'],
list:[
{ name: "总数", value: [10,20,30,40,50,60,70] ,color:['rgba(0,244,255,1)','rgba(0,77,167,1)'] ,hatColor:'#087df9'},
{ name: "已处置", value: [10,20,30,40,50,60,70],color:['rgba(24, 232, 229, 1)','rgba(3, 110, 83, 1)'],hatColor:'#00FFFF' },
list: [
{ name: "总数", value: [10,20,30,40,50,60,70], color:['rgba(0,244,255,1)','rgba(0,77,167,1)'], hatColor:'#087df9'},
{ name: "已处置", value: [10,20,30,40,50,60,70], color:['rgba(24, 232, 229, 1)','rgba(3, 110, 83, 1)'], hatColor:'#00FFFF'},
],
}
},
// 新增:是否启用自动循环展示提示框
autoTooltip: {
type: Boolean,
default: false
},
// 新增:提示框循环间隔时间(毫秒)
tooltipInterval: {
type: Number,
default: 2000
},
// 新增:鼠标悬停时是否暂停循环
pauseOnHover: {
type: Boolean,
default: true
}
});
watch(()=>props.data,val=>{
nextTick(()=>{ handleDate() })
},{immediate:true,deep:true})
// 响应式变量
const myChart = ref(null);
const tooltipTimer = ref(null);
const currentTooltipIndex = ref(0);
const isPaused = ref(false);
watch(() => props.data, val => {
nextTick(() => { handleDate() })
}, { immediate: true, deep: true })
// 启动自动循环展示提示框
function startAutoTooltip() {
// 详细的条件检查和日志
if (!props.autoTooltip) {
return;
}
if (!props.data) {
// console.warn('自动提示框未启动 - 缺少数据');
return;
}
if (!props.data.xDate || props.data.xDate.length === 0) {
// console.warn('自动提示框未启动 - xDate数据为空');
return;
}
if (!props.data.list || props.data.list.length === 0) {
// console.warn('自动提示框未启动 - list数据为空');
return;
}
if (!myChart.value) {
// console.warn('自动提示框未启动 - 图表实例不存在');
return;
}
// 清除之前的定时器
stopAutoTooltip();
const dataLength = props.data.xDate.length;
currentTooltipIndex.value = 0;
// console.log(`开始自动提示框循环 - 数据长度: ${dataLength}, 间隔: ${props.tooltipInterval}ms`);
// console.log('数据预览:', {
// xDate: props.data.xDate.slice(0, 3),
// listCount: props.data.list.length,
// firstSeriesName: props.data.list[0]?.name,
// firstSeriesValueCount: props.data.list[0]?.value?.length
// });
tooltipTimer.value = setInterval(() => {
try {
// 检查图表实例是否仍然存在
if (!myChart.value) {
// console.error('图表实例丢失,停止自动提示框');
stopAutoTooltip();
return;
}
// 检查是否暂停
if (isPaused.value) {
// console.log('提示框循环已暂停');
return;
}
// 先隐藏当前提示框
myChart.value.dispatchAction({
type: 'hideTip'
});
// 延迟一点时间再显示新的提示框,确保动画效果
setTimeout(() => {
if (myChart.value && !isPaused.value) {
try {
// 获取当前数据点信息
const currentData = props.data.xDate[currentTooltipIndex.value];
const currentValues = props.data.list.map(series => series.value[currentTooltipIndex.value]);
// 验证数据有效性
if (currentData === undefined) {
// console.error(`数据索引 ${currentTooltipIndex.value} 超出范围`);
stopAutoTooltip();
return;
}
// 显示当前索引的提示框 - 使用第一个系列
myChart.value.dispatchAction({
type: 'showTip',
seriesIndex: 0,
dataIndex: currentTooltipIndex.value
});
// console.log(`✓ 显示提示框 [${currentTooltipIndex.value}/${dataLength-1}] - ${currentData}:`, currentValues);
} catch (error) {
// console.error('显示提示框时出错:', error);
// 如果出错,尝试停止循环避免持续错误
stopAutoTooltip();
}
}
}, 100);
// 更新索引,循环展示
currentTooltipIndex.value = (currentTooltipIndex.value + 1) % dataLength;
} catch (error) {
// console.error('自动提示框循环出错:', error);
stopAutoTooltip();
}
}, props.tooltipInterval);
// console.log(`✓ 自动提示框已启动 - 间隔: ${props.tooltipInterval}ms, 数据长度: ${dataLength}`);
}
// 停止自动循环展示提示框
function stopAutoTooltip() {
if (tooltipTimer.value) {
clearInterval(tooltipTimer.value);
tooltipTimer.value = null;
// console.log('自动提示框已停止');
}
}
// 暂停自动循环
function pauseAutoTooltip() {
isPaused.value = true;
// console.log('自动提示框已暂停');
}
// 恢复自动循环
function resumeAutoTooltip() {
isPaused.value = false;
// console.log('自动提示框已恢复');
}
// 处理数据
function handleDate() {
let xDate = props.data.xDate;
let legend = props.data.list.map(v=>{return {name:v.name}})
let series = props.data.list.map((item,i)=>{
let legend = props.data.list.map(v => { return { name: v.name } })
let series = props.data.list.map((item, i) => {
let obj = {
name: item.name,
type: "bar",
@ -38,15 +184,15 @@ function handleDate() {
barWidth: "10px",
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0,0,0,1,[
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: item.color ? item.color[0] : "rgba(0,244,255,1)" },
{ offset: 1, color: item.color ? item.color[1] : "rgba(0,77,167,1)" }],false),
{ offset: 1, color: item.color ? item.color[1] : "rgba(0,77,167,1)" }], false),
}
},
markPoint: {
symbol: 'path://M62 62h900v900h-900v-900z', // 使用 SVG path 绘制扁圆形状
symbolSize: [11, 4], // 设置扁圆的宽和高
itemStyle: { color: item.hatColor || '#087df9' },// 圆盘颜色
itemStyle: { color: item.hatColor || '#087df9' },// 圆盘颜色
data: item.value.map((obj, index) => ({
xAxis: index, // 对应柱子的横坐标
yAxis: obj + 0 // 柱子的值加上一些偏移量
@ -55,11 +201,11 @@ function handleDate() {
}
return obj
})
lineChartFn(xDate,legend,series)
lineChartFn(xDate, legend, series)
}
function lineChartFn(xDate,legend,series) {
var myChart = echarts.init(document.getElementById(props.echartsId));
function lineChartFn(xDate, legend, series) {
myChart.value = echarts.init(document.getElementById(props.echartsId));
var option = {
legend: {
type: "plain",
@ -69,15 +215,65 @@ function lineChartFn(xDate,legend,series) {
data: legend
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow"
trigger: "item",
backgroundColor: 'rgba(0, 0, 0, 0.9)',
borderColor: '#00d4ff',
borderWidth: 2,
borderRadius: 8,
textStyle: {
color: '#fff',
fontSize: 13,
fontWeight: 'normal'
},
formatter: function(params) {
// 获取当前数据点的所有系列信息
const dataIndex = params.dataIndex;
const categoryName = params.name;
let result = `<div style="margin-bottom: 8px; font-weight: bold; color: #00d4ff; font-size: 14px; border-bottom: 1px solid #00d4ff; padding-bottom: 4px;">${categoryName}</div>`;
// 遍历所有系列,显示该数据点的所有信息
if (props.data && props.data.list) {
props.data.list.forEach((seriesData, index) => {
const value = seriesData.value[dataIndex];
const color = seriesData.color ? seriesData.color[0] : '#00d4ff';
result += `<div style="margin: 4px 0; display: flex; align-items: center;">
<span style="display: inline-block; width: 12px; height: 12px; background: ${color}; border-radius: 50%; margin-right: 8px; border: 1px solid rgba(255,255,255,0.3);"></span>
<span style="color: #fff; margin-right: 8px; min-width: 60px;">${seriesData.name}:</span>
<span style="color: #00d4ff; font-weight: bold; font-size: 14px;">${value}</span>
</div>`;
});
}
return result;
},
// 确保提示框能够正确显示
confine: true,
// 添加动画效果
transitionDuration: 0.2,
// 设置提示框位置
position: function (point, params, dom, rect, size) {
// 计算提示框位置,避免超出边界
let x = point[0] + 15;
let y = point[1] - 10;
// 如果右侧空间不够,显示在左侧
if (x + size.contentSize[0] > size.viewSize[0]) {
x = point[0] - size.contentSize[0] - 15;
}
// 如果上方空间不够,显示在下方
if (y < 0) {
y = point[1] + 20;
}
return [x, y];
}
},
grid: {
top: "25%",
right: "8%",
left: "10%",
right: "2%",
left: "6%",
bottom: "22%"
},
xAxis: [
@ -120,13 +316,46 @@ function lineChartFn(xDate,legend,series) {
],
series: series
};
option && myChart.setOption(option);
window.onresize = function () { myChart.resize(); };
document.getElementById(props.echartsId).setAttribute("_echarts_instance_", "");
option && myChart.value.setOption(option);
// 添加鼠标事件监听
if (props.pauseOnHover) {
myChart.value.on('mouseover', () => {
pauseAutoTooltip();
});
myChart.value.on('mouseout', () => {
resumeAutoTooltip();
});
}
// 启动自动循环展示
if (props.autoTooltip) {
setTimeout(() => {
startAutoTooltip();
}, 1000); // 延迟1秒启动确保图表完全渲染
}
window.onresize = function () {
if (myChart.value) {
myChart.value.resize();
}
};
}
onMounted(() => {
lineChartFn();
});
// 组件卸载时清理定时器
onUnmounted(() => {
stopAutoTooltip();
if (myChart.value) {
myChart.value.dispose();
myChart.value = null;
}
});
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,171 @@
<template>
<div class="tooltip-demo">
<div class="demo-header">
<h2>ECharts 提示框循环展示演示</h2>
<div class="controls">
<el-button @click="toggleAutoTooltip" :type="autoTooltip ? 'success' : 'info'">
{{ autoTooltip ? '停止循环' : '开始循环' }}
</el-button>
<el-button @click="changeInterval">
切换间隔 (当前: {{ tooltipInterval }}ms)
</el-button>
<el-button @click="changeData">
切换数据
</el-button>
</div>
</div>
<div class="chart-container">
<BarHatEcharts
:data="currentData"
:autoTooltip="autoTooltip"
:tooltipInterval="tooltipInterval"
:pauseOnHover="true"
echartsId="tooltipDemoChart"
/>
</div>
<div class="feature-description">
<h3>功能说明</h3>
<ul>
<li> <strong>自动循环展示</strong>提示框会按设定间隔自动循环显示每个数据点的信息</li>
<li> <strong>智能暂停</strong>鼠标悬停在图表上时自动暂停循环离开时恢复</li>
<li> <strong>可配置间隔</strong>支持自定义循环间隔时间123</li>
<li> <strong>美观样式</strong>深色主题提示框蓝色边框清晰的数据展示</li>
<li> <strong>错误处理</strong>完善的错误处理机制确保稳定运行</li>
<li> <strong>生命周期管理</strong>组件卸载时自动清理定时器防止内存泄漏</li>
</ul>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import BarHatEcharts from './barHatEcharts.vue';
const autoTooltip = ref(true);
const tooltipInterval = ref(2000);
const dataSet1 = {
xDate: ['巴宜区', '工布江达县', '波密县', '朗县', '墨脱县', '察隅县', '米林县'],
list: [
{ name: "总数", value: [10,20,30,40,50,60,70], color:['rgba(0,244,255,1)','rgba(0,77,167,1)'], hatColor:'#087df9'},
{ name: "已处置", value: [8,15,25,35,45,55,65], color:['rgba(24, 232, 229, 1)','rgba(3, 110, 83, 1)'], hatColor:'#00FFFF'},
]
};
const dataSet2 = {
xDate: ['东城区', '西城区', '朝阳区', '丰台区', '石景山区', '海淀区'],
list: [
{ name: "报警数量", value: [25,35,45,30,20,40], color:['rgba(255,99,132,1)','rgba(255,99,132,0.3)'], hatColor:'#ff6384'},
{ name: "处理完成", value: [20,30,40,25,18,35], color:['rgba(54,162,235,1)','rgba(54,162,235,0.3)'], hatColor:'#36a2eb'},
{ name: "待处理", value: [5,5,5,5,2,5], color:['rgba(255,206,86,1)','rgba(255,206,86,0.3)'], hatColor:'#ffce56'},
]
};
const currentData = ref(dataSet1);
function toggleAutoTooltip() {
autoTooltip.value = !autoTooltip.value;
}
function changeInterval() {
const intervals = [1000, 2000, 3000];
const currentIndex = intervals.indexOf(tooltipInterval.value);
const nextIndex = (currentIndex + 1) % intervals.length;
tooltipInterval.value = intervals[nextIndex];
}
function changeData() {
currentData.value = currentData.value === dataSet1 ? dataSet2 : dataSet1;
}
</script>
<style lang="scss" scoped>
.tooltip-demo {
padding: 20px;
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
min-height: 100vh;
color: #fff;
}
.demo-header {
margin-bottom: 30px;
text-align: center;
h2 {
margin-bottom: 20px;
color: #00d4ff;
font-size: 28px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.controls {
display: flex;
justify-content: center;
gap: 15px;
flex-wrap: wrap;
}
}
.chart-container {
height: 400px;
background: rgba(0,29,75,0.6);
border-radius: 8px;
padding: 20px;
margin-bottom: 30px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.feature-description {
background: rgba(0,0,0,0.3);
padding: 20px;
border-radius: 8px;
border-left: 4px solid #00d4ff;
h3 {
color: #00d4ff;
margin-bottom: 15px;
font-size: 20px;
}
ul {
list-style: none;
padding: 0;
li {
margin-bottom: 10px;
padding-left: 10px;
line-height: 1.6;
strong {
color: #00d4ff;
}
}
}
}
:deep(.el-button) {
background: rgba(0,212,255,0.2);
border-color: #00d4ff;
color: #00d4ff;
&:hover {
background: rgba(0,212,255,0.3);
border-color: #00d4ff;
color: #fff;
}
&.el-button--success {
background: rgba(103,194,58,0.2);
border-color: #67c23a;
color: #67c23a;
&:hover {
background: rgba(103,194,58,0.3);
border-color: #67c23a;
color: #fff;
}
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div style="pointer-events: none" :class="props.parentClass">
<el-dialog :top="props.top" style="pointer-events: auto !important;" :modal="false" draggable v-model="props.modelValue" :destroy-on-close="true"
:show-close="false" :close-on-click-modal="false" :width="width" :custom-class="coumClass">
:show-close="false" :close-on-click-modal="false" :width="width" :custom-class="coumClass" :append-to-body="true">
<template #title>
<div class="my-header">
<span class="imgIcon"> {{props.title}}</span>
@ -82,9 +82,8 @@ function closeDialog(params) {
padding: 8px 10px;
box-sizing: border-box;
pointer-events: auto !important;
height:calc(100% - 300px);
/* height:calc(100% - 300px); */
overflow: auto;
}
.zdy-model-dialog .el-dialog__header {
padding: 0 !important;

View File

@ -0,0 +1,114 @@
<template>
<div class="flowLine">
<svg width="1919" height="58" viewBox="0 0 1919 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- 背景路径 - 静态 -->
<path class="path-bg" d="M0.5 2H700.5L711.5 16.5H740.5L778 56H1138L1175 16.5H1204L1213 2H1918.5" stroke="rgba(0, 114, 255, 0.2)" stroke-width="4"/>
<!-- 动画路径 - 带描边效果 -->
<path class="path-animated" d="M0.5 2H700.5L711.5 16.5H740.5L778 56H1138L1175 16.5H1204L1213 2H1918.5" stroke="url(#paint0_linear_2539_19618)" stroke-width="4"/>
<!-- 主发光点 -->
<circle class="glow-dot" r="6" fill="url(#radialGradient)">
<animateMotion dur="6s" repeatCount="indefinite" rotate="auto">
<mpath href="#motionPath" />
</animateMotion>
<animate attributeName="r" values="5;7;5" dur="2s" repeatCount="indefinite" />
</circle>
<!-- 次要发光点 -->
<circle class="glow-dot secondary" r="4" fill="url(#radialGradient2)">
<animateMotion dur="6s" repeatCount="indefinite" rotate="auto" begin="1s">
<mpath href="#motionPath" />
</animateMotion>
<animate attributeName="r" values="3;5;3" dur="1.5s" repeatCount="indefinite" />
</circle>
<!-- 用于动画的隐藏路径 -->
<path id="motionPath" d="M0.5 2H700.5L711.5 16.5H740.5L778 56H1138L1175 16.5H1204L1213 2H1918.5" stroke="none"/>
<defs>
<linearGradient id="paint0_linear_2539_19618" x1="852.344" y1="1.29965" x2="853.359" y2="67.7414" gradientUnits="userSpaceOnUse">
<stop stop-color="#0072FF"/>
<stop offset="0.54596" stop-color="#00FFFF"/>
<stop offset="1" stop-color="#0072FF"/>
</linearGradient>
<radialGradient id="radialGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(0 0) scale(10)">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/>
<stop offset="40%" stop-color="#00FFFF" stop-opacity="1"/>
<stop offset="70%" stop-color="#0072FF" stop-opacity="0.8"/>
<stop offset="100%" stop-color="#0072FF" stop-opacity="0"/>
</radialGradient>
<radialGradient id="radialGradient2" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(0 0) scale(8)">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.9"/>
<stop offset="50%" stop-color="#00FFFF" stop-opacity="0.8"/>
<stop offset="100%" stop-color="#0072FF" stop-opacity="0"/>
</radialGradient>
<!-- 增强的滤镜效果 -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.5 0 0 0 0 1 0 0 0 1 0" result="blue-glow"/>
<feBlend in="SourceGraphic" in2="blue-glow" mode="screen"/>
</filter>
</defs>
</svg>
</div>
</template>
<script setup>
</script>
<style scoped>
.flowLine {
width: 100%;
height: 100%;
position: absolute;
top: 10px;
pointer-events: none;
pointer-events: none;
}
.zdy_line_svg {
width: 100%;
height: 100%;
}
/* 描边动画效果 */
.path-animated {
stroke-dasharray: 3000;
stroke-dashoffset: 3000;
animation: dash 8s cubic-bezier(0.4, 0, 0.2, 1) forwards infinite;
filter: url(#glow);
will-change: stroke-dashoffset;
}
.glow-dot {
filter: url(#glow);
will-change: transform;
}
.glow-dot.secondary {
opacity: 0.7;
}
@keyframes dash {
0% {
stroke-dashoffset: 3000;
opacity: 0.3;
}
30% {
stroke-dashoffset: 0;
opacity: 1;
}
70% {
stroke-dashoffset: 0;
opacity: 1;
}
100% {
stroke-dashoffset: -3000;
opacity: 0.3;
}
}
</style>

View File

@ -1,5 +1,6 @@
<template>
<div class="headBox">
<FlowLine></FlowLine>
<div class="headBoxBg">
<!-- 左边 -->
<el-popover width="480px" :visible="isShowVisble" :append-to-body="true" trigger="click" popper-class="bszdr-tq-Popover" >
@ -84,10 +85,12 @@
</div>
</ul>
</div>
</div>
</template>
<script setup>
import FlowLine from './flowLine.vue'
import { getItem } from "@/utils/storage";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
@ -277,5 +280,7 @@ onUnmounted(() => {
background: transparent !important;
}
}
</style>

View File

@ -0,0 +1,10 @@
<svg width="1919" height="58" viewBox="0 0 1919 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.5 2H700.5L711.5 16.5H740.5L778 56H1138L1175 16.5H1204L1213 2H1918.5" stroke="url(#paint0_linear_2539_19618)" stroke-width="4"/>
<defs>
<linearGradient id="paint0_linear_2539_19618" x1="852.344" y1="1.29965" x2="853.359" y2="67.7414" gradientUnits="userSpaceOnUse">
<stop stop-color="#0072FF"/>
<stop offset="0.54596" stop-color="#00FFFF"/>
<stop offset="1" stop-color="#0072FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 525 B

View File

@ -3,7 +3,7 @@
<span class="title">情报来源类型</span>
</div>
<div class="comom-cnt">
<BarHatEcharts echartsId="qbltBox" :data="list"></BarHatEcharts>
<BarHatEcharts echartsId="qbltBox" :autoTooltip="true" :data="list"></BarHatEcharts>
</div>
</template>

View File

@ -11,7 +11,6 @@ const loginDialog = ref(false);
const deptList = ref([]);
const store = useStore();
function redirectAuth() {
let token = location.hash.slice(20) || null;
if (token != null) {
token = token.replace(/\ +/g, "");