lcw
This commit is contained in:
@ -24,7 +24,7 @@
|
||||
<div style="background-color: #fff;color: black;padding: 15px;overflow: auto;" :style="{ height: tabHeight + 'px' }"
|
||||
ref="tableBox">
|
||||
<div style="border-bottom: 1px #ccc solid;padding-bottom: 30px;">
|
||||
<h1 class="headline">{{ nd }}年度西藏公安执法数据分析</h1>
|
||||
<h1 class="headline">{{ nd }}年度西藏公安战术研判报告</h1>
|
||||
<div style="display: flex;align-items: center;justify-content: space-between; color: red;margin-top: 30px;padding: 0 30px;">
|
||||
<div>{{ deptId.name }}</div>
|
||||
<div>{{ deptId?.ord }}</div>
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
|
||||
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
|
||||
<el-button size="small" type="primary">导入</el-button>
|
||||
<el-button type="primary" size="small" @click="addEdit('add', null)">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
@ -40,12 +41,12 @@
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox">
|
||||
<MyTable
|
||||
:tableData="pageData.tableData"
|
||||
:tableColumn="pageData.tableColumn"
|
||||
<MyTable
|
||||
:tableData="pageData.tableData"
|
||||
:tableColumn="pageData.tableColumn"
|
||||
:tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount"
|
||||
:tableConfiger="pageData.tableConfiger"
|
||||
:key="pageData.keyCount"
|
||||
:tableConfiger="pageData.tableConfiger"
|
||||
:controlsWidth="pageData.controlsWidth"
|
||||
@chooseData="chooseData"
|
||||
>
|
||||
@ -62,7 +63,7 @@
|
||||
</template>
|
||||
<template #bqList="{ row }">
|
||||
<ul >
|
||||
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} 分) </li>
|
||||
<li class="one_text_detail marks mb4" :key="index" v-for="(item, index) in row.bqList">{{ item.bqMc }}({{ item.bqFz || 0 }} 分) </li>
|
||||
</ul>
|
||||
</template>
|
||||
<template #bgxx="{ row }">
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
|
||||
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
|
||||
<el-button size="small" type="primary" >导入</el-button>
|
||||
<el-button type="primary" size="small" @click="addEdit('add', null)">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
</el-popover>
|
||||
<el-button size="small" type="primary" @click="handleZxs">转线索</el-button>
|
||||
<el-button size="small" type="primary" @click="handleMove">移交管控</el-button>
|
||||
<el-button size="small" type="primary" >导入</el-button>
|
||||
<el-button type="primary" size="small" @click="addEdit('add', '')">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
|
||||
@ -1,191 +0,0 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<span class="title">人力情报信息采集流转详情</span>
|
||||
<div>
|
||||
<el-button @click="close">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form_cnt">
|
||||
<FormMessage disabled v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
|
||||
<template #gapdive>
|
||||
<div style="width: 100%;height: 10px;" class="mb20">
|
||||
<el-divider content-position="left">基础信息</el-divider>
|
||||
</div>
|
||||
</template>
|
||||
<template #gapline>
|
||||
<div style="width: 100%;height: 10px;" class="mb20">
|
||||
<el-divider content-position="left">情报内容</el-divider>
|
||||
</div>
|
||||
</template>
|
||||
<template #scfj>
|
||||
<div style="width: 100%;padding-left: 50px;">
|
||||
<div>上传附件:<span class="f12">(可附电子表格、Word文档、图像、音视频文件)</span> </div>
|
||||
<div><MOSTY.Upload :showBtn="true" :isAll="true" :isImg="true" disabled :limit="10" v-model="fjdz" /> </div>
|
||||
</div>
|
||||
</template>
|
||||
</FormMessage>
|
||||
<el-divider content-position="left"><span class="mr20">相关人员</span> </el-divider>
|
||||
<MyTable
|
||||
:tableData="pageForm.tableData"
|
||||
:tableColumn="pageForm.tableColumn"
|
||||
:tableHeight="pageForm.tableHeight"
|
||||
:key="pageForm.keyCount"
|
||||
:tableConfiger="pageForm.tableConfiger"
|
||||
:controlsWidth="pageForm.controlsWidth"
|
||||
>
|
||||
<template #xb="{row}">
|
||||
<DictTag :value="row.xb" :tag="false" :options="props.dic.D_BZ_XB" />
|
||||
</template>
|
||||
<template #bqList="{row}">
|
||||
<div v-if="row.bqList">
|
||||
<el-tag type="success" v-for="(it,idx) in row.bqList" :key="idx">{{ it.bqMc }}</el-tag >
|
||||
</div>
|
||||
</template>
|
||||
<!-- 操作 -->
|
||||
<template #controls="{ row,index }">
|
||||
<el-link size="small" type="success" @click="addEdit('detail', row,index)">详情</el-link>
|
||||
</template>
|
||||
</MyTable>
|
||||
</div>
|
||||
<!-- 人员 -->
|
||||
<AddPeo ref="showAdd" v-if="showPerson" v-model="showPerson" :dic="props.dic" ></AddPeo>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import AddPeo from '@/components/addPerson/index.vue'
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import FormMessage from "@/components/aboutTable/FormMessage.vue";
|
||||
import { qcckGet } from "@/api/qcckApi.js";
|
||||
import { ref, defineExpose, reactive, onMounted, defineEmits, getCurrentInstance, nextTick } from "vue";
|
||||
const emit = defineEmits(["change"]);
|
||||
const props = defineProps({
|
||||
dic: Object
|
||||
});
|
||||
const { proxy } = getCurrentInstance();
|
||||
const dialogForm = ref(false); //弹窗
|
||||
const rules = reactive({
|
||||
xsMc: [{ required: true, message: "请输入情报名称", trigger: "blur" }],
|
||||
xlLx: [{ required: true, message: "请选择情报类型", trigger: "change" }],
|
||||
qbLy: [{ required: true, message: "请选择情报来源", trigger: "change" }],
|
||||
});
|
||||
const formData = ref([
|
||||
{ prop: "gapdive", type: "slot",width:'100%' },
|
||||
{ label: "情报名称", prop: "xsMc", type: "input" },
|
||||
{ label: "情报类型", prop: "xlLx", type: "select", options:props.dic.D_GS_XS_LX },
|
||||
{ label: "情报来源", prop: "qbLy", type: "select", options:props.dic.D_GS_XS_LY},
|
||||
{ label: "情报上报时间", prop: "zxkssj", type: "datetime"},
|
||||
// { label: "指向结束时间", prop: "zxjssj", type: "datetime"},
|
||||
{ label: "指向地点", prop: "zxdz", type: "input"},
|
||||
{ label: "所属专题", prop: "sszt", type: "select",options:props.dic.D_BZ_SSZT},
|
||||
{ prop: "gapline", type: "slot",width:'100%' },
|
||||
{ prop: "scfj", type: "slot",width:'100%'},
|
||||
{ label: "情报内容", prop: "xsNr", type: "textarea",width:'100%'},
|
||||
{ label: "群体类型", prop: "qtlx", type: "select",options:props.dic.D_GS_XS_QTLX },
|
||||
{ label: "群体名称", prop: "qtmc", type: "input"},
|
||||
{ label: "涉及人数", prop: "sjrs", type: "inputNumber"},
|
||||
{ label: "情报报送单位", prop: "ssbmdm", type: "department"},
|
||||
]);
|
||||
const fjdz = ref()
|
||||
const listQuery = ref({}); //表单
|
||||
const loading = ref(false);
|
||||
const elform = ref();
|
||||
const pageForm = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "checkBox",
|
||||
loading: false
|
||||
},
|
||||
controlsWidth: 220,
|
||||
tableColumn: [
|
||||
{ label: "姓名", prop: "xm" },
|
||||
{ label: "性别", prop: "xb",showSolt:true },
|
||||
{ label: "身份证号", prop: "sfzh" },
|
||||
{ label: "户籍地", prop: "hjdz" },
|
||||
{ label: "户籍地派出所", prop: "hjdpcs" },
|
||||
{ label: "标签", prop: "bqList",showSolt:true }
|
||||
]
|
||||
});
|
||||
const showAdd = ref()
|
||||
const showPerson = ref(false)
|
||||
onMounted(()=>{
|
||||
tabHeightFn()
|
||||
})
|
||||
|
||||
|
||||
// 初始化数据
|
||||
const init = (type, row) => {
|
||||
fjdz.value = []
|
||||
tabHeightFn()
|
||||
dialogForm.value = true;
|
||||
// 初始化表单数据,并根据详情页设置禁用状态
|
||||
if (row) getDataById(row.id);
|
||||
};
|
||||
// 根据id查询详情
|
||||
const getDataById = (id) => {
|
||||
qcckGet({id}, "/mosty-gsxt/qbcj/selectByid").then((res) => {
|
||||
fjdz.value = res.ossList || [];
|
||||
listQuery.value = res;
|
||||
pageForm.tableData = res.ryList || [];
|
||||
});
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
const addEdit = (type,row,index) =>{
|
||||
showPerson.value = true;
|
||||
nextTick(()=>{
|
||||
showAdd.value.init(type,row,index)
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭
|
||||
const close = () => {
|
||||
fjdz.value = []
|
||||
listQuery.value = {};
|
||||
dialogForm.value = false;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
pageForm.tableHeight = window.innerHeight - 720;
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
|
||||
defineExpose({ init });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/assets/css/layout.scss";
|
||||
@import "~@/assets/css/element-plus.scss";
|
||||
::v-deep .el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
|
||||
color: #0072ff;
|
||||
background: rgba(0, 114, 255, 0.3);
|
||||
}
|
||||
.boxlist {
|
||||
width: 99%;
|
||||
height: 225px;
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
::v-deep .avatar-uploader{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::v-deep .el-upload-list{
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
::v-deep .el-upload-list__item-name .el-icon{
|
||||
top: 3px;
|
||||
}
|
||||
</style>
|
||||
@ -1,147 +1,148 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<span class="title">人力情报信息采集流转详情</span>
|
||||
<span class="title">警务工作{{ title }}</span>
|
||||
<div>
|
||||
<el-button @click="submitForm()" type="primary">保存</el-button>
|
||||
<el-button @click="close">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form_cnt">
|
||||
<FormMessage disabled v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
|
||||
<template #gapdive>
|
||||
<div style="width: 100%;height: 10px;" class="mb20">
|
||||
<el-divider content-position="left">基础信息</el-divider>
|
||||
</div>
|
||||
</template>
|
||||
<template #gapline>
|
||||
<div style="width: 100%;height: 10px;" class="mb20">
|
||||
<el-divider content-position="left">情报内容</el-divider>
|
||||
</div>
|
||||
</template>
|
||||
<template #scfj>
|
||||
<div style="width: 100%;padding-left: 50px;">
|
||||
<div>上传附件:<span class="f12">(可附电子表格、Word文档、图像、音视频文件)</span> </div>
|
||||
<div><MOSTY.Upload :showBtn="true" :isAll="true" :isImg="true" disabled :limit="10" v-model="fjdz" /> </div>
|
||||
</div>
|
||||
</template>
|
||||
</FormMessage>
|
||||
<el-divider content-position="left"><span class="mr20">相关人员</span> </el-divider>
|
||||
<MyTable
|
||||
:tableData="pageForm.tableData"
|
||||
:tableColumn="pageForm.tableColumn"
|
||||
:tableHeight="pageForm.tableHeight"
|
||||
:key="pageForm.keyCount"
|
||||
:tableConfiger="pageForm.tableConfiger"
|
||||
:controlsWidth="pageForm.controlsWidth"
|
||||
>
|
||||
<template #xb="{row}">
|
||||
<DictTag :value="row.xb" :tag="false" :options="props.dic.D_BZ_XB" />
|
||||
</template>
|
||||
<template #bqList="{row}">
|
||||
<div v-if="row.bqList">
|
||||
<el-tag type="success" v-for="(it,idx) in row.bqList" :key="idx">{{ it.bqMc }}</el-tag >
|
||||
</div>
|
||||
</template>
|
||||
<!-- 操作 -->
|
||||
<template #controls="{ row,index }">
|
||||
<el-link size="small" type="success" @click="addEdit('detail', row,index)">详情</el-link>
|
||||
</template>
|
||||
</MyTable>
|
||||
<div style="display: flex;width: 100%;" v-loading="loading">
|
||||
<div class="form_cnt">
|
||||
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
|
||||
<template #gapdive>
|
||||
<div style="width: 100%;height: 10px;" class="mb20">
|
||||
<el-divider content-position="left">基础信息</el-divider>
|
||||
</div>
|
||||
</template>
|
||||
<template #gapline>
|
||||
<div style="width: 100%;height: 10px;" class="mb20">
|
||||
<el-divider content-position="left">情报内容</el-divider>
|
||||
</div>
|
||||
</template>
|
||||
<template #scfj>
|
||||
<div style="width: 100%;padding-left: 50px;">
|
||||
<div>上传附件:<span class="f12">(可附电子表格、Word文档、图像、音视频文件)</span> </div>
|
||||
<div>
|
||||
<MOSTY.Upload :showBtn="true" :isAll="true" :isImg="true" disabled :limit="10" v-model="fjdz" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</FormMessage>
|
||||
<el-divider content-position="left"><span class="mr20">活跃人员</span> </el-divider>
|
||||
<Personnel :dict="props.dict" ref="personnel" :perList="listQuery.ryList"/>
|
||||
<el-divider content-position="left"><span class="mr20">车辆信息</span> </el-divider>
|
||||
<VehicleCar :dict="props.dict" ref="vehicleCar" :clList="listQuery.clList"/>
|
||||
<el-divider content-position="left"><span class="mr20">关联群体</span> </el-divider>
|
||||
<Group :dict="props.dict" ref="group" :qtList="listQuery.qtList" />
|
||||
</div>
|
||||
<div class="person" v-if="showPj">
|
||||
<AddForm ref="addForm" :dict="props.dict" :msgeDat="msgeDat" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 人员 -->
|
||||
<AddPeo ref="showAdd" v-if="showPerson" v-model="showPerson" :dic="props.dic" ></AddPeo>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import AddPeo from '@/components/addPerson/index.vue'
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Personnel from '../components/personnel/index.vue'
|
||||
import VehicleCar from '../components/vehicleCar/index.vue'
|
||||
import Group from '../components/group/index.vue'
|
||||
import FormMessage from "@/components/aboutTable/FormMessage.vue";
|
||||
import { qcckGet } from "@/api/qcckApi.js";
|
||||
import { ref, defineExpose, reactive, onMounted, defineEmits, getCurrentInstance, nextTick } from "vue";
|
||||
const emit = defineEmits(["change"]);
|
||||
import { qbcjAdd, qbcjUpdate, qbcjSelectByid } from "@/api/Intelligence.js";
|
||||
import { ref, defineExpose, onMounted, defineEmits, watch } from "vue";
|
||||
import AddForm from '@/views/backOfficeSystem/MakeAcomment/components/a/addForm.vue'
|
||||
|
||||
const emit = defineEmits(["getList"]);
|
||||
const props = defineProps({
|
||||
dic: Object
|
||||
dict: Object
|
||||
});
|
||||
const { proxy } = getCurrentInstance();
|
||||
const loading=ref(false)
|
||||
const dialogForm = ref(false); //弹窗
|
||||
const rules = reactive({
|
||||
xsMc: [{ required: true, message: "请输入情报名称", trigger: "blur" }],
|
||||
xlLx: [{ required: true, message: "请选择情报类型", trigger: "change" }],
|
||||
qbLy: [{ required: true, message: "请选择情报来源", trigger: "change" }],
|
||||
});
|
||||
const formData = ref([
|
||||
{ prop: "gapdive", type: "slot",width:'100%' },
|
||||
{ label: "情报名称", prop: "xsMc", type: "input" },
|
||||
{ label: "情报类型", prop: "xlLx", type: "select", options:props.dic.D_GS_XS_LX },
|
||||
{ label: "情报来源", prop: "qbLy", type: "select", options:props.dic.D_GS_XS_LY},
|
||||
{ label: "情报上报时间", prop: "zxkssj", type: "datetime"},
|
||||
// { label: "指向结束时间", prop: "zxjssj", type: "datetime"},
|
||||
{ label: "指向地点", prop: "zxdz", type: "input"},
|
||||
{ label: "所属专题", prop: "sszt", type: "select",options:props.dic.D_BZ_SSZT},
|
||||
{ prop: "gapline", type: "slot",width:'100%' },
|
||||
{ prop: "scfj", type: "slot",width:'100%'},
|
||||
{ label: "情报内容", prop: "xsNr", type: "textarea",width:'100%'},
|
||||
{ label: "群体类型", prop: "qtlx", type: "select",options:props.dic.D_GS_XS_QTLX },
|
||||
{ label: "群体名称", prop: "qtmc", type: "input"},
|
||||
{ label: "涉及人数", prop: "sjrs", type: "inputNumber"},
|
||||
{ label: "情报报送单位", prop: "ssbmdm", type: "department"},
|
||||
]);
|
||||
const formData = ref();
|
||||
watch(() => dialogForm.value, (val) => {
|
||||
if (val) {
|
||||
formData.value = [
|
||||
{ prop: "gapdive", type: "slot", width: '100%' },
|
||||
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' },
|
||||
{ label: "情报类型", prop: "qblx", type: "select", options: props.dict.D_GS_XS_LX, width: '45%' },
|
||||
{ label: "情报密级", prop: "qbmj", type: "select", options: props.dict.D_BZ_BMJB, width: '45%' },
|
||||
{ label: "情报来源", prop: "qbly", type: "select", options: props.dict.D_GS_XS_LY, width: '45%' },
|
||||
{ label: "情报上报时间", prop: "sxsbsj", type: "datetime", width: '45%' },
|
||||
{ label: "指向时间", prop: "zxkssj", type: "datetime", width: '45%' },
|
||||
{ label: "指向地址", prop: "zxdz", type: "input", width: '45%' },
|
||||
{ label: "附件上传", prop: "fjdz", type: "upload", width: '100%' },
|
||||
{ label: "情报内容", prop: "qbnr", type: "textarea", width: '100%' },
|
||||
]
|
||||
}
|
||||
}, { deep: true })
|
||||
const fjdz = ref()
|
||||
const listQuery = ref({}); //表单
|
||||
const loading = ref(false);
|
||||
const elform = ref();
|
||||
const pageForm = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "checkBox",
|
||||
loading: false
|
||||
},
|
||||
controlsWidth: 220,
|
||||
tableColumn: [
|
||||
{ label: "姓名", prop: "xm" },
|
||||
{ label: "性别", prop: "xb",showSolt:true },
|
||||
{ label: "身份证号", prop: "sfzh" },
|
||||
{ label: "户籍地", prop: "hjdz" },
|
||||
{ label: "户籍地派出所", prop: "hjdpcs" },
|
||||
{ label: "标签", prop: "bqList",showSolt:true }
|
||||
]
|
||||
});
|
||||
const showAdd = ref()
|
||||
const showPerson = ref(false)
|
||||
onMounted(()=>{
|
||||
tabHeightFn()
|
||||
onMounted(() => {
|
||||
})
|
||||
|
||||
|
||||
const addForm = ref()
|
||||
const msgeDat = ref()
|
||||
const title = ref("")
|
||||
const showPj = ref(false)
|
||||
const disabled = ref(false)
|
||||
// 初始化数据
|
||||
const init = (type, row) => {
|
||||
title.value = type == "add" ? "新增" : type == "info" ? "详情" : "编辑"
|
||||
disabled.value = type == 'info' ? true : false
|
||||
fjdz.value = []
|
||||
tabHeightFn()
|
||||
dialogForm.value = true;
|
||||
// 初始化表单数据,并根据详情页设置禁用状态
|
||||
if (row) getDataById(row.id);
|
||||
if (type == 'info' || type == 'edit') {
|
||||
showPj.value = true
|
||||
msgeDat.value = row
|
||||
// 初始化表单数据,并根据详情页设置禁用状态
|
||||
if (row) getDataById(row.id);
|
||||
} else {
|
||||
showPj.value = false
|
||||
}
|
||||
};
|
||||
// 根据id查询详情
|
||||
const getDataById = (id) => {
|
||||
qcckGet({id}, "/mosty-gsxt/qbcj/selectByid").then((res) => {
|
||||
qbcjSelectByid({ id }).then((res) => {
|
||||
fjdz.value = res.ossList || [];
|
||||
listQuery.value = res;
|
||||
pageForm.tableData = res.ryList || [];
|
||||
});
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
const addEdit = (type,row,index) =>{
|
||||
showPerson.value = true;
|
||||
nextTick(()=>{
|
||||
showAdd.value.init(type,row,index)
|
||||
// 获取人员信息
|
||||
const personnel = ref(null)
|
||||
const vehicleCar = ref(null)
|
||||
const group = ref(null)
|
||||
// 新增
|
||||
const submitForm = () => {
|
||||
loading.value = true
|
||||
elform.value.submit(valid => {
|
||||
if (valid) {
|
||||
const promes = {
|
||||
...listQuery.value,
|
||||
fjdz: fjdz.value.length > 0 ? fjdz.value.join(',') : '',
|
||||
ryList: personnel.value.listData() || [],
|
||||
clList: vehicleCar.value.listData() || [],
|
||||
qtList:group.value.listData() || [],
|
||||
}
|
||||
if (title.value == '新增') {
|
||||
qbcjAdd(promes).then((res) => {
|
||||
emit("getList")
|
||||
close()
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else if (title.value == '编辑') {
|
||||
qbcjUpdate(promes).then((res) => {
|
||||
emit("getList")
|
||||
close()
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭
|
||||
const close = () => {
|
||||
fjdz.value = []
|
||||
@ -149,25 +150,18 @@ const close = () => {
|
||||
dialogForm.value = false;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
pageForm.tableHeight = window.innerHeight - 720;
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
|
||||
defineExpose({ init });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/assets/css/layout.scss";
|
||||
@import "~@/assets/css/element-plus.scss";
|
||||
::v-deep .el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
|
||||
|
||||
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
|
||||
color: #0072ff;
|
||||
background: rgba(0, 114, 255, 0.3);
|
||||
}
|
||||
|
||||
.boxlist {
|
||||
width: 99%;
|
||||
height: 225px;
|
||||
@ -175,17 +169,29 @@ defineExpose({ init });
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
::v-deep .avatar-uploader{
|
||||
::v-deep .avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::v-deep .el-upload-list{
|
||||
::v-deep .el-upload-list {
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
::v-deep .el-upload-list__item-name .el-icon{
|
||||
|
||||
::v-deep .el-upload-list__item-name .el-icon {
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.form_cnt {
|
||||
// width: 75%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.person {
|
||||
padding-left: 20px;
|
||||
width: 25%;
|
||||
// height: 100vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
<!-- 批量导入 -->
|
||||
<template>
|
||||
|
||||
</template>
|
||||
<script setup>
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -1,16 +1,24 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="人力情报数据采集管理">
|
||||
<!-- <el-button type="primary">
|
||||
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon>
|
||||
<span style="vertical-align: middle">导出</span>
|
||||
</el-button> -->
|
||||
<el-button type="primary" @click="dologShowFn()">
|
||||
<PageTitle title="警务工作管理">
|
||||
<el-button type="primary" @click="addEdit('add')">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">全域搜索</span>
|
||||
<span style="vertical-align: middle">新增</span>
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dologCancel()">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">导出</span>
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="ids.length === 0" @click="delDictItem(ids)">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">批量删除</span>
|
||||
</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
@ -18,17 +26,17 @@
|
||||
<div ref="searchBox">
|
||||
<Search :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox">
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
|
||||
@chooseData="chooseData">
|
||||
|
||||
<template #xlLx="{ row }">
|
||||
<DictTag :tag="false" :value="row.xlLx" :options="D_GS_XS_LX" />
|
||||
<template #qblx="{ row }">
|
||||
<DictTag :tag="false" :value="row.qblx" :options="D_GS_XS_LX" />
|
||||
</template>
|
||||
<template #qbLy="{ row }">
|
||||
<DictTag :tag="false" :value="row.qbLy" :options="D_GS_XS_LY" />
|
||||
<template #qbly="{ row }">
|
||||
<DictTag :tag="false" :value="row.qbly" :options="D_GS_XS_LY" />
|
||||
</template>
|
||||
<!-- <template #czzt="{row}">
|
||||
<DictTag :tag="false" :value="row.czzt" :options="D_GS_XS_CZZT" />
|
||||
@ -39,9 +47,10 @@
|
||||
</template>
|
||||
<!-- 操作 -->
|
||||
<template #controls="{ row }">
|
||||
<el-link size="small" type="primary" @click="addEdit('edit', row)">详情</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('edit', row)">修改</el-link>
|
||||
<!-- <el-link size="small" type="primary" @click="addEdit('edit', row)">下发指令</el-link> -->
|
||||
<el-popconfirm title="是否进行发布?" @confirm="confirm(row)">
|
||||
<el-popconfirm title="是否进行发布?" @confirm="confirm(row)">
|
||||
<template #reference>
|
||||
<el-link size="small" type="primary">发布</el-link>
|
||||
</template>
|
||||
@ -82,31 +91,42 @@
|
||||
}"></Pages>
|
||||
</div>
|
||||
<!-- 新增 -->
|
||||
<AddForm ref="detailDiloag" @change="change" v-if="isShow"
|
||||
:dic="{ D_BZ_SF, D_BZ_XB, D_GS_XS_LY, D_BZ_SSZT, D_GS_XS_LX, D_GS_XS_QTLX }" />
|
||||
|
||||
<DialogDragger title="全域搜索" top="30px" v-model="dologShow" coumClass="zdy-model-dialogs" @close="close" width="80%">
|
||||
<iframe style="width: 100%; height: 1000px" src="https://www.baidu.com" frameborder="0">
|
||||
xxxxx
|
||||
</iframe>
|
||||
</DialogDragger>
|
||||
<AddForm ref="detailDiloag" @getList="getList" :dict="{
|
||||
D_BZ_SF,
|
||||
D_GS_XS_LY,
|
||||
D_BZ_SSZT,
|
||||
D_GS_XS_LX,
|
||||
D_GS_XS_QTLX,
|
||||
D_GS_ZDQT_LB,
|
||||
D_BZ_BMJB,
|
||||
D_BZ_CLPP,
|
||||
D_BZ_CLYS,
|
||||
D_BZ_CLLX,
|
||||
D_BZ_XZQHDM
|
||||
}" />
|
||||
</div>
|
||||
<ExportFile v-model="exportFileModel" :tableColumn="tableColumn" :dict="{ D_GS_XS_LY ,D_GS_XS_LX}" :dataModel="pageData.tableData"/>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { download } from "@/utils/request";
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import DialogDragger from "@/views/home/layout/dialogDragger.vue";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import AddForm from "./components/addForm.vue";
|
||||
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
|
||||
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
|
||||
// import {updateBkgzl} from '@/api/'
|
||||
import { qbcjSelectPage, qbcjDeletes } from "@/api/Intelligence.js";
|
||||
import { reactive, ref, onMounted, getCurrentInstance, nextTick, watch } from "vue";
|
||||
import ExportFile from './components/exportFile.vue'
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_GS_XS_CZZT, D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX, D_GS_XS_QTLX, D_BZ_XB, D_BZ_XSSHZT } = proxy.$dict("D_GS_XS_CZZT", "D_GS_XS_LY", "D_BZ_SSZT", "D_BZ_SF", "D_GS_XS_LX", "D_GS_XS_QTLX", "D_BZ_XB", "D_BZ_XSSHZT"); //获取字典数据
|
||||
const { D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX,
|
||||
D_GS_XS_QTLX, D_BZ_XSSHZT, D_GS_ZDQT_LB,
|
||||
D_BZ_BMJB, D_BZ_CLPP, D_BZ_CLYS, D_BZ_CLLX, D_BZ_XZQHDM, D_GS_XS_CZZT } =
|
||||
proxy.$dict("D_BZ_BMJB", "D_GS_XS_CZZT", "D_GS_XS_LY",
|
||||
"D_BZ_SSZT", "D_BZ_SF", "D_GS_XS_LX", "D_GS_XS_QTLX",
|
||||
"D_BZ_XSSHZT", "D_GS_ZDQT_LB", "D_BZ_CLPP", "D_BZ_CLYS", "D_BZ_CLLX", "D_BZ_XZQHDM", "D_GS_XS_CZZT"); //获取字典数据
|
||||
const detailDiloag = ref();
|
||||
const searchBox = ref(); //搜索框
|
||||
const chooseRow = ref({})
|
||||
@ -114,19 +134,27 @@ const rules = reactive({
|
||||
bhyy: false,
|
||||
shzt: false,
|
||||
})
|
||||
const ids = ref([])
|
||||
const chooseData = (val) => {
|
||||
ids.value = val.map(item => {
|
||||
return item.id
|
||||
})
|
||||
}
|
||||
const isShow = ref(false)
|
||||
const searchConfiger = ref([
|
||||
{ label: "情报名称", prop: 'xsMc', placeholder: "请输入情报名称", showType: "input" },
|
||||
{ label: "内容关键字", prop: 'xsNr', placeholder: "请输入语义关键字", showType: "input" },
|
||||
{ label: "情报类型", prop: 'xlLx', placeholder: "请选择情报类型", showType: "select", options: D_GS_XS_LX },
|
||||
{ label: "情报来源", prop: 'qbLy', placeholder: "请选择情报来源", showType: "select", options: D_GS_XS_LY },
|
||||
{ label: "情报上报时间", prop: 'kssj', placeholder: "请选择开始时间", showType: "date" },
|
||||
// { label: "结束时间", prop: 'jssj', placeholder: "请选择结束时间", showType: "date" },
|
||||
{ label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" },
|
||||
{ label: "姓名", prop: 'sjryxm', placeholder: "请输入姓名", showType: "input" },
|
||||
{ label: "身份证号", prop: 'sjrysfzh', placeholder: "请输入身份证号", showType: "input" },
|
||||
{ label: "群体名称", prop: 'qtmc', placeholder: "请输入群体名称", showType: "input" },
|
||||
{ label: "指向地点", prop: 'zxdz', placeholder: "请输入指向地点", showType: "input" },
|
||||
{ label: "指向时间", prop: 'zxkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
|
||||
{ label: "录入时间", prop: 'lrkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
|
||||
{ label: "情报类型", prop: 'qblx', placeholder: "请选择情报类型", showType: "select", options: D_GS_XS_LX },
|
||||
{ label: "情报来源", prop: 'qbly', placeholder: "请选择情报来源", showType: "select", options: D_GS_XS_LY },
|
||||
{ label: "情报处置状态", prop: 'czzt', placeholder: "请选择处置状态", showType: "select", options: D_GS_XS_CZZT },
|
||||
{ label: "来源单位", prop: 'gxdwdm', placeholder: "请选择来源单位", showType: "department" },
|
||||
{ label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" },
|
||||
]);
|
||||
|
||||
|
||||
|
||||
const pageData = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
@ -143,27 +171,26 @@ const pageData = reactive({
|
||||
controlsWidth: 240,
|
||||
tableColumn: [
|
||||
{ label: "上报人姓名", prop: "xssbr" },
|
||||
// { label: "上报人电话", prop: "xssbrdh" },
|
||||
{ label: "情报编号", prop: "xsBh" },
|
||||
{ label: "情报名称", prop: "xsMc" },
|
||||
{ label: "情报类型", prop: "xlLx", showSolt: true },
|
||||
{ label: "情报来源", prop: "qbLy", showSolt: true },
|
||||
{ label: "情报上报时间", prop: "zxkssj" },
|
||||
// { label: "结束时间", prop: "zxjssj" },
|
||||
{ label: "情报标题", prop: "qbmc" },
|
||||
{ label: "情报类型", prop: "qblx", showSolt: true },
|
||||
{ label: "情报来源", prop: "qbly", showSolt: true },
|
||||
{ label: "情报上报时间", prop: "sxsbsj" },
|
||||
{ label: "指向地点", prop: "zxdz" },
|
||||
{ label: "情报内容", prop: "xsNr" },
|
||||
// { label: "处置状态", prop: "czzt",showSolt: true},
|
||||
{ label: "附件", prop: "fjdz", showSolt: true },
|
||||
// { label: "关联任务", prop: "xssbrdh" },//没有字段
|
||||
{ label: "审核状态", prop: "shzt", showSolt: true },
|
||||
{ label: "情报内容", prop: "qbnr" },
|
||||
]
|
||||
});
|
||||
|
||||
const queryFrom = ref({});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
tabHeightFn();
|
||||
tabHeightFn()
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -189,7 +216,17 @@ const handleSumbit = (row) => {
|
||||
|
||||
// 搜索
|
||||
const onSearch = (val) => {
|
||||
queryFrom.value = { ...val }
|
||||
const { lrkssj, zxkssj } = val
|
||||
console.log(lrkssj, zxkssj);
|
||||
const promes = {
|
||||
...pageData.pageConfiger,
|
||||
lrkssj: lrkssj ? lrkssj[0] : '',
|
||||
lrjssj: lrkssj ? lrkssj[1] : '',
|
||||
zxkssj: zxkssj ? zxkssj[0] : '',
|
||||
zxjssj: zxkssj ? zxkssj[1] : '',
|
||||
}
|
||||
|
||||
queryFrom.value = { ...promes }
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList()
|
||||
}
|
||||
@ -206,8 +243,8 @@ const changeSize = (val) => {
|
||||
// 获取列表
|
||||
const getList = () => {
|
||||
pageData.tableConfiger.loading = true;
|
||||
let data = { ...pageData.pageConfiger, ...queryFrom.value, cjLx: '1' };
|
||||
qcckGet(data, '/mosty-gsxt/qbcj/selectPage').then(res => {
|
||||
let data = { ...pageData.pageConfiger, ...queryFrom.value };
|
||||
qbcjSelectPage(data).then(res => {
|
||||
pageData.tableData = res.records || [];
|
||||
pageData.total = res.total;
|
||||
pageData.tableConfiger.loading = false;
|
||||
@ -216,17 +253,25 @@ const getList = () => {
|
||||
// 删除
|
||||
const delDictItem = (id) => {
|
||||
proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
|
||||
qcckPost({ id }, '/mosty-gsxt/qbcj/delete').then(() => {
|
||||
qbcjDeletes({ ids: Array.isArray(id) ? id : [id] }).then((res) => {
|
||||
proxy.$message({ type: "success", message: "删除成功" });
|
||||
getList();
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
}).catch(() => { });
|
||||
}
|
||||
|
||||
// 导出
|
||||
const exportFile = () => {
|
||||
window.open('/mosty-api/mosty-gsxt/qbcj/exportQbsjcjDc?cjLx=1', '_self')
|
||||
}
|
||||
// 导出数据
|
||||
const tableColumn = reactive([
|
||||
{ label: "上报人姓名", prop: "xssbr" },
|
||||
{ label: "情报编号", prop: "xsBh" },
|
||||
{ label: "情报标题", prop: "qbmc" },
|
||||
{ label: "情报类型", prop: "qblx", showSolt: true,zd:'D_GS_XS_LX' },
|
||||
{ label: "情报来源", prop: "qbly", showSolt: true,zd:'D_GS_XS_LY' },
|
||||
{ label: "情报上报时间", prop: "sxsbsj" },
|
||||
{ label: "指向地点", prop: "zxdz" },
|
||||
{ label: "情报内容", prop: "qbnr",showOverflowTooltip: true },
|
||||
])
|
||||
|
||||
// 详情
|
||||
const addEdit = (type, row) => {
|
||||
@ -237,7 +282,7 @@ const addEdit = (type, row) => {
|
||||
};
|
||||
//发布
|
||||
const confirm = (item) => {
|
||||
qcckPost({id:item.id,sffb:1}, '/mosty-gsxt/qbcj/qbfb').then(res => {
|
||||
qcckPost({ id: item.id, sffb: 1 }, '/mosty-gsxt/qbcj/qbfb').then(res => {
|
||||
proxy.$message({ type: "success", message: "发布成功" });
|
||||
getList();
|
||||
})
|
||||
@ -250,9 +295,10 @@ const tabHeightFn = () => {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
const dologShow = ref(false)
|
||||
const dologShowFn = (val) => {
|
||||
dologShow.value = true;
|
||||
|
||||
const exportFileModel = ref(false)
|
||||
const dologCancel = () => {
|
||||
exportFileModel.value = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<span class="title">社会信息人员建设管理{{ title }} </span>
|
||||
<span class="title">力量建设管理{{ title }} </span>
|
||||
<div>
|
||||
<el-button type="primary" size="small" :loading="loading" @click="submit">保存</el-button>
|
||||
<el-button size="small" @click="close">关闭</el-button>
|
||||
@ -121,21 +121,25 @@ const validateIdentity = () => {
|
||||
const { proxy } = getCurrentInstance();
|
||||
const dialogForm = ref(false); //弹窗
|
||||
const formData = ref([
|
||||
{ label: "管辖部门", prop: "gxbmDm", type: "department" },
|
||||
{ label: "姓名", prop: "ryXm", type: "input" },
|
||||
{ label: "联系电话", prop: "ryLxdh", type: "input" },
|
||||
{ label: "身份证号", prop: "rySfzh", type: "input" },
|
||||
{ label: "出生日期", prop: "ryCsrq", type: "date" },
|
||||
{ label: "性别", prop: "ryXb", type: "select", options: props.dic.D_BZ_XB },
|
||||
{ label: "民族", prop: "ryMz", type: "select", options: props.dic.D_BZ_MZ },
|
||||
{ label: "学历", prop: "ryXl", type: "select", options: props.dic.D_BZ_WHCD },
|
||||
// { label: "力量编号", prop: "bh", type: "input", width: "30%" },
|
||||
{ label: "管辖部门", prop: "gxbmDm", type: "department", width: "30%" },
|
||||
{ label: "姓名", prop: "ryXm", type: "input", width: "30%" },
|
||||
{ label: "联系电话", prop: "ryLxdh", type: "input", width: "30%" },
|
||||
{ label: "身份证号", prop: "rySfzh", type: "input", width: "30%" },
|
||||
{ label: "出生日期", prop: "ryCsrq", type: "date", width: "30%" },
|
||||
{ label: "性别", prop: "ryXb", type: "select", options: props.dic.D_BZ_XB, width: "30%" },
|
||||
{ label: "民族", prop: "ryMz", type: "select", options: props.dic.D_BZ_MZ, width: "30%" },
|
||||
{ label: "学历", prop: "ryXl", type: "select", options: props.dic.D_BZ_WHCD, width: "30%" },
|
||||
{
|
||||
label: "政治面貌",
|
||||
prop: "ryZzmm",
|
||||
type: "select",
|
||||
options: props.dic.D_BZ_ZZMM
|
||||
options: props.dic.D_BZ_ZZMM, width: "30%"
|
||||
},
|
||||
{ label: "所在单位", prop: "rySzdw", type: "input" },
|
||||
{ label: "所在单位", prop: "rySzdw", type: "input", width: "30%" },
|
||||
{ label: "工作阵地", prop: "gzzd", type: "input" , width: "45%"},
|
||||
{ label: "作用发挥", prop: "zyfh", type: "input", width: "45%" },
|
||||
|
||||
{ label: "居住地地址", prop: "jzdDz", type: "textarea", width: "100%" }
|
||||
]);
|
||||
const listQuery = ref({}); //表单
|
||||
@ -144,15 +148,15 @@ const elform = ref();
|
||||
const title = ref("");
|
||||
const rules = reactive({
|
||||
gxbmDm: [{ required: true, message: "请选择管辖部门", trigger: "change" }],
|
||||
ryXm: [{ required: true, message: "请输入人员姓名", trigger: "blur" }],
|
||||
rySfzh: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入人员身份证号",
|
||||
trigger: ["blur", "change"]
|
||||
},
|
||||
{ trigger: ["blur", "change"], validator: validateIdentity() }
|
||||
],
|
||||
// ryXm: [{ required: true, message: "请输入人员姓名", trigger: "blur" }],
|
||||
// rySfzh: [
|
||||
// {
|
||||
// required: true,
|
||||
// message: "请输入人员身份证号",
|
||||
// trigger: ["blur", "change"]
|
||||
// },
|
||||
// { trigger: ["blur", "change"], validator: validateIdentity() }
|
||||
// ],
|
||||
...rule.phoneRule({ require: true, validator: true }, "ryLxdh") // 是否必填 是否进行校验 可以传第二个参数
|
||||
});
|
||||
onMounted(() => { });
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="社会信息人员建设管理">
|
||||
<PageTitle title="力量建设管理">
|
||||
<el-button type="primary" @click="addEdit('add', '')">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
@ -83,11 +83,14 @@ const pageData = reactive({
|
||||
},
|
||||
controlsWidth: 120,
|
||||
tableColumn: [
|
||||
{ label: "编号", prop: "bh" },
|
||||
{ label: "姓名", prop: "ryXm" },
|
||||
{ label: "联系电话", prop: "ryLxdh" },
|
||||
{ label: "身份证号", prop: "rySfzh" },
|
||||
{ label: "工作阵地", prop: "gzzd",showOverflowTooltip: true },
|
||||
{ label: "发挥作用", prop: "zyfh" ,showOverflowTooltip: true},
|
||||
{ label: "民族", prop: "ryMz", showSolt: true },
|
||||
{ label: "居住地址", prop: "jzdDz" }
|
||||
{ label: "居住地址", prop: "jzdDz",showOverflowTooltip: true }
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
@ -1,42 +1,53 @@
|
||||
<template>
|
||||
<el-dialog :title="title" width="800px" :model-value="modelShow" append-to-body @close="closed" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-form :model="listQuery" inline :rules="rules" ref="formRef" :label-width="130" >
|
||||
<el-form-item label="区域名称" prop="qymc">
|
||||
<MOSTY.Other width="100%" clearable v-model="listQuery.qymc" placeholder="请输入区域名称"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域类型" prop="qylx">
|
||||
<MOSTY.Select v-model="listQuery.qylx" filterable :dictEnum="props.dic.D_ZDY_QYLX" width="100%" clearable placeholder="请选择区域类型"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域级别" prop="qyjb">
|
||||
<MOSTY.Select v-model="listQuery.qyjb" filterable :dictEnum="props.dic.D_ZDY_QYJB" width="100%" clearable placeholder="请选择区域类型"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="行政区划" prop="xzqhdm" v-if="listQuery.qylx == 'xzqh'">
|
||||
<MOSTY.Select v-model="listQuery.xzqhdm" filterable :dictEnum="props.dic.D_BZ_XZQHDM" width="100%" clearable placeholder="请选择行政区划"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="地图范围" prop="pgis" class="ww100">
|
||||
<div class="flex ww100">
|
||||
<el-input v-model="listQuery.pgis" readonly placeholder="请输入地图范围" style="flex: 1;"></el-input>
|
||||
<el-button type="primary" style="width: 136px;" class="ml10" @click="chooseMap">
|
||||
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon>
|
||||
<span style="vertical-align: middle">选择地图范围</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="感知源信息" class="ww100">
|
||||
<div class="flex ww100">
|
||||
<div class="boo">
|
||||
<span v-if="!listQuery.sxts || listQuery.sxts.length == 0" class="f14 ml10" style="color: #e1e1e1;">感知源信息</span>
|
||||
<el-tag class="ml4 mr4" v-for="(it,idx) in listQuery.sxts" :key="idx">{{ it.sbmc }}</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div class="mapbox" v-if="showMap" v-loading="disabled"><GdMap></GdMap></div>
|
||||
<div class="mt10 flex just-center">
|
||||
<el-button @click="closed">取 消</el-button>
|
||||
<el-button type="primary" @click="submit" v-loading="loading">确 定</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<el-dialog :title="title" width="800px" :model-value="modelShow" append-to-body @close="closed"
|
||||
:destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-form :model="listQuery" inline :rules="rules" ref="formRef" :label-width="130">
|
||||
<el-form-item label="区域名称" prop="qymc">
|
||||
<MOSTY.Other width="100%" clearable v-model="listQuery.qymc" placeholder="请输入区域名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域类型" prop="qylx">
|
||||
<MOSTY.Select @change="changeMap" v-model="listQuery.qylx" filterable :dictEnum="props.dic.D_ZDY_QYLX"
|
||||
width="100%" clearable placeholder="请选择区域类型" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域级别" prop="qyjb">
|
||||
<MOSTY.Select v-model="listQuery.qyjb" filterable :dictEnum="props.dic.D_ZDY_QYJB" width="100%" clearable
|
||||
placeholder="请选择区域类型" />
|
||||
</el-form-item>
|
||||
<el-form-item label="行政区划" prop="xzqhdm" v-if="listQuery.qylx == 'xzqh'">
|
||||
<MOSTY.Select @change="changeXzqh" v-model="listQuery.xzqhdm" filterable :dictEnum="props.dic.D_BZ_XZQHDM"
|
||||
width="100%" clearable placeholder="请选择行政区划" />
|
||||
</el-form-item>
|
||||
<el-form-item label="地图范围" prop="pgis" class="ww100">
|
||||
<div class="flex ww100">
|
||||
<el-input v-model="listQuery.pgis" readonly placeholder="请输入地图范围" style="flex: 1;"></el-input>
|
||||
<el-button :disabled="listQuery.qylx == 'xzqh'" type="primary" style="width: 136px;" class="ml10" @click="chooseMap">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">选择地图范围</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="感知源信息" class="ww100">
|
||||
<div class="flex ww100">
|
||||
<div class="boo" @click="openDialog = true">
|
||||
<span v-if="!listQuery.sxts || listQuery.sxts.length == 0" class="f14 ml10"
|
||||
style="color: #e1e1e1;">感知源信息</span>
|
||||
<el-tag class="ml4 mr4" v-for="(it, idx) in listQuery.sxts" :key="idx">{{ it.sbmc }}</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div class="mapbox" v-if="showMap" v-loading="disabled">
|
||||
<GdMap></GdMap>
|
||||
</div>
|
||||
<div class="mt10 flex just-center">
|
||||
<el-button @click="closed">取 消</el-button>
|
||||
<el-button type="primary" @click="submit" v-loading="loading">确 定</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<ChooseGzy v-model="openDialog" @choose="chooseDataGzy" :roleIds="roleIds"/>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -44,137 +55,209 @@ import { qcckGet, qcckPost } from "@/api/qcckApi.js";
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import GdMap from "@/components/GdMap/index.vue";
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import { ref, defineProps, onMounted, nextTick ,onUnmounted} from "vue";
|
||||
import { ref, defineProps, onMounted, nextTick, onUnmounted } from "vue";
|
||||
import ChooseGzy from "@/components/ChooseList/ChooseGzy/index.vue";
|
||||
import { bm } from '../xzqh'
|
||||
const props = defineProps({
|
||||
dic: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
dic: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
});
|
||||
const disabled = ref(false)
|
||||
const loading = ref(false)
|
||||
const modelShow = ref(false);
|
||||
const emit = defineEmits(["change"]);
|
||||
const title = ref("新增区域");
|
||||
const listQuery = ref({sxts:[],pgis:[]});
|
||||
const listQuery = ref({ sxts: [], pgis: [] });
|
||||
const formRef = ref();
|
||||
const showMap = ref(false);
|
||||
const rules = {
|
||||
qymc: [{ required: true, message: "请输入区域名称", trigger: "blur" }],
|
||||
qylx: [{ required: true, message: "请选择区域类型", trigger: "change" }],
|
||||
qyjb: [{ required: true, message: "请选择区域级别", trigger: "change" }],
|
||||
xzqhdm: [{ required: true, message: "请选择行政区划", trigger: "change" }],
|
||||
pgis: [{ required: true, message: "请输入地图范围", trigger: ['change','blur'] }],
|
||||
sxts: [{ required: true, message: "请输入感知元信息", trigger: "blur" }],
|
||||
qymc: [{ required: true, message: "请输入区域名称", trigger: "blur" }],
|
||||
qylx: [{ required: true, message: "请选择区域类型", trigger: "change" }],
|
||||
qyjb: [{ required: true, message: "请选择区域级别", trigger: "change" }],
|
||||
xzqhdm: [{ required: true, message: "请选择行政区划", trigger: "change" }],
|
||||
pgis: [{ required: true, message: "请输入地图范围", trigger: ['change', 'blur'] }],
|
||||
sxts: [{ required: true, message: "请输入感知元信息", trigger: "blur" }],
|
||||
};
|
||||
|
||||
onMounted(()=>{
|
||||
emitter.on('coordString',val=>{
|
||||
if(val.flag == 'bkqy_ht') {
|
||||
listQuery.value.pgis = val.coord;
|
||||
emitter.emit('deletePointArea','gzy_ht');
|
||||
disabled.value = true;
|
||||
qcckPost({pgis:val.coord[0]},'/mosty-gsxt/tbGsxtBkQy/getSxtList').then(res=>{
|
||||
listQuery.value.sxts = res || [];
|
||||
let icon = require('@/assets/point/sp.png');
|
||||
emitter.emit('addPointArea',{flag:'gzy_ht',icon,coords:listQuery.value.sxts});
|
||||
disabled.value = false;
|
||||
}).catch(()=>{
|
||||
disabled.value = false;
|
||||
})
|
||||
}
|
||||
})
|
||||
onMounted(() => {
|
||||
emitter.on('coordString', val => {
|
||||
if (val.flag == 'bkqy_ht') {
|
||||
listQuery.value.pgis = val.coord;
|
||||
emitter.emit('deletePointArea', 'gzy_ht');
|
||||
disabled.value = true;
|
||||
qcckPost({ pgis: val.coord[0] }, '/mosty-gsxt/tbGsxtBkQy/getSxtList').then(res => {
|
||||
listQuery.value.sxts = res || [];
|
||||
let icon = require('@/assets/point/sp.png');
|
||||
emitter.emit('addPointArea', { flag: 'gzy_ht', icon, coords: listQuery.value.sxts });
|
||||
disabled.value = false;
|
||||
}).catch(() => {
|
||||
disabled.value = false;
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 初始化
|
||||
const init = (type,row) => {
|
||||
listQuery.value = {sxts:[],pgis:[]};
|
||||
title.value = type === "add" ? "新增区域" : "编辑区域";
|
||||
modelShow.value = true;
|
||||
nextTick(() => {
|
||||
showMap.value = true;
|
||||
});
|
||||
if(type === "edit") getDateById(row.id)
|
||||
const init = (type, row) => {
|
||||
listQuery.value = { sxts: [], pgis: [] };
|
||||
title.value = type === "add" ? "新增区域" : "编辑区域";
|
||||
modelShow.value = true;
|
||||
nextTick(() => {
|
||||
showMap.value = true;
|
||||
});
|
||||
if (type === "edit") getDateById(row.id)
|
||||
};
|
||||
|
||||
// 更具id获取数据
|
||||
const getDateById = (id) =>{
|
||||
qcckGet({id},'/mosty-gsxt/tbGsxtBkQy/selectByid').then(res=>{
|
||||
res.pgis = res.pgis ? [res.pgis]:[[[]]]
|
||||
let icon = require('@/assets/point/sp.png');
|
||||
nextTick(()=>{
|
||||
if(res.sxts && res.sxts.length > 0) emitter.emit('addPointArea',{flag:'gzy_ht',icon,coords:res.sxts});
|
||||
if(res.pgis){
|
||||
let obj = { position: res.pgis, text:'', id: res.id };
|
||||
emitter.emit("echoPlane", { coords: [obj], flag: "bkqy", type: "polygon" });
|
||||
}
|
||||
})
|
||||
listQuery.value = res || {};
|
||||
const getDateById = (id) => {
|
||||
qcckGet({ id }, '/mosty-gsxt/tbGsxtBkQy/selectByid').then(res => {
|
||||
res.pgis = res.pgis ? [res.pgis] : [[[]]]
|
||||
let icon = require('@/assets/point/sp.png');
|
||||
nextTick(() => {
|
||||
if (res.qylx=='xzqh') {
|
||||
emitter.emit('setBoundarys', {
|
||||
data: {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
geometry: {
|
||||
type: "Polygon", // 多边形类型
|
||||
coordinates: res.pgis // 坐标数组
|
||||
},
|
||||
properties: {}, // 属性信息
|
||||
type: "Feature", // 特征类型
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
if (res.sxts && res.sxts.length > 0) emitter.emit('addPointArea', { flag: 'gzy_ht', icon, coords: res.sxts });
|
||||
if (res.pgis) {
|
||||
let obj = { position: res.pgis, text: '', id: res.id };
|
||||
emitter.emit("echoPlane", { coords: [obj], flag: "bkqy", type: "polygon" });
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
listQuery.value = res || {};
|
||||
})
|
||||
}
|
||||
|
||||
// 地图选择
|
||||
const chooseMap = () =>{
|
||||
listQuery.value.pgis = [];
|
||||
listQuery.value.sxts = [];
|
||||
emitter.emit('removeEara','bkqy_ht')
|
||||
emitter.emit('deletePointArea','bkqy')
|
||||
emitter.emit('deletePointArea','gzy_ht')
|
||||
emitter.emit('drawShape',{type:'polygon',flag:'bkqy_ht'})
|
||||
const chooseMap = () => {
|
||||
listQuery.value.pgis = [];
|
||||
listQuery.value.sxts = [];
|
||||
emitter.emit('removeEara', 'bkqy_ht')
|
||||
emitter.emit('deletePointArea', 'bkqy')
|
||||
emitter.emit('deletePointArea', 'gzy_ht')
|
||||
emitter.emit('drawShape', { type: 'polygon', flag: 'bkqy_ht' })
|
||||
}
|
||||
|
||||
// 提交
|
||||
const submit = () => {
|
||||
formRef.value.validate(valid => {
|
||||
if(!valid) return false;
|
||||
loading.value = true;
|
||||
let params = { ...listQuery.value }
|
||||
params.pgis = params.pgis[0]
|
||||
let url = title.value == '新增区域' ? '/mosty-gsxt/tbGsxtBkQy/add' :'/mosty-gsxt/tbGsxtBkQy/update'
|
||||
qcckPost(params,url).then(res=>{
|
||||
loading.value = false;
|
||||
emit('change');
|
||||
closed();
|
||||
}).catch(()=>{
|
||||
loading.value = false;
|
||||
})
|
||||
});
|
||||
formRef.value.validate(valid => {
|
||||
if (!valid) return false;
|
||||
loading.value = true;
|
||||
let params = { ...listQuery.value }
|
||||
if (params.qylx == 'xzqh') {
|
||||
params.pgis = params.pgis
|
||||
} else {
|
||||
params.pgis = params.pgis[0]
|
||||
}
|
||||
let url = title.value == '新增区域' ? '/mosty-gsxt/tbGsxtBkQy/add' : '/mosty-gsxt/tbGsxtBkQy/update'
|
||||
qcckPost(params, url).then(res => {
|
||||
loading.value = false;
|
||||
emit('change');
|
||||
closed();
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
});
|
||||
};
|
||||
const closed = () => {
|
||||
emitter.emit('removeEara','bkqy_ht')
|
||||
emitter.emit('deletePointArea','gzy_ht')
|
||||
showMap.value = false;
|
||||
formRef.value.resetFields();
|
||||
modelShow.value = false;
|
||||
emitter.emit('removeEara', 'bkqy_ht')
|
||||
emitter.emit('deletePointArea', 'gzy_ht')
|
||||
showMap.value = false;
|
||||
roleIds.value=[]
|
||||
formRef.value.resetFields();
|
||||
modelShow.value = false;
|
||||
};
|
||||
const changeXzqh = (val) => {
|
||||
emitter.emit('removeBj')
|
||||
listQuery.value.pgis=bm[val]
|
||||
emitter.emit('setBoundarys', {
|
||||
data: {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
geometry: {
|
||||
type: "Polygon", // 多边形类型
|
||||
coordinates: [bm[val]] // 坐标数组
|
||||
},
|
||||
properties: {}, // 属性信息
|
||||
type: "Feature", // 特征类型
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
onUnmounted(()=>{
|
||||
emitter.off("coordString");
|
||||
})
|
||||
}
|
||||
|
||||
const changeMap = (val) => {
|
||||
if (val == 'xzqh') {
|
||||
emitter.emit('removeEara', 'bkqy_ht')
|
||||
emitter.emit('deletePointArea', 'bkqy')
|
||||
} else {
|
||||
emitter.emit('removeBj')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 感知源弹窗
|
||||
const openDialog = ref(false);
|
||||
const roleIds=ref([])
|
||||
const chooseDataGzy = (val) => {
|
||||
roleIds.value = val.map(item => item.id)
|
||||
listQuery.value.sxts = val.map(item => {
|
||||
return {
|
||||
sbbh:item.sbbh,
|
||||
sblx:item.sblx,
|
||||
sbmc:item.sbmc,
|
||||
}}
|
||||
)
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
emitter.off("coordString");
|
||||
})
|
||||
defineExpose({
|
||||
init
|
||||
init
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mapbox{
|
||||
position: relative;
|
||||
margin-left: 40px;
|
||||
width: calc(100% - 40px);
|
||||
height: 320px;
|
||||
background: red;
|
||||
.mapbox {
|
||||
position: relative;
|
||||
margin-left: 40px;
|
||||
width: calc(100% - 40px);
|
||||
height: 320px;
|
||||
background: red;
|
||||
}
|
||||
.boo{
|
||||
width: 100%;
|
||||
min-height: 32px;
|
||||
max-height: 74px;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
box-sizing: border-box;
|
||||
letter-spacing: 1px;
|
||||
|
||||
.boo {
|
||||
width: 100%;
|
||||
min-height: 32px;
|
||||
max-height: 74px;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
box-sizing: border-box;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -74,6 +74,7 @@ import Search from "@/components/aboutTable/Search.vue";
|
||||
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
import { bs } from './xzqh'
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_BZ_SF, D_ZDY_QYJB, D_ZDY_QYLX,D_BZ_XZQHDM } = proxy.$dict("D_BZ_SF","D_ZDY_QYJB","D_ZDY_QYLX","D_BZ_XZQHDM"); //获取字典数据
|
||||
const searchBox = ref(); //搜索框
|
||||
@ -133,6 +134,19 @@ const pageData = reactive({
|
||||
{ label: "是否启用", prop: "qyzt", showSolt: true }
|
||||
]
|
||||
});
|
||||
function stringTo2DArray(text) {
|
||||
const items = text.split(',').map(item => parseFloat(item));
|
||||
console.log(items);
|
||||
|
||||
return items.reduce((result, item, index) => {
|
||||
if (index % 2 === 0) {
|
||||
result.push([item]);
|
||||
} else {
|
||||
result[result.length - 1].push(item);
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
|
||||
76701
src/views/backOfficeSystem/IntelligentControl/DeploymentArea/xzqh.js
Normal file
76701
src/views/backOfficeSystem/IntelligentControl/DeploymentArea/xzqh.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div :class="dataOrge.gzlid?'ww80':'ww100'">
|
||||
<div :class="dataOrge.gzlid ? 'ww80' : 'ww100'">
|
||||
<div class="form_cnt">
|
||||
<el-form :model="listQuery" :rules="rules" :disabled="disabled" ref="elform" inline :label-width="100"
|
||||
label-position="left">
|
||||
@ -56,14 +56,29 @@
|
||||
</template>
|
||||
</MyTable>
|
||||
</div>
|
||||
|
||||
<div class="smallTitle">布控范围</div>
|
||||
<div class=" mapSearch flex">
|
||||
<el-select v-model="hzfs" placeholder="请选择布控范围" clearable @change="qhhzfs">
|
||||
<el-option label="区域选择" value="1"></el-option>
|
||||
<el-option label="自定义范围" value="2"></el-option>
|
||||
</el-select>
|
||||
<el-select multiple style="margin-left: 10px;" v-model="bkqyList" placeholder="请选择布控范围" clearable
|
||||
@change="hzfsChage" v-if="hzfs == '1'">
|
||||
<el-option :label="item.label" :value="item.value" v-for="(item, index) in bkqyArr" :key="index">{{
|
||||
item.label
|
||||
}}</el-option>
|
||||
</el-select>
|
||||
<!-- <MOSTY.Select v-model="listQuery.bkqyList" filterable multiple :dictEnum="bkqyArr" style="width:350px"
|
||||
placeholder="请选择布控范围" clearable /> -->
|
||||
<el-button type="primary" @click="drawQy" style="margin-left: 10px;" v-else>
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">自定义区域</span>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="ww100 relative mb10"
|
||||
style="height: 250px;border: 1px solid #dcdfe6;border-radius: 4px;overflow: hidden;">
|
||||
<div class="absolute mapSearch flex">
|
||||
<MOSTY.Select v-model="listQuery.bkqyList" filterable multiple :dictEnum="bkqyArr" style="width:350px"
|
||||
placeholder="请选择布控范围" clearable />
|
||||
</div>
|
||||
<GdMap></GdMap>
|
||||
</div>
|
||||
<!-- <el-form-item prop="bkBt" label="布控要素" style="width: 100%;">
|
||||
@ -110,37 +125,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ww20" v-if="dataOrge.gzlid">
|
||||
<!-- <div class="smallTitle">审批信息</div>
|
||||
<div class="ww100">
|
||||
<el-steps :active="listQuery.wccz" space="500" finish-status="success" direction="vertical" status=''>
|
||||
<el-step :title="item.eventType == '0' ? '发起申请' : item.eventType == '1' ? '审批结束' : item.nodeName"
|
||||
v-for="(item, index) in workflow" :key="index">
|
||||
<template #description>
|
||||
<div class="ww100 mt10 mb20 nodeBox" v-if="item.eventType == '0'||item.eventType == '1'">
|
||||
<div class="nodeorgNameTg">{{ item.log.userData.orgname }}</div>
|
||||
<div class="flex just-between nameTag">
|
||||
<div>{{ item.log.userName }}</div>
|
||||
<div class="fontColor">{{ item.eventType == '0' ? '发起' : '结束' }}</div>
|
||||
</div>
|
||||
<div>{{ item.log.xtLrsj }}</div>
|
||||
</div>
|
||||
<div v-else class="ww100 mt10 mb20 nodeBox">
|
||||
<div :class="item.taskStatus=='2'?'nodeorgNameTg':'nodeorgNameDd'">{{ item.orgNameData.orgname }}</div>
|
||||
<div v-for="(items, indexs) in item.log" :key="indexs">
|
||||
<div class="flex just-between nameTag" >
|
||||
<div>{{ items.userName }}</div>
|
||||
<div :class="item.taskStatus=='2'?'fontColor':'fontColorDd'">审批中</div>
|
||||
</div>
|
||||
<div>{{ items.xtLrsj }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</el-step>
|
||||
|
||||
</el-steps>
|
||||
</div> -->
|
||||
<ApprovalEcho ref="approvalEcho"/>
|
||||
<ApprovalEcho ref="approvalEcho" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -168,11 +153,12 @@ import GdMap from "@/components/GdMap/index.vue";
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
|
||||
import { tableColumnList,Zd } from '@/views/backOfficeSystem/ApprovalInformation/tableRow.js'
|
||||
|
||||
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, nextTick, watch } from "vue";
|
||||
import { tableColumnList, Zd } from '@/views/backOfficeSystem/ApprovalInformation/tableRow.js'
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { ref, defineExpose, reactive, defineEmits, getCurrentInstance, nextTick, watch, onMounted } from "vue";
|
||||
import { queryProcessNode, queryProcessNodeLog, queryProcess } from '@/api/spl'
|
||||
import ApprovalEcho from "@/components/flowPath/ApprovalEcho.vue";
|
||||
import { tbGsxtBkId } from "@/api/commit.js";
|
||||
const emit = defineEmits(["change"]);
|
||||
const props = defineProps({
|
||||
dic: Object
|
||||
@ -228,6 +214,7 @@ let tableDate = reactive({
|
||||
{ label: "标签", prop: "bqList", showSolt: true, showOverflowTooltip: true }
|
||||
]
|
||||
});
|
||||
|
||||
const title = ref('')
|
||||
const disabled = ref(false)
|
||||
// 初始化数据
|
||||
@ -237,11 +224,7 @@ const init = (type, row) => {
|
||||
tableDate.tableConfiger.haveControls = true;
|
||||
disabled.value = false;
|
||||
listQuery.value.bkfqrXm = getItem("USERNAME");
|
||||
console.log(getItem("USERNAME"));
|
||||
|
||||
listQuery.value.bkfqrSfzh = getItem("idEntityCard");
|
||||
console.log( getItem("USERID"));
|
||||
console.log( getItem("idEntityCard"));
|
||||
listQuery.value.bkfqrSsbmmc = getItem("deptId")[0].deptName;;
|
||||
listQuery.value.bkfqrSsbmdm = getItem("deptId")[0].deptCode;;
|
||||
}
|
||||
@ -249,7 +232,7 @@ const init = (type, row) => {
|
||||
disabled.value = type == 'detail' ? true : false;
|
||||
dialogForm.value = true;
|
||||
if (row) tableDate.tableConfiger.haveControls = false;
|
||||
Zd({D_GS_BK_DJ:props.dic.D_GS_BK_DJ,BD_BK_CLYJBQ:props.dic.BD_BK_CLYJBQ})
|
||||
Zd({ D_GS_BK_DJ: props.dic.D_GS_BK_DJ, BD_BK_CLYJBQ: props.dic.BD_BK_CLYJBQ })
|
||||
|
||||
get_bkqy_list(row)
|
||||
};
|
||||
@ -264,32 +247,23 @@ const get_bkqy_list = (row) => {
|
||||
if (row) getDataById(row.id);
|
||||
})
|
||||
}
|
||||
const dataOrge=ref({})
|
||||
const dataOrge = ref({})
|
||||
const approvalEcho = ref()
|
||||
watch(() => approvalEcho.value, (val) => {
|
||||
if (val) {
|
||||
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
|
||||
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
|
||||
}
|
||||
|
||||
},{deep:true})
|
||||
}, { deep: true })
|
||||
|
||||
|
||||
// 根据id获取详情
|
||||
const getDataById = (id) => {
|
||||
qcckGet({}, '/mosty-gsxt/tbGsxtBk/selectVoById/' + id).then(res => {
|
||||
res.bkfj = res.ossList || [];
|
||||
res.bkqyList = res.qyList ? res.qyList.map(v => v.id) : [];
|
||||
listQuery.value = res || {}
|
||||
dataOrge.value=res
|
||||
tableDate.tableColumn = tableColumnList[res.bkDx ? res.bkDx : '01']
|
||||
})
|
||||
}
|
||||
watch(() => approvalEcho.value, (val) => {
|
||||
if (val) {
|
||||
console.log(approvalEcho.value);
|
||||
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
|
||||
approvalEcho.value.getWorkflow(dataOrge.value.gzlid)
|
||||
}
|
||||
|
||||
},{deep:true})
|
||||
}, { deep: true })
|
||||
|
||||
|
||||
const shangeDx = () => {
|
||||
@ -342,7 +316,7 @@ const choosed = (val) => {
|
||||
id: item.id, fjZp: item.fjZp, ryXm: item.ryXm, ryXb: item.ryXb,
|
||||
rySfzh: item.rySfzh, ryHjd: item.hjdXz, ryXjd: item.xzdXz,
|
||||
rySjhm: item.ryLxdh, qtXnsf: item.qtXnsf, clCjh: item.clCjh,
|
||||
clCph: item.clCph, qtTzms: item.qtTzms, bqList: bqs, yjdj: item.zdrYjdj,ssbmdm:item.zrSsbmdm
|
||||
clCph: item.clCph, qtTzms: item.qtTzms, bqList: bqs, yjdj: item.zdrYjdj, ssbmdm: item.zrSsbmdm
|
||||
}
|
||||
})
|
||||
listQuery.value.bkdxList = [...addPerson.value, ...arr];
|
||||
@ -352,7 +326,7 @@ const choosed = (val) => {
|
||||
|
||||
return {
|
||||
clCph: item.hphm, clCjh: item.clCjh, clSyr: item.clSyr, clSyrsfzh: item.clSyrsfzh,
|
||||
clYs: item.clYs, gxSsbmmc: item.gxSsbmmc,yjbq: item.yjbq, yjdj: item.yjdj,ssbmdm:item.zrSsbmdm
|
||||
clYs: item.clYs, gxSsbmmc: item.gxSsbmmc, yjbq: item.yjbq, yjdj: item.yjdj, ssbmdm: item.zrSsbmdm
|
||||
}
|
||||
})
|
||||
listQuery.value.bkdxList = [...addPerson.value, ...arr];
|
||||
@ -374,7 +348,7 @@ const choosed = (val) => {
|
||||
rySfzh: item.rySfzh, ryHjd: item.hjdXz, ryXjd: item.xzdXz,
|
||||
rySjhm: item.ryLxdh, qtXnsf: item.qtXnsf, clCjh: item.clCjh,
|
||||
clCph: item.clCph, qtTzms: item.qtTzms, bqList: bqs,
|
||||
yjdj: item.zdrYjdj,ssbmdm:item.zrSsbmdm
|
||||
yjdj: item.zdrYjdj, ssbmdm: item.zrSsbmdm
|
||||
}
|
||||
})
|
||||
listQuery.value.bkdxList = brrPeo;
|
||||
@ -427,7 +401,13 @@ const submit = () => {
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
emitter.on("coordString", (res) => {
|
||||
listQuery.value.bkqyList = [{
|
||||
pgis: res.coord[0],
|
||||
}]
|
||||
});
|
||||
});
|
||||
// 关闭
|
||||
const close = () => {
|
||||
listQuery.value = {};
|
||||
@ -435,7 +415,7 @@ const close = () => {
|
||||
loading.value = false;
|
||||
addPerson.value = [];
|
||||
roleIds.value = []
|
||||
dataOrge.value={}
|
||||
dataOrge.value = {}
|
||||
};
|
||||
// 选择身份证
|
||||
const chooseVisible_SFZ = ref(false)
|
||||
@ -468,11 +448,103 @@ const getWorkflow = async (id) => {
|
||||
log: log
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
};
|
||||
const drawQy = () => {
|
||||
emitter.emit("drawShape", {
|
||||
flag: "select_point",
|
||||
type: "polygon",
|
||||
isclear: true
|
||||
});
|
||||
}
|
||||
const hzfs = ref('1')
|
||||
const bkqyList = ref()
|
||||
const qhhzfs = () => {
|
||||
listQuery.value.bkqyList = []
|
||||
bkqyList.value = []
|
||||
emitter.emit('removeBj')
|
||||
emitter.emit('removeEara', "select_point")
|
||||
}
|
||||
|
||||
const hzfsChage = (val) => {
|
||||
const qyList = []
|
||||
console.log(val);
|
||||
|
||||
listQuery.value.bkqyList = val.map((item, index) => {
|
||||
const data = bkqyArr.value.filter(items => items.id == item)[0]
|
||||
console.log(data);
|
||||
|
||||
if (data) {
|
||||
qyList.push(data.pgis)
|
||||
}
|
||||
console.log(item);
|
||||
return {
|
||||
bkQyid: data.id,
|
||||
pgis: data.pgis
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
changeXzqh(qyList)
|
||||
}, 2000)
|
||||
}
|
||||
const changeXzqh = (val) => {
|
||||
// 先移除已有的边界
|
||||
emitter.emit('removeBj')
|
||||
// 如果传入的是多个区域数据(二维数组)
|
||||
const features = val.map((area, index) => ({
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [area] // 确保格式正确
|
||||
},
|
||||
properties: {
|
||||
},
|
||||
type: "Feature"
|
||||
}))
|
||||
// 循环为每个区域创建单独的多边形,这样可以设置不同的样式
|
||||
features.forEach((feature, index) => {
|
||||
emitter.emit('setBoundarys', {
|
||||
data: {
|
||||
type: "FeatureCollection",
|
||||
features: [feature]
|
||||
},
|
||||
color: '#cf1010',
|
||||
fillColor: 'rgba(255, 255, 255,0)',
|
||||
})
|
||||
})
|
||||
}
|
||||
// 根据id获取详情
|
||||
const getDataById = (id) => {
|
||||
qcckGet({}, '/mosty-gsxt/tbGsxtBk/selectVoById/' + id).then(res => {
|
||||
res.bkfj = res.ossList || [];
|
||||
listQuery.value = res || {}
|
||||
dataOrge.value = res
|
||||
if (res.bkqyList) {
|
||||
bkqyList.value = res.bkqyList ? res.bkqyList.map(v => {
|
||||
{
|
||||
if (v.bkQyid) {
|
||||
hzfs.value = '1'
|
||||
} else {
|
||||
hzfs.value = '2'
|
||||
}
|
||||
return v.bkQyid
|
||||
}
|
||||
|
||||
}) : [];
|
||||
const data = res.bkqyList.map(item => {
|
||||
return item.pgis
|
||||
})
|
||||
setTimeout(() => {
|
||||
console.log(data);
|
||||
changeXzqh(data)
|
||||
// listQuery.value.bkDxxx = data.join(',')
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
|
||||
tableDate.tableColumn = tableColumnList[res.bkDx ? res.bkDx : '01']
|
||||
})
|
||||
}
|
||||
defineExpose({ init });
|
||||
</script>
|
||||
|
||||
@ -489,9 +561,8 @@ defineExpose({ init });
|
||||
}
|
||||
|
||||
.mapSearch {
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
z-index: 100;
|
||||
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
@ -538,9 +609,11 @@ defineExpose({ init });
|
||||
color: #000000 !important;
|
||||
border-color: #000000 !important;
|
||||
}
|
||||
::v-deep .el-step__description{
|
||||
|
||||
::v-deep .el-step__description {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
::v-deep .el-step__description.is-wait {
|
||||
|
||||
color: #000000 !important;
|
||||
@ -584,7 +657,9 @@ defineExpose({ init });
|
||||
|
||||
.fontColor {
|
||||
color: #1abe20;
|
||||
} .fontColorDd {
|
||||
}
|
||||
|
||||
.fontColorDd {
|
||||
color: #18a2dd;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<!-- 直接使用box作为根元素,减少嵌套层级 -->
|
||||
<div class="box" ref="chartDom" style="width: 100%; margin: 0; padding: 0;"></div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, watch } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
let chartDom = ref(null); //注意变量名 和 ref名字要对应
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '2023年1月1日至2023年12月31日'
|
||||
},
|
||||
xAxisData: {
|
||||
type: Array,
|
||||
default: () => ['A', 'B', 'C', 'D', 'E', 'F']
|
||||
},
|
||||
seriesData: {
|
||||
type: Array,
|
||||
default: () => [[2549], [12421], [2637],[ 3146],[ 15189], [9562]]
|
||||
},
|
||||
// yAxisData: {
|
||||
// type: Array,
|
||||
// default: () => [2549, 12421, 2637, 3146, 15189, 9562]
|
||||
// },
|
||||
});
|
||||
|
||||
// 保存图表实例的引用
|
||||
const myChart = ref(null);
|
||||
let resizeTimer = null;
|
||||
const chartInstance = ref(null);
|
||||
onMounted(() => {
|
||||
// 确保DOM渲染完成后再初始化图表
|
||||
setTimeout(() => {
|
||||
initChart();
|
||||
}, 0);
|
||||
|
||||
// 监听窗口大小变化,确保图表能正确调整大小
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// 组件卸载时清理监听器
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
if (resizeTimer) {
|
||||
clearTimeout(resizeTimer);
|
||||
}
|
||||
// 销毁图表实例
|
||||
if (myChart.value) {
|
||||
myChart.value.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
// 处理窗口大小变化的函数
|
||||
const handleResize = () => {
|
||||
// 防抖处理,避免频繁调用
|
||||
if (resizeTimer) {
|
||||
clearTimeout(resizeTimer);
|
||||
}
|
||||
resizeTimer = setTimeout(() => {
|
||||
// 如果图表实例存在,调用resize方法
|
||||
if (myChart.value) {
|
||||
myChart.value.resize();
|
||||
}
|
||||
}, 200);
|
||||
};
|
||||
watch([
|
||||
() => props.seriesData,
|
||||
() => props.xAxisData,
|
||||
], () => {
|
||||
initChart();
|
||||
},{deep:true});
|
||||
const initChart = () => {
|
||||
chartInstance.value = props.seriesData.map((item, index) => {
|
||||
return {
|
||||
name: props.xAxisData[index],
|
||||
data: item,
|
||||
type: "bar",
|
||||
barWidth: "20",
|
||||
// barGap: 20, // 系列之间的间距
|
||||
barCategoryGap: '20%', // 使用百分比更适应不同宽度
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: function (params) {
|
||||
// 值为0或null时不显示
|
||||
if (params.value === 0 || params.value === null) {
|
||||
return '';
|
||||
}
|
||||
// 格式化数值显示
|
||||
return params.value.toLocaleString();
|
||||
},
|
||||
color: '#2c3e50',
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
distance: 10 // 标签与柱子的距离
|
||||
},
|
||||
}
|
||||
})
|
||||
// 保存图表实例以便后续调用resize
|
||||
myChart.value = echarts.init(chartDom.value);
|
||||
// 重置容器大小确保占满
|
||||
chartDom.value.style.width = '100%';
|
||||
|
||||
var option = {
|
||||
title: {
|
||||
text: props.title,
|
||||
left: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
// 鼠标悬浮提示数据
|
||||
trigger: "axis",
|
||||
backgroundColor: "rgba(32, 33, 36,.7)",
|
||||
borderColor: "rgba(32, 33, 36,0.20)",
|
||||
borderWidth: 15,
|
||||
textStyle: {
|
||||
// 文字提示样式
|
||||
color: "#fff",
|
||||
fontSize: "12",
|
||||
},
|
||||
axisPointer: {
|
||||
// 坐标轴虚线
|
||||
type: "cross",
|
||||
label: {
|
||||
backgroundColor: "#6a7985",
|
||||
},
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
right: 0
|
||||
},
|
||||
// },
|
||||
grid: {
|
||||
// 控制图表的位置,设置为最紧凑以占满整个容器
|
||||
left: "2%",
|
||||
right: "2%",
|
||||
top: "15%",
|
||||
bottom: "3%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
data: props.xAxisData,
|
||||
},
|
||||
yAxis: {
|
||||
// axisLabel: {
|
||||
// // y轴线 标签修改
|
||||
// textStyle: {
|
||||
// color: "white", //坐标值得具体的颜色
|
||||
// },
|
||||
// },
|
||||
// data: props.xAxisData,
|
||||
},
|
||||
series: chartInstance.value
|
||||
};
|
||||
myChart.value.setOption(option);
|
||||
|
||||
// 初始时强制调整大小,确保完全适应容器
|
||||
setTimeout(() => {
|
||||
if (myChart.value) {
|
||||
myChart.value.resize();
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 根容器样式,确保完全占满父容器 */
|
||||
.box {
|
||||
width: 100% !important;
|
||||
height: 60vh;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
box-sizing: border-box !important;
|
||||
display: block !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
/* 确保ECharts实例占满容器 */
|
||||
:deep(.echarts) {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
min-width: 0 !important;
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
/* 为父级元素设置样式,确保没有额外的内边距 */
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/* 防止任何默认的边距或内边距影响 */
|
||||
* {
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<!-- 将固定id改为ref引用 -->
|
||||
<div ref="chartContainer" style="height: 100%;"></div>
|
||||
</template>
|
||||
<script setup>
|
||||
import * as echarts from 'echarts';
|
||||
import { onMounted, onUnmounted, ref, watch, defineProps } from 'vue';
|
||||
|
||||
// 定义组件的属性,使其可复用
|
||||
const props = defineProps({
|
||||
// 图表数据
|
||||
chartData: {
|
||||
type: Array,
|
||||
default: () => [
|
||||
{ value: 40, name: 'rose 1' },
|
||||
{ value: 38, name: 'rose 2' },
|
||||
{ value: 32, name: 'rose 3' },
|
||||
{ value: 30, name: 'rose 4' },
|
||||
{ value: 28, name: 'rose 5' },
|
||||
{ value: 26, name: 'rose 6' },
|
||||
{ value: 22, name: 'rose 7' },
|
||||
{ value: 18, name: 'rose 8' }
|
||||
]
|
||||
},
|
||||
// 图表标题
|
||||
chartName: {
|
||||
type: String,
|
||||
default: 'Nightingale Chart'
|
||||
},
|
||||
// 是否显示工具箱
|
||||
showToolbox: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否显示图例
|
||||
showLegend: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 内半径
|
||||
innerRadius: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 外半径
|
||||
outerRadius: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
// 扇形间距
|
||||
padAngle: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
title: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
text: 'Nightingale Chart',
|
||||
left: 'center'
|
||||
})
|
||||
},
|
||||
roseType: {
|
||||
type: String,
|
||||
default: 'radius'
|
||||
}
|
||||
});
|
||||
|
||||
// 图表容器引用
|
||||
const chartContainer = ref(null);
|
||||
// 图表实例引用
|
||||
const chartInstance = ref(null);
|
||||
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
const chartDom = chartContainer.value;
|
||||
if (!chartDom) return;
|
||||
|
||||
// 如果已经存在实例,先销毁
|
||||
if (chartInstance.value) {
|
||||
chartInstance.value.dispose();
|
||||
}
|
||||
|
||||
// 创建新实例
|
||||
chartInstance.value = echarts.init(chartDom);
|
||||
|
||||
// 设置图表选项
|
||||
const option = {
|
||||
title: props.title,
|
||||
legend: props.showLegend ? {
|
||||
top: 'bottom'
|
||||
} : false,
|
||||
toolbox: props.showToolbox ? {
|
||||
show: true,
|
||||
feature: {
|
||||
mark: { show: true },
|
||||
dataView: { show: true, readOnly: false },
|
||||
restore: { show: true },
|
||||
saveAsImage: { show: true }
|
||||
}
|
||||
} : false,
|
||||
series: [
|
||||
{
|
||||
name: props.chartName,
|
||||
type: 'pie',
|
||||
radius: [props.innerRadius, props.outerRadius],
|
||||
center: ['50%', '50%'],
|
||||
roseType: props.roseType,
|
||||
// 在 ECharts 5.3.3 中,当 roseType 为 'area' 时,padAngle 需要特殊处理
|
||||
// 为了确保间距生效,我们需要添加一个小的非零值来替代0
|
||||
// padAngle: props.padAngle === 0 ? 0.1 : props.padAngle,
|
||||
itemStyle: {
|
||||
borderColor: '#fff',
|
||||
borderWidth:props.padAngle
|
||||
},
|
||||
// 显示百分比
|
||||
label: {
|
||||
show: true,
|
||||
formatter: function(params) {
|
||||
// 对于值为0的项,显示0%而不是极小值计算出的百分比
|
||||
if (props.chartData.find(d => d.name === params.name && d.value === 0)) {
|
||||
return params.name + ': 0%';
|
||||
}
|
||||
return params.name + ': ' + params.percent + '%';
|
||||
}
|
||||
},
|
||||
// 鼠标悬停时的样式
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '16',
|
||||
fontWeight: 'bold',
|
||||
formatter: function(params) {
|
||||
// 对于值为0的项,显示0%而不是极小值计算出的百分比
|
||||
if (props.chartData.find(d => d.name === params.name && d.value === 0)) {
|
||||
return params.name + ': 0%';
|
||||
}
|
||||
return params.name + ': ' + params.percent + '%';
|
||||
}
|
||||
}
|
||||
},
|
||||
// 处理数据,确保值为0的项也能显示
|
||||
data: props.chartData.map(item => ({
|
||||
...item,
|
||||
// 对于值为0的数据,设置一个极小值来确保它在饼图中显示
|
||||
value: item.value === 0 ? 0.0000001 : item.value
|
||||
}))
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 应用选项
|
||||
chartInstance.value.setOption(option);
|
||||
};
|
||||
|
||||
// 处理窗口大小变化,自动调整图表大小
|
||||
const handleResize = () => {
|
||||
if (chartInstance.value) {
|
||||
chartInstance.value.resize();
|
||||
}
|
||||
};
|
||||
|
||||
// 组件挂载时初始化图表
|
||||
onMounted(() => {
|
||||
initChart();
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// 组件卸载时销毁图表实例并移除事件监听
|
||||
onUnmounted(() => {
|
||||
if (chartInstance.value) {
|
||||
chartInstance.value.dispose();
|
||||
}
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// 监听数据变化,更新图表
|
||||
watch(() => props.chartData, () => {
|
||||
initChart();
|
||||
}, { deep: true });
|
||||
|
||||
// 监听其他配置变化,更新图表
|
||||
watch([
|
||||
() => props.chartName,
|
||||
() => props.showToolbox,
|
||||
() => props.showLegend,
|
||||
() => props.innerRadius,
|
||||
() => props.outerRadius,
|
||||
() => props.padAngle,
|
||||
()=> props.roseType,
|
||||
], () => {
|
||||
initChart();
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
:deep(div) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* min-height: 400px; */
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,441 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- <div class="titleBox">
|
||||
<PageTitle title="警情分析报告">
|
||||
<el-button type="primary" @click="generatePDF()">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">导出</span>
|
||||
</el-button>
|
||||
</PageTitle>
|
||||
</div> -->
|
||||
<!-- 搜索 -->
|
||||
<!-- <div ref="searchBox">
|
||||
<Search :searchArr="searchConfiger" @submit="onSearch">
|
||||
<template #defaultSlot>
|
||||
<el-select v-model="bjlbList" placeholder="请选择情报类型" multiple collapse-tags>
|
||||
<el-option v-for="item in dictItemList" :key="item.dm" :label="item.zdmc" :value="item.dm" />
|
||||
</el-select>
|
||||
</template>
|
||||
</Search>
|
||||
</div> -->
|
||||
<div style="background-color: #fff;color: black;padding: 15px;overflow: auto;" :style="{ height: tabHeight + 'px' }"
|
||||
ref="tableBox">
|
||||
<div style="border-bottom: 1px #ccc solid;padding-bottom: 30px;">
|
||||
<h1 class="headline">{{ nd }}年度西藏公安战术研判报告</h1>
|
||||
<div style="display: flex;align-items: center;justify-content: space-between; color: red;margin-top: 30px;padding: 0 30px;font-size: 18px;font-weight: 700;">
|
||||
<div>{{ deptId.name }}</div>
|
||||
<div>{{ deptId?.ord }}</div>
|
||||
<div>{{ deptId?.time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>为全面、客观、准确掌握全区公安机关的执法状况,自治区
|
||||
公安厅基于数据统计,对全区公安机关{{ nd }}年度的执法状况作
|
||||
了客观分析。</p>
|
||||
<h2>一、执法状况总体分析</h2>
|
||||
<h2>1.接处警情况</h2>
|
||||
<h2>1.1接报警情</h2>
|
||||
<p>
|
||||
{{ timeValidate(TimeValue.startTime, 'td') }}至{{ timeValidate(TimeValue.endTime, 'td') }}
|
||||
,全区公安机关共
|
||||
接报各类警情{{ dataList.XsfxTj.total }}起,同比{{ `${dataList.XsfxTj.tbbsb > 0 ? "下降" : "上升"}
|
||||
${dataList.XsfxTj.tbbsb}%,同比${dataList.XsfxTj.tbbsb > 0 ? "下降" : "上升"}${dataList.XsfxTj.tbbsb}%` }}。</p>
|
||||
<h2>1.1.1类型维度</h2>
|
||||
<p>
|
||||
从警情类型来看,{{ sortingRatioValue.Ydfx[0]?.name }}警情最多,占到{{ sortingRatioValue.Ydfx[0]?.ratio }};其次为{{
|
||||
sortingRatioValue.Ydfx[1]?.name }}警情,占到{{ sortingRatioValue.Ydfx[1]?.ratio }}。
|
||||
</p>
|
||||
<MaleNightingalePicture roseType="area" style="height: 550px;" :title="{ text: '接警情类型', left: 'center' }"
|
||||
:chartData="dataList.jqlxTj" :chartName="'接警情类型'" :innerRadius="0" :padAngle="4" />
|
||||
<h2>1.1.2来源维度</h2>
|
||||
<p>
|
||||
从警情来源来看,{{ sortingRatioValue.Jqlx[0]?.name }}警情最多,占到{{ sortingRatioValue.Jqlx[0]?.ratio }};其次为{{
|
||||
sortingRatioValue.Jqlx[1]?.name }}警情,占到{{ sortingRatioValue.Jqlx[1]?.ratio }}。
|
||||
</p>
|
||||
<MaleNightingalePicture roseType="area" :title="{ text: '警情来源', left: 'center' }" style="height: 550px;"
|
||||
:chartData="dataList.jqlyTj" :innerRadius="50" :outerRadius="150" :padAngle="4" />
|
||||
|
||||
<h2>1.1.3地域维度</h2>
|
||||
<p>从地市分布地市来看,{{ sortingRatioValue.Dywdtj[0]?.ssbm }}警情量最大,占到全区警情总
|
||||
量的{{ sortingRatioValue.Dywdtj[0]?.ratio }}。
|
||||
<span v-if="sortingRatioValue.Dywdtj.length > 1">
|
||||
其次为{{ sortingRatioValue.Dywdtj[1]?.ssbm }}
|
||||
<span v-if="sortingRatioValue.Dywdtj.length > 2">
|
||||
<span v-if="sortingRatioValue.Dywdtj.length > 3">
|
||||
和{{ sortingRatioValue.Dywdtj[3]?.ssbm }},两市警情量较为接近。
|
||||
</span>
|
||||
<span>
|
||||
警情量最少的为{{ sortingRatioValue.Dywdtj[sortingRatioValue.Dywdtj.length - 1]?.ssbm }}。
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
<Histogram title="地市分布" :xAxisData="dataList.dyTj.xAxisData" :seriesData="dataList.dyTj.seriesData" />
|
||||
<h2>1.1.4时间维度</h2>
|
||||
<p>
|
||||
我们将所有警情按照月份划分进行统计发现,每月警情分布
|
||||
较为平均。最高月份为
|
||||
{{ sortingRatioValue.Ydfx[0]?.month }}月,占到{{ sortingRatioValue.Ydfx[0]?.ratio }};
|
||||
<span v-if="sortingRatioValue.Ydfx.length > 1">
|
||||
最低月份为{{ sortingRatioValue.Ydfx[sortingRatioValue.Ydfx.length - 1]?.month }}月,
|
||||
占到{{ sortingRatioValue.Ydfx[sortingRatioValue.Ydfx.length - 1]?.ratio }}。
|
||||
考虑是因为{{ sortingRatioValue.Ydfx[0]?.month }}月为我区传统旅游旺季,进藏人员较多。
|
||||
<!-- {{sortingRatioValue.Ydfx[sortingRatioValue.Ydfx.length-1]?.month}}月一般春节及藏历新年期间,在藏人员较少。 -->
|
||||
</span>
|
||||
</p>
|
||||
<MaleNightingalePicture :title="{ text: '警情分布', left: 'center' }" style="height: 550px;"
|
||||
:chartData="dataList.ydTj" :innerRadius="10" :outerRadius="150" :padAngle="2" />
|
||||
<!-- <p>
|
||||
按照24小时每小时时段进行划分后发现,警情多发时段集
|
||||
中在9时至20时,每小时均在1000起以上。
|
||||
</p> -->
|
||||
<h2>1.2警情处置</h2>
|
||||
<h2>1.2.1结果维度</h2>
|
||||
<p>
|
||||
从警情处置结果来看,
|
||||
<span v-for="(item, index) in sortingRatioValue.Cljgf">
|
||||
{{ `${item.name}占到${item.ratio},` }}
|
||||
</span>
|
||||
</p>
|
||||
<MaleNightingalePicture :title="{ text: '警情处置', left: 'center' }" style="height: 550px;"
|
||||
:chartData="dataList.CljgfTj" :innerRadius="0" :outerRadius="150" :padAngle="2" />
|
||||
<h2>1.2.2效率维度</h2>
|
||||
<p>从处警效率来看,{{ sortingRatioValue.Czlfx[1]?.name }}处警的,占到{{ sortingRatioValue.Czlfx[0]?.ratio
|
||||
}}。表明我区公安机关在接警之后能够在第一时间处警。
|
||||
</p>
|
||||
<MaleNightingalePicture :title="{ text: '效率维度', left: 'center' }" style="height: 550px;"
|
||||
:chartData="dataList.withinTj" :innerRadius="0" :outerRadius="150" :padAngle="0" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<AddForm ref="addForm" :dict="{ D_GS_XS_LX }" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import MaleNightingalePicture from './components/maleNightingalePicture.vue'
|
||||
import Histogram from './components/histogram.vue'
|
||||
import { timeValidate } from '@/utils/tools.js'
|
||||
import { getItem, setItem } from '@/utils/storage'
|
||||
import { fxbgDywdtj, getDictItem, fxbgJqlxtj, fxbgJqlytj, fxbgYdfx, fxbgXsfx, fxgbCljgf, fxgbCzlfx, fxbgTj } from '@/api/semanticAnalysis'
|
||||
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
|
||||
import { reactive, ref, onMounted, getCurrentInstance, nextTick, computed, watch } from "vue";
|
||||
const props = defineProps({
|
||||
// 数据
|
||||
search: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_GS_XS_LX } = proxy.$dict("D_GS_XS_LX"); //获取字典数据
|
||||
const dictItemList = ref([])
|
||||
const searchConfiger = reactive([
|
||||
{
|
||||
label: "时间",
|
||||
showType: "daterange",
|
||||
prop: "startTime",
|
||||
placeholder: "请输入警情名称",
|
||||
},
|
||||
{
|
||||
showType: "defaultSlot",
|
||||
// prop: "bjlbList",
|
||||
placeholder: "请选择情报类型",
|
||||
label: "警情类别"
|
||||
},
|
||||
])
|
||||
const bjlbList = ref([])
|
||||
onMounted(() => {
|
||||
tabHeightFn()
|
||||
})
|
||||
const tabHeight = ref(0)
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
tabHeight.value = window.innerHeight - 300
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
const pageData = reactive({
|
||||
parameter: {},
|
||||
total: 0,
|
||||
loading: false,
|
||||
tableData: []
|
||||
})
|
||||
const onSearch = (val) => {
|
||||
const promes = {
|
||||
startTime: val.startTime ? val.startTime[0] : '',
|
||||
endTime: val.startTime ? val.startTime[1] : '',
|
||||
}
|
||||
const bjlbLists = bjlbList.value ? bjlbList.value.join(',') : ""
|
||||
pageData.parameter = { bjlbList: bjlbLists, ...promes }
|
||||
funAll()
|
||||
}
|
||||
|
||||
// 数据处理
|
||||
|
||||
const dataList = reactive({
|
||||
dyTj: {
|
||||
xAxisData: [],
|
||||
seriesData: [],
|
||||
},
|
||||
jqlxTj: [],
|
||||
jqlyTj: [],
|
||||
CljgfTj: [],
|
||||
XsfxTj: [],
|
||||
})
|
||||
const sortingRatioValue = reactive({
|
||||
Dywdtj: [],
|
||||
Ydfx: [],
|
||||
Cljgf: [],
|
||||
Czlfx: [],
|
||||
Lyfx: [],
|
||||
Jqlx: []
|
||||
})
|
||||
const sortingRatio = (data) => {
|
||||
// 提取所有number值
|
||||
// 计算总数
|
||||
const total = data.reduce((sum, item) => sum + item.number, 0);
|
||||
// 找出第一大和第二大的值及其对应的name
|
||||
const sortedData = [...data].sort((a, b) => b.number - a.number);
|
||||
const dataValue = sortedData.map(item => {
|
||||
return {
|
||||
...item,
|
||||
ratio: total > 0 ? (item.number / total * 100).toFixed(2) + '%' : '0%',
|
||||
}
|
||||
})
|
||||
return dataValue
|
||||
}
|
||||
// 地域统计
|
||||
const getfxbgDywdtj = () => {
|
||||
let params = {
|
||||
...pageData.parameter,
|
||||
}
|
||||
fxbgDywdtj(params).then(res => {
|
||||
dataList.dyTj.xAxisData = res.map(it => it.ssbm)
|
||||
dataList.dyTj.seriesData = [];
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
dataList.dyTj.seriesData[i] = [];
|
||||
for (let j = 0; j < res.length; j++) {
|
||||
dataList.dyTj.seriesData[i][j] = 0;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < dataList.dyTj.seriesData.length; i++) {
|
||||
dataList.dyTj.seriesData[i][i] = res[i].number
|
||||
}
|
||||
sortingRatioValue.Dywdtj = sortingRatio(res)
|
||||
})
|
||||
}
|
||||
// 警情类型统计
|
||||
const getfxbgJqlxtj = () => {
|
||||
let params
|
||||
if (pageData.parameter.bjlbList) {
|
||||
params = {
|
||||
...pageData.parameter,
|
||||
}
|
||||
} else {
|
||||
params = {
|
||||
...pageData.parameter,
|
||||
bjlbList: dictItemList.value.map(item => item.dm).join(',')
|
||||
}
|
||||
}
|
||||
fxbgJqlxtj(params).then(res => {
|
||||
sortingRatioValue.Jqlx = sortingRatio(res)
|
||||
dataList.jqlxTj = res.map(item => {
|
||||
return {
|
||||
name: item.name,
|
||||
value: item.number
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// 警情来源统计
|
||||
const getfxbgJqlytj = () => {
|
||||
let params = {
|
||||
...pageData.parameter,
|
||||
}
|
||||
fxbgJqlytj(params).then(res => {
|
||||
sortingRatioValue.Lyfx = sortingRatio(res)
|
||||
dataList.jqlyTj = res.map(item => {
|
||||
return {
|
||||
name: item.name,
|
||||
value: item.number
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//分析报告-时间维度-月分析
|
||||
const getfxbgYdfx = () => {
|
||||
let params = {
|
||||
...pageData.parameter,
|
||||
}
|
||||
fxbgYdfx(params).then(res => {
|
||||
sortingRatioValue.Ydfx = sortingRatio(res)
|
||||
dataList.ydTj = res.map(item => {
|
||||
return {
|
||||
name: item.month,
|
||||
value: item.number
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// 分析报告-处理结果分析
|
||||
const getfxgbCljgf = () => {
|
||||
let params = {
|
||||
...pageData.parameter,
|
||||
}
|
||||
|
||||
fxgbCljgf(params).then(res => {
|
||||
sortingRatioValue.Cljgf = sortingRatio(res)
|
||||
dataList.CljgfTj = res.map(item => {
|
||||
return {
|
||||
name: item.name,
|
||||
value: item.number
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// 分析报告-处置率分析
|
||||
const getfxgbCzlfx = () => {
|
||||
let params = {
|
||||
...pageData.parameter,
|
||||
}
|
||||
fxgbCzlfx(params).then(res => {
|
||||
dataList.withinTj = [{
|
||||
name: "超时分流(超过24小时)",
|
||||
value: res.within24h ? res.within24h : 0
|
||||
}, {
|
||||
name: "按时分流(24小时内)",
|
||||
value: res.over24h ? res.over24h : 0
|
||||
}]
|
||||
sortingRatioValue.Czlfx = sortingRatio(dataList.withinTj)
|
||||
})
|
||||
}
|
||||
|
||||
const getfxbgTj = () => {
|
||||
let params = {
|
||||
...pageData.parameter,
|
||||
}
|
||||
fxbgTj(params).then(res => {
|
||||
console.log(res, "xxx");
|
||||
dataList.XsfxTj = res
|
||||
})
|
||||
}
|
||||
const TimeValue = ref({
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
const nd = ref()
|
||||
|
||||
watch(() => pageData.parameter, (newVal) => {
|
||||
if (newVal.startTime) {
|
||||
TimeValue.value.startTime = newVal.startTime
|
||||
TimeValue.value.endTime = newVal.endTime
|
||||
if (timeValidate(newVal.startTime, 'yd') == timeValidate(newVal.endTime, 'yd')) {
|
||||
nd.value = timeValidate(newVal.startTime, 'yd')
|
||||
} else {
|
||||
nd.value = `${timeValidate(newVal.startTime, 'yd')}至${timeValidate(newVal.endTime, 'yd')}`
|
||||
}
|
||||
}
|
||||
}, { deep: true })
|
||||
|
||||
const deptId = ref({
|
||||
name: ''
|
||||
})
|
||||
const Time = () => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
const startOfYear = new Date(currentYear, 0, 1); // 今年1月1日
|
||||
const endOfYear = new Date(currentYear, 11, 31, 23); // 今年12月31日23:59:59.999
|
||||
const year = startOfYear.getFullYear();
|
||||
const month = String(startOfYear.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(startOfYear.getDate()).padStart(2, '0');
|
||||
const endYear = endOfYear.getFullYear();
|
||||
const endMonth = String(endOfYear.getMonth() + 1).padStart(2, '0');
|
||||
const endDay = String(endOfYear.getDate()).padStart(2, '0');
|
||||
const devt = getItem('deptId')
|
||||
deptId.value.name = devt[0].deptName
|
||||
nd.value = timeValidate('', 'yd')
|
||||
deptId.value.time = timeValidate('', 'ydm')
|
||||
deptId.value.ord=timeValidate('', 'mm')
|
||||
TimeValue.value.startTime = `${year}-${month}-${day}`
|
||||
TimeValue.value.endTime = `${endYear}-${endMonth}-${endDay}`
|
||||
|
||||
}
|
||||
Time()
|
||||
const funAll = () => {
|
||||
getfxbgDywdtj()
|
||||
getfxbgJqlxtj()
|
||||
getfxbgJqlytj()
|
||||
getfxgbCljgf()
|
||||
getfxbgYdfx()
|
||||
getfxgbCzlfx()
|
||||
getfxbgTj()
|
||||
}
|
||||
|
||||
const getDictItemList = () => {
|
||||
const promes = {
|
||||
startTime: props.search.startTime ,
|
||||
endTime: props.search.endTime,
|
||||
}
|
||||
if (props.search.lx) {
|
||||
const bjlbLists = props.search.lx ? props.search.lx.join(',') : ""
|
||||
pageData.parameter = { bjlbList: bjlbLists, ...promes }
|
||||
funAll()
|
||||
} else {
|
||||
const promesing = {
|
||||
dictCode: "00000000"
|
||||
}
|
||||
getDictItem(promesing).then(res => {
|
||||
const bjlbLists = res.map(item=>item.dm).join(',')?res.map(item=>item.dm).join(','):""
|
||||
pageData.parameter = { bjlbList: bjlbLists, ...promes }
|
||||
funAll()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const data = ref()
|
||||
watch(() => dictItemList.value, (val) => {
|
||||
data.value = val
|
||||
}, { deep: true })
|
||||
getDictItemList()
|
||||
const tableBox = ref(null);
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.headline {
|
||||
text-align: center;
|
||||
color: red;
|
||||
}
|
||||
|
||||
p {
|
||||
text-indent: 2em;
|
||||
/* 首行缩进2个汉字 */
|
||||
margin: 1em 0;
|
||||
/* 段落间距 */
|
||||
line-height: 1.6;
|
||||
/* 行高 */
|
||||
font-size: 16px;
|
||||
/* 字体大小 */
|
||||
text-align: justify;
|
||||
/* 两端对齐 */
|
||||
}
|
||||
|
||||
/* 特殊情况处理 */
|
||||
p.no-indent {
|
||||
text-indent: 0;
|
||||
/* 不需要缩进的段落 */
|
||||
}
|
||||
|
||||
p.first-no-indent:first-of-type {
|
||||
text-indent: 0;
|
||||
/* 第一个段落不缩进 */
|
||||
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<el-dialog :title="title" v-model="visible" width="80%" destroy-on-close>
|
||||
<JudgmentReport :search="search"/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import { ref, reactive ,watch} from 'vue'
|
||||
import JudgmentReport from './AnalysisReport/index.vue'
|
||||
const title = ref('详情')
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
search: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const opebg = ref(false)
|
||||
watch(() => props.visible, (val) => {
|
||||
opebg.value = val
|
||||
},{immediate:true})
|
||||
const emit=defineEmits(['update:visible'])
|
||||
</script>
|
||||
@ -14,7 +14,6 @@
|
||||
<MoreBarEcharts echartsId="cztjEcharts" :data="obj.data_lxtj"></MoreBarEcharts>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hh50">
|
||||
<div class="comm-title">会商统计</div>
|
||||
<div class="echartsBox">
|
||||
@ -35,10 +34,10 @@
|
||||
<div ref="searchBox">
|
||||
<el-form :model="searchList" ref="searchFormRef" :inline="true">
|
||||
<el-form-item label="类型">
|
||||
<el-cascader ref="cascaRef" @change="changeCascader" :disabled="readonly_lx" v-model="searchList.lx" clearable
|
||||
:options="cascaderList" :props="{ checkStrictly: true,multiple: true }" placeholder="请选择类型" />
|
||||
<el-cascader ref="cascaRef" v-model="searchList.lx" @change="changeCascader" collapse-tags
|
||||
:disabled="readonly_lx" :options="cascaderList" :props="{ multiple: true }" placeholder="请选择类型" />
|
||||
</el-form-item>
|
||||
<el-form-item label="人员">
|
||||
<!-- <el-form-item label="人员">
|
||||
<el-input @change="changeRy" v-model="searchList.ry" :disabled="readonly_ry" clearable
|
||||
placeholder="请输入姓名或身份证"></el-input>
|
||||
</el-form-item>
|
||||
@ -52,10 +51,11 @@
|
||||
<el-input @change="changeRy" :disabled="readonly_dd" v-model="searchList.xxdz" clearable
|
||||
placeholder="请输入详细地址"></el-input>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="时间">
|
||||
<el-date-picker v-model="searchList.datetimes" type="datetimerange" unlink-panels :range-separator="'至'"
|
||||
start-placeholder="开始日期时间" end-placeholder="结束日期时间" value-format="YYYY-MM-DD HH:mm:ss" />
|
||||
<el-date-picker v-model="searchList.datetimes" type="daterange" unlink-panels :range-separator="'至'"
|
||||
start-placeholder="开始日期时间" end-placeholder="结束日期时间" format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSearch">查询</el-button>
|
||||
@ -67,9 +67,9 @@
|
||||
<li class="list-item" ref="listBoxRef" v-for="(it, idx) in list" :key="idx">
|
||||
<div class="comm-title title-s">{{ it.title }}</div>
|
||||
<div class="list-table">
|
||||
<MyTable :tableData="it.tableList" :tableColumn="it.tableColumn" :key="idx + '' + it.keyCount" :fixed="false"
|
||||
:tableHeight="pageData.tableHeight" :tabelModel="it.title" :tableConfiger="pageData.tableConfiger"
|
||||
:controlsWidth="pageData.controlsWidth">
|
||||
<MyTable :tableData="it.tableList" :tableColumn="it.tableColumn" :key="idx + '' + it.keyCount"
|
||||
:fixed="false" :tableHeight="pageData.tableHeight" :tabelModel="it.title"
|
||||
:tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
|
||||
<template #jqlbdm="{ row }">
|
||||
<DictTag :tag="false" :value="row.jqlbdm" :options="JQLB" />
|
||||
</template>
|
||||
@ -85,22 +85,26 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<YpModel v-model="showModel" :textContent="textContent"></YpModel>
|
||||
<!-- <YpModel v-model="showModel" :textContent="textContent"></YpModel> -->
|
||||
<!-- 弹窗 -->
|
||||
<DetailDialog ref="detaileRef"></DetailDialog>
|
||||
<!-- <DetailDialog ref="detaileRef"></DetailDialog> -->
|
||||
<!-- 研判报告弹窗 -->
|
||||
<JudgmentReport v-model="visible" :search="search"></JudgmentReport>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { lzJcjPjdbSelectPage } from '@/api/semanticAnalysis.js'
|
||||
import { ElMessage } from "element-plus";
|
||||
import DetailDialog from './components/detailDialog.vue'
|
||||
import YpModel from '@/components/ypModel/index.vue'
|
||||
// import DetailDialog from './components/detailDialog.vue'
|
||||
import JudgmentReport from './components/judgmentReport.vue'
|
||||
// import YpModel from '@/components/ypModel/index.vue'
|
||||
import { qcckPost, qcckGet } from "@/api/qcckApi.js";
|
||||
import MoreBarEcharts from "@/views/home/echarts/moreBarEcharts.vue";
|
||||
import LineEcharts from "@/views/home/echarts/moreLineEcharts.vue";
|
||||
import MyTable from "@/components/aboutTable/DarkTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import {tbJqGetPageList } from '@/api/yj.js'
|
||||
const router = useRouter();
|
||||
import { nextTick, onMounted, reactive, getCurrentInstance, ref, watch } from 'vue';
|
||||
const { proxy } = getCurrentInstance();
|
||||
@ -108,9 +112,9 @@ const { JQLB } = proxy.$dict("JQLB"); //获取字典数据
|
||||
const readonly_lx = ref(false)
|
||||
const readonly_ry = ref(false)
|
||||
const readonly_dd = ref(false)
|
||||
const cascaRef=ref()
|
||||
const cascaRef = ref()
|
||||
const showModel = ref(false);
|
||||
const detaileRef = ref();
|
||||
// const detaileRef = ref();
|
||||
const searchBox = ref();
|
||||
const listBoxRef = ref();
|
||||
const textContent = ref('');
|
||||
@ -319,34 +323,50 @@ const getJqList = () => {
|
||||
const handleHs = (val) => {
|
||||
router.push({ path: '/MeetingRoom', query: { tsypid: val.id } })
|
||||
}
|
||||
|
||||
const visible = ref(false)
|
||||
const search = ref({})
|
||||
const handleYP = () => {
|
||||
let arr=cascaRef.value.getCheckedNodes()
|
||||
searchForm.value.jqlbdms=arr.map((el)=>{
|
||||
return el.value
|
||||
})
|
||||
let params = {
|
||||
hskssj: searchForm.value.kssj,
|
||||
hsjssj: searchForm.value.jssj,
|
||||
jqlbdms:searchForm.value.jqlbdms
|
||||
console.log(searchList.value);
|
||||
visible.value = true
|
||||
let data = []
|
||||
if (searchList.value.lx) {
|
||||
data = searchList.value.lx.map(item => {
|
||||
return item[item.length - 1]
|
||||
})
|
||||
|
||||
}
|
||||
qcckPost(params, '/mosty-gsxt/lzJcjPjdb/getJqDcypbg').then(res => {
|
||||
let data = res || {};
|
||||
let html = `<p class="html_bt">${data.bt}</p>`
|
||||
html += `<p>${data.head}</p>`
|
||||
html += `<p>${data.nr}</p>`
|
||||
html += `<p>${data.bc}</p>`
|
||||
html += `<p>${data.end}</p>`
|
||||
textContent.value = html;
|
||||
showModel.value = true;
|
||||
})
|
||||
search.value = {
|
||||
lx: searchList.value.lx ? data : '',
|
||||
startTime: searchList.value.datetimes ? searchList.value.datetimes[0] : '',
|
||||
endTime: searchList.value.datetimes ? searchList.value.datetimes[1] : '',
|
||||
}
|
||||
|
||||
// let arr=cascaRef.value.getCheckedNodes()
|
||||
// searchForm.value.jqlbdms=arr.map((el)=>{
|
||||
// return el.value
|
||||
// })
|
||||
// let params = {
|
||||
// hskssj: searchForm.value.kssj,
|
||||
// hsjssj: searchForm.value.jssj,
|
||||
// jqlbdms:searchForm.value.jqlbdms
|
||||
// }
|
||||
// qcckPost(params, '/mosty-gsxt/lzJcjPjdb/getJqDcypbg').then(res => {
|
||||
// let data = res || {};
|
||||
// let html = `<p class="html_bt">${data.bt}</p>`
|
||||
// html += `<p>${data.head}</p>`
|
||||
// html += `<p>${data.nr}</p>`
|
||||
// html += `<p>${data.bc}</p>`
|
||||
// html += `<p>${data.end}</p>`
|
||||
// textContent.value = html;
|
||||
// showModel.value = true;
|
||||
// })
|
||||
}
|
||||
|
||||
// 选择类型
|
||||
const changeCascader = (val) => {
|
||||
console.log(val,'val');
|
||||
console.log(cascaRef.value.getCheckedNodes(),'++++++++');
|
||||
|
||||
console.log(val, 'val');
|
||||
console.log(cascaRef.value.getCheckedNodes(), '++++++++');
|
||||
|
||||
readonly_lx.value = false;
|
||||
readonly_ry.value = val ? true : false
|
||||
readonly_dd.value = val ? true : false
|
||||
@ -372,6 +392,7 @@ const changeBm = (val) => {
|
||||
}
|
||||
// 重置
|
||||
const resetForm = () => {
|
||||
searchList.value = {}
|
||||
searchForm.value = {}
|
||||
readonly_lx.value = false
|
||||
readonly_ry.value = false
|
||||
@ -381,7 +402,25 @@ const resetForm = () => {
|
||||
// 搜索
|
||||
const onSearch = () => {
|
||||
if (searchList.value.lx || searchList.value.ry || searchList.value.dd) {
|
||||
detaileRef.value.init(searchList.value)
|
||||
const data= searchList.value.lx.map(item => {
|
||||
return item[item.length - 1]
|
||||
})
|
||||
console.log(searchList.value);
|
||||
|
||||
const promes = {
|
||||
startTime: searchList.value.datetimes ? searchList.value.datetimes[0] : '',
|
||||
endTime: searchList.value.datetimes ? searchList.value.datetimes[1] : '',
|
||||
bjlbs: searchList.value.lx ? data.join(',') : '',
|
||||
}
|
||||
console.log(promes);
|
||||
|
||||
tbJqGetPageList(promes).then(res => {
|
||||
list[1].tableList = res.records || [];
|
||||
list[1].pageConfiger.total = res.total;
|
||||
})
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
ElMessage.warning('请选择查询条件')
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-dialog v-model="modelValue" center width="1000px" :destroy-on-close="true" title="网上会商" @close="close"
|
||||
<el-dialog v-model="props.modelValue" center width="1000px" :destroy-on-close="true" title="网上会商" @close="close"
|
||||
:close-on-click-modal="false">
|
||||
<div class="cntBox">
|
||||
<div class="form_item flex">
|
||||
|
||||
@ -79,11 +79,11 @@ const pageData = reactive({
|
||||
tableColumn: [
|
||||
{
|
||||
label: "研判标题",
|
||||
prop: "ypbt"
|
||||
prop: "jymc"
|
||||
},
|
||||
{
|
||||
label: "研判时间",
|
||||
prop: "ypsj"
|
||||
prop: "fbsj"
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<span class="title">{{ title }}模型 </span>
|
||||
<div>
|
||||
<el-button type="primary" size="small" :loading="loading" @click="submit" v-show="title != '详情'">保存</el-button>
|
||||
<el-button size="small" @click="close">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form_cnt">
|
||||
<FormMessage :formList="formData" v-model="listQuery" ref="elform" :rules="rules" :disabled="editAdd">
|
||||
</FormMessage>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, getCurrentInstance } from 'vue'
|
||||
import FormMessage from "@/components/aboutTable/FormMessage.vue";
|
||||
import { addEntity,editEntity } from '@/api/model.js'
|
||||
import { ElMessage } from "element-plus";
|
||||
const proxy = getCurrentInstance()
|
||||
const props = defineProps({
|
||||
dict: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
}
|
||||
})
|
||||
const dialogForm = ref(false)
|
||||
const emit = defineEmits(['getLits'])
|
||||
// 判断是否增删改
|
||||
const editAdd = ref(false)
|
||||
const title = ref("新增")
|
||||
const formData = ref()
|
||||
const listQuery = ref({})
|
||||
const elform = ref()
|
||||
const rules = ref({
|
||||
mxmc: [
|
||||
{ required: true, message: '请输入模型名称', trigger: 'blur' },
|
||||
],
|
||||
mxlx: [
|
||||
{ required: true, message: '请选择模型类型', trigger: 'change' },
|
||||
],
|
||||
})
|
||||
const init = (type, row) => {
|
||||
dialogForm.value = true
|
||||
editAdd.value = false
|
||||
formData.value = [
|
||||
{ label: "模型名称", prop: "mxmc", type: "input", width: "40%" },
|
||||
{
|
||||
label: "模型类型", prop: "mxlx", type: "select",
|
||||
width: "40%", options: props.dict.D_MXGL_MXLX
|
||||
},
|
||||
]
|
||||
listQuery.value = { ...row }
|
||||
if (type == 'edit') {
|
||||
title.value = "编辑"
|
||||
} else if (type == 'add') {
|
||||
title.value = "新增"
|
||||
} else {
|
||||
editAdd.value = true
|
||||
title.value = "详情"
|
||||
}
|
||||
}
|
||||
|
||||
// 表单内容
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
// 新增
|
||||
const submit = () => {
|
||||
elform.value.submit((data) => {
|
||||
loading.value = true
|
||||
if (title.value == '新增') {
|
||||
addEntity(listQuery.value).then((res) => {
|
||||
ElMessage.success("新增成功");
|
||||
emit('getLits')
|
||||
dialogForm.value = false
|
||||
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
});
|
||||
} else {
|
||||
editEntity(listQuery.value).then((res) => {
|
||||
ElMessage.success("修改成功");
|
||||
emit('getLits')
|
||||
dialogForm.value = false
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
});
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭
|
||||
const close = () => {
|
||||
dialogForm.value = false
|
||||
}
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,290 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="预警规则">
|
||||
<el-button type="primary" size="small" @click="openAddRule('add', item)">新增</el-button>
|
||||
<el-button type="primary" size="small" :disabled="ids.length == 0" @click="deleteRule(ids)">批量删除</el-button>
|
||||
<el-button size="small" @click="retenHome()">返回</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
<div ref="searchBox">
|
||||
<Search :searchArr="searchConfiger" @submit="onSearch" />
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox">
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
|
||||
@chooseData="chooseData">
|
||||
<template #tjName="{ row }">
|
||||
<div class="flex one_text_detail" v-if="row.tj">{{ ` ${row.tj} ${row.cs}` }} </div>
|
||||
</template>
|
||||
<template #zz="{ row }">
|
||||
<template v-if="row.zz">
|
||||
<span v-for="(item, index) in jsonParse(row.zz)" :key="index">{{ item.zzmc }}
|
||||
<span v-if="index < jsonParse(row.zz).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #sfbq="{ row }">
|
||||
<template v-if="row.sfbq">
|
||||
<span v-for="(item, index) in jsonParse(row.sfbq)" :key="index">{{ item.bqmc }}
|
||||
<span v-if="index < jsonParse(row.sfbq).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #xwbq="{ row }">
|
||||
<template v-if="row.xwbq">
|
||||
<span v-for="(item, index) in jsonParse(row.xwbq)" :key="index">{{ item.bqmc }}
|
||||
<span v-if="index < jsonParse(row.xwbq).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #dd="{ row }">
|
||||
<template v-if="row.dd">
|
||||
<span v-for="(item, index) in jsonParse(row.dd)" :key="index">{{ item.dz }}
|
||||
<span v-if="index < jsonParse(row.dd).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #ryxx="{ row }">
|
||||
<template v-if="row.ryxx">
|
||||
<span v-for="(item, index) in jsonParse(row.ryxx)" :key="index">{{ item.xm }}
|
||||
<span v-if="index < jsonParse(row.ryxx).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #jqlx="{ row }">
|
||||
<template v-if="row.jqlx">
|
||||
<span v-for="(item, index) in jsonParse(row.jqlx)" :key="index">{{ item.lxmc }}
|
||||
<span v-if="index < jsonParse(row.jqlx).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #sjlx="{ row }">
|
||||
<template v-if="row.sjlx">
|
||||
<span v-for="(item, index) in jsonParse(row.sjlx)" :key="index">{{ item.lxmc }}
|
||||
<span v-if="index < jsonParse(row.sjlx).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #wp="{ row }">
|
||||
<template v-if="row.wp">
|
||||
<span v-for="(item, index) in jsonParse(row.wp)" :key="index">{{ item.wpmc }}
|
||||
<span v-if="index < jsonParse(row.wp).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #controls="{ row }">
|
||||
<el-link type="primary" size="small" @click="yzSsyjpzMxgzxl( row.id)">运行规则</el-link>
|
||||
<el-link type="primary" size="small" @click="openAddRule('edit',item, row)">修改</el-link>
|
||||
<el-link type="primary" size="small" @click="openAddRule('detail',item, row)">详情</el-link>
|
||||
<!-- <el-link type="primary" size="small" @click="openAddRule('detail',item, row)">预警列表</el-link> -->
|
||||
<el-link type="danger" size="small" @click="deleteRule(row.id)">删除</el-link>
|
||||
|
||||
</template>
|
||||
</MyTable>
|
||||
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
|
||||
...pageData.pageConfiger,
|
||||
total: pageData.total
|
||||
}"></Pages>
|
||||
</div>
|
||||
</div>
|
||||
<List ref="regulation" :dict="{ D_BB_AJLB,D_BZ_WPLX }" @getList="getList" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessage } from "element-plus";
|
||||
import List from "../list";
|
||||
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { deleteYjgzpz,getYjgzpzMxgzxl,getYjgzpzPageList } from "@/api/model";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
import { template } from "lodash";
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_BB_AJLB,D_BZ_WPLX} = proxy.$dict("D_BB_AJLB","D_BZ_WPLX")
|
||||
const regulation = ref(null)
|
||||
const queryFrom = ref({})
|
||||
const searchBox = ref(); //搜索框
|
||||
|
||||
const searchConfiger = ref([
|
||||
{
|
||||
label: "规则名称",
|
||||
prop: "gzmc",
|
||||
placeholder: "请输入规则名称",
|
||||
showType: "input"
|
||||
},
|
||||
{
|
||||
label: "时间",
|
||||
prop: "startTime",
|
||||
placeholder: "请选择时间",
|
||||
showType: "daterange"
|
||||
},
|
||||
]);
|
||||
|
||||
const pageData = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "null",
|
||||
loading: false
|
||||
},
|
||||
total: 0,
|
||||
pageConfiger: {
|
||||
pageSize: 20,
|
||||
pageCurrent: 1
|
||||
},
|
||||
controlsWidth: 300,
|
||||
tableColumn: [
|
||||
{ label: "规则名称", prop: "gzmc", showOverflowTooltip: true },
|
||||
{ label: "开始时间", prop: "jssj", showOverflowTooltip: true },
|
||||
{ label: "结束时间", prop: "kssj", showOverflowTooltip: true },
|
||||
{ label: "条件", prop: "tjName", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "组织", prop: "zz", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "人员信息", prop: "ryxx", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "警情类型", prop: "jqlx", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "事件类型", prop: "sjlx", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "物品", prop: "wp", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "地址", prop: "dd", showOverflowTooltip: true, showSolt: true },
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
tabHeightFn();
|
||||
});
|
||||
|
||||
// 搜索
|
||||
const onSearch = (val) => {
|
||||
queryFrom.value = { ...val };
|
||||
queryFrom.value.startTime = val.startTime&&val.startTime.length > 0 ? val.startTime[0] : '';
|
||||
queryFrom.value.endTime = val.startTime&&val.startTime.length > 0 ? val.startTime[1] : '';
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeNo = (val) => {
|
||||
pageData.pageConfiger.pageCurrent = val;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeSize = (val) => {
|
||||
pageData.pageConfiger.pageSize = val;
|
||||
getList();
|
||||
};
|
||||
//
|
||||
// 获取列表
|
||||
const getList = () => {
|
||||
const promes = {
|
||||
...pageData.pageConfiger,
|
||||
...queryFrom.value,
|
||||
mxid:props.item.id,
|
||||
}
|
||||
getYjgzpzPageList(promes).then((res) => {
|
||||
pageData.tableData = res.records
|
||||
pageData.total = res.total
|
||||
});
|
||||
};
|
||||
const retenHome = () => {
|
||||
emitter.emit('changeModel', { name: '研判首页', row: {} });
|
||||
}
|
||||
const openAddRule = (type, item, row) => {
|
||||
regulation.value.init(type, item, row)
|
||||
}
|
||||
const ids = ref([])
|
||||
|
||||
const chooseData = (val) => {
|
||||
ids.value = val.map(item => item.id)
|
||||
}
|
||||
const deleteRule = (row) => {
|
||||
proxy.$confirm('是否删除该规则, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let list
|
||||
if (Array.isArray(row)) {
|
||||
list = ids.value
|
||||
} else {
|
||||
list =[row]
|
||||
}
|
||||
deleteYjgzpz({ids:list}).then(() => {
|
||||
ElMessage.success("删除成功");
|
||||
getList()
|
||||
})
|
||||
}).catch((err) => {
|
||||
proxy.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
});
|
||||
});
|
||||
}
|
||||
const yzSsyjpzMxgzxl = (params) => {
|
||||
getYjgzpzMxgzxl({id:params}).then((res) => {
|
||||
console.log(res);
|
||||
})
|
||||
}
|
||||
const jsonParse = (val) => {
|
||||
if (val) {
|
||||
return JSON.parse(val)
|
||||
}
|
||||
}
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.control-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,696 +0,0 @@
|
||||
<template>
|
||||
<!-- 可用条件类型列表 -->
|
||||
<div class="regulation-wrapper">
|
||||
<div class="rule-name-section flex align-center">
|
||||
<div class="rule-name-label">规则名称:</div>
|
||||
<el-input v-model="gzmc" :disabled="disabled" placeholder="请输入规则名称" class="search-input" clearable></el-input>
|
||||
</div>
|
||||
<!-- 可用条件区域 -->
|
||||
<div class="condition-section">
|
||||
<div class="available-conditions">
|
||||
<VueDraggable class="flex-wrap" v-model="dataList" ghostClass="ghost"
|
||||
:group="{ name: 'people', pull: 'clone', put: false }" :clone="clone">
|
||||
<el-button v-for="item in dataList" :key="item.name" class="condition-button" size="small">
|
||||
<i class="el-icon-document-add"></i>
|
||||
{{ item.name }}
|
||||
</el-button>
|
||||
</VueDraggable>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 拖拽提示 -->
|
||||
<div class="drag-hint">
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
<span>拖拽条件到下方区域</span>
|
||||
</div>
|
||||
|
||||
<!-- 已选条件区域 -->
|
||||
<div class="selected-section">
|
||||
<div class="section-title">
|
||||
<i class="el-icon-check-square"></i>
|
||||
<span>已选条件</span>
|
||||
<span class="selected-count">{{ copyList.length }}</span>
|
||||
</div>
|
||||
<div class="selected-container">
|
||||
<VueDraggable v-model="copyList" :group="{ name: 'people', pull: !disabled, put: !disabled }" ghostClass="ghost"
|
||||
class="selected-list" itemKey="name">
|
||||
<div v-for="(item, indexs) in copyList" :key="item" class="draggable-item">
|
||||
<div class="item-content">
|
||||
<div v-if="!disabled" class="item-remove-btn" @click="romes(item)"><el-icon :size="16">
|
||||
<Close />
|
||||
</el-icon></div>
|
||||
<span class="item-text">{{ item.name }}{{}}</span>
|
||||
</div>
|
||||
<div v-if="item[item['key']]">
|
||||
<template v-if="item.key == 'dd'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
|
||||
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
|
||||
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
|
||||
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'cs'">
|
||||
<div class="count-condition-container">
|
||||
<el-select v-model="item[item['key']].tj" placeholder="请选择条件" class="condition-select">
|
||||
<el-option :label="item" :value="item" v-for="(item, index) in dataConst" :key="index"></el-option>
|
||||
</el-select>
|
||||
<el-input-number v-model="item[item['key']].cs" :min="1" :max="1000" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'zz'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
|
||||
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
|
||||
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
|
||||
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'kssj'">
|
||||
<div class="condition-input-container flex just-between">
|
||||
<div>
|
||||
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
|
||||
type="date" :placeholder="`请选择${item.name}`" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'jssj'">
|
||||
<div class="condition-input-container flex just-between">
|
||||
<div>
|
||||
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
|
||||
type="date" :placeholder="`请选择${item.name}`" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="item.key == 'sjlx'">
|
||||
<div class="condition-input-container flex just-between">
|
||||
<el-select v-model="item[item['key']]" multiple :placeholder="`请选择${item.name}`">
|
||||
<el-option v-for="item in dict.D_BB_AJLB" :key="item.dm" :label="item.zdmc" :value="item.dm" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'wp'">
|
||||
<div class="condition-input-container flex just-between">
|
||||
<el-select v-model="item[item['key']]" multiple :placeholder="`请选择${item.name}`" style="width: 240px">
|
||||
<el-option v-for="item in dict.D_BZ_WPLX" :key="item.dm" :label="item.zdmc" :value="item.dm" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'ryxx'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input v-model="item[item['key']][index].xm" :placeholder="`请输入姓名`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-input v-model="item[item['key']][index].sfzh" :placeholder="`请输入身份证号`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
|
||||
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
|
||||
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
|
||||
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="item.key == 'jqlx'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input @click="chooseMarksVisible = true" v-model="item[item['key']][index].lxmc"
|
||||
:placeholder="`请输入${item.name}`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" @click="removeItem(item['key'], index)" type="danger"
|
||||
size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</VueDraggable>
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<div v-if="copyList.length === 0" class="empty-state">
|
||||
<i class="el-icon-tickets"></i>
|
||||
<p>暂无已选条件</p>
|
||||
<p class="empty-tip">从上方拖拽条件到此处</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ChooseIdeJqlb v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { ElMessage } from "element-plus";
|
||||
import ChooseIdeJqlb from '@/components/ChooseList/ChooseIdeJqlb/index.vue'
|
||||
import { VueDraggable } from 'vue-draggable-plus'//npm install vue-draggable-plus
|
||||
const props = defineProps({
|
||||
dict: {
|
||||
type: Object,
|
||||
default: () => { },
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [
|
||||
'Joao',
|
||||
'Jean',
|
||||
'Johanna',
|
||||
'Juan',
|
||||
],
|
||||
}, defaultData: {
|
||||
type: Object,
|
||||
default: () => { },
|
||||
}, disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const dataConst = reactive([
|
||||
">",
|
||||
"<",
|
||||
"="
|
||||
])
|
||||
const gzmc = ref('')
|
||||
const dataList = ref(props.list)
|
||||
const copyList = ref([])
|
||||
const clone = (val) => {
|
||||
if (val.key == 'jqlx') {
|
||||
dataList.value = dataList.value.filter(item => item.key != 'sjlx')
|
||||
}
|
||||
if (val.key == 'sjlx') {
|
||||
dataList.value = dataList.value.filter(item => item.key != 'jqlx')
|
||||
}
|
||||
const data = copyList.value.find(item => item.name == val.name)
|
||||
if (data) {
|
||||
console.log("已存在")
|
||||
} else {
|
||||
switch (val.key) {
|
||||
case 'cs':
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: {}
|
||||
}
|
||||
case "wp":
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: []
|
||||
}
|
||||
case 'ryxx':
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: [{
|
||||
xm: "",
|
||||
sfzh: ""
|
||||
}]
|
||||
}
|
||||
case 'kssj':
|
||||
case 'jssj':
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: []
|
||||
}
|
||||
case 'sjlx':
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: []
|
||||
}
|
||||
default:
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: [""]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
watch(() => props.defaultData, (val) => {
|
||||
if (val) {
|
||||
gzmc.value = val.gzmc
|
||||
const data = props.list.map(item => {
|
||||
switch (item.key) {
|
||||
case 'cs':
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val.cs && val.tj ? {
|
||||
cs: val.cs,
|
||||
tj: val.tj
|
||||
} : null
|
||||
}
|
||||
case 'jssj':
|
||||
case 'kssj':
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? val[item.key] : null,
|
||||
}
|
||||
case 'zz':
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.zzmc) : null,
|
||||
}
|
||||
case 'dd':
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.dz) : null,
|
||||
}
|
||||
default:
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]) : null
|
||||
}
|
||||
}
|
||||
})
|
||||
copyList.value = data.filter(item => item[item.key] != null)
|
||||
}
|
||||
}, { deep: true, immediate: true })
|
||||
const addInput = (key, index) => {
|
||||
if (key == 'ryxx') {
|
||||
copyList.value[index][key].push({
|
||||
xm: "",
|
||||
sfzh: ""
|
||||
})
|
||||
} else {
|
||||
copyList.value[index][key].push("")
|
||||
}
|
||||
}
|
||||
|
||||
// 移除项目
|
||||
const removeItem = (key, index) => {
|
||||
const data = copyList.value.findIndex(item => item.key == key)
|
||||
if (copyList.value[data][key].length == 1) {
|
||||
return
|
||||
}
|
||||
copyList.value[data][key].splice(index, 1)
|
||||
}
|
||||
const chooseMarksVisible = ref(false)
|
||||
const roleIds = ref([])
|
||||
const choosed = (val) => {
|
||||
roleIds.value = val.map(item => item.id)
|
||||
copyList.value.find(item => item.key == 'jqlx')['jqlx'] = val.map(item => {
|
||||
return {
|
||||
lxmc: item.zdmc,
|
||||
lxdm: item.dm
|
||||
}
|
||||
})
|
||||
}
|
||||
const romes = (val) => {
|
||||
copyList.value = copyList.value.filter(item => item.key !== val.key)
|
||||
if (val.key == 'jqlx' || val.key == 'sjlx') {
|
||||
dataList.value = props.list
|
||||
}
|
||||
}
|
||||
|
||||
const promes = ref({})
|
||||
// 新增
|
||||
const retValue = () => {
|
||||
if (gzmc.value == '') {
|
||||
return
|
||||
}
|
||||
const data = copyList.value.map(item => {
|
||||
return {
|
||||
[item.key]: item[item.key]
|
||||
}
|
||||
})
|
||||
promes.value = data.reduce((acc, cur) => {
|
||||
return { ...acc, ...cur }
|
||||
}, {})
|
||||
promes.value = { ...promes.value, ...promes.value.cs, gzmc: gzmc.value }
|
||||
if (promes.value.dd && promes.value.dd.length > 0) {
|
||||
const dd = promes.value.dd.map(item => {
|
||||
return { dz: item }
|
||||
})
|
||||
promes.value.dd = JSON.stringify(dd)
|
||||
}
|
||||
if (promes.value.zz && promes.value.zz.length > 0) {
|
||||
const zz = promes.value.zz.map(item => {
|
||||
return { zzmc: item }
|
||||
})
|
||||
promes.value.zz = JSON.stringify(zz)
|
||||
}
|
||||
const sjlx = copyList.value.find(item => item.key == 'sjlx')
|
||||
if (sjlx) {
|
||||
const data = props.dict.D_BB_AJLB.filter(item => {
|
||||
if (sjlx['sjlx'].includes(item.dm)) {
|
||||
return item
|
||||
}
|
||||
}).map(item => {
|
||||
return {
|
||||
lxmc: item.zdmc,
|
||||
lxdm: item.dm
|
||||
}
|
||||
})
|
||||
promes.value.sjlx = JSON.stringify(data)
|
||||
}
|
||||
const wplx = copyList.value.find(item => item.key == 'wp')
|
||||
if (wplx) {
|
||||
const data = props.dict.D_BZ_WPLX.filter(item => {
|
||||
if (wplx['wp'].includes(item.dm)) {
|
||||
return item
|
||||
}
|
||||
}).map(item => {
|
||||
return {
|
||||
wpmc: item.zdmc,
|
||||
wpdm: item.dm
|
||||
}
|
||||
})
|
||||
promes.value.wp = JSON.stringify(data)
|
||||
}
|
||||
if (promes.value.ryxx && promes.value.ryxx.length > 0) {
|
||||
promes.value.ryxx = JSON.stringify(promes.value.ryxx)
|
||||
}
|
||||
if (promes.value.jqlx && promes.value.jqlx.length > 0) {
|
||||
promes.value.jqlx = JSON.stringify(promes.value.jqlx)
|
||||
}
|
||||
return promes.value
|
||||
}
|
||||
defineExpose({
|
||||
retValue
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.regulation-wrapper {
|
||||
padding: 20px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
// 条件区域通用样式
|
||||
.condition-section,
|
||||
.selected-section {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
// margin-bottom: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.condition-section:hover,
|
||||
.selected-section:hover {
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
// 区域标题
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
color: #303133;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 2px solid #e6f7ff;
|
||||
|
||||
i {
|
||||
color: #409eff;
|
||||
margin-right: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.selected-count {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
color: #606266;
|
||||
background: #f0f9ff;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
min-width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// 可用条件区域
|
||||
.available-conditions {
|
||||
// min-height: 100px;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.condition-button {
|
||||
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
border-radius: 8px !important;
|
||||
padding: 8px 16px !important;
|
||||
font-size: 14px !important;
|
||||
transition: all 0.3s ease !important;
|
||||
min-width: 120px;
|
||||
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(135deg, #66b1ff 0%, #409eff 100%) !important;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
// 拖拽提示
|
||||
.drag-hint {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
// align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
font-size: 16px;
|
||||
animation: bounce 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 已选条件区域
|
||||
.selected-container {
|
||||
min-height: 120px;
|
||||
border: 2px dashed #dcdfe6;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
transition: all 0.3s ease;
|
||||
background-color: #dcdfe670;
|
||||
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
background: #f0f9ff;
|
||||
}
|
||||
}
|
||||
|
||||
.selected-list {
|
||||
display: flex;
|
||||
min-height: 100px;
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
// 拖拽项样式
|
||||
.draggable-item {
|
||||
position: relative;
|
||||
padding: 3px;
|
||||
margin: 8px;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: table-cell;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px) scale(1.02);
|
||||
box-shadow: 0 6px 16px rgba(103, 194, 58, 0.4);
|
||||
}
|
||||
|
||||
&.ghost {
|
||||
opacity: 0.6;
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 20px 12px 12px 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-width: 140px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.item-remove {
|
||||
color: #c0c4cc;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
padding: 4px;
|
||||
border-radius: 50%;
|
||||
|
||||
&:hover {
|
||||
color: #f56c6c;
|
||||
background: #fef0f0;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 规则名称区域 */
|
||||
.rule-name-section {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.rule-name-label {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
/* 项目删除按钮 */
|
||||
.item-remove-btn {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
/* 条件输入容器 */
|
||||
.condition-input-container {
|
||||
flex-wrap: nowrap;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* 计数条件容器 */
|
||||
.count-condition-container {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* 条件选择框 */
|
||||
.condition-select {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
/* 按钮右侧边距 */
|
||||
.btn-margin-right {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
// 空状态样式
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: #909399;
|
||||
|
||||
i {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
color: #dcdfe6;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
font-size: 12px;
|
||||
color: #c0c4cc;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&:hover i {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
// 拖拽效果
|
||||
.ghost {
|
||||
opacity: 0.6;
|
||||
background-color: #e6f7ff;
|
||||
border: 2px dashed #409eff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.regulation-wrapper {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.condition-section,
|
||||
.selected-section {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.condition-button {
|
||||
min-width: 100px;
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
min-width: 120px;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
:v-deep .el-select {
|
||||
width: 59%;
|
||||
}
|
||||
</style>
|
||||
@ -1,257 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="四色预警规则">
|
||||
<el-button type="primary" size="small" @click="openAddRule('add', item)">新增</el-button>
|
||||
<el-button type="primary" size="small" :disabled="ids.length == 0" @click="deleteRule(ids)">批量删除</el-button>
|
||||
<el-button size="small" @click="retenHome()">返回</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
<div ref="searchBox">
|
||||
<Search :searchArr="searchConfiger" @submit="onSearch" />
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox">
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
|
||||
@chooseData="chooseData">
|
||||
<!-- <template #tjName="{ row }">
|
||||
<div class="flex one_text_detail">{{ ` ${row.tj} ${row.cs}` }} </div>
|
||||
</template> -->
|
||||
<!-- <template #fxDj="{ row }">
|
||||
<DictTag :tag="false" :value="row.fxDj" :options="D_GS_RQFJ_FXDJ"/>
|
||||
</template> -->
|
||||
<template #zz="{ row }">
|
||||
<template v-if="row.zz">
|
||||
<span v-for="(item, index) in jsonParse(row.zz)" :key="index">{{ item.zzmc }}
|
||||
<span v-if="index < jsonParse(row.zz).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #sfbq="{ row }">
|
||||
<template v-if="row.sfbq">
|
||||
<span v-for="(item, index) in jsonParse(row.sfbq)" :key="index">{{ item.bqmc }}
|
||||
<span v-if="index < jsonParse(row.sfbq).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #xwbq="{ row }">
|
||||
<template v-if="row.xwbq">
|
||||
<span v-for="(item, index) in jsonParse(row.xwbq)" :key="index">{{ item.bqmc }}
|
||||
<span v-if="index < jsonParse(row.xwbq).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #dd="{ row }">
|
||||
<template v-if="row.dd">
|
||||
<span v-for="(item, index) in jsonParse(row.dd)" :key="index">{{ item.dz }}
|
||||
<span v-if="index < jsonParse(row.dd).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #controls="{ row }">
|
||||
<el-link type="primary" size="small" @click="yzSsyjpzMxgzxl( row.id)">运行规则</el-link>
|
||||
<el-link type="primary" size="small" @click="openAddRule('edit',item, row)">修改</el-link>
|
||||
<el-link type="primary" size="small" @click="openAddRule('detail',item, row)">详情</el-link>
|
||||
<!-- <el-link type="primary" size="small" @click="openAddRule('detail',item, row)">预警列表</el-link> -->
|
||||
<el-link type="danger" size="small" @click="deleteRule(row.id)">删除</el-link>
|
||||
|
||||
</template>
|
||||
</MyTable>
|
||||
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
|
||||
...pageData.pageConfiger,
|
||||
total: pageData.total
|
||||
}"></Pages>
|
||||
</div>
|
||||
</div>
|
||||
<List ref="regulation" :dict="{ D_BZ_RYBQ }" @getList="getList" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessage } from "element-plus";
|
||||
import List from "../list";
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { getSsyjpzPageList, deleteSsyjpz,getSsyjpzMxgzxl } from "@/api/model";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
import { template } from "lodash";
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_BZ_RYBQ } = proxy.$dict("D_BZ_RYBQ")
|
||||
const regulation = ref(null)
|
||||
const queryFrom = ref({})
|
||||
const searchBox = ref(); //搜索框
|
||||
|
||||
const searchConfiger = ref([
|
||||
{
|
||||
label: "规则名称",
|
||||
prop: "gzmc",
|
||||
placeholder: "请输入规则名称",
|
||||
showType: "input"
|
||||
},
|
||||
{
|
||||
label: "时间",
|
||||
prop: "startTime",
|
||||
placeholder: "请选择时间",
|
||||
showType: "daterange"
|
||||
},
|
||||
]);
|
||||
|
||||
const pageData = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "null",
|
||||
loading: false
|
||||
},
|
||||
total: 0,
|
||||
pageConfiger: {
|
||||
pageSize: 20,
|
||||
pageCurrent: 1
|
||||
},
|
||||
controlsWidth: 300,
|
||||
tableColumn: [
|
||||
{ label: "规则名称", prop: "gzmc", showOverflowTooltip: true },
|
||||
{ label: "开始时间", prop: "jssj", showOverflowTooltip: true },
|
||||
{ label: "结束时间", prop: "kssj", showOverflowTooltip: true },
|
||||
// { label: "条件", prop: "tjName", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "组织", prop: "zz", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "身份标签", prop: "sfbq", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "行为标签", prop: "xwbq", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "地址", prop: "dd", showOverflowTooltip: true, showSolt: true },
|
||||
]
|
||||
});
|
||||
onMounted(() => {
|
||||
getList();
|
||||
tabHeightFn();
|
||||
});
|
||||
|
||||
// 搜索
|
||||
const onSearch = (val) => {
|
||||
queryFrom.value.startTime = val.startTime&&val.startTime.length > 0 ? val.startTime[0] : '';
|
||||
queryFrom.value.endTime = val.startTime&&val.startTime.length > 0 ? val.startTime[1] : '';
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeNo = (val) => {
|
||||
pageData.pageConfiger.pageCurrent = val;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeSize = (val) => {
|
||||
pageData.pageConfiger.pageSize = val;
|
||||
getList();
|
||||
};
|
||||
//
|
||||
// 获取列表
|
||||
const getList = () => {
|
||||
|
||||
const promes = {
|
||||
...pageData.pageConfiger,
|
||||
...queryFrom.value,
|
||||
mxid:props.item.id
|
||||
}
|
||||
getSsyjpzPageList(promes).then((res) => {
|
||||
pageData.tableData = res.records
|
||||
pageData.total = res.total
|
||||
});
|
||||
};
|
||||
const retenHome = () => {
|
||||
emitter.emit('changeModel', { name: '研判首页', row: {} });
|
||||
}
|
||||
const openAddRule = (type, item, row) => {
|
||||
regulation.value.init(type, item, row)
|
||||
}
|
||||
const ids = ref([])
|
||||
|
||||
const chooseData = (val) => {
|
||||
ids.value = val.map(item => item.id)
|
||||
}
|
||||
const deleteRule = (row) => {
|
||||
proxy.$confirm('是否删除该规则, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let list
|
||||
if (Array.isArray(row)) {
|
||||
list = ids.value
|
||||
} else {
|
||||
list =[row]
|
||||
}
|
||||
deleteSsyjpz({ids:list}).then(() => {
|
||||
ElMessage.success("删除成功");
|
||||
getList()
|
||||
})
|
||||
}).catch((err) => {
|
||||
proxy.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
});
|
||||
});
|
||||
}
|
||||
const yzSsyjpzMxgzxl = (params) => {
|
||||
getSsyjpzMxgzxl({id:params}).then((res) => {
|
||||
console.log(res);
|
||||
})
|
||||
}
|
||||
const jsonParse = (val) => {
|
||||
if (val) {
|
||||
return JSON.parse(val)
|
||||
}
|
||||
}
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.control-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,638 +0,0 @@
|
||||
<template>
|
||||
<!-- 可用条件类型列表 -->
|
||||
<div class="regulation-wrapper">
|
||||
<div class="rule-name-section flex align-center">
|
||||
<div class="rule-name-label">规则名称:</div>
|
||||
<el-input v-model="gzmc" :disabled="disabled" placeholder="请输入规则名称" class="search-input" clearable></el-input>
|
||||
</div>
|
||||
<!-- 可用条件区域 -->
|
||||
<div class="condition-section">
|
||||
<div class="available-conditions">
|
||||
<VueDraggable class="flex-wrap" v-model="dataList" ghostClass="ghost"
|
||||
:group="{ name: 'people', pull: 'clone', put: false }" :clone="clone">
|
||||
<el-button v-for="item in dataList" :key="item.name" class="condition-button" size="small">
|
||||
<i class="el-icon-document-add"></i>
|
||||
{{ item.name }}
|
||||
</el-button>
|
||||
</VueDraggable>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 拖拽提示 -->
|
||||
<div class="drag-hint">
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
<span>拖拽条件到下方区域</span>
|
||||
</div>
|
||||
|
||||
<!-- 已选条件区域 -->
|
||||
<div class="selected-section">
|
||||
<div class="section-title">
|
||||
<i class="el-icon-check-square"></i>
|
||||
<span>已选条件</span>
|
||||
<span class="selected-count">{{ copyList.length }}</span>
|
||||
</div>
|
||||
<div class="selected-container">
|
||||
<VueDraggable v-model="copyList" :group="{ name: 'people', pull: !disabled, put: !disabled }" ghostClass="ghost"
|
||||
class="selected-list" itemKey="name">
|
||||
<div v-for="(item, indexs) in copyList" :key="item" class="draggable-item">
|
||||
|
||||
<div class="item-content">
|
||||
<div v-if="!disabled" class="item-remove-btn" @click="romes(item)"><el-icon :size="16">
|
||||
<Close />
|
||||
</el-icon></div>
|
||||
<span class="item-text">{{ item.name }}</span>
|
||||
</div>
|
||||
<div v-if="item[item['key']]">
|
||||
<template v-if="item.key == 'dd'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
|
||||
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
|
||||
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
|
||||
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="item.key == 'sfbq'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input @click="chooseIdentityVisible = true" v-model="item[item['key']][index].bqmc"
|
||||
:placeholder="`请输入${item.name}`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" @click="removeItem(item['key'], index)" type="danger"
|
||||
size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- <template v-if="item.key == 'cs'">
|
||||
<div class="count-condition-container">
|
||||
<el-select v-model="item[item['key']].tj" placeholder="请选择条件" class="condition-select">
|
||||
<el-option :label="item" :value="item" v-for="(item, index) in dataConst" :key="index"></el-option>
|
||||
</el-select>
|
||||
<el-input-number v-model="item[item['key']].cs" :min="1" :max="1000" />
|
||||
</div>
|
||||
</template> -->
|
||||
<template v-if="item.key == 'xwbq'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input @click="chooseMarksVisible = true" v-model="item[item['key']][index].bqmc"
|
||||
:placeholder="`请输入${item.name}`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" @click="removeItem(item['key'], index)" type="danger"
|
||||
size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'zz'">
|
||||
<div class="condition-input-container flex just-between" v-for="(value, index) in item[item['key']]">
|
||||
<div>
|
||||
<el-input v-model="item[item['key']][index]" :placeholder="`请输入${item.name}`" clearable></el-input>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="btn-margin-right" v-if="index == item[item['key']].length - 1"
|
||||
@click="addInput(item['key'], indexs)" type="danger" size="mini">+</el-button>
|
||||
<el-button class="btn-margin-right" v-if="index != item[item['key']].length - 1"
|
||||
@click="removeItem(item['key'], index)" type="danger" size="mini">-</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'kssj'">
|
||||
<div class="condition-input-container flex just-between">
|
||||
<div>
|
||||
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
|
||||
type="date" :placeholder="`请选择${item.name}`" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.key == 'jssj'">
|
||||
<div class="condition-input-container flex just-between">
|
||||
<div>
|
||||
<el-date-picker value-format="YYYY-MM-DD" format="YYYY-MM-DD" v-model="item[item['key']]"
|
||||
type="date" :placeholder="`请选择${item.name}`" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</VueDraggable>
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<div v-if="copyList.length === 0" class="empty-state">
|
||||
<i class="el-icon-tickets"></i>
|
||||
<p>暂无已选条件</p>
|
||||
<p class="empty-tip">从上方拖拽条件到此处</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ChooseMarks v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" />
|
||||
<ChooseIdentity v-model="chooseIdentityVisible" @choosed="choosedIdentity" :roleIds="roleIdsIdentity" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import ChooseMarks from "@/components/ChooseList/ChooseMarks/index.vue";
|
||||
import ChooseIdentity from "@/components/ChooseList/ChooseIdentity/index.vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { VueDraggable } from 'vue-draggable-plus'//npm install vue-draggable-plus
|
||||
const props = defineProps({
|
||||
dict: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [
|
||||
'Joao',
|
||||
'Jean',
|
||||
'Johanna',
|
||||
'Juan',
|
||||
],
|
||||
}, defaultData: {
|
||||
type: Object,
|
||||
default: () => { },
|
||||
}, disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const dataConst = reactive([
|
||||
">",
|
||||
"<",
|
||||
"="
|
||||
])
|
||||
const gzmc = ref('')
|
||||
const dataList = ref(props.list)
|
||||
const copyList = ref([])
|
||||
const clone = (val) => {
|
||||
const data = copyList.value.find(item => item.name == val.name)
|
||||
if (data) {
|
||||
console.log("已存在")
|
||||
} else {
|
||||
// if (val.key == 'cs') {
|
||||
// return {
|
||||
// name: val.name,
|
||||
// key: val.key,
|
||||
// [val["key"]]: {}
|
||||
// }
|
||||
// } else {
|
||||
if (val.key == 'cs') {
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: []
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
name: val.name,
|
||||
key: val.key,
|
||||
[val["key"]]: [""]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
watch(() => props.defaultData, (val) => {
|
||||
if (val) {
|
||||
gzmc.value = val.gzmc
|
||||
const data = props.list.map(item => {
|
||||
|
||||
switch (item.key) {
|
||||
// case 'cs':
|
||||
// return {
|
||||
// name: item.name,
|
||||
// key: item.key,
|
||||
// [item["key"]]: {
|
||||
// cs: val.cs,
|
||||
// tj: val.tj
|
||||
// }
|
||||
// }
|
||||
case 'jssj':
|
||||
case 'kssj':
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? val[item.key] : null,
|
||||
}
|
||||
case 'zz':
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.zzmc) : null,
|
||||
}
|
||||
case 'dd':
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]).map(item => item.dz) : null,
|
||||
}
|
||||
default:
|
||||
return {
|
||||
name: item.name,
|
||||
key: item.key,
|
||||
[item["key"]]: val[item.key] ? JSON.parse(val[item.key]) : null
|
||||
}
|
||||
}
|
||||
})
|
||||
copyList.value = data.filter(item => {
|
||||
return item[item.key] != null
|
||||
})
|
||||
|
||||
}
|
||||
}, { deep: true, immediate: true })
|
||||
const addInput = (key, index) => {
|
||||
copyList.value[index][key].push("")
|
||||
}
|
||||
|
||||
// 移除项目
|
||||
const removeItem = (key, index) => {
|
||||
const data = copyList.value.findIndex(item => item.key == key)
|
||||
if (copyList.value[data][key].length == 1) {
|
||||
return
|
||||
}
|
||||
copyList.value[data][key].splice(index, 1)
|
||||
}
|
||||
|
||||
// 选择预警标签
|
||||
const roleIds = ref([])
|
||||
const chooseMarksVisible = ref()
|
||||
const choosed = (val) => {
|
||||
roleIds.value = val.map(item => item.id)
|
||||
copyList.value.find(item => item.key == 'xwbq')['xwbq'] = val.map(item => {
|
||||
return {
|
||||
bqdm: item.bqDm,
|
||||
bqmc: item.bqMc
|
||||
}
|
||||
})
|
||||
}
|
||||
// 选择身份标签
|
||||
const chooseIdentityVisible = ref()
|
||||
const roleIdsIdentity = ref([])
|
||||
const choosedIdentity = (val) => {
|
||||
roleIdsIdentity.value = val.map(item => item.id)
|
||||
copyList.value.find(item => item.key == 'sfbq')['sfbq'] = val.map(item => {
|
||||
return {
|
||||
bqdm: item.bqDm,
|
||||
bqmc: item.bqMc
|
||||
}
|
||||
})
|
||||
}
|
||||
const romes = (val) => {
|
||||
copyList.value = copyList.value.filter(item => item.key !== val.key)
|
||||
}
|
||||
|
||||
const promes = ref({})
|
||||
// 新增
|
||||
const retValue = () => {
|
||||
if (gzmc.value == '') {
|
||||
return
|
||||
}
|
||||
const data = copyList.value.map(item => {
|
||||
return {
|
||||
[item.key]: item[item.key]
|
||||
}
|
||||
})
|
||||
promes.value = data.reduce((acc, cur) => {
|
||||
console.log(cur);
|
||||
|
||||
return { ...acc, ...cur }
|
||||
}, {})
|
||||
promes.value = { ...promes.value, gzmc: gzmc.value }
|
||||
if (promes.value.dd && promes.value.dd.length > 0) {
|
||||
promes.value.dd = promes.value.dd.map(item => {
|
||||
return { dz: item }
|
||||
})
|
||||
}
|
||||
if (promes.value.zz && promes.value.zz.length > 0) {
|
||||
promes.value.zz = promes.value.zz.map(item => {
|
||||
return { zzmc: item }
|
||||
})
|
||||
}
|
||||
promes.value.kssj = promes.value.kssj ? promes.value.kssj.toString() : null
|
||||
promes.value.jssj = promes.value.jssj ? promes.value.jssj.toString() : null
|
||||
const retData = {
|
||||
...promes.value,
|
||||
dd: promes.value.dd ? JSON.stringify(promes.value.dd) : null,
|
||||
sfbq: promes.value.sfbq ? JSON.stringify(promes.value.sfbq) :null,
|
||||
xwbq: promes.value.xwbq ? JSON.stringify(promes.value.xwbq) :null,
|
||||
zz: promes.value.zz ? JSON.stringify(promes.value.zz) :null,
|
||||
}
|
||||
return retData
|
||||
}
|
||||
defineExpose({
|
||||
retValue
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.regulation-wrapper {
|
||||
padding: 20px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
// 条件区域通用样式
|
||||
.condition-section,
|
||||
.selected-section {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
// margin-bottom: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.condition-section:hover,
|
||||
.selected-section:hover {
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
// 区域标题
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
color: #303133;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 2px solid #e6f7ff;
|
||||
|
||||
i {
|
||||
color: #409eff;
|
||||
margin-right: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.selected-count {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
color: #606266;
|
||||
background: #f0f9ff;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
min-width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// 可用条件区域
|
||||
.available-conditions {
|
||||
// min-height: 100px;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.condition-button {
|
||||
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
border-radius: 8px !important;
|
||||
padding: 8px 16px !important;
|
||||
font-size: 14px !important;
|
||||
transition: all 0.3s ease !important;
|
||||
min-width: 120px;
|
||||
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(135deg, #66b1ff 0%, #409eff 100%) !important;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
// 拖拽提示
|
||||
.drag-hint {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
// align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
font-size: 16px;
|
||||
animation: bounce 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 已选条件区域
|
||||
.selected-container {
|
||||
min-height: 120px;
|
||||
border: 2px dashed #dcdfe6;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
transition: all 0.3s ease;
|
||||
background-color: #dcdfe670;
|
||||
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
background: #f0f9ff;
|
||||
}
|
||||
}
|
||||
|
||||
.selected-list {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
// 拖拽项样式
|
||||
.draggable-item {
|
||||
position: relative;
|
||||
// background: rgba(103, 194, 58, 0.3);
|
||||
padding: 3px;
|
||||
margin: 8px;
|
||||
// box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: table-cell;
|
||||
justify-content: space-between;
|
||||
// cursor: move;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px) scale(1.02);
|
||||
box-shadow: 0 6px 16px rgba(103, 194, 58, 0.4);
|
||||
}
|
||||
|
||||
&.ghost {
|
||||
opacity: 0.6;
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 20px 12px 12px 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-width: 140px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.item-remove {
|
||||
color: #c0c4cc;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
padding: 4px;
|
||||
border-radius: 50%;
|
||||
|
||||
&:hover {
|
||||
color: #f56c6c;
|
||||
background: #fef0f0;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 规则名称区域 */
|
||||
.rule-name-section {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.rule-name-label {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
/* 项目删除按钮 */
|
||||
.item-remove-btn {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
/* 条件输入容器 */
|
||||
.condition-input-container {
|
||||
flex-wrap: nowrap;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* 计数条件容器 */
|
||||
.count-condition-container {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* 条件选择框 */
|
||||
.condition-select {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
/* 按钮右侧边距 */
|
||||
.btn-margin-right {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
// 空状态样式
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: #909399;
|
||||
|
||||
i {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
color: #dcdfe6;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
font-size: 12px;
|
||||
color: #c0c4cc;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&:hover i {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
// 拖拽效果
|
||||
.ghost {
|
||||
opacity: 0.6;
|
||||
background-color: #e6f7ff;
|
||||
border: 2px dashed #409eff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.regulation-wrapper {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.condition-section,
|
||||
.selected-section {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.condition-button {
|
||||
min-width: 100px;
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
min-width: 120px;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
:v-deep .el-select {
|
||||
width: 59%;
|
||||
}
|
||||
</style>
|
||||
@ -1,234 +0,0 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<span class="title">{{ title }}规则 </span>
|
||||
<div>
|
||||
<el-button type="primary" size="small" :loading="loading" @click="submit" v-show="title != '详情'">保存</el-button>
|
||||
<el-button size="small" @click="close">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form_cnt">
|
||||
<EarlyWarning :list="listData" v-if=" listQuery.mxlx=='01'" ref="regulationRef" :dict="props.dict" :defaultData="defaultData"
|
||||
:disabled="title == '详情'" />
|
||||
<Regulation :list="listData" v-if=" listQuery.mxlx=='02'" ref="regulationRef" :dict="props.dict" :defaultData="defaultData"
|
||||
:disabled="title == '详情'" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElMessage } from "element-plus";
|
||||
import { addSsyjpz, editSsyjpz,addYjgzpz,editYjgzpz } from '@/api/model'
|
||||
import Regulation from "../components/FourColor/regulation.vue";
|
||||
import EarlyWarning from "../components/EarlyWarning/regulation.vue";
|
||||
const props = defineProps({
|
||||
dict: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
}
|
||||
})
|
||||
const dialogForm = ref(false)
|
||||
const title = ref("新增")
|
||||
const emit = defineEmits(['getList'])
|
||||
const typeData = {
|
||||
'02': [{
|
||||
name: "地点",
|
||||
key: "dd",
|
||||
id: 1
|
||||
}, {
|
||||
name: "身份标签",
|
||||
key: "sfbq",
|
||||
id: 2
|
||||
},
|
||||
// {
|
||||
// name: "次数",
|
||||
// key: "cs",
|
||||
// id: 3
|
||||
// },
|
||||
{
|
||||
name: "行为标签",
|
||||
key: "xwbq",
|
||||
id: 4
|
||||
}, {
|
||||
name: "组织",
|
||||
key: "zz",
|
||||
id: 5
|
||||
}, {
|
||||
name: "开始时间",
|
||||
key: "kssj",
|
||||
id: 6
|
||||
}, {
|
||||
name: "结束时间",
|
||||
key: "jssj",
|
||||
id: 7
|
||||
}],
|
||||
'01': [{
|
||||
name: "地点",
|
||||
key: "dd",
|
||||
}, {
|
||||
name: '警情类型',
|
||||
key: 'jqlx',
|
||||
}, {
|
||||
name: '人员信息',
|
||||
key: 'ryxx',
|
||||
}, {
|
||||
name: '事件类型',
|
||||
key: 'sjlx',
|
||||
}, {
|
||||
name: '物品',
|
||||
key: 'wp',
|
||||
}, {
|
||||
name: '组织',
|
||||
key: 'zz',
|
||||
}, {
|
||||
name: '开始时间',
|
||||
key: 'kssj',
|
||||
}, {
|
||||
name: '结束时间',
|
||||
key: 'jssj',
|
||||
}, {
|
||||
name: '次数',
|
||||
key: 'cs',
|
||||
}],
|
||||
|
||||
}
|
||||
const listData = ref([])
|
||||
const listQuery = ref()
|
||||
const defaultData = ref({})
|
||||
const mxlx=ref()
|
||||
const init = (type, item, row) => {
|
||||
dialogForm.value = true
|
||||
listQuery.value = item
|
||||
listData.value = typeData[item.mxlx]
|
||||
|
||||
if (type == 'edit') {
|
||||
defaultData.value = row
|
||||
title.value = "编辑"
|
||||
} else if (type == 'add') {
|
||||
defaultData.value={}
|
||||
title.value = "新增"
|
||||
} else {
|
||||
title.value = "详情"
|
||||
defaultData.value = row
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const regulationRef = ref(null)
|
||||
const loading = ref(false)
|
||||
// 新增
|
||||
const submit = () => {
|
||||
|
||||
switch (listQuery.value.mxlx) {
|
||||
case '01':
|
||||
addYjgzpzs()
|
||||
break;
|
||||
case '02':
|
||||
addSsyj()
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
const addSsyj = () => {
|
||||
const data = regulationRef.value.retValue()
|
||||
if (!data||!data.gzmc) {
|
||||
ElMessage.warning('请填写规则名称')
|
||||
return
|
||||
}
|
||||
if (title.value == "新增") {
|
||||
const promes = {
|
||||
mxid: listQuery.value.id,
|
||||
...data
|
||||
}
|
||||
addSsyjpz(promes).then((result) => {
|
||||
ElMessage.success('新增成功')
|
||||
emit('getList')
|
||||
close()
|
||||
}).catch((err) => {
|
||||
ElMessage.error(err.message)
|
||||
});
|
||||
} else {
|
||||
editSsyjpz({
|
||||
id: defaultData.value.id,
|
||||
...data
|
||||
}).then((result) => {
|
||||
ElMessage.success('编辑成功')
|
||||
emit('getList')
|
||||
close()
|
||||
}).catch((err) => {
|
||||
ElMessage.error(err.message)
|
||||
});
|
||||
}
|
||||
}
|
||||
const addYjgzpzs = () => {
|
||||
const data = regulationRef.value.retValue()
|
||||
if (!data||!data.gzmc) {
|
||||
ElMessage.warning('请填写规则名称')
|
||||
return
|
||||
}
|
||||
if (title.value == "新增") {
|
||||
const promes = {
|
||||
mxid: listQuery.value.id,
|
||||
...data
|
||||
}
|
||||
addYjgzpz(promes).then((result) => {
|
||||
ElMessage.success('新增成功')
|
||||
emit('getList')
|
||||
close()
|
||||
}).catch((err) => {
|
||||
ElMessage.error(err.message)
|
||||
});
|
||||
} else {
|
||||
editYjgzpz({
|
||||
id: defaultData.value.id,
|
||||
...data
|
||||
}).then((result) => {
|
||||
ElMessage.success('编辑成功')
|
||||
emit('getList')
|
||||
close()
|
||||
}).catch((err) => {
|
||||
ElMessage.error(err.message)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const close = () => {
|
||||
dialogForm.value = false
|
||||
}
|
||||
defineExpose({
|
||||
init,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .el-button+.el-button {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.just-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.mb-10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.mr-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,273 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="预警列表">
|
||||
<el-button type="primary" size="small" @click="openAddRule('add', item)">新增</el-button>
|
||||
<el-button type="primary" size="small" :disabled="ids.length == 0" @click="deleteRule(ids)">批量删除</el-button>
|
||||
<el-button size="small" @click="retenHome()">返回</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
<div ref="searchBox">
|
||||
<Search :searchArr="searchConfiger" @submit="onSearch" />
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox">
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
|
||||
@chooseData="chooseData">
|
||||
<template #tjName="{ row }">
|
||||
<div class="flex one_text_detail" v-if="row.tj">{{ ` ${row.tj} ${row.cs}` }} </div>
|
||||
</template>
|
||||
<template #zz="{ row }">
|
||||
<template v-if="row.zz">
|
||||
<span v-for="(item, index) in jsonParse(row.zz)" :key="index">{{ item.zzmc }}
|
||||
<span v-if="index < jsonParse(row.zz).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #sfbq="{ row }">
|
||||
<template v-if="row.sfbq">
|
||||
<span v-for="(item, index) in jsonParse(row.sfbq)" :key="index">{{ item.bqmc }}
|
||||
<span v-if="index < jsonParse(row.sfbq).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #xwbq="{ row }">
|
||||
<template v-if="row.xwbq">
|
||||
<span v-for="(item, index) in jsonParse(row.xwbq)" :key="index">{{ item.bqmc }}
|
||||
<span v-if="index < jsonParse(row.xwbq).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #dd="{ row }">
|
||||
<template v-if="row.dd">
|
||||
<span v-for="(item, index) in jsonParse(row.dd)" :key="index">{{ item.dz }}
|
||||
<span v-if="index < jsonParse(row.dd).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #ryxx="{ row }">
|
||||
<template v-if="row.ryxx">
|
||||
<span v-for="(item, index) in jsonParse(row.ryxx)" :key="index">{{ item.xm }}
|
||||
<span v-if="index < jsonParse(row.ryxx).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #jqlx="{ row }">
|
||||
<template v-if="row.jqlx">
|
||||
<span v-for="(item, index) in jsonParse(row.jqlx)" :key="index">{{ item.lxmc }}
|
||||
<span v-if="index < jsonParse(row.jqlx).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #sjlx="{ row }">
|
||||
<template v-if="row.sjlx">
|
||||
<span v-for="(item, index) in jsonParse(row.sjlx)" :key="index">{{ item.lxmc }}
|
||||
<span v-if="index < jsonParse(row.sjlx).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #wp="{ row }">
|
||||
<template v-if="row.wp">
|
||||
<span v-for="(item, index) in jsonParse(row.wp)" :key="index">{{ item.wpmc }}
|
||||
<span v-if="index < jsonParse(row.wp).length - 1">、</span>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #controls="{ row }">
|
||||
<el-link type="primary" size="small" @click="yzSsyjpzMxgzxl( row.id)">运行规则</el-link>
|
||||
<el-link type="primary" size="small" @click="openAddRule('edit',item, row)">修改</el-link>
|
||||
<el-link type="primary" size="small" @click="openAddRule('detail',item, row)">详情</el-link>
|
||||
<!-- <el-link type="primary" size="small" @click="openAddRule('detail',item, row)">预警列表</el-link> -->
|
||||
<el-link type="danger" size="small" @click="deleteRule(row.id)">删除</el-link>
|
||||
|
||||
</template>
|
||||
</MyTable>
|
||||
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
|
||||
...pageData.pageConfiger,
|
||||
total: pageData.total
|
||||
}"></Pages>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessage } from "element-plus";
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { deleteYjgzpz,getYjgzpzMxgzxl,getYjxxPageList } from "@/api/model";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
import { template } from "lodash";
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_BB_AJLB,D_BZ_WPLX} = proxy.$dict("D_BB_AJLB","D_BZ_WPLX")
|
||||
const regulation = ref(null)
|
||||
const queryFrom = ref({})
|
||||
const searchBox = ref(); //搜索框
|
||||
|
||||
const searchConfiger = ref([
|
||||
|
||||
{
|
||||
label: "时间",
|
||||
prop: "startTime",
|
||||
placeholder: "请选择时间",
|
||||
showType: "daterange"
|
||||
},
|
||||
]);
|
||||
const pageData = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "null",
|
||||
loading: false
|
||||
},
|
||||
total: 0,
|
||||
pageConfiger: {
|
||||
pageSize: 20,
|
||||
pageCurrent: 1
|
||||
},
|
||||
controlsWidth: 300,
|
||||
tableColumn: [
|
||||
{ label: "预警时间", prop: "gzmc", showOverflowTooltip: true },
|
||||
{ label: "类型", prop: "jssj", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "内容", prop: "kssj", showOverflowTooltip: true, showSolt: true },
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
tabHeightFn();
|
||||
});
|
||||
|
||||
// 搜索
|
||||
const onSearch = (val) => {
|
||||
queryFrom.value.startTime = val.startTime&&val.startTime.length > 0 ? val.startTime[0] : '';
|
||||
queryFrom.value.endTime = val.startTime&&val.startTime.length > 0 ? val.startTime[1] : '';
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeNo = (val) => {
|
||||
pageData.pageConfiger.pageCurrent = val;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeSize = (val) => {
|
||||
pageData.pageConfiger.pageSize = val;
|
||||
getList();
|
||||
};
|
||||
//
|
||||
// 获取列表
|
||||
const getList = () => {
|
||||
const promes = {
|
||||
...pageData.pageConfiger,
|
||||
...queryFrom.value,
|
||||
mxid:props.item.id,
|
||||
}
|
||||
getYjxxPageList(promes).then((res) => {
|
||||
pageData.tableData = res.records
|
||||
pageData.total = res.total
|
||||
});
|
||||
};
|
||||
const retenHome = () => {
|
||||
emitter.emit('changeModel', { name: '研判首页', row: {} });
|
||||
}
|
||||
const openAddRule = (type, item, row) => {
|
||||
regulation.value.init(type, item, row)
|
||||
}
|
||||
const ids = ref([])
|
||||
|
||||
const chooseData = (val) => {
|
||||
ids.value = val.map(item => item.id)
|
||||
}
|
||||
const deleteRule = (row) => {
|
||||
proxy.$confirm('是否删除该规则, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let list
|
||||
if (Array.isArray(row)) {
|
||||
list = ids.value
|
||||
} else {
|
||||
list =[row]
|
||||
}
|
||||
deleteYjgzpz({ids:list}).then(() => {
|
||||
ElMessage.success("删除成功");
|
||||
getList()
|
||||
})
|
||||
}).catch((err) => {
|
||||
proxy.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
});
|
||||
});
|
||||
}
|
||||
const yzSsyjpzMxgzxl = (params) => {
|
||||
getYjgzpzMxgzxl({id:params}).then((res) => {
|
||||
console.log(res);
|
||||
})
|
||||
}
|
||||
const jsonParse = (val) => {
|
||||
if (val) {
|
||||
return JSON.parse(val)
|
||||
}
|
||||
}
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.control-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,321 +0,0 @@
|
||||
<template>
|
||||
<!-- 研判类型 -->
|
||||
<div class="content">
|
||||
<div class="titleBox">
|
||||
<PageTitle title="模型平台">
|
||||
<el-button type="primary" @click="openAddModel('add')" :icon="CirclePlus">
|
||||
新增模型
|
||||
</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
<div ref="searchBox">
|
||||
<Search :searchArr="searchConfiger" @submit="onSearch"> </Search>
|
||||
</div>
|
||||
<ul class="cntlsit mb10" v-if="show" v-infinite-scroll="load" :style="{ height: listHeight + 'px' }"
|
||||
v-loading="loading">
|
||||
<li class="model-card" v-for="(it, idx) in list" :key="idx">
|
||||
<div class="model-info">
|
||||
<div class="model-name">
|
||||
<strong>模型名称:</strong>{{ it.mxmc }}
|
||||
</div>
|
||||
<div class="model-type flex">
|
||||
<strong>模型类型:</strong> <DictTag :tag="false" :value="it.mxlx" :options="D_MXGL_MXLX" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="model-image-container" @click="openYjList">
|
||||
<img class="model-image"
|
||||
src="@/assets/images/mxbg.jpg" alt="">
|
||||
</div>
|
||||
<div class="model-actions">
|
||||
<span class="action-btn action-btn-view" @click.stop="openAddRule('', it)">
|
||||
<el-icon class="action-icon"><Document /></el-icon>查看规则
|
||||
</span>
|
||||
<span class="action-btn action-btn-edit" @click.stop="openAddModel('edit', it)">
|
||||
<el-icon class="action-icon"><ChatDotSquare /></el-icon>编辑
|
||||
</span>
|
||||
<span class="action-btn action-btn-edit" @click.stop="openAddModel('detail', it)">
|
||||
<el-icon class="action-icon"><Edit /></el-icon>详情
|
||||
</span>
|
||||
<span class="action-btn action-btn-delete" @click.stop="delDictItem(it.id)">
|
||||
<el-icon class="action-icon"><Files /></el-icon>删除
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<div class="empty-container">
|
||||
<MOSTY.Empty :show="!loading && list.length <= 0"></MOSTY.Empty>
|
||||
</div>
|
||||
<div class="no-more-data" v-if="total == list.length && total > 0">暂时没有数据了!</div>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- <AddModel ref="addModel" :dict="{ D_MXGL_MXLX }" @getLits="getLits" /> -->
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import { getPageList, deleteEntity } from '@/api/model.js'
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { CirclePlus } from '@element-plus/icons-vue'
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import { reactive, ref, onMounted, getCurrentInstance, watch, defineEmits } from "vue";
|
||||
// import AddModel from "../components/AddModel/addModel";
|
||||
const emit = defineEmits(['change'])
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_MXGL_MXLX ,D_BZ_RYBQ} = proxy.$dict("D_MXGL_MXLX","D_BZ_RYBQ")
|
||||
const searchBox = ref(); //搜索框
|
||||
const show = ref(false)
|
||||
const listHeight = ref()
|
||||
const searchConfiger = ref([
|
||||
{ label: "模型名称", prop: "mxmc", placeholder: "请输入模型名称", showType: "input" },
|
||||
{
|
||||
label: "模型类型",
|
||||
prop: "mxlx",
|
||||
placeholder: "请选择模型类型",
|
||||
showType: "select",
|
||||
options: D_MXGL_MXLX
|
||||
},
|
||||
]);
|
||||
const PaginationConfig = reactive({
|
||||
pageCurrent: 1,
|
||||
pageSize: 8,
|
||||
});
|
||||
const total = ref(0)
|
||||
const list = ref([])
|
||||
const loading = ref(false);
|
||||
const formData = ref({})
|
||||
onMounted(() => {
|
||||
show.value = true;
|
||||
tabHeightFn();
|
||||
getLits()
|
||||
})
|
||||
|
||||
|
||||
const onSearch = (val) => {
|
||||
formData.value = { ...formData.value, ...val, };
|
||||
PaginationConfig.pageCurrent = 1;
|
||||
getLits();
|
||||
}
|
||||
const load = () => {
|
||||
if (total.value == list.value.length) return;
|
||||
PaginationConfig.pageCurrent++;
|
||||
// getLits();
|
||||
}
|
||||
const getLits = () => {
|
||||
let params = {
|
||||
...PaginationConfig,
|
||||
...formData.value
|
||||
}
|
||||
loading.value = true;
|
||||
|
||||
getPageList(params).then(res => {
|
||||
let arr = res.records || [];
|
||||
list.value = PaginationConfig.pageCurrent == 1 ? arr : list.value.concat(arr);
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
listHeight.value = window.innerHeight - searchBox.value.offsetHeight - 230;
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
const delDictItem = (id) => {
|
||||
proxy.$confirm('是否删除该模型, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
deleteEntity({ ids: [id] }).then(res => {
|
||||
proxy.$message.success("删除成功!")
|
||||
getLits()
|
||||
})
|
||||
}).catch(() => {
|
||||
proxy.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
// 打开弹窗
|
||||
const addModel = ref(null)
|
||||
const openAddModel = (type, row) => {
|
||||
addModel.value.init(type, row)
|
||||
}
|
||||
// 打开规则弹窗
|
||||
const openAddRule = (type, row) => {
|
||||
switch (row.mxlx) {
|
||||
case '02':
|
||||
emitter.emit('changeModel', {row,name:'四色预警规则'})
|
||||
break;
|
||||
case '01':
|
||||
emitter.emit('changeModel', {row,name:'预警规则'})
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
const openYjList = (row) => {
|
||||
emitter.emit('changeModel', {row,name:'预警列表'})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-top: 20px;
|
||||
margin-left: 10px;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.btnsBox {
|
||||
background: #fff;
|
||||
padding: 10px 5px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.cntlsit {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: start;
|
||||
gap: 20px;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
background: #fff;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
// 模型卡片样式
|
||||
.model-card {
|
||||
width: 300px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
// 模型信息区域
|
||||
.model-info {
|
||||
padding: 16px;
|
||||
background-color: #fafafa;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
.model-name,
|
||||
.model-type {
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
|
||||
strong {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.model-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 模型图片区域
|
||||
.model-image-container {
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.model-image {
|
||||
width: 100%;
|
||||
height: 168px;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 操作按钮区域
|
||||
.model-actions {
|
||||
text-align: right;
|
||||
padding: 12px 0px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
background-color: #fafafa;
|
||||
|
||||
.action-btn {
|
||||
// margin-left: 12px;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
|
||||
.action-icon {
|
||||
margin-right: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.action-btn-view,
|
||||
.action-btn-edit {
|
||||
color: #409eff;
|
||||
|
||||
&:hover {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
}
|
||||
|
||||
.action-btn-delete {
|
||||
color: #f4ac47;
|
||||
|
||||
&:hover {
|
||||
background-color: #fff7e6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 空状态和无更多数据样式
|
||||
.empty-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.no-more-data {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
color: #a29f9f;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<div>详情</div>
|
||||
<div><el-button @click="close">关闭</el-button></div>
|
||||
</div>
|
||||
<div class="form_cnt">
|
||||
<FormMessage v-model="listQuery" disabled :formList="formData" ref="elform">
|
||||
<template #yjTp="{ row }">
|
||||
<template v-if="!listQuery.yjTp || listQuery.yjTp.includes('baidu')">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="listQuery.yjlx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</template>
|
||||
<el-image v-else style="width: 80px; height:120px" :src="listQuery.yjTp" :preview-src-list="[row.yjTp]"
|
||||
show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="listQuery.yjlx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
</FormMessage>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import FormMessage from "@/components/aboutTable/FormMessage.vue";
|
||||
import { ref, defineExpose } from "vue";
|
||||
const props = defineProps({
|
||||
dict: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
const dialogForm = ref(false); //弹窗
|
||||
const formData = ref([
|
||||
{ label: "预警照片", prop: "yjTp", type: "slot", width: '100%' },
|
||||
{ label: "预警名称", prop: "yjBt", type: "input" },
|
||||
{ label: "预警人员姓名", prop: "yjRyxm", type: "input" },
|
||||
{ label: "车牌号", prop: "yjClcph", type: "input" },
|
||||
{ label: "身份证号", prop: "yjRysfzh", type: "input" },
|
||||
{ label: "预警地址", prop: "yjDz", type: "input" },
|
||||
{ label: "预警时间", prop: "yjsj", type: "date" },
|
||||
{ label: "预警类型", prop: "yjlx", type: "select", options: props.dict.D_BZ_YJLX },
|
||||
{ label: "预警内容", prop: "yjnr", type: "textarea", width: '100%' },
|
||||
]);
|
||||
const listQuery = ref({}); //表单
|
||||
const elform = ref();
|
||||
// 初始化数据
|
||||
const init = (row) => {
|
||||
dialogForm.value = true;
|
||||
listQuery.value = row;
|
||||
};
|
||||
|
||||
// 关闭
|
||||
const close = () => {
|
||||
listQuery.value = {};
|
||||
dialogForm.value = false;
|
||||
};
|
||||
|
||||
defineExpose({ init });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/assets/css/layout.scss";
|
||||
@import "~@/assets/css/element-plus.scss";
|
||||
|
||||
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
|
||||
color: #0072ff;
|
||||
background: rgba(0, 114, 255, 0.3);
|
||||
}
|
||||
|
||||
.boxlist {
|
||||
width: 99%;
|
||||
height: 225px;
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
::v-deep .avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::v-deep .el-upload-list {
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::v-deep .el-upload-list__item-name .el-icon {
|
||||
top: 3px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="预警详情">
|
||||
<!-- <el-button type="primary" size="small" @click="yzSsyjpzMxgzxl()">测试</el-button> -->
|
||||
<el-button size="small" @click="retenHome()">返回</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
<div ref="searchBox">
|
||||
<Search :searchArr="searchConfiger" @submit="onSearch" />
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox">
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
|
||||
<template #yjTp="{ row }">
|
||||
<template v-if="!row.yjTp || row.yjTp.includes('baidu')">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjlx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</template>
|
||||
<el-image v-else style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]"
|
||||
show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjlx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
<template #yjlx="{ row }">
|
||||
<DictTag :tag="false" :value="row.yjlx" :options="dict.D_BZ_YJLX" />
|
||||
</template>
|
||||
<template #controls="{ row }">
|
||||
<el-link type="primary" size="small" @click="openYjdict(row)">详情</el-link>
|
||||
</template>
|
||||
</MyTable>
|
||||
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
|
||||
...pageData.pageConfiger,
|
||||
total: pageData.total
|
||||
}"></Pages>
|
||||
</div>
|
||||
</div>
|
||||
<DetailsFollows ref="yjdict" :dict="dict" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { mxglJqxqPageList } from "@/api/model";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import { reactive, ref, onMounted, getCurrentInstance, watch } from "vue";
|
||||
import DetailsFollows from './detailsFollows.vue'
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}, dict: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const queryFrom = ref({})
|
||||
const searchBox = ref(); //搜索框
|
||||
const yjdict = ref(null)//详情弹窗
|
||||
const ItemData = ref()//模型数据
|
||||
const searchConfiger = ref([
|
||||
{
|
||||
label: "时间",
|
||||
prop: "startTime",
|
||||
placeholder: "请选择时间",
|
||||
showType: "daterange"
|
||||
},
|
||||
]);
|
||||
const pageData = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "null",
|
||||
loading: false
|
||||
},
|
||||
total: 0,
|
||||
pageConfiger: {
|
||||
pageSize: 20,
|
||||
pageCurrent: 1
|
||||
},
|
||||
controlsWidth: 150,
|
||||
tableColumn: [
|
||||
// { label: "预警名称", prop: "", showOverflowTooltip: true },
|
||||
// { label: "预警图片", prop: "yjTp", showOverflowTooltip: true, showSolt: true },
|
||||
{ label: "报警人", prop: "bjrmc", showOverflowTooltip: true },
|
||||
{ label: "接警单号", prop: "bjh", showOverflowTooltip: true },
|
||||
// { label: "车牌号", prop: "yjClcph", showOverflowTooltip: true },
|
||||
// { label: "身份证号", prop: "yjRysfzh", showOverflowTooltip: true },
|
||||
{ label: "报警时间", prop: "bjsj", showOverflowTooltip: true },
|
||||
{ label: "报警地址", prop: "bjdz", showOverflowTooltip: true },
|
||||
{ label: "类型", prop: "yjlx", showSolt: true },
|
||||
{ label: "报警内容", prop: "bjnr", showOverflowTooltip: true },
|
||||
]
|
||||
});
|
||||
onMounted(() => {
|
||||
getList();
|
||||
tabHeightFn();
|
||||
|
||||
});
|
||||
const openYjdict = (val) => {
|
||||
yjdict.value.init(val)
|
||||
}
|
||||
watch(() => props.item, (val) => {
|
||||
ItemData.value = val
|
||||
}, { deep: true })
|
||||
|
||||
// 获取列表
|
||||
const getList = () => {
|
||||
const promes = {
|
||||
...pageData.pageConfiger,
|
||||
...queryFrom.value,
|
||||
yjid: props.item.id,
|
||||
}
|
||||
mxglJqxqPageList(promes).then((res) => {
|
||||
pageData.tableData = res.records || []
|
||||
pageData.total = res.total
|
||||
});
|
||||
};
|
||||
// 搜索
|
||||
const onSearch = (val) => {
|
||||
queryFrom.value.startTime = val.startTime && val.startTime.length > 0 ? val.startTime[0] : '';
|
||||
queryFrom.value.endTime = val.startTime && val.startTime.length > 0 ? val.startTime[1] : '';
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeNo = (val) => {
|
||||
pageData.pageConfiger.pageCurrent = val;
|
||||
getList();
|
||||
};
|
||||
|
||||
const changeSize = (val) => {
|
||||
pageData.pageConfiger.pageSize = val;
|
||||
getList();
|
||||
};
|
||||
//返回
|
||||
const retenHome = () => {
|
||||
emitter.emit('changeModel', { name: '预警列表', row: {} });
|
||||
}
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.control-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -19,7 +19,8 @@
|
||||
<DictTag :tag="false" :value="row.yjlx" :options="dict.D_BZ_TPYJLX" />
|
||||
</template>
|
||||
<template #controls="{ row }">
|
||||
<el-link type="primary" size="small" @click="opneModel">打开研判报告</el-link>
|
||||
<el-link type="primary" size="small" @click="opneModel(row)">打开研判报告</el-link>
|
||||
<el-link type="primary" size="small" @click="warningDetails(row)">预警详情</el-link>
|
||||
<el-link type="primary" size="small" @click="openYjdict(row)">详情</el-link>
|
||||
</template>
|
||||
</MyTable>
|
||||
@ -36,12 +37,13 @@
|
||||
<script setup>
|
||||
import YpModel from '@/components/ypModel/index.vue'
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { getYjxxPageList,getSsyjpzMxgzxl } from "@/api/model";
|
||||
import { getYjxxPageList,getSsyjpzMxgzxl,mxglYjxqSelectList } from "@/api/model";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
import {timeValidate} from '@/utils/tools'
|
||||
import { timeValidate } from '@/utils/tools'
|
||||
import { completions } from '@/api/semanticAnalysis'
|
||||
import { reactive, ref, onMounted, getCurrentInstance, watch } from "vue";
|
||||
import { textStyle, Firstlevelheading, Subheading, BiheadlinegTitle, newTotitle,BigTitle,fbtool, headTitle, report, signature } from '../content.js'
|
||||
import Yjdict from './yjdict.vue'
|
||||
@ -62,14 +64,41 @@ const showModel = ref(false)
|
||||
const textContent=ref('')//报告数据
|
||||
const SaveReport = () => {
|
||||
}
|
||||
const opneModel = () => {
|
||||
const opneModel = (row) => {
|
||||
showModel.value = true
|
||||
textContent.value=''
|
||||
textContent.value += BigTitle("林芝市公安局情指中心") + BigTitle("研判专刊(初稿)") + newTotitle({
|
||||
textContent.value = ''
|
||||
mxglYjxqSelectList({
|
||||
yjid: row.id,
|
||||
}).then((res) => {
|
||||
let str = {
|
||||
model: "deepseek-32b",
|
||||
prompt: `# 角色定位\n你是一名资深警务人员,尤其擅长对警情、案件、线索等非结构化文本数据进行阅读理解,并从中提取各种对象特征信息进行结构化,并总结各种对象之间的关联关系。\n`,
|
||||
max_tokens: 1000,
|
||||
}
|
||||
res.forEach(item => {
|
||||
const lx = props.dict.D_BZ_YJLX.find(items => {
|
||||
return items.value == item.yjlx
|
||||
}).zdmc
|
||||
str.prompt+=`预警名称:${item.yjBt},预警人员姓名:${item.yjRyxm},身份证号:${item.yjRysfzh},车牌号:${item.yjClcph},预警地址:${item.yjDz},预警类型:${lx},预警内容:${item.yjnr},预警时间:${item.yjsj}\n`
|
||||
})
|
||||
str.prompt += `根据以上预警信息,总结出一个解决方案`
|
||||
let jsonMatch
|
||||
completions(str).then(reslve => {
|
||||
jsonMatch = reslve.choices[0].text
|
||||
textContent.value += BigTitle("林芝市公安局情指中心") + BigTitle("研判专刊(初稿)") + newTotitle({
|
||||
org: "市公安局情指中心编",
|
||||
time: timeValidate()
|
||||
})+fbtool('同类事件发生3次以上预警')+textStyle("2025年9月2日164525,产生同类事件3次以上预警,刑事案件中的置充身份诈美发生3起,同七上升30%、环比比下健5%")
|
||||
+ Subheading('1.警情内容') + Subheading('2.警情内容') + Subheading('3.警情内容')
|
||||
}) + fbtool(`同类事件发生${res.length}次以上预警`)
|
||||
res.forEach((item,index) => {
|
||||
const lx = props.dict.D_BZ_YJLX.find((items) => {
|
||||
return items.value == item.yjlx
|
||||
}).zdmc
|
||||
textContent.value +=Subheading(`${index+1}.警情内容`)+textStyle(`预警名称:${item.yjBt},预警人员姓名:${item.yjRyxm},身份证号:${item.yjRysfzh},车牌号:${item.yjClcph},预警地址:${item.yjDz},预警类型:${lx},预警内容:${item.yjnr},预警时间:${item.yjsj}\n`)
|
||||
})
|
||||
textContent.value+=Subheading(`解决方案`)+textStyle(jsonMatch?jsonMatch:'暂无解决方案')
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const searchConfiger = ref([
|
||||
@ -86,7 +115,7 @@ const pageData = reactive({
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "null",
|
||||
loading: false
|
||||
// loading: false
|
||||
},
|
||||
total: 0,
|
||||
pageConfiger: {
|
||||
@ -159,9 +188,10 @@ const yzSsyjpzMxgzxl = (params) => {
|
||||
// })
|
||||
getSsyjpzMxgzxl({id:'88c166e670da48e59324906648794b05'}).then((res) => {
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const warningDetails = (row) => {
|
||||
emitter.emit('changeModel', { row, name: '预警详情' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,25 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<YpHome v-if="showModel == '研判首页'"></YpHome>
|
||||
<!-- <ModeList v-if="showModel == '四色预警规则'" :item="itemData" ></ModeList>
|
||||
<EarlyWarning v-if="showModel == '预警规则'" :item="itemData" ></EarlyWarning> -->
|
||||
<!-- <YjList v-if="showModel == '预警列表'" :item="itemData" ></YjList> -->
|
||||
<List v-if="showModel == '四色预警规则' || showModel == '预警规则'" :item="itemData"></List>
|
||||
<YjDetail v-if="showModel == '预警列表'" :item="itemData" :dict="{D_BZ_TPYJLX}"></YjDetail>
|
||||
<YjDetail v-if="showModel == '预警列表'" :item="itemData" :dict="{ D_BZ_TPYJLX,D_BZ_YJLX }"></YjDetail>
|
||||
<WarningList v-if="showModel == '预警详情'" :item="itemData" :dict="{ D_BZ_YJLX }"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import YpHome from "./components/ypHome.vue";
|
||||
// import YjList from "./components/yjList.vue";
|
||||
import YjDetail from './components/AddModel/yjList.vue'
|
||||
import List from "./components/list.vue";
|
||||
// import ModeList from "./components/FourColor/modeList.vue";
|
||||
// import EarlyWarning from "./components/EarlyWarning/modeList.vue";
|
||||
import WarningList from "./components/AddModel/warningList.vue"
|
||||
const { proxy } = getCurrentInstance();
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { onMounted, ref, getCurrentInstance } from "vue";
|
||||
const { D_BZ_TPYJLX} = proxy.$dict("D_BZ_TPYJLX")
|
||||
const { D_BZ_TPYJLX,D_BZ_YJLX } = proxy.$dict("D_BZ_TPYJLX","D_BZ_YJLX")
|
||||
|
||||
const showModel = ref('研判首页')
|
||||
const itemData = ref({})
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm" v-infinite-scroll="load" :infinite-scroll-disabled="disabled">
|
||||
<!-- v-if="dialogForm" -->
|
||||
<div v-infinite-scroll="load" :infinite-scroll-disabled="disabled">
|
||||
<!-- class="head_box" -->
|
||||
<div style="position: sticky;top: 0;float: right;">
|
||||
<!-- <div style="position: sticky;top: 0;float: right;">
|
||||
<el-button size="small" @click="close">关闭</el-button>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="content_box">
|
||||
<div>
|
||||
<div class="title_box">{{ listQuery.xsMc }}</div>
|
||||
@ -35,8 +36,11 @@
|
||||
</div>
|
||||
|
||||
<div class="title_box virtual">评论列表</div>
|
||||
<CommentList v-for="(item, index) in pagesData.listData" :key="index" :index="index" :item="item"
|
||||
<div style="height: 38vh;overflow: auto;">
|
||||
<CommentList v-for="(item, index) in pagesData.listData" :key="index" :index="index" :item="item"
|
||||
@postReply="postReply" @delComment="delComment" :userInfo="userInfo" @cjpjZan="cjpjZan"/>
|
||||
</div>
|
||||
|
||||
<div class="sticky">
|
||||
<div class="title_box virtual">发表评论</div>
|
||||
<div class="flex flex-column ">
|
||||
@ -58,36 +62,35 @@ import { ref, reactive, toRaw, watch, onMounted, onUnmounted } from "vue";
|
||||
import CommentList from '../itemXs/commentList.vue'
|
||||
import { getItem } from '@/utils/storage.js'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
const emit = defineEmits(["updateDate"]);
|
||||
const props = defineProps({
|
||||
dict: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}, msgeDat: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
|
||||
const dialogForm = ref(false); //弹窗
|
||||
const listQuery = ref({})
|
||||
// 初始化数据
|
||||
const commentInit = (row) => {
|
||||
// 根据id查询详情
|
||||
qcckGet({ id: row }, "/mosty-gsxt/qbcj/selectByid").then((res) => {
|
||||
listQuery.value = res;
|
||||
cjpjSelectPage()
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
};
|
||||
watch(() => props.msgeDat, (newVal) => {
|
||||
commentInit(newVal.id)
|
||||
},{deep: true,immediate: true})
|
||||
|
||||
const textarea2 = ref()
|
||||
const userInfo = ref(getItem('idEntityCard'))
|
||||
// 初始化数据
|
||||
const init = (row) => {
|
||||
dialogForm.value = true;
|
||||
// 根据id查询详情
|
||||
if (row) {
|
||||
qcckGet({ id: row }, "/mosty-gsxt/qbcj/selectByid").then((res) => {
|
||||
listQuery.value = res;
|
||||
});
|
||||
cjpjSelectPage()
|
||||
}
|
||||
|
||||
};
|
||||
// 关闭
|
||||
const close = () => {
|
||||
dialogForm.value = false;
|
||||
pagesData.pagebreak.pageCurrent = 1
|
||||
};
|
||||
const pagesData = reactive({
|
||||
total: 0,
|
||||
pagebreak: {
|
||||
@ -184,8 +187,6 @@ const cjpjZan = (val,data) => {
|
||||
const disabled = ref(false)
|
||||
|
||||
|
||||
defineExpose({ init });
|
||||
|
||||
const load = () => {
|
||||
if (pagesData.pagebreak.pageCurrent < pagesData.total) {
|
||||
pagesData.pagebreak.pageCurrent++
|
||||
@ -281,7 +282,7 @@ const load = () => {
|
||||
}
|
||||
|
||||
.itemXs_Xs {
|
||||
width: 18%;
|
||||
// width: 18%;
|
||||
font-size: 14px;
|
||||
color: #6c6c6c;
|
||||
line-height: 20px;
|
||||
|
||||
@ -187,7 +187,7 @@ const handleLike = (item) => {
|
||||
|
||||
.itemXs_time {
|
||||
justify-content: space-between;
|
||||
width: 23%;
|
||||
// width: 23%;
|
||||
align-items: center;
|
||||
color: #000;
|
||||
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<CommentList v-for="(item, index) in pagesData.listData" :key="index" :item="item" @delComment="cjhfRemove" :userInfo="userInfo"/>
|
||||
<el-pagination v-if="pagesData.total > 10" v-model:current-page="pagesData.pagebreak.pageCurrent"
|
||||
v-model:page-size="pagesData.pagebreak.pageSize" :size="10" :disabled="false" :total="pagesData.total"
|
||||
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
|
||||
<div style="text-align: center;width: 100%;height: 20px;" v-if="pagesData.total == 0">暂无回复</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { qcckGet, qcckPost, qcckPut } from "@/api/qcckApi.js";
|
||||
|
||||
@ -320,17 +320,13 @@ function simpleExtractJSON(text) {
|
||||
// 找到第一个 [
|
||||
const startIndex = text.indexOf('[');
|
||||
if (startIndex === -1) return null;
|
||||
|
||||
// 找到最后一个完整的 }
|
||||
let lastBraceIndex = text.lastIndexOf('}');
|
||||
if (lastBraceIndex === -1) return null;
|
||||
|
||||
// 确保 } 后面没有其他字符(除了空格和换行)
|
||||
let endIndex = lastBraceIndex + 1;
|
||||
|
||||
// 截取从 [ 到最后一个 } 的内容,然后加上 ]
|
||||
let jsonString = text.substring(startIndex, endIndex) + ']';
|
||||
|
||||
try {
|
||||
return JSON.parse(jsonString);
|
||||
} catch (error) {
|
||||
|
||||
496
src/views/backOfficeSystem/calendar/index.vue
Normal file
496
src/views/backOfficeSystem/calendar/index.vue
Normal file
@ -0,0 +1,496 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="敏感节点"> </PageTitle>
|
||||
</div>
|
||||
<div class="tabBox contentBox">
|
||||
<div class="leftBox">
|
||||
<el-calendar ref="calendar" v-model="currentDate">
|
||||
<template #header="{ date }">
|
||||
<div style="display: flex;">
|
||||
<el-select @change="goToSelectedMonth" v-model="selectedYear" style="margin-right: 10px;">
|
||||
<el-option v-for="year in years" :key="year" :label="year + '年'" :value="year" />
|
||||
</el-select>
|
||||
<el-select @change="goToSelectedMonth" v-model="selectedMonth">
|
||||
<el-option v-for="month in months" :key="month.value" :label="month.label" :value="month.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div style="color: #000;display: flex;align-items: center;">
|
||||
<div style="margin-right: 10px;"> {{ dateVal }}</div> <el-button
|
||||
@click="selectDate('today')">今天</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #dateCell="{ data }">
|
||||
<div @click="chooseDay(data)" class="dayonChage"
|
||||
:class="{ 'day': dateVal == data.day,
|
||||
'special': dataIntegration.includes(data.day)}"
|
||||
>
|
||||
<div> {{ data.day.split("-")[2] }}</div>
|
||||
<div v-for="(item, index) in getAllFestivals(data.day)" :key="index"> {{ item.name }}</div>
|
||||
<div v-if="getWorkdayType(data.day)" class="holiday-badge"
|
||||
:class="getWorkdayType(data.day) == '班' ? 'holiday-work' : 'holiday-rest'">
|
||||
{{ getWorkdayType(data.day) }}
|
||||
</div>
|
||||
<div> {{ getLunarMonthDay(data.date) }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-calendar>
|
||||
</div>
|
||||
<div class="riteBox">
|
||||
<div class="sensitive-list-header">
|
||||
<h3>敏感时间节点</h3>
|
||||
<div class="add-form">
|
||||
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
|
||||
<el-form-item prop="jdbt">
|
||||
<el-input v-model="ruleForm.jdbt" placeholder="请输入敏感事件名称" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="jdnr">
|
||||
<el-input v-model="ruleForm.jdnr" type="textarea" placeholder="请输入敏感事件内容" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitForm(ruleFormRef)">
|
||||
{{ submitZt ? '新增' : '修改' }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sensitive-list">
|
||||
<div v-for="(item, index) in sensitiveNodes" :key="index" class="sensitive-item">
|
||||
<div class="sensitive-date">{{ item.date }}</div>
|
||||
<div class="sensitive-content">{{ item.jdbt }}</div>
|
||||
<el-button type="text" @click="modification(item)" size="small">修改</el-button>
|
||||
<el-button type="text" @click="deleteSensitiveNode(item.id)" size="small">删除</el-button>
|
||||
</div>
|
||||
<div v-if="sensitiveNodes.length === 0" class="empty-tip">暂无敏感时间节点</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { Solar, HolidayUtil } from 'lunar-javascript'
|
||||
import { timeValidate } from "@/utils/tools";
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { tbGsxtMgjdSave, tbGsxtMgjdSelectList, tbGsxtMgjdUpdate, tbGsxtMgjdDelete } from "@/api/tbGsxtMgjd";
|
||||
const dateVal = ref();
|
||||
const ruleFormRef = ref()
|
||||
// 获取工作日类型
|
||||
const getWorkdayType = (date) => {
|
||||
try {
|
||||
const time = new Date(date)
|
||||
const year = time.getFullYear()
|
||||
const month = time.getMonth() + 1 // JavaScript月份从0开始
|
||||
const day = time.getDate()
|
||||
|
||||
// 正确调用HolidayUtil.getHoliday方法,传入数值类型的年、月、日
|
||||
const holiday = HolidayUtil.getHoliday(year, month, day)
|
||||
|
||||
if (holiday) {
|
||||
// 如果是调休需要上班
|
||||
if (holiday.isWork()) {
|
||||
return '班'
|
||||
}
|
||||
// 如果是法定节假日放假
|
||||
return '休'
|
||||
}
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error('获取节假日信息失败:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
// 获取农历月日
|
||||
const getLunarMonthDay = (date) => {
|
||||
if (!date) return ''
|
||||
const solar = Solar.fromDate(date)
|
||||
const lunar = solar.getLunar()
|
||||
return lunar.getJieQi() ? lunar.getJieQi() : lunar.getDayInChinese()
|
||||
}
|
||||
const getAllFestivals = (date) => {
|
||||
const time = new Date(date)
|
||||
const solar = Solar.fromDate(time)
|
||||
const lunar = solar.getLunar()
|
||||
const result = []
|
||||
// 获取农历节日
|
||||
const lunarFestivals = lunar.getFestivals()
|
||||
lunarFestivals.forEach(festival => {
|
||||
result.push({
|
||||
type: '农历节日',
|
||||
name: festival,
|
||||
})
|
||||
})
|
||||
|
||||
// 获取公历节日
|
||||
const solarFestivals = solar.getFestivals()
|
||||
solarFestivals.forEach(festival => {
|
||||
result.push({
|
||||
type: '公历节日',
|
||||
name: festival,
|
||||
})
|
||||
})
|
||||
|
||||
// 获取其他纪念日
|
||||
const otherFestivals = solar.getOtherFestivals()
|
||||
otherFestivals.forEach(festival => {
|
||||
result.push({
|
||||
type: '纪念日',
|
||||
name: festival,
|
||||
})
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
const selectedYear = ref();
|
||||
const selectedMonth = ref('');
|
||||
const calendar = ref(null)
|
||||
// 生成年份选项(前后10年)
|
||||
const years = computed(() => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
const years = [];
|
||||
for (let i = currentYear - 10; i <= currentYear + 10; i++) {
|
||||
years.push(i);
|
||||
}
|
||||
return years;
|
||||
});
|
||||
|
||||
// 月份选项
|
||||
const months = ref([
|
||||
{ label: '1月', value: 0 },
|
||||
{ label: '2月', value: 1 },
|
||||
{ label: '3月', value: 2 },
|
||||
{ label: '4月', value: 3 },
|
||||
{ label: '5月', value: 4 },
|
||||
{ label: '6月', value: 5 },
|
||||
{ label: '7月', value: 6 },
|
||||
{ label: '8月', value: 7 },
|
||||
{ label: '9月', value: 8 },
|
||||
{ label: '10月', value: 9 },
|
||||
{ label: '11月', value: 10 },
|
||||
{ label: '12月', value: 11 }
|
||||
]);
|
||||
// 切换日期
|
||||
const chooseDay = (data) => {
|
||||
dateVal.value = data.day
|
||||
ruleForm.value.jdrq = data.day
|
||||
querySensitiveNodes()
|
||||
submitZt.value = true
|
||||
ruleForm.value = {}
|
||||
ruleForm.value.jdrq = dateVal.value
|
||||
}
|
||||
const currentDate = ref(new Date());
|
||||
|
||||
// 敏感时间节点数据
|
||||
const sensitiveNodes = ref([]);
|
||||
onMounted(() => {
|
||||
initialize()
|
||||
gettingData()
|
||||
})
|
||||
|
||||
// 获取选项初始值
|
||||
const initialize = () => {
|
||||
const year = timeValidate(currentDate.value, 'yd')
|
||||
const month = timeValidate(currentDate.value, 'ym')
|
||||
dateVal.value = timeValidate(currentDate.value, 'ymd')
|
||||
selectedYear.value = parseFloat(year)
|
||||
selectedMonth.value = parseFloat(month) - 1
|
||||
ruleForm.value.jdrq = dateVal.value
|
||||
querySensitiveNodes()
|
||||
}
|
||||
const goToSelectedMonth = () => {
|
||||
if (selectedYear.value && selectedMonth.value !== '') {
|
||||
const newDate = new Date(selectedYear.value, selectedMonth.value, 1);
|
||||
currentDate.value = newDate;
|
||||
dateVal.value = timeValidate(currentDate.value, 'ymd')
|
||||
gettingData()
|
||||
}
|
||||
};
|
||||
|
||||
const ruleForm = ref({})
|
||||
const rules = {
|
||||
jdrq: [
|
||||
{ required: true, message: '请选择日期', trigger: 'blur' }
|
||||
],
|
||||
jdnr: [
|
||||
{ required: true, message: '请输入敏感事件内容', trigger: 'blur' }
|
||||
],
|
||||
jdbt: [
|
||||
{ required: true, message: '请输入敏感事件名称', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
const selectDate = (val) => {
|
||||
if (!calendar.value) return
|
||||
calendar.value.selectDate(val)
|
||||
dateVal.value = timeValidate(currentDate.value, 'ymd')
|
||||
initialize()
|
||||
gettingData()
|
||||
}
|
||||
const submitZt = ref(true)
|
||||
// 提交表单
|
||||
const submitForm = async (formEl) => {
|
||||
if (!formEl) return
|
||||
try {
|
||||
await formEl.validate()
|
||||
const promes = { ...ruleForm.value }
|
||||
console.log(promes);
|
||||
|
||||
if (submitZt.value) {
|
||||
tbGsxtMgjdSave(promes).then(() => {
|
||||
ElMessage.success('新增成功')
|
||||
querySensitiveNodes()
|
||||
// 在API调用成功后再重置表单
|
||||
resetForm(formEl)
|
||||
})
|
||||
} else {
|
||||
tbGsxtMgjdUpdate(promes).then(() => {
|
||||
ElMessage.success('修改成功')
|
||||
querySensitiveNodes()
|
||||
// 在API调用成功后再重置表单
|
||||
resetForm(formEl)
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('验证失败:', error)
|
||||
}
|
||||
}
|
||||
// 查询敏感事件
|
||||
const querySensitiveNodes = () => {
|
||||
tbGsxtMgjdSelectList({ jdrq: dateVal.value }).then((res) => {
|
||||
sensitiveNodes.value = res && res.length > 0 ? res : []
|
||||
})
|
||||
}
|
||||
// 重置表单
|
||||
const resetForm = (formEl) => {
|
||||
if (!formEl) return
|
||||
try {
|
||||
formEl.resetFields()
|
||||
} catch (error) {
|
||||
// 手动重置表单数据
|
||||
ruleForm.value = { jdrq: dateVal.value || '', jdbt: '', jdnr: '' }
|
||||
}
|
||||
// 重置提交状态为新增
|
||||
submitZt.value = true
|
||||
}
|
||||
|
||||
// 删除敏感时间节点
|
||||
const deleteSensitiveNode = (id) => {
|
||||
ElMessageBox.confirm('确定要删除这个敏感时间节点吗?', '确认删除', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
tbGsxtMgjdDelete({ ids: [id] }).then(() => {
|
||||
ElMessage.success('删除成功')
|
||||
querySensitiveNodes()
|
||||
})
|
||||
}).catch(() => {
|
||||
ElMessage.info('已取消删除')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 修改
|
||||
const modification = (item) => {
|
||||
ruleForm.value = { ...item }
|
||||
submitZt.value = false
|
||||
}
|
||||
const dataIntegration = ref([])
|
||||
// 获取当前月份的所有信息
|
||||
const gettingData = () => {
|
||||
const date = new Date(dateVal.value);
|
||||
date.setDate(1)
|
||||
const startTime = timeValidate(date.toLocaleDateString(), 'ymd')
|
||||
date.setMonth(date.getMonth() + 1);
|
||||
date.setDate(0);
|
||||
const endTime = timeValidate(date.toLocaleDateString(), 'ymd')
|
||||
const params = { startTime, endTime }
|
||||
tbGsxtMgjdSelectList(params).then(res => {
|
||||
if (res&&res.length>0) {
|
||||
dataIntegration.value=[...new Set(res.map(item => item.jdrq))]?[...new Set(res.map(item => item.jdrq))] : []
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.contentBox {
|
||||
height: calc(100vh - 190px);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
color: #000;
|
||||
|
||||
.leftBox {
|
||||
width: calc(100% - 20px - 20%)
|
||||
}
|
||||
|
||||
.riteBox {
|
||||
width: calc(100% - 20px - 80%);
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sensitive-list-header {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.sensitive-list-header h3 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.add-form {
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
gap: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.sensitive-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sensitive-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 8px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.sensitive-date {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.sensitive-content {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
// ::v-deep .el-calendar__header {
|
||||
// padding: 4px 20px !important;
|
||||
// color: #fff;
|
||||
// }
|
||||
|
||||
// ::v-deep .el-calendar__body {
|
||||
// padding: 3px 20px 35px !important;
|
||||
// }
|
||||
|
||||
::v-deep .el-calendar-table thead th {
|
||||
// padding: 4px 0 !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table td.is-today {
|
||||
color: #35ff02;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table thead th {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-day {
|
||||
background-color: #fff;
|
||||
text-align: center !important;
|
||||
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table:not(.is-range) td.prev {
|
||||
color: #bbbbbb8f !important;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table:not(.is-range) td.next,
|
||||
.el-calendar-table:not(.is-range) td.prev {
|
||||
color: #bbbbbb8f !important;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table td {
|
||||
color: #000 !important;
|
||||
}
|
||||
.dayonChage.special.day {
|
||||
background-color: #e6a23c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.day {
|
||||
background-color: rgb(76, 134, 243);
|
||||
color: #35ff02;
|
||||
}
|
||||
.special{
|
||||
background-color: rgba(253, 112, 112, 0.856);
|
||||
color: #ffffff;
|
||||
}
|
||||
// 敏感日期样式
|
||||
.sensitive-day {
|
||||
background-color: rgba(255, 214, 0, 0.3);
|
||||
border: 1px solid #ffd600;
|
||||
}
|
||||
|
||||
.dayonChage {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
/* 水平居中 */
|
||||
justify-content: center;
|
||||
/* 垂直居中 */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 节假日徽章样式 */
|
||||
.holiday-badge {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
/* 调休上班样式 - 红底白字 */
|
||||
.holiday-work {
|
||||
|
||||
background-color: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 法定节假日样式 - 绿底白字 */
|
||||
.holiday-rest {
|
||||
background-color: green;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
@ -2,9 +2,9 @@
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="行为预警">
|
||||
<el-button type="primary" @click="exportExcel">
|
||||
<!-- <el-button type="primary" @click="exportExcel">
|
||||
<span style="vertical-align: middle">导出</span>
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
@ -13,37 +13,31 @@
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox">
|
||||
<MyTable
|
||||
:tableData="pageData.tableData"
|
||||
:tableColumn="pageData.tableColumn"
|
||||
:tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount"
|
||||
:tableConfiger="pageData.tableConfiger"
|
||||
>
|
||||
<template #xwcs="{ row }">
|
||||
<span style="color: #0072ff;" @click="handleClick(row)">{{ row.xwcs }}</span>
|
||||
</template>
|
||||
<template #bqYs="{ row }">
|
||||
<DictTag :value="row.bqys" :tag="false" :options="D_GS_SSYJ" />
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger">
|
||||
<template #xwcs="{ row }">
|
||||
<span style="color: #0072ff;" @click="handleClick(row)">{{ row.xwcs }}</span>
|
||||
</template>
|
||||
<template #bqYs="{ row }">
|
||||
<!-- <div :style="{
|
||||
backgroundColor: bqYs(row.bqys)
|
||||
}"></div> -->
|
||||
|
||||
<DictTag :value="row.bqys" :tag="false" :color="bqYs(row.bqys)" :options="D_GS_SSYJ" />
|
||||
</template>
|
||||
<template #controls="{ row }">
|
||||
<el-link type="primary">下发指令</el-link>
|
||||
<el-link type="success">查看反馈</el-link>
|
||||
</template>
|
||||
</MyTable>
|
||||
<Pages
|
||||
@changeNo="changeNo"
|
||||
@changeSize="changeSize"
|
||||
:tableHeight="pageData.tableHeight"
|
||||
:pageConfiger="{
|
||||
...pageData.pageConfiger,
|
||||
total: pageData.total
|
||||
}"
|
||||
></Pages>
|
||||
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
|
||||
...pageData.pageConfiger,
|
||||
total: pageData.total
|
||||
}"></Pages>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 详情 -->
|
||||
<Detail ref="detailRef"></Detail>
|
||||
<Detail ref="detailRef"></Detail>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -54,16 +48,26 @@ import Search from "@/components/aboutTable/Search.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import { qcckGet } from "@/api/qcckApi.js";
|
||||
import { reactive, ref, onMounted,getCurrentInstance } from "vue";
|
||||
import { tbGsxtBqglSelectList } from '@/api/zdr'
|
||||
import { reactive, ref, onMounted, getCurrentInstance, computed, watch } from "vue";
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_GS_SSYJ } = proxy.$dict("D_GS_SSYJ"); //获取字典数据
|
||||
const searchBox = ref(); //搜索框
|
||||
const bqLbData = ref({
|
||||
bqXl: []
|
||||
})
|
||||
|
||||
const searchConfiger = ref(
|
||||
[
|
||||
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input"},
|
||||
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input"},
|
||||
{ label: "电话号码", prop: 'dh', placeholder: "请输入电话号码", showType: "input"},
|
||||
]);
|
||||
{ label: "姓名", prop: 'xm', placeholder: "请输入姓名", showType: "input" },
|
||||
{ label: "身份证号码", prop: 'sfzh', placeholder: "请输入身份证号码", showType: "input" },
|
||||
{ label: "电话号码", prop: 'dh', placeholder: "请输入电话号码", showType: "input" },
|
||||
{
|
||||
label: "标签小类", prop: 'bqxl', placeholder: "请选择标签小类",
|
||||
showType: "select", options: []
|
||||
},
|
||||
]);
|
||||
|
||||
const detailRef = ref()
|
||||
const queryFrom = ref({});
|
||||
const pageData = reactive({
|
||||
@ -81,42 +85,70 @@ const pageData = reactive({
|
||||
pageCurrent: 1
|
||||
}, //分页
|
||||
tableColumn: [
|
||||
{ label: "姓名", prop: "xm"},
|
||||
{ label: "姓名", prop: "xm" },
|
||||
{ label: "身份证号", prop: "sfzh" },
|
||||
{ label: "电话", prop: "dh" },
|
||||
{ label: "行为大类", prop: "xldlmc"},
|
||||
{ label: "行为子类", prop: "xwzlmc", showOverflowTooltip: true },
|
||||
{ label: "行为描述", prop: "xwms", showOverflowTooltip: true },
|
||||
{ label: "行为大类", prop: "xldlmc" },
|
||||
{ label: "行为子类", prop: "xwzlmc", showOverflowTooltip: true },
|
||||
{ label: "行为描述", prop: "xwms", showOverflowTooltip: true },
|
||||
{ label: "行为次数", prop: "xwcs", showSolt: true },
|
||||
{ label: "行为颜色", prop: "bqYs",showSolt: true },
|
||||
{ label: "行为分值", prop: "xwfz",},
|
||||
{ label: "行为颜色", prop: "bqYs", showSolt: true },
|
||||
{ label: "行为分值", prop: "xwfz", },
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
const gettbGsxtBqglSelectList = (val) => {
|
||||
tbGsxtBqglSelectList({ bqLx: '02', bqlb: val, bqDlId: '241cc7b69a50428287cc79445e310180' }).then((res) => {
|
||||
bqLbData.value.bqXl = res.map(item => {
|
||||
return {
|
||||
label: item.bqMc,
|
||||
value: item.id
|
||||
}
|
||||
}) || []
|
||||
})
|
||||
}
|
||||
watch(() => bqLbData.value.bqXl, (res) => {
|
||||
searchConfiger.value.push({
|
||||
label: "标签小类", prop: 'bqxl', placeholder: "请选择标签小类",
|
||||
showType: "select", options: res
|
||||
},)
|
||||
}, { deep: true })
|
||||
onMounted(() => {
|
||||
tabHeightFn();
|
||||
getList()
|
||||
gettbGsxtBqglSelectList('02')
|
||||
|
||||
});
|
||||
|
||||
// 搜索
|
||||
const onSearch = (val) =>{
|
||||
queryFrom.value = {...val}
|
||||
const onSearch = (val) => {
|
||||
queryFrom.value = { ...val }
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList()
|
||||
}
|
||||
const changeNo = (val) =>{
|
||||
const changeNo = (val) => {
|
||||
pageData.pageConfiger.pageCurrent = val;
|
||||
getList()
|
||||
}
|
||||
const changeSize = (val) =>{
|
||||
const changeSize = (val) => {
|
||||
pageData.pageConfiger.pageSize = val;
|
||||
getList()
|
||||
}
|
||||
const getList = () =>{
|
||||
const getList = () => {
|
||||
pageData.tableConfiger.loading = true;
|
||||
qcckGet(queryFrom.value,'/mosty-gsxt/yjzxXwyj/getPageList').then((res)=>{
|
||||
const promes = {
|
||||
...queryFrom.value,
|
||||
pageCurrent: pageData.pageConfiger.pageCurrent,
|
||||
pageSize: pageData.pageConfiger.pageSize
|
||||
}
|
||||
qcckGet(promes, '/mosty-gsxt/yjzxXwyj/getPageList').then((res) => {
|
||||
pageData.total = res.total || 0;
|
||||
pageData.tableConfiger.loading = false;
|
||||
// pageData.tableData = res.records || [];
|
||||
}).catch(()=>{
|
||||
pageData.tableData = res.records.map(item => {
|
||||
return {...item,bqys: '01'}
|
||||
}) || [];
|
||||
}).catch(() => {
|
||||
pageData.tableConfiger.loading = false;
|
||||
})
|
||||
}
|
||||
@ -126,7 +158,7 @@ const handleClick = (row) => {
|
||||
}
|
||||
|
||||
const exportExcel = () => {
|
||||
if (pageData.tableData.length === 0) return ElMessage({ message: "暂无数据", type: "warning" });
|
||||
if (pageData.tableData.length === 0) return ElMessage({ message: "暂无数据", type: "warning" });
|
||||
const headers = pageData.tableColumn.map(item => item.label);
|
||||
const data = pageData.tableData.map(item => {
|
||||
return [item.xm, item.sfzh, item.dh, item.xldlmc, item.xwzlmc, item.xwms, item.xwcs, item.xwfz];
|
||||
@ -136,11 +168,21 @@ const exportExcel = () => {
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "sheet1");
|
||||
XLSX.writeFile(workbook, "行为预警.xlsx");
|
||||
}
|
||||
|
||||
const bqYs = (val) => {
|
||||
if (val == '01') {
|
||||
return '#ff0202'
|
||||
} else if (val == '02') {
|
||||
return '#ff8c00'
|
||||
} else if (val == '03') {
|
||||
return '#ffff00'
|
||||
} else if (val == '04') {
|
||||
return '#0000ff'
|
||||
}
|
||||
}
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
|
||||
window.onresize = function () { tabHeightFn(); };
|
||||
window.onresize = function () { tabHeightFn(); };
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@ -6,7 +6,12 @@
|
||||
<span>{{ changetText(props.item.yjJb) }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-image :preview-teleported="true" style="width: 80px; height: 110px" :src="item.yjTp"
|
||||
|
||||
<template v-if="!item.yjTp || item.yjTp.includes('baidu')">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</template>
|
||||
<el-image v-else :preview-teleported="true" style="width: 80px; height: 110px" :src="item.yjTp"
|
||||
:preview-src-list="[item.yjTp]" show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
@ -15,7 +20,6 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<span class="smallbtn" @click.stop="() => { }">全息档案</span>
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="组合预警">
|
||||
<el-button>
|
||||
<!-- <el-button>
|
||||
<span style="vertical-align: middle">导出</span>
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
@ -134,4 +134,4 @@ const tabHeightFn = () => {
|
||||
.el-loading-mask {
|
||||
background: rgba(0, 0, 0, 0.5) !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="身份预警">
|
||||
<el-button>
|
||||
<!-- <el-button>
|
||||
<span style="vertical-align: middle">导出</span>
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
|
||||
@ -7,14 +7,19 @@
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
|
||||
<template #yjTp="{ row }">
|
||||
<el-image style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]" show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2"/>
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else/>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<template v-if="!row.yjTp || row.yjTp.includes('baidu')">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</template>
|
||||
<el-image v-else style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]"
|
||||
show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<!-- <el-image :preview-teleported="true" style="width: 80px; height: 110px" :src="row.yjTp"
|
||||
:preview-src-list="[row.yjTp]" /> -->
|
||||
</template>
|
||||
@ -59,7 +64,7 @@ const pageData = reactive({
|
||||
rowHieght: 61,
|
||||
showSelectType: "null",
|
||||
loading: false,
|
||||
haveControls:false
|
||||
haveControls: false
|
||||
},
|
||||
|
||||
total: 0,
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
<!-- 搜索 -->
|
||||
<div ref="searchBox" class="searchBox">
|
||||
<el-form :model="listQuery" label-width="auto" :inline="true" ref="searchArr">
|
||||
<el-form-item label="布控类型" prop="yjlx">
|
||||
<el-form-item label="布控类型" prop="yjlx" >
|
||||
<el-select v-model="listQuery.yjlx" placeholder="请选择预警类型">
|
||||
<el-option v-for="item in D_BZ_YJLX" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="布控人员" prop="yjRyxm ">
|
||||
<el-select v-model="listQuery.yjRyxm" filterable remote reserve-keyword placeholder="请选择布控人员"
|
||||
<el-select clearable v-model="listQuery.yjRyxm" filterable remote reserve-keyword placeholder="请输入布控人员"
|
||||
:remote-method="remoteMethod" :loading="loading" style="width: 240px">
|
||||
<el-option v-for="item in opentions" :key="item.rySfzh" :label="item.ryXm" :value="item.rySfzh" />
|
||||
</el-select>
|
||||
@ -44,19 +44,19 @@
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="500"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth">
|
||||
<template #yjTp="{ row }">
|
||||
<el-image style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]" show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2"/>
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else/>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
|
||||
|
||||
|
||||
<!-- <el-image :preview-teleported="true" style="width: 80px; height: 110px" :src="row.yjTp"
|
||||
:preview-src-list="[row.yjTp]" /> -->
|
||||
<template v-if="!row.yjTp || row.yjTp.includes('baidu')">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</template>
|
||||
<el-image v-else style="width: 80px; height:120px" :src="row.yjTp" :preview-src-list="[row.yjTp]"
|
||||
show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="row.yjLx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
<template #nl="{ row }">
|
||||
{{ IdCard(row.yjRysfzh, 3) }}
|
||||
@ -163,16 +163,17 @@ const activeName = ref('local')
|
||||
onMounted(() => {
|
||||
tabHeightFn();
|
||||
});
|
||||
const listQuery = reactive({})
|
||||
const listQuery = ref({})
|
||||
const opentions = ref([])
|
||||
const localWarningRef = ref(null);
|
||||
// 搜索
|
||||
|
||||
const onSearch = () => {
|
||||
const promes = {
|
||||
yjRyxm: listQuery.yjRyxm,
|
||||
yjlx: listQuery.yjlx,
|
||||
startTime: listQuery.time ? listQuery.time[0] : '',
|
||||
endTime: listQuery.time ? listQuery.time[1] : '',
|
||||
yjRyxm: listQuery.value.yjRyxm,
|
||||
yjlx: listQuery.value.yjlx,
|
||||
startTime: listQuery.value.time ? listQuery.value.time[0] : '',
|
||||
endTime: listQuery.value.time ? listQuery.value.time[1] : '',
|
||||
}
|
||||
localWarningRef.value.getList(promes)
|
||||
}
|
||||
@ -189,10 +190,10 @@ const remoteMethod = (query) => {
|
||||
opentions.value = []
|
||||
}
|
||||
}
|
||||
const searchArr = ref(null)
|
||||
const searchArr = ref()
|
||||
const resetForm = (formEl) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
listQuery.value = {}
|
||||
localWarningRef.value.getList()
|
||||
}
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
@ -206,10 +207,10 @@ const tabHeightFn = () => {
|
||||
|
||||
const exportExcel = () => {
|
||||
const promes = {
|
||||
yjRyxm: listQuery.yjRyxm,
|
||||
yjlx: listQuery.yjlx,
|
||||
startTime: listQuery.time ? listQuery.time[0] : '',
|
||||
endTime: listQuery.time ? listQuery.time[1] : '',
|
||||
yjRyxm: listQuery.value.yjRyxm,
|
||||
yjlx: listQuery.value.yjlx,
|
||||
startTime: listQuery.value.time ? listQuery.value.time[0] : '',
|
||||
endTime: listQuery.value.time ? listQuery.value.time[1] : '',
|
||||
}
|
||||
tbYjxxQueryYjxx(promes).then(res => {
|
||||
pageData.tableData = res
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<el-dialog
|
||||
title="分配权限"
|
||||
width="500px"
|
||||
:model-value="modelValue"
|
||||
:model-value="props.modelValue"
|
||||
:destroy-on-close="true"
|
||||
@close="closed"
|
||||
>
|
||||
|
||||
219
src/views/forumPost/components/changeTheAvatar.vue
Normal file
219
src/views/forumPost/components/changeTheAvatar.vue
Normal file
@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="modelValue"
|
||||
center
|
||||
width="500px"
|
||||
:destroy-on-close="true"
|
||||
:title="title"
|
||||
@close="close"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="avatar-upload-container">
|
||||
<div class="avatar-preview">
|
||||
<img v-if="avatarUrl" :src="avatarUrl" alt="预览头像" class="preview-image">
|
||||
<div v-else class="preview-placeholder">
|
||||
<el-icon class="placeholder-icon"><User /></el-icon>
|
||||
<span>请上传头像</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-section">
|
||||
<el-upload
|
||||
class="avatar-uploader"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:on-change="handleAvatarChange"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
accept="image/*"
|
||||
>
|
||||
<el-button size="small" type="primary">选择图片</el-button>
|
||||
</el-upload>
|
||||
<div class="upload-tips">
|
||||
<p>• 支持 JPG、PNG 格式</p>
|
||||
<p>• 图片大小不超过 2MB</p>
|
||||
<p>• 建议尺寸为 200x200 像素</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="confirmUpload"
|
||||
:loading="uploading"
|
||||
:disabled="!avatarUrl || uploading"
|
||||
>
|
||||
{{ uploading ? '上传中...' : '确认更换' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from "vue";
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { User } from '@element-plus/icons-vue';
|
||||
import { upImageUploadId } from '@/api/commit';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "更换头像"
|
||||
},
|
||||
heightNumber: {
|
||||
type: Number,
|
||||
default: 250
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:modelValue", "avatarUpdated"]);
|
||||
|
||||
// 头像相关状态
|
||||
const avatarUrl = ref('');
|
||||
const uploading = ref(false);
|
||||
|
||||
// 监听对话框显示状态,重置头像预览
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (!newVal) {
|
||||
// 对话框关闭时重置头像预览
|
||||
avatarUrl.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
// 当前选择的文件
|
||||
const selectedFile = ref(null);
|
||||
|
||||
// 处理头像选择
|
||||
const handleAvatarChange = (file) => {
|
||||
selectedFile.value = file.raw;
|
||||
// 创建临时预览URL
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
avatarUrl.value = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file.raw);
|
||||
};
|
||||
|
||||
// 上传前检查
|
||||
const beforeAvatarUpload = (file) => {
|
||||
const isJPG = file.type === 'image/jpeg';
|
||||
const isPNG = file.type === 'image/png';
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
|
||||
if (!isJPG && !isPNG) {
|
||||
ElMessage.error('请上传 JPG 或 PNG 格式的图片!');
|
||||
return false;
|
||||
}
|
||||
if (!isLt2M) {
|
||||
ElMessage.error('图片大小不能超过 2MB!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// 确认上传头像
|
||||
const confirmUpload = async () => {
|
||||
if (!avatarUrl.value || !selectedFile.value) {
|
||||
ElMessage.warning('请先选择头像图片');
|
||||
return;
|
||||
}
|
||||
|
||||
uploading.value = true;
|
||||
try {
|
||||
// 创建FormData对象
|
||||
const formData = new FormData();
|
||||
formData.append('file', selectedFile.value);
|
||||
// 调用实际的上传接口
|
||||
const response = await upImageUploadId(formData);
|
||||
console.log(response);
|
||||
emits('avatarUpdated', response);
|
||||
// 关闭对话框
|
||||
close();
|
||||
|
||||
} catch (error) {
|
||||
console.error('上传头像失败:', error);
|
||||
ElMessage.error('上传头像失败,请重试');
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭对话框
|
||||
const close = () => {
|
||||
emits("update:modelValue", false);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.avatar-upload-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 2px solid #e8e8e8;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #f5f7fa;
|
||||
|
||||
.preview-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.preview-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #909399;
|
||||
|
||||
.placeholder-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-section {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.upload-tips {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
|
||||
p {
|
||||
margin: 4px 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
418
src/views/forumPost/components/particulars.vue
Normal file
418
src/views/forumPost/components/particulars.vue
Normal file
@ -0,0 +1,418 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<span class="title">{{ title }} </span>
|
||||
<div>
|
||||
<el-button size="small" @click="close">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 标题 -->
|
||||
<div class="contentTitle">
|
||||
<div class="content">
|
||||
{{ listQuery.title }}
|
||||
</div>
|
||||
<div class="contentButton">
|
||||
<el-button size="small" type="primary" @click="showModel = true">回复</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contentDeit" v-for="(item, index) in ListData" :key="index">
|
||||
<div class="deitleft">
|
||||
<div class="media_left">
|
||||
<el-image style="width: 120px; height:120px"
|
||||
:src="item.fbrtx ? setAddress(item.fbrtx) : setAddress(item.hfrtx)" show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/mr.png" class="user-avatar" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="head_name">{{ item.fbrxm ? item.fbrxm : item.hfrxm }}</div>
|
||||
</div>
|
||||
<div class="deitright">
|
||||
<div class="deitContent">
|
||||
{{ item.content ? item.content : item.hfnr }}
|
||||
<template v-if="item.tp && Array.isArray(item.tp) && item.tp.length > 0">
|
||||
<div style="display: flex;">
|
||||
<div v-for="(img, imgIndex) in item.tp" :key="imgIndex" class="image-item">
|
||||
<el-image :src="setAddress(img)" show-progress style="max-width: 250px; max-height: 400px; margin: 5px;">
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/default_male.png" width="80" height="80" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
<div class="deitTime">
|
||||
<div>{{ item.time ? item.time : item.hfsj }}</div>
|
||||
<div class="reply" v-if="!item.replyShow" @click="sendXhf(item)">
|
||||
<span v-if="listQuery.id != item.id">({{ item.xjfhList ? item.xjfhList.length : 0 }})</span> 回复
|
||||
</div>
|
||||
<div class="reply" v-else @click="item.replyShow = !item.replyShow">收起回复</div>
|
||||
</div>
|
||||
<transition name="fade-slide">
|
||||
<div class="responseContent" v-if="item.replyShow">
|
||||
<div class="comment" v-for="(items, indexs) in item.xjfhList" :key="indexs">
|
||||
<div class="head_img">
|
||||
<el-image style="width: 100%; height:100%" :src="setAddress(items.hfrtx)" show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/mr.png" class="user-avatar" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="commentContent">
|
||||
<span class="name">{{ items.hfrxm }}</span><span v-if="items.sjhfrxm">回复:{{ items.sjhfrxm }}</span>
|
||||
<div class="commentContentText">{{ items.hfnr }}</div>
|
||||
<div class="clickreply">
|
||||
<div>{{ items.hfsj }}</div>
|
||||
<div @click="openXhf(items)">回复</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="end">
|
||||
<el-input v-model="hfContent" type="textarea" placeholder="请输入内容" class="input"></el-input>
|
||||
<div class="send">
|
||||
<V3Emoji :options-name="optionsName" @click-emoji="onVue3Emoje" :recent="true" style="width: 40px;">
|
||||
</V3Emoji>
|
||||
<el-button type="primary" @click="sendHf(item)">发送</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<WriteBack v-model="showModel" :ItemData="listQuery" @SaveReport="getbGsxtXxltHfSelectPage" title="回复帖子"
|
||||
:showCancel="false" :heightNumber="436"></WriteBack>
|
||||
</template>
|
||||
<script setup>
|
||||
import { tbGsxtXxltHfid, tbGsxtXxltHfSave, tbGsxtXxltHfSelectList } from '@/api/tbGsxtXxltHf.js'
|
||||
import V3Emoji from "vue3-emoji";
|
||||
import WriteBack from './writeBack.vue'
|
||||
import { setAddress } from '@/utils/tools.js'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getItem } from '@/utils/storage.js'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
ref,
|
||||
defineExpose,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
} from "vue";
|
||||
|
||||
const emit = defineEmits(["updateDate"]);
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
const optionsName = {
|
||||
'Smileys & Emotion': '笑脸&表情',
|
||||
'Food & Drink': '食物&饮料',
|
||||
'Animals & Nature': '动物&自然',
|
||||
'Travel & Places': '旅行&地点',
|
||||
'People & Body': '人物&身体',
|
||||
Objects: '物品',
|
||||
Symbols: '符号',
|
||||
Flags: '旗帜',
|
||||
Activities: '活动'
|
||||
};
|
||||
const dialogForm = ref(false); //弹窗
|
||||
|
||||
const title = ref("回复帖子");
|
||||
const listQuery = ref({});
|
||||
const ListData = ref([])
|
||||
// 初始化数据
|
||||
const init = (row) => {
|
||||
dialogForm.value = true;
|
||||
console.log(row);
|
||||
listQuery.value = {
|
||||
...row,
|
||||
tp: row.tp && Array.isArray(row.tp) ? row.tp : []
|
||||
}
|
||||
ListData.value = [row]
|
||||
getbGsxtXxltHfSelectPage()
|
||||
};
|
||||
const showModel = ref(false)
|
||||
const getbGsxtXxltHfSelectPage = () => {
|
||||
tbGsxtXxltHfid(listQuery.value.id).then(res => {
|
||||
let data
|
||||
if (res.replyList) {
|
||||
data = res.replyList.map(item => {
|
||||
return {
|
||||
...item,
|
||||
tp: item.hftp ? item.hftp.split(',') : []
|
||||
}
|
||||
})
|
||||
} else {
|
||||
data = []
|
||||
}
|
||||
ListData.value = [...[listQuery.value], ...data].map(item => {
|
||||
return {
|
||||
...item,
|
||||
replyShow: false
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const hfContent = ref('')
|
||||
const onVue3Emoje = (val) => {
|
||||
hfContent.value += val
|
||||
}
|
||||
const sfwxhf = ref(true)
|
||||
const xhfMsg = ref({})
|
||||
// 回复
|
||||
const sendHf = async (val) => {
|
||||
let item
|
||||
if (sfwxhf) {
|
||||
item = val
|
||||
} else {
|
||||
item = xhfMsg.value
|
||||
}
|
||||
const ltmasg = getItem("ltmasg")
|
||||
// 处理hfContent.value,移除@用户名:前缀
|
||||
let pureContent = hfContent.value;
|
||||
// 检查是否以@开头并且包含冒号
|
||||
if (pureContent.startsWith('@') && pureContent.includes(':')) {
|
||||
// 提取冒号后面的内容作为纯文本
|
||||
const colonIndex = pureContent.indexOf(':');
|
||||
if (colonIndex !== -1 && colonIndex < pureContent.length - 1) {
|
||||
pureContent = pureContent.substring(colonIndex + 1).trim();
|
||||
}
|
||||
}
|
||||
if (hfContent.value === '') {
|
||||
ElMessage.warning('请输入内容');
|
||||
return
|
||||
}
|
||||
const promes = {
|
||||
hfnr: pureContent, // 只使用处理后的纯内容
|
||||
hfrsfzh: ltmasg.sfzh,
|
||||
hfrtx: ltmasg.tx,
|
||||
hfrxm: ltmasg.xm,
|
||||
ltid: listQuery.value.id,
|
||||
sfyjhf: 0,
|
||||
sjhfid: item.id,
|
||||
sjhfrxm: sfwxhf.value ? '' : item.hfrxm
|
||||
}
|
||||
try {
|
||||
const res = await tbGsxtXxltHfSave(promes)
|
||||
if (res) {
|
||||
const dataxhf = await tbGsxtXxltHfSelectList({ sjhfid: item.id })
|
||||
item.xjfhList = dataxhf
|
||||
hfContent.value = ''
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
sfwxhf.value = true
|
||||
}
|
||||
// 小回复
|
||||
const sendXhf = (item) => {
|
||||
if (item.id === listQuery.value.id) {
|
||||
showModel.value = true
|
||||
} else {
|
||||
item.replyShow = !item.replyShow
|
||||
}
|
||||
};
|
||||
// 打开回复
|
||||
const openXhf = (item) => {
|
||||
hfContent.value = '@' + item.hfrxm + ':'
|
||||
xhfMsg.value = item
|
||||
sfwxhf.value = false
|
||||
}
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
// 关闭回复
|
||||
const close = () => {
|
||||
if (route.query.id) {
|
||||
const query = { ...route.query };
|
||||
delete query.id;
|
||||
router.replace({ query });
|
||||
}
|
||||
// 关闭对话框
|
||||
dialogForm.value = false;
|
||||
};
|
||||
defineExpose({ init });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.contentTitle {
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
.content {
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.contentButton {
|
||||
flex: 1;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.contentDeit {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
.deitleft {
|
||||
width: 130px;
|
||||
background-color: #f6f7fb;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
|
||||
.head_img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
padding: 2px;
|
||||
border: 1px solid #ccc;
|
||||
// margin-right: 12px;
|
||||
}
|
||||
|
||||
.head_img img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.head_name {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
width: 80px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.deitright {
|
||||
width: calc(100% - 130px);
|
||||
// background-color: aqua;
|
||||
padding: 15px;
|
||||
|
||||
.deitContent {
|
||||
line-height: 24px;
|
||||
font-size: 16px;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
min-height: 180px;
|
||||
|
||||
}
|
||||
|
||||
.deitTime {
|
||||
// width:180px;
|
||||
width: 230px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-left: auto;
|
||||
|
||||
.reply {
|
||||
border-bottom: 0;
|
||||
color: #1D53BF;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
width: 80px;
|
||||
background: #f7f8fa;
|
||||
}
|
||||
}
|
||||
|
||||
/* 过渡动画样式 */
|
||||
.fade-slide-enter-active,
|
||||
.fade-slide-leave-active {
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.fade-slide-enter-from,
|
||||
.fade-slide-leave-to {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fade-slide-enter-to,
|
||||
.fade-slide-leave-from {
|
||||
max-height: 500px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.responseContent {
|
||||
line-height: 24px;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
background: #f7f8fa;
|
||||
border: 1px solid #f0f1f2;
|
||||
margin-top: -1px;
|
||||
|
||||
.comment {
|
||||
display: flex;
|
||||
|
||||
.head_img {
|
||||
float: left;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 1px #ccc solid;
|
||||
padding: 1px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.commentContent {
|
||||
width: calc(100% - 50px);
|
||||
font-size: 14px;
|
||||
|
||||
.name {
|
||||
color: #1D53BF;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.clickreply {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 200px;
|
||||
margin-left: auto;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.head_img img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.end {
|
||||
.send {
|
||||
margin-top: 10px;
|
||||
margin-right: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: right;
|
||||
// margin-top:auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
130
src/views/forumPost/components/release.vue
Normal file
130
src/views/forumPost/components/release.vue
Normal file
@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" center width="1000px" :destroy-on-close="true" :title="title" @close="close"
|
||||
:close-on-click-modal="false">
|
||||
<div class="cntBox">
|
||||
<FormMessage :formList="formData" v-model="listQuery" ref="elform" :rules="rules" />
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button type="primary" :loading="loding" @click="downloadWithStyles">发布</el-button>
|
||||
<el-button type="primary" @click="close">取消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import "@wangeditor/editor/dist/css/style.css";
|
||||
import FormMessage from "@/components/aboutTable/FormMessage.vue";
|
||||
import { tbGsxtXxltSave, tbGsxtXxltUpdate } from "@/api/tbGsxtXxltHf.js";
|
||||
import { ref, shallowRef, onBeforeUnmount, defineEmits, defineProps, watch, reactive, computed } from "vue";
|
||||
import { getItem } from "@/utils/storage";
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "报告模板"
|
||||
},
|
||||
heightNumber: {
|
||||
type: Number,
|
||||
default: 448
|
||||
},
|
||||
ItemData: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:modelValue", "changeFn", "SaveReport"]);
|
||||
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emits('update:modelValue', value)
|
||||
});
|
||||
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (newVal && props.ItemData.id) {
|
||||
listQuery.value = { ...props.ItemData}
|
||||
} else if (newVal) {
|
||||
listQuery.value = { }
|
||||
}
|
||||
}, { deep: true })
|
||||
const listQuery = ref({tp:[]})
|
||||
const elform = ref()
|
||||
const formData = ref([
|
||||
{ label: "帖子标题", prop: "title", type: "input", width: '100%' },
|
||||
{ label: "帖子内容", prop: "content", type: "textarea", width: '100%' },
|
||||
{
|
||||
label: "是否公开", prop: "fbfw", type: "select", width: '100%', options: [
|
||||
{ label: '公开', value: '02' },
|
||||
{ label: '不公开', value: '01' }
|
||||
]
|
||||
},
|
||||
{ label: "图片", prop: "tp", type: "upload", width: '100%', limit: 10 },
|
||||
])
|
||||
|
||||
const rules = reactive({
|
||||
title: [
|
||||
{ required: true, message: "请输入帖子标题", trigger: "blur" }
|
||||
],
|
||||
content: [
|
||||
{ required: true, message: "请输入帖子内容", trigger: "blur" }
|
||||
],
|
||||
fbfw: [
|
||||
{ required: true, message: "请选择是否公开", trigger: "blur" }
|
||||
],
|
||||
})
|
||||
const loding=ref(false)
|
||||
const downloadWithStyles = () => {
|
||||
const ltmasg= getItem('ltmasg')
|
||||
elform.value.submit((valid) => {
|
||||
loding.value=true
|
||||
if (valid) {
|
||||
const formData = {
|
||||
fbrtx: ltmasg.tx,
|
||||
fbrxm: ltmasg.xm,
|
||||
fbrxm: ltmasg.sfzh,
|
||||
...listQuery.value,
|
||||
tp: listQuery.value.tp ? listQuery.value.tp.join(',') : ''
|
||||
}
|
||||
if (props.ItemData.id) {
|
||||
tbGsxtXxltUpdate(formData).then((res) => {
|
||||
emits("SaveReport");
|
||||
close();
|
||||
}).finally(()=>{
|
||||
loding.value=false
|
||||
})
|
||||
} else {
|
||||
tbGsxtXxltSave(formData).then((res) => {
|
||||
emits("SaveReport");
|
||||
close();
|
||||
}).finally(()=>{
|
||||
loding.value=false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
const close = () => {
|
||||
// 重置表单数据
|
||||
listQuery.value.tp = null
|
||||
listQuery.value = {}
|
||||
dialogVisible.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cntBox {
|
||||
height: 60vh;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
border: 1px dashed #e9e9e9;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__label {
|
||||
width: 80px !important;
|
||||
}
|
||||
</style>
|
||||
311
src/views/forumPost/components/theLeft.vue
Normal file
311
src/views/forumPost/components/theLeft.vue
Normal file
@ -0,0 +1,311 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="user-profile-card">
|
||||
<!-- <div class="profile-header">
|
||||
<h3>信息</h3>
|
||||
</div> -->
|
||||
|
||||
<div class="profile-content">
|
||||
<div class="avatar-section">
|
||||
<div class="avatar-wrapper" @click="showAvatarModel = true">
|
||||
<el-image style="width: 120px; height:120px" :src="setAddress(userInfo.tx)"
|
||||
show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/mr.png" class="user-avatar" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="avatar-upload-overlay">
|
||||
<el-icon class="upload-icon">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="avatar-hint">点击更换头像</div> -->
|
||||
</div>
|
||||
|
||||
<div class="info-section">
|
||||
<div class="info-item" @click="showEditModel = true">
|
||||
<span class="info-label">昵称:</span>
|
||||
<span class="info-value">{{ userInfo.nc }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">姓名:</span>
|
||||
<span class="info-value">{{ userInfo.xm }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">部门:</span>
|
||||
<span class="info-value single-line-ellipsis">{{ userInfo.deptName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 更换头像对话框 -->
|
||||
<ChangeTheAvatar v-model="showAvatarModel" title="更换头像" :heightNumber="250" @avatarUpdated="handleAvatarUpdated">
|
||||
</ChangeTheAvatar>
|
||||
|
||||
<!-- 编辑信息对话框 -->
|
||||
<el-dialog v-model="showEditModel" title="编辑昵称" width="600px" center :close-on-click-modal="false">
|
||||
<el-form ref="editForm" :model="editUserInfo" label-width="100px" :rules="rules">
|
||||
<el-form-item label="昵称" prop="nc">
|
||||
<el-input v-model="userInfo.nc" placeholder="请输入昵称"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showEditModel = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSave">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, watch } from "vue";
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import ChangeTheAvatar from './changeTheAvatar.vue';
|
||||
import { tbGsxtXxltTxTxQueryBySfzh, tbGsxtXxltTxTxSave } from '@/api/tbGsxtXxltHf.js'
|
||||
import { getItem,setItem ,removeItem} from '@/utils/storage.js'
|
||||
import { setAddress } from '@/utils/tools'
|
||||
|
||||
// 控制显示状态的变量
|
||||
const showAvatarModel = ref(false);
|
||||
const showEditModel = ref(false);
|
||||
|
||||
// 用户信息
|
||||
const userInfo = ref({});
|
||||
|
||||
// 编辑表单数据
|
||||
const editUserInfo = reactive({});
|
||||
|
||||
// 表单验证规则
|
||||
const rules = {
|
||||
nc: [
|
||||
{ required: true, message: '请输入昵称', trigger: 'blur' },
|
||||
{ min: 2, max: 20, message: '昵称长度在 2 到 20 个字符', trigger: 'blur' }
|
||||
]
|
||||
|
||||
};
|
||||
|
||||
// 编辑表单引用
|
||||
const editForm = ref();
|
||||
// 监听编辑对话框显示,复制用户信息到编辑表单
|
||||
watch(() => showEditModel.value, (newVal) => {
|
||||
if (newVal) {
|
||||
// 深拷贝用户信息到编辑表单
|
||||
Object.assign(editUserInfo, userInfo.value);
|
||||
}
|
||||
});
|
||||
// 处理头像更新
|
||||
const handleAvatarUpdated = (newAvatar) => {
|
||||
|
||||
userInfo.value.tx = newAvatar
|
||||
tbGsxtXxltTxTxSave(userInfo.value).then(res => {
|
||||
removeItem('ltmasg')
|
||||
gettbGsxtXxltTxTxQueryBySfzh()
|
||||
ElMessage({ message: '头像更新成功', type: 'success' });
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
// 处理保存编辑信息
|
||||
const handleSave = () => {
|
||||
editForm.value.validate((valid) => {
|
||||
if (valid) {
|
||||
showEditModel.value = false;
|
||||
tbGsxtXxltTxTxSave(userInfo.value).then(res => {
|
||||
removeItem('ltmasg')
|
||||
gettbGsxtXxltTxTxQueryBySfzh()
|
||||
ElMessage({ message: '信息保存成功', type: 'success' });
|
||||
})
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
const gettbGsxtXxltTxTxQueryBySfzh = () => {
|
||||
const sfzh = getItem('idEntityCard')
|
||||
const ltmasg= getItem('ltmasg')
|
||||
if (!ltmasg) {
|
||||
tbGsxtXxltTxTxQueryBySfzh({
|
||||
sfzh: sfzh
|
||||
}).then(res => {
|
||||
const deptId = getItem('deptId')[0]
|
||||
userInfo.value = { ...res, deptName: deptId.deptName }
|
||||
setItem('ltmasg', userInfo.value)
|
||||
})
|
||||
} else { userInfo.value = ltmasg
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
gettbGsxtXxltTxTxQueryBySfzh()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-container {
|
||||
// height: 100%;
|
||||
// padding: 20px;
|
||||
background-color: #f6f7fb;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-profile-card {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
padding: 24px;
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.profile-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.avatar-wrapper {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
border: 3px solid #e8e8e8;
|
||||
transition: border-color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.avatar-upload-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-hint {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
.info-section {
|
||||
width: 100%;
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
// width: 100px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.single-line-ellipsis {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.app-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.user-profile-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.avatar-section .avatar-wrapper {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.info-section .info-item {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
.info-label {
|
||||
width: auto;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
460
src/views/forumPost/components/theRight.vue
Normal file
460
src/views/forumPost/components/theRight.vue
Normal file
@ -0,0 +1,460 @@
|
||||
<template>
|
||||
|
||||
<div class="app-container" v-show="cs">
|
||||
<div class="publish-section"><el-button type="primary" @click="handleEdit()">发布帖子</el-button></div>
|
||||
<div v-if="list.length > 0" v-infinite-scroll="load">
|
||||
<div class="post-card" v-for="(item, index) in list" :key="index">
|
||||
<div class="post-content" @click="handleOpen(item)" @mouseenter="showActions[index] = true"
|
||||
@mouseleave="showActions[index] = false">
|
||||
<div class="post-header">
|
||||
<div class="post-title">
|
||||
{{ item.title || '无标题' }}
|
||||
</div>
|
||||
<div class="post-meta">
|
||||
<div class="post-time" style="margin-right: 20px;" title="发布人">{{ item.fbrxm || '暂无发布人' }}</div>
|
||||
<div class="post-time" title="发布时间">{{ item.time || '暂无时间' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="post-body">
|
||||
<div class="post-text">
|
||||
{{ item.content }}
|
||||
</div>
|
||||
<div class="post-images">
|
||||
<div class="image-list">
|
||||
<div v-for="(img, imgIndex) in item.tp" :key="imgIndex" class="image-item" v-if="item.tp && item.tp.length > 0">
|
||||
<el-image :src="setAddress(img)" show-progress>
|
||||
<template #error>
|
||||
<div class="image-slot error">
|
||||
<img src="@/assets/images/default_male.png" width="80" height="80" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;justify-content: flex-end;margin-bottom: 10px;" v-if="sfzh == item.fbrsfzh">
|
||||
<el-button type="text" size="small" class="action-btn edit-btn" @click.stop="handleEdit(item)">
|
||||
<el-icon>
|
||||
<Edit />
|
||||
</el-icon> 修改
|
||||
</el-button>
|
||||
<el-button type="text" size="small" class="action-btn delete-btn" @click.stop="handleDelete(item)">
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon> 删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空数据占位 -->
|
||||
<div v-else class="empty-data">
|
||||
<div class="empty-icon">
|
||||
<el-icon size="64">
|
||||
<Document />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="empty-text">暂无帖子数据</div>
|
||||
<div class="empty-hint">点击上方按钮发布第一条帖子吧</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<Release v-model="showModel" :ItemData="ItemData" @SaveReport="SaveReport" title="帖子发布" :showCancel="false"
|
||||
:heightNumber="436"></Release>
|
||||
<Particulars ref="particulars"/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Release from './release.vue'
|
||||
import { setAddress } from '@/utils/tools'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { tbGsxtXxltSelectPage, tbGsxtXxltDelete ,tbGsxtXxltHfid} from '@/api/tbGsxtXxltHf'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Edit, Delete, Document } from '@element-plus/icons-vue'
|
||||
import { getItem } from '@/utils/storage.js'
|
||||
import Particulars from "./particulars.vue";
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const particulars = ref()
|
||||
const showModel = ref(false)
|
||||
const listQuery = reactive({
|
||||
pageCurrent: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
const total = ref(0)
|
||||
const list = ref([])
|
||||
const showActions = ref({})
|
||||
const sfzh = ref()
|
||||
const ItemData = ref()
|
||||
const cs=ref(false)//需要删除
|
||||
onMounted(() => {
|
||||
sfzh.value = getItem('idEntityCard')
|
||||
SaveReport()
|
||||
if (route.query.id) {
|
||||
tbGsxtXxltHfid(route.query.id).then(res => {
|
||||
ItemData.value = res
|
||||
particulars.value.init(ItemData.value)
|
||||
cs.value=true
|
||||
})
|
||||
} else {
|
||||
cs.value=true
|
||||
}
|
||||
|
||||
})
|
||||
const SaveReport = () => {
|
||||
tbGsxtXxltSelectPage(listQuery).then(res => {
|
||||
// 使用可选链操作符和箭头函数隐式返回优化代码
|
||||
const data = (res.records || []).map(item => ({
|
||||
...item,
|
||||
tp: item.tp ? item.tp.split(',') : []
|
||||
}))
|
||||
total.value = res.total || 0
|
||||
// 初始化所有操作按钮为隐藏状态
|
||||
const actions = {}
|
||||
list.value = data
|
||||
list.value.forEach((_, index) => {
|
||||
actions[index] = false
|
||||
})
|
||||
|
||||
showActions.value = actions
|
||||
})
|
||||
}
|
||||
|
||||
const handleOpen = (item) => {
|
||||
particulars.value.init(item);
|
||||
}
|
||||
|
||||
// 修改帖子
|
||||
const handleEdit = (item) => {
|
||||
ItemData.value = item
|
||||
// 这里可以添加实际的修改逻辑
|
||||
showModel.value = true
|
||||
}
|
||||
|
||||
// 删除帖子
|
||||
const handleDelete = (item) => {
|
||||
ElMessageBox.confirm(
|
||||
`确定要删除帖子「${item.title}」吗?`,
|
||||
'删除确认',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
tbGsxtXxltDelete(item.id).then(res => {
|
||||
if (res) {
|
||||
ElMessage({ message: `帖子「${item.title}」已删除`, type: 'success' })
|
||||
SaveReport() // 删除后刷新列表
|
||||
} else {
|
||||
ElMessage({ message: `删除帖子「${item.title}」失败:${res.msg || '未知错误'}`, type: 'error' })
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
ElMessage({ message: '已取消删除', type: 'info' })
|
||||
})
|
||||
}
|
||||
const load = () => {
|
||||
|
||||
if (listQuery.pageCurrent * listQuery.pageSize < total.value) {
|
||||
listQuery.pageCurrent++
|
||||
SaveReport()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// 主容器样式
|
||||
.app-container {
|
||||
padding: 16px;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
// 发布按钮区域
|
||||
.publish-section {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
// 帖子卡片样式
|
||||
.post-card {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
// 帖子内容区域
|
||||
.post-content {
|
||||
padding: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// 帖子头部
|
||||
.post-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
// 帖子标题
|
||||
.post-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #409eff;
|
||||
margin-right: 16px;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
transition: color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
// 帖子元信息
|
||||
.post-meta {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
// 发布时间
|
||||
.post-time {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// 帖子主体
|
||||
.post-body {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// 帖子文本内容
|
||||
.post-text {
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 12px;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// 帖子图片容器
|
||||
.post-images {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
// 图片列表
|
||||
.image-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: -4px;
|
||||
}
|
||||
|
||||
// 图片项
|
||||
.image-item {
|
||||
margin: 4px;
|
||||
width: 100px;
|
||||
height: 160px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
// 帖子图片
|
||||
.post-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
// 更多图片提示
|
||||
.image-more {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
// 操作按钮容器
|
||||
.post-actions {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
background: white;
|
||||
padding: 8px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
// 操作按钮显示状态
|
||||
.post-actions-visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
// 操作按钮基础样式
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 12px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
background: #f5f7fa;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
// 修改按钮样式
|
||||
.edit-btn:hover {
|
||||
color: #409eff;
|
||||
background: #ecf5ff;
|
||||
}
|
||||
|
||||
// 删除按钮样式
|
||||
.delete-btn:hover {
|
||||
color: #f56c6c;
|
||||
background: #fef0f0;
|
||||
}
|
||||
|
||||
// 空数据样式
|
||||
.empty-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 20px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
margin-bottom: 16px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 16px;
|
||||
margin-bottom: 8px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
// 移动端适配
|
||||
@media (max-width: 768px) {
|
||||
.app-container {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.post-card {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.post-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.post-text {
|
||||
font-size: 13px;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.image-item {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.image-more {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.post-actions {
|
||||
right: 12px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 3px 8px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.empty-data {
|
||||
padding: 40px 16px;
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
134
src/views/forumPost/components/writeBack.vue
Normal file
134
src/views/forumPost/components/writeBack.vue
Normal file
@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" center width="1000px" :destroy-on-close="true" :title="title" @close="close"
|
||||
:close-on-click-modal="false">
|
||||
<div class="cntBox">
|
||||
<FormMessage :formList="formData" v-model="hfrsfzh" ref="elform" :rules="rules" >
|
||||
<template #content>
|
||||
<el-input type="textarea" placeholder="请输入内容" v-model="hfrsfzh.hfnr"></el-input>
|
||||
<div style="width: 100%;border-bottom: 1px solid #eee;margin-top: 10px">
|
||||
<V3Emoji :options-name="optionsName" width="40px" title="表情" @click-emoji="onVue3Emoje"
|
||||
:recent="true" ></V3Emoji>
|
||||
</div>
|
||||
</template>
|
||||
</FormMessage>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="downloadWithStyles" :loading="loading">发布</el-button>
|
||||
<el-button type="primary" @click="close">取消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import "@wangeditor/editor/dist/css/style.css";
|
||||
import V3Emoji from "vue3-emoji";
|
||||
import FormMessage from "@/components/aboutTable/FormMessage.vue";
|
||||
import { getItem } from '@/utils/storage.js'
|
||||
import { tbGsxtXxltHfSave } from '@/api/tbGsxtXxltHf'
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { ref, defineEmits, defineProps, watch, reactive ,computed} from "vue";
|
||||
const optionsName = {
|
||||
'Smileys & Emotion': '笑脸&表情',
|
||||
'Food & Drink': '食物&饮料',
|
||||
'Animals & Nature': '动物&自然',
|
||||
'Travel & Places': '旅行&地点',
|
||||
'People & Body': '人物&身体',
|
||||
Objects: '物品',
|
||||
Symbols: '符号',
|
||||
Flags: '旗帜',
|
||||
Activities: '活动'
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "回复帖子"
|
||||
},
|
||||
heightNumber: {
|
||||
type: Number,
|
||||
default: 448
|
||||
},ItemData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
const emits = defineEmits(["changeFn", "update:modelValue", "SaveReport"]);
|
||||
const hfrsfzh = ref({hftp:[]})
|
||||
watch(() => props.ItemData, (newVal) => {
|
||||
if (newVal) {
|
||||
listQuery.value = {
|
||||
...newVal,
|
||||
hftp:newVal.hftp?newVal.hftp.split(','):[]
|
||||
}
|
||||
console.log(listQuery.value);
|
||||
}
|
||||
}, { deep: true })
|
||||
const listQuery = ref({hftp:[]})
|
||||
const elform = ref()
|
||||
const formData = ref([
|
||||
{ label: "帖子内容", prop: "content", type: "slot", width: '100%' },
|
||||
{ label: "图片", prop: "hftp", type: "upload", width: '100%', limit: 10 },
|
||||
])
|
||||
const loading = ref(false)
|
||||
const rules = reactive({
|
||||
hfnr: [
|
||||
{ required: true, message: "请输入帖子内容", trigger: "blur" }
|
||||
]
|
||||
})
|
||||
|
||||
const onVue3Emoje = (val) => {
|
||||
hfrsfzh.value.hfnr += val
|
||||
}
|
||||
const downloadWithStyles = () => {
|
||||
const ltmasg = getItem('ltmasg')
|
||||
const params = {
|
||||
hfnr: hfrsfzh.value.hfnr,
|
||||
hfrsfzh: ltmasg.sfzh,
|
||||
hfrtx: ltmasg.tx,
|
||||
hfrxm: ltmasg.xm,
|
||||
ltid: listQuery.value.id,
|
||||
sfyjhf: "1",
|
||||
hftp:hfrsfzh.value.hftp?hfrsfzh.value.hftp.join(','):''
|
||||
}
|
||||
loading.value = true
|
||||
tbGsxtXxltHfSave(params).then(res => {
|
||||
close()
|
||||
emits("SaveReport", res);
|
||||
ElMessage.success('回复成功');
|
||||
}).finally(()=>{
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emits('update:modelValue', value)
|
||||
});
|
||||
|
||||
const close = () => {
|
||||
hfrsfzh.value.hftp = []
|
||||
hfrsfzh.value = {}
|
||||
dialogVisible.value = false
|
||||
// emits("update:modelValue", false);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cntBox {
|
||||
height: 60vh;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
border: 1px dashed #e9e9e9;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__label {
|
||||
width: 80px !important;
|
||||
}
|
||||
</style>
|
||||
40
src/views/forumPost/index.vue
Normal file
40
src/views/forumPost/index.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle title="情报论坛"> </PageTitle>
|
||||
</div>
|
||||
<div class=" bilateral">
|
||||
<div class="the-left"> <TheLeft/></div>
|
||||
<div class="the-right"> <TheRight @handleOpen="handleOpen"/></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import TheLeft from "./components/theLeft.vue";
|
||||
import TheRight from "./components/theRight.vue";
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.bilateral{
|
||||
background-color: #fff;
|
||||
height: calc(100vh - 190px);
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
color: #000;
|
||||
justify-content: space-between;
|
||||
.the-left{
|
||||
width: 210px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.the-right{
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -1,22 +1,26 @@
|
||||
<template>
|
||||
<div class="warning-card ">
|
||||
<div class="warning-card" :style="{'border':`1px solid ${changeBG(item.yjJb)}`}" >
|
||||
<div class="warning-image flex">
|
||||
<el-image 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/default_male.png" width="65" height="70" v-else/>
|
||||
</div>
|
||||
<!-- -->
|
||||
<template v-if="!item.yjTp || item.yjTp.includes('baidu')">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</template>
|
||||
</el-image>
|
||||
|
||||
<el-image v-else 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/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>
|
||||
<span>{{ item.yjClcph }}</span>
|
||||
</div>
|
||||
<div class="flex align-center mt4" v-else>
|
||||
<span>{{ item.yjRyxm }}</span>
|
||||
<span class="gapline mr10 ml10"></span>
|
||||
@ -24,11 +28,11 @@
|
||||
<span class="gapline mr10 ml10"></span>
|
||||
<span>{{ IdCard(item.yjRysfzh, 3) }}</span>
|
||||
</div>
|
||||
<span class="tag" v-if="item.yjbqmc">{{ item.yjbqmc }}</span>
|
||||
<span class="tag" v-if="item.yjbqmc" :style="{'background':`${changeBG(item.yjJb)}`}">{{ item.yjbqmc }}</span>
|
||||
</div>
|
||||
<div v-if="item.yjLx == 2" class="flex">车牌类型:
|
||||
<DictTag :tag="false" :value="item.yjHplx" color="#fff" :options="dict.D_BZ_HPZL" />
|
||||
</div>
|
||||
<div v-if="item.yjLx == 2" class="flex">车牌类型:
|
||||
<DictTag :tag="false" :value="item.yjHplx" 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>
|
||||
@ -40,7 +44,9 @@
|
||||
<div class="mt4 two_text_detail">处置结果:{{ item.yjNr }}</div>
|
||||
</div>
|
||||
<div class="warning-info pt5 ">
|
||||
<div class="two_text_detail flex lh25"><img src="@/assets/images/ddtb.png" width="20" height="25" alt="" srcset="">{{ item.yjNr }}</div>
|
||||
<div class="two_text_detail flex lh25"><img src="@/assets/images/ddtb.png" width="20" height="25" alt=""
|
||||
srcset="">{{
|
||||
item.yjNr }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -65,7 +71,7 @@ const changeBG = (str) => {
|
||||
case "20":
|
||||
return "orange";
|
||||
case "30":
|
||||
return "yellow";
|
||||
return "#b5b522";
|
||||
default: return "blue";
|
||||
}
|
||||
};
|
||||
@ -73,8 +79,9 @@ const changeBG = (str) => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.warning-card {
|
||||
background: url("~@/assets/images/xxxxxx.png") no-repeat center center;
|
||||
// background: url("~@/assets/images/xxxxxx.png") no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
|
||||
gap: 12px;
|
||||
margin-bottom: 4px;
|
||||
padding: 10px;
|
||||
@ -129,8 +136,9 @@ const changeBG = (str) => {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.warning-boder{
|
||||
border-bottom: 2px dashed #0958b2;
|
||||
|
||||
.warning-boder {
|
||||
border-bottom: 2px dashed #0958b2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,20 +1,32 @@
|
||||
<template>
|
||||
<div class="warning-card flex align-center" :class="changeBG(item.yjJb)">
|
||||
<div class="warning-image">
|
||||
<el-image style="width: 80px; height:120px" :src="item.yjTp" :preview-src-list="[item.yjTp]" show-progress>
|
||||
<template v-if="!item.yjTp || item.yjTp.includes('baidu')">
|
||||
<img src="@/assets/images/car.png" width="65" height="70" v-if="item.yjLx == 2" />
|
||||
<img src="@/assets/images/default_male.png" width="65" height="70" v-else />
|
||||
</template>
|
||||
<el-image v-else style="width: 80px; height:120px" :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/default_male.png" width="65" height="70" v-else />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<!-- <el-image style="width: 80px; height:120px" :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/default_male.png" width="65" height="70" v-else/>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</el-image> -->
|
||||
<!-- <img :src="item.yjTp" width="80" height="120" alt="" /> -->
|
||||
</div>
|
||||
<div class="warning-info">
|
||||
<div class="flex just-between align-center">
|
||||
<div class="flex align-center mt4" v-if="item.yjLx == 2">
|
||||
<span >{{ item.yjClcph }}</span>
|
||||
<span>{{ item.yjClcph }}</span>
|
||||
</div>
|
||||
<div class="flex align-center mt4" v-else>
|
||||
<span>{{ item.yjRyxm }}</span>
|
||||
@ -24,15 +36,24 @@
|
||||
<span>{{ IdCard(item.yjRysfzh, 3) }}</span>
|
||||
</div>
|
||||
|
||||
<span class="tag" v-if="item.yjbqmc">{{ item.yjbqmc }}</span>
|
||||
<span class="tag" v-if="item.yjbqmc" :style="{ 'background': `${changeBG(item.yjJb)}` }">{{ item.yjbqmc }}</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.yjLx == 2" class="flex">车牌类型:
|
||||
<DictTag :tag="false" :value="item.yjHplx" 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 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>
|
||||
@ -57,7 +78,7 @@ const changeBG = (str) => {
|
||||
case "20":
|
||||
return "orange";
|
||||
case "30":
|
||||
return "yellow";
|
||||
return "#b5b522";
|
||||
default: return "blue";
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,29 +1,25 @@
|
||||
<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>
|
||||
<MOSTY.Empty :show="props.data.length <= 0" :imgSize="150"></MOSTY.Empty>
|
||||
</ul>
|
||||
<!-- :style="{height: `calc(100vh - ${handleHs}px)`}" -->
|
||||
|
||||
<div style="position:relative;width: 100%;" :style="{ height: `calc(100vh - ${handleHs}px)` }">
|
||||
<GdMap v-if="showMap"></GdMap>
|
||||
<GdMap v-if="showMap" :mapKey="'home_yj_map'" :mapid="'homeYjMap'" />
|
||||
</div>
|
||||
</DialogDragger>
|
||||
</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 { ref, defineProps, onMounted, watch } from "vue";
|
||||
import { ref, defineProps, onMounted, watch, getCurrentInstance } from "vue";
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
const gjyjList = ref(null); //预警列表数据
|
||||
const { proxy } = getCurrentInstance();
|
||||
//参数传递
|
||||
const props = defineProps({
|
||||
//某条预警详情
|
||||
@ -36,7 +32,6 @@ const props = defineProps({
|
||||
default: false
|
||||
},
|
||||
});
|
||||
console.log(props.show);
|
||||
|
||||
//关闭
|
||||
function close() {
|
||||
@ -48,23 +43,51 @@ onMounted(() => {
|
||||
setTimeout(() => {
|
||||
showMap.value = true
|
||||
setTimeout(() => {
|
||||
// 只删除一次home_yj_map区域的点,避免影响其他地图
|
||||
emitter.emit('deletePointArea', 'home_yj_map');
|
||||
|
||||
// 收集所有有效坐标的数据点
|
||||
const validPoints = [];
|
||||
for (let i = 0; i < props.data.length; i++) {
|
||||
const item = props.data[i];
|
||||
console.log(item);
|
||||
// 修复重复的坐标判断条件
|
||||
if (!item.jd || !item.wd) {
|
||||
// 使用警告而不是return,避免中断循环
|
||||
console.warn("该预警没有坐标:", item);
|
||||
continue;
|
||||
}
|
||||
validPoints.push(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 });
|
||||
// 如果有有效点,显示第一条并添加所有点
|
||||
if (validPoints.length > 0) {
|
||||
// 只显示第一条数据的详情
|
||||
emitter.emit('showHomeYJ', [validPoints[0]]);
|
||||
|
||||
// 为每个有效点添加标记
|
||||
validPoints.forEach((item, index) => {
|
||||
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_${index}`,
|
||||
baseFlag: 'home_yj_map',
|
||||
icon,
|
||||
coords: [item]
|
||||
});
|
||||
});
|
||||
|
||||
// 只设置一次地图中心(使用第一个有效点)
|
||||
emitter.emit('setMapCenter', {
|
||||
location: [validPoints[0].jd, validPoints[0].wd],
|
||||
zoomLevel: 10,
|
||||
flag: 'home_yj_map' // 添加标识,确保只影响当前地图
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
|
||||
|
||||
}, 200);
|
||||
})
|
||||
const handleHs = ref(0)
|
||||
|
||||
@ -254,6 +254,10 @@ function lineChartFn(xDate, legend, series) {
|
||||
transitionDuration: 0.2,
|
||||
// 设置提示框位置
|
||||
position: function (point, params, dom, rect, size) {
|
||||
// console.log(point, params, dom, rect, size);
|
||||
// 设置提示框的z-index为999,确保显示在最上层
|
||||
dom.style.zIndex = 999;
|
||||
|
||||
// 计算提示框位置,避免超出边界
|
||||
let x = point[0] + 15;
|
||||
let y = point[1] - 10;
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<div class="homeBox">
|
||||
<!-- <GdMap></GdMap> -->
|
||||
<!-- 头部 -->
|
||||
|
||||
<Head></Head>
|
||||
<!-- 左边 -->
|
||||
<div class="home-aside asideL">
|
||||
<div class="asideL-top">
|
||||
|
||||
<DbCount></DbCount>
|
||||
</div>
|
||||
<div class="asideL-Bottom">
|
||||
@ -16,116 +17,175 @@
|
||||
<QblyType></QblyType>
|
||||
</div>
|
||||
<div class="commom-aside">
|
||||
<QbfkCount></QbfkCount>
|
||||
<!-- <GroupWarning /> -->
|
||||
<TextType></TextType>
|
||||
<!-- <QbfkCount></QbfkCount> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右边 -->
|
||||
<div class="home-aside asideR">
|
||||
<div class="commom-aside-big">
|
||||
<SituationAssessment />
|
||||
<Calendar />
|
||||
</div>
|
||||
<div class="commom-aside-big">
|
||||
<GroupWarning />
|
||||
<Experience />
|
||||
|
||||
</div>
|
||||
<div class="commom-aside-small">
|
||||
<Experience />
|
||||
<SituationAssessment />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 中间 -->
|
||||
<div class="home-center">
|
||||
<div class="middle-top"><Yszs /></div>
|
||||
<div class="flex middle-bottom mt10">
|
||||
<div class="mr10" style="width: 50%;"><DeployControl /></div>
|
||||
<div class="flex-1" style="flex: 1;"><ZdryWarning /></div>
|
||||
<div class="middle-top">
|
||||
<Yszs />
|
||||
</div>
|
||||
<div class="flex middle-bottom mt10">
|
||||
<div style="width: 100%;border: 1px sienna;position: relative">
|
||||
<GdMap></GdMap>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
</div>
|
||||
<!-- 底部 -->
|
||||
<div class="home-foot-t">
|
||||
<Bkcz></Bkcz>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 左边弹窗 -->
|
||||
<LeftDialog></LeftDialog>
|
||||
|
||||
<Fxq :initial-position="{ x: position.x, y: position.y }">
|
||||
<el-badge value="0" class="item badge-top-left">
|
||||
<div class='fxq fxq1'>
|
||||
<div class="title" @click.stop="opneMsg('xtxx')"> <img src="@/assets/images/xtxx.png" /> 系统消息</div>
|
||||
</div>
|
||||
</el-badge>
|
||||
<!-- <div class='fxq fxq2'>
|
||||
<div class="title" @click.stop="opneMsg('tztg')"> <img src="@/assets/images/tztg.png" /> 通知通报</div>
|
||||
</div>
|
||||
<div class='fxq fxq3'>
|
||||
<div class="title"> <img src="@/assets/images/xxxt.png" /> 消息协同</div>
|
||||
</div> -->
|
||||
</Fxq>
|
||||
<Information v-model='showDialog' :title='title'>
|
||||
<systemMessages :dict="{ BD_D_XXLX, BD_D_XXLY }" :idEntityCard='idEntityCard' :xxlx="showMsgLx" />
|
||||
</Information>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, getCurrentInstance, reactive } from 'vue'
|
||||
import { ref, getCurrentInstance, reactive, onMounted } from 'vue'
|
||||
import LeftDialog from './dialog/leftDialog'
|
||||
import GdMap from "@/components/GdMap/index.vue";
|
||||
import Head from './layout/head.vue'
|
||||
import DbCount from './model/dbCount.vue'
|
||||
import QbfkCount from './model/qbfkCount.vue'
|
||||
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 ZdryWarning from './model/zdryWarning.vue'
|
||||
import GroupWarning from './model/groupWarning.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 Fxq from './model/fxq.vue'
|
||||
import Information from './model/information.vue'
|
||||
import systemMessages from './model/mesgSwitch/systemMessages.vue'
|
||||
import { getItem } from '@/utils/storage.js'
|
||||
import { queryXxTj} from '@/api/commit.js'
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { BD_D_XXLX, BD_D_XXLY } = proxy.$dict('BD_D_XXLX', 'BD_D_XXLY'); //获取字典数据
|
||||
const idEntityCard = getItem('idEntityCard')
|
||||
const position = reactive({
|
||||
x: window.innerWidth - 120,
|
||||
y: window.innerHeight - 100
|
||||
})
|
||||
import Calendar from './model/calendar.vue'
|
||||
|
||||
//消息
|
||||
const title = ref('系统消息')
|
||||
const showDialog = ref(false)
|
||||
const showMsgLx = ref('')
|
||||
const opneMsg = (val) => {
|
||||
showDialog.value = true
|
||||
showMsgLx.value = val
|
||||
switch (val) {
|
||||
case 'xtxx':
|
||||
title.value = '系统消息'
|
||||
break;
|
||||
case 'tztg':
|
||||
title.value = '通知通告'
|
||||
break;
|
||||
case 'xxxt':
|
||||
title.value = '消息协同'
|
||||
break;
|
||||
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) => {
|
||||
setTimeout(() => {
|
||||
// 先移除已有的边界
|
||||
emitter.emit('removeBj')
|
||||
if (trg) {
|
||||
console.log("多个");
|
||||
// 如果传入的是多个区域数据(二维数组)
|
||||
const features = val.map((area, index) => ({
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [area] // 确保格式正确
|
||||
},
|
||||
properties: {
|
||||
},
|
||||
type: "Feature"
|
||||
}))
|
||||
// 循环为每个区域创建单独的多边形,这样可以设置不同的样式
|
||||
features.forEach((feature, index) => {
|
||||
emitter.emit('setBoundarys', {
|
||||
data: {
|
||||
type: "FeatureCollection",
|
||||
features: [feature]
|
||||
},
|
||||
color: '#cf1010',
|
||||
fillColor: 'rgba(255, 255, 255,0)',
|
||||
})
|
||||
})
|
||||
} else {
|
||||
|
||||
// 保持原来的逻辑,处理单个区域
|
||||
emitter.emit('setBoundarys', {
|
||||
data: {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [val] // 使用正确的GeoJSON格式
|
||||
},
|
||||
properties: {},
|
||||
type: "Feature"
|
||||
}
|
||||
]
|
||||
},
|
||||
color: '#cf1010',
|
||||
fillColor: 'rgba(255, 255, 255,0)',
|
||||
})
|
||||
}
|
||||
}, 3000)
|
||||
}
|
||||
const getDepId = () => {
|
||||
const deptId = getItem('deptId')
|
||||
const deptLevel = deptId[0].deptLevel ? deptId[0].deptLevel : null
|
||||
const deptCode = deptId[0].deptCode ? deptId[0].deptCode : null
|
||||
if (deptLevel.startsWith('2')) {
|
||||
const data = Object.values(bm).map(item => item);
|
||||
changeXzqh(data,true)
|
||||
} else {
|
||||
switch (deptCode) {
|
||||
case '54040200000'://巴宜区
|
||||
changeXzqh(bm[542621])
|
||||
break;
|
||||
case '54042400000'://波密县
|
||||
changeXzqh(bm[542625])
|
||||
break;
|
||||
case '54042500000'://察隅县
|
||||
changeXzqh(bm[542626])
|
||||
break;
|
||||
case '54042100000'://工布江达县
|
||||
changeXzqh(bm[542622])
|
||||
break;
|
||||
case '54042600000'://朗县
|
||||
changeXzqh(bm[542627])
|
||||
break;
|
||||
case '54042200000'://米林县
|
||||
changeXzqh(bm[542623])
|
||||
break;
|
||||
case '54042300000'://墨脱县
|
||||
changeXzqh(bm[542624])
|
||||
break;
|
||||
default:
|
||||
const data = Object.values(bm).map(item => item);
|
||||
changeXzqh(data,true)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
const queryXxTjList = () => {
|
||||
queryXxTj({}).then((res) => {
|
||||
console.log(res);
|
||||
|
||||
}).catch((err) => {
|
||||
|
||||
});
|
||||
const makerCenter = () => {
|
||||
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] });
|
||||
}
|
||||
queryXxTjList()
|
||||
onMounted(() => {
|
||||
getDepId()
|
||||
makerCenter()
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -189,4 +249,36 @@ queryXxTjList()
|
||||
left: -10px;
|
||||
transform: translateY(-50%) translateX(-50%);
|
||||
}
|
||||
|
||||
.badge-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
max-height: 200px;
|
||||
/* 默认展开的最大高度 */
|
||||
min-height: 45px;
|
||||
/* 确保收缩时有足够空间显示第一个图标 */
|
||||
}
|
||||
|
||||
.badge-content:not(.expanded) {
|
||||
max-height: 45px;
|
||||
}
|
||||
|
||||
/* 收缩时只显示第一个图标,隐藏其他内容 */
|
||||
.badge-content:not(.expanded)> :not(:first-child) {
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.badge-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -156,8 +156,9 @@ onMounted(() => {
|
||||
|
||||
// 按钮切换
|
||||
const handleBtns = (val) => {
|
||||
btnsActive.value = val;
|
||||
console.log(val);
|
||||
|
||||
btnsActive.value = val;
|
||||
switch (val) {
|
||||
case "智能布控":
|
||||
router.push("/DeploymentArea");
|
||||
@ -177,12 +178,7 @@ const handleBtns = (val) => {
|
||||
// window.open(NPShref.href, "_blank");
|
||||
break;
|
||||
case "退出登录":
|
||||
window.opener = null;
|
||||
window.open('', '_self');
|
||||
window.close();
|
||||
store.commit("app/clearTag", null, { immediate: true });
|
||||
store.commit("permission/deleteRouter", { immediate: true });
|
||||
store.commit("user/deleteKeepLiiveRoute", "home");
|
||||
store.dispatch("user/logout");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@ -7,7 +7,18 @@
|
||||
<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="">
|
||||
<!-- <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"/>
|
||||
@ -28,11 +39,11 @@
|
||||
<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";
|
||||
@ -135,8 +146,8 @@ const tabHeightFn = () => {
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/css/homeScreen.scss";
|
||||
::v-deeep .comom-title{
|
||||
@ -164,4 +175,4 @@ const tabHeightFn = () => {
|
||||
color: #ffffff !important;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
426
src/views/home/model/calendar.vue
Normal file
426
src/views/home/model/calendar.vue
Normal file
@ -0,0 +1,426 @@
|
||||
<template>
|
||||
<div class="comom-title" @click="calendarPush">
|
||||
<span class="title">敏感节点</span>
|
||||
</div>
|
||||
<el-calendar ref="calendar" v-model="currentDate">
|
||||
<template #header="{ date }">
|
||||
<div>
|
||||
<el-select size="small" @change="goToSelectedMonth" v-model="selectedYear"
|
||||
style="width: 80px; margin-right: 10px;">
|
||||
<el-option v-for="year in years" :key="year" :label="year + '年'" :value="year" />
|
||||
</el-select>
|
||||
<el-select size="small" @change="goToSelectedMonth" v-model="selectedMonth" style="width: 80px;">
|
||||
<el-option v-for="month in months" :key="month.value" :label="month.label" :value="month.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div>
|
||||
<el-button size="small" @click="selectDate('today')">今天</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #dateCell="{ data }">
|
||||
<el-popover trigger="click" :width="400" title="敏感事件" popper-class="custom-sensitive-popover">
|
||||
<!-- 日期信息区域 -->
|
||||
<div class="date-info-section">
|
||||
<div class="gan-date-item">
|
||||
<span class="date-label">公历日期:</span>
|
||||
<span class="date-value">{{ getYearInGanDate(data) }}</span>
|
||||
</div>
|
||||
<div class="lunar-date-item">
|
||||
<span class="date-label">农历日期:</span>
|
||||
<span class="date-value">农历 {{ getLunarMonthDay(data.date, true) }}({{ getYearInGanZhis(data) }})</span>
|
||||
</div>
|
||||
<div class="jieqi-date-item">
|
||||
<span class="date-label">节气信息:</span>
|
||||
<span class="date-value jieqi-highlight">{{ getYearInGanjq(data) || '无' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 敏感时间节点内容 -->
|
||||
<div v-if="sensitiveNodes.length > 0" class="sensitive-content-popover">
|
||||
<div v-for="(item, index) in sensitiveNodes" :key="index" class="sensitive-item-popover">
|
||||
<div class="sensitive-date-popover">{{ item.jdrq }}</div>
|
||||
<div class="sensitive-title-popover">{{ item.jdbt }}</div>
|
||||
<div class="sensitive-desc-popover">{{ item.jdnr }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="sensitive-empty-popover">
|
||||
暂无敏感事件
|
||||
</div>
|
||||
|
||||
<template #reference>
|
||||
<div @click="chooseDay(data)" class="dayonChage" :class="{
|
||||
'day': dateVal == data.day,
|
||||
'special': dataIntegration.includes(data.day)
|
||||
}">
|
||||
<span> {{ data.day.split("-")[2] }}</span>
|
||||
<span style="font-size: 8px;"> {{ getLunarMonthDay(data.date) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
|
||||
</template>
|
||||
</el-calendar>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { Solar, Lunar } from 'lunar-javascript'
|
||||
import { timeValidate } from "@/utils/tools";
|
||||
import { useRouter } from 'vue-router'
|
||||
import { tbGsxtMgjdSave, tbGsxtMgjdSelectList, tbGsxtMgjdUpdate, tbGsxtMgjdDelete } from "@/api/tbGsxtMgjd";
|
||||
const dateVal = ref();
|
||||
const router = useRouter()
|
||||
// 获取农历月日
|
||||
const getLunarMonthDay = (date, pd) => {
|
||||
if (!date) return ''
|
||||
const solar = Solar.fromDate(date)
|
||||
const lunar = solar.getLunar()
|
||||
if (pd) {
|
||||
return `${lunar.getMonthInChinese()}月${lunar.getDayInChinese()}`
|
||||
} else {
|
||||
return lunar.getJieQi() ? lunar.getJieQi() : lunar.getDayInChinese()
|
||||
}
|
||||
}
|
||||
// 获取生效年
|
||||
const getYearInGanZhis = (data) => {
|
||||
const solar = Solar.fromDate(data.date)
|
||||
const lunar = solar.getLunar()
|
||||
return `${lunar.getYearInGanZhi()}年${lunar.getMonthInGanZhiExact()}月${lunar.getDayInGanZhi()}日`
|
||||
}
|
||||
// 获取日期
|
||||
const getYearInGanDate = (data) => {
|
||||
const solar = Solar.fromDate(data.date)
|
||||
return `${solar.getYear()}年${solar.getMonth()}月${solar.getDay()}日 星期${solar.getWeekInChinese()}`
|
||||
}
|
||||
// 获取节气
|
||||
const getYearInGanjq = (data) => {
|
||||
const solar = Solar.fromDate(data.date)
|
||||
const lunar = solar.getLunar()
|
||||
return lunar.getJieQi()
|
||||
}
|
||||
|
||||
const selectedYear = ref();
|
||||
const selectedMonth = ref('');
|
||||
const calendar = ref(null)
|
||||
// 生成年份选项(前后10年)
|
||||
const years = computed(() => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
const years = [];
|
||||
for (let i = currentYear - 10; i <= currentYear + 10; i++) {
|
||||
years.push(i);
|
||||
}
|
||||
return years;
|
||||
});
|
||||
|
||||
// 月份选项
|
||||
const months = ref([
|
||||
{ label: '1月', value: 0 },
|
||||
{ label: '2月', value: 1 },
|
||||
{ label: '3月', value: 2 },
|
||||
{ label: '4月', value: 3 },
|
||||
{ label: '5月', value: 4 },
|
||||
{ label: '6月', value: 5 },
|
||||
{ label: '7月', value: 6 },
|
||||
{ label: '8月', value: 7 },
|
||||
{ label: '9月', value: 8 },
|
||||
{ label: '10月', value: 9 },
|
||||
{ label: '11月', value: 10 },
|
||||
{ label: '12月', value: 11 }
|
||||
]);
|
||||
const chooseDay = (data) => {
|
||||
dateVal.value = data.day
|
||||
querySensitiveNodes()
|
||||
}
|
||||
|
||||
// 敏感时间节点数据
|
||||
const sensitiveNodes = ref([]);
|
||||
|
||||
// 查询敏感事件
|
||||
const querySensitiveNodes = () => {
|
||||
tbGsxtMgjdSelectList({ jdrq: dateVal.value }).then((res) => {
|
||||
sensitiveNodes.value = res && res.length > 0 ? res : []
|
||||
})
|
||||
}
|
||||
const currentDate = ref(new Date());
|
||||
onMounted(() => {
|
||||
initialize()
|
||||
})
|
||||
const goToSelectedMonth = () => {
|
||||
if (selectedYear.value && selectedMonth.value !== '') {
|
||||
const newDate = new Date(selectedYear.value, selectedMonth.value, 1);
|
||||
currentDate.value = newDate;
|
||||
dateVal.value = timeValidate(currentDate.value, 'ymd')
|
||||
}
|
||||
};
|
||||
const selectDate = (val) => {
|
||||
if (!calendar.value) return
|
||||
dateVal.value = timeValidate(currentDate.value, 'ymd')
|
||||
calendar.value.selectDate(val)
|
||||
initialize()
|
||||
}
|
||||
// 获取当前时间
|
||||
const initialize = () => {
|
||||
const year = timeValidate(currentDate.value, 'yd')
|
||||
const month = timeValidate(currentDate.value, 'ym')
|
||||
dateVal.value = timeValidate(currentDate.value, 'ymd')
|
||||
selectedYear.value = parseFloat(year)
|
||||
selectedMonth.value = parseFloat(month) - 1
|
||||
gettingData()
|
||||
}
|
||||
const dataIntegration = ref([])
|
||||
// 获取当前月份的所有信息
|
||||
const gettingData = () => {
|
||||
const date = new Date(dateVal.value);
|
||||
date.setDate(1)
|
||||
const startTime = timeValidate(date.toLocaleDateString(), 'ymd')
|
||||
date.setMonth(date.getMonth() + 1);
|
||||
date.setDate(0);
|
||||
const endTime = timeValidate(date.toLocaleDateString(), 'ymd')
|
||||
const params = { startTime, endTime }
|
||||
tbGsxtMgjdSelectList(params).then(res => {
|
||||
if (res && res.length > 0) {
|
||||
dataIntegration.value = [...new Set(res.map(item => item.jdrq))] ? [...new Set(res.map(item => item.jdrq))] : []
|
||||
}
|
||||
})
|
||||
}
|
||||
// 获取农历月日
|
||||
// const getLunarMonthDay = (date) => {
|
||||
// if (!date) return ''
|
||||
// const solar = Solar.fromDate(date)
|
||||
// const lunar = solar.getLunar()
|
||||
// return `${lunar.getMonthInChinese()}${lunar.getDayInChinese()}`
|
||||
// }
|
||||
const calendarPush = () => {
|
||||
router.push('/calendar')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/css/homeScreen.scss";
|
||||
|
||||
.zdryBox {
|
||||
background: #052249;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
|
||||
.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-calendar__header {
|
||||
padding: 4px 20px !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar__body {
|
||||
padding: 3px 20px 35px !important;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table thead th {
|
||||
padding: 4px 0 !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table td.is-today {
|
||||
color: #35ff02;
|
||||
}
|
||||
|
||||
/* 敏感事件列表容器 */
|
||||
.sensitive-content-popover {
|
||||
padding: 12px;
|
||||
overflow: auto;
|
||||
max-height: 350px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* 敏感事件项 */
|
||||
.sensitive-item-popover {
|
||||
margin-bottom: 16px;
|
||||
padding: 12px;
|
||||
background-color: #fafafa;
|
||||
border-radius: 6px;
|
||||
border-left: 4px solid #f56c6c;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.sensitive-item-popover:hover {
|
||||
background-color: #f5f7fa;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.sensitive-item-popover:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 敏感事件日期 */
|
||||
.sensitive-date-popover {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
margin-bottom: 6px;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
/* 敏感事件标题 */
|
||||
.sensitive-title-popover {
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 敏感事件描述 */
|
||||
.sensitive-desc-popover {
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* 无敏感事件提示 */
|
||||
.sensitive-empty-popover {
|
||||
text-align: center;
|
||||
padding: 30px 20px;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.sensitive-empty-popover:before {
|
||||
content: "📅";
|
||||
display: block;
|
||||
font-size: 32px;
|
||||
margin-bottom: 12px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* 日期信息区域样式 */
|
||||
.date-info-section {
|
||||
padding: 12px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 10px;
|
||||
border-left: 4px solid #409eff;
|
||||
}
|
||||
|
||||
.gan-date-item,
|
||||
.lunar-date-item,
|
||||
.jieqi-date-item {
|
||||
line-height: 28px;
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.gan-date-item:last-child,
|
||||
.lunar-date-item:last-child,
|
||||
.jieqi-date-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.date-label {
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.date-value {
|
||||
color: #303133;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.jieqi-highlight {
|
||||
color: #f56c6c;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 自定义el-popover标题样式 */
|
||||
.custom-sensitive-popover .el-popover__title {
|
||||
background-color: #409eff;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
margin: -1px -1px 0 -1px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 优化el-popover内容区域 */
|
||||
.custom-sensitive-popover .el-popover__content {
|
||||
padding: 0;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* 优化日历单元格样式 */
|
||||
.dayonChage {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.dayonChage:hover {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.dayonChage.day {
|
||||
background-color: #409eff;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dayonChage.special {
|
||||
// background-color: #fef0f0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dayonChage.special.day {
|
||||
background-color: #e6a23c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 修复日历单元格高度 */
|
||||
::v-deep .el-calendar-day {
|
||||
height: 35px !important;
|
||||
padding: 5px !important;
|
||||
text-align: center !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
::v-deep .el-calendar-table:not(.is-range) td.prev,
|
||||
::v-deep .el-calendar-table:not(.is-range) td.next {
|
||||
color: #646464;
|
||||
}
|
||||
|
||||
.day {
|
||||
background-color: rgb(76, 134, 243);
|
||||
color: #35ff02;
|
||||
}
|
||||
|
||||
.special {
|
||||
background-color: rgba(253, 112, 112, 0.856);
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
@ -1,10 +1,23 @@
|
||||
<template>
|
||||
<div class="comom-title">
|
||||
<span class="title">线索研判盯办统计</span>
|
||||
</div>
|
||||
<el-popover placement="right" :width="430">
|
||||
<template #reference>
|
||||
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
|
||||
</template>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="datetimerange"
|
||||
:shortcuts="shortcuts"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
/>
|
||||
</el-popover>
|
||||
</div>
|
||||
<ul class="comom-cnt xsBox flex flex-warp just-between align-center">
|
||||
<li class="xs-item" v-for="(item, idx) in contentItem" :key="idx">
|
||||
{{ item.label }}:{{ item.value }}条
|
||||
{{ item.label }}:{{ item.value }}条
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
@ -12,29 +25,61 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
const contentItem = ref([
|
||||
{label:'线索总数',value:'892'},
|
||||
{label:'下发总数',value:'892'},
|
||||
{label:'已处置总数',value:'892'},
|
||||
{label:'反馈总数',value:'892'},
|
||||
{label:'未反馈总数',value:'892'},
|
||||
{label:'未处置总数',value:'892'},
|
||||
{ label: '线索总数', value: '82' },
|
||||
{ label: '下发总数', value: '82' },
|
||||
{ label: '已处置总数', value: '80' },
|
||||
{ label: '反馈总数', value: '50' },
|
||||
{ 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]
|
||||
},
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/css/homeScreen.scss";
|
||||
.xsBox{
|
||||
background: url("~@/assets/images/bg_12.png") no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
.xs-item{
|
||||
width: 31%;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
background: url("~@/assets/images/content-item.png") no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
.xsBox {
|
||||
background: url("~@/assets/images/bg_12.png") no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.xs-item {
|
||||
width: 31%;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
background: url("~@/assets/images/content-item.png") no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,14 +1,24 @@
|
||||
<template>
|
||||
<div class="comom-title">
|
||||
<span class="title">布控预警</span>
|
||||
<div class="title">预警列表</div>
|
||||
<div class="expand-btn" @click="changeTab('deployControl')">
|
||||
<el-icon size="20">
|
||||
<ArrowDownBold v-if="isExpanded" />
|
||||
<ArrowUpBold v-else />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comom-cnt zdryBox">
|
||||
<div style="height:33px;">
|
||||
<div class=" zdryBox" v-show="isExpanded">
|
||||
<div>
|
||||
<CheckBox :data="checkDatas" @changeData="changeDatas"></CheckBox>
|
||||
</div>
|
||||
<div v-if="typeS">
|
||||
<CheckBox :data="checkData" @changeData="changeData"></CheckBox>
|
||||
</div>
|
||||
<ul class="ryBox" ref="scrollTableRef" @mouseenter="stopAutoScroll" @mouseleave="startAutoScroll" v-loading="loading" v-infinite-scroll="loadList" >
|
||||
<ul class="ryBox" ref="scrollTableRef" @mouseenter="stopAutoScroll" @mouseleave="startAutoScroll"
|
||||
v-loading="loading" v-infinite-scroll="loadList">
|
||||
<li v-for="item in personList" :key="item.id" @click="chooseItem(item)">
|
||||
<DeployControlItem :item="item" :dict="{D_BZ_HPZL}"/>
|
||||
<DeployControlItem :item="item" :dict="{ D_BZ_HPZL }" />
|
||||
</li>
|
||||
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
|
||||
</ul>
|
||||
@ -21,172 +31,267 @@ import { qcckPost } from "@/api/qcckApi.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 { 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 { D_BZ_HPZL } = proxy.$dict('D_BZ_HPZL')
|
||||
const checkData = reactive({
|
||||
list: ["一级", "二级", "三级", "四级"],
|
||||
hasChoose: ["一级", "二级", "三级", "四级"]
|
||||
});
|
||||
const checkDatas = reactive({
|
||||
list: ["布控", "行为", "身份", "组合"],
|
||||
hasChoose: ["布控", "行为", "身份", "组合"]
|
||||
});
|
||||
const total = ref(0);
|
||||
const yjJb = ref('10,20,30,40');
|
||||
const pageNum = ref(1);
|
||||
const loading = ref(false); // 加载中
|
||||
const personList = ref([]);
|
||||
|
||||
const scrollTableRef = ref(null) // 滚动元素区域
|
||||
let isAutoScrolling = true // 是否自动滚动
|
||||
const intervalId = ref(null) //定时器
|
||||
|
||||
onMounted(()=>{
|
||||
getList()
|
||||
autoScroll()
|
||||
})
|
||||
onUnmounted(() => {
|
||||
if (intervalId.value) clearInterval(intervalId.value)// 清理定时器
|
||||
stopAutoScroll()
|
||||
})
|
||||
// 自动滚动
|
||||
const autoScroll = () => {
|
||||
if(personList.value.length==0){return}
|
||||
intervalId.value = setInterval(() => {
|
||||
if (!isAutoScrolling) return
|
||||
const scrollTableEl = scrollTableRef.value
|
||||
scrollTableEl.scrollTop += 1 // 垂直滚动距离
|
||||
let scrollTop = scrollTableEl.scrollTop;
|
||||
let scrollHeight = scrollTableEl.scrollHeight;
|
||||
let offsetHeight = Math.ceil(scrollTableEl.getBoundingClientRect().height);
|
||||
let currentHeight = scrollTop + offsetHeight;
|
||||
if (currentHeight >= scrollHeight) { // 到底部
|
||||
if(personList.value.length == total.value){
|
||||
scrollTableEl.scrollTop = 0;
|
||||
}else{
|
||||
pageNum.value++;
|
||||
getList('load')
|
||||
}
|
||||
const scrollTableRef = ref(null);
|
||||
const isAutoScrolling = ref(false);
|
||||
let scrollTimer = null;
|
||||
onMounted(() => {
|
||||
getList();
|
||||
// 数据加载完成后启动自动滚动
|
||||
setTimeout(() => {
|
||||
if (personList.value.length > 0) {
|
||||
startAutoScroll();
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
// 停止滚动
|
||||
const stopAutoScroll = () => {
|
||||
isAutoScrolling = false
|
||||
}
|
||||
|
||||
// 开始滚动
|
||||
const startAutoScroll = () => {
|
||||
isAutoScrolling = true
|
||||
autoScroll()
|
||||
}
|
||||
|
||||
|
||||
}, 1000);
|
||||
})
|
||||
// 复选框切换
|
||||
function changeData(val){
|
||||
function changeData(val) {
|
||||
pageNum.value = 1;
|
||||
personList.value = [];
|
||||
checkData.hasChoose = val;
|
||||
let ids = [];
|
||||
val.forEach(it => {
|
||||
if(it == '一级') ids.push(10);
|
||||
if(it == '二级') ids.push(20);
|
||||
if(it == '三级') ids.push(30);
|
||||
if(it == '四级') ids.push(40);
|
||||
if (it == '一级') ids.push(10);
|
||||
if (it == '二级') ids.push(20);
|
||||
if (it == '三级') ids.push(30);
|
||||
if (it == '四级') ids.push(40);
|
||||
});
|
||||
yjJb.value = ids.join(',')
|
||||
if(val.length == 0) personList.value = [];
|
||||
if (val.length == 0) personList.value = [];
|
||||
else getList();
|
||||
}
|
||||
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
|
||||
} else {
|
||||
typeS.value=false
|
||||
}
|
||||
val.forEach(it => {
|
||||
if (it == '布控') {
|
||||
ids.push(10)
|
||||
typeS.value=true
|
||||
};
|
||||
if (it == '行为') ids.push(20);
|
||||
if (it == '身份') ids.push(30);
|
||||
if (it == '组合') ids.push(40);
|
||||
});
|
||||
yjJb.value = ids.join(',')
|
||||
if (val.length == 0) personList.value = [];
|
||||
else getList();
|
||||
}
|
||||
const isExpanded = ref(true); // 控制展开/收缩状态
|
||||
|
||||
const changeTab = () => {
|
||||
// 切换展开/收缩状态
|
||||
isExpanded.value = !isExpanded.value;
|
||||
|
||||
// 如果是收缩状态,停止自动滚动
|
||||
if (!isExpanded.value) {
|
||||
stopAutoScroll();
|
||||
} else if (personList.value.length > 0) {
|
||||
// 如果是展开状态并且有数据,启动自动滚动
|
||||
startAutoScroll();
|
||||
}
|
||||
}
|
||||
// 自动滚动函数
|
||||
const autoScroll = () => {
|
||||
if (!scrollTableRef.value || !isAutoScrolling.value) return;
|
||||
const container = scrollTableRef.value;
|
||||
const speed = 1; // 滚动速度
|
||||
// 滚动容器
|
||||
container.scrollTop += speed;
|
||||
// 判断是否滚动到底部,如果是则回到顶部重新开始
|
||||
if (container.scrollTop >= container.scrollHeight - container.clientHeight - 5) {
|
||||
container.scrollTop = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// 开始自动滚动
|
||||
const startAutoScroll = () => {
|
||||
if (isAutoScrolling.value || !scrollTableRef.value) return;
|
||||
isAutoScrolling.value = true;
|
||||
// 清除可能存在的定时器
|
||||
if (scrollTimer) {
|
||||
clearInterval(scrollTimer);
|
||||
}
|
||||
// 设置新的定时器,控制滚动速度
|
||||
scrollTimer = setInterval(autoScroll, 30);
|
||||
};
|
||||
|
||||
// 停止自动滚动
|
||||
const stopAutoScroll = () => {
|
||||
isAutoScrolling.value = false;
|
||||
if (scrollTimer) {
|
||||
clearInterval(scrollTimer);
|
||||
scrollTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
// 组件卸载时清理定时器
|
||||
stopAutoScroll();
|
||||
});
|
||||
|
||||
// 触底加载
|
||||
const loadList = () =>{
|
||||
if( personList.value.length == total.value) return;
|
||||
const loadList = () => {
|
||||
if (personList.value.length == total.value) return;
|
||||
pageNum.value++;
|
||||
getList()
|
||||
}
|
||||
|
||||
const getList = (type) =>{
|
||||
let data = { pageSize:10, pageNum:pageNum.value,yjJb:yjJb.value ,bkyj:1};
|
||||
const getList = (type) => {
|
||||
let data = { pageSize: 10, pageNum: pageNum.value, yjJb: yjJb.value, bkyj: 1 };
|
||||
loading.value = !type ? true : false;
|
||||
qcckPost(data,'/mosty-gsxt/tbYjxx/getPageList').then(res=>{
|
||||
qcckPost(data, '/mosty-gsxt/tbYjxx/getPageList').then(res => {
|
||||
loading.value = false;
|
||||
let arr = res.records || [];
|
||||
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
|
||||
total.value = res.total;
|
||||
}).catch(()=>{
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
const 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});
|
||||
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});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-loading-mask{
|
||||
background: rgba(0,0,0,0.5);
|
||||
.el-loading-mask {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/css/homeScreen.scss";
|
||||
.zdryBox{
|
||||
|
||||
.zdryBox {
|
||||
background: #052249;
|
||||
height: 100%;
|
||||
.ryBox{
|
||||
height: calc(100% - 33px);
|
||||
height: 560px;
|
||||
|
||||
.ryBox {
|
||||
height: calc(100% - 80px);
|
||||
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__label {
|
||||
color: #fff;
|
||||
}
|
||||
::v-deep .el-checkbox__input.is-checked+.el-checkbox__label{
|
||||
color:#00FFFF;
|
||||
|
||||
::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__inner {
|
||||
background: rgba(0, 144, 255, 0.2);
|
||||
border: 1px solid #0072FF;
|
||||
}
|
||||
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner{
|
||||
|
||||
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
|
||||
background-color: #00FFFF;
|
||||
border-color:#00FFFF;
|
||||
border-color: #00FFFF;
|
||||
}
|
||||
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner{
|
||||
|
||||
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
|
||||
background-color: #00FFFF;
|
||||
border-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__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{
|
||||
|
||||
::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>
|
||||
|
||||
144
src/views/home/model/experience copy.vue
Normal file
144
src/views/home/model/experience copy.vue
Normal file
@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<div class="comom-title">
|
||||
<span class="title">经验分享</span>
|
||||
</div>
|
||||
<div class="comom-cnt zdryBox">
|
||||
<!-- <ul class="ryBox" v-loading="loading" v-infinite-scroll="loadList" style="overflow: auto">
|
||||
<li v-for="item in personList" :key="item.id" >
|
||||
<Assessment :item="item" :dict="{D_GS_ZDQT_LB,D_BZ_TYJB}" :lx="3"/>
|
||||
</li>
|
||||
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
|
||||
</ul> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import { qcckPost } from "@/api/qcckApi.js";
|
||||
import Assessment from "@/views/home/components/assessmentItem.vue";
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import CheckBox from "@/components/checkBox/index.vue";
|
||||
import { ref ,reactive, onMounted,getCurrentInstance} from 'vue';
|
||||
const { proxy } = getCurrentInstance();
|
||||
const {D_GS_ZDQT_LB,D_BZ_TYJB} =proxy.$dict('D_GS_ZDQT_LB','D_BZ_TYJB')
|
||||
const checkData = reactive({
|
||||
list: ["人员", "车辆"],
|
||||
hasChoose: ["人员", "车辆"],
|
||||
});
|
||||
const total = ref(0);
|
||||
const yjJb = ref('10,20,30,40');
|
||||
const pageNum = ref(1);
|
||||
const loading = ref(false); // 加载中
|
||||
const personList = ref([]);
|
||||
onMounted(()=>{
|
||||
getList()
|
||||
})
|
||||
// 复选框切换
|
||||
function changeData(val){
|
||||
pageNum.value = 1;
|
||||
personList.value = [];
|
||||
checkData.hasChoose = val;
|
||||
let ids = [];
|
||||
val.forEach(it => {
|
||||
if(it == '人员') ids.push(1);
|
||||
if(it == '车辆') ids.push(2);
|
||||
});
|
||||
yjJb.value = ids.join(',')
|
||||
if(val.length == 0) personList.value = [];
|
||||
else getList();
|
||||
}
|
||||
|
||||
// 触底加载
|
||||
const loadList = () =>{
|
||||
if( personList.value.length == total.value) return;
|
||||
pageNum.value++;
|
||||
getList()
|
||||
}
|
||||
|
||||
const getList = () =>{
|
||||
let data = { pageSize:10, pageCurrent:pageNum.value };
|
||||
loading.value = true;
|
||||
qcckPost(data,'/mosty-gsxt/gsxt/jyfx/selectPage').then(res=>{
|
||||
loading.value = false;
|
||||
let arr = res.records || [];
|
||||
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
|
||||
total.value = res.total;
|
||||
}).catch(()=>{
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
const 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});
|
||||
}
|
||||
</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;
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -1,144 +1,192 @@
|
||||
<template>
|
||||
<div class="comom-title">
|
||||
<span class="title">经验分享</span>
|
||||
<div class="comom-title" @click="chooseForumPost">
|
||||
<span class="title">情报论坛</span>
|
||||
</div>
|
||||
<div class="comom-cnt zdryBox">
|
||||
<ul class="ryBox" v-loading="loading" v-infinite-scroll="loadList" style="overflow: auto">
|
||||
<li v-for="item in personList" :key="item.id" >
|
||||
<Assessment :item="item" :dict="{D_GS_ZDQT_LB,D_BZ_TYJB}" :lx="3"/>
|
||||
</li>
|
||||
<MOSTY.Empty :show="!loading && personList.length <= 0" :imgSize="100"></MOSTY.Empty>
|
||||
</ul>
|
||||
<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 emitter from "@/utils/eventBus.js";
|
||||
import { qcckPost } from "@/api/qcckApi.js";
|
||||
import Assessment from "@/views/home/components/assessmentItem.vue";
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import CheckBox from "@/components/checkBox/index.vue";
|
||||
import { ref ,reactive, onMounted,getCurrentInstance} from 'vue';
|
||||
const { proxy } = getCurrentInstance();
|
||||
const {D_GS_ZDQT_LB,D_BZ_TYJB} =proxy.$dict('D_GS_ZDQT_LB','D_BZ_TYJB')
|
||||
const checkData = reactive({
|
||||
list: ["人员", "车辆"],
|
||||
hasChoose: ["人员", "车辆"],
|
||||
});
|
||||
const total = ref(0);
|
||||
const yjJb = ref('10,20,30,40');
|
||||
const pageNum = ref(1);
|
||||
const loading = ref(false); // 加载中
|
||||
import { tbGsxtXxltSelectPage } from '@/api/tbGsxtXxltHf'
|
||||
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
||||
import {useRouter} from 'vue-router'
|
||||
const router = useRouter()
|
||||
|
||||
// 数据相关
|
||||
const personList = ref([]);
|
||||
onMounted(()=>{
|
||||
getList()
|
||||
})
|
||||
// 复选框切换
|
||||
function changeData(val){
|
||||
pageNum.value = 1;
|
||||
personList.value = [];
|
||||
checkData.hasChoose = val;
|
||||
let ids = [];
|
||||
val.forEach(it => {
|
||||
if(it == '人员') ids.push(1);
|
||||
if(it == '车辆') ids.push(2);
|
||||
});
|
||||
yjJb.value = ids.join(',')
|
||||
if(val.length == 0) personList.value = [];
|
||||
else getList();
|
||||
}
|
||||
const displayList = ref([]); // 用于显示的数据列表
|
||||
const loading = ref(false);
|
||||
|
||||
// 触底加载
|
||||
const loadList = () =>{
|
||||
if( personList.value.length == total.value) return;
|
||||
pageNum.value++;
|
||||
getList()
|
||||
}
|
||||
// 轮播相关
|
||||
const carouselList = ref(null);
|
||||
const scrollTimer = ref(null);
|
||||
const scrollSpeed = ref(3000); // 滚动间隔时间(ms)
|
||||
const itemHeight = ref(106); // 每个item的高度(px)
|
||||
const currentIndex = ref(0);
|
||||
|
||||
const getList = () =>{
|
||||
let data = { pageSize:10, pageCurrent:pageNum.value };
|
||||
// 获取数据
|
||||
const getList = () => {
|
||||
loading.value = true;
|
||||
qcckPost(data,'/mosty-gsxt/gsxt/jyfx/selectPage').then(res=>{
|
||||
tbGsxtXxltSelectPage({ pageSize: 10, pageCurrent: 1 }).then(res => {
|
||||
loading.value = false;
|
||||
let arr = res.records || [];
|
||||
personList.value = pageNum.value == 1 ? arr : personList.value.concat(arr);
|
||||
total.value = res.total;
|
||||
}).catch(()=>{
|
||||
personList.value = res.records || [];
|
||||
// 复制一份数据到displayList,实现无缝滚动效果
|
||||
displayList.value = [...personList.value, ...personList.value];
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
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});
|
||||
}
|
||||
// 开始轮播
|
||||
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)`;
|
||||
|
||||
// 当滚动到复制的数据部分时,重置位置实现无缝滚动
|
||||
if (currentIndex.value >= personList.value.length) {
|
||||
setTimeout(() => {
|
||||
currentIndex.value = 0;
|
||||
carouselList.value.style.transition = 'none';
|
||||
carouselList.value.style.transform = 'translateY(0)';
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
// 点击项
|
||||
const chooseItem = (item) => {
|
||||
pauseCarousel(); // 点击时暂停轮播
|
||||
router.push({
|
||||
path: '/forumPost',
|
||||
query: { id: item.id }
|
||||
})
|
||||
};
|
||||
|
||||
// 添加跳转
|
||||
const chooseForumPost = () => {
|
||||
pauseCarousel(); // 点击时暂停轮播
|
||||
router.push({ path: '/forumPost' })
|
||||
};
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
getList();
|
||||
// 数据加载后开始轮播
|
||||
setTimeout(() => {
|
||||
startCarousel();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// 组件卸载前清除定时器
|
||||
onBeforeUnmount(() => {
|
||||
pauseCarousel();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-loading-mask{
|
||||
background: rgba(0,0,0,0.5);
|
||||
.el-loading-mask {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/css/homeScreen.scss";
|
||||
.zdryBox{
|
||||
background: #052249;
|
||||
|
||||
.zdryBox {
|
||||
height: 100%;
|
||||
.ryBox{
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.carousel-container {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ryBox {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
transition: background-color 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
&: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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::-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;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
56
src/views/home/model/iframe.vue
Normal file
56
src/views/home/model/iframe.vue
Normal file
@ -0,0 +1,56 @@
|
||||
<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>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}, title: {
|
||||
type: String,
|
||||
default: '提示'
|
||||
}, showFooter: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}, src: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue', 'submit', 'close'])
|
||||
const close = () => {
|
||||
emit('update:modelValue', false)
|
||||
emit('close')
|
||||
}
|
||||
const submit = () => {
|
||||
emit('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;
|
||||
}
|
||||
</style>
|
||||
@ -1,7 +1,20 @@
|
||||
<template>
|
||||
<div class="comom-title">
|
||||
<span class="title">情报来源类型</span>
|
||||
</div>
|
||||
<el-popover placement="right" :width="430">
|
||||
<template #reference>
|
||||
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
|
||||
</template>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="datetimerange"
|
||||
:shortcuts="shortcuts"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
/>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="comom-cnt">
|
||||
<BarHatEcharts echartsId="qbltBox" :autoTooltip="true" :data="list"></BarHatEcharts>
|
||||
</div>
|
||||
@ -10,7 +23,7 @@
|
||||
<script setup>
|
||||
import { qcckPost } from "@/api/qcckApi.js";
|
||||
import BarHatEcharts from "@/views/home/echarts/barHatEcharts.vue";
|
||||
import { onMounted, reactive } from "vue";
|
||||
import { onMounted, reactive ,ref} from "vue";
|
||||
const list = reactive({
|
||||
xDate: ['110警情','人力情报','系统采集','民警处置单'],
|
||||
list:[
|
||||
@ -29,7 +42,36 @@ const getCount = () =>{
|
||||
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]
|
||||
},
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
|
||||
@ -40,4 +82,4 @@ const getCount = () =>{
|
||||
background: rgba(0,29,75,0.6);
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,42 +1,87 @@
|
||||
<template>
|
||||
<div class="comom-title">
|
||||
<span class="title">情报上报数量统计</span>
|
||||
</div>
|
||||
<el-popover placement="right" :width="430">
|
||||
<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="comom-cnt qxsbBox">
|
||||
<LineEcharts echartsId="qbsbEcharts" :data="dataList"></LineEcharts>
|
||||
<LineEcharts echartsId="qbsbEcharts" :data="dataList"></LineEcharts>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { qcckPost } from "@/api/qcckApi.js";
|
||||
import LineEcharts from "../echarts/moreLineEcharts.vue";
|
||||
import { reactive, onMounted } from 'vue';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
|
||||
const dataList = reactive({
|
||||
xData:['巴宜区','工布江达县','米林县','墨脱县','波密县','察隅县','朗县'],
|
||||
color:['#0386FB','#00FFFF'],
|
||||
list:[
|
||||
{label:'总数',val:[0,0,0,0,0,0,0]},
|
||||
{label:'已处置',val:[0,0,0,0,0,0,0]},
|
||||
xData: ['巴宜区', '工布江达县', '米林县', '墨脱县', '波密县', '察隅县', '朗县'],
|
||||
color: ['#0386FB', '#00FFFF'],
|
||||
list: [
|
||||
{ label: '总数', val: [0, 0, 0, 0, 0, 0, 0] },
|
||||
{ label: '已处置', val: [0, 0, 0, 0, 0, 0, 0] },
|
||||
]
|
||||
});
|
||||
onMounted(() => {
|
||||
getCount()
|
||||
});
|
||||
|
||||
const getCount = () =>{
|
||||
qcckPost({},'/mosty-gsxt/qbcj/getXscjTjForQx').then(res=>{
|
||||
dataList.xDate = res ? res.ycz.map(v=> v.org_name):[];
|
||||
dataList.list[0].val = res ? res.zs.map(v=>v.count):[];
|
||||
dataList.list[1].val = res ? res.ycz.map(v=>v.count):[];
|
||||
const listQuery = ref()
|
||||
const getCount = () => {
|
||||
const promes = {
|
||||
startTime: listQuery.value ? listQuery.value[0] : "",
|
||||
endTime: listQuery.value ? listQuery.value[1] : ""
|
||||
}
|
||||
qcckPost(promes, '/mosty-gsxt/qbcj/getXscjTjForQx').then(res => {
|
||||
dataList.xDate = res ? res.ycz.map(v => v.org_name) : [];
|
||||
dataList.list[0].val = res ? res.zs.map(v => v.count) : [];
|
||||
dataList.list[1].val = res ? res.ycz.map(v => v.count) : [];
|
||||
})
|
||||
}
|
||||
const changeTime = () => {
|
||||
console.log(listQuery.value);
|
||||
|
||||
getCount()
|
||||
}
|
||||
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";
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
87
src/views/home/model/textType.vue
Normal file
87
src/views/home/model/textType.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="comom-title">
|
||||
<span class="title">情报文本类型</span>
|
||||
<el-popover placement="right" :width="430">
|
||||
<template #reference>
|
||||
<div class="title" style="position: relative;z-index: 10000;height: 40px;width: 40px;"></div>
|
||||
</template>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="datetimerange"
|
||||
:shortcuts="shortcuts"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
/>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="comom-cnt" >
|
||||
<BarHatEcharts echartsId="qbltBoxs" :autoTooltip="true" :data="list" ></BarHatEcharts>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<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({
|
||||
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' },
|
||||
],
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getCount()
|
||||
});
|
||||
|
||||
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 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>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/css/homeScreen.scss";
|
||||
.qbltBox {
|
||||
height: 100%;
|
||||
background: rgba(0,29,75,0.6);
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
</style>
|
||||
@ -4,7 +4,7 @@
|
||||
<div class="mr10"><img :src="item.icon" alt=""></div>
|
||||
<div class="vountItem">
|
||||
<div style="color:#ffffff" class="f16 lh20">{{ item.label }}</div>
|
||||
<div class="mt4 f12" style="color: #ffffff;">{{ item.value }}</div>
|
||||
<div class="mt4 f12" style="color: #ffffff;font-size: 24px;">{{ item.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -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:"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')},
|
||||
]);
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@ -3,14 +3,13 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter } from "vue-router";
|
||||
import {
|
||||
getCookie
|
||||
} from "@/utils/cookie";
|
||||
import {
|
||||
setItem
|
||||
} from "@/utils/storage";
|
||||
import { getSessionForSfzh, idCardNoLogin } from "@/api/user-manage";
|
||||
import { getSessionForSfzh, idCardNoLogin, idCardNoLoginPcs, getSessionForSfzhPcs } from "@/api/user-manage";
|
||||
import {
|
||||
setTimeStamp
|
||||
} from "@/utils/auth";
|
||||
@ -18,7 +17,14 @@ const loginDialog = ref(false);
|
||||
const deptList = ref([]);
|
||||
const store = useStore();
|
||||
function redirectAuth() {
|
||||
handleLogin();
|
||||
const url = window.location.href
|
||||
const urlObj = new URL(url);
|
||||
const hostname = urlObj.hostname.split('.')[0]
|
||||
if (hostname == 'pcs'||hostname == 'zhpcs') {
|
||||
pcsHandleLogin()
|
||||
} else {
|
||||
handleLogin();
|
||||
}
|
||||
}
|
||||
|
||||
const handleLogin = (e) => {
|
||||
@ -75,6 +81,60 @@ const handleLogin = (e) => {
|
||||
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";
|
||||
});
|
||||
} else {
|
||||
console.error("没有找到clientKey cookie");
|
||||
// 没有cookie时重定向到登录页面
|
||||
window.location.hash = "/login";
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
redirectAuth();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user