This commit is contained in:
lcw
2025-12-05 21:36:34 +08:00
parent 64ab9fc44c
commit b39387c4ed
97 changed files with 3342 additions and 298 deletions

View File

@ -10,7 +10,6 @@
</template>
<script setup>
import * as ocr from "@paddlejs-models/ocr";
import Watermark from "@/components/Watermark.vue";
import { ref, reactive, nextTick, provide, onMounted, getCurrentInstance, onBeforeUnmount } from "vue";
import { useStore } from "vuex";
@ -19,14 +18,15 @@ import { getItem, setItem } from "@/utils/storage";
import { generateNewStyle, writeNewStyle } from "@/utils/theme";
import { timeValidate } from "@/utils/tools";
import Fzq from '@/components/fzq/index.vue'
import router from "./router";
import * as ocr from "@paddlejs-models/ocr";
const { proxy } = getCurrentInstance();
const store = useStore();
generateNewStyle(store.getters.mainColor).then((newStyle) => {
writeNewStyle(newStyle);
});
// 只在首次加载时调用一次避免多次创建style元素
if (!document.getElementById('dynamic-theme-style')) {
generateNewStyle(store.getters.mainColor).then((newStyle) => {
writeNewStyle(newStyle);
});
}
const isRouterAlive = ref(true);
const reload = () => {
isRouterAlive.value = false;
@ -60,11 +60,18 @@ const initPage = async () => {
}
}
const content = ref([])
const frashJs = () => {
const sfzh = getItem("idEntityCard")
const userName = getItem("USERNAME")
// 获取初始水印内容
const getWatermarkContent = () => {
const sfzh = getItem("idEntityCard") || ''
const userName = getItem("USERNAME") || ''
const time = timeValidate()
content.value = [userName, sfzh, time, "林芝哨岗系统", "禁止泄露公民个人信息和警务工作秘密"]
return [userName, sfzh, time, "林芝哨岗系统", "禁止泄露公民个人信息和警务工作秘密"]
}
// 初始化水印内容
content.value = getWatermarkContent()
// 只在需要时调用,避免频繁更新导致重新渲染
const frashJs = () => {
content.value = getWatermarkContent()
}
// 监听标签页切换

View File

@ -319,15 +319,19 @@ const uploadFile = (file) =>{
// 刷新js
// 全局变量用于跟踪OCR模型是否已经初始化
let ocrModelInitialized = false;
// 只初始化一次OCR模型
const frashJs = async () =>{
if(!imgIsLoad){
if(!ocrModelInitialized){
try {
await ocr.init();// 模型初始化
imgIsLoad = true;
ocrModelInitialized = true;
proxy.$message({ type: "success", message: "加载成功" });
} catch (err) {
proxy.$message({ type: "error", message: "加载失败,请刷新页面" });
imgIsLoad = false;
ocrModelInitialized = false;
}
}
}

View File

@ -5,7 +5,7 @@
<!-- 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" />
<el-input v-model="listQuery[item.prop]" v-else-if="item.type == 'textarea'" type="textarea" :rows="item.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" />
<!-- 数值 number-->

View File

@ -1,16 +1,25 @@
<template>
<div style="width: 100%" :class="getConfiger.showSelectType === 'radio' ? 'tabBoxRadio' : ''">
<!-- hasChildren要在tableData中定义表示当前行有没有下一级 children要在tableData中定义表示下一级的数据-->
<el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange"
:row-key="getConfiger.rowKey" :border="getConfiger.border" :default-expand-all="getConfiger.defaultExpandAll"
:stripe="getConfiger.stripe" :height="tableHeight" v-loading="tableConfiger.loading" :lazy="getConfiger.lazy"
: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' }">
:row-style="(row, index) => getRowStyle(row, index)"
:row-class-name="(row, index) => getRowClassName(row, index)">
<!-- 修改v-if条件让showSelectType为null时也能显示选择列默认为复选框 -->
<el-table-column style="width: 55px" type="selection" width="55" v-if="getConfiger.showSelectType !='null'" :class="getConfiger.showSelectType === 'radio' ? 'tabBoxRadio' : ''" />
<el-table-column style="width: 55px" type="selection" width="55" v-if="getConfiger.showSelectType != 'null'"
:class="getConfiger.showSelectType === 'radio' ? 'tabBoxRadio' : ''" />
<el-table-column type="expand" v-if="expand">
<template #default="props">
<slot name="expand" :props="props.row"></slot>
</template>
</el-table-column>
<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"
@ -18,7 +27,6 @@
:show-overflow-tooltip="item.showOverflowTooltip || false" :sortable="item.sortable || false">
<!-- 使用自定义 -->
<template v-if="item.showSolt" #default="scope">
<slot :name="item.prop" v-bind="scope"></slot>
</template>
<!-- 默认 -->
@ -72,6 +80,18 @@ const props = defineProps({
fixed: {
type: String,
default: "right"
},
expand: {
type: Boolean,
default: false
},
rowStyle: {
type: Function,
default: null
},
rowClassName: {
type: Function,
default: null
}
});
// 可选的时候选择的数据
@ -133,6 +153,30 @@ const load = (date, treeNode, resolve) => {
]);
}, 1000);
};
// 获取行样式
const getRowStyle = (row, index) => {
// 基础行高样式
const baseStyle = { height: getConfiger.rowHeight === 'auto' ? getConfiger.rowHeight : getConfiger.rowHeight + 'px' };
// 如果有自定义行样式函数,合并样式
if (props.rowStyle) {
const customStyle = props.rowStyle(row, index);
return { ...baseStyle, ...customStyle };
}
return baseStyle;
};
// 获取行类名
const getRowClassName = (row, index) => {
// 如果有自定义行类名函数,使用它
if (props.rowClassName) {
return props.rowClassName(row, index);
}
return '';
};
// 设置默认选中(在调用的父页面要确保 tableData传出来了如果延迟传过来默认选中不会生效
function setDefaultChoose() {
nextTick(() => {
@ -160,5 +204,4 @@ function setDefaultChoose() {
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -118,6 +118,10 @@ onMounted(() => {
emitter.on("handleClick", () => {
idEntityCard.value = getItem('idEntityCard')
handleClick()
// 清除旧定时器,避免多个定时器同时运行
if (intTime.value) {
clearInterval(intTime.value)
}
intTime.value = setInterval(() => {
handleClick()
}, 60000)

View File

@ -12,7 +12,7 @@ export const MAIN_COLOR = "mainColor";
//默认主题色
export const DEFAULT_COLOR = "#409eff";
localStorage.getItem('token');
// tags
export const TAGS_VIEW = "tagsView";

View File

@ -1,6 +1,5 @@
import permission from "./permission";
export default app => {
app.directive('permission',permission)
app.directive('permission', permission)
}

View File

@ -17,44 +17,54 @@ const whiteList = ['/login', '/oatuh_login', '/404', '/401', '/zeroTrust_login',
* from 来自哪
* next 往下走
*/
let onRun = true;
router.beforeEach(async (to, from, next) => {
// 存在 token ,进入主页
// if (store.state.user.token) {
// 快捷访问
console.log(store.getters.token);
if (store.getters.token) {
console.log("路由1");
// 判断用户资料是否获取
// 若不存在用户信息,则需要获取用户信息
// 触发获取用户信息的 action并获取用户当前权限
await store.commit('permission/setRouteReady', true)
store.commit('permission/setRouteReady', 1)
// 添加完动态路由之后,需要在进行一次主动跳转
const afterMenuList = await getItem('menusPermission');
const afterMenuList = getItem('menusPermission');
// 处理用户权限,筛选出需要添加的权限
if (store.state.permission.routes == 0) {
console.log(store.state.permission.routes);
if (store.state.permission.routes.length === 0) {
const filterRoutes = await store.dispatch('permission/filterRoutes', afterMenuList)
filterRoutes.forEach(item => {
router.addRoute(item)
})
console.log("已添加动态路由");
next({
...to,
replace: true
})
} else {
console.log('已存在路由');
next()
}
// 利用 addRoute 循环添加
} else {
// 没有token的情况下可以进入白名单
if (whiteList.indexOf(to.path) > -1) {
console.log("路由2");
next()
} else {
const cookie = getCookie("clientKey");
if (cookie) {
console.log("路由3");
next(`/zeroTrust_login`)
} else {
console.log("路由4");
const isOatuh = getItem('isOatuh')
// 没有token的情况下可以进入白名单
if (isOatuh) {
console.log("路由5");
const idEntityCard = getItem('idEntityCard')
next(`/oatuh_login?token=${Base64.encode(idEntityCard)}`)
} else {

View File

@ -128,7 +128,15 @@ export const publicRoutes = [
title: "系统配置",
icon: "article-ranking"
}
}
}, {
path: "/calendar",
name: "calendar",
component: () => import("@/views/backOfficeSystem/calendar/index.vue"),
meta: {
title: "敏感节点",
icon: "article"
}
},
]
},
{
@ -249,6 +257,24 @@ export const publicRoutes = [
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/warningBk/index"),
// },
{
path: "/identityWarning",
name: "identityWarning",
meta: { title: "身份预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/identityWarning/index"),
},
{
path: "/behaviorWarning",
name: "behaviorWarning",
meta: { title: "行为预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/behaviorWarning/index"),
},
{
path: "/combinedWarning",
name: "combinedWarning",
meta: { title: "组合预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/combinedWarning/index"),
}, {
path: "/warningList",
name: "warningList",
component: () => import("@/views/backOfficeSystem/fourColorManage/warningList/index"),
@ -257,24 +283,6 @@ export const publicRoutes = [
icon: "article"
}
},
{
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",
@ -282,12 +290,6 @@ export const publicRoutes = [
// component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/modelWarning/index"),
// },
{
path: "/fouColorWarning",
name: "fouColorWarning",
meta: { title: "四色预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/fouColorWarning/index"),
},
]
},
@ -412,8 +414,40 @@ export const publicRoutes = [
title: "数据监测",
icon: "article"
}
}, {
path: "/ssemanticAnalysis",
name: "semanticAnalysis",
component: () => import("@/views/backOfficeSystem/SemanticAnalysis/index.vue"),
meta: {
title: "语义分析",
icon: "article"
}
},
{
path: "/StatisticalAnalysis",
name: "StatisticalAnalysis",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/StatisticalAnalysis/index"),
meta: {
title: "情报统计分析",
icon: "article"
}
}, {
path: "/InstructionInformation",
name: "InstructionInformation",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/InstructionInformation/index"),
meta: {
title: "情报指令",
icon: "article"
}
}, {
path: "/RecordsOperations",
name: "RecordsOperations",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/RecordsOperations/index"),
meta: {
title: "操作记录",
icon: "article"
}
}
]
},
{
@ -483,9 +517,9 @@ export const publicRoutes = [
meta: { title: "信息汇聚支撑", icon: "article" },
children: [
{
path: "/CollectCrculate",
name: "CollectCrculate",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"),
path: "/InfoCollection",
name: "InfoCollection",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/infoCollection/index"),
meta: { title: "信息采集", icon: "article" },
},
{
@ -537,15 +571,7 @@ export const publicRoutes = [
icon: "article"
}
},
{
path: "/ssemanticAnalysis",
name: "semanticAnalysis",
component: () => import("@/views/backOfficeSystem/SemanticAnalysis/index.vue"),
meta: {
title: "语义分析",
icon: "article"
}
},
// 暂时不要
// {
// path: "/MoralAnalysis",
@ -571,35 +597,11 @@ export const publicRoutes = [
meta: { title: "情报流转", icon: "article" },
redirect: "/InformationFlow",
children: [
{
path: "/InstructionInformation",
name: "InstructionInformation",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/InstructionInformation/index"),
meta: {
title: "指令信息",
icon: "article"
}
},
{
path: "/StatisticalAnalysis",
name: "StatisticalAnalysis",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/InformationFlows/StatisticalAnalysis/index"),
meta: {
title: "情报统计分析",
icon: "article"
}
}
]
},
{
path: "/RecordsOperations",
name: "RecordsOperations",
component: () => import("@/views/backOfficeSystem/ResearchJudgment/RecordsOperations/index"),
meta: {
title: "操作记录",
icon: "article"
}
}
]
},
@ -810,25 +812,39 @@ export const publicRoutes = [
icon: "article"
}
},
]
},
{
path: "/forumPost",
name: "forumPost",
component: () => import("@/views/forumPost/index.vue"),
meta: {
title: "情报论坛",
icon: "article"
}
},
{
path: "/rests",
name: "rests",
meta: {
title: "其他",
icon: "article"
},
children: [
{
path: "/calendar",
name: "calendar",
component: () => import("@/views/backOfficeSystem/calendar/index.vue"),
meta: {
title: "敏感节点",
icon: "article"
}
path: "/fouColorWarning",
name: "fouColorWarning",
meta: { title: "四色预警", icon: "article" },
component: () => import("@/views/backOfficeSystem/fourColorManage/warningControl/fouColorWarning/index"),
}, {
path: "/forumPost",
name: "forumPost",
component: () => import("@/views/forumPost/index.vue"),
meta: {
title: "情报论坛",
icon: "article"
}
path: "/CollectCrculate",
name: "CollectCrculate",
component: () => import("@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/index"),
meta: { title: "信息采集", icon: "article" },
},
]
}
},
]
}
];

View File

@ -21,7 +21,7 @@ export default {
state.routes = [...publicRoutes, ...newRoutes]
},
setRouteReady(state, num) {
state.routeReady = state.routeReady + num;
state.routeReady = num;
},
resetrouteReady(state) {
state.routeReady = 0
@ -36,26 +36,24 @@ export default {
*/
filterRoutes(context, menus) {
let routes = []
// 路由权限匹配
// menus.forEach(key => {
// // 权限名 与 路由的 name 匹配
// routes.push(...privateRoutes.filter(item => item.name === key))
// })
/**
* 树结构数据条件过滤
* js 指定删除数组(树结构数据)
* 根据用户权限筛选出可访问的路由
*/
//测试比对
// routes = filter(privateRoutes, menus)
if (menus && menus.length > 0) {
routes = filter(privateRoutes, menus)
}
// 最后添加 不匹配路由进入 404
routes.push({
path: '/:catchAll(.*)',
redirect: '/404'
})
context.commit('setRoutes', routes);
context.commit('setRouteReady', 1);
// context.commit('setRouteReady', true);
return routes
}
}

View File

@ -26,6 +26,7 @@ export const generateNewStyle = async (parimaryColor) => {
*/
export const writeNewStyle = (newStyle) => {
const style = document.createElement('style');
style.id = 'dynamic-theme-style'; // 添加唯一标识
style.innerText = newStyle;
document.head.appendChild(style);
};

View File

@ -362,3 +362,15 @@ export function getUUid() {
let uuid = list.join("");
return uuid;
}
// 预警等级颜色
export const bqYs = (val) => {
if (val == '01') {
return '#ff0202'
} else if (val == '02') {
return '#ff8c00'
} else if (val == '03') {
return '#ffd208ff'
} else if (val == '04') {
return '#0000ff'
}
}

View File

@ -127,7 +127,7 @@ const changeSize = (val) => {
// 获取列表
const getList = () => {
};
// 表格高度计算

View File

@ -18,41 +18,46 @@
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量转线索</span>
<span style="vertical-align: middle">转线索</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量转合成</span>
<span style="vertical-align: middle">转合成</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量打标</span>
<span style="vertical-align: middle">打标</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="handleSumbit(ids)" v-if="qxkz.deptLevel != '01'">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量上报</span>
<span style="vertical-align: middle">上报</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="delDictItem(ids)">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量删除</span>
<span style="vertical-align: middle">删除</span>
</el-button>
<el-button type="success" @click="openSearch">
<Search style="width: 1em; height: 1em; margin-right: 8px" />
<span style="vertical-align: middle" v-if="!search">搜索</span>
<span style="vertical-align: middle" v-else>关闭搜索</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
<div ref="searchBox" v-if="search">
<Searchs :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
</div>
<!-- 表格 -->
<div class="tabBox">
<div class="tabBox" :style="{ height: (pageData.tableHeight + 40) + 'px' }">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData">
@ -68,17 +73,16 @@
<!-- 操作 -->
<template #controls="{ row }">
<!-- 01 提交 02 上报 03 采纳 04 退回 05 打标签v-if="qxkz.deptLevel == '01'" -->
<el-link size="small" type="primary" v-if="row.czzt == '02' && qxkz.depBool"
@click="cnMsg(row)">采纳</el-link>
<el-link size="small" type="primary" v-if="row.czzt == '02' && qxkz.depBool" @click="cnMsg(row)">采纳</el-link>
<el-link size="small" type="primary" v-if="row.czzt == '03' && qxkz.depBool"
@click="opneMsg(row)">打标签</el-link>
<el-link size="small" type="primary" @click="rollbackNewspapers(row)"
v-if="row.czzt == '02' && row.qbjb == '00' &&row.fxjsfsb!=1&&row.pcssfsb!=0&& qxkz.depBool">回退</el-link>
v-if="row.czzt == '02' && row.qbjb == '00' && row.fxjsfsb != 1 && row.pcssfsb != 0 && qxkz.depBool">回退</el-link>
<el-link size="small" type="primary" @click="checkProcess(row)">查看流程</el-link>
<el-link size="small" type="primary" @click="appearNewspapers(row)"
v-if="(row.czzt == '01' || row.czzt == '04') && row.qbjb == '00' && qxkz.deptLevel != '01'">上报</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转线索</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转合成</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转合成</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">转会商</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
<el-link size="small" type="primary" @click="addEdit('edit', row)">修改</el-link>
@ -118,11 +122,11 @@ import * as MOSTY from "@/components/MyComponents/index";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import Searchs from "@/components/aboutTable/Search.vue";
import AddForm from "./components/addForm.vue";
import { useRouter, useRoute } from 'vue-router'
import { qbcjSelectQbsbPage, qbcjDeletes, qbcjCzzt, qbcjPlsb } from "@/api/Intelligence.js";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
import MakeTag from '../components/maketag.vue'
import ExportFile from './components/exportFile.vue'
import CheckProcess from '../components/checkProcess.vue'
@ -177,15 +181,16 @@ const pageData = reactive({
},
controlsWidth: 240,
tableColumn: [
{ label: "上报人姓名", prop: "xssbr" },
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "情报编号", prop: "xsBh" },
{ label: "上报人姓名", prop: "xssbr" },
{ label: "情报标题", prop: "qbmc" },
{ label: "情报类型", prop: "qblx", showSolt: true },
{ label: "情报来源", prop: "cjlx", showSolt: true },
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "指向地点", prop: "zxdz" },
{ label: "消息状态", prop: "czzt", showSolt: true },
{ label: "情报内容", prop: "qbnr" },
// { label: "情报内容", prop: "qbnr" },
]
});
const queryFrom = ref({});
@ -234,7 +239,7 @@ const cnMsg = (item) => {
}).catch(() => { });
}
// 批量打标
// 打标
const batchMark = () => {
const listDb = tableList.value.filter(item => item.czzt != '03')
if (listDb.length == 0) {
@ -332,13 +337,7 @@ const addEdit = (type, row) => {
detailDiloag.value.init(type, row);
}, 500)
};
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
const route = useRoute()
const titleData = ref()
const qxkz = reactive({
@ -372,12 +371,30 @@ onMounted(() => {
});
const getRouter = () => {
titleData.value = route.meta.title
}
const exportFileModel = ref(false)
const dologCancel = () => {
exportFileModel.value = true;
}
// 搜索栏
const search = ref(false)
const openSearch = () => {
search.value = !search.value
nextTick(() => {
tabHeightFn()
})
}
// 表格高度计算
const tabHeightFn = () => {
if (search.value) {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
} else {
pageData.tableHeight = window.innerHeight - 250;
}
window.onresize = function () {
tabHeightFn();
};
};
// 流程
const checkProcessModel = ref()
const checkProcess = (item) => {

View File

@ -0,0 +1,389 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">{{ titleData }}{{ title }}</span>
<div>
<el-button @click="submitForm()" type="primary" v-if="!disabled">保存</el-button>
<el-button @click="close">关闭</el-button>
</div>
</div>
<div class="form-container">
<div class="form-content" v-loading="loading">
<!-- <div class="form_cnt"> -->
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
</FormMessage>
<!-- </div> -->
</div>
<div class="ml50 mr50 timeline-container">
<div class="timeline-title">信息流程展示</div>
<el-timeline class="timeline-full-width">
<el-timeline-item :timestamp="item.czsj" placement="top" v-for="(item, index) in lcList" :key="index">
<el-card class="process-card">
<div class="process-info">
<div class="info-label">处置人</div>
<div class="info-value">{{ item.czrxm || '未记录' }}</div>
</div>
<div class="process-info">
<div class="info-label">处置结果</div>
<div class="info-value">
<DictTag :tag="false" :value="item.czzt" :options="dict.D_BZ_QBCZZT" />
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
<MOSTY.Empty :show="lcList.length == 0" :imgSize="100"></MOSTY.Empty>
</div>
</div>
</div>
<!-- <pursueContent v-model="pursueShow" :dataList="dataList" :updeteBool="true" @getqbcjCzztList="getqbcjCzztList" /> -->
</template>
<script setup>
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qbcjAdd, qbcjUpdate, qbcjSelectByid } from "@/api/Intelligence.js";
// import pursueContent from "@/views/backOfficeSystem/HumanIntelligence/components/pursueContent.vue";
import { ref, defineExpose, onMounted, defineEmits, watch, getCurrentInstance } from "vue";
import { useRoute, useRouter } from 'vue-router'
import { qbcjCzztList, qbcjCzztDelete } from '@/api/qbcj'
import * as MOSTY from "@/components/MyComponents/index";
import { qbcjSelectCzlcList } from "@/api/Intelligence.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(["getList"]);
const props = defineProps({
dict: Object,
titleData: {
type: String,
default: ""
},
showBc: {
type: Boolean,
default: false
}
});
const loading = ref(false)
const dialogForm = ref(false); //弹窗
const formData = ref();
const rules = ref({
qbmc: [{ required: true, message: "请输入情报标题", trigger: "blur" }],
qbnr: [{ required: true, message: "请输入情报内容", trigger: "blur" }],
})
watch(() => dialogForm.value, (val) => {
if (val) {
formData.value = [
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' },
{ label: "情报等级", prop: "qbmj", type: "select", options: props.dict.D_BZ_BMJB, width: '45%' },
{ label: "情报内容", prop: "qbnr", type: "textarea", width: '100%', rows: 100 },
{ label: "附件上传", prop: "fjdz", type: "upload", width: '100%', isImg: false },
]
}
}, { deep: true })
const fjdz = ref()
const listQuery = ref({}); //表单
const elform = ref();
onMounted(() => {
})
const addForm = ref()
const msgeDat = ref()
const title = ref("")
const showPj = ref(false)
const disabled = ref(false)
// 初始化数据
const init = (type, row) => {
title.value = type == "add" ? "新增" : type == "info" ? "详情" : "编辑"
disabled.value = type == 'info' ? true : false
fjdz.value = []
dialogForm.value = true;
if (type == 'info' || type == 'edit') {
showPj.value = true
msgeDat.value = row
getqbcjPldb(row.id)
// 初始化表单数据,并根据详情页设置禁用状态
if (row) getDataById(row.id);
getqbcjCzztList()
} else {
showPj.value = false
}
};
// 根据id查询详情
const getDataById = (id) => {
qbcjSelectByid({ id }).then((res) => {
fjdz.value = res.ossList || [];
listQuery.value = res;
});
};
// 新增
const submitForm = () => {
loading.value = true
elform.value.submit(valid => {
if (valid) {
const promes = {
...listQuery.value,
cjLx: 0
}
if (title.value == '新增') {
qbcjAdd(promes).then((res) => {
emit("getList")
close()
}).finally(() => {
loading.value = false
})
} else if (title.value == '编辑') {
qbcjUpdate(promes).then((res) => {
emit("getList")
close()
}).finally(() => {
loading.value = false
})
}
}
})
}
const route = useRoute()
const router = useRouter()
// 关闭
const close = () => {
if (route.query.id) {
const query = { ...route.query };
delete query.id;
router.replace({ query });
}
fjdz.value = []
listQuery.value = {};
dialogForm.value = false;
loading.value = false;
};
const qbBcList = ref()
// const getqbcjCzztList = () => {
// qbcjCzztList({ qbid: msgeDat.value.id }).then(res => {
// console.log(res);
// qbBcList.value = res || []
// })
// }
// const pursueShow = ref(false)
// const dataList = ref()
const lcList = ref([])
const getqbcjPldb = (id) => {
qbcjSelectCzlcList({ qbid: id }).then(res => {
lcList.value = res || []
})
.catch(() => {
})
}
defineExpose({ init });
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
color: #0072ff;
background: rgba(0, 114, 255, 0.3);
}
.boxlist {
width: 99%;
height: 225px;
margin-top: 10px;
overflow: hidden;
}
::v-deep .avatar-uploader {
display: flex;
align-items: center;
}
::v-deep .el-upload-list {
margin-left: 20px;
display: flex;
align-items: center;
}
::v-deep .el-upload-list__item-name .el-icon {
top: 3px;
}
.form_cnt {
// width: 75%;
flex: 1;
}
.person {
padding-left: 20px;
width: 25%;
// height: 100vh;
}
/* 补充信息样式 */
.supplement-title {
font-size: 14px;
font-weight: 500;
color: #333;
margin: 16px 0 10px 0;
padding-left: 5px;
border-left: 3px solid #24b6dd;
}
.supplement-list {
margin-left: 5px;
}
.supplement-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 12px;
background-color: #f5f7fa;
border: 1px solid #e4e7ed;
border-radius: 4px;
margin-bottom: 8px;
margin-right: 10px;
transition: all 0.3s ease;
}
.supplement-item:hover {
background-color: #ecf5ff;
border-color: #c6e2ff;
}
.supplement-content {
flex: 1;
font-size: 14px;
color: #606266;
line-height: 1.5;
}
.supplement-actions {
display: flex;
gap: 12px;
}
.action-icon {
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.edit-icon {
color: #24b6dd;
}
.edit-icon:hover {
color: #409eff;
transform: scale(1.1);
}
.delete-icon {
color: #f56c6c;
}
.delete-icon:hover {
color: #f78989;
transform: scale(1.1);
}
/* 时间线标题样式 */
.timeline-title {
font-size: 16px;
font-weight: 600;
color: #303133;
padding: 12px 16px;
margin-bottom: 10px;
background-color: #f5f7fa;
border-bottom: 1px solid #ebeef5;
border-radius: 4px 4px 0 0;
}
/* 时间线样式优化 */
.el-timeline {
margin-top: 20px;
}
/* 处置流程卡片样式 */
.process-card {
border: none;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
margin-bottom: 16px;
border-left: 3px solid #409EFF;
}
.process-card:hover {
box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
}
/* 卡片内部信息样式 */
.process-info {
display: flex;
align-items: flex-start;
margin-bottom: 12px;
flex-wrap: wrap;
}
.process-info:last-child {
margin-bottom: 0;
}
.info-label {
font-size: 14px;
font-weight: 600;
color: #409EFF;
margin-right: 8px;
min-width: 65px;
}
.info-value {
font-size: 14px;
color: #606266;
line-height: 1.6;
flex: 1;
word-break: break-word;
}
/* 时间戳样式 */
.el-timeline-item__timestamp {
font-size: 13px;
color: #909399;
margin-bottom: 8px;
}
/* 时间线节点样式 */
.el-timeline-item__node {
background-color: #409EFF;
}
::v-deep .el-textarea__inner {
height: 50vh !important;
}
/* 容器类样式 */
.form-container {
display: flex;
width: 100%;
}
.form-content {
display: flex;
width: 80%;
}
.timeline-container {
border: 1px solid #ebeef5;
flex: 1;
margin: 0 10px;
}
/* 时间线宽度 */
.timeline-full-width {
width: 100%;
}
</style>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,435 @@
<template>
<div>
<div class="titleBox">
<PageTitle :title="titleData">
<el-button type="primary" @click="addEdit('add')">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">新增</span>
</el-button>
<el-button type="primary" @click="dologCancel()">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">导出</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">转线索</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">转合成</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">打标</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="handleSumbit(ids)" v-if="qxkz.deptLevel != '01'">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">上报</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="delDictItem(ids)">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">删除</span>
</el-button>
<el-button type="success" @click="openSearch">
<Search style="width: 1em; height: 1em; margin-right: 8px" />
<span style="vertical-align: middle" v-if="!search">搜索</span>
<span style="vertical-align: middle" v-else>关闭搜索</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox" v-if="search">
<Searchs :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
</div>
<!-- 表格 -->
<div class="tabBox" :style="{ height: (pageData.tableHeight + 40) + 'px' }">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData">
<template #qblx="{ row }">
<DictTag :tag="false" :value="row.qblx" :options="D_GS_XS_LX" />
</template>
<template #cjlx="{ row }">
<DictTag :tag="false" :value="row.cjLx" :options="D_BZ_CJLX" />
</template>
<template #czzt="{ row }">
<DictTag :tag="false" :value="row.czzt" :options="D_BZ_QBCZZT" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<!-- 01 提交 02 上报 03 采纳 04 退回 05 打标签v-if="qxkz.deptLevel == '01'" -->
<el-link size="small" type="primary" v-if="row.czzt == '02' && qxkz.depBool" @click="cnMsg(row)">采纳</el-link>
<el-link size="small" type="primary" v-if="row.czzt == '03' && qxkz.depBool"
@click="opneMsg(row)">打标签</el-link>
<el-link size="small" type="primary" @click="rollbackNewspapers(row)"
v-if="row.czzt == '02' && row.qbjb == '00' && row.fxjsfsb != 1 && row.pcssfsb != 0 && qxkz.depBool">回退</el-link>
<el-link size="small" type="primary" @click="checkProcess(row)">查看流程</el-link>
<el-link size="small" type="primary" @click="appearNewspapers(row)"
v-if="(row.czzt == '01' || row.czzt == '04') && row.qbjb == '00' && qxkz.deptLevel != '01'">上报</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转线索</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转合成</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">转会商</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">肯定</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">创建</el-link>
<el-link size="small" type="primary" @click="addEdit('edit', row)">修改</el-link>
<el-link size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
</template>
</MyTable>checkProcess
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
<!-- 新增 -->
<AddForm ref="detailDiloag" @getList="getList" :titleData="titleData" :dict="{
D_BZ_SF,
D_GS_XS_LY,
D_BZ_SSZT,
D_GS_XS_LX,
D_GS_XS_QTLX,
D_GS_ZDQT_LB,
D_BZ_BMJB,
D_BZ_CLPP,
D_BZ_CLYS,
D_BZ_CLLX,
D_BZ_XZQHDM
}" />
</div>
<ExportFile v-model="exportFileModel" :tableColumn="tableColumn" :dict="{ D_GS_XS_LY, D_GS_XS_LX, D_GS_XS_LX }"
:dataModel="pageData.tableData" />
<MakeTag v-model="chooseRow" :dataList="dataList" :dict="{ D_BZ_CJLX, D_BZ_QBCZZT, D_GS_XS_LX, D_BZ_BQJB }"
@getList="getList" />
<CheckProcess v-model="checkProcessModel" :dataList="dataList" :dict="{ D_BZ_QBCZZT }" />
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Searchs from "@/components/aboutTable/Search.vue";
import AddForm from "./components/addForm.vue";
import { useRouter, useRoute } from 'vue-router'
import { qbcjSelectQbsbPage, qbcjDeletes, qbcjCzzt, qbcjPlsb } from "@/api/Intelligence.js";
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
import MakeTag from '../components/maketag.vue'
import ExportFile from './components/exportFile.vue'
import CheckProcess from '../components/checkProcess.vue'
import { ElMessageBox } from 'element-plus'
import { getItem } from '@//utils/storage.js'
const { proxy } = getCurrentInstance();
const { D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX, D_BZ_BQJB,
D_GS_XS_QTLX, D_GS_ZDQT_LB,
D_BZ_BMJB, D_BZ_CLPP, D_BZ_CLYS, D_BZ_CLLX, D_BZ_XZQHDM, D_BZ_QBCZZT, D_BZ_CJLX } =
proxy.$dict("D_BZ_BMJB", "D_GS_XS_LY",
"D_BZ_SSZT", "D_BZ_SF", "D_GS_XS_LX", "D_GS_XS_QTLX",
"D_GS_ZDQT_LB", "D_BZ_CLPP", "D_BZ_CLYS", "D_BZ_CLLX", "D_BZ_XZQHDM", "D_BZ_QBCZZT", "D_BZ_CJLX", "D_BZ_BQJB"); //获取字典数据
const detailDiloag = ref();
const searchBox = ref(); //搜索框
const ids = ref([])
const tableList = ref([]);
const chooseData = (val) => {
ids.value = val.map(item => {
return item.id
})
tableList.value = val
}
const isShow = ref(false)
const searchConfiger = ref([
{ label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" },
{ label: "姓名", prop: 'xssbr', placeholder: "请输入姓名", showType: "input" },
{ label: "录入时间", prop: 'lrkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
{ label: "情报来源", prop: 'cjLx', placeholder: "请选择情报来源", showType: "select", options: D_BZ_CJLX },
{ label: "情报处置状态", prop: 'czzt', placeholder: "请选择处置状态", showType: "select", options: D_BZ_QBCZZT },
{ label: "来源单位", prop: 'ssbmdm', placeholder: "请选择来源单位", showType: "department" },
{ label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" },
]);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType: "checkBox",
loading: false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
},
controlsWidth: 240,
tableColumn: [
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "情报编号", prop: "xsBh" },
// { label: "上报人姓名", prop: "xssbr" },
{ label: "情报标题", prop: "qbmc" },
// { label: "情报类型", prop: "qblx", showSolt: true },
{ label: "情报来源", prop: "cjlx", showSolt: true },
{ label: "情报上报时间", prop: "sxsbsj" },
// { label: "指向地点", prop: "zxdz" },
{ label: "消息状态", prop: "czzt", showSolt: true },
// { label: "情报内容", prop: "qbnr" },
]
});
const queryFrom = ref({});
// 上报
const appearNewspapers = (item) => {
proxy.$confirm("确定要上报", "警告", { type: "warning" }).then(() => {
qbcjCzzt({ id: item.id, czzt: '02', qbjb: '00' }).then(res => {
proxy.$message({ type: "success", message: "上报成功" });
getList();
})
}).catch(() => { });
}
// 回退
const rollbackNewspapers = (item) => {
ElMessageBox.prompt('请输入回退原因', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
.then(({ value }) => {
qbcjCzzt({ id: item.id, czzt: '01', qbjb: '00', czthyy: value }).then(res => {
proxy.$message({ type: "success", message: "回退成功" });
getList();
})
})
.catch(() => {
})
}
const chooseRow = ref(false)
const dataList = ref()
const opneMsg = (item) => {
chooseRow.value = true
dataList.value = [item]
}
const cnMsg = (item) => {
proxy.$confirm("确定要采纳", "警告", { type: "warning" }).then(() => {
qbcjCzzt({ id: item.id, czzt: '03', qbjb: '00' }).then(res => {
proxy.$message({ type: "success", message: "采纳成功" });
getList();
})
}).catch(() => { });
}
// 打标
const batchMark = () => {
const listDb = tableList.value.filter(item => item.czzt != '03')
if (listDb.length == 0) {
chooseRow.value = true
dataList.value = tableList.value
} else {
proxy.$message({
message: '还有情报未采纳',
type: 'warning',
showClose: true,
})
}
}
const handleSumbit = () => {
const listDb = tableList.value.filter(item => item.czzt != '01' && item.czzt != '04')
if (listDb.length == 0) {
proxy.$confirm("确定要上报", "警告", { type: "warning" }).then(() => {
qbcjPlsb({ ids: ids.value, qbjb: '00' }).then(res => {
proxy.$message({ type: "success", message: "上报成功" });
getList();
})
}).catch(() => { });
} else {
proxy.$message({
message: '请选择正确数据',
type: 'warning',
showClose: true,
})
}
}
// 搜索
const onSearch = (val) => {
const { lrkssj, zxkssj } = val
const promes = {
...pageData.pageConfiger,
...val,
lrkssj: lrkssj ? lrkssj[0] : '',
lrjssj: lrkssj ? lrkssj[1] : '',
zxkssj: zxkssj ? zxkssj[0] : '',
zxjssj: zxkssj ? zxkssj[1] : '',
}
queryFrom.value = { ...promes }
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;
let data = { ...pageData.pageConfiger, ...queryFrom.value };
qbcjSelectQbsbPage(data).then(res => {
pageData.tableData = res.records || [];
pageData.total = res.total;
pageData.tableConfiger.loading = false;
}).catch(() => { pageData.tableConfiger.loading = false; })
}
// 删除
const delDictItem = (id) => {
proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
qbcjDeletes({ ids: Array.isArray(id) ? id : [id] }).then((res) => {
proxy.$message({ type: "success", message: "删除成功" });
getList();
}).catch(() => {
})
}).catch(() => { });
}
// 导出数据
const tableColumn = reactive([
{ label: "上报人姓名", prop: "xssbr" },
{ label: "情报编号", prop: "xsBh" },
{ label: "情报标题", prop: "qbmc" },
{ label: "情报类型", prop: "qblx", showSolt: true, zd: 'D_GS_XS_LX' },
{ label: "情报来源", prop: "cjLx", showSolt: true, zd: 'D_BZ_CJLX' },
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "指向地点", prop: "zxdz" },
{ label: "情报内容", prop: "qbnr", showOverflowTooltip: true },
])
// 详情
const addEdit = (type, row) => {
isShow.value = true;
setTimeout(() => {
detailDiloag.value.init(type, row);
}, 500)
};
const route = useRoute()
const titleData = ref()
const qxkz = reactive({
deptBizType: '',
deptLevel: '',
depBool: false
});
onMounted(() => {
const { deptBizType, deptLevel } = getItem('deptId')[0]
const Jb = deptLevel[0] == '2' ? '01' : deptLevel[0] == '3' ? '02' : '03'
qxkz.deptBizType = deptBizType
qxkz.deptLevel = Jb
if (deptBizType == '23' && Jb == '01') {
qxkz.depBool = true
} else {
qxkz.depBool = false
}
getRouter()
tabHeightFn()
if (route.query.id) {
detailDiloag.value.init('edit', {
id: route.query.id
});
return
}
getList()
});
const getRouter = () => {
titleData.value = route.meta.title
}
const exportFileModel = ref(false)
const dologCancel = () => {
exportFileModel.value = true;
}
// 搜索栏
const search = ref(false)
const openSearch = () => {
search.value = !search.value
nextTick(() => {
tabHeightFn()
})
}
// 表格高度计算
const tabHeightFn = () => {
if (search.value) {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
} else {
pageData.tableHeight = window.innerHeight - 250;
}
window.onresize = function () {
tabHeightFn();
};
};
// 流程
const checkProcessModel = ref()
const checkProcess = (item) => {
checkProcessModel.value = true
dataList.value = item
}
</script>
<style lang="scss" scoped>
.label-pop {
position: relative;
&::before {
position: absolute;
content: '*';
top: 0;
left: -7px;
color: red;
}
}
</style>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
:v-deep .el-dialog {
width: 90% !important;
}
.zdy-model-dialogs {
/* background-color: rgb(50, 148, 214); */
background: url("~@/assets/images/bg46.png") no-repeat center center;
background-size: 100% 100%;
padding: 8px 10px;
box-sizing: border-box;
pointer-events: auto !important;
height: calc(100% - 50px);
overflow: auto;
}
</style>

View File

@ -88,12 +88,12 @@ import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import AddForm from "@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/components/addForm.vue";
import AddForm from "@/views/backOfficeSystem/HumanIntelligence/infoCollection/components/addForm.vue";
import { useRoute } from 'vue-router'
import { qbcjSelectPage, qbcjDeletes } from "@/api/Intelligence.js";
import { reactive, ref, onMounted, getCurrentInstance, watch } from "vue";
import MakeTag from '@/views/backOfficeSystem/HumanIntelligence/components/maketag.vue'
import ExportFile from '@/views/backOfficeSystem/HumanIntelligence/CollectCrculate/components/exportFile.vue'
import ExportFile from '@/views/backOfficeSystem/HumanIntelligence/infoCollection/components/exportFile.vue'
import CheckProcess from '@/views/backOfficeSystem/HumanIntelligence/components/checkProcess.vue'
import pursueContent from "../components/pursueContent.vue";
import Fszl from '../components/fszl.vue'

View File

@ -14,8 +14,8 @@
label-position="left">
<div style="display: flex; align-items: center;margin-bottom: 10px;">
<el-radio-group v-model="listQuery.bkDx" size="large" fill="#6cf" @change="shangeDx">
<el-radio-button :label="item.dm" v-for="(item, index) in props.dic.D_GS_BK_DX"
:key="index" >{{ item.zdmc }}</el-radio-button>
<el-radio-button :label="item.dm" v-for="(item, index) in props.dic.D_GS_BK_DX" :key="index">{{
item.zdmc }}</el-radio-button>
</el-radio-group>
<el-button type="primary" @click="handleAddPeo" v-if="!disabled" style="margin-left: 10px;">
<el-icon style="vertical-align: middle">
@ -53,7 +53,7 @@
</MyTable>
</div>
<div style="width: 100%;" class="mt25">
<el-form-item prop="bkSjKs" label="布控开始时间" label-width="120px" >
<el-form-item prop="bkSjKs" label="布控开始时间" label-width="120px">
<MOSTY.Date v-model="listQuery.bkSjKs" type="datetime" format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择布控开始时间" clearable />
</el-form-item>
@ -61,17 +61,17 @@
<MOSTY.Date v-model="listQuery.bkSjJs" type="datetime" format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择布控结束时间" clearable />
</el-form-item>
<el-form-item prop="czYq" label="处置要求" label-width="60px" style="width:18% ;">
<el-form-item prop="czYq" label="处置要求" label-width="60px" style="width:18% ;">
<MOSTY.Select v-model="listQuery.czYq" :dictEnum="props.dic.D_GS_BK_CZYQ" placeholder="请选择处置要求"
clearable />
</el-form-item>
<el-form-item prop="bkDj" label="布控等级" label-width="60px" style="width:18% ;">
<el-form-item prop="bkDj" label="布控等级" label-width="60px" style="width:18% ;">
<MOSTY.Select v-model="listQuery.bkDj" :dictEnum="props.dic.D_GS_BK_DJ" placeholder="请选择布控级别"
clearable />
</el-form-item>
</div>
<div style="width: 100%;" class="mt10">
<el-form-item prop="bkSy" label="布控事由" style="width: 100%;" >
<el-form-item prop="bkSy" label="布控事由" style="width: 100%;">
<MOSTY.Other v-model="listQuery.bkSy" placeholder="请输入布控事由" type="textarea" style="width: 100%;"
clearable />
</el-form-item>
@ -84,7 +84,7 @@
</div>
</el-form-item>
</div>
<div class="smallTitle">布控范围</div>
<div class="smallTitle">布控范围</div>
<div class=" mapSearch flex">
<el-select v-model="hzfs" placeholder="请选择布控范围" clearable @change="qhhzfs">
<el-option label="区域选择" value="1"></el-option>
@ -347,7 +347,6 @@ const choosed = (val) => {
// 选择人员
const handleAddPeo = () => {
console.log(listQuery.value.bkDx);
if (!listQuery.value.bkDx) return proxy.$message({ type: "warning", message: '请选择布控对象' });
switch (listQuery.value.bkDx) {
@ -386,7 +385,16 @@ const submit = () => {
let params = { ...listQuery.value, bklx: bklx };
params.bkfj = params.bkfj ? params.bkfj.join(',') : '';
params.bkdxList = params.bkdxList ? params.bkdxList : [];
params.bkdxList.forEach(item => { item.fjZp = item.fjZp ? item.fjZp.join(',') : '' })
params.bkdxList.forEach(item => {
if (Array.isArray(item.fjZp)) {
item.fjZp = item.fjZp ? item.fjZp.join(',') : ''
} else {
item.fjZp = item.fjZp
}
})
loading.value = true;
let url = title.value == '新增' ? "/mosty-gsxt/tbGsxtBk/save" : "/mosty-gsxt/tbGsxtBk/update";
qcckPost(params, url).then((res) => {
@ -661,11 +669,13 @@ defineExpose({ init });
color: #18a2dd;
}
}
::v-deep .el-form-item__label{
::v-deep .el-form-item__label {
padding: 0;
}
::v-deep .el-radio-button__inner{
color:#000 !important;
::v-deep .el-radio-button__inner {
color: #000 !important;
}
</style>

View File

@ -15,6 +15,7 @@
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #bkZt="{ row }">
<DictTag :tag="false" :value="row.bkZt" :options="D_GS_BK_ZT" />
</template>

View File

@ -72,7 +72,7 @@
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import { ref, computed, onMounted } from "vue";
import { ref, computed, onMounted ,watch} from "vue";
import { Solar, HolidayUtil } from 'lunar-javascript'
import { timeValidate } from "@/utils/tools";
import { ElMessage, ElMessageBox } from 'element-plus';
@ -142,7 +142,7 @@ const getAllFestivals = (date) => {
name: festival,
})
})
console.log(result)
return result
}
const selectedYear = ref();
@ -315,7 +315,15 @@ const gettingData = () => {
})
}
// 监听currentDate变化同步更新下拉选择器的值
watch(currentDate, (newDate) => {
const year = timeValidate(newDate, 'yd')
const month = timeValidate(newDate, 'ym')
selectedYear.value = parseFloat(year)
selectedMonth.value = parseFloat(month) - 1
dateVal.value = timeValidate(newDate, 'ymd')
gettingData()
})
</script>
@ -483,7 +491,6 @@ const gettingData = () => {
/* 调休上班样式 - 红底白字 */
.holiday-work {
background-color: red;
color: white;
}

View File

@ -5,14 +5,19 @@
<!-- <el-button type="primary" @click="exportExcel">
<span style="vertical-align: middle">导出</span>
</el-button> -->
<el-button type="success" @click="openSearch">
<Search style="width: 1em; height: 1em; margin-right: 8px" />
<span style="vertical-align: middle" v-if="!search">搜索</span>
<span style="vertical-align: middle" v-else>关闭搜索</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
<div ref="searchBox" v-if="search">
<Searchs :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Searchs>
</div>
<!-- 表格 -->
<div class="tabBox">
<div class="tabBox" :style="{height:(pageData.tableHeight + 40)+'px'}">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #xwcs="{ row }">
@ -56,7 +61,7 @@
import * as XLSX from "xlsx";
import Detail from './components/detail.vue'
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Search from "@/components/aboutTable/Search.vue";
import Searchs from "@/components/aboutTable/Search.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
@ -66,7 +71,7 @@ import Information from "@/views/home/model/information.vue";
import SemdFqzl from '@/components/instructionHasBeen/sendFqzl.vue'
import emitter from "@/utils/eventBus.js";
import FkDialog from "@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/components/fkDialog.vue";
import { reactive, ref, onMounted, getCurrentInstance, computed, watch } from "vue";
import { reactive, ref, onMounted, getCurrentInstance, computed, watch,nextTick } from "vue";
import AddFrom from './components/addFrom.vue'
const { proxy } = getCurrentInstance();
const { D_GS_SSYJ ,D_GSXT_YJXX_CZZT} = proxy.$dict("D_GS_SSYJ","D_GSXT_YJXX_CZZT"); //获取字典数据
@ -260,10 +265,23 @@ const openAddModel = (row) => {
}
const search = ref(false)
const openSearch = () => {
search.value = !search.value
nextTick(() => {
tabHeightFn()
})
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () { tabHeightFn(); };
if (search.value) {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
} else {
pageData.tableHeight = window.innerHeight - 250;
}
window.onresize = function () {
tabHeightFn();
};
};
</script>

View File

@ -5,14 +5,19 @@
<!-- <el-button>
<span style="vertical-align: middle">导出</span>
</el-button> -->
<el-button type="success" @click="openSearch">
<Search style="width: 1em; height: 1em; margin-right: 8px" />
<span style="vertical-align: middle" v-if="!search">搜索</span>
<span style="vertical-align: middle" v-else>关闭搜索</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
<div ref="searchBox" v-if="search">
<Searchs :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Searchs>
</div>
<!-- 表格 -->
<div class="tabBox">
<div class="tabBox" :style="{height:(pageData.tableHeight + 40)+'px'}">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #sfcs="{ row }">
@ -21,14 +26,14 @@
<template #bqys="{ row }">
<DictTag :value="row.bqys" :tag="false" :color="bqYs(row.bqys)" :options="D_GS_SSYJ" />
</template>
<template #czzt="{ row }">
<DictTag :value="row.czzt" :options="D_GSXT_YJXX_CZZT" />
<template #czzt="{ row }">
<DictTag :value="row.czzt" :options="D_GSXT_YJXX_CZZT" />
</template>
<template #controls="{ row }">
<el-link type="warning" @click="pushAssess(row)">全息档案</el-link>
<el-link type="primary" @click="showDetail(row)">转合成</el-link>
<el-link type="danger" @click="delDictItem(row.id)">转会商</el-link>
<el-link type="success" @click="handleQsFk(row, '签收')" v-if="row.czzt == '01'">签收</el-link>
<el-link type="success" @click="handleQsFk(row, '签收')" v-if="row.czzt == '01'">签收</el-link>
<el-link type="success" @click="handleQsFk(row, '反馈')" v-else-if="row.czzt == '02'">反馈</el-link>
<el-link type="success" @click="handleQsFk(row, '查看反馈')" v-else>查看反馈</el-link>
<el-link type="primary" @click="openAddModel(row)">详情</el-link>
@ -41,18 +46,18 @@
</div>
</div>
<Detail ref="detailRef" />
<HolographicArchive v-model="assessShow" :dataList="dataList" />
<FkDialog @change="getList" lx="04" />
<HolographicArchive v-model="assessShow" :dataList="dataList" />
<FkDialog @change="getList" lx="04" />
<Information v-model="showDialog" title="发送指令" @submit='submit' @close='closeFszl'>
<SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj"
:tacitly="tacitly" />
</Information>
<AddFrom ref="addModelRef" :dict="{D_GSXT_YJXX_CZZT, D_BZ_YJJB,D_GS_SSYJ}"/>
<AddFrom ref="addModelRef" :dict="{ D_GSXT_YJXX_CZZT, D_BZ_YJJB, D_GS_SSYJ }" />
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Search from "@/components/aboutTable/Search.vue";
import Searchs from "@/components/aboutTable/Search.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { tbYjxxGetZbtj, tbGsxtBqzhSelectList } from '@/api/yj.js'
@ -61,13 +66,13 @@ import Information from "@/views/home/model/information.vue";
import SemdFqzl from '@/components/instructionHasBeen/sendFqzl.vue'
import FkDialog from "@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/components/fkDialog.vue";
import AddFrom from "./components/addFrom.vue";
import { reactive, ref, onMounted, getCurrentInstance, watch } from "vue";
import { reactive, ref, onMounted, getCurrentInstance, watch,nextTick } from "vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import Detail from './components/detail.vue'
import emitter from "@/utils/eventBus.js";
const searchBox = ref();
const { proxy } = getCurrentInstance();
const {D_GSXT_YJXX_CZZT} = proxy.$dict("D_GSXT_YJXX_CZZT")
const { D_GSXT_YJXX_CZZT } = proxy.$dict("D_GSXT_YJXX_CZZT")
// 搜索配置
const searchConfiger = ref([
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input" },
@ -103,7 +108,7 @@ const pageData = reactive({
{ label: "预警时间", prop: "yjsj" },
{ label: "预警分值", prop: "sffz" },
{ label: "处置状态", prop: "czzt", showSolt: true },
{ label: "所属县局", prop: "ssbm" },
{ label: "所属县局", prop: "ssbm" },
]
});
@ -232,9 +237,21 @@ const openAddModel = (row) => {
addModelRef.value.init(row)
}
// 搜索栏
const search = ref(false)
const openSearch = () => {
search.value = !search.value
nextTick(() => {
tabHeightFn()
})
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
if (search.value) {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
} else {
pageData.tableHeight = window.innerHeight - 250;
}
window.onresize = function () {
tabHeightFn();
};

View File

@ -5,11 +5,16 @@
<!-- <el-button>
<span style="vertical-align: middle">导出</span>
</el-button> -->
<el-button type="success" @click="openSearch">
<Search style="width: 1em; height: 1em; margin-right: 8px" />
<span style="vertical-align: middle" v-if="!search">搜索</span>
<span style="vertical-align: middle" v-else>关闭搜索</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount">
<div ref="searchBox" v-if="search">
<Searchs :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount">
<template #defaultSlot>
<el-select @change="gettbGsxtBqglSelectList" v-model="queryFrom.sfdl" placeholder="请选择身份类型"
style="width: 100%">
@ -21,10 +26,10 @@
<el-option :label="item.label" :value="item.value" v-for="(item, index) in bqLbData.bqXl" :key="index" />
</el-select>
</template>
</Search>
</Searchs>
</div>
<!-- 表格 -->
<div class="tabBox">
<div class="tabBox" :style="{height:(pageData.tableHeight + 40)+'px'}">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #sfcs="{ row }">
@ -64,7 +69,7 @@
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Search from "@/components/aboutTable/Search.vue";
import Searchs from "@/components/aboutTable/Search.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import HolographicArchive from '@/views/home/components/holographicArchive.vue'
@ -72,7 +77,7 @@ import Information from "@/views/home/model/information.vue";
import SemdFqzl from '@/components/instructionHasBeen/sendFqzl.vue'
import AddFrom from "./components/addFrom.vue";
import FkDialog from "@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/components/fkDialog.vue";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import { reactive, ref, onMounted, getCurrentInstance,nextTick } from "vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { yjzxSfyjSelectList } from "@/api/yj.js";
import { tbGsxtBqglSelectList } from '@/api/zdr'
@ -264,9 +269,21 @@ const addModelRef = ref(null)
const openAddFrom = (row) => {
addModelRef.value.init('add', row)
}
// 搜索栏
const search = ref(false)
const openSearch = () => {
search.value = !search.value
nextTick(() => {
tabHeightFn()
})
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
if (search.value) {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
} else {
pageData.tableHeight = window.innerHeight - 250;
}
window.onresize = function () {
tabHeightFn();
};

View File

@ -63,9 +63,9 @@ watch(() => props.dict, (res) => {
{ label: "布控车牌号", prop: "yjClcph", type: "input" },
{ label: "布控身份证", prop: "yjRysfzh", type: "input" },
{ label: "预警标签", prop: "yjbqmc", type: "input" },
{ label: "所属部门", prop: "ssbm", type: "input" },
{ label: "所属县局", prop: "ssxgaj", type: "input" },
{ label: "所属市局", prop: "sssgaj", type: "input" },
{ label: "管辖部门", prop: "ssbm", type: "input" },
{ label: "管辖县局", prop: "ssxgaj", type: "input" },
{ label: "管辖市局", prop: "sssgaj", type: "input" },
{ label: "接警员姓名", prop: "jjyxm", type: "input" },
{ label: "预警内容", prop: "yjNr", type: "textarea", width: "100%" },
]

View File

@ -1,22 +1,26 @@
<template>
<div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<div class="tabBox" :style="{height:!search?maxHeight+200+'px':(maxHeight+150)+'px'}">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="maxHeight+'px'"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
:expand="true" :rowClassName="getRowClassName">
<template #expand="{ props }">
<div class="expand-content" style="max-width: 100%">
<Items :data="props" :dict="dict" />
</div>
</template>
<template #yjTp="{ row }">
<template v-if="!row.yjTp || row.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
<img src="@/assets/images/car.png" width="30" height="30" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="30" height="30" v-else />
</template>
<el-image v-else style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]"
<el-image v-else style="width: 30px; height:30px" :src="row.yjTp" :preview-src-list="[row.yjTp]"
show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
<img src="@/assets/images/car.png" width="30" height="30" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="30" height="30" v-else />
</div>
</template>
</el-image>
@ -50,7 +54,7 @@
<el-button type="success" @click="showFeedback(item, '反馈')" v-if="item.czzt == '02'">反馈</el-button>
<el-button type="success" @click="showFeedback(item, '查看反馈')" v-if="item.czzt == '03'">查看反馈</el-button> -->
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="maxHeight+100" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
@ -63,10 +67,11 @@
<SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj"
:tacitly="tacitly" />
</Information>
<AddFrom ref="addFrom" />
<!-- <AddFrom ref="addFrom" /> -->
</template>
<script setup>
import Items from '../item/items.vue'
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { IdCard } from '@/utils/validate.js'
@ -84,6 +89,13 @@ const props = defineProps({
dict: {
type: Object,
default: {}
},
maxHeight: {
type: Number,
default: 666
}, search: {
type: Boolean,
default: false
}
});
const pageData = reactive({
@ -103,24 +115,17 @@ const pageData = reactive({
}, //分页
controlsWidth: 300, //操作栏宽度
tableColumn: [
{ label: "预警图片", prop: "yjTp", showSolt: true },
{ label: "姓名", prop: "yjRyxm", width: 150, showOverflowTooltip: true },
{ label: "年龄", prop: "nl", showSolt: true },
{ label: "性别", prop: "xb", showSolt: true, width: 100 },
{ label: "预警级别", prop: "yjJb", showSolt: true },
{ label: "相似度", prop: "xsd", showSolt: true },
{ label: "预警时间", prop: "yjSj", showOverflowTooltip: true, width: 200 },
{ label: "预警地点", prop: "yjDz", showOverflowTooltip: true, width: 200 },
{ label: "预警次数", prop: "yjCs", showOverflowTooltip: true },
{ label: "处置状态", prop: "czzt", showSolt: true, width: 100 },
{ label: "布控手机号", prop: "yjRysjh", showOverflowTooltip: true, width: 100 },
{ label: "布控车牌号", prop: "yjClcph", showOverflowTooltip: true, width: 100 },
{ label: "身份证", prop: "yjRysfzh", showOverflowTooltip: true, width: 200 },
{ label: "预警图片", prop: "yjTp", showSolt: true,width: 100 },
{ label: "处置状态", prop: "czzt", showSolt: true },
{ label: "预警时间", prop: "yjSj", showOverflowTooltip: true },
{ label: "姓名", prop: "yjRyxm" },
{ label: "年龄", prop: "nl", showSolt: true,width: 80 },
{ label: "数据来源", prop: "yjLylx", showOverflowTooltip: true },
{ label: "身份证", prop: "yjRysfzh", showOverflowTooltip: true },
// { label: "预警级别", prop: "yjJb", showSolt: true },
// { label: "相似度", prop: "xsd", showSolt: true },
{ label: "布控车牌号", prop: "yjClcph", showOverflowTooltip: true },
{ label: "预警标签", prop: "yjbqmc", width: 250 },
{ label: "所属部门", prop: "ssbm", width: 100 },
{ label: "所属县局", prop: "ssxgaj", width: 100 },
{ label: "所属市局", prop: "sssgaj", width: 100 },
]
});
@ -132,7 +137,7 @@ const pageData = reactive({
onMounted(() => {
tabHeightFn();
// tabHeightFn();
getList()
});
@ -215,15 +220,26 @@ const closeFszl = () => {
}
const addFrom = ref()
const openAddFrom = (row) => {
emitter.emit('openAddFrom',row)
emitter.emit('openAddFrom', row)
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - 430;
window.onresize = function () {
tabHeightFn();
};
// 根据预警级别设置行样式
const getRowClassName = (row) => {
if (!row.row.yjJb) return '';
const level = String(row.row.yjJb);
if (level === '01' || level.includes('红') || level.includes('高')) return 'warning-level-01';
if (level === '02' || level.includes('橙') || level.includes('中')) return 'warning-level-02';
if (level === '03' || level.includes('黄') || level.includes('低')) return 'warning-level-03';
if (level === '04' || level.includes('蓝')) return 'warning-level-04';
return '';
};
// // 表格高度计算
// const tabHeightFn = () => {
// pageData.tableHeight = window.innerHeight - 430;
// window.onresize = function () {
// tabHeightFn();
// };
// };
defineExpose({
getList
})
@ -233,4 +249,40 @@ defineExpose({
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
/* 预警级别行样式 */
.warning-level-01 {
background-color: rgba(255, 2, 2, 0.1) !important;
}
.warning-level-01:hover {
background-color: rgba(255, 2, 2, 0.15) !important;
}
.warning-level-02 {
background-color: rgba(255, 140, 0, 0.1) !important;
}
.warning-level-02:hover {
background-color: rgba(255, 140, 0, 0.15) !important;
}
.warning-level-03 {
background-color: rgba(255, 210, 8, 0.1) !important;
}
.warning-level-03:hover {
background-color: rgba(255, 210, 8, 0.15) !important;
}
.warning-level-04 {
background-color: rgba(0, 0, 255, 0.1) !important;
}
.warning-level-04:hover {
background-color: rgba(0, 0, 255, 0.15) !important;
}
/* 确保行样式应用到所有单元格 */
.warning-level-01 td,
.warning-level-02 td,
.warning-level-03 td,
.warning-level-04 td {
background-color: transparent !important;
}
</style>

View File

@ -1,10 +1,17 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="预警列表" />
<PageTitle title="预警列表">
<el-button type="success" @click="openSearch">
<Search style="width: 1em; height: 1em; margin-right: 8px" />
<span style="vertical-align: middle" v-if="!search">搜索</span>
<span style="vertical-align: middle" v-else>关闭搜索</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox" class="searchBox">
<div ref="searchBox" class="searchBox" v-if="search">
<el-form :model="listQuery" label-width="auto" :inline="true" ref="searchArr">
<el-form-item label="布控类型" prop="yjlx">
<el-select v-model="listQuery.yjlx" placeholder="请选择预警类型">
@ -27,15 +34,16 @@
<el-button @click="resetForm(searchArr)">重置</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格 -->
<div class="tabBox" :style="{ height: pageData.tableHeight + 'px' }">
<div class="tabBox" :style="{ height: (pageData.tableHeight + 40) + 'px' }">
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick"
style="position: relative;z-index: 1;">
<el-tab-pane label="本地预警" name="local">
<div style="padding:0 10px;"> <el-button type="primary" @click="exportExcel">导出</el-button></div>
<LocalWarning ref="localWarningRef" :dict="{D_GSXT_YJXX_CZZT, D_BZ_YJJB}"/>
<LocalWarning :maxHeight="search ? (pageData.tableHeight - 200) : (pageData.tableHeight - 200)"
ref="localWarningRef" :dict="{ D_GSXT_YJXX_CZZT, D_BZ_YJJB, D_BZ_YJLYXT }" :search="search"/>
<!-- pageData.tableHeight-125 -->
</el-tab-pane>
<el-tab-pane label="区厅预警" name="district">区厅预警</el-tab-pane>
</el-tabs>
@ -46,14 +54,14 @@
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
<template #yjTp="{ row }">
<template v-if="!row.yjTp || row.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
<img src="@/assets/images/car.png" width="30" height="30" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="30" height="30" v-else />
</template>
<el-image v-else style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]" show-progress>
<el-image v-else style="width: 30px; height:30px" :src="row.yjTp" :preview-src-list="[row.yjTp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
<img src="@/assets/images/car.png" width="30" height="30" v-if="row.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="30" height="30" v-else />
</div>
</template>
</el-image>
@ -61,14 +69,16 @@
<template #nl="{ row }">
{{ IdCard(row.yjRysfzh, 3) }}
</template>
<template #yjLylx="{ row }">
<DictTag v-model:value="row.yjLylx" :options="D_BZ_YJLYXT" />
</template>
<template #xb="{ row }">
{{ IdCard(row.yjRysfzh, 2) }}
</template>
<template #czzt="{ row }">
<DictTag v-model:value="row.czzt" :options="D_GSXT_YJXX_CZZT" />
</template>
<template #yjJb="{ row }">
<template #yjJb="{ row }">
<DictTag v-model:value="row.yjJb" :options="D_BZ_YJJB" />
</template>
<template #xsd="{ row }">
@ -76,7 +86,6 @@
</template>
<!-- 操作 -->
</MyTable>
<template #footer>
<div class="dialog-footer">
<el-button @click="showDc = false">关闭</el-button>
@ -86,12 +95,12 @@
</div>
</template>
</el-dialog>
<AddFrom ref="addFromRef" :dict="{D_GSXT_YJXX_CZZT, D_BZ_YJJB}"/>
<AddFrom ref="addFromRef" :dict="{ D_GSXT_YJXX_CZZT, D_BZ_YJJB, D_BZ_YJLYXT }" />
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Search from "@/components/aboutTable/Search.vue";
// import Search from "@/components/aboutTable/Search.vue";
import { IdCard } from '@/utils/validate.js'
import { tbGsxtZdrySelectList } from "@/api/zdr.js"
import { tbYjxxQueryYjxx } from "@/api/yj.js";
@ -103,7 +112,7 @@ import FileSaver from "file-saver";
import emitter from "@/utils/eventBus.js";
import * as XLSX from "xlsx";
const { proxy } = getCurrentInstance();
const { D_BZ_YJLX, D_GSXT_YJXX_CZZT, D_BZ_YJJB } = proxy.$dict("D_BZ_YJLX", "D_GSXT_YJXX_CZZT","D_BZ_YJJB")
const { D_BZ_YJLX, D_GSXT_YJXX_CZZT, D_BZ_YJJB, D_BZ_YJLYXT } = proxy.$dict("D_BZ_YJLX", "D_GSXT_YJXX_CZZT", "D_BZ_YJJB", "D_BZ_YJLYXT")
const searchBox = ref(); //搜索框
const shortcuts = [
{
@ -152,18 +161,19 @@ const pageData = reactive({
controlsWidth: 160, //操作栏宽度
tableColumn: [
{ label: "预警图片", prop: "yjTp", showSolt: true },
{ label: "处置状态", prop: "czzt", showSolt: true },
{ label: "预警时间", prop: "yjSj", showOverflowTooltip: true },
{ label: "姓名", prop: "yjRyxm" },
{ label: "年龄", prop: "nl", showSolt: true },
{ label: "数据来源", prop: "yjLylx", showOverflowTooltip: true },
{ label: "性别", prop: "xb", showSolt: true },
{ label: "预警级别", prop: "yjJb", showSolt: true },
{ 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 },
{ label: "处置状态", prop: "czzt", showSolt: true },
]
});
const showDc = ref(false)
@ -207,14 +217,32 @@ const resetForm = (formEl) => {
listQuery.value = {}
localWarningRef.value.getList()
}
// // 表格高度计算
// const tabHeightFn = () => {
// pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
// window.onresize = function () {
// tabHeightFn();
// };
// };
// 搜索栏
const search = ref(false)
const openSearch = () => {
search.value = !search.value
nextTick(() => {
tabHeightFn()
})
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
if (search.value) {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
} else {
pageData.tableHeight = window.innerHeight - 250;
}
window.onresize = function () {
tabHeightFn();
};
};
// 导出
const exportExcel = () => {
@ -321,7 +349,11 @@ const handleExport = () => {
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-table--fit {
height: calc(100% - 50px) !important;
}
</style>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;

View File

@ -0,0 +1,197 @@
<template>
<div class="warning-item">
<!-- 第一行图片姓名年龄性别 -->
<div class="first-row">
<div class="avatar-container">
<template v-if="!data.yjTp || data.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="60" height="70" v-if="data.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="60" height="70" v-else />
</template>
<el-image v-else style="width: 60px; height:70px" :src="data.yjTp" :preview-src-list="[data.yjTp]"
show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="60" height="70" v-if="data.yjLx == 2" />
<img src="@/assets/images/default_male.png" width="60" height="70" v-else />
</div>
</template>
</el-image>
</div>
<div class="basic-info">
<div class="info-items name">姓名<span>{{ data.yjRyxm }}</span></div>
<div class="info-items gender">性别<span> {{ IdCard(data.yjRysfzh, 3) }}</span></div>
<div class="info-items age">年龄<span> {{ IdCard(data.yjRysfzh, 2) }}</span></div>
</div>
</div>
<!-- 第二行其他所有字段 -->
<div class="second-row">
<div class="info-item title">预警标题<span>{{ data.yjBt }}</span></div>
<div class="info-item level">
预警级别
<DictTag :color="bqYs(data.yjJb)" :tag="false" v-model:value="data.yjJb" :options="props.dict.D_BZ_YJJB" />
<!-- <span :class="getLevelClass(data.yjJb)">{{ data.yjJb || data.yjLx }}</span> -->
</div>
<div class="info-item similarity">相似度<span>{{ data.xsd }}%</span></div>
</div>
<div class="second-row">
<div class="info-item time">预警时间<span>{{ data.yjSj }}</span></div>
<div class="info-item location">预警地点<span>{{ data.yjDz }}</span></div>
<div class="info-item count">预警次数<span>{{ data.yjCs }}</span></div>
</div>
<div class="second-row">
<div class="info-item status">
处置状态 <DictTag v-model:value="data.czzt" :options="props.dict.D_GSXT_YJXX_CZZT" />
</div>
<div class="info-item phone">布控手机<span>{{ data.yjRysjh }}</span></div>
<div class="info-item car">布控车牌号<span>{{ data.yjClcph }}</span></div>
</div>
<div class="second-row">
<div class="info-item idcard">布控身份证<span>{{ data.yjRysfzh }}</span></div>
<div class="info-item tag">预警标签<span>{{ data.yjbqmc }}</span></div>
<div class="info-item department">管辖部门<span>{{ data.ssbm }}</span></div>
</div>
<div class="second-row">
<div class="info-item county">管辖县局<span>{{ data.ssxgaj }}</span></div>
<div class="info-item city">管辖市局<span>{{ data.sssgaj }}</span></div>
<div class="info-item officer">接警员<span>{{ data.jjyxm }}</span></div>
</div>
<div class="second-row">
<div class="info-item content full-width">预警内容<span>{{ data.yjNr }}</span></div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { bqYs } from '@/utils/tools'
import { IdCard } from '@/utils/validate.js'
const props = defineProps({
data: {
type: Object,
default: () => { }
},
dict: {
type: Object,
default: () => { }
},
})
</script>
<style lang="scss" scoped>
.warning-item {
width: 100%;
padding: 15px;
border: 1px solid #e8e8e8;
border-radius: 8px;
background-color: #fafafa;
}
.first-row {
display: flex;
align-items: center;
margin-bottom: 15px;
padding-bottom: 15px;
border-bottom: 1px solid #e0e0e0;
}
.avatar-container {
margin-right: 20px;
}
.basic-info {
display: flex;
gap: 30px;
align-items: center;
}
.second-row {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 10px;
}
.info-items {
box-sizing: border-box;
display: flex;
// justify-content: space-between;
padding: 5px 0;
color: #333;
span {
font-weight: 500;
color: #606266;
}
}
.info-item {
flex: 0 0 calc(33.33% - 20px);
box-sizing: border-box;
display: flex;
// justify-content: space-between;
padding: 5px 0;
color: #333;
span {
font-weight: 500;
color: #606266;
}
}
// 特殊字段样式
.name span {
color: #1890ff;
font-weight: bold;
}
// 预警级别颜色
.level-high span {
color: #f56c6c;
font-weight: bold;
}
.level-medium span {
color: #e6a23c;
font-weight: bold;
}
.level-low span {
color: #67c23a;
font-weight: bold;
}
// 处置状态颜色
.status-completed span {
color: #67c23a;
font-weight: bold;
}
.status-processing span {
color: #409eff;
font-weight: bold;
}
.status-pending span {
color: #e6a23c;
font-weight: bold;
}
// 全宽字段
.full-width {
flex: 0 0 100% !important;
}
// 内容字段特殊样式
.content {
flex-direction: column;
align-items: flex-start;
span {
margin-top: 5px;
padding: 8px 12px;
background-color: #f0f9eb;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
}
}
</style>

View File

@ -149,7 +149,7 @@ const changeXzqh = (val, trg) => {
type: "FeatureCollection",
features: [feature]
},
color: 'rgba(209 112 65,1)',
color: 'rgba(209, 112, 65, 0.8)',
fillColor: 'rgba(255, 255, 255,0)',
})
})

View File

@ -33,6 +33,14 @@
<div class="jieqi-date-item">
<span class="date-label">节气信息</span>
<span class="date-value jieqi-highlight">{{ getYearInGanjq(data) || '无' }}</span>
</div>
<div class="jieqi-date-item">
<span class="date-label">节日信息</span>
<span class="date-value jieqi-highlight">
<span>
{{ getAllFestivals(data.date,true).join('、') || '无' }}
</span>
</span>
</div>
</div>
@ -51,7 +59,8 @@
<template #reference>
<div @click="chooseDay(data)" class="dayonChage" :class="{
'day': dateVal == data.day,
'special': dataIntegration.includes(data.day)
'special': dataIntegration.includes(data.day),
'model': getAllFestivals(data.date).length > 0
}">
<span> {{ data.day.split("-")[2] }}</span>
<span style="font-size: 8px;"> {{ getLunarMonthDay(data.date) }}</span>
@ -66,7 +75,7 @@
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { ref, computed, onMounted, watch } from "vue";
import { Solar, Lunar } from 'lunar-javascript'
import { timeValidate } from "@/utils/tools";
import { useRouter } from 'vue-router'
@ -148,6 +157,16 @@ const currentDate = ref(new Date());
onMounted(() => {
initialize()
})
// 监听currentDate变化同步更新下拉选择器的值
watch(currentDate, (newDate) => {
const year = timeValidate(newDate, 'yd')
const month = timeValidate(newDate, 'ym')
selectedYear.value = parseFloat(year)
selectedMonth.value = parseFloat(month) - 1
dateVal.value = timeValidate(newDate, 'ymd')
gettingData()
})
const goToSelectedMonth = () => {
if (selectedYear.value && selectedMonth.value !== '') {
const newDate = new Date(selectedYear.value, selectedMonth.value, 1);
@ -193,6 +212,49 @@ const gettingData = () => {
// const lunar = solar.getLunar()
// return `${lunar.getMonthInChinese()}${lunar.getDayInChinese()}`
// }
const getAllFestivals = (date,boolean=false) => {
console.log(date);
const time = new Date(date)
const solar = Solar.fromDate(time)
const lunar = solar.getLunar()
const result = []
// 获取农历节日
const lunarFestivals = lunar.getFestivals()
lunarFestivals.forEach(festival => {
result.push({
type: '农历节日',
name: festival,
})
})
// 获取公历节日
const solarFestivals = solar.getFestivals()
solarFestivals.forEach(festival => {
result.push({
type: '公历节日',
name: festival,
})
})
// 获取其他纪念日
const otherFestivals = solar.getOtherFestivals()
otherFestivals.forEach(festival => {
result.push({
type: '纪念日',
name: festival,
})
})
if (boolean) {
return result.filter(item => item.type != '纪念日').map(item => item.name)
} else {
return result.filter(item => item.type != '纪念日')
}
}
const calendarPush = () => {
router.push('/calendar')
}
@ -426,4 +488,8 @@ const calendarPush = () => {
background-color: rgba(253, 112, 112, 0.856);
color: #ffffff;
}
.model{
background-color: rgb(76, 243, 93);
color: #ffffff;
}
</style>

View File

@ -17,9 +17,10 @@ import {
const loginDialog = ref(false);
const deptList = ref([]);
const store = useStore();
console.log("路由6");
// 处理页面可见性变化的函数
const handleVisibilityChange = () => {
console.log("页面可见性变化");
// 获取会话信息 - 带上所有cookies
fetch('https://pcs.lz.dsj.xz:9020/getSession', {
method: 'GET',