|
|
@ -1,7 +1,16 @@ |
|
|
<script setup lang="ts"> |
|
|
<script setup lang="ts"> |
|
|
import { nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'; |
|
|
import { nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'; |
|
|
|
|
|
import { ElMessage } from 'element-plus'; |
|
|
import { getDicts } from '@/api/system/dict/data'; |
|
|
import { getDicts } from '@/api/system/dict/data'; |
|
|
import { listHighCheckArea, listHighCheckDomain, type HighFrequencyRow } from '@/api/efcode/report/high-frequency'; |
|
|
import { |
|
|
|
|
|
listHighCheckArea, |
|
|
|
|
|
listHighCheckDomain, |
|
|
|
|
|
exportHighCheckArea, |
|
|
|
|
|
exportHighCheckDomain, |
|
|
|
|
|
type HighFrequencyRow |
|
|
|
|
|
} from '@/api/efcode/report/high-frequency'; |
|
|
|
|
|
import { listKeyEnterpriseDetails } from '@/api/efcode/report/key-enterprises'; |
|
|
|
|
|
import { getDomainInfo, type DashboardDomainVo } from '@/api/efcode/dashboard/area-info'; |
|
|
|
|
|
|
|
|
/** 维度:area=各区域 field=各领域 */ |
|
|
/** 维度:area=各区域 field=各领域 */ |
|
|
const props = defineProps<{ |
|
|
const props = defineProps<{ |
|
|
@ -16,7 +25,7 @@ const queryParams = reactive({ |
|
|
district: undefined as string | undefined, // 区域 tab 用 |
|
|
district: undefined as string | undefined, // 区域 tab 用 |
|
|
domainName: undefined as string | undefined, // 领域 tab 用 |
|
|
domainName: undefined as string | undefined, // 领域 tab 用 |
|
|
year: String(now.getFullYear()), |
|
|
year: String(now.getFullYear()), |
|
|
month: `${String(now.getFullYear())}-${String(now.getMonth() + 1).padStart(2, '0')}` |
|
|
month: String(now.getMonth() + 1).padStart(2, '0') |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
/** 年份选项(近 5 年) */ |
|
|
/** 年份选项(近 5 年) */ |
|
|
@ -27,14 +36,7 @@ const yearOptions = (() => { |
|
|
|
|
|
|
|
|
// ======================== 字典 ======================== |
|
|
// ======================== 字典 ======================== |
|
|
const areaOptions = ref<any[]>([]); |
|
|
const areaOptions = ref<any[]>([]); |
|
|
const fieldOptions = [ |
|
|
const fieldOptions = ref<DashboardDomainVo[]>([]); |
|
|
{ label: '食品安全', value: 'food' }, |
|
|
|
|
|
{ label: '药品安全', value: 'drug' }, |
|
|
|
|
|
{ label: '特种设备', value: 'special_equipment' }, |
|
|
|
|
|
{ label: '产品质量', value: 'product' }, |
|
|
|
|
|
{ label: '计量', value: 'metrology' }, |
|
|
|
|
|
{ label: '认证认可', value: 'certification' } |
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
const loadAreaDict = async () => { |
|
|
const loadAreaDict = async () => { |
|
|
try { |
|
|
try { |
|
|
@ -45,6 +47,15 @@ const loadAreaDict = async () => { |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const loadFieldDict = async () => { |
|
|
|
|
|
try { |
|
|
|
|
|
const res = await getDomainInfo(); |
|
|
|
|
|
fieldOptions.value = res.data || []; |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error('加载所属领域字典失败', e); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// ======================== 表格数据 ======================== |
|
|
// ======================== 表格数据 ======================== |
|
|
const loading = ref(false); |
|
|
const loading = ref(false); |
|
|
const tableData = ref<HighFrequencyRow[]>([]); |
|
|
const tableData = ref<HighFrequencyRow[]>([]); |
|
|
@ -63,23 +74,26 @@ const calcTableHeight = () => { |
|
|
tableHeight.value = window.innerHeight - rect.top - 84; |
|
|
tableHeight.value = window.innerHeight - rect.top - 84; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** 区域接口/导出使用的执法时间(由年份 + 月份拼接为 YYYY-MM-01) */ |
|
|
|
|
|
const buildEnforcementTime = () => `${queryParams.year}-${queryParams.month}-01`; |
|
|
|
|
|
|
|
|
const getList = async () => { |
|
|
const getList = async () => { |
|
|
loading.value = true; |
|
|
loading.value = true; |
|
|
try { |
|
|
try { |
|
|
let rows: HighFrequencyRow[] = []; |
|
|
let rows: HighFrequencyRow[] = []; |
|
|
let totalNum = 0; |
|
|
let totalNum = 0; |
|
|
if (props.dimension === 'area') { |
|
|
if (props.dimension === 'area') { |
|
|
// 区域接口:district + enforcementTime(直接用 month 的 YYYY-MM 值) |
|
|
// 区域接口:district + enforcementTime(由独立年月拼接) |
|
|
const res = await listHighCheckArea({ |
|
|
const res = await listHighCheckArea({ |
|
|
pageNum: queryParams.pageNum, |
|
|
pageNum: queryParams.pageNum, |
|
|
pageSize: queryParams.pageSize, |
|
|
pageSize: queryParams.pageSize, |
|
|
district: queryParams.district, |
|
|
district: queryParams.district, |
|
|
enforcementTime: queryParams.month |
|
|
enforcementTime: buildEnforcementTime() |
|
|
}); |
|
|
}); |
|
|
rows = (res as any)?.rows || []; |
|
|
rows = (res as any)?.rows || []; |
|
|
totalNum = (res as any)?.total || 0; |
|
|
totalNum = (res as any)?.total || 0; |
|
|
} else { |
|
|
} else { |
|
|
// 领域接口:domainName + year + month(month 传值和 area 一样,但后端参数名不同) |
|
|
// 领域接口:domainName + year + month(独立年月字段) |
|
|
const res = await listHighCheckDomain({ |
|
|
const res = await listHighCheckDomain({ |
|
|
pageNum: queryParams.pageNum, |
|
|
pageNum: queryParams.pageNum, |
|
|
pageSize: queryParams.pageSize, |
|
|
pageSize: queryParams.pageSize, |
|
|
@ -109,15 +123,34 @@ const handleReset = () => { |
|
|
queryParams.district = undefined; |
|
|
queryParams.district = undefined; |
|
|
queryParams.domainName = undefined; |
|
|
queryParams.domainName = undefined; |
|
|
queryParams.year = String(new Date().getFullYear()); |
|
|
queryParams.year = String(new Date().getFullYear()); |
|
|
queryParams.month = `${String(new Date().getFullYear())}-${String(new Date().getMonth() + 1).padStart(2, '0')}`; |
|
|
queryParams.month = String(new Date().getMonth() + 1).padStart(2, '0'); |
|
|
queryParams.pageNum = 1; |
|
|
queryParams.pageNum = 1; |
|
|
queryParams.pageSize = 20; |
|
|
queryParams.pageSize = 20; |
|
|
getList(); |
|
|
getList(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/** 导出 */ |
|
|
/** 导出(各区域走 exporthighCheckArea,各领域走 exportHighCheckDomain) */ |
|
|
const handleExport = () => { |
|
|
const handleExport = async () => { |
|
|
// TODO: 接入导出接口后实现文件下载 |
|
|
try { |
|
|
|
|
|
const res = |
|
|
|
|
|
props.dimension === 'area' |
|
|
|
|
|
? await exportHighCheckArea({ |
|
|
|
|
|
district: queryParams.district, |
|
|
|
|
|
enforcementTime: buildEnforcementTime() |
|
|
|
|
|
}) |
|
|
|
|
|
: await exportHighCheckDomain({ domainName: queryParams.domainName }); |
|
|
|
|
|
const blob = new Blob([res as any], { |
|
|
|
|
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' |
|
|
|
|
|
}); |
|
|
|
|
|
const url = window.URL.createObjectURL(blob); |
|
|
|
|
|
const link = document.createElement('a'); |
|
|
|
|
|
link.href = url; |
|
|
|
|
|
link.download = props.dimension === 'area' ? '高频检查区域.xlsx' : '高频检查领域.xlsx'; |
|
|
|
|
|
link.click(); |
|
|
|
|
|
window.URL.revokeObjectURL(url); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
ElMessage.error('导出失败'); |
|
|
|
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/** 多选 */ |
|
|
/** 多选 */ |
|
|
@ -132,6 +165,7 @@ interface EnforcementDetailRow { |
|
|
bureauDeptName: string; |
|
|
bureauDeptName: string; |
|
|
categoryText: string; |
|
|
categoryText: string; |
|
|
lawEnforcer: string; |
|
|
lawEnforcer: string; |
|
|
|
|
|
lawEnforcerTwo?: string; |
|
|
itemText: string; |
|
|
itemText: string; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -147,7 +181,15 @@ const getDetailList = async () => { |
|
|
detailLoading.value = true; |
|
|
detailLoading.value = true; |
|
|
try { |
|
|
try { |
|
|
if (!detailEnterprise.value) return; |
|
|
if (!detailEnterprise.value) return; |
|
|
// TODO: 接入真实详情接口 listHighFrequencyDetail |
|
|
// 详情接口:enterpriseNumber(企业统一信用代码)+ enforcementTime(YYYY-MM-01) |
|
|
|
|
|
const res = await listKeyEnterpriseDetails({ |
|
|
|
|
|
pageNum: detailPage.value, |
|
|
|
|
|
pageSize: detailPageSize.value, |
|
|
|
|
|
enterpriseNumber: detailEnterprise.value.enterpriseNumber, |
|
|
|
|
|
enforcementTime: buildEnforcementTime() |
|
|
|
|
|
}); |
|
|
|
|
|
detailTableData.value = (res as any)?.rows || (Array.isArray(res) ? res : []); |
|
|
|
|
|
detailTotal.value = (res as any)?.total ?? detailTableData.value.length; |
|
|
} finally { |
|
|
} finally { |
|
|
detailLoading.value = false; |
|
|
detailLoading.value = false; |
|
|
} |
|
|
} |
|
|
@ -174,7 +216,11 @@ const handleDetailPageChange = (page: number) => { |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
onMounted(() => { |
|
|
onMounted(() => { |
|
|
loadAreaDict(); |
|
|
if (props.dimension === 'area') { |
|
|
|
|
|
loadAreaDict(); |
|
|
|
|
|
} else { |
|
|
|
|
|
loadFieldDict(); |
|
|
|
|
|
} |
|
|
getList(); |
|
|
getList(); |
|
|
nextTick(() => calcTableHeight()); |
|
|
nextTick(() => calcTableHeight()); |
|
|
window.addEventListener('resize', calcTableHeight); |
|
|
window.addEventListener('resize', calcTableHeight); |
|
|
@ -209,7 +255,7 @@ defineExpose({ calcTableHeight }); |
|
|
class="search-select" |
|
|
class="search-select" |
|
|
clearable |
|
|
clearable |
|
|
> |
|
|
> |
|
|
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.label" /> |
|
|
<el-option v-for="item in fieldOptions" :key="item.domainId" :label="item.domainName" :value="item.domainName" /> |
|
|
</el-select> |
|
|
</el-select> |
|
|
</el-form-item> |
|
|
</el-form-item> |
|
|
<el-form-item label="年份"> |
|
|
<el-form-item label="年份"> |
|
|
@ -221,7 +267,7 @@ defineExpose({ calcTableHeight }); |
|
|
<el-date-picker |
|
|
<el-date-picker |
|
|
v-model="queryParams.month" |
|
|
v-model="queryParams.month" |
|
|
type="month" |
|
|
type="month" |
|
|
value-format="YYYY-MM" |
|
|
value-format="MM" |
|
|
class="period-date" |
|
|
class="period-date" |
|
|
placeholder="选择月份" |
|
|
placeholder="选择月份" |
|
|
/> |
|
|
/> |
|
|
@ -252,11 +298,12 @@ defineExpose({ calcTableHeight }); |
|
|
<el-table-column type="selection" width="55" align="center" /> |
|
|
<el-table-column type="selection" width="55" align="center" /> |
|
|
<el-table-column label="序号" width="90" align="center" type="index" /> |
|
|
<el-table-column label="序号" width="90" align="center" type="index" /> |
|
|
<el-table-column prop="enterpriseName" label="企业名称" min-width="300" align="center" /> |
|
|
<el-table-column prop="enterpriseName" label="企业名称" min-width="300" align="center" /> |
|
|
<el-table-column prop="areaName" label="所属区" width="160" align="center" /> |
|
|
<el-table-column prop="district" label="所属区" width="160" align="center" v-if="dimension === 'area'" /> |
|
|
<el-table-column prop="streetName" label="所属街道" width="160" align="center" /> |
|
|
<el-table-column prop="street" label="所属街道" width="160" align="center" v-if="dimension === 'area'" /> |
|
|
|
|
|
<el-table-column prop="domainName" label="所属领域" width="260" align="center" v-if="dimension !== 'area'" /> |
|
|
<el-table-column label="行政执法次数" width="180" align="center"> |
|
|
<el-table-column label="行政执法次数" width="180" align="center"> |
|
|
<template #default="{ row }"> |
|
|
<template #default="{ row }"> |
|
|
<span v-if="row.enforcementCount !== null && row.enforcementCount !== undefined">{{ row.enforcementCount }}次</span> |
|
|
<span>{{ dimension === 'area'? row.xzzfcs:row.jccs }}次</span> |
|
|
</template> |
|
|
</template> |
|
|
</el-table-column> |
|
|
</el-table-column> |
|
|
<el-table-column label="操作" width="80" align="center" fixed="right"> |
|
|
<el-table-column label="操作" width="80" align="center" fixed="right"> |
|
|
@ -301,8 +348,8 @@ defineExpose({ calcTableHeight }); |
|
|
v-if="detailEnterprise" |
|
|
v-if="detailEnterprise" |
|
|
:closable="false" |
|
|
:closable="false" |
|
|
show-icon |
|
|
show-icon |
|
|
type="warning" |
|
|
:title="`所属区:${detailEnterprise.district || '-'} | 所属街道:${detailEnterprise.street || '-'} | 行政执法次数:${detailEnterprise.xzzfcs ?? 0}次 | 时段:${queryParams.year}年${queryParams.month}`" |
|
|
:title="`预警企业 | 所属区:${detailEnterprise.areaName || '-'} | 所属街道:${detailEnterprise.streetName || '-'} | 行政执法次数:${detailEnterprise.enforcementCount ?? 0}次 | 时段:${queryParams.year}年${queryParams.month}`" |
|
|
type="info" |
|
|
class="mb-4" |
|
|
class="mb-4" |
|
|
/> |
|
|
/> |
|
|
|
|
|
|
|
|
@ -317,9 +364,13 @@ defineExpose({ calcTableHeight }); |
|
|
<el-table-column label="序号" type="index" width="80" align="center" /> |
|
|
<el-table-column label="序号" type="index" width="80" align="center" /> |
|
|
<el-table-column label="执法时间" prop="enforcementTime" min-width="180" align="center" /> |
|
|
<el-table-column label="执法时间" prop="enforcementTime" min-width="180" align="center" /> |
|
|
<el-table-column label="执法单位" prop="bureauDeptName" min-width="260" align="center" /> |
|
|
<el-table-column label="执法单位" prop="bureauDeptName" min-width="260" align="center" /> |
|
|
<el-table-column label="执法类别" prop="categoryText" width="140" align="center" /> |
|
|
<el-table-column label="执法类别" prop="dictLabel" width="140" align="center" /> |
|
|
<el-table-column label="执法人员" prop="lawEnforcer" width="140" align="center" /> |
|
|
<el-table-column label="执法人员" width="140" align="center"> |
|
|
<el-table-column label="执法事项" prop="itemText" min-width="220" align="center" /> |
|
|
<template #default="{ row }"> |
|
|
|
|
|
{{ [row.lawEnforcer, row.lawEnforcerTwo].filter(Boolean).join('、') }} |
|
|
|
|
|
</template> |
|
|
|
|
|
</el-table-column> |
|
|
|
|
|
<el-table-column label="执法事项" prop="lawEnforcementItemText" min-width="220" align="center" /> |
|
|
</el-table> |
|
|
</el-table> |
|
|
|
|
|
|
|
|
<el-pagination |
|
|
<el-pagination |
|
|
@ -389,4 +440,7 @@ defineExpose({ calcTableHeight }); |
|
|
margin-top: 16px; |
|
|
margin-top: 16px; |
|
|
justify-content: flex-end; |
|
|
justify-content: flex-end; |
|
|
} |
|
|
} |
|
|
|
|
|
.mb-4 { |
|
|
|
|
|
margin-bottom: 16px; |
|
|
|
|
|
} |
|
|
</style> |
|
|
</style> |
|
|
|