Browse Source

涉访涉诉--重复件功能

master
buaixuexideshitongxue 1 month ago
parent
commit
641103dd79
  1. 139
      src/components/data/complaintformdialog.vue
  2. 52
      src/components/data/complaintproblemInfo.vue
  3. 55
      src/components/negative/verify-sfss.vue
  4. 229
      src/views/data/DuplicateDrawerWithDetail.vue

139
src/components/data/complaintformdialog.vue

@ -132,7 +132,6 @@
<el-button <el-button
type="primary" type="primary"
:loading="duplicateLoading" :loading="duplicateLoading"
:disabled="model.responderIdCodeSkip"
@click="onCheckDuplicate" @click="onCheckDuplicate"
> >
查看 查看
@ -268,107 +267,21 @@
</el-button> </el-button>
</div> </div>
</template> </template>
<!-- 重复件提示抽屉 -->
<el-drawer
v-model="duplicateDrawerVisible"
direction="rtl"
size="40%"
class="duplicate-drawer"
>
<template #header>
<div class="drawer-header danger">
<el-icon size="22">
<WarningFilled />
</el-icon>
<div class="title-group">
<div class="title">信息重复件风险提醒</div>
</div>
</div>
</template>
<!-- 内容区域 -->
<div class="drawer-body">
<!-- 顶部风险提示 -->
<el-alert
type="warning"
show-icon
:closable="false"
class="drawer-alert"
>
<template #title>
系统检测到信息可能存在重复登记记录
</template>
</el-alert>
<!-- 当前身份证号高亮 -->
<div class="id-highlight">
当前信息
<span>
身份证{{ model.responderIdCode }}
&nbsp;&nbsp;&nbsp;
姓名{{ model.responderName }}
&nbsp;&nbsp;&nbsp;
电话{{ model.responderPhone }}
</span>
</div>
<!-- 无数据 -->
<el-empty
v-if="duplicateList.length === 0"
description="暂无重复数据"
/>
<!-- 重复件表格 -->
<el-table
v-else
:data="duplicateList"
stripe
style="width: 100%"
>
<el-table-column
prop="originId"
label="编号"
width="140"
/>
<el-table-column
prop="sourceTable"
label="来源"
width="120"
/>
<el-table-column
prop="responderName"
label="姓名"
width="90"
/>
<el-table-column
prop="responderIdCode"
label="身份证号"
width="100"
show-overflow-tooltip
/>
<el-table-column
prop="thingDesc"
label="投诉内容"
width="150"
show-overflow-tooltip
/>
<el-table-column
prop="discoveryTime"
label="登记/受理时间"
width="180"
>
<template #default="{ row }">
{{
row.discoveryTime
? dayjs(row.discoveryTime).format('YYYY-MM-DD HH:mm:ss')
: '-'
}}
</template>
</el-table-column>
</el-table>
</div>
</el-drawer>
</el-dialog> </el-dialog>
<DuplicateDrawerWithDetail
v-model="duplicateDrawerVisible"
:dict="dict"
:query="{
responderIdCode: model.responderIdCode,
responderName: model.responderName,
responderPhone: model.responderPhone
}"
:requestFn="maileRepeatt"
detailIdKey="complaintId"
/>
</template> </template>
<script setup> <script setup>
@ -377,6 +290,8 @@ import {maileRepeatt} from "@/api/data/complaintCollection.ts";
import { WarningFilled } from '@element-plus/icons-vue' import { WarningFilled } from '@element-plus/icons-vue'
import dayjs from "dayjs"; import dayjs from "dayjs";
import feedback from "@/utils/feedback.ts"; import feedback from "@/utils/feedback.ts";
import Complaint_detail from "@/components/data/complaint_detail.vue";
import DuplicateDrawerWithDetail from "@/views/data/DuplicateDrawerWithDetail.vue";
const props = defineProps({ const props = defineProps({
modelValue: Boolean, // modelValue: Boolean, //
@ -447,27 +362,7 @@ const duplicateDrawerVisible = ref(false)
const duplicateList = ref([]) const duplicateList = ref([])
const duplicateLoading = ref(false) const duplicateLoading = ref(false)
const onCheckDuplicate = async () => { const onCheckDuplicate = async () => {
duplicateLoading.value = true duplicateDrawerVisible.value = true
duplicateList.value = []
try {
const body = {
responderIdCode: props.model.responderIdCode,
responderName: props.model.responderName,
responderPhone: props.model.responderPhone,
}
const res = await maileRepeatt(body)
const list = res?.complaintCollectionRepeatDTOS || []
if (list.length > 0) {
duplicateList.value = list
duplicateDrawerVisible.value = true
} else {
feedback.msgSuccess("未发现重复登记记录");
}
} catch (error) {
// feedback.msgError('')
} finally {
duplicateLoading.value = false
}
} }
// region // region

52
src/components/data/complaintproblemInfo.vue

@ -55,9 +55,21 @@
<div class="col col-12"> <div class="col col-12">
<label>是否重复件</label> <label>是否重复件</label>
<span>{{ getDictLabel(dict?.yesNo, data.repeatt) }}</span> <div class="inline-actions">
<span>{{ getDictLabel(dict?.yesNo, data.repeatt) }}</span>
<el-button
v-if="String(data.repeatt) === '1'"
class="repeat-btn"
type="primary"
link
@click="onRepeatClick"
>
查看
</el-button>
</div>
</div> </div>
<div class="col col-12"> <div class="col col-12">
<label>标签</label> <label>标签</label>
<span>{{ tagText }}</span> <span>{{ tagText }}</span>
@ -74,11 +86,29 @@
<file-list :files="data.thingFiles" /> <file-list :files="data.thingFiles" />
</div> </div>
</div> </div>
<DuplicateDrawerWithDetail
v-model="duplicateDrawerVisible"
:dict="dict"
:query="{
responderIdCode: data.responderIdCode,
responderName: data.responderName,
responderPhone: data.responderPhone
}"
:requestFn="maileRepeatt"
detailIdKey="complaintId"
:excludeId="data.id"
/>
</template> </template>
<script setup> <script setup>
import { computed } from "vue"; import { computed } from "vue";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { ElMessage } from "element-plus";
import DuplicateDrawerWithDetail from "@/views/data/DuplicateDrawerWithDetail.vue";
import {maileRepeatt} from "@/api/data/complaintCollection.ts";
const props = defineProps({ const props = defineProps({
data: { type: Object, default: () => ({}) }, // base data: { type: Object, default: () => ({}) }, // base
@ -144,6 +174,15 @@ const tagText = computed(() => {
.filter((x) => x && x !== "/") .filter((x) => x && x !== "/")
.join(",") || "/"; .join(",") || "/";
}); });
const duplicateDrawerVisible = ref(false);
const onRepeatClick = () => {
duplicateDrawerVisible.value = true;
};
</script> </script>
<style scoped> <style scoped>
@ -213,4 +252,15 @@ span {
.mb-10 { .mb-10 {
margin-bottom: 10px; margin-bottom: 10px;
} }
.inline-actions {
display: inline-flex;
align-items: center;
gap: 8px;
flex: 0 0 auto;
}
.repeat-btn {
padding: 0; /* link 按钮默认就很轻,这行是让它更像文字 */
}
</style> </style>

55
src/components/negative/verify-sfss.vue

@ -60,7 +60,18 @@
<div class="col col-12"> <div class="col col-12">
<label>是否重复件</label> <label>是否重复件</label>
<span>{{ getDictLabel(dict.yesNo, currentRow.repeatt) }}</span> <div class="inline-actions">
<span>{{ getDictLabel(dict?.yesNo, currentRow.repeatt) }}</span>
<el-button
v-if="String(currentRow.repeatt) === '1'"
class="repeat-btn"
type="primary"
link
@click="onRepeatClick"
>
查看
</el-button>
</div>
</div> </div>
<div class="col col-12"> <div class="col col-12">
@ -1565,22 +1576,34 @@
</el-form> </el-form>
<DuplicateDrawerWithDetail
v-model="duplicateDrawerVisible"
:dict="dict"
:query="{
responderIdCode: currentRow.responderIdCode,
responderName: currentRow.responderName,
responderPhone: currentRow.responderPhone
}"
:requestFn="maileRepeatt"
detailIdKey="complaintId"
:excludeId="currentRow.id"
/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {BASE_PATH} from "@/api/request";
import { import {
InspectCase,
IsRectify,
AccountabilityTarget, AccountabilityTarget,
BlameType, BlameType,
ProblemSources,
PersonType,
HostLevel, HostLevel,
PersonType,
ProblemSources,
SubjectiveAspect, SubjectiveAspect,
} from "@/enums/dictEnums"; } from "@/enums/dictEnums";
import useCatchStore from "@/stores/modules/catch"; import useCatchStore from "@/stores/modules/catch";
import {getConfinementListAll} from "@/api/work/confinement"; import {getConfinementListAll} from "@/api/work/confinement";
import {timeFormat} from "@/utils/util"; import {timeFormat} from "@/utils/util";
import {maileRepeatt} from "@/api/data/complaintCollection";
import DuplicateDrawerWithDetail from "@/views/data/DuplicateDrawerWithDetail.vue";
// //
const catchSotre = useCatchStore(); const catchSotre = useCatchStore();
@ -2009,6 +2032,14 @@ const formatLocalDateTime = (val) => {
} }
const duplicateDrawerVisible = ref(false);
const onRepeatClick = () => {
duplicateDrawerVisible.value = true;
};
defineExpose({ defineExpose({
validate, validate,
getData, getData,
@ -2085,4 +2116,16 @@ span {
text-align-last: left; text-align-last: left;
line-height: 1.6; line-height: 1.6;
} }
.inline-actions {
display: inline-flex;
align-items: center;
gap: 8px;
flex: 0 0 auto;
}
.repeat-btn {
padding: 0; /* link 按钮默认就很轻,这行是让它更像文字 */
}
</style> </style>

229
src/views/data/DuplicateDrawerWithDetail.vue

@ -0,0 +1,229 @@
<template>
<!-- 重复件抽屉 -->
<el-drawer
v-model="visible"
direction="rtl"
size="40%"
class="duplicate-drawer"
>
<template #header>
<div class="drawer-header danger">
<el-icon size="22">
<WarningFilled />
</el-icon>
<div class="title-group">
<div class="title">信息重复件风险提醒</div>
</div>
</div>
</template>
<div class="drawer-body">
<el-alert type="warning" show-icon :closable="false" class="drawer-alert">
<template #title>系统检测到信息可能存在重复登记记录</template>
</el-alert>
<div class="id-highlight">
当前信息
<span>
身份证{{ query.responderIdCode || "-" }}
&nbsp;&nbsp;&nbsp;
姓名{{ query.responderName || "-" }}
&nbsp;&nbsp;&nbsp;
电话{{ query.responderPhone || "-" }}
</span>
</div>
<el-empty v-if="list.length === 0" description="暂无重复数据" />
<el-table
v-else
:data="list"
stripe
style="width: 100%"
:row-class-name="rowClassName"
@row-click="handleRowClick"
>
<el-table-column prop="originId" label="编号" width="140" />
<el-table-column prop="sourceTable" label="来源" width="120" />
<!-- <el-table-column prop="sourceTable" label="来源" width="120">-->
<!-- <template #default="{ row }">-->
<!-- <span :class="{ 'source-highlight': String(row?.sourceTable || '').includes('(投)') }">-->
<!-- {{ row.sourceTable || '-' }}-->
<!-- </span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="responderName" label="姓名" width="90" />
<el-table-column prop="responderIdCode" label="身份证号" width="100" show-overflow-tooltip />
<el-table-column prop="thingDesc" label="投诉内容" width="150" show-overflow-tooltip />
<el-table-column prop="discoveryTime" label="登记/受理时间" width="180">
<template #default="{ row }">
{{ row.discoveryTime ? dayjs(row.discoveryTime).format("YYYY-MM-DD HH:mm:ss") : "-" }}
</template>
</el-table-column>
</el-table>
</div>
</el-drawer>
<!-- 详情弹窗封装在组件内部 -->
<complaint_detail
width="80vw"
v-model="detailShow"
:id="activeId"
:dict="dict"
/>
</template>
<script setup>
import { computed, ref, watch } from "vue";
import dayjs from "dayjs";
import { WarningFilled } from "@element-plus/icons-vue";
import Complaint_detail from "@/components/data/complaint_detail.vue";
/**
* 目标组件内部封装
* 1) 抽屉展示重复件列表
* 2) 点击行 -> 打开 complaint_detail
*
* props:
* - modelValue: 抽屉开关
* - query: 查重条件身份证/姓名/电话
* - dict: 详情组件需要的 dict
* - requestFn: 请求查重函数 maileRepeatt
* - autoFetchOnOpen: 打开抽屉是否自动查一次
*
* emits:
* - update:modelValue
* - loaded: 查重结果给父组件可选做缓存/提示
* - opened-detail: 打开了哪条详情可选
*/
const props = defineProps({
modelValue: { type: Boolean, default: false },
query: {
type: Object,
default: () => ({ responderIdCode: "", responderName: "", responderPhone: "" }),
},
dict: { type: Object, default: () => ({}) },
requestFn: { type: Function, required: true },
autoFetchOnOpen: { type: Boolean, default: true },
// id complaintId
detailIdKey: { type: String, default: "complaintId" },
excludeId: { type: [String, Number], default: "" },
});
const emit = defineEmits(["update:modelValue", "loaded", "opened-detail"]);
const visible = computed({
get: () => props.modelValue,
set: (v) => emit("update:modelValue", v),
});
const list = ref([]);
const detailShow = ref(false);
const activeId = ref("");
const fetchList = async () => {
const body = {
responderIdCode: props.query?.responderIdCode,
responderName: props.query?.responderName,
responderPhone: props.query?.responderPhone,
};
const res = await props.requestFn(body);
const rows = res?.complaintCollectionRepeatDTOS || [];
const exclude = String(props.excludeId || "");
list.value = exclude
? rows.filter(r => String(r?.complaintId || "") !== exclude)
: rows;
emit("loaded", rows);
return rows;
};
watch(
() => visible.value,
async (v) => {
if (!v) return;
list.value = [];
if (props.autoFetchOnOpen) {
try {
await fetchList();
} catch (e) {
list.value = [];
}
}
}
);
const handleRowClick = (row) => {
const id = row?.[props.detailIdKey];
if (!id) return; // ElMessage.warning("ID")
activeId.value = id;
detailShow.value = true;
emit("opened-detail", row);
};
const rowClassName = ({ row }) => {
return String(row?.sourceTable || "").includes("投") ? "row-highlight" : "";
};
</script>
<style>
/* 抽屉整体 */
.duplicate-drawer {
--el-drawer-padding-primary: 20px;
}
.drawer-header {
display: flex;
align-items: center;
gap: 12px;
padding: 4px 0;
}
.drawer-header.danger {
color: #0d73ee;
}
.drawer-header .title {
font-size: 20px;
font-weight: 600;
line-height: 1.2;
}
.drawer-body {
padding-top: 8px;
}
.drawer-alert {
margin-bottom: 16px;
}
.id-highlight {
margin-bottom: 20px;
padding: 12px 16px;
background: #fafafa;
border-left: 4px solid #faad14;
font-size: 14px;
line-height: 22px;
}
.id-highlight span {
margin-left: 8px;
font-weight: 600;
color: #d4380d;
}
.clickable-row:hover > td {
background: #f5f7fa;
}
.row-highlight > td {
background: #fff4e6 !important;
}
</style>
Loading…
Cancel
Save