This commit is contained in:
lcw
2025-11-22 21:59:58 +08:00
parent ea3022c3f6
commit 93c49dff27
661 changed files with 195357 additions and 2160 deletions

View File

@ -34,8 +34,9 @@
</h3>
</template>
<div class="grid-container">
<div v-for="(item,index) in listQuery.ossList" class="grid-item" :key="index">
<el-image :src="setAddress(item.id)" :zoom-rate="1.2" :max-scale="7" :min-scale="0.2" :preview-src-list="srcList"
<el-image :src="setAddress(item.fjZp)" :zoom-rate="1.2" :max-scale="7" :min-scale="0.2" :preview-src-list="srcList"
show-progress :initial-index="4" fit="cover">
<template #error>
<div class="image-slot">
@ -102,6 +103,8 @@ const listQuery = ref({})
const srcList = ref([])
const getDataById = (id) => {
qcckGet({}, '/mosty-gsxt/tbGsxtBk/selectVoById/' + id).then(res => {
console.log(res);
listQuery.value=res
srcList.value=res.ossList.map(v=>setAddress(v.id))
})

View File

@ -2,7 +2,7 @@
<div>
<div class="titleBox">
<PageTitle title="重点车辆管理">
<el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<!-- <el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<template #reference>
<el-button type="primary" @click="(visible = !visible), (visiblefp = false)" size="small">布控申请</el-button>
</template>
@ -23,7 +23,7 @@
</div>
</el-popover>
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button> -->
<el-button type="primary" size="small" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon>
<span style="vertical-align: middle">新增</span>

View File

@ -2,7 +2,7 @@
<div>
<div class="titleBox">
<PageTitle title="重点群体管理">
<el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<!-- <el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<template #reference>
<el-button type="primary" @click="(visible = !visible), (visiblefp = false)" size="small">布控申请
</el-button>
@ -25,8 +25,8 @@
</el-popover>
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary">导入</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button> -->
<!-- <el-button size="small" type="primary">导入</el-button> -->
<el-button type="primary" size="small" @click="addEdit('add', null)">
<el-icon style="vertical-align: middle">
<CirclePlus />

View File

@ -2,7 +2,7 @@
<div>
<div class="titleBox">
<PageTitle title="重点群体管理">
<el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<!-- <el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<template #reference>
<el-button type="primary" @click="(visible = !visible), (visiblefp = false)" size="small">布控申请
</el-button>
@ -26,8 +26,8 @@
</el-popover>
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary" >导入</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button> -->
<!-- <el-button size="small" type="primary" >导入</el-button> -->
<el-button type="primary" size="small" @click="addEdit('add', null)">
<el-icon style="vertical-align: middle">
<CirclePlus />

View File

@ -2,7 +2,7 @@
<div>
<div class="titleBox">
<PageTitle title="重点群体审核">
<el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<!-- <el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<template #reference>
<el-button type="primary" @click="(visible = !visible), (visiblefp = false)" size="small">布控申请
</el-button>
@ -24,7 +24,7 @@
</div>
</el-popover>
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button> -->
<el-button type="primary" size="small" @click="addEdit('add', null)">
<el-icon style="vertical-align: middle">
<CirclePlus />
@ -39,12 +39,12 @@
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
@chooseData="chooseData"
>
@ -60,13 +60,13 @@
<li class="one_text_detail">创建时间{{ row.xtCjsj }}</li>
</ul>
</div>
</template>
<template #bqList="{ row }">
<ul >
<ul >
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} ) </li>
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} ) </li>
</ul>
</ul>
</template>

View File

@ -100,7 +100,10 @@ import VisitRecord from '../model/visitRecord.vue'
import CaseInfo from '../model/caseInfo.vue'
import ActualPerformance from '../model/actualPerformance.vue'
import CzModel from '../model/czModel.vue'
import { ref, onUnmounted ,getCurrentInstance} from "vue";
import { useRouter, useRoute } from 'vue-router'
import { ref, onUnmounted, getCurrentInstance } from "vue";
const router = useRouter()
const route = useRoute()
const { proxy } = getCurrentInstance();
const emit = defineEmits(["updateDate"]);
const chooseMarksVisible = ref(false);
@ -218,8 +221,15 @@ const submit = async () => {
// 关闭
const close = () => {
if (route.query.id) {
const query = { ...route.query };
delete query.id;
router.replace({ query });
}
dialogForm.value = false;
loading.value = false;
emit('updateDate')
};
defineExpose({ init });

View File

@ -2,16 +2,16 @@
<div>
<div class="titleBox">
<PageTitle title="重点人管理">
<el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<!-- <el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<template #reference>
<el-button type="primary" @click="(visible = !visible), (visiblefp = false)" size="small">布控申请</el-button>
</template>
<div class="flex just-center">
<el-button size="small" type="primary" v-for="it in D_GS_BK_SQLX" :key="it.dm"
@click="handleApplication(it)">{{it.zdmc }}</el-button>
@click="handleApplication(it)">{{ it.zdmc }}</el-button>
</div>
</el-popover>
<el-popover placement="bottom" :visible="visiblefp" :width="400" trigger="click">
</el-popover> -->
<!-- <el-popover placement="bottom" :visible="visiblefp" :width="400" trigger="click">
<template #reference>
<el-button size="small" type="primary" @click="(visiblefp = !visiblefp), (visible = false)">指定分配</el-button>
</template>
@ -22,10 +22,10 @@
<el-button type="primary" @click="handlefp" size="small">分配</el-button>
</div>
</div>
</el-popover>
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary" >导入</el-button>
</el-popover> -->
<!-- <el-button size="small" type="primary" @click="handleZxs">转线索</el-button> -->
<!-- <el-button size="small" type="primary" @click="handleMove">移交管控</el-button> -->
<!-- <el-button size="small" type="primary">导入</el-button> -->
<el-button type="primary" size="small" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle">
<CirclePlus />
@ -81,8 +81,10 @@
<!-- 操作 -->
<template #controls="{ row }">
<el-link size="small" type="success" @click="handleremove(row.id)">移除</el-link>
<el-link size="small" type="success" v-if="row.zdrZt == '01'||row.zdrZt == '03'" @click="handleSend(row.id)">送审</el-link>
<el-link size="small" type="primary" v-if="row.zdrZt == '01'||row.zdrZt == '03'" @click="addEdit('edit', row)">编辑</el-link>
<el-link size="small" type="success" v-if="row.zdrZt == '01' || row.zdrZt == '03'"
@click="handleSend(row.id)">送审</el-link>
<el-link size="small" type="primary" v-if="row.zdrZt == '01' || row.zdrZt == '03'"
@click="addEdit('edit', row)">编辑</el-link>
<el-link size="small" type="primary" @click="addEdit('detail', row)">详情</el-link>
<el-link size="small" type="danger" @click="deleteRow(row.id)">删除</el-link>
</template>
@ -114,6 +116,9 @@ import Search from "@/components/aboutTable/Search.vue";
import AddForm from "./components/addForm.vue";
import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js";
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const { proxy } = getCurrentInstance();
const { D_GS_ZDQT_ZT, D_GS_ZDR_RYJB, D_BZ_XB, D_BZ_MZ, D_BZ_XZQHDM, D_GS_ZDR_BK_ZT, D_GS_ZDR_CZZT, D_GS_BQ_ZL, D_GS_BQ_LB, D_GS_BQ_LX, D_GS_ZDR_YJDJ, D_GS_BK_SSJZ, D_GS_BK_SQLX, D_BZ_SF, D_GS_XS_LY, D_BZ_SSZT, D_GS_XS_LX, D_GS_XS_QTLX } =
proxy.$dict("D_GS_ZDQT_ZT", "D_GS_ZDR_RYJB", "D_BZ_XB", "D_BZ_MZ", "D_BZ_XZQHDM", "D_GS_ZDR_BK_ZT", "D_GS_ZDR_CZZT", "D_GS_BQ_ZL", "D_GS_BQ_LB", "D_GS_BQ_LX", "D_GS_ZDR_YJDJ", "D_GS_BK_SSJZ", "D_GS_BK_SQLX", "D_BZ_SF", "D_GS_XS_LY", "D_BZ_SSZT", "D_GS_XS_LX", "D_GS_XS_QTLX");
@ -191,8 +196,14 @@ const pageData = reactive({
});
onMounted(() => {
getList();
tabHeightFn();
tabHeightFn();
if (route.query.id) {
addEdit('x', {
id: route.query.id
})
}else{
getList();
}
});
// 搜索
@ -215,7 +226,8 @@ const changeSize = (val) => {
const getList = () => {
pageData.tableConfiger.loading = true;
// 人员类型D_ZDRY_RYLX(01 重点 02 普通〉
let data = { rylx: '01', ...pageData.pageConfiger, ...queryFrom.value };
// rylx: '01',
let data = {...pageData.pageConfiger, ...queryFrom.value };
qcckGet(data, "/mosty-gsxt/tbGsxtZdry/selectPage").then((res) => {
pageData.tableData = res.records || [];
pageData.total = res.total;

View File

@ -69,7 +69,7 @@ const rules = reactive({
ryJg: [{ required: true, message: "请选择籍贯", trigger: "change" }],
zdrRyjb: [{ required: true, message: "请选择人员级别", trigger: "change" }],
zdrYjdj: [{ required: true, message: "请选择预警等级", trigger: "change" }],
rylx: [{ required: true, message: "请选择人员类型", trigger: "change" }]
// rylx: [{ required: true, message: "请选择人员类型", trigger: "change" }]
});
const listQuery = ref({ ryLxdh: [""] }); //表单
const chooseMarksVisible = ref(false); // 控制标签选择弹窗显示
@ -90,19 +90,19 @@ const formData = ref([
{ label: "出生日期", prop: "ryCsrq", type: "date" },
{ label: "户籍地区划", prop: "hjdQh", type: "select", options: D_BZ_XZQHDM },
{ label: "户籍地详址", prop: "hjdXz", type: "input" },
{ label: "户籍地派出所", prop: "hjdPcsdm", type: "department" },
{ label: "户籍地派出所", prop: "hjdPcsdm",depMc:"hjdPcsmc" ,type: "department" },
{ label: "现住地区划", prop: "xzdQh", type: "select", options: D_BZ_XZQHDM },
{ label: "现住地详址", prop: "xzdXz", type: "input" },
{ label: "现住地派出所", prop: "xzdPcsdm", type: "department" },
{ label: "现住地派出所", prop: "xzdPcsdm",depMc:"xzdPcsmc" ,type: "department" },
{ label: "管辖单位", prop: "gxSsbmdm", depMc: 'gxSsbmmc', type: "department" },
{ label: "诉求单位", prop: "sqSsbmdm", depMc: 'sqSsbmmc', type: "department" },
{ label: "责任单位", prop: "zrSsbmdm", depMc: 'zrSsbmmc', type: "department" },
{ label: "所属警种", prop: "zdrSsjz", type: "select", options: D_GS_BK_SSJZ },
{ label: "涉及警种", prop: "zdrSjjz", type: "select", options: D_GS_BK_SSJZ, multiple: true },
{ label: "婚姻状态", prop: "hyzk", type: "select", options: D_BZ_HYZK },
{ label: "处置状态", prop: "zdrCzzt", type: "select", options: D_GS_ZDR_CZZT },
{ label: "布控状态", prop: "zdrBkZt", type: "select", options: D_BZ_RCBKZT },
{ label: "人员类型", prop: "rylx", type: "select", options: D_ZDRY_RYLX },
// { label: "处置状态", prop: "zdrCzzt", type: "select", options: D_GS_ZDR_CZZT },
// { label: "布控状态", prop: "zdrBkZt", type: "select", options: D_BZ_RCBKZT },
// { label: "人员类型", prop: "rylx", type: "select", options: D_ZDRY_RYLX },
{ label: "入库开始时间", prop: "zdrRkkssj", type: "datetime" },
{ label: "入库结束时间", prop: "zdrRkjssj", type: "datetime" },
{ label: "Mac地址", prop: "macDz", type: "input" },

View File

@ -2,7 +2,7 @@
<div>
<div class="titleBox">
<PageTitle title="重点人审批">
<el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<!-- <el-popover placement="bottom" :visible="visible" :width="400" trigger="click">
<template #reference>
<el-button type="primary" @click="(visible = !visible), (visiblefp = false)" size="small">布控申请</el-button>
</template>
@ -23,7 +23,7 @@
</div>
</el-popover>
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button> -->
</PageTitle>
</div>
<!-- 搜索 -->
@ -56,7 +56,7 @@
</template>
<template #bqList="{ row }">
<ul >
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} ) </li>
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} ) </li>
</ul>
</template>

View File

@ -138,13 +138,11 @@ const init = (row) => {
listQuery.value = res
})
};
watch(() => approvalEcho.value, (val) => {
if (val) {
approvalEcho.value.getWorkflow(listQuery.value.gzlid)
}
}, { deep: true })
// 关闭
const close = () => {
dialogForm.value = false;

View File

@ -1,16 +1,17 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">警务工作{{ title }}</span>
<span class="title">{{ titleData }}{{ title }}</span>
<div>
<el-button @click="submitForm()" type="primary">保存</el-button>
<el-button @click="close">关闭</el-button>
</div>
</div>
<div style="display: flex;width: 100%;" v-loading="loading">
<div style="display: flex;width: 100%;" v-loading="loading">
<div class="form_cnt">
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
<template #gapdive>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">基础信息</el-divider>
</div>
@ -30,15 +31,15 @@
</template>
</FormMessage>
<el-divider content-position="left"><span class="mr20">活跃人员</span> </el-divider>
<Personnel :dict="props.dict" ref="personnel" :perList="listQuery.ryList"/>
<Personnel :dict="props.dict" ref="personnel" :perList="listQuery.ryList" />
<el-divider content-position="left"><span class="mr20">车辆信息</span> </el-divider>
<VehicleCar :dict="props.dict" ref="vehicleCar" :clList="listQuery.clList"/>
<VehicleCar :dict="props.dict" ref="vehicleCar" :clList="listQuery.clList" />
<el-divider content-position="left"><span class="mr20">关联群体</span> </el-divider>
<Group :dict="props.dict" ref="group" :qtList="listQuery.qtList" />
</div>
<div class="person" v-if="showPj">
<!-- <div class="person" v-if="showPj&&listQuery.qbjb!='00'">
<AddForm ref="addForm" :dict="props.dict" :msgeDat="msgeDat" />
</div>
</div> -->
</div>
</div>
</template>
@ -50,14 +51,18 @@ import VehicleCar from '../components/vehicleCar/index.vue'
import Group from '../components/group/index.vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qbcjAdd, qbcjUpdate, qbcjSelectByid } from "@/api/Intelligence.js";
import { ref, defineExpose, onMounted, defineEmits, watch } from "vue";
import { ref, defineExpose, onMounted, defineEmits, watch } from "vue";
import AddForm from '@/views/backOfficeSystem/MakeAcomment/components/a/addForm.vue'
import {useRoute,useRouter} from 'vue-router'
const emit = defineEmits(["getList"]);
const props = defineProps({
dict: Object
dict: Object,
titleData: {
type: String,
default: ""
}
});
const loading=ref(false)
const loading = ref(false)
const dialogForm = ref(false); //弹窗
const formData = ref();
watch(() => dialogForm.value, (val) => {
@ -66,8 +71,8 @@ watch(() => dialogForm.value, (val) => {
{ prop: "gapdive", type: "slot", width: '100%' },
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' },
{ label: "情报类型", prop: "qblx", type: "select", options: props.dict.D_GS_XS_LX, width: '45%' },
{ label: "情报级", prop: "qbmj", type: "select", options: props.dict.D_BZ_BMJB, width: '45%' },
{ label: "情报来源", prop: "qbly", type: "select", options: props.dict.D_GS_XS_LY, width: '45%' },
{ label: "情报级", prop: "qbmj", type: "select", options: props.dict.D_BZ_BMJB, width: '45%' },
// { label: "情报来源", prop: "qbly", type: "select", options: props.dict.D_GS_XS_LY, width: '45%' },
{ label: "情报上报时间", prop: "sxsbsj", type: "datetime", width: '45%' },
{ label: "指向时间", prop: "zxkssj", type: "datetime", width: '45%' },
{ label: "指向地址", prop: "zxdz", type: "input", width: '45%' },
@ -118,12 +123,16 @@ const submitForm = () => {
loading.value = true
elform.value.submit(valid => {
if (valid) {
const promes = {
...listQuery.value,
fjdz: fjdz.value.length > 0 ? fjdz.value.join(',') : '',
ryList: personnel.value.listData() || [],
clList: vehicleCar.value.listData() || [],
qtList:group.value.listData() || [],
qtList: group.value.listData() || [],
cjLx: 0
}
if (title.value == '新增') {
qbcjAdd(promes).then((res) => {
@ -143,8 +152,15 @@ const submitForm = () => {
}
})
}
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;

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="警务工作管理">
<PageTitle :title="titleData">
<el-button type="primary" @click="addEdit('add')">
<el-icon style="vertical-align: middle">
<CirclePlus />
@ -14,6 +14,18 @@
</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 />
@ -35,63 +47,34 @@
<template #qblx="{ row }">
<DictTag :tag="false" :value="row.qblx" :options="D_GS_XS_LX" />
</template>
<template #qbly="{ row }">
<DictTag :tag="false" :value="row.qbly" :options="D_GS_XS_LY" />
<template #cjlx="{ row }">
<DictTag :tag="false" :value="row.cjLx" :options="D_BZ_CJLX" />
</template>
<!-- <template #czzt="{row}">
<DictTag :tag="false" :value="row.czzt" :options="D_GS_XS_CZZT" />
</template> -->
<template #shzt="{ row }">
<!-- 采纳将这条信息推送到情报管理,退回 -->
<DictTag :tag="false" :value="row.shzt" :options="D_BZ_XSSHZT" @clickTag="clickTag(row.shzt)" />
<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.deptLevel == '01'" @click="cnMsg(row)">采纳</el-link>
<el-link size="small" type="primary" v-if="row.czzt == '03'&&qxkz.deptLevel == '01'" @click="opneMsg(row)">打标签</el-link>
<el-link size="small" type="primary" @click="rollbackNewspapers(row)"
v-if="row.czzt == '02' && row.qbjb == '00'" >回退</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)">详情</el-link>
<el-link size="small" type="primary" @click="addEdit('edit', row)">修改</el-link>
<!-- <el-link size="small" type="primary" @click="addEdit('edit', row)">下发指令</el-link> -->
<el-popconfirm title="是否进行发布?" @confirm="confirm(row)">
<template #reference>
<el-link size="small" type="primary">发布</el-link>
</template>
</el-popconfirm>
<el-popover placement="left" :visible="row.visible" :width="400" trigger="click">
<template #reference>
<el-link size="small" type="primary" @click.stop="handleSh(row)">转线索</el-link>
</template>
<div class="flex mb10 align-center">
<div class="w70 label-pop">状态 :</div>
<div style="flex:1">
<el-radio-group v-model="chooseRow.shzt" @change="rules.bhyy = false">
<el-radio v-for="obj in D_BZ_XSSHZT" :key="obj.value" :label="obj.value">{{ obj.zdmc }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="flex" v-if="chooseRow.shzt == '01'">
<div class="w70 label-pop">驳回原因 :</div>
<div style="flex:1">
<MOSTY.Other filterable style="width: 100%;" v-model="chooseRow.bhyy" type="textarea" rows="3" clearable
placeholder="请输入审核原因" />
<div class="f12" style="color: red;" v-if="rules.bhyy">请输入驳回原因</div>
</div>
</div>
<div class="mt10 flex just-center">
<el-button size="small" @click.stop="cancel(row)">取消</el-button>
<el-button size="small" type="primary" @click.stop="handleSumbit(row)">确定</el-button>
</div>
</el-popover>
<el-link size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
</template>
</MyTable>
</MyTable>checkProcess
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
<!-- 新增 -->
<AddForm ref="detailDiloag" @getList="getList" :dict="{
<AddForm ref="detailDiloag" @getList="getList" :titleData="titleData" :dict="{
D_BZ_SF,
D_GS_XS_LY,
D_BZ_SSZT,
@ -105,7 +88,11 @@
D_BZ_XZQHDM
}" />
</div>
<ExportFile v-model="exportFileModel" :tableColumn="tableColumn" :dict="{ D_GS_XS_LY ,D_GS_XS_LX}" :dataModel="pageData.tableData"/>
<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>
@ -116,43 +103,46 @@ import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import AddForm from "./components/addForm.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { qbcjSelectPage, qbcjDeletes } from "@/api/Intelligence.js";
import { reactive, ref, onMounted, getCurrentInstance, nextTick, watch } from "vue";
import { useRouter, useRoute } from 'vue-router'
import { qbcjSelectQbsbPage, qbcjDeletes, qbcjCzzt,qbcjPlsb } from "@/api/Intelligence.js";
import { reactive, ref, onMounted, getCurrentInstance } 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_GS_XS_QTLX, D_BZ_XSSHZT, D_GS_ZDQT_LB,
D_BZ_BMJB, D_BZ_CLPP, D_BZ_CLYS, D_BZ_CLLX, D_BZ_XZQHDM, D_GS_XS_CZZT } =
proxy.$dict("D_BZ_BMJB", "D_GS_XS_CZZT", "D_GS_XS_LY",
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_BZ_XSSHZT", "D_GS_ZDQT_LB", "D_BZ_CLPP", "D_BZ_CLYS", "D_BZ_CLLX", "D_BZ_XZQHDM", "D_GS_XS_CZZT"); //获取字典数据
"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 chooseRow = ref({})
const rules = reactive({
bhyy: false,
shzt: false,
})
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: 'sjryxm', placeholder: "请输入姓名", showType: "input" },
{ label: "身份证号", prop: 'sjrysfzh', placeholder: "请输入身份证号", showType: "input" },
{ label: "姓名", prop: 'xssbr', placeholder: "请输入姓名", showType: "input" },
{ label: "身份证号", prop: 'sfzh', placeholder: "请输入身份证号", showType: "input" },
{ label: "群体名称", prop: 'qtmc', placeholder: "请输入群体名称", showType: "input" },
{ label: "指向地点", prop: 'zxdz', placeholder: "请输入指向地点", showType: "input" },
{ label: "指向时间", prop: 'zxkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
{ label: "录入时间", prop: 'lrkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
{ label: "情报类型", prop: 'qblx', placeholder: "请选择情报类型", showType: "select", options: D_GS_XS_LX },
{ label: "情报来源", prop: 'qbly', placeholder: "请选择情报来源", showType: "select", options: D_GS_XS_LY },
{ label: "情报处置状态", prop: 'czzt', placeholder: "请选择处置状态", showType: "select", options: D_GS_XS_CZZT },
{ label: "来源单位", prop: 'gxdwdm', placeholder: "请选择来源单位", showType: "department" },
{ label: "情报来源", prop: '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({
@ -174,52 +164,99 @@ const pageData = reactive({
{ label: "情报编号", prop: "xsBh" },
{ label: "情报标题", prop: "qbmc" },
{ label: "情报类型", prop: "qblx", showSolt: true },
{ label: "情报来源", prop: "qbly", 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();
})
onMounted(() => {
getList()
tabHeightFn()
});
const handleSh = (val) => {
chooseRow.value = { id: val.id, shzt: '01' }
val.visible = !val.visible;
}).catch(() => { });
}
const cancel = (row) => {
row.visible = false;
rules.bhyy = false;
chooseRow.value = {}
}
const handleSumbit = (row) => {
rules.bhyy = !chooseRow.value.bhyy ? true : false;
if (chooseRow.value.shzt == '01' && rules.bhyy) return false;
let data = { ...chooseRow.value }
qcckPost(data, '/mosty-gsxt/qbcj/updateByXssh').then(res => {
row.visible = false;
proxy.$message({ type: "success", message: "审核成功" });
getList();
// 回退
const rollbackNewspapers = (item) => {
ElMessageBox.prompt('请输入回退原因', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
.then(({ value }) => {
qbcjCzzt({ id: item.id, czzt: '04', 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
console.log(lrkssj, zxkssj);
const promes = {
...pageData.pageConfiger,
...pageData.pageConfiger,
...val,
lrkssj: lrkssj ? lrkssj[0] : '',
lrjssj: lrkssj ? lrkssj[1] : '',
zxkssj: zxkssj ? zxkssj[0] : '',
@ -244,7 +281,7 @@ const changeSize = (val) => {
const getList = () => {
pageData.tableConfiger.loading = true;
let data = { ...pageData.pageConfiger, ...queryFrom.value };
qbcjSelectPage(data).then(res => {
qbcjSelectQbsbPage(data).then(res => {
pageData.tableData = res.records || [];
pageData.total = res.total;
pageData.tableConfiger.loading = false;
@ -257,22 +294,20 @@ const delDictItem = (id) => {
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: "qbly", showSolt: true,zd:'D_GS_XS_LY' },
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "指向地点", prop: "zxdz" },
{ label: "情报内容", prop: "qbnr",showOverflowTooltip: true },
{ 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;
@ -280,14 +315,6 @@ const addEdit = (type, row) => {
detailDiloag.value.init(type, row);
}, 500)
};
//发布
const confirm = (item) => {
qcckPost({ id: item.id, sffb: 1 }, '/mosty-gsxt/qbcj/qbfb').then(res => {
proxy.$message({ type: "success", message: "发布成功" });
getList();
})
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
@ -295,10 +322,42 @@ const tabHeightFn = () => {
tabHeightFn();
};
};
const route = useRoute()
const titleData = ref()
const qxkz = reactive({
deptBizType: '',
deptLevel: '',
});
onMounted(() => {
const { deptBizType, deptLevel } = getItem('deptId')[0]
const Jb = deptLevel[0] == '2' ? '01' : deptLevel[0] == '3' ? '02' : '03'
qxkz.deptBizType = deptBizType
qxkz.deptLevel = Jb
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 checkProcessModel=ref()
const checkProcess = (item) => {
checkProcessModel.value = true
dataList.value = item
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">社会信息员工工作考核{{ title }} </span>
<span class="title">工作考核{{ title }} </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit" >保存</el-button>
<el-button size="small" @click="close">关闭</el-button>

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="社会信息员工工作考核">
<PageTitle title="工作考核">
<el-button type="primary" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon>
<span style="vertical-align: middle">新增</span>

View File

@ -0,0 +1,213 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">{{ titleData }}{{ title }}</span>
<div>
<!-- <el-button @click="submitForm()" type="primary">保存</el-button> -->
<el-button @click="close">关闭</el-button>
</div>
</div>
<div style="display: flex;width: 100%;" v-loading="loading">
<div class="form_cnt">
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
<template #gapdive>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">基础信息</el-divider>
</div>
</template>
<template #gapline>
<div style="width: 100%;height: 10px;" class="mb20">
<el-divider content-position="left">情报内容</el-divider>
</div>
</template>
<template #scfj>
<div style="width: 100%;padding-left: 50px;">
<div>上传附件:<span class="f12">可附电子表格Word文档图像音视频文件</span> </div>
<div>
<MOSTY.Upload :showBtn="true" :isAll="true" :isImg="true" disabled :limit="10" v-model="fjdz" />
</div>
</div>
</template>
</FormMessage>
<el-divider content-position="left"><span class="mr20">活跃人员</span> </el-divider>
<Personnel :dict="props.dict" ref="personnel" :perList="listQuery.ryList" />
<el-divider content-position="left"><span class="mr20">车辆信息</span> </el-divider>
<VehicleCar :dict="props.dict" ref="vehicleCar" :clList="listQuery.clList" />
<el-divider content-position="left"><span class="mr20">关联群体</span> </el-divider>
<Group :dict="props.dict" ref="group" :qtList="listQuery.qtList" />
</div>
<div class="person" v-if="showPj&&listQuery.qbjb!='00'">
<AddForm ref="addForm" :dict="props.dict" :msgeDat="msgeDat" />
</div>
</div>
</div>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import Personnel from '../components/personnel/index.vue'
import VehicleCar from '../components/vehicleCar/index.vue'
import Group from '../components/group/index.vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qbcjAdd, qbcjUpdate, qbcjSelectByid } from "@/api/Intelligence.js";
import { ref, defineExpose, onMounted, defineEmits, watch } from "vue";
import AddForm from '@/views/backOfficeSystem/MakeAcomment/components/a/addForm.vue'
import {useRoute,useRouter} from 'vue-router'
const emit = defineEmits(["getList"]);
const props = defineProps({
dict: Object,
titleData: {
type: String,
default: ""
}
});
const loading = ref(false)
const dialogForm = ref(false); //弹窗
const formData = ref();
watch(() => dialogForm.value, (val) => {
if (val) {
formData.value = [
{ prop: "gapdive", type: "slot", width: '100%' },
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' },
{ label: "情报类型", prop: "qblx", type: "select", options: props.dict.D_GS_XS_LX, width: '45%' },
{ label: "情报等级", prop: "qbmj", type: "select", options: props.dict.D_BZ_BMJB, width: '45%' },
// { label: "情报来源", prop: "qbly", type: "select", options: props.dict.D_GS_XS_LY, width: '45%' },
{ label: "情报上报时间", prop: "sxsbsj", type: "datetime", width: '45%' },
{ label: "指向时间", prop: "zxkssj", type: "datetime", width: '45%' },
{ label: "指向地址", prop: "zxdz", type: "input", width: '45%' },
{ label: "附件上传", prop: "fjdz", type: "upload", width: '100%' },
{ label: "情报内容", prop: "qbnr", type: "textarea", width: '100%' },
]
}
}, { deep: true })
const fjdz = ref()
const listQuery = ref({}); //表单
const 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
// 初始化表单数据,并根据详情页设置禁用状态
if (row) getDataById(row.id);
} else {
showPj.value = false
}
};
// 根据id查询详情
const getDataById = (id) => {
qbcjSelectByid({ id }).then((res) => {
fjdz.value = res.ossList || [];
listQuery.value = res;
});
};
// 获取人员信息
const personnel = ref(null)
const vehicleCar = ref(null)
const group = ref(null)
// 新增
const submitForm = () => {
loading.value = true
elform.value.submit(valid => {
if (valid) {
const promes = {
...listQuery.value,
fjdz: fjdz.value.length > 0 ? fjdz.value.join(',') : '',
ryList: personnel.value.listData() || [],
clList: vehicleCar.value.listData() || [],
qtList: group.value.listData() || [],
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;
};
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;
}
</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,339 @@
<template>
<div>
<div class="titleBox">
<PageTitle :title="titleData">
<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 v-if="qxkz.deptLevel == '01'" type="primary" :disabled="ids.length === 0" @click="batchMark(ids)">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量打标</span>
</el-button>
<el-button type="primary" :disabled="ids.length === 0" @click="delDictItem(ids)">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">批量删除</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
@chooseData="chooseData">
<template #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 }">
<el-link size="small" type="primary" @click="opneMsg(row)" v-if="qxkz.deptLevel == '01'">打标签</el-link>
<el-link size="small" type="primary" @click="checkProcess(row)">查看流程</el-link>
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
<el-link size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
</div>
<!-- 新增 -->
<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 Search from "@/components/aboutTable/Search.vue";
import AddForm from "./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 '../components/maketag.vue'
import ExportFile from './components/exportFile.vue'
import CheckProcess from '../components/checkProcess.vue'
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([]);
onMounted(() => {
const { deptBizType, deptLevel } = getItem('deptId')[0]
const Jb = deptLevel[0] == '2' ? '01' : deptLevel[0] == '3' ? '02' : '03'
qxkz.deptBizType = deptBizType
qxkz.deptLevel = Jb
getRouter()
tabHeightFn()
if (route.query.id) {
detailDiloag.value.init('edit', {
id: route.query.id
});
return
}
getList()
});
const chooseData = (val) => {
ids.value = val.map(item => {
return item.id
})
tableList.value = val
}
const qxkz = reactive({
deptBizType: "",
deptLevel: ""
})
const list = ref()
const searchConfiger = ref();
watch(() => D_BZ_BQJB, val => {
if (qxkz.deptLevel == '01') {
list.value = val.value.filter(item => {
return item.dm != '00'
})
} else if (qxkz.deptLevel == '02') {
list.value = val.value.filter(item => {
return item.dm == '01' || item.dm == '02'
})
} else {
list.value = []
}
searchConfiger.value = [
{ label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" },
{ label: "姓名", prop: 'xssbr', placeholder: "请输入姓名", showType: "input" },
{ label: "身份证号", prop: 'sfzh', placeholder: "请输入身份证号", showType: "input" },
{ label: "群体名称", prop: 'qtmc', placeholder: "请输入群体名称", showType: "input" },
{ label: "指向地点", prop: 'zxdz', placeholder: "请输入指向地点", showType: "input" },
{ label: "指向时间", prop: 'zxkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
{ label: "录入时间", prop: 'lrkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
{ label: "情报类型", prop: 'qblx', placeholder: "请选择情报类型", showType: "select", options: D_GS_XS_LX },
{ label: "情报来源", prop: 'cjLx', placeholder: "请选择情报来源", showType: "select", options: D_BZ_CJLX },
{ label: "情报处置状态", prop: 'czzt', placeholder: "请选择处置状态", showType: "select", options: D_BZ_QBCZZT },
{
label: "标签级别", prop: 'qbjbList', placeholder: "请选择标签", showType: "select", options: list.value
},
{ label: "来源单位", prop: 'ssbmdm', placeholder: "请选择来源单位", showType: "department" },
{ label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" },
]
}, { deep: true, immediate: true })
const isShow = ref(false)
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: "xssbr" },
{ label: "情报编号", prop: "xsBh" },
{ 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 chooseRow = ref(false)
const dataList = ref()
const opneMsg = (item) => {
chooseRow.value = true
dataList.value = [item]
}
// 批量打标
const batchMark = () => {
chooseRow.value = true
dataList.value = tableList.value
}
// 搜索
const onSearch = (val) => {
const { lrkssj, zxkssj } = val
const promes = {
...val,
...pageData.pageConfiger,
lrkssj: lrkssj ? lrkssj[0] : '',
lrjssj: lrkssj ? lrkssj[1] : '',
zxkssj: zxkssj ? zxkssj[0] : '',
zxjssj: zxkssj ? zxkssj[1] : '',
}
queryFrom.value = { ...promes }
pageData.pageConfiger.pageCurrent = 1;
getList()
}
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 };
if (queryFrom.value.qbjbList == '' || queryFrom.value.qbjbList == undefined) {
if (qxkz.deptLevel == '02') {
data = { ...data, qbjbList: "01,02" }
}else if(qxkz.deptLevel == '03'){
data = { ...data, qbjbList: "01" }
}
}
qbcjSelectPage(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 tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
window.onresize = function () {
tabHeightFn();
};
};
const route = useRoute()
const titleData = ref()
const getRouter = () => {
titleData.value = route.meta.title
}
const exportFileModel = ref(false)
const dologCancel = () => {
exportFileModel.value = true;
}
// 流程
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

@ -1,7 +1,7 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">人力情报信息收集任务调度{{ title }} </span>
<span class="title">上报任务调度{{ title }} </span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="人力情报信息收集任务调度">
<PageTitle title="上报任务调度">
<el-button type="primary" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle">
<CirclePlus />

View File

@ -0,0 +1,158 @@
<!--文件导出 -->
<template>
<el-dialog v-model="modelValue" :title="title" :width="width" @close="close" append-to-body>
<div style="height: 50vh; overflow: auto;">
<el-timeline style="max-width: 600px">
<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>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { onMounted, reactive, watch, ref } from 'vue'
import {qbcjSelectCzlcList } from "@/api/Intelligence.js";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
width: {
type: String,
default: '50%'
}, tableColumn: {
type: Array,
default: () => []
}, dict: {
type: Object,
default: () => ({})
},
dataList: {
type: Object,
default: () => ({})
},
title: {
type: String,
default: '操作流程'
}
})
onMounted(() => {
})
const dxRadio = ref()
const emit = defineEmits(['update:modelValue', 'getList'])
// 当对话框显示时处理表格列配置
watch(() => props.modelValue, (newVal) => {
if (newVal) {
getqbcjPldb()
}
})
const close = () => {
emit('update:modelValue', false)
}
const lcList=ref([])
const getqbcjPldb = () => {
qbcjSelectCzlcList({ qbid: props.dataList.id }).then(res => {
lcList.value=res||[]
})
.catch(() => {
})
}
</script>
<style scoped>
/* 时间线样式优化 */
.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;
}
/* 响应式设计 */
@media screen and (max-width: 768px) {
.process-info {
flex-direction: column;
}
.info-label {
margin-bottom: 4px;
}
}
</style>

View File

@ -0,0 +1,193 @@
<!--文件导出 -->
<template>
<el-dialog v-model="modelValue" :title="title" :width="width" @close="close" append-to-body>
<div style="height: 50vh; overflow: auto;">
<div class="intelligence-container" v-for="(item, index) in dataList" :key="index">
<div class="info-row">
<div class="info-item">
<div class="info-label">情报标题</div>
<div class="info-value">{{ item.qbmc }}</div>
</div>
<div class="info-item">
<div class="info-label">上报时间</div>
<div class="info-value">{{ item.sxsbsj }}</div>
</div>
</div>
<div class="info-row">
<div class="info-item">
<div class="info-label">情报类型</div>
<div class="info-value">
<DictTag :tag="false" :value="item.qblx" :options="dict.D_GS_XS_LX" />
</div>
</div>
<div class="info-item">
<div class="info-label">情报来源</div>
<div class="info-value">
<DictTag :tag="false" :value="item.cjLx" :options="dict.D_BZ_CJLX" />
</div>
</div>
</div>
<div class="content-section">
<div class="info-label">情报内容</div>
<div class="info-content">{{ item.qbnr }}</div>
</div>
</div>
<div class="content-section">
<div class="info-label">选中标签</div>
<el-radio-group v-model="dxRadio">
<el-radio :label="items.dm" v-for="(items, index) in dictList" :key="index">{{ items.zdmc }}</el-radio>
</el-radio-group>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submit">
确认
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { onMounted, reactive, watch, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { qbcjCzzt, qbcjPldb } from "@/api/Intelligence.js";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
width: {
type: String,
default: '50%'
}, tableColumn: {
type: Array,
default: () => []
}, dict: {
type: Object,
default: () => ({})
},
dataList: {
type: Array,
default: () => ([])
},
title: {
type: String,
default: '打标签'
}
})
onMounted(() => {
})
const dxRadio = ref()
const emit = defineEmits(['update:modelValue', 'getList'])
// 当对话框显示时处理表格列配置
watch(() => props.modelValue, (newVal) => {
if (newVal) {
dxRadio.value = props.dataList[0].qbjb
}
}, { deep: true })
const dictList = ref([])
watch(() => props.dict, (newVal, oldVal) => {
if (newVal) {
dictList.value = newVal.D_BZ_BQJB.filter(item => item.dm != '00')
}
})
const close = () => {
emit('update:modelValue', false)
}
const submit = () => {
if (!dxRadio.value) {
ElMessage({
message: '请选择标签',
type: 'warning',
showClose: true,
})
return
}
getqbcjPldb()
}
const getqbcjPldb = () => {
qbcjPldb({ ids: props.dataList.map(item => item.id), qbjb: dxRadio.value, czzt: '05' }).then(res => {
ElMessage({
message: '操作成功',
type: 'success',
showClose: true,
})
emit('getList')
close()
})
.catch(() => {
})
}
</script>
<style scoped>
.intelligence-container {
padding: 10px;
}
.info-row {
display: flex;
margin-bottom: 20px;
gap: 30px;
flex-wrap: wrap;
}
.info-item {
flex: 1;
min-width: 250px;
}
.info-label {
font-size: 14px;
font-weight: 600;
color: #409EFF;
margin-bottom: 8px;
}
.info-value {
font-size: 14px;
color: #606266;
padding: 8px;
background-color: #f5f7fa;
border-radius: 4px;
min-height: 32px;
line-height: 1.5;
}
.content-section {
margin-top: 10px;
}
.info-content {
font-size: 14px;
color: #606266;
padding: 12px;
background-color: #f5f7fa;
border-radius: 4px;
min-height: 100px;
line-height: 1.8;
white-space: pre-wrap;
word-break: break-word;
border-left: 3px solid #409EFF;
}
/* 响应式设计 */
@media screen and (max-width: 768px) {
.info-row {
flex-direction: column;
gap: 15px;
}
.info-item {
min-width: 100%;
}
}
</style>

View File

@ -20,7 +20,8 @@
<el-form-item label="地图范围" prop="pgis" class="ww100">
<div class="flex ww100">
<el-input v-model="listQuery.pgis" readonly placeholder="请输入地图范围" style="flex: 1;"></el-input>
<el-button :disabled="listQuery.qylx == 'xzqh'" type="primary" style="width: 136px;" class="ml10" @click="chooseMap">
<el-button :disabled="listQuery.qylx == 'xzqh'" type="primary" style="width: 136px;" class="ml10"
@click="chooseMap">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
@ -46,7 +47,7 @@
</div>
</el-form>
</el-dialog>
<ChooseGzy v-model="openDialog" @choose="chooseDataGzy" :roleIds="roleIds"/>
<ChooseGzy v-model="openDialog" @choose="chooseDataGzy" :roleIds="roleIds" />
</template>
@ -116,29 +117,29 @@ const getDateById = (id) => {
res.pgis = res.pgis ? [res.pgis] : [[[]]]
let icon = require('@/assets/point/sp.png');
nextTick(() => {
if (res.qylx=='xzqh') {
if (res.qylx == 'xzqh') {
emitter.emit('setBoundarys', {
data: {
type: "FeatureCollection",
features: [
{
geometry: {
type: "Polygon", // 多边形类型
coordinates: res.pgis // 坐标数组
},
properties: {}, // 属性信息
type: "Feature", // 特征类型
}
]
}
data: {
type: "FeatureCollection",
features: [
{
geometry: {
type: "Polygon", // 多边形类型
coordinates: res.pgis // 坐标数组
},
properties: {}, // 属性信息
type: "Feature", // 特征类型
}
]
}
})
})
} else {
if (res.sxts && res.sxts.length > 0) emitter.emit('addPointArea', { flag: 'gzy_ht', icon, coords: res.sxts });
if (res.pgis) {
let obj = { position: res.pgis, text: '', id: res.id };
emitter.emit("echoPlane", { coords: [obj], flag: "bkqy", type: "polygon" });
}
if (res.pgis) {
let obj = { position: res.pgis, text: '', id: res.id };
emitter.emit("echoPlane", { coords: [obj], flag: "bkqy", type: "polygon" });
}
}
})
@ -181,13 +182,13 @@ const closed = () => {
emitter.emit('removeEara', 'bkqy_ht')
emitter.emit('deletePointArea', 'gzy_ht')
showMap.value = false;
roleIds.value=[]
roleIds.value = []
formRef.value.resetFields();
modelShow.value = false;
};
const changeXzqh = (val) => {
emitter.emit('removeBj')
listQuery.value.pgis=bm[val]
listQuery.value.pgis = bm[val]
emitter.emit('setBoundarys', {
data: {
type: "FeatureCollection",
@ -218,15 +219,16 @@ const changeMap = (val) => {
// 感知源弹窗
const openDialog = ref(false);
const roleIds=ref([])
const roleIds = ref([])
const chooseDataGzy = (val) => {
roleIds.value = val.map(item => item.id)
listQuery.value.sxts = val.map(item => {
listQuery.value.sxts = val.map(item => {
return {
sbbh:item.sbbh,
sblx:item.sblx,
sbmc:item.sbmc,
}}
sbbh: item.sbbh,
sblx: item.sblx,
sbmc: item.sbmc,
}
}
)
}

View File

@ -12,16 +12,12 @@
<div class="form_cnt">
<el-form :model="listQuery" :rules="rules" :disabled="disabled" ref="elform" inline :label-width="100"
label-position="left">
<div class="smallTitle">布控信息</div>
<!-- <el-form-item prop="bkBt" label="布控标题">
<MOSTY.Other v-model="listQuery.bkBt" placeholder="请输入布控标题" clearable />
</el-form-item> -->
<el-form-item prop="bkDx" label="布控对象">
<MOSTY.Select v-model="listQuery.bkDx" @change="shangeDx" :dictEnum="props.dic.D_GS_BK_DX"
placeholder="请选择布控对象" clearable />
</el-form-item>
<div class="ww100 mt10 mb10">
<el-button type="primary" @click="handleAddPeo" v-if="!disabled">
<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-group>
<el-button type="primary" @click="handleAddPeo" v-if="!disabled" style="margin-left: 10px;">
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
@ -33,7 +29,7 @@
:tableHeight="tableDate.tableHeight" :key="tableDate.keyCount" :tableConfiger="tableDate.tableConfiger"
:controlsWidth="tableDate.controlsWidth">
<template #fjZp="{ row }">
<el-image :src="row.fjZp"></el-image>
<el-image :src="setAddress(row.fjZp)"></el-image>
</template>
<template #yjdj="{ row }">
<DictTag :tag="false" :value="row.yjdj" :options="props.dic.D_GS_ZDR_YJDJ" />
@ -56,39 +52,8 @@
</template>
</MyTable>
</div>
<div class="smallTitle">布控范围</div>
<div class=" mapSearch flex">
<el-select v-model="hzfs" placeholder="请选择布控范围" clearable @change="qhhzfs">
<el-option label="区域选择" value="1"></el-option>
<el-option label="自定义范围" value="2"></el-option>
</el-select>
<el-select multiple style="margin-left: 10px;" v-model="bkqyList" placeholder="请选择布控范围" clearable
@change="hzfsChage" v-if="hzfs == '1'">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in bkqyArr" :key="index">{{
item.label
}}</el-option>
</el-select>
<!-- <MOSTY.Select v-model="listQuery.bkqyList" filterable multiple :dictEnum="bkqyArr" style="width:350px"
placeholder="请选择布控范围" clearable /> -->
<el-button type="primary" @click="drawQy" style="margin-left: 10px;" v-else>
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">自定义区域</span>
</el-button>
</div>
<div class="ww100 relative mb10"
style="height: 250px;border: 1px solid #dcdfe6;border-radius: 4px;overflow: hidden;">
<GdMap></GdMap>
</div>
<!-- <el-form-item prop="bkBt" label="布控要素" style="width: 100%;">
<div class="flex align-center">
<el-button @click="listQuery.bkYz = it.dm" :type="listQuery.bkYz == it.dm ? 'primary' : ''"
v-for="it in props.dic.D_GS_BK_BKYS" :key="it">{{ it.zdmc }}</el-button>
</div>
</el-form-item> -->
<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>
@ -96,19 +61,17 @@
<MOSTY.Date v-model="listQuery.bkSjJs" type="datetime" format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择布控结束时间" clearable />
</el-form-item>
</div>
<div style="width: 100%;" class="mt25">
<el-form-item prop="czYq" label="处置要求">
<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="布控等级">
<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>
@ -120,6 +83,30 @@
<div>支持pngjpgpdf文件上传</div>
</div>
</el-form-item>
</div>
<div class="smallTitle">布控范围</div>
<div class=" mapSearch flex">
<el-select v-model="hzfs" placeholder="请选择布控范围" clearable @change="qhhzfs">
<el-option label="区域选择" value="1"></el-option>
<el-option label="自定义范围" value="2"></el-option>
</el-select>
<el-select multiple style="margin-left: 10px;" v-model="bkqyList" placeholder="请选择布控范围" clearable
@change="hzfsChage" v-if="hzfs == '1'">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in bkqyArr" :key="index">{{
item.label
}}</el-option>
</el-select>
<el-button type="primary" @click="drawQy" style="margin-left: 10px;" v-else>
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">自定义区域</span>
</el-button>
</div>
<div class="ww100 relative mb10"
style="height: 60vh;border: 1px solid #dcdfe6;border-radius: 4px;overflow: hidden;">
<GdMap></GdMap>
</div>
</el-form>
</div>
@ -158,11 +145,14 @@ import emitter from "@/utils/eventBus.js";
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, nextTick, watch, onMounted } from "vue";
import { queryProcessNode, queryProcessNodeLog, queryProcess } from '@/api/spl'
import ApprovalEcho from "@/components/flowPath/ApprovalEcho.vue";
import { useRouter, useRoute } from 'vue-router'
import { setAddress } from '@/utils/tools.js'
import { tbGsxtBkId } from "@/api/commit.js";
const emit = defineEmits(["change"]);
const props = defineProps({
dic: Object
});
const route = useRoute()
const elform = ref()
const roleIds = ref([]); //角色ID
const chooseVisible_RY = ref(false); //选择布控人员弹窗
@ -357,6 +347,8 @@ const choosed = (val) => {
// 选择人员
const handleAddPeo = () => {
console.log(listQuery.value.bkDx);
if (!listQuery.value.bkDx) return proxy.$message({ type: "warning", message: '请选择布控对象' });
switch (listQuery.value.bkDx) {
case '01':
@ -385,7 +377,13 @@ const handleAddPeo = () => {
const submit = () => {
elform.value.validate((validate) => {
if (!validate) return;
let params = { ...listQuery.value };
let bklx = ''
if (route.name == 'myControl') {
bklx = '01'
} else {
bklx = '02'
}
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(',') : '' })
@ -663,4 +661,11 @@ defineExpose({ init });
color: #18a2dd;
}
}
::v-deep .el-form-item__label{
padding: 0;
}
::v-deep .el-radio-button__inner{
color:#000 !important;
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="titleBox">
<PageTitle title="我的布控">
<PageTitle :title=" route.meta.title ">
<el-button type="primary" @click="handleAdd('add', null)">发起布控</el-button>
</PageTitle>
</div>
@ -47,12 +47,12 @@
<template v-if="!row.gzlid">
<el-link type="primary" v-if="['01', '03', '06'].includes(row.bkZt)" size="small"
@click="createProcess(row)">送审</el-link>
<el-link type="primary" size="small" @click="tbGsxtBkQuashList( row)" v-else>撤控</el-link>
<el-link type="primary" v-if="['01', '03', '06'].includes(row.bkZt)" size="small"
@click="handleAdd('edit', row)">编辑</el-link>
</template>
<!-- 审核通过后才有轨迹 -->
<el-link type="primary" size="small" @click="handleAdd('detail', row)">轨迹</el-link>
<el-link type="primary" size="small" @click="handleAdd('detail', row)">详情</el-link>
<el-link type="danger" size="small" @click="handleRow(row.id)"
v-if="['01', '03', '06'].includes(row.bkZt)">删除</el-link>
@ -66,14 +66,13 @@
</div>
</div>
<!-- 布控类型 -->
<AddBkdx ref="addBkdxForm" @change="getList"
:dic="{
D_GS_BK_DX, D_GS_BK_BKYS, D_BZ_XB, D_GS_BK_CZYQ,
D_GS_BK_DJ, BD_BK_CLYJBQ, D_GS_BK_CZJSDWLX, D_GS_BK_TJFS,D_GS_ZDR_YJDJ
}" />
<AddBkdx ref="addBkdxForm" @change="getList" :dic="{
D_GS_BK_DX, D_GS_BK_BKYS, D_BZ_XB, D_GS_BK_CZYQ,
D_GS_BK_DJ, BD_BK_CLYJBQ, D_GS_BK_CZJSDWLX, D_GS_BK_TJFS, D_GS_ZDR_YJDJ
}" />
<!-- 预警弹窗 -->
<YjDialog ref="warningkdxForm"></YjDialog>
<SubmissionProcess v-model="showSp" :data="rowData" :userData="{ ajmc: '布控审批', flowType: 'BKSP',modelName:'布控' }"
<SubmissionProcess v-model="showSp" :data="rowData" :userData="{ ajmc: '布控审批', flowType: 'BKSP', modelName: '布控' }"
:path="fixedValue" @getList="getList" />
</template>
@ -86,10 +85,14 @@ import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js";
import SubmissionProcess from '@/components/flowPath/submissionProcess.vue'
import {tbGsxtBkQuash} from '@/api/zdr.js'
import { useRouter, useRoute } from 'vue-router'
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
const router = useRouter()
const route = useRoute()
const { proxy } = getCurrentInstance();
const { D_GS_BK_BKYS, D_BZ_XB, D_GS_BK_SJLX, D_GS_BK_DJ, BD_BK_CLYJBQ,D_GS_ZDR_YJDJ,
D_GS_BK_DX, D_GS_BK_ZT, D_GS_BK_CZYQ, D_GS_BK_CZJSDWLX, D_GS_BK_TJFS } = proxy.$dict("D_GS_ZDR_YJDJ","D_GS_BK_BKYS", "D_BZ_XB", "D_GS_BK_SJLX", "D_GS_BK_DJ", "D_GS_BK_DX", "D_GS_BK_ZT", "D_GS_BK_CZYQ", "D_GS_BK_CZJSDWLX", "D_GS_BK_TJFS", 'BD_BK_CLYJBQ'); //获取字典数据
const { D_GS_BK_BKYS, D_BZ_XB, D_GS_BK_SJLX, D_GS_BK_DJ, BD_BK_CLYJBQ, D_GS_ZDR_YJDJ,
D_GS_BK_DX, D_GS_BK_ZT, D_GS_BK_CZYQ, D_GS_BK_CZJSDWLX, D_GS_BK_TJFS } = proxy.$dict("D_GS_ZDR_YJDJ", "D_GS_BK_BKYS", "D_BZ_XB", "D_GS_BK_SJLX", "D_GS_BK_DJ", "D_GS_BK_DX", "D_GS_BK_ZT", "D_GS_BK_CZYQ", "D_GS_BK_CZJSDWLX", "D_GS_BK_TJFS", 'BD_BK_CLYJBQ'); //获取字典数据
const addBkdxForm = ref(null); //布控对象组件
const warningkdxForm = ref(); //布控对象组件
const searchBox = ref(); //搜索框
@ -144,11 +147,10 @@ const pageData = reactive({
});
// 固定值
const fixedValue = {
clueVerification:'deploymentApproval',
clueVerification: 'deploymentApproval',
byMeansOf: 'tbGsxtBk/gsbkCallback',
nobyMeansOf: 'tbGsxtBk/gsbkCallback',
recycle:'tbGsxtBk/gsbkCallback',
recycle: 'tbGsxtBk/gsbkCallback',
}
const showSp = ref(false);
const rowData = ref()
@ -180,10 +182,19 @@ const changeSize = (val) => {
// 获取列表
const getList = () => {
pageData.tableConfiger.loading = true;
let bklx = ''
console.log();
if (route.name == 'myControl') {
bklx = '01'
} else {
bklx = '02'
}
let data = {
...pageData.pageConfiger,
...queryFrom.value,
bkcxlx: '01'
bkcxlx: '01',
bklx: bklx
};
qcckGet(data, "/mosty-gsxt/tbGsxtBk/selectPage").then((res) => {
pageData.tableData = res.records || [];
@ -194,25 +205,10 @@ const getList = () => {
});
};
// 打开预警
const openWarning = (val) => {
warningkdxForm.value.init(val)
}
const handleAdd = (type, row) => {
addBkdxForm.value.init(type, row);
};
// 送审
const handleSend = (id) => {
proxy.$confirm("确定要送审?", "警告", { type: "warning" }).then(() => {
qcckPost({}, "/mosty-gsxt/tbGsxtBk/subExamine/" + id).then(() => {
proxy.$message({ type: "success", message: "送审成功" });
getList();
});
})
}
// 删除
const handleRow = (id) => {
proxy.$confirm("确定要删除?", "警告", { type: "warning" }).then(() => {
@ -229,7 +225,14 @@ const tabHeightFn = () => {
window.onresize = function () {
tabHeightFn();
};
};</script>
};
const tbGsxtBkQuashList = (item) => {
tbGsxtBkQuash({id:item.id}).then(res=>{
proxy.$message({ type: "success", message: "操作成功" });
getList();
})
}
</script>
<style lang="scss" scoped>
.el-loading-mask {

View File

@ -0,0 +1,136 @@
<template>
<el-dialog width="1400px" :draggable="true" custom-class="bgData" :model-value="modelValue" append-to-body
@close="close" :show-close="false">
<template #title>
<div class="title">
<div class="titleName">测试数据</div>
<div>
<el-icon :size="25" class="titleIcon">
<BottomLeft />
</el-icon>
<el-icon :size="25" class="titleIcon">
<FullScreen />
</el-icon>
<el-icon @click="close" :size="25" class="titleIcon">
<Close />
</el-icon>
</div>
</div>
<div class="statusBar">
<div>00:04</div>
<div>正在讲话...</div>
<div>
<el-icon :size="25" class="titleIcon">
<InfoFilled />
</el-icon>
<el-icon :size="25" class="titleIcon">
<CircleCheckFilled />
</el-icon>
<el-icon @click="close" :size="25" class="titleIcon">
<Unlock />
</el-icon>
</div>
</div>
</template>
<div class="content"></div>
<template #footer>
<Footer @close="close" />
</template>
</el-dialog>
</template>
<script setup>
import { ref, watch, reactive, toRaw, computed, getCurrentInstance } from "vue";
import Footer from './footer.vue'
// import useCallModule from '../sdk/call.js'
const { proxy } = getCurrentInstance();
// const Call = useCallModule()
lemon.login.login({
username: "linzhigongan1",
password: "linzhigongan1",
realm: "puc.com",
webpucUrl: "https://192.168.0.1:16888",
}).then(res => {
console.log(res,"登录成功");
}).catch(err => {
console.log(err,"登录失败");
})
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
titleValue: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:modelValue']);
const close = () => {
emit('update:modelValue', false);
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.title {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #e4e7ed;
padding: 10px;
.titleName {
font-size: 20px;
margin-bottom: 5px;
width: 40%;
}
.titleIcon {
margin-left: 15px;
}
}
.statusBar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 6px;
}
.content {
padding: 0 10px;
height: 60vh;
overflow: auto;
background-color: #000;
}
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
.bgData {
padding: 10px;
}
::v-deep .el-dialog__body {
padding: 0 !important;
}
</style>
<style>
.bgData .el-dialog__header,
.el-dialog__body {
padding: 0;
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<div class="footer">
<div class="footerWidth">
<div>
<div class="icon"><img src="@/assets/images/icon/jyy-k.png" alt=""></div>
<div>麦克风</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/lb-k.png" alt=""></div>
<div>喇叭</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/sp-k.png" alt=""></div>
<div>摄像头</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/fx.png" alt=""></div>
<div>共享</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/hyyq.png" alt=""></div>
<div>邀请参会</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/glcy.png" alt=""></div>
<div>管理成员</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/jt.png" alt=""></div>
<div>截图</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/gb.png" alt=""></div>
<div>视频广播</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/yyjl.png" alt=""></div>
<div>语音激励</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/fz.png" alt=""></div>
<div>画面反转</div>
</div>
<div>
<div class="icon"><img src="@/assets/images/icon/yy.png" alt=""></div>
<div>应用</div>
</div>
</div>
<div class="footerBtn">
<el-button type="danger">结束会议</el-button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const emit=defineEmits(['close'])
const close=()=>{
emit('close')
}
</script>
<style scoped lang="scss">
.footer {
display: flex;
justify-content: space-between;
align-items: center;
height: 50px;
.footerWidth {
display: flex;
justify-content: space-between;
align-items: center;
flex: 1;
.icon{
width: 25px;
margin: 0 auto;
img{
width: 100%;
}
}
}
.footerBtn {
width: 100px;
margin-left: 20px;
}
}
</style>

View File

@ -0,0 +1,139 @@
<template>
<el-dialog width="1400px" title="选择参会人员" :draggable="true" :model-value="modelValue" append-to-body @close="close"
:show-close="false">
<div class="content">
<div class="left">
<el-tabs v-model="activeName" @tab-click="handleClick" :stretch="true">
<el-tab-pane label="全网设备" name="first">
<el-tree-v2 style="max-width: 600px" :data="data" :props="propsData" :height="530" />
</el-tab-pane>
<el-tab-pane label="调度台" name="second">Config</el-tab-pane>
<el-tab-pane label="动态警组" name="third">Role</el-tab-pane>
<el-tab-pane label="第三方会议" name="fourth">Task</el-tab-pane>
<el-tab-pane label="车载" name="fourth">Task</el-tab-pane>
</el-tabs>
<!-- <el-tree-v2
style="max-width: 600px"
:data="data"
:props="propsData"
:height="600"
/> -->
</div>
<div class="right"></div>
</div>
</el-dialog>
</template>
<script setup>
import { ref, watch, reactive, toRaw, computed, getCurrentInstance, onMounted } from "vue";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
titleValue: {
type: String,
default: ''
}
})
// Tabs 组件
const activeName = ref('first')
const handleClick = (tab) => {
console.log(tab)
}
onMounted(() => {
lemon.basedata.fetchSystemOrg({
flat: true,
key_word: ""
}).then(res => {
console.log(res);
})
})
const getJgList = () => {
}
const getKey = (prefix, id) => {
return `${prefix}-${id}`
}
const createData = (
maxDeep,
maxChildren,
minNodesNumber,
deep = 1,
key = 'node'
) => {
let id = 0
return Array.from({ length: minNodesNumber })
.fill(deep)
.map(() => {
const childrenNumber =
deep === maxDeep ? 0 : Math.round(Math.random() * maxChildren)
const nodeKey = getKey(key, ++id)
return {
id: nodeKey,
label: nodeKey,
children: childrenNumber
? createData(maxDeep, maxChildren, childrenNumber, deep + 1, nodeKey)
: undefined,
}
})
}
const propsData = {
value: 'id',
label: 'label',
children: 'children',
}
const data = createData(4, 30, 40)
const emit = defineEmits(['update:modelValue']);
const close = () => {
emit('update:modelValue', false);
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.content {
padding: 0 10px;
height: 60vh;
overflow: auto;
display: flex;
.left {
width: 20%;
height: 100%;
// background-color: #3c8aff;
margin-right: 5px;
}
.right {
flex: 1;
height: 99%;
border: 1px solid #ccc;
}
}
::v-deep .el-tabs__nav-wrap::after {
background-color: #ccc;
}
::v-deep .el-tabs__nav-next,
.el-tabs__nav-prev {
color: #000;
}
::v-deep .el-tabs__item {
color: #000;
}
::v-deep .el-tabs__item.is-active {
color: #3c8aff;
}
</style>

View File

@ -13,11 +13,12 @@
<el-input placeholder="请选择关联线索" @click="chooseVisiblexS = true" readonly v-model="listQuery.glxsmc"></el-input>
</template>
<template #chryList>
<el-input placeholder="请选择参会人员" @click="chooseVisible = true" readonly v-model="listQuery.rymc"></el-input>
<el-input placeholder="请选择参会人员" @click="openMeetings = true" readonly v-model="listQuery.rymc"></el-input>
</template>
</FormMessage>
</div>
</div>
<Personnel v-model="openMeetings" />
<ChooseUser v-model="chooseVisible" :Single="false" @choosedUsers="handleUserSelected" :roleIds="roleIds" />
<Xslist v-model="chooseVisiblexS" @choosed="choosed" :roleIds="roleIdsxs"></Xslist>
</template>
@ -27,6 +28,7 @@ import ChooseUser from "@/components/ChooseList/ChooseUser/index.vue";
import Xslist from '@/components/ChooseList/ChooseXs/index.vue'
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import Personnel from '../components/Communications/personnel.vue'
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, } from "vue";
const emit = defineEmits(["updateDate"]);
@ -109,6 +111,8 @@ const close = () => {
dialogForm.value = false;
loading.value = false;
};
// 选择参会人员
const openMeetings=ref(false)
defineExpose({ init });
</script>

View File

@ -66,6 +66,7 @@
<!-- 详情 -->
<DetailForm ref="detailDiloag" @updateDate="getList" />
<RoomDetail />
<ConferenceRoom v-model="conferenceRoomVisible" titleValue="会议详情" />
</template>
<script setup>
@ -77,7 +78,8 @@
import RoomDetail from "./components/roomDetail.vue";
import { useRoute, useRouter } from 'vue-router';
import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
import ConferenceRoom from "./components/Communications/conferenceRoom.vue";
const route = useRoute();
const { proxy } = getCurrentInstance();
const detailDiloag = ref();
@ -165,10 +167,11 @@
})
};
// 加入会议
const joinMeeting = (item) => {
qcckPost({id:item.id},'/mosty-gsxt/wshs/addWshyRy').then((res)=>{
getList();
})
const joinMeeting = (item) => {
conferenceRoomVisible.value = true;
// qcckPost({id:item.id},'/mosty-gsxt/wshs/addWshyRy').then((res)=>{
// getList();
// })
};
// 删除
@ -192,7 +195,12 @@ const delDictItem = (id) =>{
window.onresize = function () {
tabHeightFn();
};
};
};
// 会议详情弹窗
const conferenceRoomVisible = ref(false);
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,714 @@
// import { Notification } from '@arco-design/web-vue';
import { ElNotification, ElMessage } from 'element-plus'
import emitter from "@/utils/eventBus.js";
// import handleCallingNotification from '../hooks/callingNotification';
let call_id;
let hangup_event_cb_id;
let force_hangup_event_cb_id;
let answer_ack_cb_id;
let incoming_cb_id;
let floor_grant_cb_id;
// Whether it is a pushVideoFile call
// 是否为视频推送的呼叫
let pushing_video = false;
// monitor call list
// 值守呼叫列表
const monitor_call_list = [];
export default function useCallModule() {
// we allow only one call exist in demo.but actually,sdk supports more
/**
* make private vioce call,return nothing,receive result in callback
* This interface has been expanded to support makeGroupVoiceCall、makeDispatcherVoiceCall、makeConferenceVoiceCall、makeCrosspatchVoiceCall
* 这个接口已扩展,除了支持语音单呼外,还支持语音组呼、语音呼叫调度员、语音会议、群组呼叫。
* @param record who you wanna call
* @returns
*/
const makeVoiceCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeVoiceCall({ basedata_id: record.basedata_id, hook_flag: 0 })
?.then((resp) => {
call_id = resp.call_id;
console.info('makeVoiceCall succ,registerCallEstablishEvent', call_id);
});
// test
// window.lemon.call.changeCamera({ call_id, target_camera: 0 });
// also can use this makecall method,the method provides the most comprehensive call capability
// For example, Voice private call, ensure that the basedata_id is a private
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 0,
// call_mode: 0,
// duplex_flag: 0,
// },
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
// For example, Voice group call,ensure that the basedata_id is a group
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 1,
// call_mode: 0,
// duplex_flag: 0, // group call ,the value must be 0
// },
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
};
/**
* make private video call,call with vioce and video,return nothing,receive result in callback
* This interface has been expanded to support makeGroupVideoCall、makeDispatcherVideoCall、makeConferenceVideoCall
* 这个接口已扩展,除了支持视频单呼外,还支持视频组呼、视频呼叫调度员、视频会议
* @param record who you wanna call
* @returns
*/
const makeVideoCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeVideoCall({ basedata_id: record.basedata_id, video_frame_size: 3 })
?.then((resp) => {
call_id = resp.call_id;
console.warn('makeVideoCall succ,call_id=', call_id);
});
// also can use this makecall method,the method provides the most comprehensive call capability
// For example, Video private call (with voice), ensure that the basedata_id is a private
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 11,
// call_mode: 2,
// duplex_flag: 1,
// },
// video_frame_size: window.lemon.call.getMaxFrameSize(),
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
// For example, Video group call,ensure that the basedata_id is a group
// window.lemon.call
// .makeCall({
// callee_guid: record.basedata_id,
// attribute: {
// call_type: 13,
// call_mode: 2,
// duplex_flag: 0, // group call ,the value must be 0
// },
// video_frame_size: window.lemon.call.getMaxFrameSize(),
// })
// ?.then((resp) => {
// console.info('makeCall succ,resp', resp);
// call_id = resp.call_id;
// });
};
const makeGroupVideoCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeGroupVideoCall({
basedata_id: record.basedata_id,
video_frame_size: 3,
})
?.then((resp) => {
console.log('makeGroupVideoCall call_id = ', call_id);
call_id = resp.call_id;
});
};
const makeGroupVoiceCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.makeGroupVoiceCall({
basedata_id: record.basedata_id,
})
?.then((resp) => {
call_id = resp.call_id;
});
};
const makeCrosspatchVoiceCall = (record) => {
window.lemon.call
.makeCrosspatchVoiceCall({ basedata_id: record.basedata_id })
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 视频上拉
* make pure video call,only video, no voice
* @param record who you wanna call
* @returns
*/
const pureVideoCall = (record) => {
if (call_id) {
console.warn('we allow only one call exist,please hangup first');
return;
}
window.lemon.call
.pullVideo({ basedata_id: record.basedata_id, hook_flag: 0 })
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 环境监听
* @param record
*/
const voiceDetect = (record) => {
window.lemon.call
.makeCall({
callee_guid: record.basedata_id,
attribute: {
call_type: 0,
call_mode: 0,
duplex_flag: 0,
ambience_flag: 1,
},
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 环境监视
* @param record
*/
const videoDetect = (record) => {
window.lemon.call
.makeCall({
callee_guid: record.basedata_id,
attribute: {
call_type: 11,
call_mode: 2,
duplex_flag: 0,
ambience_flag: 1,
},
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 音频会议
* @param record
*/
const makeConferenceVoiceCall = (record) => {
window.lemon.call
.makeConferenceVoiceCall({
basedata_id: record.basedata_id,
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* 音视频会议
* @param record
*/
const makeConferenceVideoCall = (record) => {
window.lemon.call
.makeConferenceVideoCall({
basedata_id: record.basedata_id,
})
?.then((resp) => {
call_id = resp.call_id;
});
};
// 广播呼叫
// Broadcast Call
const makeBroadcastCall = (record) => {
window.lemon.call
.makeCall({
callee_guid: record.basedata_id,
attribute: {
call_type: 3,
call_mode: 0,
},
})
?.then((resp) => {
call_id = resp.call_id;
});
};
/**
* hangup call
*/
const hangup = (id) => {
console.info('try hangup,call_id=', call_id);
console.info('try hangup,id=', id);
window.lemon.call
.hangupCall({ call_id: id || call_id })
?.then(() => {
call_id = undefined;
window.calling_conference = undefined;
// console.log('22222registerCallEstablishEven');
})
.catch((err) => {
console.error('hangup call error,', err);
});
};
/**
* 接听呼叫
* answer call
*/
const answerCall = () => {
ElNotification.close(call_id);
window.lemon.call
.answerCall({ call_id })
?.then(() => {
// display alert ui
ElNotification.close(call_id);
})
.catch((err) => {
console.error('answer call error,', err);
});
};
// 禁麦
// mute the microphone
const setMuteMic = (mute) => {
return window.lemon.call.muteMic({
call_id,
is_mute: mute,
});
};
// 禁摄像头
// disable the camera
const setMuteCamera = (mute) => {
return window.lemon.call.muteCamera({
call_id,
is_mute: mute,
});
};
// 静音
// mute call
const setMuteCall = (mute) => {
return window.lemon.call.muteCall({
call_id,
is_mute: mute,
});
};
const removeMonitorCall = (callId) => {
const index = monitor_call_list.findIndex(
(item) => item.call_id === callId
);
if (index >= 0) {
monitor_call_list.splice(index, 1);
emitter.emit('monitorUpdate');
}
};
const getMonitorCallList = () => {
return monitor_call_list;
};
// 添加 挂断 回调
// After hanging up the call, you can receive a notification and process the style of the current page based on the notification
const registerhangupEvent = () => {
if (hangup_event_cb_id !== undefined) {
return;
}
hangup_event_cb_id = window.lemon.call.addHangupEvt((data) => {
console.info('receive hangup event');
console.info(
'receive hangup event receive call id',
String(data.call_id)
);
console.info('receive hangup event local call id', String(call_id));
if (data.call_id === call_id) {
// remove display alert ui
ElNotification.close(call_id);
call_id = undefined;
window.calling_conference = undefined;
// console.log('2222211111registerCallEstablishEvent');
}
// pushVideoFile uninit
// 如果是视频推送的,挂断是反初始化一些东西。
if (pushing_video) {
window.video.src = undefined;
window.showVideo.value = false;
pushing_video = false;
window.videoViewRoot.style.display = 'none';
}
removeMonitorCall(data.call_id);
});
};
// 添加强拆事件
const registerForceHangupEvent = () => {
if (force_hangup_event_cb_id !== undefined) {
return;
}
force_hangup_event_cb_id = window.lemon.call.addForceHangupEvt((data) => {
// 目前强拆成功,都是走挂断通知事件。 当失败了,才走强拆事件通知。
if (data.result === 0) {
if (data.call_id === call_id) {
ElNotification.close(call_id);
call_id = undefined;
window.calling_conference = undefined;
}
removeMonitorCall(data.call_id);
} else {
// 强拆失败 fail
ElMessage.error("强拆失败");
}
});
};
// 添加接听回调通知 代表呼叫建立
// receive the answer acknowledgement asynchronously after the call is established
const registerCallEstablishEvent = () => {
if (answer_ack_cb_id !== undefined) {
return;
}
answer_ack_cb_id = window.lemon.call.addAnswerAckEvt((data) => {
// console.info('registerCallEstablishEvent0', call_id);
console.info('registerCallEstablishEvent', String(data.call_id));
console.info('registerCallEstablishEvent', JSON.stringify(data));
call_id = data.call_id;
// pushVideoFile init
// 接通后,视频推送的文件开始播放
if (pushing_video) {
window.videoViewRoot.style.display = 'unset';
window.showVideo.value = true;
window.video.play();
}
});
};
// 注册来电通知回调
// add the incoming call callback
const registerReceiveCallEvent = () => {
if (incoming_cb_id !== undefined) {
return;
}
incoming_cb_id = window.lemon.call.addIncomingEvt((session) => {
console.log('receive call------>', session);
call_id = session.call_id;
const callingReq = {
callInfo: session,
equipment: undefined,
text: {
calling: '队列',
answer: '接听',
hangUp: '挂断',
},
};
console.log('receive this------>', useCallModule());
if (session.listen_flag) {
// monitor call,auto answer call
// 值守的来电呼叫,自动接听
window.lemon.call.answerCall({ call_id: session.call_id });
monitor_call_list.push(session);
emitter.emit('monitorUpdate');
} else {
// normal call
// 正常来电,弹框询问接听
// handleCallingNotification(callingReq);
}
});
};
// 申请话权
// apply floor
const applyFloor = () => {
console.info('try applyFloor,call_id=', call_id);
if (!call_id) {
console.warn('no call exits');
return undefined;
}
return window.lemon.floor
.applySpeak({ call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('applyFloor request sucess');
} else {
ElMessage.error("申请话权失败");
}
})
.catch((err) => {
console.error('applyFloor error,', err);
});
};
// 释放话权
// release floor
const releaseFloor = () => {
console.info('try releaseFloor,call_id=', call_id);
return window.lemon.floor
.releaseSpeak({ call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('releaseSpeak request sucess');
} else {
ElMessage.error("释放话权失败");
}
})
.catch((err) => {
console.error('releaseSpeak error,', err);
});
};
// add floor event
// 添加话权通知事件
const registerFloorGrantEvent = () => {
if (floor_grant_cb_id !== undefined) {
return;
}
floor_grant_cb_id = window.lemon.floor.addGrantEvt((grantInfo) => {
console.log('registerFloorGrantEvent', grantInfo);
if (grantInfo.result !== 0) {
ElMessage.error("话权申请失败");
}
});
};
// 强拆
// override the call
const forceHangupCall = (callId) => {
return window.lemon.call
.forceHangupCall({ call_id: callId || call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('forceHangupCall request sucess');
} else {
ElMessage.error("强拆失败");
}
call_id = undefined;
window.calling_conference = undefined;
// console.log('2222233registerCallEstablishEven');
})
.catch((err) => {
console.error('forceHangupCall error,', err);
});
};
// 强插
// interrupt the call during monitoring
const forceApplySpeak = (callId) => {
return window.lemon.floor
.forceApplySpeak({ call_id: callId || call_id })
?.then((resp) => {
if (resp.result === 0) {
console.log('forceApplySpeak request sucess');
call_id = callId;
} else {
ElMessage.error("强插失败");
}
})
.catch((err) => {
console.error('forceApplySpeak error,', err);
});
};
/**
* 会议成员禁言
* mute or unmute a conference member
* @param param
* @param param.conference_basedata_id
*/
const muteMemberInConference = (
conference_basedata_id,
member_basedata_id,
mute
) => {
return window.lemon.call.conferenceMemberSpeakSet({
conference_call_id: call_id,
conference_basedata_id,
member_setting: {
member_basedata_id,
forbid: mute ? 1 : 0,
},
});
};
/**
* 视频推送
* select a local video file and play then push the stream to remote
* @param record
* @param file
* @returns
*/
const pushVideoFile = (record, url) => {
console.info('try pushVideoFile,call_id=', call_id);
if (call_id) {
console.warn('call exits');
return;
}
console.warn('window.video', window.video);
// set the file to video tag
if (window.video) {
const canPlayListener = () => {
window.video.removeEventListener('canplay', canPlayListener);
// capture stream
const stream = (window.video)?.captureStream();
console.info('pushVideoFile,inited stream=', stream);
// register hook listner ,play the video when remote hooked
registerCallEstablishEvent();
// init the call
window.lemon.call
.pushVideoFile({
basedata_id: record?.basedata_id,
stream,
})
?.then((resp) => {
pushing_video = true;
call_id = resp.call_id;
});
};
const endListener = () => {
console.info('pushVideoFile,video play end');
window.video.removeEventListener('ended', endListener);
hangup();
};
// maybe did't finish the video,so that we has listener already,remove it
window.video.removeEventListener('ended', endListener);
console.info('pushVideoFile,add canplay Event Listener', canPlayListener);
window.video.addEventListener('canplay', canPlayListener);
// hangup the call when video finished
console.info('pushVideoFile,add ended Event Listener', endListener);
window.video.addEventListener('ended', endListener);
window.video.autoplay = false;
window.video.src = url;
}
};
/**
* 视频转发
* share a exist call to another device
* @param record
* @param stop
* @returns
*/
const forwardVideoCall = (record, stop) => {
console.info('try forwardVideoCall,call_id=', call_id);
if (!call_id) {
console.warn('no call exits,can not forward');
ElMessage.warning('no call exits');
return undefined;
}
return window.lemon.call
.forwardVideoCall({
basedata_id: record?.basedata_id,
call_id,
action: stop ? 1 : 0,
})
?.then((resp) => {
if (resp.result === 0) {
console.log('forwardVideoCall request sucess');
} else {
ElMessage.error("视频转发失败");
}
})
.catch((err) => {
console.error('forwardVideoCall error,', err);
});
};
const getEmitter = () => {
return emitter;
};
// call sdk unInit
const unInit = () => {
call_id = undefined;
if (hangup_event_cb_id) {
window.lemon.call.removeHangupEvt(hangup_event_cb_id);
hangup_event_cb_id = undefined;
}
if (force_hangup_event_cb_id) {
window.lemon.call.removeForceHangupEvt(force_hangup_event_cb_id);
force_hangup_event_cb_id = undefined;
}
if (answer_ack_cb_id) {
window.lemon.call.removeAnswerAckEvt(answer_ack_cb_id);
answer_ack_cb_id = undefined;
}
if (incoming_cb_id) {
window.lemon.call.removeIncomingEvt(incoming_cb_id);
incoming_cb_id = undefined;
}
if (floor_grant_cb_id) {
window.lemon.floor.removeGrantEvt(floor_grant_cb_id);
floor_grant_cb_id = undefined;
}
monitor_call_list.length = 0;
};
return {
makeVoiceCall,
makeVideoCall,
pureVideoCall,
registerhangupEvent,
registerReceiveCallEvent,
answerCall,
makeGroupVoiceCall,
makeGroupVideoCall,
makeBroadcastCall,
hangup,
voiceDetect,
videoDetect,
applyFloor,
releaseFloor,
setMuteCamera,
setMuteMic,
setMuteCall,
muteMemberInConference,
makeConferenceVoiceCall,
makeConferenceVideoCall,
makeCrosspatchVoiceCall,
registerCallEstablishEvent,
pushVideoFile,
forwardVideoCall,
forceHangupCall,
getMonitorCallList,
getEmitter,
forceApplySpeak,
registerFloorGrantEvent,
registerForceHangupEvent,
unInit,
};
}

View File

@ -0,0 +1,37 @@
// import { h } from 'vue';
// import { Notification } from '@arco-design/web-vue';
// import { IconClose } from '@arco-design/web-vue/es/icon';
// import Content from '@/views/webPuc/callingNotification/components/content.vue';
// import Footer from '@/views/webPuc/callingNotification/components/footer.vue';
// import { formatShowNameFin } from './format-show-name';
// export default function handleCallingNotification(propsObj) {
// const { callInfo, text } = propsObj;
// const { calling, answer = 'answer', hangUp = 'hang up' } = text;
// Notification.info({
// id: callInfo.call_id,
// showIcon: false,
// position: 'bottomLeft',
// closable: true,
// closeIconElement: () => {
// return h(IconClose);
// },
// title: () =>
// h(Content, {
// callInfo,
// calling,
// getName: formatShowNameFin(
// callInfo.caller_alias,
// callInfo.caller_number
// ),
// }),
// content: () =>
// h(Footer, {
// callInfo,
// answer,
// hangUp,
// }),
// duration: 0,
// style: { width: '260px' },
// });
// }

View File

@ -18,17 +18,18 @@
<el-option v-for="item in dictItemList" :key="item.dm" :label="item.zdmc" :value="item.dm" />
</el-select>
</template>
</Search>
</div> -->
</Search>
</div> -->
<div style="background-color: #fff;color: black;padding: 15px;overflow: auto;" :style="{ height: tabHeight + 'px' }"
ref="tableBox">
<div style="border-bottom: 1px #ccc solid;padding-bottom: 30px;">
<h1 class="headline">{{ nd }}年度西藏公安战术研判报告</h1>
<div style="display: flex;align-items: center;justify-content: space-between; color: red;margin-top: 30px;padding: 0 30px;font-size: 18px;font-weight: 700;">
<div>{{ deptId.name }}</div>
<div>{{ deptId?.ord }}</div>
<div>{{ deptId?.time }}</div>
</div>
<h1 class="headline">{{ nd }}年度林芝市公安战术研判报告</h1>
<div
style="display: flex;align-items: center;justify-content: space-between; color: red;margin-top: 30px;padding: 0 30px;font-size: 18px;font-weight: 700;">
<div>{{ deptId.name }}</div>
<div>{{ deptId?.ord }}</div>
<div>{{ deptId?.time }}</div>
</div>
</div>
<p>为全面客观准确掌握全区公安机关的执法状况自治区
@ -72,7 +73,7 @@
</span>
</span>
</p>
<Histogram title="地市分布" :xAxisData="dataList.dyTj.xAxisData" :seriesData="dataList.dyTj.seriesData" />
<Histogram title="地市分布" :xAxisData="dataList.dyTj.xAxisData" :seriesData="dataList.dyTj.seriesData" />
<h2>1.1.4时间维度</h2>
<p>
我们将所有警情按照月份划分进行统计发现每月警情分布
@ -103,10 +104,13 @@
:chartData="dataList.CljgfTj" :innerRadius="0" :outerRadius="150" :padAngle="2" />
<h2>1.2.2效率维度</h2>
<p>从处警效率来看{{ sortingRatioValue.Czlfx[1]?.name }}处警的占到{{ sortingRatioValue.Czlfx[0]?.ratio
}}表明我区公安机关在接警之后能够在第一时间处警
}}表明我区公安机关在接警之后能够在第一时间处警
</p>
<MaleNightingalePicture :title="{ text: '效率维度', left: 'center' }" style="height: 550px;"
:chartData="dataList.withinTj" :innerRadius="0" :outerRadius="150" :padAngle="0" />
<h2>2.总结分析</h2>
<p style="min-height: 100px;" v-loading="loading">{{ textContent }} </p>
</div>
</div>
@ -114,14 +118,12 @@
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import Search from "@/components/aboutTable/Search.vue";
import MaleNightingalePicture from './components/maleNightingalePicture.vue'
import Histogram from './components/histogram.vue'
import { timeValidate } from '@/utils/tools.js'
import { getItem, setItem } from '@/utils/storage'
import { fxbgDywdtj, getDictItem, fxbgJqlxtj, fxbgJqlytj, fxbgYdfx, fxbgXsfx, fxgbCljgf, fxgbCzlfx, fxbgTj } from '@/api/semanticAnalysis'
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { completions } from '@/api/semanticAnalysis'
import { reactive, ref, onMounted, getCurrentInstance, nextTick, computed, watch } from "vue";
const props = defineProps({
// 数据
@ -130,6 +132,7 @@ const props = defineProps({
default: null
}
})
const loading = ref(false);
const { proxy } = getCurrentInstance();
const { D_GS_XS_LX } = proxy.$dict("D_GS_XS_LX"); //获取字典数据
const dictItemList = ref([])
@ -214,7 +217,7 @@ const getfxbgDywdtj = () => {
let params = {
...pageData.parameter,
}
fxbgDywdtj(params).then(res => {
return fxbgDywdtj(params).then(res => {
dataList.dyTj.xAxisData = res.map(it => it.ssbm)
dataList.dyTj.seriesData = [];
for (let i = 0; i < res.length; i++) {
@ -242,7 +245,7 @@ const getfxbgJqlxtj = () => {
bjlbList: dictItemList.value.map(item => item.dm).join(',')
}
}
fxbgJqlxtj(params).then(res => {
return fxbgJqlxtj(params).then(res => {
sortingRatioValue.Jqlx = sortingRatio(res)
dataList.jqlxTj = res.map(item => {
return {
@ -257,7 +260,7 @@ const getfxbgJqlytj = () => {
let params = {
...pageData.parameter,
}
fxbgJqlytj(params).then(res => {
return fxbgJqlytj(params).then(res => {
sortingRatioValue.Lyfx = sortingRatio(res)
dataList.jqlyTj = res.map(item => {
return {
@ -273,7 +276,7 @@ const getfxbgYdfx = () => {
let params = {
...pageData.parameter,
}
fxbgYdfx(params).then(res => {
return fxbgYdfx(params).then(res => {
sortingRatioValue.Ydfx = sortingRatio(res)
dataList.ydTj = res.map(item => {
return {
@ -289,7 +292,7 @@ const getfxgbCljgf = () => {
...pageData.parameter,
}
fxgbCljgf(params).then(res => {
return fxgbCljgf(params).then(res => {
sortingRatioValue.Cljgf = sortingRatio(res)
dataList.CljgfTj = res.map(item => {
return {
@ -304,7 +307,7 @@ const getfxgbCzlfx = () => {
let params = {
...pageData.parameter,
}
fxgbCzlfx(params).then(res => {
return fxgbCzlfx(params).then(res => {
dataList.withinTj = [{
name: "超时分流(超过24小时)",
value: res.within24h ? res.within24h : 0
@ -320,7 +323,7 @@ const getfxbgTj = () => {
let params = {
...pageData.parameter,
}
fxbgTj(params).then(res => {
return fxbgTj(params).then(res => {
console.log(res, "xxx");
dataList.XsfxTj = res
})
@ -360,41 +363,46 @@ const Time = () => {
deptId.value.name = devt[0].deptName
nd.value = timeValidate('', 'yd')
deptId.value.time = timeValidate('', 'ydm')
deptId.value.ord=timeValidate('', 'mm')
deptId.value.ord = timeValidate('', 'mm')
TimeValue.value.startTime = `${year}-${month}-${day}`
TimeValue.value.endTime = `${endYear}-${endMonth}-${endDay}`
}
Time()
const funAll = () => {
getfxbgDywdtj()
getfxbgJqlxtj()
getfxbgJqlytj()
getfxgbCljgf()
getfxbgYdfx()
getfxgbCzlfx()
getfxbgTj()
// 使用Promise.all确保所有数据获取函数执行完成
Promise.all([
getfxbgDywdtj(),
getfxbgJqlxtj(),
getfxbgJqlytj(),
getfxgbCljgf(),
getfxbgYdfx(),
getfxgbCzlfx(),
getfxbgTj()
]).then(() => {
extractTextContent()
})
}
const getDictItemList = () => {
const promes = {
startTime: props.search.startTime ,
endTime: props.search.endTime,
startTime: props.search.startTime,
endTime: props.search.endTime,
}
if (props.search.lx) {
const bjlbLists = props.search.lx ? props.search.lx.join(',') : ""
pageData.parameter = { bjlbList: bjlbLists, ...promes }
const bjlbLists = props.search.lx ? props.search.lx.join(',') : ""
pageData.parameter = { bjlbList: bjlbLists, ...promes }
funAll()
} else {
const promesing = {
dictCode: "00000000"
}
dictCode: "00000000"
}
getDictItem(promesing).then(res => {
const bjlbLists = res.map(item=>item.dm).join(',')?res.map(item=>item.dm).join(','):""
pageData.parameter = { bjlbList: bjlbLists, ...promes }
funAll()
})
}
const bjlbLists = res.map(item => item.dm).join(',') ? res.map(item => item.dm).join(',') : ""
pageData.parameter = { bjlbList: bjlbLists, ...promes }
funAll()
})
}
}
@ -404,6 +412,49 @@ watch(() => dictItemList.value, (val) => {
}, { deep: true })
getDictItemList()
const tableBox = ref(null);
const textContent = ref('')
// 获取p标签的所有文字内容去除所有<>包裹的内容
const extractTextContent = () => {
loading.value = true
// 获取当前组件的HTML内容
const componentHtml = tableBox.value ? tableBox.value.innerHTML : '';
// 存储提取的文本内容
const extractedTexts = [];
// 提取p标签的文本内容
const pRegex = /<p[^>]*>(.*?)<\/p>/gs;
let pMatch;
while ((pMatch = pRegex.exec(componentHtml)) !== null) {
let pContent = pMatch[1];
// 去除所有<>包裹的内容
pContent = pContent.replace(/<[^>]*>/g, '');
// 去除HTML注释
pContent = pContent.replace(/<!--[\s\S]*?-->/g, '');
// 清理文本,去除多余空白字符
const cleanText = pContent.replace(/\s+/g, ' ').trim();
if (cleanText) {
extractedTexts.push(cleanText);
}
}
// 合并为一个字符串
const result = extractedTexts.join(' ');
console.log('提取的文本内容:', result);
completions({
model: "deepseek-32b",
prompt: `# 角色定位\n你是一名资深警务人员尤其擅长对警情、案件、线索等非结构化文本数据进行阅读理解并总结各种对象之间的关联关系,对下面数据进行一个分析总结给出一个总结报告。\n${result}`,
max_tokens: 1000,
}).then(res => {
textContent.value = res.choices[0].text
}).finally(() => {
loading.value = false
})
// return result;
};
</script>

View File

@ -602,6 +602,7 @@ const tabHeightFn = () => {
::v-deep .el-table .el-table__cell {
padding: 0;
}
::v-deep .el-table th.el-table__cell>.cell {

View File

@ -37,7 +37,7 @@
<script setup>
import YpModel from '@/components/ypModel/index.vue'
import emitter from "@/utils/eventBus.js";
import { getYjxxPageList,getSsyjpzMxgzxl,mxglYjxqSelectList } from "@/api/model";
import { getYjxxPageList,getSsyjpzMxgzxl,mxglJqxqGetPageList } from "@/api/model";
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
@ -67,7 +67,7 @@ const SaveReport = () => {
const opneModel = (row) => {
showModel.value = true
textContent.value = ''
mxglYjxqSelectList({
mxglJqxqGetPageList({
yjid: row.id,
}).then((res) => {
let str = {
@ -75,13 +75,13 @@ const opneModel = (row) => {
prompt: `# 角色定位\n你是一名资深警务人员尤其擅长对警情、案件、线索等非结构化文本数据进行阅读理解并从中提取各种对象特征信息进行结构化并总结各种对象之间的关联关系。\n`,
max_tokens: 1000,
}
res.forEach(item => {
const lx = props.dict.D_BZ_YJLX.find(items => {
res.forEach(item => {
const lx = props.dict.D_BZ_JQLY.find(items => {
return items.value == item.yjlx
}).zdmc
str.prompt+=`预警名称:${item.yjBt},警人姓名:${item.yjRyxm},身份证号:${item.yjRysfzh},车牌号:${item.yjClcph},警地址:${item.yjDz},警类型:${lx},预警内容:${item.yjnr},预警时间:${item.yjsj}\n`
str.prompt+=`警情内容:${item.bjnr},警人姓名:${item.bjrmc},警地址:${item.bjdz},警类型:${lx},警时间:${item.bjsj}\n`
})
str.prompt += `根据以上警信息,总结出一个解决方案`
str.prompt += `根据以上警信息,总结出一个解决方案`
let jsonMatch
completions(str).then(reslve => {
jsonMatch = reslve.choices[0].text
@ -90,7 +90,7 @@ const opneModel = (row) => {
time: timeValidate()
}) + fbtool(`同类事件发生${res.length}次以上预警`)
res.forEach((item,index) => {
const lx = props.dict.D_BZ_YJLX.find((items) => {
const lx = props.dict.D_BZ_JQLY.find((items) => {
return items.value == item.yjlx
}).zdmc
textContent.value +=Subheading(`${index+1}.警情内容`)+textStyle(`预警名称:${item.yjBt},预警人员姓名:${item.yjRyxm},身份证号:${item.yjRysfzh},车牌号:${item.yjClcph},预警地址:${item.yjDz},预警类型:${lx},预警内容:${item.yjnr},预警时间:${item.yjsj}\n`)

View File

@ -30,7 +30,8 @@ const props = defineProps({
item: {
type: Object,
default: () => {},
}
},
})
const { proxy } = getCurrentInstance();
const { D_BB_AJLB,D_BZ_WPLX,D_BZ_RYBQ} = proxy.$dict("D_BB_AJLB","D_BZ_WPLX","D_BZ_RYBQ")

View File

@ -1,8 +1,9 @@
<template>
<div>
<YpHome v-if="showModel == '研判首页'"></YpHome>
<List v-if="showModel == '四色预警规则' || showModel == '预警规则'" :item="itemData"></List>
<YjDetail v-if="showModel == '预警列表'" :item="itemData" :dict="{ D_BZ_TPYJLX,D_BZ_YJLX }"></YjDetail>
<List v-if="showModel == '四色预警规则' || showModel == '预警规则'" :item="itemData" :dict="{ D_BZ_TPYJLX}"></List>
<YjDetail v-if="showModel == '预警列表'" :item="itemData" :dict="{ D_BZ_TPYJLX,D_BZ_YJLX,D_BZ_JQLY }"></YjDetail>
<WarningList v-if="showModel == '预警详情'" :item="itemData" :dict="{ D_BZ_YJLX }"/>
</div>
</template>
@ -14,7 +15,7 @@ import WarningList from "./components/AddModel/warningList.vue"
const { proxy } = getCurrentInstance();
import emitter from "@/utils/eventBus.js";
import { onMounted, ref, getCurrentInstance } from "vue";
const { D_BZ_TPYJLX,D_BZ_YJLX } = proxy.$dict("D_BZ_TPYJLX","D_BZ_YJLX")
const { D_BZ_TPYJLX,D_BZ_YJLX ,D_BZ_JQLY} = proxy.$dict("D_BZ_TPYJLX","D_BZ_YJLX","D_BZ_JQLY")
const showModel = ref('研判首页')
const itemData = ref({})

View File

@ -11,18 +11,18 @@
<div class="content_icon flex align-center">
<div class="icon_img"><img src="@/assets/images/ly-person-icon.png" alt="" srcset=""></div>
<div class="flex align-space-around dir-column">
<div class="publisher">发布者{{ listQuery.ssbm }}{{ listQuery.fbrxm }}</div>
<div>发布于{{ listQuery.fbsj }}</div>
<div class="publisher">发布者{{ listQuery.xtCjbmmc }}{{ listQuery.xssbr }}</div>
<div>发布于{{ listQuery.czsj }}</div>
</div>
</div>
<p class="content_text">{{ listQuery.xsNr }} </p>
<p class="content_text">{{ listQuery.qbnr }} </p>
<div class="itemXs_Xs flex just-between align-center">
<div class=" flex just-between align-center">
<!-- <div class=" flex just-between align-center">
<el-icon class="icon">
<Histogram />
</el-icon>
&nbsp;{{ listQuery.rd ? listQuery.rd : 0 }}
</div>
</div> -->
<div class=" flex just-between align-center">
<el-icon class="icon">
<ChatDotSquare />
@ -30,7 +30,7 @@
&nbsp;{{ pls }}
</div>
<div class="flex align-center">情报类型
<DictTag :tag="false" :value="listQuery.xlLx" color="#5c5c5c" :options="dict.D_GS_XS_LX" />
<DictTag :tag="false" :value="listQuery.qblx" color="#5c5c5c" :options="dict.D_GS_XS_LX" />
</div>
</div>
</div>
@ -107,6 +107,14 @@ const sendComment = () => {
cjid: listQuery.value.id,
dzs: 10
}
if(!textarea2.value){
ElMessage({
message: '请输入评论内容',
type: 'warning',
plain: true,
})
return
}
qcckPost(prmes, '/mosty-gsxt/gsxt/cjpj/add').then((res) => {
textarea2.value = ''; // 清空评论内容
cjpjSelectPage()

View File

@ -7,18 +7,19 @@
<div class="itemXs_time flex ">
<div> {{ item.pldd }}</div>
<div>{{ item.plsj }}</div>
<div><span @click="openReply(index)" class="hf">回复</span>
&nbsp;&nbsp;
<div>
<!-- <span @click="openReply(index)" class="hf">回复</span>
&nbsp;&nbsp; -->
<span class="del" @click="delComment(item)"
v-show="userInfo==item.plrsfzh"
>删除</span></div>
<div @click="showReply(item)" class="ck">查看回复</div>
<div @click="handleLike(item)" class="ck">点赞{{dzs }}</div>
<!-- <div @click="showReply(item)" class="ck">查看回复</div> -->
<!-- <div @click="handleLike(item)" class="ck">点赞{{dzs }}</div> -->
</div>
<div class="pubContent flex" v-if="showInput" style="align-items: flex-end">
<!-- <div class="pubContent flex" v-if="showInput" style="align-items: flex-end">
<el-input v-model="textarea2" style="flex: 1;margin-right: 10px;" type="textarea" placeholder="请输入内容" /><el-button
type="primary" @click="sendComment(item)">回复</el-button>
</div>
</div> -->
<div v-if="show">
<ReplyList :replyId="item" ref="replyList" :userInfo="userInfo"/>
</div>

View File

@ -36,7 +36,6 @@ import ExtractionText from "@/components/ExtractionText/index.vue";
import { lzJcjPjdbSelectPage, tbGsxtBqglSelect, yyfxAdd, completions } from '@/api/semanticAnalysis'
import { qcckGet } from "@/api/qcckApi.js";
import { getCurrentInstance } from 'vue'
import { ParsingText } from '@/api/qcckApi'
import emitter from "@/utils/eventBus.js";
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'

View File

@ -70,12 +70,12 @@ const dialogForm = ref(false); //弹窗
const formData = reactive([
{ label: "标签名称", prop: "bqMc", type: "input" },
{ label: "标签代码", prop: "bqDm", type: "input" },
{
label: "标签等级",
prop: "bqDj",
type: "select",
options: props.dic.D_GS_BQ_DJ
},
// {
// label: "标签等级",
// prop: "bqDj",
// type: "select",
// options: props.dic.D_GS_BQ_DJ
// },
{
label: "标签颜色",
prop: "bqYs",
@ -89,9 +89,9 @@ const formData = reactive([
const rules = reactive({
bqMc: [{ required: true, message: "请输入标签名称", trigger: "blur" }],
bqDm: [{ required: true, message: "请输入标签代码", trigger: "blur" }],
bqDj: [
{ required: true, message: "请选择标签等级", trigger: ["blur", "change"] }
],
// bqDj: [
// { required: true, message: "请选择标签等级", trigger: ["blur", "change"] }
// ],
bqYs: [
{ required: true, message: "请选择标签颜色", trigger: ["blur", "change"] }
],

View File

@ -71,7 +71,7 @@ const type = ref('标签大类')
const show = ref(false)
const searchConfiger = ref([
{ label: "标签名称",prop:'bqMc',placeholder: "请输入标签名称", showType: "input"},
{ label: "标签等级",prop:'bqDj' ,placeholder: "请选择标签等级", showType: "select",options:D_GS_BQ_DJ },
// { label: "标签等级",prop:'bqDj' ,placeholder: "请选择标签等级", showType: "select",options:D_GS_BQ_DJ },
{ label: "标签颜色",prop:'bqYs' ,placeholder: "请选择标签颜色", showType: "select",options:D_GS_SSYJ },
]);
const queryFrom = ref({});
@ -92,7 +92,7 @@ const pageData = reactive({
tableColumn: [
{ label: "标签名称", prop: "bqMc" },
{ label: "标签代码", prop: "bqDm" },
{ label: "标签等级", prop: "bqDj",showSolt:true},
// { label: "标签等级", prop: "bqDj",showSolt:true},
{ label: "标签颜色", prop: "bqYs",showSolt:true},
{ label: "标签说明", prop: "bqSm"},
]

View File

@ -39,7 +39,8 @@ const dialogForm = ref(false); //弹窗
const formData = reactive([
{ label: "标签名称", prop: "bqMc", type: "input" },
{ label: "标签代码", prop: "bqDm", type: "input" },
{ label: "标签等级", prop: "bqDj", type: "select", options: props.dic.D_GS_BQ_DJ },
// 领导要求取消
// { label: "标签等级", prop: "bqDj", type: "select", options: props.dic.D_GS_BQ_DJ },
{ label: "标签颜色", prop: "bqYs", type: "select", options: props.dic.D_GS_SSYJ },
{ label: "标签分值", prop: "bqFz", type: "number" ,max:100},
{ label: "标签说明", prop: "bqSm", type: "textarea",width: '100%' },
@ -48,7 +49,7 @@ const formData = reactive([
const rules = reactive({
bqMc: [{ required: true, message: "请输入标签名称", trigger: "blur" }],
bqDm: [{ required: true, message: "请输入标签代码", trigger: "blur" }],
bqDj: [{ required: true, message: "请选择标签等级", trigger: ['blur','change'] }],
// bqDj: [{ required: true, message: "请选择标签等级", trigger: ['blur','change'] }],
bqYs: [{ required: true, message: "请选择标签颜色", trigger: ['blur','change'] }],
bqFz: [{ required: true, message: "请输入标签分值", trigger: ['blur','change'] }],
});

View File

@ -70,7 +70,7 @@ const type = ref('标签大类')
const show = ref(false)
const searchConfiger = ref([
{ label: "标签名称",prop:'bqMc',placeholder: "请输入标签名称", showType: "input"},
{ label: "标签等级",prop:'bqDj' ,placeholder: "请选择标签等级", showType: "select",options:D_GS_BQ_DJ },
// { label: "标签等级",prop:'bqDj' ,placeholder: "请选择标签等级", showType: "select",options:D_GS_BQ_DJ },
{ label: "标签颜色",prop:'bqYs' ,placeholder: "请选择标签颜色", showType: "select",options:D_GS_SSYJ },
]);
const queryFrom = ref({});
@ -91,7 +91,7 @@ const pageData = reactive({
tableColumn: [
{ label: "标签名称", prop: "bqMc" },
{ label: "标签代码", prop: "bqDm" },
{ label: "标签等级", prop: "bqDj",showSolt:true},
// { label: "标签等级", prop: "bqDj",showSolt:true},
{ label: "标签颜色", prop: "bqYs",showSolt:true},
{ label: "标签说明", prop: "bqSm"},
]

View File

@ -165,12 +165,12 @@ const dialogForm = ref(false); //弹窗
const formData = reactive([
{ label: "组合标签名称", prop: "bqMc", type: "input" },
{ label: "组合标签代码", prop: "bqDm", type: "input" },
{
label: "标签等级",
prop: "bqDj",
type: "select",
options: props.dic.D_GS_BQ_DJ
},
// {
// label: "标签等级",
// prop: "bqDj",
// type: "select",
// options: props.dic.D_GS_BQ_DJ
// },
{
label: "标签颜色",
prop: "bqYs",

View File

@ -74,7 +74,7 @@ const searchBox = ref(); //搜索框
const searchConfiger = ref(
[
{ label: "组合标签名称", prop: 'bqMc', placeholder: "请输入组合标签名称", showType: "input"},
{ label: "组合标签标签等级", prop: 'bqDj', placeholder: "请选择组合标签标签等级", showType: "select",options: D_GS_BQ_DJ },
// { label: "组合标签标签等级", prop: 'bqDj', placeholder: "请选择组合标签标签等级", showType: "select",options: D_GS_BQ_DJ },
{ label: "组合标签颜色", prop: 'bqYs', placeholder: "请选择组合标签标签颜色", showType: "select",options: D_GS_SSYJ },
]);
const queryFrom = ref({});
@ -95,7 +95,7 @@ const pageData = reactive({
tableColumn: [
{ label: "组合标签名称", prop: "bqMc" },
{ label: "标签代码", prop: "bqDm" },
{ label: "组合标签等级", prop: "bqDj",showSolt:true },
// { label: "组合标签等级", prop: "bqDj",showSolt:true },
{ label: "组合标签颜色", prop: "bqYs",showSolt:true },
{ label: "组合标签分值", prop: "bqFz"},
{ label: "组合标签说明", prop: "bqSm",showOverflowTooltip:true },

View File

@ -13,7 +13,7 @@ onMounted(() => {
});
const initCharts = (data) => {
vehicleChart = echarts.init(echart.value)
const colors =['#ff1818', '#0066ff', '#ff9900', '#00cc66']
const colors = ['#ff1818', '#0066ff', '#ff9900', '#00cc66']
const countData = [
{
value: 0,
@ -45,10 +45,10 @@ const initCharts = (data) => {
},
];
data.forEach(item => {
if(item.yj_jb == '10') countData[0].value = item.count;
if(item.yj_jb == '20') countData[1].value = item.count;
if(item.yj_jb == '30') countData[2].value = item.count;
if(item.yj_jb == '40') countData[3].value = item.count;
if (item.yj_jb == '10') countData[0].value = item.count;
if (item.yj_jb == '20') countData[1].value = item.count;
if (item.yj_jb == '30') countData[2].value = item.count;
if (item.yj_jb == '40') countData[3].value = item.count;
});
vehicleChart.setOption(createChartOption(countData, colors))
}
@ -60,8 +60,9 @@ const createChartOption = (data, colors) => {
},
legend: {
orient: 'vertical',
left: '60%',
left: '53%',
top: 'center',
itemGap: 40,
textStyle: {
color: '#fff',
rich: {
@ -69,33 +70,42 @@ const createChartOption = (data, colors) => {
color: '#fff'
},
percentage: {
padding: [0, 0, 0, 10]
padding: [0, 0, 0, 0]
},
red: {
color: colors[0]
color: colors[0],
padding: [2, 0, 2, 0], // 增加上下边距
// lineHeight: 25 // 增加行高
},
orange: {
color: colors[2]
color: colors[2],
padding: [2, 0, 2, 0],
// lineHeight: 25
},
yellow: {
color: colors[3]
color: colors[3],
padding: [2, 0, 2, 0],
// lineHeight: 25
},
blue: {
color: colors[1]
color: colors[1],
padding: [2, 0, 2, 0],
// lineHeight: 25
},
}
},
formatter: (name) => {
const item = data.find(d => d.name === name);
let percentage = ((item.value / total) * 100).toFixed(2);
return `${name} ${item.value} {${item.colorType}|(${percentage}%)}`
}
formatter: (name) => {
const item = data.find(d => d.name === name);
let percentage = ((item.value / total) * 100).toFixed(2);
return `${name} ${item.value} {${item.colorType}|(${percentage}%)}`
}
},
series: [
{
type: 'pie',
radius: ['55%', '70%'],
center: ['28%', '50%'],
center: ['25%', '50%'],
data: data.map(item => ({
...item,
itemStyle: {
@ -116,8 +126,8 @@ const createChartOption = (data, colors) => {
},
{
type: 'pie',
radius: ['65%', '85%'],
center: ['28%', '50%'],
radius: ['35%', '50%'],
center: ['25%', '50%'],
data: data.map(item => ({
...item,
itemStyle: {
@ -145,7 +155,7 @@ const handleResize = () => {
vehicleChart?.resize()
}
defineExpose({initCharts})
defineExpose({ initCharts })
</script>
<style lang='scss' scoped>

View File

@ -79,7 +79,8 @@ const title = ref('')
onMounted(() => {
emitter.on("openFkDialog", (val) => {
showDialog.value = true;
listQuery.value = {yjid:val.id}
listQuery.value = { yjid: val.id }
title.value = val.type;
if(val.type == '查看反馈'){
qcckGet({}, "/mosty-gsxt/tbYjxx/getInfo/"+val.id).then((res) => {
@ -108,13 +109,16 @@ const handleUserSelected = (val) => {
listQuery.value.czzrmjsfzh = val[0].inDustRialId
break;
}
}
const submitForm = () =>{
elform.value.submit((val)=>{
loading.value = true;
qcckPost(val, "/mosty-gsxt/tbYjxx/yjfk").then(() => {
loading.value = true;
const prome = {
...listQuery.value,
}
qcckPost(prome, "/mosty-gsxt/tbYjxx/yjfk").then(() => {
loading.value = false;
proxy.$message({ type: "success", message: "反馈成功" });
emit('change')
@ -122,7 +126,6 @@ const submitForm = () =>{
}).catch(() => {
loading.value = false;
})
})
}
@ -139,4 +142,4 @@ const close = () => {
overflow: hidden;
overflow-y: auto;
}
</style>
</style>

View File

@ -77,83 +77,18 @@ function showOnMap() {
ElMessage({ message: '暂无轨迹数据', type: 'warning' });
return;
}
for (let i = 0; i < 2; i++) {
for (let i = 0; i < mapData.value.length; i++) {
let coords = mapData.value[i].list.map(item => {
return [item.jd, item.wd]
})
// const coords =[ [
// [
// 94.354613,
// 22.658568
// ],
// [
// 94.354613,
// 23.658568
// ],
// [
// 94.354613,
// 24.658568
// ],
// [
// 94.354613,
// 25.658568
// ],
// [
// 94.354613,
// 26.658568
// ],
// [
// 94.354613,
// 27.658568
// ],
// [
// 94.354613,
// 28.658568
// ],
// [
// 94.354613,
// 29.658568
// ]
// ],[
// [
// 89.354613,
// 22.658568
// ],
// [
// 90.354613,
// 23.658568
// ],
// [
// 91.354613,
// 24.658568
// ],
// [
// 92.354613,
// 25.658568
// ],
// [
// 93.354613,
// 26.658568
// ],
// [
// 94.354613,
// 27.658568
// ],
// [
// 95.354613,
// 28.658568
// ],
// [
// 96.354613,
// 29.658568
// ]
// ]]
emitter.emit('drawLineAnimation', {
type: "solid",
coords: coords,
isclear: true,
flag: "yjLine"
flag: "yjLine"
})
}
// const coords = mapData.value.map(item => {

View File

@ -31,7 +31,7 @@
</div>
<!-- 表格 -->
<div class="tabBox" :style="{ height: pageData.tableHeight + 'px' }">
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick">
<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" />

View File

@ -1,59 +1,73 @@
<template>
<div class="warning-card" :style="{'border':`1px solid ${changeBG(item.yjJb)}`}" >
<div class="warning-card" :style="{ 'border': `1px solid ${changeBG(item.yjjb)}` }">
<div class="warning-image flex">
<!-- -->
<template v-if="!item.yjTp || item.yjTp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
<template v-if="!item.yjtp || item.yjtp.includes('baidu')">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjlb == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</template>
<el-image v-else style="width: 65px; height: 70px" :src="item.yjTp" :preview-src-list="[item.yjTp]" show-progress>
<el-image preview-teleported v-else @click.stop style="width: 65px; height: 70px" :src="item.yjtp" :preview-src-list="[item.yjtp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjlb == 2" />
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
</div>
</template>
</el-image>
<div class="ml10 warning-info">
<div class="flex just-between align-center">
<div class="flex align-center mt4" v-if="item.yjLx == 2">
<span>{{ item.yjClcph }}</span>
<div class="flex align-center mt4" v-if="item.yjlb == 2">
<span>{{ item.cph }}</span>
</div>
<div class="flex align-center mt4" v-else>
<span>{{ item.yjRyxm }}</span>
<span>{{ item.ryxm }}</span>
<span class="gapline mr10 ml10"></span>
<span>{{ IdCard(item.yjRysfzh, 2) }}</span>
<span>{{ IdCard(item.rysfzh, 2) }}</span>
<span class="gapline mr10 ml10"></span>
<span>{{ IdCard(item.yjRysfzh, 3) }}</span>
<span>{{ IdCard(item.rysfzh, 3) }}</span>
</div>
<span class="tag" v-if="item.yjbqmc" :style="{'background':`${changeBG(item.yjJb)}`}">{{ item.yjbqmc }}</span>
<span class="tag" v-if="item.yjbq" :style="{ 'background': `${changeBG(item.yjjb)}` }">{{ item.yjbq }}</span>
</div>
<div v-if="item.yjLx == 2" class="flex">车牌类型
<DictTag :tag="false" :value="item.yjHplx" color="#fff" :options="dict.D_BZ_HPZL" />
<div v-if="item.yjlb == 2" class="flex">车牌类型
<DictTag :tag="false" :value="item.hplx" color="#fff" :options="dict.D_BZ_HPZL" />
</div>
<div class="mt4" v-else>身份证{{ item.yjRysfzh }}</div>
<div class="mt4 two_text_detail">预警时间{{ item.yjSj }}</div>
<div class="mt4" v-else>身份证{{ item.rysfzh }}</div>
<div class="mt4 two_text_detail">预警时间{{ item.yjsj }}</div>
</div>
</div>
<div class="warning-info warning-boder pb5">
<div class="mt4 two_text_detail">预警内容{{ item.yjNr }}</div>
<div class="warning-info warning-boder pb5" v-if="item.yjlx == '01'">
<div class="mt4 two_text_detail">预警内容{{ item.yjnr }}</div>
</div>
<div class="warning-info pt5 pb5 warning-boder">
<div class="mt4 two_text_detail">处置结果{{ item.yjNr }}</div>
<div class="warning-info pt5 pb5 warning-boder" v-if="item.yjlx == '01'">
<div class="mt4 two_text_detail">处置结果{{ item.yjnr }}</div>
</div>
<div class="warning-info pt5 ">
<div class="warning-info pt5 " v-if="item.yjlx == '01'">
<div class="two_text_detail flex lh25"><img src="@/assets/images/ddtb.png" width="20" height="25" alt=""
srcset="">{{
item.yjNr }}</div>
item.yjnr }}</div>
</div>
<div class="mt4 two_text_detail" v-if="buttonBox">
<el-button type="primary" @click="pushAssess(item)">全息档案</el-button>
<el-button color="#ef7762" @click="showDetail(item)" style="color: #fff;">转合成</el-button>
<el-button type="warning">转基管</el-button>
<el-button type="danger">转会商</el-button>
<el-button type="success" @click="showFeedback(item, '签收')" v-if="item.czzt == '01'">签收</el-button>
<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>
<el-button type="success" @click="plotThetrajectory(item.rysfzh)">轨迹上图</el-button>
</div>
<!-- props.item.czzt == '03'" -->
</div>
<HolographicArchive v-model="assessShow" :dataList="dataList" />
</template>
<script setup>
import { IdCard } from '@/utils/validate.js'
import { reactive, ref } from "vue";
import { reactive, ref, getCurrentInstance } from "vue";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import HolographicArchive from './holographicArchive.vue'
const { proxy } = getCurrentInstance();
const props = defineProps({
item: {
type: Object,
@ -61,8 +75,12 @@ const props = defineProps({
}, dict: {
tupe: Object,
default: {}
}, buttonBox: {
type: Boolean,
default: false
}
});
const emit = defineEmits(["plotThetrajectory", "showDetail", 'showFeedback']);
const changeBG = (str) => {
switch (str) {
@ -72,9 +90,44 @@ const changeBG = (str) => {
return "orange";
case "30":
return "#b5b522";
default: return "blue";
default:
return "blue";
}
};
// 轨迹上图
const plotThetrajectory = (val) => {
emit('plotThetrajectory', val);
}
// 查看反馈
const showFeedback = (val, type) => {
switch (type) {
case '签收':
proxy.$confirm("是否确定要签收", "警告", { type: "warning" }).then(() => {
qcckPost({ id: val.id }, "/mosty-gsxt/tbYjxx/yjqs").then(() => {
val.czzt = '02'
proxy.$message({ type: "success", message: "签收成功" });
});
})
break;
case '反馈':
case '查看反馈':
const data = {
...val,
type: type,
}
emit('showFeedback', data);
break;
}
}
const showDetail = (item) => {
emit('showDetail', item);
}
const assessShow = ref(false)
const dataList = ref()
const pushAssess = (val) => {
assessShow.value = true;
dataList.value = val;
}
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,431 @@
<!--全息档案展示组件 -->
<template>
<el-dialog v-model="modelValue" :title="title" :width="width" @close="close" append-to-body>
<div class="archive-container">
<!-- 基本信息卡片 -->
<div class="basic-info-card">
<div class="info-header">
<!-- 头像区域 -->
<div class="avatar-section">
<el-image class="main-avatar" :src="personData.rltp || personData.qsztp" fit="cover"
:preview-src-list="[personData.rltp , personData.qsztp]" />
</div>
<!-- 基本信息 -->
<div class="basic-info">
<!-- 姓名字段单独一行 -->
<div class="info-row">
<div class="info-item">
<span class="info-label">姓名</span>
<span class="info-value">{{ personData.xm || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">身份号</span>
<span class="info-value">{{ personData.sfzhm || '未记录' }}</span>
</div>
</div>
<!-- 基本信息 - 两个字段一行 -->
<div class="info-row">
<div class="info-item">
<span class="info-label">出生日期</span>
<span class="info-value">{{ personData.csrq || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">性别</span>
<span class="info-value">{{ personData.xb || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">民族</span>
<span class="info-value">{{ personData.mz || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">婚姻状况</span>
<span class="info-value">{{ personData.hyzq || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">联系方式</span>
<span class="info-value">{{ personData.lxfs || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">户主号码</span>
<span class="info-value">{{ personData.hzhm || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">文化程度</span>
<span class="info-value">{{ personData.whcd || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">毕业情况</span>
<span class="info-value">{{ personData.byqq || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">身高</span>
<span class="info-value">{{ personData.sg || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item full-width">
<span class="info-label">人员标签</span>
<span class="info-value">{{ personData.rybq || '未记录' }}</span>
</div>
</div>
</div>
</div>
<!-- 详细信息 -->
<div class="detail-info">
<!-- 详细信息 - 两个字段一行 -->
<div class="info-row">
<div class="info-item">
<span class="info-label">人员国籍</span>
<span class="info-value">{{ personData.rygj || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">人员地区</span>
<span class="info-value">{{ personData.rydq || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">户籍城市</span>
<span class="info-value">{{ personData.hjcs || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">户籍籍贯</span>
<span class="info-value">{{ personData.hjjg || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">工作单位</span>
<span class="info-value">{{ personData.gzdw || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">职业信息</span>
<span class="info-value">{{ personData.zyxx || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">入境时间</span>
<span class="info-value">{{ personData.rjsj || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">入境事由</span>
<span class="info-value">{{ personData.rjsy || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">证件类型</span>
<span class="info-value">{{ personData.qzlx || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">证件号码</span>
<span class="info-value">{{ personData.qzhm || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">证件校验</span>
<span class="info-value">{{ personData.zjxy || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">境外人员类别</span>
<span class="info-value">{{ personData.jwrylb || '未记录' }}</span>
</div>
</div>
<!-- <div class="info-row">
<div class="info-item">
<span class="info-label">毕业情况</span>
<span class="info-value">{{ personData.byqq || '未记录' }}</span>
</div>
<div class="info-item">
<span class="info-label">统战序列备注</span>
<span class="info-value">{{ personData.trzxlbz || '未记录' }}</span>
</div>
</div> -->
<!-- <div class="info-row">
<div class="info-item">
<span class="info-label">户主号码</span>
<span class="info-value">{{ personData.hzhm || '未记录' }}</span>
</div>
</div> -->
<!-- <div class="info-row">
<div class="info-item">
<span class="info-label">起始图片</span>
<span class="info-value">{{ personData.qsztp ? '已上传' : '未记录' }}</span>
</div>
</div> -->
<!-- 户籍和居住地放在最后独占一行 -->
<div class="info-row">
<div class="info-item full-width">
<span class="info-label">户籍所在地</span>
<span class="info-value">{{ personData.hjdz || '未记录' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item full-width">
<span class="info-label">居住地</span>
<span class="info-value">{{ personData.jzdz || '未记录' }}</span>
</div>
</div>
</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">关闭</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, defineProps, defineEmits, reactive, watch } from 'vue';
import {ryxxJbxxSave} from '@/api/qxda.js'
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
title: {
type: String,
default: '全息档案'
},
width: {
type: String,
default: '50%'
},
url: {
type: String,
default: ''
},
dataList: {
type: Object,
default: () => ({})
}
});
watch(() => props.modelValue, (newVal, oldVal) => {
if (newVal) {
getryxxJbxxSave()
}
})
// 个人信息数据对象 - 使用用户提供的数据
const personData = ref({ });
// 预览图片列表
const srcList = ref([
'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg',
]);
// 定义事件
const emit = defineEmits(['update:modelValue']);
const getryxxJbxxSave = () => {
ryxxJbxxSave({ sfzhm:'540402195805123219' // props.dataList.rysfzh
}).then((res) => {
personData.value = res[0]
});
}
const close = () => {
emit('update:modelValue', false);
};
</script>
<style scoped>
/* 容器样式 */
.archive-container {
padding: 15px;
height: 50vh;
overflow: auto;
}
/* 基本信息卡片 */
.basic-info-card {
background-color: #f0f9ff;
border: 1px solid #91d5ff;
border-radius: 8px;
padding: 25px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}
/* 信息头部(头像+基础信息) */
.info-header {
display: flex;
align-items: flex-start;
gap: 40px;
margin-bottom: 0;
padding-bottom: 20px;
border-bottom: 1px solid #d6eaff;
margin-bottom: 20px;
}
/* 头像区域 */
.avatar-section {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
/* 主头像 */
.main-avatar {
width: 120px;
height: 140px;
border: 3px solid #409EFF;
border-radius: 4px;
background-color: #fff;
}
/* 辅助头像容器 */
.sub-avatars {
display: flex;
gap: 8px;
}
/* 小头像 */
.sub-avatar {
width: 50px;
height: 50px;
border: 2px solid #409EFF;
border-radius: 4px;
background-color: #fff;
}
/* 基本信息区域 */
.basic-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 12px;
}
/* 信息行 */
.info-row {
display: flex;
margin-bottom: 0;
align-items: center;
flex-wrap: wrap;
min-height: 32px;
}
/* 信息项 */
.info-item {
margin-right: 0;
margin-bottom: 0;
flex: 0 0 calc(50% - 10px);
max-width: calc(50% - 10px);
min-height: 32px;
display: flex;
align-items: center;
padding-right: 20px;
}
/* 全宽信息项(用于姓名字段和地址字段) */
.info-item.full-width {
flex: 0 0 100%;
max-width: 100%;
padding-right: 0;
}
/* 信息标签 */
.info-label {
color: #0060c8;
font-weight: bold;
font-size: 14px;
margin-right: 8px;
white-space: nowrap;
min-width: 80px;
}
/* 信息值 */
.info-value {
color: #000;
font-size: 14px;
word-break: break-all;
flex: 1;
}
/* 详细信息区域 */
.detail-info {
background-color: #fff;
border-radius: 6px;
padding: 20px;
border-left: 4px solid #409EFF;
margin-top: 0;
display: flex;
flex-direction: column;
gap: 12px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.info-header {
flex-direction: column;
align-items: center;
text-align: left;
gap: 20px;
}
.info-row {
flex-direction: column;
align-items: stretch;
min-height: auto;
margin-bottom: 0;
}
.info-item {
margin-right: 0;
margin-bottom: 0;
flex: 0 0 100%;
max-width: 100%;
min-height: 36px;
display: flex;
align-items: center;
padding-right: 0;
}
.info-label {
display: inline-block;
min-width: 80px;
}
.info-value {
flex: 1;
}
/* 全宽信息项在移动端保持全宽 */
.info-item.full-width {
flex: 0 0 100%;
max-width: 100%;
}
}
</style>

View File

@ -45,15 +45,7 @@
<div class="mt4 two_text_detail">预警时间{{ item.yjSj }}</div>
<div class="mt4 one_text_detail">预警地址{{ item.yjDz }}</div>
<div class="mt4 two_text_detail">预警内容{{ item.yjNr }}</div>
<div class="mt4 two_text_detail">
<el-button type="primary">全息档案</el-button>
<el-button color="#ef7762" style="color: #fff;">转合成</el-button>
<el-button type="warning">转基管</el-button>
<el-button type="danger">转会商</el-button>
<el-button type="success">查看反馈</el-button>
<el-button type="success">轨迹上图</el-button>
</div>
</div>
</div>
</template>

View File

@ -1,8 +1,9 @@
<template>
<DialogDragger title="预警详情" top="150px" v-model="props.show" @close="close">
<ul class="warningList" ref="gjyjList">
<li v-for="item in props.data" :key="item.id">
<YjItem :item="item" />
<li v-for="item in props.data" :key="item">
<deployControlItem :item="item" :buttonBox="true" @plotThetrajectory="plotThetrajectory"
@showFeedback="showFeedback" @showDetail="showDetail"/>
</li>
<MOSTY.Empty :show="props.data.length <= 0" :imgSize="150"></MOSTY.Empty>
</ul>
@ -10,12 +11,23 @@
<GdMap v-if="showMap" :mapKey="'home_yj_map'" :mapid="'homeYjMap'" />
</div>
</DialogDragger>
<FkDialog @change="close"/>
<Information v-model="showDialog" title="发送指令" @submit='submit' @close='closeFszl'>
<SemdFqzl ref="semdFqzlRef" :itemData="itemData" @handleClose="handleClose" identification="yj"
:tacitly="tacitly" />
</Information>
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import GdMap from "@/components/GdMap/index.vue";
import DialogDragger from "@/views/home/layout/dialogDragger.vue";
import YjItem from "@/views/home/components/yjItem.vue";
import deployControlItem from "@/views/home/components/deployControlItem.vue";
import Information from "@/views/home/model/information.vue";
import SemdFqzl from '@/components/instructionHasBeen/sendFqzl.vue'
import { tbYjxxGsgj } from '@/api/yj'
import FkDialog from "@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/components/fkDialog.vue";
import { ref, defineProps, onMounted, watch, getCurrentInstance } from "vue";
import emitter from "@/utils/eventBus.js";
const gjyjList = ref(null); //预警列表数据
@ -92,9 +104,132 @@ onMounted(() => {
})
const handleHs = ref(0)
watch(() => gjyjList.value, (val) => {
console.log(val.clientHeight);
handleHs.value = val.clientHeight + 198 + 150 + 20
}, { deep: true })
// 轨迹上图
const plotThetrajectory = (val) => {
tbYjxxGsgj({
startTime: null,
endTime: null,
yjRysfzh: val
}).then(res => {
console.log(res);
if (res && res[0].list.length > 0) {
let coords = res[0].list.map(item => {
return [item.jd, item.wd]
})
// const coords = [
// [
// 94.3695802486277983689433312974870204925537109375,
// 29.659805088901098457654370577074587345123291015625
// ],
// [
// 94.369054723455093380835023708641529083251953125,
// 29.66032233866609857386720250360667705535888671875
// ],
// [
// 94.3684916577901020673380116932094097137451171875,
// 29.660979382630298317735650925897061824798583984375
// ],
// [
// 94.3683415069466065006054122932255268096923828125,
// 29.660755708570601285600787377916276454925537109375
// ],
// [
// 94.3675662718153063224235665984451770782470703125,
// 29.659987675165101705943015986122190952301025390625
// ],
// [
// 94.366890606904092919648974202573299407958984375,
// 29.659353928438999759009675472043454647064208984375
// ],
// [
// 94.3656729217579055557507672347128391265869140625,
// 29.6582345740253998656044132076203823089599609375
// ],
// [
// 94.3646650204280064144768402911722660064697265625,
// 29.657336173164399184543071896769106388092041015625
// ],
// [
// 94.364147680070203705327003262937068939208984375,
// 29.6567231392728984928908175788819789886474609375
// ],
// [
// 94.3636436022359958997185458429157733917236328125,
// 29.65662527779360146951148635707795619964599609375
// ],
// [
// 94.362367320062702447103220038115978240966796875,
// 29.6567138191363000032652053050696849822998046875
// ],
// [
// 94.3614396063849056872641085647046566009521484375,
// 29.656713819753800720491199172101914882659912109375
// ],
// [
// 94.3603242001151016893345513381063938140869140625,
// 29.65673712009380125209645484574139118194580078125
// ],
// [
// 94.358962121621999585840967483818531036376953125,
// 29.65674177535930056137658539228141307830810546875
// ],
// [
// 94.3576684689077040957272402010858058929443359375,
// 29.65681167375640114869383978657424449920654296875
// ],
// [
// 94.3564404495050013110812869854271411895751953125,
// 29.65685827438640131958891288377344608306884765625
// ],
// [
// 94.3547512464013067301493720151484012603759765625,
// 29.656946809372101370172458700835704803466796875
// ]
// ]
emitter.emit('drawLineAnimation', {
type: "solid",
coords: coords,
isclear: true,
flag: "yjLine"
})
} else {
ElMessage({ message: '暂无轨迹数据', type: 'warning' });
}
})
}
// 查看反馈
const showFeedback = (val) => {
console.log(val,"查查零xxxxxx零");
emitter.emit("openFkDialog",val )
}
// 发送指令
const showDialog = ref(false)
const itemData = ref()
const showDetail = (item) => {
showDialog.value = true;
itemData.value = item
}
const handleClose = () => {
showDialog.value = false;
}
const semdFqzlRef = ref()
const tacitly = {
title: 'yjbt',
instructionContent: 'yjnr'
}
const submit = () => {
semdFqzlRef.value.getsendFqzl()
}
const closeFszl = () => {
semdFqzlRef.value.close()
}
</script>
<style lang="scss" scoped>

View File

@ -225,13 +225,12 @@ function lineChartFn(xDate, legend, series) {
fontSize: 13,
fontWeight: 'normal'
},
formatter: function(params) {
formatter: function (params) {
// 获取当前数据点的所有系列信息
const dataIndex = params.dataIndex;
const categoryName = params.name;
let result = `<div style="margin-bottom: 8px; font-weight: bold; color: #00d4ff; font-size: 14px; border-bottom: 1px solid #00d4ff; padding-bottom: 4px;">${categoryName}</div>`;
// 遍历所有系列,显示该数据点的所有信息
if (props.data && props.data.list) {
props.data.list.forEach((seriesData, index) => {
@ -240,7 +239,7 @@ function lineChartFn(xDate, legend, series) {
result += `<div style="margin: 4px 0; display: flex; align-items: center;">
<span style="display: inline-block; width: 12px; height: 12px; background: ${color};
border-radius: 50%; margin-right: 8px; border: 1px solid rgba(255,255,255,0.3);"></span>
<span style="color: #fff; margin-right: 8px; min-width: 60px;">${categoryName}:</span>
<span style="color: #fff; margin-right: 8px; min-width: 60px;">${seriesData.name}:</span>
<span style="color: #00d4ff; font-weight: bold; font-size: 14px;">${value}</span>
</div>`;
});

View File

@ -1,12 +1,11 @@
<template>
<div class="homeBox">
<div class="homeBox" style="background-color: #07274d;">
<!-- 头部 -->
<Head></Head>
<!-- 左边 -->
<div class="home-aside asideL">
<div class="asideL-top">
<DbCount></DbCount>
</div>
<div class="asideL-Bottom">
@ -14,11 +13,21 @@
<QbsbCount></QbsbCount>
</div>
<div class="commom-aside">
<QblyType></QblyType>
<KeyPpersonneltypes />
</div>
<div class="commom-aside">
<!-- <GroupWarning /> -->
<TextType></TextType>
<div class="commom-aside" @mouseenter="mouseEnter" @mouseleave="mouseLeave"
style="position: relative; height: 100%; overflow: hidden;">
<!-- <GroupWarning /> -->
<div style="position: relative; height: 100%;">
<transition name="flip" mode="out-in">
<div :key="'qb'" v-if="reversalPushShow" class="flip-wrapper">
<QblyType @reversalPush="reversalPush"></QblyType>
</div>
<div :key="'text'" v-else class="flip-wrapper">
<TextType @reversalPush="reversalPush"></TextType>
</div>
</transition>
</div>
<!-- <QbfkCount></QbfkCount> -->
</div>
</div>
@ -29,11 +38,11 @@
<Calendar />
</div>
<div class="commom-aside-big">
<Experience />
<Experience />
</div>
<div class="commom-aside-small">
<SituationAssessment />
<!-- <SituationAssessment /> -->
<Judgment />
</div>
</div>
<!-- 中间 -->
@ -48,13 +57,27 @@
<div class="flex-1" style="width: 340px;position: absolute;z-index: 100;right: 0;">
<DeployControl />
</div>
<!-- <div class="mr10" style="width: 30%;"><DeployControl /></div> -->
<!-- <div class="flex-1" style="flex: 1;"><ZdryWarning /></div> -->
<!-- <div class="flex-1" style="width: 340px;position: absolute;z-index: 100;left: 0;">
<div style="background-color: #07274d; height: 100px;">
生份证"xxxxxxxx"
</div>
</div> -->
<div class="flex-1" style="width: 340px;position: absolute;z-index: 100;left: 0;top: 30%;">
<GeneralWindow />
</div>
</div>
</div>
<!-- 底部 -->
<div class="home-foot-t">
<Bkcz></Bkcz>
<div style="width: 33%;">
<WarningDistrict></WarningDistrict>
</div>
<div style="width: 33%;">
<WarningLevels></WarningLevels>
</div>
<div style="width: 33%;">
<Bkcz></Bkcz>
</div>
</div>
</div>
<!-- 左边弹窗 -->
@ -63,7 +86,7 @@
</template>
<script setup>
import { ref, getCurrentInstance, reactive, onMounted } from 'vue'
import { ref, getCurrentInstance, reactive, onMounted, onUnmounted } from 'vue'
import LeftDialog from './dialog/leftDialog'
import GdMap from "@/components/GdMap/index.vue";
import Head from './layout/head.vue'
@ -72,20 +95,21 @@ import QbsbCount from './model/qbsbCount.vue'
import QblyType from './model/qblyType.vue'
import TextType from './model/textType.vue'
import Bkcz from './model/bkcz.vue'
import GroupWarning from './model/groupWarning.vue'
import WarningLevels from './model/warningLevels.vue'
import Yszs from './model/yszs.vue'
import DeployControl from './model/deployControl.vue';
import SituationAssessment from './model/situationAssessment.vue'
import Experience from './model/experience.vue'
import Calendar from './model/calendar.vue'
import { getItem, setItem} from "@/utils/storage";
import KeyPpersonneltypes from './model/keyPpersonneltypes.vue'
import WarningDistrict from './model/WarningDistrict.vue'
import { getItem, setItem } from "@/utils/storage";
import emitter from "@/utils/eventBus.js";
import { bm ,centralPoint} from '@/views/backOfficeSystem/IntelligentControl/DeploymentArea/xzqh.js'
import SwitchSysDialog from '@/components/SwitchSysDialog.vue'
const changeXzqh = (val,trg) => {
import { bm, centralPoint } from '@/views/backOfficeSystem/IntelligentControl/DeploymentArea/xzqh.js'
import Judgment from './model/judgment.vue'
import { tbYjxxGetList } from '@/api/zdr.js'
import GeneralWindow from './model/generalWindow.vue'
const changeXzqh = (val, trg) => {
setTimeout(() => {
// 先移除已有的边界
emitter.emit('removeBj')
@ -141,7 +165,7 @@ const getDepId = () => {
const deptCode = deptId[0].deptCode ? deptId[0].deptCode : null
if (deptLevel.startsWith('2')) {
const data = Object.values(bm).map(item => item);
changeXzqh(data,true)
changeXzqh(data, true)
} else {
switch (deptCode) {
case '54040200000'://巴宜区
@ -159,30 +183,96 @@ const getDepId = () => {
case '54042600000'://朗县
changeXzqh(bm[542627])
break;
case '54042200000'://米林县
case '54042200000'://米林县
changeXzqh(bm[542623])
break;
case '54042300000'://墨脱县
case '54042300000'://墨脱县
changeXzqh(bm[542624])
break;
default:
const data = Object.values(bm).map(item => item);
changeXzqh(data,true)
const data = Object.values(bm).map(item => item);
changeXzqh(data, true)
break;
}
}
}
}
const makerCenter = () => {
const dw = require("@/assets/point/dingwei.png")
const dw = require("@/assets/point/dingwei.png")
const coords = centralPoint.map(item => {
return { jd: item.point[0], wd: item.point[1], jzMc: item.name }
})
emitter.emit("addPointArea", { coords, icon: dw, flag: "hm", size: '14px', showTitle: true, offset: [0, -25] });
}
const timeRef = ref('')
let bj=ref(0)
// 布控预警上图
const getTbYjxxGetList = () => {
tbYjxxGetList().then(res => {
const coords = res.map(item => {
return {
id: item.id,
jd: item.jd,
wd: item.wd,
yjtp: item.yjTp,
yjnr: item.yjNr,
yjLx: item.yjlx,
yjlx: '01',
yjsj: item.yjSj,
rysfzh: item.yjRysfzh,
ryxm: item.yjRyxm,
}
})
if (timeRef.value != coords[0].yjsj&&bj.value==1) {
const icons = require("@/assets/point/jq.png")
emitter.emit('addPointArea', { coords: [{ jd: coords[0].jd, wd: coords[0].wd }], icon: icons, flag: 'yjs' })
emitter.emit('yjDetail', coords[0])
timeRef.value = coords[0].yjsj
}
bj.value=1
const icon = require("@/assets/point/yj.png")
emitter.emit('addPoint', { coords: coords, icon: icon, flag: 'yj', fontColor: '#FF0000' })
})
}
let timing = ref(true)
onMounted(() => {
getDepId()
makerCenter()
mouseLeave()
getTbYjxxGetList()
})
const timer = setInterval(() => {
getTbYjxxGetList()
}, 60000)
const reversalPushShow = ref(true)
const reversalPush = () => {
reversalPushShow.value = !reversalPushShow.value
// 移除clearInterval调用避免定时器被清除
}
// 鼠标移入
const mouseEnter = () => {
clearInterval(timing.value)
}
// 鼠标移出
const mouseLeave = () => {
// 清除可能存在的旧定时器,避免多个定时器同时运行
clearInterval(timing.value)
// 设置为5秒自动切换更容易测试效果
timing.value = setInterval(() => {
reversalPush()
}, 30000)
}
onUnmounted(() => {
clearInterval(timing.value)
clearInterval(timer)
})
@ -281,4 +371,38 @@ onMounted(() => {
align-items: center;
}
.home-foot-t {
display: flex;
}
/* Vue 过渡动画 - 翻转效果 */
.flip-enter-active,
.flip-leave-active {
transition: transform 0.6s ease, opacity 0.6s ease;
transform-style: preserve-3d;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.flip-enter-from {
transform: rotateY(90deg) translateZ(0);
opacity: 0;
}
.flip-leave-to {
transform: rotateY(-90deg) translateZ(0);
opacity: 0;
}
/* 包装层样式 */
.flip-wrapper {
position: relative;
width: 100%;
height: calc(100%/3 - 8px);
backface-visibility: hidden;
perspective: 1000px;
}
</style>

View File

@ -3,17 +3,19 @@
<FlowLine></FlowLine>
<div class="headBoxBg">
<!-- 左边 -->
<el-popover width="480px" :visible="isShowVisble" :append-to-body="true" trigger="click" popper-class="bszdr-tq-Popover" >
<el-popover width="480px" :visible="isShowVisble" :append-to-body="true" trigger="click"
popper-class="bszdr-tq-Popover">
<template #reference>
<ul class="topBtn topBtn-left flex" ref="btnRefs" v-if="wekendays && wekendays.length > 0" @click="openWinter" >
<li class="flex align-center pointer mr10" >
<ul class="topBtn topBtn-left flex" ref="btnRefs" v-if="wekendays && wekendays.length > 0"
@click="openWinter">
<li class="flex align-center pointer mr10">
<img class="mr10" :src="showIcon(wekendays[0].dqtq)" alt="" />
<div class="">
<div class="f15 text">{{ wekendays[0].dqtq }}</div>
<div class="tests">{{ wekendays[0].fx }}</div>
</div>
</li>
<li class="flex align-center mr10 ml10 pointer" >
<li class="flex align-center mr10 ml10 pointer">
<img class="mr10" :src="icon3" alt="" />
<div>
<div class="f16 text">{{ wekendays[0].dqwd }}°C</div>
@ -22,10 +24,11 @@
</div>
</div>
</li>
<li class="flex align-center pointer relative" >
<span class="tqCount" v-if="wekendays[0].list.length > 0">{{ wekendays[0].list.length }}</span>
<img v-if="wekendays[0].list.length > 0" width="34" height="34" class="mr10" src="@/assets/images/icon_066.gif" alt="" />
<img v-else class="mr10" src="@/assets/images/icon_057.png" alt="" />
<li class="flex align-center pointer relative">
<span class="tqCount" v-if="wekendays[0].list.length > 0">{{ wekendays[0].list.length }}</span>
<img v-if="wekendays[0].list.length > 0" width="34" height="34" class="mr10"
src="@/assets/images/icon_066.gif" alt="" />
<img v-else class="mr10" src="@/assets/images/icon_057.png" alt="" />
<div>
<div class="f16 text"> {{ hour + ":" + minute + ":" + second }}</div>
<div class="tests">{{ weekenday }} {{ datatime }}</div>
@ -41,8 +44,8 @@
<div class="tc" style="width: 80px">风速</div>
<div class="tc" style="width: 100px">日期</div>
</li>
<li class="tqItem relative flex align-center pointer mb8" v-for="(iv, idx) in wekendays" :key="idx" >
<span class="Count" v-if="iv.list.length > 0">{{ iv.list.length }}</span>
<li class="tqItem relative flex align-center pointer mb8" v-for="(iv, idx) in wekendays" :key="idx">
<span class="Count" v-if="iv.list.length > 0">{{ iv.list.length }}</span>
<img class="mr10" :src="showIcon(iv.dqtq)" alt="" />
<div class="tc" style="width: 100px"> {{ iv.btwd }}° ~ {{ iv.yjwd }}° </div>
<div class="tc" style="width: 80px"></div>
@ -54,14 +57,16 @@
</el-popover>
<ul class="leftBtn-yjbtn flex">
<li class="leftBtn-item pointer" @click.stop="handleBtns(it)" :class="btnsActive == it ? 'yjbtnActive' : ''" v-for="it in btns.leftBtn" :key="it">
<li class="leftBtn-item pointer" @click.stop="handleBtns(it)" :class="btnsActive == it ? 'yjbtnActive' : ''"
v-for="it in btns.leftBtn" :key="it">
<span class="btms">{{ it }}</span>
</li>
</ul>
<div class="top-center pointer">{{ props.title }}</div>
<div class="top-center pointer" @click="handleBtns('后台')">{{ props.title }}</div>
<!-- 右边 -->
<ul class="topBtn topBtn-right" v-if="!props.type">
<li class="topBtn-item" @click.stop="handleBtns(it)" :class="btnsActive == it ? 'active-topBtn' : ''" v-for="it in btns.rightBtn" :key="it">
<ul class="topBtn topBtn-right" v-if="!props.type">
<li class="topBtn-item" @click.stop="handleBtns(it)" :class="btnsActive == it ? 'active-topBtn' : ''"
v-for="it in btns.rightBtn" :key="it">
<span>{{ it }}</span>
</li>
</ul>
@ -70,18 +75,27 @@
<div class="flex align-center">
<img class="mr10" src="@/assets/images/icon_046.png" alt="" />
<div class="f14">
<div style="color:#0BB7FF">{{ userName }}</div><div>{{ dept }}</div>
<div style="color:#0BB7FF">{{ userName }}</div>
<div>{{ dept }}</div>
</div>
<el-popover popper-class="zdy-meuns-popover" placement="bottom" width="400" :append-to-body="true" v-model:visible="showMore" trigger="click">
<el-popover popper-class="zdy-meuns-popover" placement="bottom" width="400" :append-to-body="true"
v-model:visible="showMore" trigger="click">
<template #reference>
<span @click="showMore = !showMore" class="ml10 mr10"><img style="width:10px" src="@/assets/images/Polygon_right.png" alt=""></span>
<span @click="showMore = !showMore" class="ml10 mr10"><img style="width:10px"
src="@/assets/images/Polygon_right.png" alt=""></span>
</template>
<div class="settingItem" @click.stop="handleBtns(iv)" v-for="iv in btns.moreBtn" :key="iv">
<el-icon color="#fff" style="top:2px;"><Notification/></el-icon><i class="ml10" style="color: #fff;">{{iv}}</i>
<div class="settingItem" @click.stop="handleBtns(iv.name)" v-for="iv in btns.moreBtn" :key="iv.name">
<!-- <el-icon color="#fff" style="top:2px;">
<Notification />
</el-icon> -->
<i class="ml10" style="color: #fff;">{{ iv.name }}</i>
</div>
</el-popover>
<span class="ml10 mr10"><img @click.stop="handleBtns('后台')" src="@/assets/images/meun.png" alt=""></span>
<!-- <img class="mr10" src="@/assets/images/Group427322485.png" style="width: 100px" alt="" />
<img class="mr10" src="@/assets/images/Group427322486.png" style="width: 100px" alt="" /> -->
<!-- <span class="ml10 mr10"><img @click.stop="handleBtns('后台')" src="@/assets/images/meun.png" alt=""></span> -->
</div>
</ul>
</div>
@ -92,7 +106,6 @@
<script setup>
import FlowLine from './flowLine.vue'
import { getItem } from "@/utils/storage";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import { timeValidate, weekValidate } from "@/utils/tools.js";
import { useRouter, useRoute, onBeforeRouteLeave } from "vue-router";
@ -107,23 +120,23 @@ const icon5 = require("@/assets/images/icon_053.png"); //大雨
const icon6 = require("@/assets/images/icon_054.png"); //雷阵雨
const icon7 = require("@/assets/images/icon_055.png"); //多云转晴 - 阴天
const icon8 = require("@/assets/images/icon_056.png"); //多云
import { ref, onMounted, defineEmits, defineProps,onUnmounted, reactive, watch } from "vue";
const userName = getItem("USERNAME");
const dept = getItem("deptId") ? getItem("deptId")[0].deptName : '';
import { ref, onMounted, defineEmits, defineProps, onUnmounted, reactive, watch } from "vue";
const userName = getItem("USERNAME");
const dept = getItem("deptId") ? getItem("deptId")[0].deptName : '';
const props = defineProps({
title: {
type: String,
default: "林芝哨岗系统"
},
type:{
type:String,
default:''
type: {
type: String,
default: ''
}
});
const wekendays = ref([
{ dqtq :'晴' ,fx:'北',dqwd:'30',btwd:'10',yjwd:'20',tqrq:'2022-10-10',list:[]},
{ dqtq :'晴' ,fx:'北',dqwd:'30',btwd:'10',yjwd:'20',tqrq:'2022-10-10',list:[]},
{ dqtq :'晴' ,fx:'北',dqwd:'30',btwd:'10',yjwd:'20',tqrq:'2022-10-10',list:[]},
{ dqtq: '晴', fx: '北', dqwd: '30', btwd: '10', yjwd: '20', tqrq: '2022-10-10', list: [] },
{ dqtq: '晴', fx: '北', dqwd: '30', btwd: '10', yjwd: '20', tqrq: '2022-10-10', list: [] },
{ dqtq: '晴', fx: '北', dqwd: '30', btwd: '10', yjwd: '20', tqrq: '2022-10-10', list: [] },
]);
const isShowVisble = ref(false);
const store = useStore();
@ -131,8 +144,10 @@ const router = useRouter();
const route = useRoute();
const btns = reactive({
rightBtn: ["四色预警", "重点人群"],
leftBtn: ["智能布控",'研判首页'],
moreBtn:['退出登录',]
leftBtn: ["智能布控", '研判首页'],
moreBtn: [
{ name: '后台', img: require('@/assets/images/Group427322486.png') },
{ name: '退出登录', img: require('@/assets/images/Group427322485.png') }]
});
const btnsActive = ref("");
@ -173,7 +188,7 @@ const handleBtns = (val) => {
router.push("/editPassword");
break;
case "重点人群":
router.push("/mpvPeo");
router.push("/mpvPeo");
// const NPShref = router.resolve({ path: '/KeyPopulations', query: {}});
// window.open(NPShref.href, "_blank");
break;
@ -251,7 +266,8 @@ onUnmounted(() => {
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.tqItem{
.tqItem {
color: #fff;
}
</style>
@ -268,16 +284,21 @@ onUnmounted(() => {
border: 1px solid #224281 !important;
display: none !important;
}
.bszdr-tq-Popover {
background: url("~@/assets/images/el-popper.png") no-repeat center center !important;
background-size: 100% 100% !important;
border: 1px solid transparent !important;
&[data-popper-placement^="bottom"] .el-popper__arrow::before {
border: none !important;
background: transparent !important;
}
}
.settingItem {
line-height: 22px;
padding: 5px;
border-bottom: 1px solid;
}
</style>

View File

@ -0,0 +1,250 @@
<template>
<div class="comom-title">
<span class="title">预警地域统计</span>
</div>
<div class="comom-cnt zdryBox">
<!-- 滚动容器 -->
<div class="scroll-container" @mouseenter="mEnter" @mouseleave="mLeave">
<div class="scroll-wrapper" :style="{ transform: `translateY(-${scrollTop}px)` }">
<ul ref="scrollItemBox" class="scroll-content">
<!-- 数据项 -->
<li v-for="(item, index) in dataList" :key="`first-${index}`" class="warning-item">
<div class="rank-number"> {{ `${index >= 10 ? index : '0' + (index + 1)}` }}</div>
<div class="bar">
<div class="qymc">{{ item.name }}</div>
<div class="jutz">
<div class="jutf">
<div class="jutf-bar" :style="{ width: item.bfb }"></div>
</div>
<div class="numbers">
{{ item.value }}
</div>
</div>
</div>
</li>
<!-- 复制的数据项用于无缝滚动 -->
<li v-for="(item, index) in dataList" :key="`first-${index}`" class="warning-item">
<div class="rank-number">
{{ `${index >= 10 ? index : '0' + (index + 1)}` }}</div>
<div class="bar">
<div class="qymc">{{ item.name }}</div>
<div class="jutz">
<div class="jutf">
<div class="jutf-bar" :style="{ width: item.bfb }"></div>
</div>
<div class="numbers">
{{ item.value }}
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { tbYjxxGetBmtj } from '@/api/yj'
// 滚动相关变量
const scrollTop = ref(0); // 列表滚动高度
const speed = ref(60); // 滚动速度
const copyHtml = ref(''); // 复制的HTML内容
const scrollItemBox = ref(null); // 滚动项容器引用
let timer = null;
// 生命周期钩子
onMounted(() => {
// 初始化滚动
initScroll();
});
// 组件卸载时清除定时器
onUnmounted(() => {
if (timer) {
clearInterval(timer);
}
});
// 初始化滚动
function initScroll() {
setTimeout(() => {
if (scrollItemBox.value) {
copyHtml.value = scrollItemBox.value.innerHTML;
startScroll();
}
}, 100);
}
const dataList = ref([])
// 鼠标移入停止滚动
function mEnter() {
if (timer) {
clearInterval(timer);
timer = null;
}
}
// 鼠标移出继续滚动
function mLeave() {
startScroll();
}
const gettbYjxxGetBmtj = () => {
tbYjxxGetBmtj({}).then(res => {
const total = res.reduce((acc, cur) => acc + Number(cur.sl), 0);
dataList.value = res.map(item => {
let bfb = total > 0 ? item.sl / total * 100 : 0
if (bfb > 100) {
bfb = 100
}
return {
value: item.sl,
name: item.ssbmmc,
bfb: bfb + '%'
}
})
})
}
gettbYjxxGetBmtj()
// 开始滚动
function startScroll() {
if (timer) return;
timer = setInterval(() => {
scrollTop.value++;
// 获取需要滚动的盒子的高度
if (scrollItemBox.value) {
const scrollHeight = scrollItemBox.value.offsetHeight / 2; // 因为有两份相同数据
// 当滚动高度大于等于盒子高度时,从头开始滚动
if (scrollTop.value >= scrollHeight) {
scrollTop.value = 0;
}
}
}, speed.value);
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox {
background: #052249;
height: 100%;
padding: 10px;
// 滚动容器样式
.scroll-container {
height: 100%;
overflow: hidden;
position: relative;
border-radius: 8px;
background: rgba(8, 42, 85, 0.5);
// padding: 10px;
}
// 滚动包装器
.scroll-wrapper {
width: 100%;
transition: transform 0s linear;
}
// 滚动内容样式
.scroll-content {
width: 100%;
margin: 0;
padding: 0;
}
// 警告列表项样式
.warning-item {
display: flex;
// align-items: center;
margin-top: 12px;
margin-bottom: 12px;
padding: 5px 10px;
justify-content: space-between;
list-style: none;
background: linear-gradient(90deg, rgba(10, 45, 90, 0.8), rgba(15, 50, 100, 0.5));
border-left: 3px solid transparent;
border-radius: 6px;
// transition: all 0.3s ease;
backdrop-filter: blur(4px);
// // 排名1-3的特殊样式
// &:nth-child(1),
// &:nth-child(11) {
// border-left-color: #FFD700; // 金色
// background: linear-gradient(90deg, rgba(255, 215, 0, 0.15), rgba(15, 50, 100, 0.5));
// }
// &:nth-child(2),
// &:nth-child(12) {
// border-left-color: #C0C0C0; // 银色
// background: linear-gradient(90deg, rgba(192, 192, 192, 0.15), rgba(15, 50, 100, 0.5));
// }
// &:nth-child(3),
// &:nth-child(13) {
// border-left-color: #CD7F32; // 铜色
// background: linear-gradient(90deg, rgba(205, 127, 50, 0.15), rgba(15, 50, 100, 0.5));
// }
}
// 排名数字样式
.rank-number {
width: 40px;
border-radius: 4px;
margin-right: 10px;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-weight: bold;
font-size: 18px;
position: relative;
font-family: "YSBTH";
overflow: hidden;
background: url('~@/assets/images/tmd.png') no-repeat center center;
// background-image: url('~@/assets/images/tmd.png') center center no-repeat;
background-size: 100% 100%;
}
}
.bar {
flex: 1;
.qymc {
font-size: 16px;
}
.jutz {
display: flex;
align-items: center;
.jutf {
height: 10px;
flex: 1;
background-color: rgba(0, 108, 151, 0.165);
.jutf-bar {
background: linear-gradient(0deg, #fddb92 0%, #d1fdff 100%);
width: 100%;
height: 100%;
}
}
.numbers {
font-family: "YSBTH";
width: 55px;
text-align: center;
font-size: 18px;
}
}
}
</style>

View File

@ -0,0 +1,178 @@
<template>
<div class="comom-title">
<div class="title">
<span class="mr12 pointer nowrap" :style="{fontSize:activeIndex == idx ? '22px':'18px'} " v-for="(it,idx) in btns" :key="idx" @click="changeActive(idx)">{{ it }}</span>
</div>
</div>
<div class="comom-cnt" id="qcbk">
<MyTable @changePage="changePage" customClass="zdy_bkcz_table" :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight" :key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" >
<template #tp="{row}">
<!-- <img width="30" height="30" src="" alt=""> -->
<template v-if="!row.ryzp || row.ryzp.includes('baidu')">
<img src="@/assets/images/default_male.png" width="30" height="30" />
</template>
<el-image v-else :preview-teleported="true" style="width: 30px; height: 30px" :src="row.ryzp"
:preview-src-list="[row.ryzp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/default_male.png" width="30" height="30"/>
</div>
</template>
</el-image>
</template>
<template #ryXb="{row}">
<DictTag :tag="false" :value="row.ryXb" color="#fff" :options="D_BZ_XB"/>
</template>
<template #zdrRyjb="{row}">
<DictTag :tag="false" :value="row.zdrRyjb" color="#fff" :options="D_GS_ZDR_RYJB"/>
</template>
<template #zdrBkZt="{row}">
<DictTag :tag="false" :value="row.zdrBkZt" color="#fff" :options="D_GS_ZDR_BK_ZT"/>
</template>
<template #zdrCzzt="{row}">
<DictTag :tag="false" color="#FDBC3A" :value="row.zdrCzzt" :options="D_GS_ZDR_CZZT" />
</template>
<!-- *************** -->
<template #qtFxdj="{row}">
<DictTag :value="row.qtFxdj" color="#fff" :options="D_GS_ZDQT_FXDJ" />
</template>
<template #qtLb="{row}">
<DictTag :value="row.qtLb" color="#fff" :options="D_GS_ZDQT_LB" />
</template>
</MyTable>
</div>
</template>
<script setup>
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import MyTable from "@/components/aboutTable/DarkTable.vue";
import { reactive, ref,onMounted,getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const { D_GS_ZDQT_LB,D_GS_ZDQT_FXDJ,D_GS_ZDR_RYJB,D_BZ_XB,D_GS_ZDR_BK_ZT,D_GS_ZDR_CZZT} = proxy.$dict('D_GS_ZDQT_LB','D_GS_ZDQT_FXDJ','D_GS_ZDR_RYJB','D_BZ_XB','D_GS_ZDR_BK_ZT','D_GS_ZDR_CZZT')
const btns = reactive(["全域布控处置重点人员", "全域布控处置重点群体"]);
const activeIndex = ref(0);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
loading: false,
rowHieght: 61,
haveControls: false,
showSelectType: "null",
showIndex: false,
stripe:true
},
tableColumn: [
{ label: "照片", prop: "tp", showSolt: true },
{ label: "姓名", prop: "ryXm", showOverflowTooltip: true },
{ label: "性别", prop: "ryXb" ,showOverflowTooltip: true,showSolt: true},
{ label: "身份证号码", prop: "rySfzh",showOverflowTooltip: true },
{ label: "管控单位", prop: "gxSsbmmc" ,showOverflowTooltip: true},
{ label: "人员级别", prop: "zdrRyjb" ,showOverflowTooltip: true,showSolt: true},
{ label: "管控状态", prop: "zdrBkZt" ,showOverflowTooltip: true,showSolt: true},
{ label: "处置状态", prop: "zdrCzzt",showOverflowTooltip: true,showSolt: true },
]
});
const page = ref(1);
const total = ref(0);
onMounted(() => {
getData()
tabHeightFn();
});
const changeActive = (idx) =>{
activeIndex.value = idx;
pageData.tableData = []
page.value = 0;
total.value = 0;
switch(idx){
case 0:
pageData.tableColumn = [
{ label: "照片", prop: "tp", showSolt: true },
{ label: "姓名", prop: "ryXm", showOverflowTooltip: true },
{ label: "性别", prop: "ryXb" ,showOverflowTooltip: true,showSolt: true},
{ label: "身份证号码", prop: "rySfzh",showOverflowTooltip: true },
{ label: "管控单位", prop: "gxSsbmmc" ,showOverflowTooltip: true},
{ label: "人员级别", prop: "zdrRyjb" ,showOverflowTooltip: true,showSolt: true},
{ label: "管控状态", prop: "zdrBkZt" ,showOverflowTooltip: true,showSolt: true},
{ label: "处置状态", prop: "zdrCzzt",showOverflowTooltip: true,showSolt: true },
]
break;
case 1:
pageData.tableColumn = [
{ label: "群体名称", prop: "qtMc"},
{ label: "群体类别", prop: "qtLb",showSolt:true},
{ label: "风险等级", prop: "qtFxdj", showSolt: true},
{ label: "列控原因", prop: "zdrLkyy"},
{ label: "开始时间", prop: "zdrRkkssj"},
{ label: "截至时间", prop: "zdrRkjssj"},
]
break;
}
pageData.keyCount++;
getData()
}
// 获取数据
const getData = () =>{
pageData.tableConfiger.loading = true;
let url = activeIndex.value == 0 ? '/mosty-gsxt/tbGsxtZdry/selectPage':'/mosty-gsxt/tbGsxtZdqt/selectPage';
let data = { pageSize:10,pageCurrent:page.value };
qcckGet(data, url).then((res) => {
let arr = res.records || [];
pageData.tableData = page.value == 1 ? arr : pageData.tableData.concat(arr)
total.value = res.total;
pageData.tableConfiger.loading = false;
}).catch(() => {
pageData.tableConfiger.loading = false;
});
}
// 触底加载
const changePage = () => {
if(pageData.tableData.length == total.value) return false;
page.value++;
getData()
};
const tabHeightFn = () => {
pageData.tableHeight = document.getElementById('qcbk').offsetHeight - 12;
window.onresize = function () {
tabHeightFn();
};
};
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
::v-deeep .comom-title{
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
}
::v-deeep .comom-cnt{
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
}
::v-deep .el-table td.el-table__cell{
color: #ffffff;
}
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell{
background: rgba(0,61,130,0.75);
}
</style>
<style lang="scss">
.zdy_bkcz_table td.el-table__cell {
color: #ffffff !important;
}
.zdy_bkcz_table th.el-table__cell {
color: #ffffff !important;
font-size: 15px;
}
</style>

View File

@ -1,149 +1,46 @@
<template>
<div class="comom-title">
<div class="title">
<span class="mr12 pointer nowrap" :style="{fontSize:activeIndex == idx ? '22px':'18px'} " v-for="(it,idx) in btns" :key="idx" @click="changeActive(idx)">{{ it }}</span>
</div>
<div class="title">预警处置统计</div>
</div>
<div class="comom-cnt" id="qcbk">
<MyTable @changePage="changePage" customClass="zdy_bkcz_table" :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight" :key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" >
<template #tp="{row}">
<!-- <img width="30" height="30" src="" alt=""> -->
<template v-if="!row.ryzp || row.ryzp.includes('baidu')">
<img src="@/assets/images/default_male.png" width="30" height="30" />
</template>
<el-image v-else :preview-teleported="true" style="width: 30px; height: 30px" :src="row.ryzp"
:preview-src-list="[row.ryzp]" show-progress>
<template #error>
<div class="image-slot error">
<img src="@/assets/images/default_male.png" width="30" height="30"/>
</div>
</template>
</el-image>
</template>
<template #ryXb="{row}">
<DictTag :tag="false" :value="row.ryXb" color="#fff" :options="D_BZ_XB"/>
</template>
<template #zdrRyjb="{row}">
<DictTag :tag="false" :value="row.zdrRyjb" color="#fff" :options="D_GS_ZDR_RYJB"/>
</template>
<template #zdrBkZt="{row}">
<DictTag :tag="false" :value="row.zdrBkZt" color="#fff" :options="D_GS_ZDR_BK_ZT"/>
</template>
<template #zdrCzzt="{row}">
<DictTag :tag="false" color="#FDBC3A" :value="row.zdrCzzt" :options="D_GS_ZDR_CZZT" />
</template>
<!-- *************** -->
<template #qtFxdj="{row}">
<DictTag :value="row.qtFxdj" color="#fff" :options="D_GS_ZDQT_FXDJ" />
</template>
<template #qtLb="{row}">
<DictTag :value="row.qtLb" color="#fff" :options="D_GS_ZDQT_LB" />
</template>
</MyTable>
<div class="comom-cnt" style="border-right: 1px solid #ebebeb;width: 100%;" v-loading="list.YjczDate.loading">
<BarHatEcharts echartsId="qylxEcharts" :data="list.YjczDate" :autoTooltip="true"></BarHatEcharts>
</div>
</template>
<script setup>
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import MyTable from "@/components/aboutTable/DarkTable.vue";
import { reactive, ref,onMounted,getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const { D_GS_ZDQT_LB,D_GS_ZDQT_FXDJ,D_GS_ZDR_RYJB,D_BZ_XB,D_GS_ZDR_BK_ZT,D_GS_ZDR_CZZT} = proxy.$dict('D_GS_ZDQT_LB','D_GS_ZDQT_FXDJ','D_GS_ZDR_RYJB','D_BZ_XB','D_GS_ZDR_BK_ZT','D_GS_ZDR_CZZT')
const btns = reactive(["全域布控处置重点人员", "全域布控处置重点群体"]);
const activeIndex = ref(0);
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted,reactive } from "vue";
const list = reactive({
YjczDate: {
loading: false,
rowHieght: 61,
haveControls: false,
showSelectType: "null",
showIndex: false,
stripe:true
xDate: [],
list: [],
},
tableColumn: [
{ label: "照片", prop: "tp", showSolt: true },
{ label: "姓名", prop: "ryXm", showOverflowTooltip: true },
{ label: "性别", prop: "ryXb" ,showOverflowTooltip: true,showSolt: true},
{ label: "身份证号码", prop: "rySfzh",showOverflowTooltip: true },
{ label: "管控单位", prop: "gxSsbmmc" ,showOverflowTooltip: true},
{ label: "人员级别", prop: "zdrRyjb" ,showOverflowTooltip: true,showSolt: true},
{ label: "管控状态", prop: "zdrBkZt" ,showOverflowTooltip: true,showSolt: true},
{ label: "处置状态", prop: "zdrCzzt",showOverflowTooltip: true,showSolt: true },
]
});
const page = ref(1);
const total = ref(0);
const getYjczDate = () => {
list.YjczDate.loading = true;
qcckGet({}, '/mosty-gsxt/tbYjxx/getYjCzztTj').then(res => {
list.YjczDate.loading = false;
list.YjczDate.xDate = res.map(item => item.zdmc);
list.YjczDate.list = [{ name:'总数',
value: res.map(item => item.count),
color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
hatColor: '#087df9'
}]
})
};
onMounted(() => {
getData()
tabHeightFn();
getYjczDate()
});
const changeActive = (idx) =>{
activeIndex.value = idx;
pageData.tableData = []
page.value = 0;
total.value = 0;
switch(idx){
case 0:
pageData.tableColumn = [
{ label: "照片", prop: "tp", showSolt: true },
{ label: "姓名", prop: "ryXm", showOverflowTooltip: true },
{ label: "性别", prop: "ryXb" ,showOverflowTooltip: true,showSolt: true},
{ label: "身份证号码", prop: "rySfzh",showOverflowTooltip: true },
{ label: "管控单位", prop: "gxSsbmmc" ,showOverflowTooltip: true},
{ label: "人员级别", prop: "zdrRyjb" ,showOverflowTooltip: true,showSolt: true},
{ label: "管控状态", prop: "zdrBkZt" ,showOverflowTooltip: true,showSolt: true},
{ label: "处置状态", prop: "zdrCzzt",showOverflowTooltip: true,showSolt: true },
]
break;
case 1:
pageData.tableColumn = [
{ label: "群体名称", prop: "qtMc"},
{ label: "群体类别", prop: "qtLb",showSolt:true},
{ label: "风险等级", prop: "qtFxdj", showSolt: true},
{ label: "列控原因", prop: "zdrLkyy"},
{ label: "开始时间", prop: "zdrRkkssj"},
{ label: "截至时间", prop: "zdrRkjssj"},
]
break;
}
pageData.keyCount++;
getData()
}
// 获取数据
const getData = () =>{
pageData.tableConfiger.loading = true;
let url = activeIndex.value == 0 ? '/mosty-gsxt/tbGsxtZdry/selectPage':'/mosty-gsxt/tbGsxtZdqt/selectPage';
let data = { pageSize:10,pageCurrent:page.value };
qcckGet(data, url).then((res) => {
let arr = res.records || [];
pageData.tableData = page.value == 1 ? arr : pageData.tableData.concat(arr)
total.value = res.total;
pageData.tableConfiger.loading = false;
}).catch(() => {
pageData.tableConfiger.loading = false;
});
}
// 触底加载
const changePage = () => {
if(pageData.tableData.length == total.value) return false;
page.value++;
getData()
};
const tabHeightFn = () => {
pageData.tableHeight = document.getElementById('qcbk').offsetHeight - 12;
window.onresize = function () {
tabHeightFn();
};
};
// const tabHeightFn = () => {
// pageData.tableHeight = document.getElementById('qcbk').offsetHeight - 12;
// window.onresize = function () {
// tabHeightFn();
// };
// };
</script>

View File

@ -1,4 +1,5 @@
<template>
<div style="height: 100%;">
<div class="comom-title" @click="calendarPush">
<span class="title">敏感节点</span>
</div>
@ -60,6 +61,8 @@
</template>
</el-calendar>
</div>
</template>
<script setup>

View File

@ -0,0 +1,42 @@
<template>
<div class="comom-title">
<div class="title">预警数据</div>
<div class="expand-btn" >
<el-icon size="20">
<ArrowDownBold v-if="isExpanded" />
<ArrowUpBold v-else />
</el-icon>
</div>
</div>
<div class=" zdryBox" >
</div>
</template>
<script setup>
import { ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue';
import emitter from '@/utils/emitter.js';
import { ref, onMounted, onUnmounted } from 'vue';
const isShow = ref({
showYj: false, //预警弹窗
showWarning: false
});
const list = reactive({
Info_YJ: [], //预警数据
Info_Warning: [],
});
onMounted(() => {
emitter.on("showHomeYJ", (val) => {
});
});
onUnmounted(() => {
emitter.off("showHomeYJ");
});
</script>
<style>
</style>

View File

@ -1,18 +1,17 @@
<template>
<div class="comom-title">
<span class="title">线索研判盯办统计</span>
<el-popover placement="right" :width="430">
<el-popover placement="right" :width="430" :visible="visible">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;" @click="visible = true"></div>
</template>
<el-date-picker
v-model="value2"
type="datetimerange"
:shortcuts="shortcuts"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
<div>
<div class="qbltData">
<div>查询</div>
<div class="close" @click.stop="close()">X</div>
</div>
<TimeData v-if="visible" @changeTime="changeTime" />
</div>
</el-popover>
</div>
<ul class="comom-cnt xsBox flex flex-warp just-between align-center">
@ -24,6 +23,7 @@
<script setup>
import { ref } from 'vue';
import TimeData from '@/views/home/model/mesgSwitch/timeData.vue'
const contentItem = ref([
{ label: '线索总数', value: '82' },
{ label: '下发总数', value: '82' },
@ -32,37 +32,16 @@ const contentItem = ref([
{ label: '未反馈总数', value: '30' },
{ label: '未处置总数', value: '2' },
])
const value2 = ref([])
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
const visible = ref(false)
const changeTime = (val) => {
listQuery.value = {
...val
}
getCount()
}
const close = () => {
visible.value = false
}
</script>
@ -82,4 +61,14 @@ const shortcuts = [
background-size: 100% 100%;
}
}
.qbltData {
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 10px 10px
}
.close {
cursor: pointer;
}
</style>

View File

@ -1,14 +1,14 @@
<template>
<div class="comom-title">
<div class="title">预警列表</div>
<div class="expand-btn" @click="changeTab('deployControl')">
<div class="expand-btn" @click="changeTab">
<el-icon size="20">
<ArrowDownBold v-if="isExpanded" />
<ArrowUpBold v-else />
</el-icon>
</div>
</div>
<div class=" zdryBox" v-show="isExpanded">
<div class="zdryBox" v-show="isExpanded">
<div>
<CheckBox :data="checkDatas" @changeData="changeDatas"></CheckBox>
</div>
@ -27,14 +27,14 @@
<script setup>
import emitter from "@/utils/eventBus.js";
import { qcckPost } from "@/api/qcckApi.js";
// import { qcckPost } from "@/api/qcckApi.js";
import { getPageAllList, yjzxXwyjId, tbYjxxGetInfo } from '@/api/yj.js'
import DeployControlItem from "@/views/home/components/deployControlItem.vue";
import * as MOSTY from "@/components/MyComponents/index";
import CheckBox from "@/components/checkBox/index.vue";
import { ref, reactive, onMounted, onUnmounted, getCurrentInstance } from 'vue';
import { ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue';
const { proxy } = getCurrentInstance();
const { D_BZ_HPZL } = proxy.$dict('D_BZ_HPZL')
const checkData = reactive({
@ -43,10 +43,11 @@ const checkData = reactive({
});
const checkDatas = reactive({
list: ["布控", "行为", "身份", "组合"],
hasChoose: ["布控", "行为", "身份", "组合"]
hasChoose: ["布控"]
});
const total = ref(0);
const yjJb = ref('10,20,30,40');
const yjJb = ref([10, 20, 30, 40]);
const yjLx = ref(['01']);
const pageNum = ref(1);
const loading = ref(false); // 加载中
const personList = ref([]);
@ -61,6 +62,9 @@ onMounted(() => {
startAutoScroll();
}
}, 1000);
emitter.on("yjDetail", (res) => {
chooseItem(res)
})
})
// 复选框切换
function changeData(val) {
@ -74,34 +78,33 @@ function changeData(val) {
if (it == '三级') ids.push(30);
if (it == '四级') ids.push(40);
});
yjJb.value = ids.join(',')
yjJb.value = ids
if (val.length == 0) personList.value = [];
else getList();
}
const typeS=ref(true)
const typeS = ref(true)
function changeDatas(val) {
console.log(val);
console.log(val.includes('布控'));
pageNum.value = 1;
personList.value = [];
checkDatas.hasChoose = val;
let ids = [];
if (val.includes('布控')) {
typeS.value=true
typeS.value = true
yjJb.value = [10, 20, 30, 40]
} else {
typeS.value=false
}
yjJb.value = []
typeS.value = false
}
val.forEach(it => {
if (it == '布控') {
ids.push(10)
typeS.value=true
ids.push('01')
typeS.value = true
};
if (it == '行为') ids.push(20);
if (it == '身份') ids.push(30);
if (it == '组合') ids.push(40);
if (it == '行为') ids.push('02');
if (it == '身份') ids.push('03');
if (it == '组合') ids.push('04');
});
yjJb.value = ids.join(',')
yjLx.value = ids
if (val.length == 0) personList.value = [];
else getList();
}
@ -164,30 +167,91 @@ const loadList = () => {
pageNum.value++;
getList()
}
const ORDIMG = 'https://89.40.7.122:38496/image'
const IMGYM = 'https://sg.lz.dsj.xz/dhimage'
const getList = (type) => {
let data = { pageSize: 10, pageNum: pageNum.value, yjJb: yjJb.value, bkyj: 1 };
let data = { pageSize: 30, pageCurrent: pageNum.value, yjjbList: yjJb.value, yjlxList: yjLx.value };
loading.value = !type ? true : false;
qcckPost(data, '/mosty-gsxt/tbYjxx/getPageList').then(res => {
getPageAllList(data).then(res => {
loading.value = false;
let arr = res.records || [];
let arr = res.records.map(item => {
return {
...item,
yjtp:item.yjlx=='01'? item.yjtp.replace(ORDIMG, IMGYM) : item.yjtp
}
}) || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(() => {
loading.value = false;
})
}
const content = ref({
ryxm: "",
rysfzh: "",
yjsj: "",
yjdz: "",
yjtp: "",
yjnr: "",
jd: 0,
wd: 0,
yjbq: "",
yjjb: "",
yjlx: "",
ssbmdm: "",
ssbm: "",
yjlb: "",
cph: "",
hplx: null
})
const chooseItem = (item) => {
emitter.emit('showHomeYJ', [item]);
// emitter.emit('deletePointArea','home_yj_map');
// if(!item.jd || !item.jd) return proxy.$message({ type: "warning", message: "该预警没有坐标!" });
// let icon = require('@/assets/point/yj.png');
// if(item.yjjb == '20') icon = require('@/assets/point/yj1.png');
// if(item.yjjb == '30') icon = require('@/assets/point/yj2.png');
// if(item.yjjb == '40') icon = require('@/assets/point/yj3.png');
// emitter.emit('addPointArea',{flag:'home_yj_map',icon,coords:[item]});
// emitter.emit('setMapCenter',{location:[item.jd,item.wd],zoomLevel:10});
switch (item.yjlx) {
case '01':
tbYjxxGetInfo(item.id).then(res => {
content.value = {
id: item.id,
ryxm: res.yjRyxm || '',
rysfzh: res.yjRysfzh,
yjsj: res.yjSj || '',
yjdz: res.yjDz || '',
yjtp: res.yjXtp .replace(ORDIMG, IMGYM) || '',
yjnr: res.yjNr || '',
yjbq: res.yjbqmc || '',
yjlx: item.yjlx || '',
jd: res.jd || 0,
wd: res.wd || 0,
yjjb: item.yjjb || '',
czzt: res.czzt || '',
yjbt: res.yjBt || '',
}
emitter.emit('showHomeYJ', [content.value]);
})
break;
case '02':
yjzxXwyjId(item.id).then(res => {
content.value = {
id: item.id,
ryxm: res.xm || '',
rysfzh: res.sfzh,
yjsj: res.yjsj || '',
yjdz: "",
yjtp: "",
yjbq: res.xwms || '',
yjlb: item.yjlb || '',
czzt: res.czzt || '',
yjbt: res.yjBt || '',
}
emitter.emit('showHomeYJ', [content.value]);
})
break;
case '':
break;
case '04':
break;
}
}
</script>

View File

@ -0,0 +1,226 @@
<template>
<div class="comom-title" @click="chooseForumPost">
<span class="title">情报论坛</span>
</div>
<div class="comom-cnt" style="height: 300px;">
<div class="zdryBox">
<div class="carousel-container"
@mouseenter="pauseCarousel"
@mouseleave="startCarousel">
<ul class="ryBox" ref="carouselList">
<li v-for="item in displayList" :key="item.id" @click="chooseItem(item)">
<div>{{ item.title }}</div>
<div class="meta-info">{{ item.time }}{{ item.fbrxm }}</div>
<div>{{ item.content }}</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<script setup>
import { tbGsxtXxltSelectPage } from '@/api/tbGsxtXxltHf'
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
import {useRouter} from 'vue-router'
const router = useRouter()
// 数据相关
const personList = ref([]);
const displayList = ref([]); // 用于显示的数据列表
const loading = ref(false);
// 轮播相关
const carouselList = ref(null);
const scrollTimer = ref(null);
const scrollSpeed = ref(3000); // 滚动间隔时间(ms)
const itemHeight = ref(106); // 每个item的高度(px) - 与CSS变量保持一致
const currentIndex = ref(0);
const visibleItems = ref(3); // 可见条目数量
// 获取数据
const getList = () => {
loading.value = true;
tbGsxtXxltSelectPage({ pageSize: 10, pageCurrent: 1 }).then(res => {
loading.value = false;
personList.value = res.records || [];
// 复制一份数据到displayList实现无缝滚动效果
displayList.value = [...personList.value, ...personList.value];
}).catch(() => {
loading.value = false;
})
};
// 开始轮播
const startCarousel = () => {
if (scrollTimer.value) return;
scrollTimer.value = setInterval(() => {
scrollToNext();
}, scrollSpeed.value);
};
// 暂停轮播
const pauseCarousel = () => {
if (scrollTimer.value) {
clearInterval(scrollTimer.value);
scrollTimer.value = null;
}
};
// 滚动到下一项
const scrollToNext = () => {
if (!carouselList.value || personList.value.length === 0) return;
currentIndex.value++;
// 实现平滑滚动
const scrollHeight = currentIndex.value * itemHeight.value;
// 设置平滑过渡效果
carouselList.value.style.transition = 'transform 0.5s ease-out';
carouselList.value.style.transform = `translateY(-${scrollHeight}px)`;
// 当滚动到原始数据的末尾时,准备重置位置实现无缝滚动
// 使用personList.length而不是displayList.length确保无缝效果
if (currentIndex.value >= personList.value.length) {
// 确保过渡动画完成后再重置位置设置稍微小于transition时间的值
setTimeout(() => {
// 重置索引和位置,移除过渡效果以避免重置时的视觉跳动
currentIndex.value = 0;
carouselList.value.style.transition = 'none';
carouselList.value.style.transform = 'translateY(0)';
// 在下一帧重新应用过渡效果,确保动画连续性
requestAnimationFrame(() => {
carouselList.value.style.transition = 'transform 0.5s ease-out';
});
}, 490); // 略微小于500ms的过渡时间确保在动画完成后立即重置
}
};
// 点击项
const chooseItem = (item) => {
pauseCarousel(); // 点击时暂停轮播
router.push({
path: '/forumPost',
query: { id: item.id }
})
};
// 添加跳转
const chooseForumPost = () => {
pauseCarousel(); // 点击时暂停轮播
router.push({ path: '/forumPost' })
};
// 生命周期
onMounted(() => {
getList();
// 数据加载后开始轮播
setTimeout(() => {
startCarousel();
}, 1000);
// 监听窗口尺寸变化,调整轮播逻辑
window.addEventListener('resize', handleResize);
});
// 处理窗口尺寸变化
const handleResize = () => {
// 窗口大小改变时可以在这里调整itemHeight等参数
// 也可以暂停并重新开始轮播以适应新尺寸
};
// 组件卸载前清除定时器和事件监听
onBeforeUnmount(() => {
pauseCarousel();
window.removeEventListener('resize', handleResize);
});
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox {
height: 100%;
position: relative;
overflow: hidden;
/* 确保只显示3个条目的高度根据实际内容调整 */
--visible-items: 3;
--item-height: 106px;
--total-height: calc(var(--visible-items) * var(--item-height));
.carousel-container {
height: 100%;
overflow: hidden;
position: relative;
/* 限制显示区域,只显示指定数量的条目 */
max-height: var(--total-height);
box-sizing: border-box;
}
.ryBox {
position: absolute;
top: 0;
left: 0;
width: 100%;
margin: 0;
padding: 0;
list-style: none;
/* 确保在重置位置时不会出现闪烁 */
will-change: transform;
backface-visibility: hidden;
perspective: 1000px;
li {
padding: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background-color 0.3s;
cursor: pointer;
/* 确保每个项目的高度一致,便于计算 */
height: var(--item-height);
box-sizing: border-box;
&:hover {
background-color: rgba(20, 107, 190, 0.2);
}
> div:first-child {
font-weight: bold;
color: #fff;
margin-bottom: 8px;
font-size: 14px;
/* 标题限制1行超出用省略号 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.meta-info {
text-align: right;
color: #83bff6;
font-size: 12px;
margin-bottom: 8px;
}
> div:last-child {
color: rgba(255, 255, 255, 0.8);
font-size: 13px;
line-height: 1.6;
/* 内容限制3行超出用省略号 */
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
</style>

View File

@ -2,19 +2,19 @@
<div class="comom-title" @click="chooseForumPost">
<span class="title">情报论坛</span>
</div>
<div class="comom-cnt" style="height: 300px;">
<div class="comom-cnt" >
<div class="zdryBox">
<div class="carousel-container"
@mouseenter="pauseCarousel"
@mouseleave="startCarousel">
<ul class="ryBox" ref="carouselList">
<li v-for="item in displayList" :key="item.id" @click="chooseItem(item)">
<div>{{ item.title }}</div>
<div class="meta-info">{{ item.time }}{{ item.fbrxm }}</div>
<div>{{ item.content }}</div>
</li>
</ul>
</div>
<ul class="ryBox" :infinite-scroll-distance="30" ref="carouselList" @mouseenter="stopAutoScroll" @mouseleave="startAutoScroll"
v-loading="loading" v-infinite-scroll="loadList">
<li v-for="item in personList" :key="item.id" @click="chooseItem(item)">
<div>{{ item.title }}</div>
<div class="meta-info">{{ item.time }}{{ item.fbrxm }}</div>
<div>{{ item.content }}</div>
</li>
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
</ul>
<!-- 触底加载更多数据 -->
<div v-if="loadingMore" class="loading-more">加载中...</div>
</div>
</div>
</template>
@ -23,74 +23,81 @@
import { tbGsxtXxltSelectPage } from '@/api/tbGsxtXxltHf'
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
import {useRouter} from 'vue-router'
import * as MOSTY from "@/components/MyComponents/index";
const router = useRouter()
// 数据相关
const personList = ref([]);
const displayList = ref([]); // 用于显示的数据列表
const loading = ref(false);
const loadingMore = ref(false);
const total = ref(0);
const pageNum = ref(1);
// 轮播相关
// 滚动相关
const carouselList = ref(null);
const scrollTimer = ref(null);
const scrollSpeed = ref(3000); // 滚动间隔时间(ms)
const itemHeight = ref(106); // 每个item的高度(px)
const currentIndex = ref(0);
const isAutoScrolling = ref(false);
let scrollTimer = null;
// 获取数据
const getList = () => {
loading.value = true;
tbGsxtXxltSelectPage({ pageSize: 10, pageCurrent: 1 }).then(res => {
const getList = (type) => {
loading.value = !type ? true : false;
loadingMore.value = !!type;
tbGsxtXxltSelectPage({ pageSize: 10, pageCurrent: pageNum.value }).then(res => {
loading.value = false;
personList.value = res.records || [];
// 复制一份数据到displayList实现无缝滚动效果
displayList.value = [...personList.value, ...personList.value];
loadingMore.value = false;
let arr = res.records || [];
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
total.value = res.total;
}).catch(() => {
loading.value = false;
loadingMore.value = false;
})
};
// 开始轮播
const startCarousel = () => {
if (scrollTimer.value) return;
scrollTimer.value = setInterval(() => {
scrollToNext();
}, scrollSpeed.value);
// 触底加载
const loadList = () => {
if (personList.value.length == total.value || loadingMore.value) return;
pageNum.value++;
getList(true)
};
// 暂停轮播
const pauseCarousel = () => {
if (scrollTimer.value) {
clearInterval(scrollTimer.value);
scrollTimer.value = null;
// 自动滚动函数
const autoScroll = () => {
if (!carouselList.value || !isAutoScrolling.value) return;
const container = carouselList.value;
const speed = 1; // 滚动速度
// 滚动容器
container.scrollTop += speed;
// 判断是否滚动到底部,如果是则回到顶部重新开始
if (container.scrollTop >= container.scrollHeight - container.clientHeight - 5) {
container.scrollTop = 0;
}
};
// 滚动到下一项
const scrollToNext = () => {
if (!carouselList.value || personList.value.length === 0) return;
// 开始自动滚动
const startAutoScroll = () => {
if (isAutoScrolling.value || !carouselList.value) return;
isAutoScrolling.value = true;
// 清除可能存在的定时器
if (scrollTimer) {
clearInterval(scrollTimer);
}
// 设置新的定时器,控制滚动速度
scrollTimer = setInterval(autoScroll, 30);
};
currentIndex.value++;
// 实现平滑滚动
const scrollHeight = currentIndex.value * itemHeight.value;
carouselList.value.style.transition = 'transform 0.5s ease-out';
carouselList.value.style.transform = `translateY(-${scrollHeight}px)`;
// 当滚动到复制的数据部分时,重置位置实现无缝滚动
if (currentIndex.value >= personList.value.length) {
setTimeout(() => {
currentIndex.value = 0;
carouselList.value.style.transition = 'none';
carouselList.value.style.transform = 'translateY(0)';
}, 500);
// 停止自动滚动
const stopAutoScroll = () => {
isAutoScrolling.value = false;
if (scrollTimer) {
clearInterval(scrollTimer);
scrollTimer = null;
}
};
// 点击项
const chooseItem = (item) => {
pauseCarousel(); // 点击时暂停轮播
stopAutoScroll(); // 点击时停止自动滚动
router.push({
path: '/forumPost',
query: { id: item.id }
@ -99,22 +106,24 @@ const chooseItem = (item) => {
// 添加跳转
const chooseForumPost = () => {
pauseCarousel(); // 点击时暂停轮播
stopAutoScroll(); // 点击时停止自动滚动
router.push({ path: '/forumPost' })
};
// 生命周期
onMounted(() => {
getList();
// 数据加载后开始轮播
// 数据加载完成后启动自动滚动
setTimeout(() => {
startCarousel();
if (personList.value.length > 0) {
startAutoScroll();
}
}, 1000);
});
// 组件卸载前清除定时器
onBeforeUnmount(() => {
pauseCarousel();
stopAutoScroll();
});
</script>
@ -127,31 +136,39 @@ onBeforeUnmount(() => {
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.loading-more {
text-align: center;
padding: 8px;
color: #83bff6;
background: rgba(0, 0, 0, 0.3);
font-size: 12px;
}
.zdryBox {
height: 100%;
position: relative;
overflow: hidden;
.carousel-container {
height: 100%;
overflow: hidden;
position: relative;
}
.ryBox {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
// 隐藏滚动条但保留滚动功能
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none; // IE和Edge
scrollbar-width: none; // Firefox
li {
padding: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background-color 0.3s;
cursor: pointer;
box-sizing: border-box;
&:hover {
background-color: rgba(20, 107, 190, 0.2);

View File

@ -163,7 +163,7 @@ onUnmounted(() => {
justify-content: center;
align-items: center; */
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
z-index: 9999;
z-index: 99;
user-select: none;
/* transition: all 0.3s ease; */
transform: translate(-50%, -50%);

View File

@ -0,0 +1,165 @@
<template>
<div v-if="isShow.showYj">
<div class="comom-title" v-if="isShow.showYj">
<div class="title">预警数据</div>
<div class="expand-btn">
<el-icon size="20"><Close @click="closeWindow"/></el-icon>
</div>
</div>
<div class="zdryBox">
<div v-if="list.Info_YJ.length > 0" class="ryBox">
<div v-for="(item, index) in list.Info_YJ" :key="index" @click="handleClick(item)">
<DeployControlItem :item="item" :dict="{ D_BZ_HPZL }" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import { ref, onMounted, onUnmounted, reactive, getCurrentInstance } from 'vue';
import DeployControlItem from "@/views/home/components/deployControlItem.vue";
const { proxy } = getCurrentInstance();
const { D_BZ_HPZL } = proxy.$dict('D_BZ_HPZL')
const isShow = ref({
showYj: false, //预警弹窗
showWarning: false
});
const ORDIMG = 'https://89.40.7.122:38496/image'
const IMGYM = 'https://sg.lz.dsj.xz/dhimage'
const list = reactive({
Info_YJ: [], //预警数据
Info_Warning: [],
});
onMounted(() => {
emitter.on("yjShow", (res) => {
isShow.value.showYj = res ? true : false;
if (res) list.Info_YJ = res.map(item => {
return {
...item,
yjtp:item.yjtp.replace(ORDIMG, IMGYM),
yjlx: '01'
}
});
});
});
const handleClick = (val) => {
emitter.emit("yjDetail", val);
}
onUnmounted(() => {
emitter.off("yjShow");
});
const closeWindow = () => {
isShow.value.showYj = false;
}
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox {
background: #052249;
min-height: 0;
max-height: 300px;
.ryBox {
max-height: 300px;
overflow: hidden;
overflow-y: auto;
}
}
::v-deep .el-checkbox {
margin-right: 10px;
}
::-webkit-scrollbar {
background-color: #263b70;
}
::-webkit-scrollbar-thumb {
background-color: #146bbe;
}
::-webkit-scrollbar-track {
background-color: #263b70;
}
::-webkit-scrollbar-corner {
background-color: #142141;
}
::v-deep .el-checkbox__label {
color: #fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label {
color: #00FFFF;
}
::v-deep .el-checkbox__inner {
background: rgba(0, 144, 255, 0.2);
border: 1px solid #0072FF;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #00FFFF;
border-color: #00FFFF;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: #00FFFF;
border-color: #00FFFF;
}
::v-deep .el-checkbox__inner::after {
border: 2px solid #000;
border-left: 0;
border-top: 0;
left: 3px;
top: 0px;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner::before {
background: #000;
}
.comom-title {
display: flex;
justify-content: space-between;
align-items: center;
}
.expand-btn {
display: flex;
align-items: center;
justify-content: center;
// background: linear-gradient(135deg, #0072FF 0%, #00B4FF 100%);
// border-radius: 50%;
color: white;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 114, 255, 0.3);
}
.expand-btn:hover {
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(0, 114, 255, 0.5);
}
.expand-btn:active {
transform: scale(0.95);
}
</style>

View File

@ -1,13 +1,13 @@
<template>
<div class="custom-iframe-dialog-container">
<el-dialog :model-value="modelValue" width="70%" :before-close="close" :destroy-on-close="true"
class="custom-iframe-dialog" top="6vh">
<div style="height: 70vh;">
<iframe :src="src" frameborder="0" width="100%" height="100%"></iframe>
</div>
</el-dialog>
<div class="iframe-container">
<el-dialog class="dialog-container" :model-value="modelValue" width="80%" top="6vh" @close="close">
<!-- -->
<div style="height: 80vh;">
<iframe :src="src" frameborder="0" width="100%" height="100%"></iframe>
<!-- <iframe src="www.baidu.com" frameborder="0" width="100%" height="100%"></iframe> -->
</div>
</el-dialog>
</div>
</template>
<script setup>
@ -39,18 +39,15 @@ const submit = () => {
</script>
<style lang="scss" scoped>
/* 使用自定义类名直接应用样式 */
.custom-iframe-dialog {
margin-top: 6vh !important;
background-color: transparent !important;
}
::deep(.el-dialog) {
background-color: rgba(0, 255, 255, 0);
}
/* 同时确保wrapper的正确布局 */
:deep(.el-dialog__wrapper) {
display: flex !important;
align-items: flex-start !important;
justify-content: center !important;
.iframe-container {
::v-deep .el-dialog__header {
background-color: rgb(4 35 74) !important;
height: 50px;
padding: 0 !important;
}
::v-deep .el-dialog__body {
padding: 0 !important;
}
}
</style>

View File

@ -0,0 +1,141 @@
<template>
<div class="comom-title">
<span class="title">战术战略研判</span>
</div>
<div class="comom-cnt zdryBox">
<div class="model-box">
<div class="model-commom" style="" v-for="value in judgmentList" :key="value.title">
<img :src="value.img" alt="">
<div class="fontStlye">
<div class="font-bold" :style="{color: value.color}">{{value.title}}</div>
<div>{{value.num}}</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const judgmentList = ref([
{
title: '战略研判数',
num: 23,
img: require('@/assets/images/y1.png'),
color: '#e58823'
},
{
title: '战术研判数',
num: 12,
img: require('@/assets/images/y2.png'),
color: '#e5d923'
},
{
title: '战术会商数',
num: 24,
img: require('@/assets/images/y3.png'),
color: '#e56723'
},
{
title: '战略会商数',
num: 30,
img: require('@/assets/images/y4.png') ,
color: '#77e523'
}
])
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.zdryBox {
background: #052249;
height: 100%;
.ryBox {
height: 100%;
overflow: hidden;
overflow-y: auto;
}
}
::-webkit-scrollbar {
background-color: #263b70;
}
::-webkit-scrollbar-thumb {
background-color: #146bbe;
}
::-webkit-scrollbar-track {
background-color: #263b70;
}
::-webkit-scrollbar-corner {
background-color: #142141;
}
::v-deep .el-checkbox__label {
color: #fff;
}
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label {
color: #00FFFF;
}
::v-deep .el-checkbox__inner {
background: rgba(0, 144, 255, 0.2);
border: 1px solid #0072FF;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #00FFFF;
border-color: #00FFFF;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: #00FFFF;
border-color: #00FFFF;
}
::v-deep .el-checkbox__inner::after {
border: 2px solid #000;
border-left: 0;
border-top: 0;
left: 3px;
top: 0px;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner::before {
background: #000;
}
.model-box{
display: flex;justify-content: space-between;padding: 20px;flex-wrap: wrap;
}
.model-commom {
width: 50%;
border-radius: 5px;
height: 100px;
position: relative;
.fontStlye{
font-size: 20px;
font-weight: 500;
position: absolute;z-index: 20;top: 18px;left: 80px;
.font-bold{
margin-bottom: 10px;
font-family: "YSBTH";
}
}
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<div class="comom-title">
<span class="title">重点人员类型</span>
<div class="title titleFz" style="" @click="visible = true">
查看列表
</div>
</div>
<div style="height: calc(100% - 35px);">
<Pie3D :data="data" />
</div>
<ZdryDiloding v-model="visible" />
</template>
<script setup>
import Pie3D from '@/components/MyComponents/Pie3D.vue'
import ZdryDiloding from '@/views/home/model/mesgSwitch/zdryDiloding.vue'
import { tbGsxtZdryzdryBqtj } from '@/api/zdr'
import { ref } from 'vue'
const data = ref([
{ value: 18, name: '涉恐人员' },
{ value: 13, name: '涉稳人员' },
{ value: 17, name: '在逃人员' },
{ value: 20, name: '涉毒人员' },
{ value: 25, name: '刑事犯罪前科' },
{ value: 30, name: '肇事肇祸精神病' },
{ value: 30, name: '重点上访人员' },
{ value: 30, name: '僧尼人员' },
])
const visible = ref(false)
const tbGsxtZdryzdryBqtjFn = () => {
tbGsxtZdryzdryBqtj({ bqlx: '01' }).then(res => {
const dataList = res.slice(0, 8)
data.value = dataList.map(item => {
return {
value: item.sl,
name: item.bqmc,
}
})
})
}
tbGsxtZdryzdryBqtjFn()
</script>
<style>
.el-loading-mask {
background: rgba(0, 0, 0, 0.5);
}
</style>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.titleFz {
position: relative;
z-index: 100;
font-size: 14px !important;
color: rgb(255, 166, 14);
}
</style>

View File

@ -0,0 +1,154 @@
<template>
<el-dialog v-model="modelValue" title="情报列表" width="70%" @close="closeDialog" destroy-on-close>
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
<MyTable customClass="zdy_peo_table" :tableData="pageData.tableData" :tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight" :key="pageData.keyCount" :tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth">
<template #qblx="{ row }">
<DictTag :tag="false" :value="row.qblx" :options="D_GS_XS_LX" />
</template>
<template #qbly="{ row }">
<DictTag :tag="false" :value="row.qbly" :options="D_GS_XS_LY" />
</template>
<template #shzt="{ row }">
<!-- 采纳将这条信息推送到情报管理,退回 -->
<DictTag :tag="false" :value="row.shzt" :options="D_BZ_XSSHZT" @clickTag="clickTag(row.shzt)" />
</template>
<template #controls="{ row }">
<el-link size="small" type="primary" @click="showDetail(row)">详情</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="closeDialog">确认 </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import MyTable from "@/components/aboutTable/MyTable.vue";
import Search from "@/components/aboutTable/Search.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { qbcjSelectPage } from "@/api/Intelligence.js";
import { ref, reactive, getCurrentInstance, watch } from "vue";
import { useRoute,useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const { proxy } = getCurrentInstance()
const { D_BZ_QBSBLY,D_GS_XS_LX,D_GS_XS_LY ,D_BZ_XSSHZT} = proxy.$dict("D_BZ_QBSBLY","D_GS_XS_LX","D_GS_XS_LY","D_BZ_XSSHZT")
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dict: {
type: Object,
default: () => ({})
}
})
const searchConfiger = ref([
{
label: "情报标题",
prop: 'qbmc',
placeholder: "请输入情报标题",
showType: "input"
},
{
label: "上报来源",
prop: "sjLy",
placeholder: "请选择上报来源",
showType: "select",
options: D_BZ_QBSBLY
}, {
label: "上报时间",
prop: "lrkssj",
placeholder: "请选择时间",
showType: "daterange"
},
]);
const emit = defineEmits(['update:modelValue'])
const closeDialog = () => {
emit('update:modelValue', false)
}
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
loading: false,
rowHieght: 40,
haveControls: true,
},
controlsWidth: 160, //操作栏宽度
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
tableColumn: [
{ label: "上报人姓名", prop: "xssbr" },
{ label: "情报编号", prop: "xsBh" },
{ label: "情报标题", prop: "qbmc" },
{ label: "情报类型", prop: "qblx", showSolt: true },
{ label: "情报来源", prop: "qbly", showSolt: true },
{ label: "情报上报时间", prop: "sxsbsj" },
{ label: "指向地点", prop: "zxdz" },
{ label: "情报内容", prop: "qbnr" },
],
tableHeight: "50vh",
});
const parameter = ref()
const onSearch = (val) => {
const promes = {
lrkssj: val.lrkssj && val.lrkssj.length > 0 ? val.lrkssj[0] : '',
lrjssj: val.lrkssj && val.lrkssj.length > 0 ? val.lrkssj[1] : '',
}
parameter.value = { ...val, ...promes }
pageData.pageConfiger.pageCurrent = 1;
changePage()
}
watch(() => props.modelValue, (val) => {
if (val) {
changePage()
}
})
const changePage = () => {
pageData.tableConfiger.loading = true;
let data = { ...pageData.pageConfiger, ...parameter.value };
qbcjSelectPage(data).then(res => {
pageData.tableData = res.records || [];
pageData.total = res.total;
pageData.tableConfiger.loading = false;
}).catch(() => { pageData.tableConfiger.loading = false; })
}
// 查看详情
const showDetail = (item) => {
router.push({
path: '/CollectCrculate',
query: {
id: item.id
}
})
}
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
changePage()
}
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
changePage()
}
</script>
<style scoped></style>

View File

@ -0,0 +1,79 @@
<template>
<div>
<el-date-picker v-model="listQuery" :type="type" :shortcuts="shortcuts" range-separator="至" start-placeholder="开始时间"
:value-format="valueFrmat" :format="valueFrmat" end-placeholder="结束时间" @change="changeTime" />
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
const props = defineProps({
type: {
type: String,
default: "datetimerange"
},
valueFrmat: {
type: String,
default: "YYYY-MM-DD HH:mm:ss"
}
})
const listQuery = ref([])
const emit = defineEmits(['changeTime'])
// 日期变化时发出事件
const changeTime = (val) => {
const promes = {
startTime:val?.[0] || '',
endTime: val?.[1] || ''
}
emit('changeTime', promes);
};
const shortcuts = [
{
text: '近3天',
value: () => {
// 结束时间当前日期的23:59:59
const end = new Date()
end.setHours(23, 59, 59, 999)
// 开始时间3天前的00:00:00
const start = new Date()
start.setDate(start.getDate() - 3)
start.setHours(0, 0, 0, 0)
return [start, end]
},
},
{
text: '近7天',
value: () => {
// 结束时间当前日期的23:59:59
const end = new Date()
end.setHours(23, 59, 59, 999)
// 开始时间3天前的00:00:00
const start = new Date()
start.setDate(start.getDate() - 7)
start.setHours(0, 0, 0, 0)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
end.setHours(23, 59, 59, 999)
const start = new Date()
start.setMonth(start.getMonth() - 1)
start.setHours(0, 0, 0, 0)
return [start, end]
},
},
]
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
</style>

View File

@ -0,0 +1,189 @@
<template>
<el-dialog v-model="modelValue" title="重点人员列表" width="70%" @close="closeDialog" destroy-on-close>
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount"></Search>
<MyTable customClass="zdy_peo_table" :tableData="pageData.tableData" :tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight" :key="pageData.keyCount" :tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth">
<template #bqList="{ row }">
<ul>
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{
item.bqFz || 0 }} ) </li>
</ul>
</template>
<template #ryXb="{ row }">
<DictTag :tag="false" :value="row.ryXb" :options="D_BZ_XB" />
</template>
<template #ryJg="{ row }">
<DictTag :tag="false" :value="row.ryJg" :options="D_BZ_XZQHDM" />
</template>
<template #ryMz="{ row }">
<DictTag :tag="false" :value="row.ryMz" :options="D_BZ_MZ" />
</template>
<template #hjdQh="{ row }">
<DictTag :tag="false" :value="row.hjdQh" :options="D_BZ_XZQHDM" />
</template>
<template #zdrRyjb="{ row }">
<DictTag :tag="false" :value="row.zdrRyjb" :options="D_GS_ZDR_RYJB" />
</template>
<template #zdrBkZt="{ row }">
<DictTag :tag="false" :value="row.zdrBkZt" :options="D_GS_ZDR_BK_ZT" />
</template>
<template #zdrCzzt="{ row }">
<DictTag :tag="false" :value="row.zdrCzzt" :options="D_GS_ZDR_CZZT" />
</template>
<template #zdrZt="{ row }">
<DictTag :tag="false" :value="row.zdrZt" :options="D_GS_ZDQT_ZT" />
</template>
<template #xtSjzt="{ row }">
<div> {{ row.xtSjzt == 0 ? "注销" : row.xtSjzt == 1 ? "正常" : "封存" }}</div>
</template>
<template #controls="{ row }">
<el-link size="small" type="primary" @click="showDetail(row)">详情</el-link>
</template>
</MyTable>
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
...pageData.pageConfiger,
total: pageData.total
}"></Pages>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="closeDialog">确认 </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import MyTable from "@/components/aboutTable/MyTable.vue";
import Search from "@/components/aboutTable/Search.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import { tbGsxtZdryselectPage } from "@/api/zdr.js";
import { ref, reactive, getCurrentInstance, watch } from "vue";
import { useRoute,useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const { proxy } = getCurrentInstance()
const { D_GS_ZDQT_ZT, D_GS_ZDR_RYJB, D_BZ_XB, D_BZ_MZ, D_BZ_XZQHDM, D_GS_ZDR_BK_ZT, D_GS_ZDR_CZZT, D_GS_BQ_ZL, D_GS_BQ_LB, D_GS_BQ_LX, D_GS_ZDR_YJDJ, D_GS_BK_SSJZ, D_GS_BK_SQLX, D_BZ_SF, D_GS_XS_LY, D_BZ_SSZT, D_GS_XS_LX, D_GS_XS_QTLX } =
proxy.$dict("D_GS_ZDQT_ZT", "D_GS_ZDR_RYJB", "D_BZ_XB", "D_BZ_MZ", "D_BZ_XZQHDM", "D_GS_ZDR_BK_ZT", "D_GS_ZDR_CZZT", "D_GS_BQ_ZL", "D_GS_BQ_LB", "D_GS_BQ_LX", "D_GS_ZDR_YJDJ", "D_GS_BK_SSJZ", "D_GS_BK_SQLX", "D_BZ_SF", "D_GS_XS_LY", "D_BZ_SSZT", "D_GS_XS_LX", "D_GS_XS_QTLX");
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
dict: {
type: Object,
default: () => ({})
}
})
const searchConfiger = ref([
{
label: "姓名",
prop: "ryXm",
placeholder: "请输入姓名",
showType: "input"
},
{
label: "身份证",
prop: "rySfzh",
placeholder: "请输入身份证",
showType: "input"
},
{
label: "户籍地",
prop: "hjdXz",
placeholder: "请输入户籍地",
showType: "input"
},
{
label: "人员级别",
prop: "zdrRyjb",
placeholder: "请输入人员级别",
showType: "select",
options: D_GS_ZDR_RYJB
},
]);
const emit = defineEmits(['update:modelValue'])
const closeDialog = () => {
emit('update:modelValue', false)
}
const pageData = reactive({
tableData: [],
keyCount: 0,
tableConfiger: {
loading: false,
rowHieght: 40,
haveControls: true,
},
controlsWidth: 160, //操作栏宽度
total: 0,
pageConfiger: {
pageSize: 20,
pageCurrent: 1
}, //分页
tableColumn: [
{ label: "姓名", prop: "ryXm", width: 150 },
{ label: "性别", prop: "ryXb", showSolt: true, width: 100 },
{ label: "籍贯", prop: "ryJg", showSolt: true, width: 100 },
{ label: "身份证", prop: "rySfzh", width: 200 },
{ label: "民族", prop: "ryMz", showSolt: true, width: 100 },
{ label: "户籍地区划", prop: "hjdQh", showSolt: true, width: 150 },
{ label: "户籍派出所", prop: "hjdPcsmc", width: 200 },
{ label: "户籍地详址", prop: "hjdXz", width: 200 },
{ label: "标签", prop: "bqList", showSolt: true, width: 400, showOverflowTooltip: true },
{ label: "管辖单位", prop: "gxSsbmmc", width: 200 },
{ label: "人员级别", prop: "zdrRyjb", showSolt: true, width: 130 },
{ label: "管控原因", prop: "zdrLkyy", width: 200, showOverflowTooltip: true },
{ label: "管控状态", prop: "zdrBkZt", width: 200, showOverflowTooltip: true },
{ label: "处置状态", prop: "zdrCzzt", showSolt: true },
{ label: "审核状态", prop: "zdrZt", showSolt: true },
{ label: "状态", prop: "xtSjzt", showSolt: true },
],
tableHeight: "50vh",
});
const parameter = ref()
const onSearch = (val) => {
parameter.value = { ...val}
pageData.pageConfiger.pageCurrent = 1;
changePage()
}
watch(() => props.modelValue, (val) => {
if (val) {
changePage()
}
})
const changePage = () => {
pageData.tableConfiger.loading = true;
let data = { ...pageData.pageConfiger, ...parameter.value};
tbGsxtZdryselectPage(data).then(res => {
pageData.tableData = res.records || [];
pageData.total = res.total;
pageData.tableConfiger.loading = false;
}).catch(() => { pageData.tableConfiger.loading = false; })
}
// 查看详情
const showDetail = (item) => {
router.push({
path: '/mpvPeo',
query: {
id: item.id
}
})
}
const changeNo = (val) => {
pageData.pageConfiger.pageCurrent = val;
changePage()
}
const changeSize = (val) => {
pageData.pageConfiger.pageSize = val;
changePage()
}
</script>
<style scoped></style>

View File

@ -1,18 +1,18 @@
<template>
<div class="comom-title">
<span class="title">情报来源类型</span>
<el-popover placement="right" :width="430">
<div class="title">情报来源类型<span class="switchover" @click="reversalPush">切换</span></div>
<el-popover :visible="visible" placement="right" :width="430">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;" @click="visible = true">
</div>
</template>
<el-date-picker
v-model="value2"
type="datetimerange"
:shortcuts="shortcuts"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
<div>
<div class="qbltData">
<div>查询</div>
<div class="close" @click.stop="close()">X</div>
</div>
<TimeData v-if="visible" @changeTime="changeTime" />
</div>
</el-popover>
</div>
<div class="comom-cnt">
@ -23,63 +23,71 @@
<script setup>
import { qcckPost } from "@/api/qcckApi.js";
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted, reactive ,ref} from "vue";
import { onMounted, reactive, ref } from "vue";
import TimeData from '@/views/home/model/mesgSwitch/timeData.vue'
const list = reactive({
xDate: ['110警情','人力情报','系统采集','民警处置单'],
list:[
{ name: "总数", value: [0,0,0,0,] ,color:['rgba(0,244,255,1)','rgba(0,77,167,1)'] ,hatColor:'#087df9'},
{ name: "已处置", value: [0,0,0,0],color:['rgba(24, 232, 229, 1)','rgba(3, 110, 83, 1)'],hatColor:'#00FFFF' },
xDate: ['110警情', '人力情报', '系统采集', '民警处置单'],
list: [
{ name: "总数", value: [0, 0, 0, 0,], color: ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'], hatColor: '#087df9' },
{ name: "已处置", value: [0, 0, 0, 0], color: ['rgba(24, 232, 229, 1)', 'rgba(3, 110, 83, 1)'], hatColor: '#00FFFF' },
],
})
const emit = defineEmits(['reversalPush'])
const visible = ref(false)
onMounted(() => {
getCount()
});
const getCount = () =>{
qcckPost({},'/mosty-gsxt/qbcj/getXscjTjForLylx').then(res=>{
list.xDate = res ? res.cz.map(v=> v.zdmc):[];
list.list[0].value = res ? res.zs.map(v=>v.count):[];
list.list[1].value = res ? res.cz.map(v=>v.count):[];
const listQuery = ref()
const getCount = () => {
const promes = {
startTime: listQuery.value?.startTime || "",
endTime: listQuery.value?.endTime || ""
}
qcckPost(promes, '/mosty-gsxt/qbcj/getXscjTjForLylx').then(res => {
list.xDate = res ? res.cz.map(v => v.zdmc) : [];
list.list[0].value = res ? res.zs.map(v => v.count) : [];
list.list[1].value = res ? res.cz.map(v => v.count) : [];
})
}
const value2 = ref([])
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
const changeTime = (val) => {
listQuery.value = {
...val
}
getCount()
}
const reversalPush = () => {
emit('reversalPush')
}
const close = () => {
visible.value = false
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.qbltBox {
height: 100%;
background: rgba(0,29,75,0.6);
background: rgba(0, 29, 75, 0.6);
border-radius: 0 0 4px 4px;
}
.qbltData {
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 10px 10px
}
.close {
cursor: pointer;
}
.switchover{
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
}
</style>

View File

@ -1,24 +1,33 @@
<template>
<div class="comom-title">
<span class="title">情报上报数量统计</span>
<el-popover placement="right" :width="430">
<span class="title">情报上报统计</span>
<div class="title titleFz" @click="visible = true">
查看列表
</div>
<!-- <el-popover placement="right" :width="430" :visible="visible">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
</template>
<el-date-picker v-model="listQuery" type="datetimerange" :shortcuts="shortcuts" range-separator="至"
start-placeholder="开始时间" value-format="YYYY-MM-DD HH:mm:ss"
format="YYYY-MM-DD HH:mm:ss" end-placeholder="结束时间" @change="changeTime" />
</el-popover>
<div>
<div class="qbltData">
<div>查询</div>
<div class="close" @click.stop="close()">X</div>
</div>
<TimeData v-if="visible" @changeTime="changeTime" />
</div>
</el-popover> -->
</div>
<div class="comom-cnt qxsbBox">
<LineEcharts echartsId="qbsbEcharts" :data="dataList"></LineEcharts>
</div>
<Intelligence v-model="visible" :dict="{D_BZ_QBSBLY}"/>
</template>
<script setup>
import { qcckPost } from "@/api/qcckApi.js";
import LineEcharts from "../echarts/moreLineEcharts.vue";
import { reactive, onMounted, ref } from 'vue';
import Intelligence from "@/views/home/model/mesgSwitch/intelligence.vue";
import { reactive, onMounted, ref, } from 'vue';
// import TimeData from '@/views/home/model/mesgSwitch/timeData.vue'
const dataList = reactive({
xData: ['巴宜区', '工布江达县', '米林县', '墨脱县', '波密县', '察隅县', '朗县'],
@ -35,8 +44,8 @@ onMounted(() => {
const listQuery = ref()
const getCount = () => {
const promes = {
startTime: listQuery.value ? listQuery.value[0] : "",
endTime: listQuery.value ? listQuery.value[1] : ""
startTime: listQuery.value?.startTime || "",
endTime: listQuery.value?.endTime || ""
}
qcckPost(promes, '/mosty-gsxt/qbcj/getXscjTjForQx').then(res => {
dataList.xDate = res ? res.ycz.map(v => v.org_name) : [];
@ -44,44 +53,39 @@ const getCount = () => {
dataList.list[1].val = res ? res.ycz.map(v => v.count) : [];
})
}
const changeTime = () => {
console.log(listQuery.value);
getCount()
const visible = ref(false)
const changeTime = (val) => {
listQuery.value = {
...val
}
getCount()
}
const close = () => {
visible.value = false
}
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
.qbltData {
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 10px 10px
}
.comom-title{
display: flex;
align-items: center;
}
.close {
cursor: pointer;
}
.titleFz {
position: relative;
z-index: 100;
font-size: 14px !important;
color: rgb(255, 166, 14);
}
</style>

View File

@ -1,18 +1,17 @@
<template>
<div class="comom-title">
<span class="title">情报文本类型</span>
<el-popover placement="right" :width="430">
<div class="title">情报文本类型<span class="switchover" @click="reversalPush">切换</span></div>
<el-popover placement="right" :width="430" :visible="visible">
<template #reference>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;" @click="visible = true"></div>
</template>
<el-date-picker
v-model="value2"
type="datetimerange"
:shortcuts="shortcuts"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
<div>
<div class="qbltData">
<div>查询</div>
<div class="close" @click.stop="close()">X</div>
</div>
<TimeData v-if="visible" @changeTime="changeTime" />
</div>
</el-popover>
</div>
<div class="comom-cnt" >
@ -23,57 +22,44 @@
<script setup>
import { qcckPost } from "@/api/qcckApi.js";
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
import { onMounted, reactive ,ref} from "vue";
const list = reactive({
import { onMounted, reactive, ref } from "vue";
import TimeData from '@/views/home/model/mesgSwitch/timeData.vue'
const list = ref({
xDate: ['上访','诈骗','敲诈勒索','盗窃'],
list:[
{ name: "总数", value: [0,0,0,0,] ,color:['rgba(0,244,255,1)','rgba(0,77,167,1)'] ,hatColor:'#087df9'},
// { name: "已处置", value: [0,0,0,0],color:['rgba(24, 232, 229, 1)','rgba(3, 110, 83, 1)'],hatColor:'#00FFFF' },
],
list:[{ name: "总数", value: [0,0,0,0] ,color:['rgba(0,244,255,1)','rgba(0,77,167,1)'] ,hatColor:'#087df9'}],
})
onMounted(() => {
getCount()
});
const listQuery = ref()
const getCount = () => {
// list.list[0].value =[0,0,0,0]
// qcckPost({},'/mosty-gsxt/qbcj/getXscjTjForLylx').then(res=>{
// list.xDate = res ? res.cz.map(v=> v.zdmc):[];
// list.list[0].value = res ? res.zs.map(v=>v.count):[];
// list.list[1].value = res ? res.cz.map(v=>v.count):[];
// })
const promes = {
startTime: listQuery.value?.startTime || "",
endTime: listQuery.value?.endTime || ""
}
qcckPost(promes, '/mosty-gsxt/qbcj/getXscjTjBySszt').then(res => {
console.log(res);
list.value.xDate = res ? res.map(v=> v.zdmc):[];
list.value.list[0].value = res ? res.map(v => v.count) : [0, 0, 0, 0];
console.log(list.value);
})
}
const visible = ref(false)
const changeTime = (val) => {
listQuery.value = {
...val
}
getCount()
}
const emit = defineEmits(['reversalPush'])
const reversalPush = () => {
emit('reversalPush')
}
const close = () => {
visible.value = false
}
const value2 = ref([])
const shortcuts = [
{
text: '近3天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
return [start, end]
},
},
{
text: '近7天',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
},
},
{
text: '近30天',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
},
},
]
</script>
@ -84,4 +70,20 @@ const shortcuts = [
background: rgba(0,29,75,0.6);
border-radius: 0 0 4px 4px;
}
.qbltData {
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 10px 10px
}
.close {
cursor: pointer;
}
.switchover{
cursor: pointer;
font-size: 14px;
margin-left: 20px;
color: rgb(255, 146, 4);
}
</style>

View File

@ -0,0 +1,64 @@
<template>
<div class="comom-title">
<div class="title">预警等级统计</div>
</div>
<div class="comom-cnt" style="border-right: 1px solid #ebebeb;width: 100%;" v-loading="loadingyj">
<WarningCount ref="yjjbRef"></WarningCount>
</div>
</template>
<script setup>
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import WarningCount from "@/views/backOfficeSystem/fourColorManage/warningControl/centerHome/components/WarningCount.vue";
import { onMounted,ref } from "vue";
const yjjbRef = ref()
const loadingyj = ref(false)
const getYjczDate = () => {
loadingyj.value = true;
qcckGet({}, '/mosty-gsxt/tbYjxx/getYjxxTj').then(res => {
loadingyj.value = false;
yjjbRef.value.initCharts(res)
})
};
onMounted(() => {
getYjczDate()
});
// const tabHeightFn = () => {
// pageData.tableHeight = document.getElementById('qcbk').offsetHeight - 12;
// window.onresize = function () {
// tabHeightFn();
// };
// };
</script>
<style lang="scss" scoped>
@import "@/assets/css/homeScreen.scss";
::v-deeep .comom-title{
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
}
::v-deeep .comom-cnt{
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
}
::v-deep .el-table td.el-table__cell{
color: #ffffff;
}
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell{
background: rgba(0,61,130,0.75);
}
</style>
<style lang="scss">
.zdy_bkcz_table td.el-table__cell {
color: #ffffff !important;
}
.zdy_bkcz_table th.el-table__cell {
color: #ffffff !important;
font-size: 15px;
}
</style>

View File

@ -14,10 +14,10 @@
import { qcckPost } from "@/api/qcckApi.js";
import { ref, onMounted } from "vue";
const contentItem = ref([
{ type:"xs", label: "警情总数", value: "0" ,icon:require('@/assets/images/top-1.png')},
{ type:"xscz", label: "预警总数", value: "0",icon:require('@/assets/images/top-2.png') },
{ type:"zdry", label: "案件总数", value: "0",icon:require('@/assets/images/top-3.png') },
{ type:"zdqt", label: "舆情总数", value: "0" ,icon:require('@/assets/images/top-4.png')},
{ type:"jqzs", label: "警情总数", value: "0" ,icon:require('@/assets/images/top-1.png')},
{ type:"yjzs", label: "预警总数", value: "0",icon:require('@/assets/images/top-2.png') },
{ type:"zdry", label: "重点人员总数", value: "0",icon:require('@/assets/images/top-3.png') },
{ type:"zdqt", label: "重点群体总数", value: "0" ,icon:require('@/assets/images/top-4.png')},
]);
onMounted(() => {
@ -32,7 +32,6 @@ const getCount = () =>{
}
})
}
</script>
<style lang="scss" scoped>

View File

@ -10,131 +10,141 @@ import {
setItem
} from "@/utils/storage";
import { getSessionForSfzh, idCardNoLogin, idCardNoLoginPcs, getSessionForSfzhPcs } from "@/api/user-manage";
import emitter from "@/utils/eventBus.js";
import {
setTimeStamp
} from "@/utils/auth";
const loginDialog = ref(false);
const deptList = ref([]);
const store = useStore();
// 处理页面可见性变化的函数
const handleVisibilityChange = () => {
// 获取会话信息 - 带上所有cookies
fetch('https://pcs.lz.dsj.xz:9020/getSession', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
// 确保发送所有cookies包括跨域cookies
credentials: 'include',
})
.then((response) => {
// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
let { placeId, userId } = data.rows[0]
if (placeId == 'amdin') {
placeId = ''
}
idCardNoLoginLogin(userId, placeId)
// 这里可以根据返回的数据进行后续处理
})
.catch((error) => {
console.error('获取会话信息失败:', error);
// 可以添加错误通知或重试逻辑
})
};
function redirectAuth() {
const url = window.location.href
const urlObj = new URL(url);
const hostname = urlObj.hostname.split('.')[0]
if (hostname == 'pcs'||hostname == 'zhpcs') {
pcsHandleLogin()
} else {
handleLogin();
}
// if (hostname == 'pcs'||hostname == 'zhpcs') {
// pcsHandleLogin()
// } else {
// handleLogin();
// }
handleVisibilityChange()
}
const handleLogin = (e) => {
// 先尝试获取cookie中的clientKey
const token = getCookie("clientKey");
if (token) {
// 使用clientKey获取会话信息
getSessionForSfzh({ cookie: token }).then((res) => {
// 使用获取到的idEntityCard进行免登
idCardNoLogin({
idCardNo: res
}).then((resIdCard) => {
// 登录成功后设置token和用户信息到store
store.commit("user/setToken", resIdCard.jwtToken);
store.commit("user/setDeptList", resIdCard.deptList);
store.commit("user/setUserName", resIdCard.userName);
store.commit("user/setMenuList", resIdCard.menuList);
store.commit("user/setUserInfo", {
token: resIdCard.jwtToken,
permission: {
buttonPermission: ["removeTest", "viewTest"],
menus: resIdCard.menuCodeSet
},
menuList: resIdCard.menuList,
deptList: resIdCard.deptList
});
// 保存用户信息到本地存储
setItem("USERNAME", resIdCard.userName);
setItem("SFRH", resIdCard.sfrh);
setItem("USERID", resIdCard.userId);
setItem("menusPermission", resIdCard.menuCodeSet);
setItem("idEntityCard", resIdCard.idEntityCard);
setItem("deptId", resIdCard.deptList);
// 保存登录时间
setTimeStamp();
// 重定向到首页
setTimeout(() => {
window.location.hash = "/";
}, 1000);
}).catch((error) => {
console.error("免登失败:", error);
// 免登失败时重定向到登录页面
// window.location.hash = "/login";
});
}).catch((error) => {
console.error("获取会话信息失败:", error);
// 获取会话信息失败时重定向到登录页面
// window.location.hash = "/login";
});
} else {
console.error("没有找到clientKey cookie");
// 没有cookie时重定向到登录页面
window.location.hash = "/login";
}
};
const pcsHandleLogin = (e) => {
// 先尝试获取cookie中的clientKey
const token = getCookie("clientKey");
if (token) {
// 使用clientKey获取会话信息
getSessionForSfzhPcs({ cookie: token }).then((res) => {
// 使用获取到的idEntityCard进行免登
idCardNoLoginPcs({
idCardNo: res
}).then((resIdCard) => {
// 登录成功后设置token和用户信息到store
store.commit("user/setToken", resIdCard.jwtToken);
store.commit("user/setDeptList", resIdCard.deptList);
store.commit("user/setUserName", resIdCard.userName);
store.commit("user/setMenuList", resIdCard.menuList);
store.commit("user/setUserInfo", {
token: resIdCard.jwtToken,
permission: {
buttonPermission: ["removeTest", "viewTest"],
menus: resIdCard.menuCodeSet
},
menuList: resIdCard.menuList,
deptList: resIdCard.deptList
});
// 保存用户信息到本地存储
setItem("USERNAME", resIdCard.userName);
setItem("SFRH", resIdCard.sfrh);
setItem("USERID", resIdCard.userId);
setItem("menusPermission", resIdCard.menuCodeSet);
setItem("idEntityCard", resIdCard.idEntityCard);
setItem("deptId", resIdCard.deptList);
// 保存登录时间
setTimeStamp();
// 重定向到首页
setTimeout(() => {
window.location.hash = "/";
}, 1000);
}).catch((error) => {
console.error("免登失败:", error);
// 免登失败时重定向到登录页面
// window.location.hash = "/login";
});
}).catch((error) => {
console.error("获取会话信息失败:", error);
// 获取会话信息失败时重定向到登录页面
// window.location.hash = "/login";
// 身份证号进行登录
const idCardNoLoginLogin = (idCard, orgId) => {
idCardNoLogin({
idCardNo: idCard,
orgCode: orgId
}).then((resIdCard) => {
// 登录成功后设置token和用户信息到store
store.commit("user/setToken", resIdCard.jwtToken);
store.commit("user/setDeptList", resIdCard.deptList);
store.commit("user/setUserName", resIdCard.userName);
store.commit("user/setMenuList", resIdCard.menuList);
store.commit("user/setUserInfo", {
token: resIdCard.jwtToken,
permission: {
buttonPermission: ["removeTest", "viewTest"],
menus: resIdCard.menuCodeSet
},
menuList: resIdCard.menuList,
deptList: resIdCard.deptList
});
} else {
console.error("没有找到clientKey cookie");
// 没有cookie时重定向到登录页面
window.location.hash = "/login";
}
};
// 保存用户信息到本地存储
setItem("USERNAME", resIdCard.userName);
setItem("SFRH", resIdCard.sfrh);
setItem("USERID", resIdCard.userId);
setItem("menusPermission", resIdCard.menuCodeSet);
setItem("idEntityCard", resIdCard.idEntityCard);
setItem("deptId", resIdCard.deptList);
// 保存登录时间
setTimeStamp();
emitter.emit("handleClick")
// 重定向到首页
setTimeout(() => {
if (window.parent !== window.self) {
window.location.hash = window.location.href.split("#")[1];
} else {
console.log("首页");
window.location.hash = "/";
}
}, 1000);
}).catch((error) => {
console.error("免登失败:", error);
// 免登失败时重定向到登录页面
// window.location.hash = "/login";
});
}
onMounted(() => {
redirectAuth();
});