lcw
This commit is contained in:
@ -0,0 +1,389 @@
|
||||
<template>
|
||||
<div class="dialog" v-if="dialogForm">
|
||||
<div class="head_box">
|
||||
<span class="title">{{ titleData }}{{ title }}</span>
|
||||
<div>
|
||||
<el-button @click="submitForm()" type="primary" v-if="!disabled">保存</el-button>
|
||||
<el-button @click="close">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-container">
|
||||
<div class="form-content" v-loading="loading">
|
||||
<!-- <div class="form_cnt"> -->
|
||||
<FormMessage :disabled="disabled" v-model="listQuery" :formList="formData" ref="elform" :rules="rules">
|
||||
</FormMessage>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
<div class="ml50 mr50 timeline-container">
|
||||
<div class="timeline-title">信息流程展示</div>
|
||||
<el-timeline class="timeline-full-width">
|
||||
<el-timeline-item :timestamp="item.czsj" placement="top" v-for="(item, index) in lcList" :key="index">
|
||||
<el-card class="process-card">
|
||||
<div class="process-info">
|
||||
<div class="info-label">处置人:</div>
|
||||
<div class="info-value">{{ item.czrxm || '未记录' }}</div>
|
||||
</div>
|
||||
<div class="process-info">
|
||||
<div class="info-label">处置结果:</div>
|
||||
<div class="info-value">
|
||||
<DictTag :tag="false" :value="item.czzt" :options="dict.D_BZ_QBCZZT" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
<MOSTY.Empty :show="lcList.length == 0" :imgSize="100"></MOSTY.Empty>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <pursueContent v-model="pursueShow" :dataList="dataList" :updeteBool="true" @getqbcjCzztList="getqbcjCzztList" /> -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import FormMessage from "@/components/aboutTable/FormMessage.vue";
|
||||
import { qbcjAdd, qbcjUpdate, qbcjSelectByid } from "@/api/Intelligence.js";
|
||||
// import pursueContent from "@/views/backOfficeSystem/HumanIntelligence/components/pursueContent.vue";
|
||||
import { ref, defineExpose, onMounted, defineEmits, watch, getCurrentInstance } from "vue";
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { qbcjCzztList, qbcjCzztDelete } from '@/api/qbcj'
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import { qbcjSelectCzlcList } from "@/api/Intelligence.js";
|
||||
const { proxy } = getCurrentInstance()
|
||||
const emit = defineEmits(["getList"]);
|
||||
const props = defineProps({
|
||||
dict: Object,
|
||||
titleData: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
showBc: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
const loading = ref(false)
|
||||
const dialogForm = ref(false); //弹窗
|
||||
const formData = ref();
|
||||
const rules = ref({
|
||||
qbmc: [{ required: true, message: "请输入情报标题", trigger: "blur" }],
|
||||
qbnr: [{ required: true, message: "请输入情报内容", trigger: "blur" }],
|
||||
})
|
||||
|
||||
watch(() => dialogForm.value, (val) => {
|
||||
if (val) {
|
||||
formData.value = [
|
||||
{ label: "情报标题", prop: "qbmc", type: "input", width: '45%' },
|
||||
{ label: "情报等级", prop: "qbmj", type: "select", options: props.dict.D_BZ_BMJB, width: '45%' },
|
||||
{ label: "情报内容", prop: "qbnr", type: "textarea", width: '100%', rows: 100 },
|
||||
{ label: "附件上传", prop: "fjdz", type: "upload", width: '100%', isImg: false },
|
||||
]
|
||||
}
|
||||
}, { deep: true })
|
||||
const fjdz = ref()
|
||||
const listQuery = ref({}); //表单
|
||||
const elform = ref();
|
||||
onMounted(() => {
|
||||
})
|
||||
const addForm = ref()
|
||||
const msgeDat = ref()
|
||||
const title = ref("")
|
||||
const showPj = ref(false)
|
||||
const disabled = ref(false)
|
||||
// 初始化数据
|
||||
const init = (type, row) => {
|
||||
title.value = type == "add" ? "新增" : type == "info" ? "详情" : "编辑"
|
||||
disabled.value = type == 'info' ? true : false
|
||||
fjdz.value = []
|
||||
dialogForm.value = true;
|
||||
if (type == 'info' || type == 'edit') {
|
||||
showPj.value = true
|
||||
msgeDat.value = row
|
||||
getqbcjPldb(row.id)
|
||||
// 初始化表单数据,并根据详情页设置禁用状态
|
||||
if (row) getDataById(row.id);
|
||||
getqbcjCzztList()
|
||||
} else {
|
||||
showPj.value = false
|
||||
}
|
||||
};
|
||||
// 根据id查询详情
|
||||
const getDataById = (id) => {
|
||||
qbcjSelectByid({ id }).then((res) => {
|
||||
fjdz.value = res.ossList || [];
|
||||
listQuery.value = res;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 新增
|
||||
const submitForm = () => {
|
||||
loading.value = true
|
||||
elform.value.submit(valid => {
|
||||
if (valid) {
|
||||
const promes = {
|
||||
...listQuery.value,
|
||||
cjLx: 0
|
||||
}
|
||||
if (title.value == '新增') {
|
||||
qbcjAdd(promes).then((res) => {
|
||||
emit("getList")
|
||||
close()
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else if (title.value == '编辑') {
|
||||
qbcjUpdate(promes).then((res) => {
|
||||
emit("getList")
|
||||
close()
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
// 关闭
|
||||
const close = () => {
|
||||
if (route.query.id) {
|
||||
const query = { ...route.query };
|
||||
delete query.id;
|
||||
router.replace({ query });
|
||||
}
|
||||
fjdz.value = []
|
||||
listQuery.value = {};
|
||||
dialogForm.value = false;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const qbBcList = ref()
|
||||
// const getqbcjCzztList = () => {
|
||||
// qbcjCzztList({ qbid: msgeDat.value.id }).then(res => {
|
||||
// console.log(res);
|
||||
// qbBcList.value = res || []
|
||||
// })
|
||||
// }
|
||||
|
||||
// const pursueShow = ref(false)
|
||||
// const dataList = ref()
|
||||
|
||||
const lcList = ref([])
|
||||
const getqbcjPldb = (id) => {
|
||||
qbcjSelectCzlcList({ qbid: id }).then(res => {
|
||||
lcList.value = res || []
|
||||
})
|
||||
.catch(() => {
|
||||
})
|
||||
}
|
||||
defineExpose({ init });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/assets/css/layout.scss";
|
||||
@import "~@/assets/css/element-plus.scss";
|
||||
|
||||
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
|
||||
color: #0072ff;
|
||||
background: rgba(0, 114, 255, 0.3);
|
||||
}
|
||||
|
||||
.boxlist {
|
||||
width: 99%;
|
||||
height: 225px;
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
::v-deep .avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::v-deep .el-upload-list {
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::v-deep .el-upload-list__item-name .el-icon {
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.form_cnt {
|
||||
// width: 75%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.person {
|
||||
padding-left: 20px;
|
||||
width: 25%;
|
||||
// height: 100vh;
|
||||
}
|
||||
|
||||
/* 补充信息样式 */
|
||||
.supplement-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin: 16px 0 10px 0;
|
||||
padding-left: 5px;
|
||||
border-left: 3px solid #24b6dd;
|
||||
}
|
||||
|
||||
.supplement-list {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.supplement-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 8px;
|
||||
margin-right: 10px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.supplement-item:hover {
|
||||
background-color: #ecf5ff;
|
||||
border-color: #c6e2ff;
|
||||
}
|
||||
|
||||
.supplement-content {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.supplement-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
color: #24b6dd;
|
||||
}
|
||||
|
||||
.edit-icon:hover {
|
||||
color: #409eff;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.delete-icon:hover {
|
||||
color: #f78989;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* 时间线标题样式 */
|
||||
.timeline-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #f5f7fa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
/* 时间线样式优化 */
|
||||
.el-timeline {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* 处置流程卡片样式 */
|
||||
.process-card {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
margin-bottom: 16px;
|
||||
border-left: 3px solid #409EFF;
|
||||
}
|
||||
|
||||
.process-card:hover {
|
||||
box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* 卡片内部信息样式 */
|
||||
.process-info {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.process-info:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #409EFF;
|
||||
margin-right: 8px;
|
||||
min-width: 65px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* 时间戳样式 */
|
||||
.el-timeline-item__timestamp {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 时间线节点样式 */
|
||||
.el-timeline-item__node {
|
||||
background-color: #409EFF;
|
||||
}
|
||||
|
||||
::v-deep .el-textarea__inner {
|
||||
height: 50vh !important;
|
||||
}
|
||||
|
||||
/* 容器类样式 */
|
||||
.form-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
display: flex;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.timeline-container {
|
||||
border: 1px solid #ebeef5;
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
/* 时间线宽度 */
|
||||
.timeline-full-width {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -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>
|
||||
@ -0,0 +1,435 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="titleBox">
|
||||
<PageTitle :title="titleData">
|
||||
<el-button type="primary" @click="addEdit('add')">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">新增</span>
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dologCancel()">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">导出</span>
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">转线索</span>
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">转合成</span>
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="ids.length === 0" @click="batchMark(ids)" v-if="qxkz.deptLevel == '01'">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">打标</span>
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="ids.length === 0" @click="handleSumbit(ids)" v-if="qxkz.deptLevel != '01'">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">上报</span>
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="ids.length === 0" @click="delDictItem(ids)">
|
||||
<el-icon style="vertical-align: middle">
|
||||
<CirclePlus />
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle">删除</span>
|
||||
</el-button>
|
||||
<el-button type="success" @click="openSearch">
|
||||
<Search style="width: 1em; height: 1em; margin-right: 8px" />
|
||||
<span style="vertical-align: middle" v-if="!search">搜索</span>
|
||||
<span style="vertical-align: middle" v-else>关闭搜索</span>
|
||||
</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
<div ref="searchBox" v-if="search">
|
||||
<Searchs :searchArr="searchConfiger" @submit="onSearch" :key="pageData.keyCount" />
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="tabBox" :style="{ height: (pageData.tableHeight + 40) + 'px' }">
|
||||
<MyTable :tableData="pageData.tableData" :tableColumn="pageData.tableColumn" :tableHeight="pageData.tableHeight"
|
||||
:key="pageData.keyCount" :tableConfiger="pageData.tableConfiger" :controlsWidth="pageData.controlsWidth"
|
||||
@chooseData="chooseData">
|
||||
<template #qblx="{ row }">
|
||||
<DictTag :tag="false" :value="row.qblx" :options="D_GS_XS_LX" />
|
||||
</template>
|
||||
<template #cjlx="{ row }">
|
||||
<DictTag :tag="false" :value="row.cjLx" :options="D_BZ_CJLX" />
|
||||
</template>
|
||||
<template #czzt="{ row }">
|
||||
<DictTag :tag="false" :value="row.czzt" :options="D_BZ_QBCZZT" />
|
||||
</template>
|
||||
<!-- 操作 -->
|
||||
<template #controls="{ row }">
|
||||
<!-- (01 提交 02 上报 03 采纳 04 退回 05 打标签)v-if="qxkz.deptLevel == '01'" -->
|
||||
<el-link size="small" type="primary" v-if="row.czzt == '02' && qxkz.depBool" @click="cnMsg(row)">采纳</el-link>
|
||||
<el-link size="small" type="primary" v-if="row.czzt == '03' && qxkz.depBool"
|
||||
@click="opneMsg(row)">打标签</el-link>
|
||||
<el-link size="small" type="primary" @click="rollbackNewspapers(row)"
|
||||
v-if="row.czzt == '02' && row.qbjb == '00' && row.fxjsfsb != 1 && row.pcssfsb != 0 && qxkz.depBool">回退</el-link>
|
||||
<el-link size="small" type="primary" @click="checkProcess(row)">查看流程</el-link>
|
||||
<el-link size="small" type="primary" @click="appearNewspapers(row)"
|
||||
v-if="(row.czzt == '01' || row.czzt == '04') && row.qbjb == '00' && qxkz.deptLevel != '01'">上报</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转线索</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('info', row)" v-if="qxkz.depBool">转合成</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('info', row)">转会商</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('info', row)">详情</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('info', row)">肯定</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('info', row)">创建</el-link>
|
||||
<el-link size="small" type="primary" @click="addEdit('edit', row)">修改</el-link>
|
||||
<el-link size="small" type="danger" @click="delDictItem(row.id)">删除</el-link>
|
||||
</template>
|
||||
</MyTable>checkProcess
|
||||
<Pages @changeNo="changeNo" @changeSize="changeSize" :tableHeight="pageData.tableHeight" :pageConfiger="{
|
||||
...pageData.pageConfiger,
|
||||
total: pageData.total
|
||||
}"></Pages>
|
||||
</div>
|
||||
<!-- 新增 -->
|
||||
<AddForm ref="detailDiloag" @getList="getList" :titleData="titleData" :dict="{
|
||||
D_BZ_SF,
|
||||
D_GS_XS_LY,
|
||||
D_BZ_SSZT,
|
||||
D_GS_XS_LX,
|
||||
D_GS_XS_QTLX,
|
||||
D_GS_ZDQT_LB,
|
||||
D_BZ_BMJB,
|
||||
D_BZ_CLPP,
|
||||
D_BZ_CLYS,
|
||||
D_BZ_CLLX,
|
||||
D_BZ_XZQHDM
|
||||
}" />
|
||||
</div>
|
||||
<ExportFile v-model="exportFileModel" :tableColumn="tableColumn" :dict="{ D_GS_XS_LY, D_GS_XS_LX, D_GS_XS_LX }"
|
||||
:dataModel="pageData.tableData" />
|
||||
<MakeTag v-model="chooseRow" :dataList="dataList" :dict="{ D_BZ_CJLX, D_BZ_QBCZZT, D_GS_XS_LX, D_BZ_BQJB }"
|
||||
@getList="getList" />
|
||||
<CheckProcess v-model="checkProcessModel" :dataList="dataList" :dict="{ D_BZ_QBCZZT }" />
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Searchs from "@/components/aboutTable/Search.vue";
|
||||
import AddForm from "./components/addForm.vue";
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { qbcjSelectQbsbPage, qbcjDeletes, qbcjCzzt, qbcjPlsb } from "@/api/Intelligence.js";
|
||||
import { reactive, ref, onMounted, getCurrentInstance, nextTick } from "vue";
|
||||
import MakeTag from '../components/maketag.vue'
|
||||
import ExportFile from './components/exportFile.vue'
|
||||
import CheckProcess from '../components/checkProcess.vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { getItem } from '@//utils/storage.js'
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_GS_XS_LY, D_BZ_SSZT, D_BZ_SF, D_GS_XS_LX, D_BZ_BQJB,
|
||||
D_GS_XS_QTLX, D_GS_ZDQT_LB,
|
||||
D_BZ_BMJB, D_BZ_CLPP, D_BZ_CLYS, D_BZ_CLLX, D_BZ_XZQHDM, D_BZ_QBCZZT, D_BZ_CJLX } =
|
||||
proxy.$dict("D_BZ_BMJB", "D_GS_XS_LY",
|
||||
"D_BZ_SSZT", "D_BZ_SF", "D_GS_XS_LX", "D_GS_XS_QTLX",
|
||||
"D_GS_ZDQT_LB", "D_BZ_CLPP", "D_BZ_CLYS", "D_BZ_CLLX", "D_BZ_XZQHDM", "D_BZ_QBCZZT", "D_BZ_CJLX", "D_BZ_BQJB"); //获取字典数据
|
||||
const detailDiloag = ref();
|
||||
const searchBox = ref(); //搜索框
|
||||
const ids = ref([])
|
||||
const tableList = ref([]);
|
||||
const chooseData = (val) => {
|
||||
ids.value = val.map(item => {
|
||||
return item.id
|
||||
})
|
||||
tableList.value = val
|
||||
}
|
||||
|
||||
|
||||
const isShow = ref(false)
|
||||
const searchConfiger = ref([
|
||||
{ label: "情报标题", prop: 'qbmc', placeholder: "请输入情报标题", showType: "input" },
|
||||
{ label: "姓名", prop: 'xssbr', placeholder: "请输入姓名", showType: "input" },
|
||||
{ label: "录入时间", prop: 'lrkssj', placeholder: "请选择开始时间", showType: "datetimerange" },
|
||||
{ label: "情报来源", prop: 'cjLx', placeholder: "请选择情报来源", showType: "select", options: D_BZ_CJLX },
|
||||
{ label: "情报处置状态", prop: 'czzt', placeholder: "请选择处置状态", showType: "select", options: D_BZ_QBCZZT },
|
||||
{ label: "来源单位", prop: 'ssbmdm', placeholder: "请选择来源单位", showType: "department" },
|
||||
{ label: "关键字", prop: 'keyword', placeholder: "请输入关键字", showType: "input" },
|
||||
]);
|
||||
const pageData = reactive({
|
||||
tableData: [],
|
||||
keyCount: 0,
|
||||
tableConfiger: {
|
||||
rowHieght: 61,
|
||||
showSelectType: "checkBox",
|
||||
loading: false
|
||||
},
|
||||
total: 0,
|
||||
pageConfiger: {
|
||||
pageSize: 20,
|
||||
pageCurrent: 1
|
||||
},
|
||||
controlsWidth: 240,
|
||||
tableColumn: [
|
||||
{ label: "情报上报时间", prop: "sxsbsj" },
|
||||
{ label: "情报编号", prop: "xsBh" },
|
||||
// { label: "上报人姓名", prop: "xssbr" },
|
||||
{ label: "情报标题", prop: "qbmc" },
|
||||
// { label: "情报类型", prop: "qblx", showSolt: true },
|
||||
{ label: "情报来源", prop: "cjlx", showSolt: true },
|
||||
{ label: "情报上报时间", prop: "sxsbsj" },
|
||||
// { label: "指向地点", prop: "zxdz" },
|
||||
{ label: "消息状态", prop: "czzt", showSolt: true },
|
||||
// { label: "情报内容", prop: "qbnr" },
|
||||
]
|
||||
});
|
||||
const queryFrom = ref({});
|
||||
|
||||
|
||||
// 上报
|
||||
const appearNewspapers = (item) => {
|
||||
proxy.$confirm("确定要上报", "警告", { type: "warning" }).then(() => {
|
||||
qbcjCzzt({ id: item.id, czzt: '02', qbjb: '00' }).then(res => {
|
||||
proxy.$message({ type: "success", message: "上报成功" });
|
||||
getList();
|
||||
})
|
||||
|
||||
}).catch(() => { });
|
||||
}
|
||||
|
||||
|
||||
// 回退
|
||||
const rollbackNewspapers = (item) => {
|
||||
ElMessageBox.prompt('请输入回退原因', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
})
|
||||
.then(({ value }) => {
|
||||
qbcjCzzt({ id: item.id, czzt: '01', qbjb: '00', czthyy: value }).then(res => {
|
||||
proxy.$message({ type: "success", message: "回退成功" });
|
||||
getList();
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
})
|
||||
}
|
||||
|
||||
const chooseRow = ref(false)
|
||||
const dataList = ref()
|
||||
const opneMsg = (item) => {
|
||||
chooseRow.value = true
|
||||
dataList.value = [item]
|
||||
}
|
||||
const cnMsg = (item) => {
|
||||
proxy.$confirm("确定要采纳", "警告", { type: "warning" }).then(() => {
|
||||
qbcjCzzt({ id: item.id, czzt: '03', qbjb: '00' }).then(res => {
|
||||
proxy.$message({ type: "success", message: "采纳成功" });
|
||||
getList();
|
||||
})
|
||||
|
||||
}).catch(() => { });
|
||||
}
|
||||
// 打标
|
||||
const batchMark = () => {
|
||||
const listDb = tableList.value.filter(item => item.czzt != '03')
|
||||
if (listDb.length == 0) {
|
||||
chooseRow.value = true
|
||||
dataList.value = tableList.value
|
||||
} else {
|
||||
proxy.$message({
|
||||
message: '还有情报未采纳',
|
||||
type: 'warning',
|
||||
showClose: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
const handleSumbit = () => {
|
||||
const listDb = tableList.value.filter(item => item.czzt != '01' && item.czzt != '04')
|
||||
if (listDb.length == 0) {
|
||||
proxy.$confirm("确定要上报", "警告", { type: "warning" }).then(() => {
|
||||
qbcjPlsb({ ids: ids.value, qbjb: '00' }).then(res => {
|
||||
proxy.$message({ type: "success", message: "上报成功" });
|
||||
getList();
|
||||
})
|
||||
}).catch(() => { });
|
||||
} else {
|
||||
proxy.$message({
|
||||
message: '请选择正确数据',
|
||||
type: 'warning',
|
||||
showClose: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 搜索
|
||||
const onSearch = (val) => {
|
||||
const { lrkssj, zxkssj } = val
|
||||
const promes = {
|
||||
...pageData.pageConfiger,
|
||||
...val,
|
||||
lrkssj: lrkssj ? lrkssj[0] : '',
|
||||
lrjssj: lrkssj ? lrkssj[1] : '',
|
||||
zxkssj: zxkssj ? zxkssj[0] : '',
|
||||
zxjssj: zxkssj ? zxkssj[1] : '',
|
||||
}
|
||||
|
||||
queryFrom.value = { ...promes }
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList()
|
||||
}
|
||||
|
||||
const changeNo = (val) => {
|
||||
pageData.pageConfiger.pageCurrent = val;
|
||||
getList()
|
||||
}
|
||||
const changeSize = (val) => {
|
||||
pageData.pageConfiger.pageSize = val;
|
||||
getList()
|
||||
}
|
||||
|
||||
// 获取列表
|
||||
const getList = () => {
|
||||
pageData.tableConfiger.loading = true;
|
||||
let data = { ...pageData.pageConfiger, ...queryFrom.value };
|
||||
qbcjSelectQbsbPage(data).then(res => {
|
||||
pageData.tableData = res.records || [];
|
||||
pageData.total = res.total;
|
||||
pageData.tableConfiger.loading = false;
|
||||
}).catch(() => { pageData.tableConfiger.loading = false; })
|
||||
}
|
||||
// 删除
|
||||
const delDictItem = (id) => {
|
||||
proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
|
||||
qbcjDeletes({ ids: Array.isArray(id) ? id : [id] }).then((res) => {
|
||||
proxy.$message({ type: "success", message: "删除成功" });
|
||||
getList();
|
||||
}).catch(() => {
|
||||
})
|
||||
}).catch(() => { });
|
||||
}
|
||||
// 导出数据
|
||||
const tableColumn = reactive([
|
||||
{ label: "上报人姓名", prop: "xssbr" },
|
||||
{ label: "情报编号", prop: "xsBh" },
|
||||
{ label: "情报标题", prop: "qbmc" },
|
||||
{ label: "情报类型", prop: "qblx", showSolt: true, zd: 'D_GS_XS_LX' },
|
||||
{ label: "情报来源", prop: "cjLx", showSolt: true, zd: 'D_BZ_CJLX' },
|
||||
{ label: "情报上报时间", prop: "sxsbsj" },
|
||||
{ label: "指向地点", prop: "zxdz" },
|
||||
{ label: "情报内容", prop: "qbnr", showOverflowTooltip: true },
|
||||
])
|
||||
// 详情
|
||||
const addEdit = (type, row) => {
|
||||
isShow.value = true;
|
||||
setTimeout(() => {
|
||||
detailDiloag.value.init(type, row);
|
||||
}, 500)
|
||||
};
|
||||
|
||||
const route = useRoute()
|
||||
const titleData = ref()
|
||||
const qxkz = reactive({
|
||||
deptBizType: '',
|
||||
deptLevel: '',
|
||||
depBool: false
|
||||
});
|
||||
onMounted(() => {
|
||||
const { deptBizType, deptLevel } = getItem('deptId')[0]
|
||||
const Jb = deptLevel[0] == '2' ? '01' : deptLevel[0] == '3' ? '02' : '03'
|
||||
qxkz.deptBizType = deptBizType
|
||||
qxkz.deptLevel = Jb
|
||||
if (deptBizType == '23' && Jb == '01') {
|
||||
qxkz.depBool = true
|
||||
} else {
|
||||
qxkz.depBool = false
|
||||
}
|
||||
|
||||
|
||||
getRouter()
|
||||
tabHeightFn()
|
||||
if (route.query.id) {
|
||||
detailDiloag.value.init('edit', {
|
||||
id: route.query.id
|
||||
});
|
||||
return
|
||||
}
|
||||
getList()
|
||||
|
||||
|
||||
});
|
||||
const getRouter = () => {
|
||||
titleData.value = route.meta.title
|
||||
}
|
||||
const exportFileModel = ref(false)
|
||||
const dologCancel = () => {
|
||||
exportFileModel.value = true;
|
||||
}
|
||||
// 搜索栏
|
||||
const search = ref(false)
|
||||
const openSearch = () => {
|
||||
search.value = !search.value
|
||||
nextTick(() => {
|
||||
tabHeightFn()
|
||||
})
|
||||
}
|
||||
// 表格高度计算
|
||||
const tabHeightFn = () => {
|
||||
if (search.value) {
|
||||
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 250;
|
||||
} else {
|
||||
pageData.tableHeight = window.innerHeight - 250;
|
||||
}
|
||||
window.onresize = function () {
|
||||
tabHeightFn();
|
||||
};
|
||||
};
|
||||
// 流程
|
||||
const checkProcessModel = ref()
|
||||
const checkProcess = (item) => {
|
||||
checkProcessModel.value = true
|
||||
dataList.value = item
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.label-pop {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: '*';
|
||||
top: 0;
|
||||
left: -7px;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.el-loading-mask {
|
||||
background: rgba(0, 0, 0, 0.5) !important;
|
||||
}
|
||||
|
||||
:v-deep .el-dialog {
|
||||
width: 90% !important;
|
||||
}
|
||||
|
||||
.zdy-model-dialogs {
|
||||
/* background-color: rgb(50, 148, 214); */
|
||||
background: url("~@/assets/images/bg46.png") no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
padding: 8px 10px;
|
||||
box-sizing: border-box;
|
||||
pointer-events: auto !important;
|
||||
height: calc(100% - 50px);
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user