4 changed files with 346 additions and 129 deletions
@ -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 || "-" }} |
||||||
|
|
||||||
|
姓名:{{ query.responderName || "-" }} |
||||||
|
|
||||||
|
电话:{{ 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…
Reference in new issue