安全管理子系统-6
今天给安全检查历史表做了id查询和时间范围查询
1、controller
package com.example.springbootdemo.controller;
import com.example.springbootdemo.entity.SafetyRiskHistory;
import com.example.springbootdemo.service.SafetyRiskHistoryService;
import org.springframework.data.domain.Sort;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@RestController
@RequestMapping("/history")
@CrossOrigin
public class SafetyRiskHistoryController {
private final SafetyRiskHistoryService service;
public SafetyRiskHistoryController(SafetyRiskHistoryService service) {
this.service = service;
}
// 获取所有历史记录(支持分页)
@GetMapping
public ResponseEntity<Page<SafetyRiskHistory>> getAllSafetyRiskHistories(
@PageableDefault(size = 10) Pageable pageable
) {
Page<SafetyRiskHistory> histories = service.getAllSafetyRiskHistories(pageable);
return new ResponseEntity<>(histories, HttpStatus.OK);
}
// 按 ID 查询
@GetMapping("/{id}")
public ResponseEntity<SafetyRiskHistory> getSafetyRiskHistoryById(@PathVariable Integer id) {
return service.getSafetyRiskHistoryById(id)
.map(history -> new ResponseEntity<>(history, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
// 按风险编码查询
@GetMapping("/riskCode/{riskCode}")
public ResponseEntity<List<SafetyRiskHistory>> findByRiskCode(@PathVariable String riskCode) {
List<SafetyRiskHistory> histories = service.findByRiskCode(riskCode);
return new ResponseEntity<>(histories, HttpStatus.OK);
}
// 按风险编码和时间范围查询(新增,对应服务层方法)
@GetMapping("/query")
public ResponseEntity<?> findByRiskCodeAndTimeRange(
@RequestParam(required = false) String riskCode,
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") Date startDate,
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") Date endDate,
@PageableDefault(size = 10, sort = "entry_date", direction = Sort.Direction.DESC) Pageable pageable
) {
System.out.println("Received params - riskCode: " + riskCode +
", startDate: " + startDate +
", endDate: " + endDate);
{
try {
Page<SafetyRiskHistory> histories = service.findByRiskCodeAndTimeRange(
StringUtils.isEmpty(riskCode) ? null : riskCode,
startDate,
endDate,
pageable
);
return new ResponseEntity<>(histories, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(Map.of("error", "查询失败: " + e.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
}
2、repository
package com.example.springbootdemo.repository;
import com.example.springbootdemo.entity.SafetyRiskHistory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
@Repository
public interface SafetyRiskHistoryRepository extends JpaRepository<SafetyRiskHistory, Integer> {
// 按风险编码查询历史记录
@Query("SELECT srh FROM SafetyRiskHistory srh WHERE srh.risk_code = :riskCode")
List<SafetyRiskHistory> findByRiskCode(String riskCode);
// 按风险编码和时间范围查询历史记录
@Query("SELECT srh FROM SafetyRiskHistory srh " +
"WHERE (:riskCode IS NULL OR srh.risk_code = :riskCode) " +
"AND (:startDate IS NULL OR srh.entry_date >= :startDate) " +
"AND (:endDate IS NULL OR srh.entry_date <= :endDate)")
Page<SafetyRiskHistory> findByRiskCodeAndTimeRange(
String riskCode,
Date startDate,
Date endDate,
Pageable pageable
);
// 添加按部门层级查询历史记录的方法(可选)
@Query("SELECT srh FROM SafetyRiskHistory srh " +
"WHERE (:company IS NULL OR srh.company = :company) AND " +
"(:new_department IS NULL OR srh.new_department = :new_department) AND " +
"(:work_area IS NULL OR srh.work_area = :work_area)")
List<SafetyRiskHistory> findByDepartmentHierarchy(
@Param("company") String company,
@Param("new_department") String new_department,
@Param("work_area") String work_area
);
}
3、service
package com.example.springbootdemo.service;
import com.example.springbootdemo.entity.SafetyRiskHistory;
import com.example.springbootdemo.repository.SafetyRiskHistoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Optional;
@Service
public class SafetyRiskHistoryService {
@Autowired
private SafetyRiskHistoryRepository repository;
// 获取所有历史记录(分页)
public Page<SafetyRiskHistory> getAllSafetyRiskHistories(Pageable pageable) {
return repository.findAll(pageable);
}
// 按 ID 查询
public Optional<SafetyRiskHistory> getSafetyRiskHistoryById(Integer id) {
return repository.findById(id);
}
// 按风险编码查询(新增,对应仓库方法)
public List<SafetyRiskHistory> findByRiskCode(String riskCode) {
return repository.findByRiskCode(riskCode);
}
// 按风险编码和时间范围查询(新增,对应仓库方法)
public Page<SafetyRiskHistory> findByRiskCodeAndTimeRange(
String riskCode,
Date startDate,
Date endDate,
Pageable pageable
) {
return repository.findByRiskCodeAndTimeRange(riskCode, startDate, endDate, pageable);
}
}
4、vue前端
<template>
<div>
<!-- 导航栏 -->
<div class="navigation-bar">
<NavigationButton />
</div>
<!-- 安全风险历史记录容器 -->
<div class="safety-risk-history-container">
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>安全风险历史记录</span>
<el-form :inline="true" class="search-form">
<el-form-item label="ID查询">
<el-input
v-model="searchId"
placeholder="请输入记录ID"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" class="el-button--primary" @click="handleSearch">
<i class="el-icon-search"></i> 查询
</el-button>
<el-button @click="resetSearch">
<i class="el-icon-refresh"></i> 重置
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<!-- 日期范围搜索区域 -->
<div class="date-search">
<el-form :inline="true" :model="searchForm" class="search-form">
<el-form-item label="日期范围">
<el-date-picker
v-model="searchForm.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handleSearch"
></el-date-picker>
</el-form-item>
</el-form>
</div>
<!-- 加载中骨架屏 -->
<el-skeleton
v-if="isLoading"
animated
style="height: 400px;"
/>
<!-- 表格数据展示 -->
<el-table
v-else
:data="tableData"
stripe
border
highlight-current-row
style="width: 100%;"
>
<!-- 编号 -->
<el-table-column
prop="id"
label="编号"
width="80"
align="center"
/>
<!-- 风险编码 -->
<el-table-column
prop="risk_code"
label="风险编码"
width="150"
/>
<!-- 公司 -->
<el-table-column
prop="company"
label="公司"
width="120"
/>
<!-- 部门 -->
<el-table-column
prop="new_department"
label="部门"
width="120"
/>
<!-- 工区 -->
<el-table-column
prop="work_area"
label="工区"
width="120"
/>
<!-- 班组 -->
<el-table-column
prop="team"
label="班组"
width="120"
/>
<!-- 专业系统 -->
<el-table-column
prop="professional_system"
label="专业系统"
width="150"
/>
<!-- 风险类别 -->
<el-table-column
prop="risk_category"
label="风险类别"
width="120"
/>
<!-- 风险项目 -->
<el-table-column
prop="risk_item"
label="风险项目"
width="150"
/>
<!-- 风险项点 -->
<el-table-column
prop="risk_point"
label="风险项点"
width="150"
/>
<!-- 风险等级 -->
<el-table-column
prop="risk_level"
label="风险等级"
width="100"
:formatter="formatRiskLevel"
/>
<!-- 危害程度 -->
<el-table-column
prop="harm_degree"
label="危害程度"
width="120"
/>
<!-- 管控措施 -->
<el-table-column
prop="control_measures"
label="管控措施"
width="200"
/>
<!-- 管控岗位 -->
<el-table-column
prop="control_position"
label="管控岗位"
width="150"
/>
<!-- 管控人员 -->
<el-table-column
prop="control_personnel"
label="管控人员"
width="150"
/>
<!-- 量化要求 -->
<el-table-column
prop="quantified_requirements"
label="量化要求"
width="200"
/>
<!-- 录入时间(格式化) -->
<el-table-column
prop="entry_date"
label="录入时间"
width="180"
:formatter="formatDateTime"
/>
<!-- 审核状态 -->
<el-table-column
prop="review_status"
label="审核状态"
width="120"
:formatter="formatReviewStatus"
/>
<!-- 审核日期(格式化) -->
<el-table-column
prop="review_date"
label="审核日期"
width="180"
:formatter="formatDateTime"
/>
<!-- 版本号 -->
<el-table-column
prop="version"
label="版本号"
width="80"
/>
<!-- 操作时间(格式化) -->
<el-table-column
prop="operation_time"
label="操作时间"
width="180"
:formatter="formatDateTime"
/>
<!-- 操作类型 -->
<el-table-column
prop="operation_type"
label="操作类型"
width="120"
/>
<!-- 更新人 -->
<el-table-column
prop="person"
label="更新人"
width="200"
/>
</el-table>
<!-- 分页组件 -->
<el-pagination
v-if="total > 0"
:current-page="currentPage"
:page-sizes="[10, 20, 30]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import request from '@/utils/request';
import NavigationButton from '@/components/NavigationButton.vue';
import { ElMessage } from 'element-plus';
// 响应式数据
const tableData = ref([]); // 表格数据
const total = ref(0); // 总条数
const currentPage = ref(1); // 当前页码(前端1-based)
const pageSize = ref(10); // 每页大小
const isLoading = ref(true); // 加载状态
const searchId = ref(''); // ID搜索输入框
// 日期范围搜索表单数据
const searchForm = ref({
dateRange: []
});
// 日期时间格式化函数(处理空值)
const formatDateTime = (row, column, cellValue) => {
if (!cellValue) return ''; // 空值直接返回空字符串
const date = new Date(cellValue);
return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
};
// 风险等级格式化(添加颜色标识)
const formatRiskLevel = (row, column, cellValue) => {
if (!cellValue) return '';
const levelMap = {
'高': 'danger',
'中': 'warning',
'低': 'success'
};
const color = levelMap[cellValue] || 'info';
return `<span class="el-tag el-tag--${color}">${cellValue}</span>`;
};
// 审核状态格式化(添加状态标识)
const formatReviewStatus = (row, column, cellValue) => {
if (!cellValue) return '';
const statusMap = {
'已审核': 'success',
'待审核': 'warning',
'已驳回': 'danger'
};
const color = statusMap[cellValue] || 'info';
return `<span class="el-tag el-tag--${color}">${cellValue}</span>`;
};
// 搜索处理
const handleSearch = async () => {
isLoading.value = true;
try {
if (searchId.value) {
// ID查询逻辑保持不变
const response = await request.get(`/history/${searchId.value}`);
tableData.value = response ? [response] : [];
total.value = response ? 1 : 0;
return;
}
// 处理日期范围参数
// 处理日期范围参数
const params = {
page: currentPage.value - 1,
size: pageSize.value,
riskCode: ''
};
if (searchForm.value.dateRange && searchForm.value.dateRange.length === 2) {
// 格式化日期为YYYY-MM-DDTHH:mm:ss
const formatDate = (date) => {
const d = new Date(date);
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}T${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
};
params.startDate = formatDate(searchForm.value.dateRange[0]);
params.endDate = formatDate(searchForm.value.dateRange[1]);
}
const response = await request.get('/history/query', { params });
if (response?.content) {
tableData.value = response.content;
total.value = response.totalElements;
} else {
tableData.value = [];
total.value = 0;
}
} catch (error) {
console.error('搜索失败:', error);
ElMessage.error(error.response?.data?.error || '搜索失败,请检查网络或重试');
tableData.value = [];
total.value = 0;
} finally {
isLoading.value = false;
}
};
// 重置搜索
const resetSearch = () => {
searchId.value = '';
searchForm.value.dateRange = [];
fetchData(); // 重新加载分页数据
};
// 加载数据(带分页参数)
const fetchData = async (page = 0, size = 10) => {
isLoading.value = true;
try {
const response = await request.get(`/history?page=${page}&size=${size}`); // 后端分页接口
tableData.value = response.content; // 数据存储在content中
total.value = response.totalElements; // 总条数
currentPage.value = page + 1; // 转换为前端显示页码(1-based)
pageSize.value = size; // 保存当前页大小
} catch (error) {
console.error('数据加载失败:', error);
ElMessage.error('数据加载失败,请检查网络或重试');
tableData.value = []; // 重置数据
total.value = 0; // 重置总条数
} finally {
isLoading.value = false; // 结束加载状态
}
};
// 初始化加载第一页数据
onMounted(() => {
fetchData(); // 初始加载page=0(后端第一页),size=10
});
// 分页事件处理:切换页码
const handleCurrentChange = (newPage) => {
currentPage.value = newPage;
handleSearch();
};
// 分页事件处理:切换页大小
const handleSizeChange = (newSize) => {
pageSize.value = newSize;
currentPage.value = 1; // 重置到第一页
handleSearch();
};
</script>
<style scoped>
/* 导航栏样式 */
.navigation-bar {
background-color: #1976D2;
display: flex;
gap: 20px;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1000;
height: 50px;
align-items: center;
padding: 0 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 确保Element UI按钮样式正确 */
.el-button.el-button--primary {
background-color: #409EFF;
border-color: #409EFF;
color: #fff;
}
.el-button.el-button--primary:hover {
background-color: #66b1ff;
border-color: #66b1ff;
}
.el-button {
font-size: 14px;
padding: 8px 15px;
border-radius: 4px;
transition: all 0.3s;
}
.el-button:not(.el-button--primary) {
background-color: #fff;
border: 1px solid #dcdfe6;
color: #606266;
}
.el-button:not(.el-button--primary):hover {
color: #409EFF;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
/* 容器样式 */
.safety-risk-history-container {
padding: 20px;
margin-top: 70px; /* 导航栏高度+边距 */
max-width: 1920px;
margin-left: auto;
margin-right: auto;
}
/* 卡片样式 */
.box-card {
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
}
.search-form {
margin-bottom: 0;
}
/* 日期搜索区域样式 */
.date-search {
padding: 15px 0;
border-top: 1px solid #EBEEF5;
}
/* 表格样式优化 */
.el-table {
margin-top: 10px;
font-size: 14px;
border-radius: 4px;
}
.el-table th {
background-color: #f5f7fa;
color: #606266;
font-weight: 600;
}
.el-table .el-tag {
margin: 0;
}
/* 骨架屏样式 */
.el-skeleton {
margin-top: 10px;
height: 400px;
border-radius: 4px;
}
/* 分页样式 */
.el-pagination {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
</style>
浙公网安备 33010602011771号