10 changed files with 897 additions and 0 deletions
@ -0,0 +1,71 @@ |
|||
package com.zdxt.enforcementcode.controller.web.supervision.report; |
|||
|
|||
import com.zdxt.enforcementcode.domain.bo.EnforcementRegistrationBo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationAnalysisVo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisDetailVo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisExportVo; |
|||
import com.zdxt.enforcementcode.report.IEnforcementRegistrationStatisticsService; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.dromara.common.core.domain.R; |
|||
import org.dromara.common.excel.utils.ExcelUtil; |
|||
import org.dromara.common.mybatis.core.page.PageQuery; |
|||
import org.dromara.common.mybatis.core.page.TableDataInfo; |
|||
import org.springframework.validation.annotation.Validated; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 执法分析(独立菜单页,按企业维度聚合统计执法次数) |
|||
* |
|||
* @author zdxt |
|||
*/ |
|||
@Slf4j |
|||
@Validated |
|||
@RequiredArgsConstructor |
|||
@RestController |
|||
@RequestMapping("/web/supervision/report/registration-statistics") |
|||
public class RegistrationStatisticsController { |
|||
|
|||
private final IEnforcementRegistrationStatisticsService statisticsService; |
|||
|
|||
/** |
|||
* 执法分析列表(分页,V2排序) |
|||
*/ |
|||
@GetMapping("/list") |
|||
public TableDataInfo<RegistrationAnalysisVo> list(EnforcementRegistrationBo bo, PageQuery pageQuery) { |
|||
return statisticsService.list(bo, pageQuery); |
|||
} |
|||
|
|||
/** |
|||
* 执法分析详情(指定企业的执法明细聚合) |
|||
*/ |
|||
@GetMapping("/detail") |
|||
public R<List<RegistrationStatisticsAnalysisDetailVo>> detail(EnforcementRegistrationBo bo) { |
|||
return R.ok(statisticsService.detail(bo)); |
|||
} |
|||
|
|||
/** |
|||
* 执法分析导出 |
|||
*/ |
|||
@PostMapping("/exportList") |
|||
public void exportList(EnforcementRegistrationBo bo, HttpServletResponse response) { |
|||
try { |
|||
List<RegistrationStatisticsAnalysisExportVo> list = statisticsService.exportList(bo); |
|||
ExcelUtil.exportExcel(list, "执法分析", RegistrationStatisticsAnalysisExportVo.class, response); |
|||
} catch (Exception e) { |
|||
log.error("导出执法分析Excel异常", e); |
|||
response.reset(); |
|||
response.setContentType("application/json; charset=utf-8"); |
|||
try { |
|||
response.getWriter().write("{\"code\":500,\"msg\":\"导出失败: " + e.getMessage() + "\"}"); |
|||
} catch (Exception ignored) { |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
package com.zdxt.enforcementcode.domain.vo.report; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serial; |
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* 执法分析-详情弹窗VO(指定企业的执法明细聚合) |
|||
* |
|||
* @author zdxt |
|||
*/ |
|||
@Data |
|||
public class RegistrationStatisticsAnalysisDetailVo implements Serializable { |
|||
|
|||
@Serial |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 执法单位 |
|||
*/ |
|||
private String bureauDeptName; |
|||
|
|||
/** |
|||
* 执法人员 |
|||
*/ |
|||
private String lawEnforcer; |
|||
|
|||
/** |
|||
* 执法事项 |
|||
*/ |
|||
private String lawEnforcementItemText; |
|||
|
|||
/** |
|||
* 数量(同一执法单位+人员+事项的次数) |
|||
*/ |
|||
private Integer total; |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
package com.zdxt.enforcementcode.domain.vo.report; |
|||
|
|||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
|||
import cn.idev.excel.annotation.ExcelProperty; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serial; |
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* 执法分析-导出Excel VO(12列,对齐旧系统导出格式) |
|||
* |
|||
* @author zdxt |
|||
*/ |
|||
@Data |
|||
@ExcelIgnoreUnannotated |
|||
public class RegistrationStatisticsAnalysisExportVo implements Serializable { |
|||
|
|||
@Serial |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@ExcelProperty(value = "区域") |
|||
private String district; |
|||
|
|||
@ExcelProperty(value = "街道") |
|||
private String street; |
|||
|
|||
@ExcelProperty(value = "企业名称") |
|||
private String enterpriseName; |
|||
|
|||
@ExcelProperty(value = "执法单位") |
|||
private String bureauDeptName; |
|||
|
|||
@ExcelProperty(value = "执法人员") |
|||
private String lawEnforcer; |
|||
|
|||
@ExcelProperty(value = "执法事项") |
|||
private String lawEnforcementItemText; |
|||
|
|||
@ExcelProperty(value = "执法时间") |
|||
private String enforcementTime; |
|||
|
|||
@ExcelProperty(value = "执法次数") |
|||
private Integer totalCount; |
|||
|
|||
@ExcelProperty(value = "2次及以下") |
|||
private String level2; |
|||
|
|||
@ExcelProperty(value = "3至4次(黄色)") |
|||
private String level34; |
|||
|
|||
@ExcelProperty(value = "5至6次(橙色)") |
|||
private String level56; |
|||
|
|||
@ExcelProperty(value = "7次及以上(红色)") |
|||
private String level7plus; |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
package com.zdxt.enforcementcode.report; |
|||
|
|||
import com.zdxt.enforcementcode.domain.bo.EnforcementRegistrationBo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationAnalysisVo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisDetailVo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisExportVo; |
|||
import org.dromara.common.mybatis.core.page.PageQuery; |
|||
import org.dromara.common.mybatis.core.page.TableDataInfo; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 执法分析服务接口(独立菜单页,按企业维度聚合统计执法次数) |
|||
* |
|||
* @author zdxt |
|||
*/ |
|||
public interface IEnforcementRegistrationStatisticsService { |
|||
|
|||
/** |
|||
* 执法分析列表(分页,V2排序) |
|||
*/ |
|||
TableDataInfo<RegistrationAnalysisVo> list(EnforcementRegistrationBo bo, PageQuery pageQuery); |
|||
|
|||
/** |
|||
* 执法分析详情(指定企业的逐条执法记录聚合) |
|||
*/ |
|||
List<RegistrationStatisticsAnalysisDetailVo> detail(EnforcementRegistrationBo bo); |
|||
|
|||
/** |
|||
* 执法分析导出(全量,V2排序) |
|||
*/ |
|||
List<RegistrationStatisticsAnalysisExportVo> exportList(EnforcementRegistrationBo bo); |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
package com.zdxt.enforcementcode.report.impl; |
|||
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.zdxt.enforcementcode.domain.bo.EnforcementRegistrationBo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationAnalysisVo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisDetailVo; |
|||
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisExportVo; |
|||
import com.zdxt.enforcementcode.mapper.EnforcementRegistrationMapper; |
|||
import com.zdxt.enforcementcode.report.IEnforcementRegistrationStatisticsService; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.dromara.common.mybatis.core.page.PageQuery; |
|||
import org.dromara.common.mybatis.core.page.TableDataInfo; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* 执法分析服务实现(独立菜单页,按企业维度聚合统计执法次数,V2排序) |
|||
* |
|||
* @author zdxt |
|||
*/ |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
@Service |
|||
public class EnforcementRegistrationStatisticsServiceImpl implements IEnforcementRegistrationStatisticsService { |
|||
|
|||
private final EnforcementRegistrationMapper registrationMapper; |
|||
|
|||
@Override |
|||
public TableDataInfo<RegistrationAnalysisVo> list(EnforcementRegistrationBo bo, PageQuery pageQuery) { |
|||
Page<RegistrationAnalysisVo> page = pageQuery.build(); |
|||
IPage<RegistrationAnalysisVo> result = registrationMapper.selectAnalysisPageV2(page, bo, null); |
|||
return TableDataInfo.build(result); |
|||
} |
|||
|
|||
@Override |
|||
public List<RegistrationStatisticsAnalysisDetailVo> detail(EnforcementRegistrationBo bo) { |
|||
return registrationMapper.selectAnalysisDetail(bo, null); |
|||
} |
|||
|
|||
@Override |
|||
public List<RegistrationStatisticsAnalysisExportVo> exportList(EnforcementRegistrationBo bo) { |
|||
// 全量加载(不分页)
|
|||
Page<RegistrationAnalysisVo> page = new Page<>(1, Integer.MAX_VALUE, false); |
|||
IPage<RegistrationAnalysisVo> result = registrationMapper.selectAnalysisPageV2(page, bo, null); |
|||
List<RegistrationAnalysisVo> records = result.getRecords(); |
|||
|
|||
// 转换为导出VO(含颜色分级列)
|
|||
return records.stream().map(vo -> { |
|||
RegistrationStatisticsAnalysisExportVo exportVo = new RegistrationStatisticsAnalysisExportVo(); |
|||
exportVo.setDistrict(vo.getDistrict()); |
|||
exportVo.setStreet(vo.getStreet()); |
|||
exportVo.setEnterpriseName(vo.getEnterpriseName()); |
|||
exportVo.setBureauDeptName(vo.getBureauDeptName()); |
|||
exportVo.setLawEnforcer(vo.getLawEnforcer()); |
|||
exportVo.setLawEnforcementItemText(vo.getLawEnforcementItemText()); |
|||
exportVo.setEnforcementTime(vo.getEnforcementTime()); |
|||
exportVo.setTotalCount(vo.getTotalCount()); |
|||
|
|||
// 颜色分级列
|
|||
int count = vo.getTotalCount() != null ? vo.getTotalCount() : 0; |
|||
exportVo.setLevel2(count <= 2 ? String.valueOf(count) : "-"); |
|||
exportVo.setLevel34(count >= 3 && count <= 4 ? String.valueOf(count) : "-"); |
|||
exportVo.setLevel56(count >= 5 && count <= 6 ? String.valueOf(count) : "-"); |
|||
exportVo.setLevel7plus(count >= 7 ? String.valueOf(count) : "-"); |
|||
|
|||
return exportVo; |
|||
}).collect(Collectors.toList()); |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
|
|||
const BASE_URL = '/web/supervision/report/registration-statistics'; |
|||
|
|||
/** 查询参数 */ |
|||
export interface AnalysisQuery { |
|||
pageNum?: number; |
|||
pageSize?: number; |
|||
bureauDeptName?: string; |
|||
lawEnforcer?: string; |
|||
enterpriseName?: string; |
|||
lawEnforcementItemText?: string; |
|||
district?: string; |
|||
street?: string; |
|||
dateType?: number; |
|||
dateSearch?: string; |
|||
beginTime?: string; |
|||
endTime?: string; |
|||
numLeft?: string; |
|||
numRight?: string; |
|||
num?: string; |
|||
enterpriseNumber?: string; |
|||
} |
|||
|
|||
/** 执法分析行VO */ |
|||
export interface RegistrationAnalysisVo { |
|||
district: string; |
|||
street: string; |
|||
enterpriseName: string; |
|||
enterpriseNumber: string; |
|||
bureauDeptName: string; |
|||
lawEnforcer: string; |
|||
lawEnforcementItemText: string; |
|||
enforcementTime: string; |
|||
totalCount: number; |
|||
colorLevel: string; |
|||
} |
|||
|
|||
/** 详情VO */ |
|||
export interface AnalysisDetailVo { |
|||
bureauDeptName: string; |
|||
lawEnforcer: string; |
|||
lawEnforcementItemText: string; |
|||
total: number; |
|||
} |
|||
|
|||
/** |
|||
* 执法分析列表(分页) |
|||
*/ |
|||
export const getAnalysisList = (params: AnalysisQuery): AxiosPromise => { |
|||
return request({ |
|||
url: `${BASE_URL}/list`, |
|||
method: 'get', |
|||
params |
|||
}); |
|||
}; |
|||
|
|||
/** |
|||
* 执法分析详情(指定企业执法明细) |
|||
*/ |
|||
export const getAnalysisDetail = (params: AnalysisQuery): AxiosPromise => { |
|||
return request({ |
|||
url: `${BASE_URL}/detail`, |
|||
method: 'get', |
|||
params |
|||
}); |
|||
}; |
|||
|
|||
/** |
|||
* 执法分析导出 |
|||
*/ |
|||
export const exportAnalysisList = (params: AnalysisQuery): AxiosPromise<Blob> => { |
|||
return request({ |
|||
url: `${BASE_URL}/exportList`, |
|||
method: 'post', |
|||
params, |
|||
responseType: 'blob' |
|||
}); |
|||
}; |
|||
@ -0,0 +1,367 @@ |
|||
<script setup lang="ts"> |
|||
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { |
|||
getAnalysisList, getAnalysisDetail, exportAnalysisList |
|||
} from '@/api/efcode/report/registration-statistics'; |
|||
import type { AnalysisQuery, RegistrationAnalysisVo, AnalysisDetailVo } from '@/api/efcode/report/registration-statistics'; |
|||
import { getDicts } from '@/api/system/dict/data'; |
|||
|
|||
// 查询参数 |
|||
const queryParams = reactive<AnalysisQuery>({ |
|||
pageNum: 1, |
|||
pageSize: 20, |
|||
bureauDeptName: undefined, |
|||
lawEnforcer: undefined, |
|||
enterpriseName: undefined, |
|||
lawEnforcementItemText: undefined, |
|||
district: undefined, |
|||
street: undefined, |
|||
dateType: undefined, |
|||
dateSearch: undefined, |
|||
beginTime: undefined, |
|||
endTime: undefined |
|||
}); |
|||
|
|||
const loading = ref(false); |
|||
const tableData = ref<RegistrationAnalysisVo[]>([]); |
|||
const total = ref(0); |
|||
const tableHeight = ref<number | undefined>(undefined); |
|||
const tableRef = ref(); |
|||
|
|||
// 字典 |
|||
const addressTypeOptions = ref<any[]>([]); |
|||
const streetOptions = ref<any[]>([]); |
|||
|
|||
// 时段模式 |
|||
const timeMode = ref('year'); |
|||
const selectedYear = ref<string>(String(new Date().getFullYear())); |
|||
const selectedQuarter = ref<number>(Math.ceil((new Date().getMonth() + 1) / 3)); |
|||
const selectedMonth = ref<string>(''); |
|||
|
|||
// 季度选项 |
|||
const quarterOptions = [ |
|||
{ label: '第一季度', value: 1 }, |
|||
{ label: '第二季度', value: 2 }, |
|||
{ label: '第三季度', value: 3 }, |
|||
{ label: '第四季度', value: 4 } |
|||
]; |
|||
|
|||
// 年份选项 |
|||
const yearOptions = (() => { |
|||
const curr = new Date().getFullYear(); |
|||
return Array.from({ length: 5 }, (_, i) => String(curr - i)); |
|||
})(); |
|||
|
|||
// 详情弹窗 |
|||
const detailDialogVisible = ref(false); |
|||
const detailLoading = ref(false); |
|||
const detailData = ref<AnalysisDetailVo[]>([]); |
|||
const detailEnterpriseName = ref(''); |
|||
|
|||
onMounted(() => { |
|||
loadDicts(); |
|||
applyYearFilter(); |
|||
handleQuery(); |
|||
nextTick(() => calcTableHeight()); |
|||
window.addEventListener('resize', calcTableHeight); |
|||
}); |
|||
|
|||
onUnmounted(() => { |
|||
window.removeEventListener('resize', calcTableHeight); |
|||
}); |
|||
|
|||
/** 计算表格高度 */ |
|||
const calcTableHeight = () => { |
|||
const el = tableRef.value?.$el as HTMLElement; |
|||
if (!el) return; |
|||
const rect = el.getBoundingClientRect(); |
|||
tableHeight.value = window.innerHeight - rect.top - 102; |
|||
}; |
|||
|
|||
/** 加载字典 */ |
|||
const loadDicts = async () => { |
|||
try { |
|||
const res = await getDicts('address_type'); |
|||
addressTypeOptions.value = res.data || []; |
|||
} catch (e) { |
|||
console.error('加载字典失败', e); |
|||
} |
|||
}; |
|||
|
|||
/** 区域变更时加载街道 */ |
|||
const handleDistrictChange = async (val: string) => { |
|||
queryParams.street = undefined; |
|||
streetOptions.value = []; |
|||
if (val) { |
|||
try { |
|||
const matched = addressTypeOptions.value.find((item: any) => item.dictLabel === val); |
|||
if (matched) { |
|||
const res = await getDicts(matched.dictValue); |
|||
streetOptions.value = res.data || []; |
|||
} |
|||
} catch (e) {} |
|||
} |
|||
}; |
|||
|
|||
/** 时段模式变更 */ |
|||
const handleTimeModeChange = (mode: string) => { |
|||
queryParams.dateType = undefined; |
|||
queryParams.dateSearch = undefined; |
|||
queryParams.beginTime = undefined; |
|||
queryParams.endTime = undefined; |
|||
if (mode === 'year') { |
|||
applyYearFilter(); |
|||
} else if (mode === 'quarter') { |
|||
applyQuarterFilter(); |
|||
} else if (mode === 'month') { |
|||
const now = new Date(); |
|||
selectedMonth.value = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`; |
|||
applyMonthFilter(); |
|||
} |
|||
}; |
|||
|
|||
/** 年度筛选 */ |
|||
const applyYearFilter = () => { |
|||
const year = selectedYear.value; |
|||
queryParams.beginTime = `${year}-01-01`; |
|||
queryParams.endTime = `${year}-12-31`; |
|||
}; |
|||
|
|||
/** 季度筛选 */ |
|||
const applyQuarterFilter = () => { |
|||
const year = selectedYear.value; |
|||
const q = selectedQuarter.value; |
|||
const startMonth = (q - 1) * 3 + 1; |
|||
const endMonth = q * 3; |
|||
const endDay = new Date(Number(year), endMonth, 0).getDate(); |
|||
queryParams.beginTime = `${year}-${String(startMonth).padStart(2, '0')}-01`; |
|||
queryParams.endTime = `${year}-${String(endMonth).padStart(2, '0')}-${endDay}`; |
|||
}; |
|||
|
|||
/** 月度筛选 */ |
|||
const applyMonthFilter = () => { |
|||
if (selectedMonth.value) { |
|||
queryParams.dateSearch = selectedMonth.value; |
|||
} |
|||
}; |
|||
|
|||
/** 年份变更 */ |
|||
const handleYearChange = () => { |
|||
if (timeMode.value === 'year') { |
|||
applyYearFilter(); |
|||
} else if (timeMode.value === 'quarter') { |
|||
applyQuarterFilter(); |
|||
} |
|||
}; |
|||
|
|||
/** 季度变更 */ |
|||
const handleQuarterChange = () => { |
|||
applyQuarterFilter(); |
|||
}; |
|||
|
|||
/** 月份变更 */ |
|||
const handleMonthChange = (val: string) => { |
|||
selectedMonth.value = val; |
|||
queryParams.dateSearch = val; |
|||
}; |
|||
|
|||
/** 搜索 */ |
|||
const handleQuery = () => { |
|||
queryParams.pageNum = 1; |
|||
getList(); |
|||
}; |
|||
|
|||
/** 重置 */ |
|||
const resetQuery = () => { |
|||
Object.assign(queryParams, { |
|||
pageNum: 1, |
|||
pageSize: 20, |
|||
bureauDeptName: undefined, |
|||
lawEnforcer: undefined, |
|||
enterpriseName: undefined, |
|||
lawEnforcementItemText: undefined, |
|||
district: undefined, |
|||
street: undefined, |
|||
dateType: undefined, |
|||
dateSearch: undefined, |
|||
beginTime: undefined, |
|||
endTime: undefined |
|||
}); |
|||
timeMode.value = 'year'; |
|||
selectedYear.value = String(new Date().getFullYear()); |
|||
selectedQuarter.value = Math.ceil((new Date().getMonth() + 1) / 3); |
|||
selectedMonth.value = ''; |
|||
streetOptions.value = []; |
|||
applyYearFilter(); |
|||
handleQuery(); |
|||
}; |
|||
|
|||
/** 查询列表 */ |
|||
const getList = async () => { |
|||
loading.value = true; |
|||
try { |
|||
const res = await getAnalysisList(queryParams); |
|||
tableData.value = res.rows || []; |
|||
total.value = res.total || 0; |
|||
} finally { |
|||
loading.value = false; |
|||
} |
|||
}; |
|||
|
|||
/** 导出 */ |
|||
const handleExport = async () => { |
|||
try { |
|||
const res = await exportAnalysisList(queryParams); |
|||
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 = '执法分析.xlsx'; |
|||
link.click(); |
|||
window.URL.revokeObjectURL(url); |
|||
} catch (e) { |
|||
ElMessage.error('导出失败'); |
|||
} |
|||
}; |
|||
|
|||
/** 点击执法次数查看详情 */ |
|||
const handleShowDetail = async (row: RegistrationAnalysisVo) => { |
|||
detailEnterpriseName.value = row.enterpriseName; |
|||
detailDialogVisible.value = true; |
|||
detailLoading.value = true; |
|||
try { |
|||
const params: AnalysisQuery = { |
|||
enterpriseNumber: row.enterpriseNumber, |
|||
dateType: queryParams.dateType, |
|||
dateSearch: queryParams.dateSearch, |
|||
beginTime: queryParams.beginTime, |
|||
endTime: queryParams.endTime |
|||
}; |
|||
const res = await getAnalysisDetail(params); |
|||
detailData.value = res.data || []; |
|||
} catch (e) { |
|||
ElMessage.error('获取详情失败'); |
|||
detailData.value = []; |
|||
} finally { |
|||
detailLoading.value = false; |
|||
} |
|||
}; |
|||
|
|||
/** 颜色分级列样式 */ |
|||
const getLevelCellStyle = (level: string) => { |
|||
const colorMap: Record<string, string> = { |
|||
yellow: '#e6a23c', |
|||
orange: '#f56c6c', |
|||
red: '#c00' |
|||
}; |
|||
return colorMap[level] || ''; |
|||
}; |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="p-2"> |
|||
<!-- 搜索区域 --> |
|||
<div class="mb-[10px]"> |
|||
<el-card shadow="hover"> |
|||
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> |
|||
<el-form-item label="执法单位" prop="bureauDeptName"> |
|||
<el-input v-model="queryParams.bureauDeptName" placeholder="请输入执法单位" clearable @keyup.enter="handleQuery" style="width: 120px" /> |
|||
</el-form-item> |
|||
<el-form-item label="执法人员" prop="lawEnforcer"> |
|||
<el-input v-model="queryParams.lawEnforcer" placeholder="请输入执法人员" clearable @keyup.enter="handleQuery" style="width: 90px" /> |
|||
</el-form-item> |
|||
<el-form-item label="企业名称" prop="enterpriseName"> |
|||
<el-input v-model="queryParams.enterpriseName" placeholder="请输入企业名称" clearable @keyup.enter="handleQuery" style="width: 120px" /> |
|||
</el-form-item> |
|||
<el-form-item label="执法事项" prop="lawEnforcementItemText"> |
|||
<el-input v-model="queryParams.lawEnforcementItemText" placeholder="请输入执法事项" clearable @keyup.enter="handleQuery" style="width: 120px" /> |
|||
</el-form-item> |
|||
<el-form-item label="时段"> |
|||
<el-select v-model="timeMode" style="width: 90px" @change="handleTimeModeChange"> |
|||
<el-option label="年度" value="year" /> |
|||
<el-option label="季度" value="quarter" /> |
|||
<el-option label="月度" value="month" /> |
|||
<el-option label="自定义" value="custom" /> |
|||
</el-select> |
|||
<el-select v-if="timeMode === 'year' || timeMode === 'quarter'" v-model="selectedYear" style="width: 100px; margin-left: 4px" @change="handleYearChange"> |
|||
<el-option v-for="y in yearOptions" :key="y" :label="y + '年'" :value="y" /> |
|||
</el-select> |
|||
<el-select v-if="timeMode === 'quarter'" v-model="selectedQuarter" style="width: 110px; margin-left: 4px" @change="handleQuarterChange"> |
|||
<el-option v-for="q in quarterOptions" :key="q.value" :label="q.label" :value="q.value" /> |
|||
</el-select> |
|||
<el-date-picker v-if="timeMode === 'month'" v-model="selectedMonth" type="month" placeholder="选择月份" value-format="YYYY-MM" style="width: 150px; margin-left: 4px" @change="handleMonthChange" /> |
|||
</el-form-item> |
|||
<el-form-item v-if="timeMode === 'custom'" label="执法时间"> |
|||
<el-date-picker v-model="queryParams.beginTime" type="date" placeholder="开始日期" value-format="YYYY-MM-DD" style="width: 130px" /> |
|||
<span style="margin: 0 4px">-</span> |
|||
<el-date-picker v-model="queryParams.endTime" type="date" placeholder="结束日期" value-format="YYYY-MM-DD" style="width: 130px" /> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> |
|||
<el-button icon="Refresh" @click="resetQuery">重置</el-button> |
|||
<el-button type="warning" icon="Download" @click="handleExport">导出</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</el-card> |
|||
</div> |
|||
|
|||
<!-- 表格区域 --> |
|||
<el-card shadow="hover"> |
|||
<el-table ref="tableRef" v-loading="loading" :data="tableData" :height="tableHeight" border stripe> |
|||
<el-table-column label="区域" prop="district" width="100" align="center" /> |
|||
<el-table-column label="街道" prop="street" width="120" align="center" /> |
|||
<el-table-column label="企业名称" prop="enterpriseName" min-width="200" :show-overflow-tooltip="true" /> |
|||
<el-table-column label="执法单位" prop="bureauDeptName" min-width="150" :show-overflow-tooltip="true" /> |
|||
<el-table-column label="执法人员" prop="lawEnforcer" min-width="120" :show-overflow-tooltip="true" /> |
|||
<el-table-column label="执法事项" prop="lawEnforcementItemText" min-width="150" :show-overflow-tooltip="true" /> |
|||
<el-table-column label="执法时间" prop="enforcementTime" width="110" align="center" /> |
|||
<el-table-column label="执法次数" width="100" align="center"> |
|||
<template #default="{ row }"> |
|||
<el-link type="success" :underline="false" @click="handleShowDetail(row)"> |
|||
{{ row.totalCount }} |
|||
</el-link> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="2次及以下" width="100" align="center"> |
|||
<template #default="{ row }"> |
|||
{{ row.totalCount <= 2 ? row.totalCount : '-' }} |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="3至4次" width="90" align="center"> |
|||
<template #default="{ row }"> |
|||
<span v-if="row.totalCount >= 3 && row.totalCount <= 4" style="color: #e6a23c; font-weight: bold;">{{ row.totalCount }}</span> |
|||
<span v-else>-</span> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="5至6次" width="90" align="center"> |
|||
<template #default="{ row }"> |
|||
<span v-if="row.totalCount >= 5 && row.totalCount <= 6" style="color: #f56c6c; font-weight: bold;">{{ row.totalCount }}</span> |
|||
<span v-else>-</span> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="7次及以上" width="100" align="center"> |
|||
<template #default="{ row }"> |
|||
<span v-if="row.totalCount >= 7" style="color: #c00; font-weight: bold;">{{ row.totalCount }}</span> |
|||
<span v-else>-</span> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
|
|||
<pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
|||
</el-card> |
|||
|
|||
<!-- 详情弹窗 --> |
|||
<el-dialog v-model="detailDialogVisible" :title="`执法详情 - ${detailEnterpriseName}`" width="700px" append-to-body destroy-on-close> |
|||
<el-table v-loading="detailLoading" :data="detailData" border stripe max-height="400"> |
|||
<el-table-column label="执法单位" prop="bureauDeptName" min-width="150" :show-overflow-tooltip="true" /> |
|||
<el-table-column label="执法人员" prop="lawEnforcer" min-width="120" :show-overflow-tooltip="true" /> |
|||
<el-table-column label="执法事项" prop="lawEnforcementItemText" min-width="150" :show-overflow-tooltip="true" /> |
|||
<el-table-column label="数量" prop="total" width="80" align="center" /> |
|||
</el-table> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<style scoped lang="scss"> |
|||
</style> |
|||
Loading…
Reference in new issue