安全管理子系统-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>  
posted @ 2025-05-21 01:02  呓语-MSHK  阅读(13)  评论(0)    收藏  举报