结算修改

This commit is contained in:
syruan 2025-12-02 14:32:24 +08:00 committed by syruan
parent 7621de57f3
commit 72944b90ce
7 changed files with 1243 additions and 911 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/build/
/classes/
/logs/

File diff suppressed because it is too large Load Diff

View File

@ -17,32 +17,43 @@
.layui-card-header {
font-weight: bold;
font-size: 16px;
background: linear-gradient(to right, #1E9FFF, #5FB878);
color: white;
}
.detail-header {
margin-bottom: 20px;
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
border-left: 4px solid #1E9FFF;
}
.detail-info {
margin-bottom: 15px;
margin-bottom: 10px;
}
.detail-info .layui-inline {
margin-right: 20px;
margin-right: 30px;
margin-bottom: 10px;
}
.detail-info .label {
font-weight: bold;
display: inline-block;
width: 100px;
min-width: 90px;
text-align: right;
margin-right: 10px;
color: #333;
}
.detail-info .value {
display: inline-block;
color: #666;
}
.total-amount {
font-size: 18px;
font-size: 20px;
color: #FF5722;
font-weight: bold;
text-align: right;
padding: 10px 20px;
padding: 15px 0;
border-top: 2px dashed #e6e6e6;
margin-top: 10px;
}
.layui-tab-content {
padding: 15px 0;
@ -50,33 +61,57 @@
.layui-table-view {
margin: 0;
}
/* 操作按钮区域样式 */
.action-buttons {
position: fixed;
bottom: 20px;
right: 30px;
z-index: 999;
background: white;
padding: 15px 20px;
border-radius: 6px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
display: flex;
gap: 10px;
flex-wrap: wrap;
max-width: 600px;
}
.action-buttons .layui-btn {
margin: 0;
}
/* 打印时隐藏操作按钮 */
@media print {
.action-buttons {
display: none !important;
}
}
</style>
</head>
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header">计算结果详情</div>
<div class="layui-card-body">
<div class="detail-header">
<div class="detail-info" style="font-size: 13px;">
<div class="detail-info">
<div class="layui-inline">
<span class="label" style="background-color: #1E9FFF !important;">工程名称:</span>
<span class="label" style="background-color: transparent !important;">工程名称:</span>
<span class="value" id="projectName"></span>
</div>
<div class="layui-inline">
<span class="label" style="background-color: #1E9FFF !important;">统计区间:</span>
<span class="label" style="background-color: transparent !important;">统计区间:</span>
<span class="value" id="timeRange"></span>
</div>
<div class="layui-inline">
<span class="label" style="background-color: #1E9FFF !important;">创建时间:</span>
<span class="label" style="background-color: transparent !important;">创建时间:</span>
<span class="value" id="createTime"></span>
</div>
<div class="layui-inline">
<span class="label" style="background-color: #1E9FFF !important;">创建人:</span>
<span class="label" style="background-color: transparent !important;">创建人:</span>
<span class="value" id="createUser"></span>
</div>
</div>
<div class="total-amount">
<i class="layui-icon layui-icon-rmb" style="font-size: 18px;"></i>
总金额:<span id="totalAmount">0.00</span> 元
</div>
</div>
@ -92,14 +127,20 @@
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-primary" id="back-btn">返回</button>
<button class="layui-btn" id="print-btn">打印</button>
<button class="layui-btn layui-btn-normal" id="export-cost-btn"><i class="layui-icon layui-icon-export"></i> 导出费用计算表</button>
<button class="layui-btn layui-btn-normal" id="export-segment-btn"><i class="layui-icon layui-icon-export"></i> 导出物资区间费用表</button>
<button class="layui-btn layui-btn-normal" id="export-record-btn"><i class="layui-icon layui-icon-export"></i> 导出领退记录表</button>
</div>
<!-- 操作按钮区域 - 固定在右下角 -->
<div class="action-buttons">
<!-- <button class="layui-btn layui-btn-warm" id="print-btn">
<i class="layui-icon layui-icon-print"></i> 打印
</button> -->
<button class="layui-btn layui-btn-normal" id="export-segment-btn">
<i class="layui-icon layui-icon-export"></i> 导出物资区间费用表
</button>
<button class="layui-btn layui-btn-primary" id="export-cost-btn">
<i class="layui-icon layui-icon-export"></i> 导出费用计算表
</button>
<button class="layui-btn layui-btn-primary" id="export-record-btn">
<i class="layui-icon layui-icon-export"></i> 导出领退记录表
</button>
</div>
</div>
</div>
@ -205,23 +246,23 @@
elem: '#calculation-table',
data: details,
cols: [[
{field: 'machineTypeName', title: '物资名称', minWidth: 160},
{field: 'machineModel', title: '规格型号', minWidth: 120},
{field: 'machineUnit', title: '单位', width: 80},
{field: 'currentCount', title: '未退还数量', width: 100},
{field: 'price', title: '单价(元/天)', width: 100, templet: function(d){
{field: 'machineTypeName', title: '物资名称', width: 180},
{field: 'machineModel', title: '规格型号', width: 150},
{field: 'machineUnit', title: '单位', width: 100},
{field: 'currentCount', title: '未退还数量', width: 120},
{field: 'price', title: '单价(元/天)', width: 120, templet: function(d){
return d.price ? d.price.toFixed(2) : '0.00';
}},
{field: 'firstLeaseTime', title: '首次领料时间', minWidth: 160, templet: function(d){
{field: 'firstLeaseTime', title: '首次领料时间', width: 180, templet: function(d){
return d.firstLeaseTime || '--';
}},
{field: 'lastReturnTime', title: '最后退料时间', minWidth: 160, templet: function(d){
{field: 'lastReturnTime', title: '最后退料时间', width: 180, templet: function(d){
return d.lastReturnTime || '--';
}},
{field: 'amount', title: '金额(元)', width: 100, style: 'color: #FF5722; font-weight: bold;', templet: function(d){
{field: 'amount', title: '金额(元)', width: 120, style: 'color: #FF5722; font-weight: bold;', templet: function(d){
return d.amount ? d.amount.toFixed(2) : '0.00';
}},
{title: '操作', width: 90, templet: function(d){
{title: '操作', width: 100, templet: function(d){
return '<a class="layui-btn layui-btn-xs" lay-event="viewDetail">查看明细</a>';
}}
]],
@ -262,7 +303,7 @@
area: ['800px', '500px'],
success: function(layero, index){
let i;
// 初始化Tab
// 初始化Tab
element.render('tab');
// 填充时段数据
@ -383,11 +424,6 @@
});
}
// 返回按钮
$('#back-btn').on('click', function(){
location.href = '${bonuspath}/backstage/projectCost/list';
});
// 打印按钮
$('#print-btn').on('click', function(){
window.print();

View File

@ -20,6 +20,10 @@
.layui-form-item .layui-input-inline {
width: 180px;
}
/* 工程名称下拉框加宽 */
.project-select-width {
width: 400px !important;
}
.filter-row {
display: flex;
align-items: center;
@ -68,8 +72,8 @@
<div class="filter-row">
<div class="filter-item">
<div class="filter-label">工程名称</div>
<div class="layui-input-inline">
<select name="projectId" lay-verify="required" lay-filter="projectSelect">
<div class="layui-input-inline project-select-width">
<select name="projectId" lay-verify="required" lay-filter="projectSelect" lay-search="">
<option value="">请选择工程</option>
</select>
</div>

View File

@ -15,91 +15,200 @@
<link rel="stylesheet" href="${bonuspath}/static/css/admin.css" media="all">
<link rel="stylesheet" href="${bonuspath}/static/css/common.css" media="all">
<style>
/* 优化筛选区域和按钮布局 */
/* 页面整体布局 */
.layui-card {
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
/* 搜索栏区域样式 */
.search-bar-wrapper {
padding: 20px;
border-radius: 6px 6px 0 0;
margin-bottom: 0;
}
.filter-area {
padding: 10px 15px;
display: flex;
align-items: center;
flex-wrap: wrap;
background-color: #fff;
gap: 15px;
}
.filter-item {
margin-right: 10px;
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.95);
padding: 8px 15px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.filter-label {
width: auto;
padding-right: 8px;
font-weight: 500;
font-weight: 600;
color: #333;
margin-right: 10px;
white-space: nowrap;
font-size: 14px;
}
.filter-buttons {
margin-left: auto;
white-space: nowrap;
.filter-item .layui-input {
border: 1px solid #e6e6e6;
border-radius: 3px;
transition: all 0.3s;
}
.filter-item .layui-input:focus {
border-color: #1E9FFF;
box-shadow: 0 0 5px rgba(30, 159, 255, 0.3);
}
.layui-input-inline-auto {
width: auto;
min-width: 120px;
min-width: 180px;
}
.layui-input-inline-date {
width: 120px;
width: 140px;
}
.layui-form-mid {
color: white;
font-weight: bold;
padding: 0 8px;
}
/* 按钮区域样式 */
.filter-buttons {
margin-left: auto;
display: flex;
gap: 10px;
}
.filter-buttons .layui-btn {
border-radius: 4px;
padding: 0 20px;
height: 38px;
line-height: 38px;
font-weight: 500;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
transition: all 0.3s;
}
.filter-buttons .layui-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.filter-buttons .layui-btn i {
margin-right: 4px;
}
/* 表格区域样式 */
.table-wrapper {
background: white;
padding: 20px;
border-radius: 0 0 6px 6px;
border-top: 3px solid #f0f0f0;
}
.layui-card-body {
padding: 0;
}
/* 表格操作按钮优化 */
.layui-table-view .layui-btn-xs {
padding: 0 10px;
height: 28px;
line-height: 28px;
border-radius: 3px;
}
/* 响应式布局 */
@media screen and (max-width: 768px) {
.search-bar-wrapper {
padding: 15px;
}
.filter-area {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.filter-item {
width: 100%;
flex-direction: column;
align-items: flex-start;
}
.filter-item {
margin-bottom: 10px;
.filter-label {
margin-bottom: 5px;
}
.layui-input-inline-auto,
.layui-input-inline-date {
width: 100%;
}
.filter-buttons {
margin-left: 0;
margin-top: 10px;
width: 100%;
display: flex;
justify-content: space-between;
}
.filter-buttons .layui-btn {
flex: 1;
}
}
</style>
</head>
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-form filter-area">
<div class="filter-item">
<div class="filter-label">工程名称</div>
<div class="layui-input-inline layui-input-inline-auto">
<input type="text" name="projectName" placeholder="请输入工程名称" autocomplete="off" class="layui-input">
<!-- 搜索栏区域 -->
<div class="search-bar-wrapper">
<div class="layui-form filter-area">
<div class="filter-item">
<div class="filter-label">工程名称</div>
<div class="layui-input-inline layui-input-inline-auto">
<input type="text" name="projectName" placeholder="请输入工程名称" autocomplete="off" class="layui-input">
</div>
</div>
</div>
<div class="filter-item">
<div class="filter-label">计算日期</div>
<div class="layui-input-inline layui-input-inline-date">
<input type="text" name="startDate" id="startDate" placeholder="开始日期" autocomplete="off" class="layui-input">
<div class="filter-item">
<div class="filter-label">计算日期</div>
<div class="layui-input-inline layui-input-inline-date">
<input type="text" name="startDate" id="startDate" placeholder="开始日期" autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid">-</div>
<div class="layui-input-inline layui-input-inline-date">
<input type="text" name="endDate" id="endDate" placeholder="结束日期" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-mid">-</div>
<div class="layui-input-inline layui-input-inline-date">
<input type="text" name="endDate" id="endDate" placeholder="结束日期" autocomplete="off" class="layui-input">
<div class="filter-buttons">
<button class="layui-btn" lay-submit lay-filter="LAY-project-cost-search">
<i class="layui-icon layui-icon-search"></i> 搜索
</button>
<button class="layui-btn layui-btn-normal" data-type="add">
<i class="layui-icon layui-icon-add-1"></i> 新增结算单
</button>
</div>
</div>
<div class="filter-buttons">
<button class="layui-btn layui-btn-sm" lay-submit lay-filter="LAY-project-cost-search">
<i class="layui-icon layui-icon-search"></i> 搜索
</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" data-type="add">
<i class="layui-icon layui-icon-add-1"></i> 新增结算单
</button>
</div>
</div>
<div class="layui-card-body">
<table id="LAY-project-cost-list" lay-filter="LAY-project-cost-list"></table>
<script type="text/html" id="table-project-cost-list">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="detail"><i class="layui-icon layui-icon-search"></i>查看</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete"><i class="layui-icon layui-icon-delete"></i>删除</a>
</script>
<!-- 表格区域 -->
<div class="table-wrapper">
<div class="layui-card-body">
<table id="LAY-project-cost-list" lay-filter="LAY-project-cost-list"></table>
<script type="text/html" id="table-project-cost-list">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="detail">
<i class="layui-icon layui-icon-search"></i> 查看
</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">
<i class="layui-icon layui-icon-delete"></i> 删除
</a>
</script>
</div>
</div>
</div>
</div>
@ -139,7 +248,7 @@
$('.layui-btn[data-type="add"]').on('click', function(){
layer.open({
type: 2,
title: '新增计算结果',
title: '机具费用结算单',
content: '${bonuspath}/backstage/projectCost/calculation_form',
area: ['90%', '90%'],
maxmin: false

View File

@ -19,6 +19,7 @@ import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -115,7 +116,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
/**
* 安全转换为String类型
*
*
* @param obj 要转换的对象
* @param defaultValue 默认值
* @return 转换后的String值
@ -132,6 +133,38 @@ public class ProjectCostServiceImpl implements ProjectCostService {
return String.valueOf(obj);
}
/**
* 格式化日期时间字符串只保留年月日部分
*
* @param dateTimeStr 日期时间字符串格式如 "2025-04-02T09:41:13" "2025-04-02 09:41:13"
* @return 格式化后的日期字符串格式为 "2025-04-02"
*/
private String formatDateOnly(String dateTimeStr) {
if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
return "";
}
try {
// 如果包含 'T'说明是 ISO 格式2025-04-02T09:41:13
if (dateTimeStr.contains("T")) {
// 直接截取 'T' 之前的部分
return dateTimeStr.substring(0, dateTimeStr.indexOf("T"));
}
// 如果包含空格说明是标准格式2025-04-02 09:41:13
else if (dateTimeStr.contains(" ")) {
// 直接截取空格之前的部分
return dateTimeStr.substring(0, dateTimeStr.indexOf(" "));
}
// 如果已经是日期格式2025-04-02直接返回
else {
return dateTimeStr;
}
} catch (Exception e) {
// 如果格式化失败返回原字符串
return dateTimeStr;
}
}
@Override
public List<ProjectLeaseCostDetail> queryProjectLeaseDetails(ProjectLeaseCostDetail o) {
return projectCostDao.queryProjectLeaseDetails(o);
@ -347,28 +380,34 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if (currentCount > 0 && !previousTime.equals(operateTime)) {
// 计算两个时间点之间的天数
long daysBetween = java.time.Duration.between(previousTime, operateTime).toDays();
// 不足一天按一天计算
if (daysBetween < 1) {
daysBetween = 1;
// 如果天数为0开始时间等于结束时间跳过这个时间段
if (daysBetween == 0) {
System.out.println("跳过无效时间段: " + previousTime + "" + operateTime + " (开始时间等于结束时间)");
} else {
// 不足一天按一天计算
if (daysBetween < 1) {
daysBetween = 1;
}
// 计算该时间段的租赁费用
double segmentAmount = currentCount * unitPrice * daysBetween;
totalItemAmount += segmentAmount;
// 记录该时间段
Map<String, Object> segment = new HashMap<>();
segment.put("startTime", previousTime.toString());
segment.put("endTime", operateTime.toString());
segment.put("days", daysBetween);
segment.put("count", currentCount);
segment.put("amount", segmentAmount);
segments.add(segment);
// 添加调试信息
System.out.println("物资ID: " + machineTypeId + ", 时段: " + previousTime + "" + operateTime
+ ", 天数: " + daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: "
+ segmentAmount);
}
// 计算该时间段的租赁费用
double segmentAmount = currentCount * unitPrice * daysBetween;
totalItemAmount += segmentAmount;
// 记录该时间段
Map<String, Object> segment = new HashMap<>();
segment.put("startTime", previousTime.toString());
segment.put("endTime", operateTime.toString());
segment.put("days", daysBetween);
segment.put("count", currentCount);
segment.put("amount", segmentAmount);
segments.add(segment);
// 添加调试信息
System.out.println("物资ID: " + machineTypeId + ", 时段: " + previousTime + "" + operateTime
+ ", 天数: " + daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: "
+ segmentAmount);
}
// 更新当前在用数量
@ -399,27 +438,33 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if (currentCount > 0 && !previousTime.equals(endDate)) {
// 计算两个时间点之间的天数
long daysBetween = java.time.Duration.between(previousTime, endDate).toDays();
// 不足一天按一天计算
if (daysBetween < 1) {
daysBetween = 1;
// 如果天数为0开始时间等于结束时间跳过这个时间段
if (daysBetween == 0) {
System.out.println("跳过无效时间段: " + previousTime + "" + endDate + " (开始时间等于结束时间)");
} else {
// 不足一天按一天计算
if (daysBetween < 1) {
daysBetween = 1;
}
// 计算该时间段的租赁费用
double segmentAmount = currentCount * unitPrice * daysBetween;
totalItemAmount += segmentAmount;
// 记录该时间段
Map<String, Object> segment = new HashMap<>();
segment.put("startTime", previousTime.toString());
segment.put("endTime", endDate.toString());
segment.put("days", daysBetween);
segment.put("count", currentCount);
segment.put("amount", segmentAmount);
segments.add(segment);
// 添加调试信息
System.out.println("物资ID: " + machineTypeId + ", 时段: " + previousTime + "" + endDate + ", 天数: "
+ daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: " + segmentAmount);
}
// 计算该时间段的租赁费用
double segmentAmount = currentCount * unitPrice * daysBetween;
totalItemAmount += segmentAmount;
// 记录该时间段
Map<String, Object> segment = new HashMap<>();
segment.put("startTime", previousTime.toString());
segment.put("endTime", endDate.toString());
segment.put("days", daysBetween);
segment.put("count", currentCount);
segment.put("amount", segmentAmount);
segments.add(segment);
// 添加调试信息
System.out.println("物资ID: " + machineTypeId + ", 时段: " + previousTime + "" + endDate + ", 天数: "
+ daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: " + segmentAmount);
}
// 更新总金额
@ -913,16 +958,16 @@ public class ProjectCostServiceImpl implements ProjectCostService {
String fileName = "物资区间费用表_" + calculation.getProjectName() + "_" + calculation.getId() + ".xls";
String sheetName = "物资区间费用表";
// 表头 - 增加工程名称规格型号故障停用天数扣减费用字段
String[] headers = { "序号", "工程名称", "物资类型", "规格型号", "起始时间", "截止时间", "租赁天数(天)", "数量", "金额(元)", "因故障造成的停用天数",
// 表头 - 增加工程名称规格型号每日单价故障停用天数扣减费用字段
String[] headers = { "序号", "工程名称", "物资类型", "规格型号", "起始时间", "截止时间", "租赁天数(天)", "数量", "每日单价(元/天)", "金额(元)", "因故障造成的停用天数",
"扣减费用(元)" };
// 列宽 - 调整并新增字段宽度
int[] widths = { 256 * 6, 256 * 60, 256 * 20, 256 * 16, 256 * 22, 256 * 22, 256 * 16, 256 * 10, 256 * 12,
int[] widths = { 256 * 6, 256 * 60, 256 * 20, 256 * 16, 256 * 22, 256 * 22, 256 * 16, 256 * 10, 256 * 14, 256 * 12,
256 * 22, 256 * 16 };
// 数据格式1:String left; 2:String center; 3:String right; 4:int right; 5:float
// right
int[] formats = { 4, 2, 2, 2, 2, 2, 4, 4, 5, 4, 5 };
int[] formats = { 4, 2, 2, 2, 2, 2, 4, 4, 5, 5, 4, 5 };
// 准备数据
List<Map<String, Object>> dataList = new ArrayList<>();
@ -939,10 +984,12 @@ public class ProjectCostServiceImpl implements ProjectCostService {
row.put("工程名称", calculation.getProjectName()); // 添加工程名称字段
row.put("物资类型", detail.getMachineTypeName());
row.put("规格型号", detail.getMachineModel()); // 添加规格型号字段
row.put("起始时间", segment.getStartTime());
row.put("截止时间", segment.getEndTime());
// 格式化时间只保留年月日
row.put("起始时间", formatDateOnly(segment.getStartTime()));
row.put("截止时间", formatDateOnly(segment.getEndTime()));
row.put("租赁天数(天)", segment.getDays());
row.put("数量", segment.getCount());
row.put("每日单价(元/天)", detail.getPrice()); // 添加每日单价字段
row.put("金额(元)", segment.getAmount());
row.put("因故障造成的停用天数", 0); // 默认为0天
row.put("扣减费用(元)", 0.00); // 默认为0.00元
@ -952,24 +999,27 @@ public class ProjectCostServiceImpl implements ProjectCostService {
}
}
// 调用带签名区域的导出方法
exportSegmentExcelWithSignature(fileName, sheetName, headers, widths, formats, dataList, response);
// 调用带签名区域的导出方法传递工程名称和制单时间
exportSegmentExcelWithSignature(fileName, sheetName, headers, widths, formats, dataList,
calculation.getProjectName(), calculation.getCreateTime(), response);
}
/**
* 封装导出带签名区域的Excel方法专用于物资区间费用表
*
* @param fileName 文件名
* @param sheetName sheet名称
* @param headers 表头
* @param widths 列宽
* @param formats 数据格式
* @param dataList 数据列表
* @param response HttpServletResponse对象
*
* @param fileName 文件名
* @param sheetName sheet名称
* @param headers 表头
* @param widths 列宽
* @param formats 数据格式
* @param dataList 数据列表
* @param projectName 工程名称
* @param createTime 制单时间
* @param response HttpServletResponse对象
* @throws Exception 导出异常
*/
private void exportSegmentExcelWithSignature(String fileName, String sheetName, String[] headers, int[] widths, int[] formats,
List<Map<String, Object>> dataList, javax.servlet.http.HttpServletResponse response) throws Exception {
List<Map<String, Object>> dataList, String projectName, String createTime, javax.servlet.http.HttpServletResponse response) throws Exception {
try {
// 设置文件名
String filename = "";
@ -989,8 +1039,90 @@ public class ProjectCostServiceImpl implements ProjectCostService {
// 创建一个sheet
HSSFSheet sheet = wb.createSheet(sheetName);
// 创建表头
int currentRowIndex = 0;
// 创建第一行标题贵州送变电智联装备云控公司设备及工器具产值明细确认单
HSSFRow titleRow = sheet.createRow(currentRowIndex);
titleRow.setHeight((short) 600); // 设置标题行高度
// 标题样式
HSSFCellStyle titleStyle = wb.createCellStyle();
HSSFFont titleFont = wb.createFont();
titleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
titleFont.setFontName("微软雅黑");
titleFont.setFontHeightInPoints((short) 14); // 标题字体稍大
titleStyle.setFont(titleFont);
titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平居中
titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
// 创建第一个单元格并设置标题内容
HSSFCell titleCell = titleRow.createCell(0);
titleCell.setCellValue("贵州送变电智联装备云控公司(设备及工器具)产值明细确认单");
titleCell.setCellStyle(titleStyle);
// 合并单元格从第0列到最后一列headers.length - 1
if (headers != null && headers.length > 1) {
org.apache.poi.ss.util.CellRangeAddress titleRegion = new org.apache.poi.ss.util.CellRangeAddress(
currentRowIndex, // 起始行
currentRowIndex, // 结束行
0, // 起始列
headers.length - 1 // 结束列
);
sheet.addMergedRegion(titleRegion);
}
currentRowIndex++;
// 创建第二行工程名称和制单时间
HSSFRow infoRow = sheet.createRow(currentRowIndex);
infoRow.setHeight((short) 400); // 设置信息行高度
// 信息行样式
HSSFCellStyle infoStyle = wb.createCellStyle();
HSSFFont infoFont = wb.createFont();
infoFont.setFontName("微软雅黑");
infoFont.setFontHeightInPoints((short) 11);
infoStyle.setFont(infoFont);
infoStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
// 计算中间列位置用于分隔左右两列
int midColumn = headers.length / 2;
// 左侧列工程名称
HSSFCell projectNameCell = infoRow.createCell(0);
projectNameCell.setCellValue("工程名称:" + projectName);
projectNameCell.setCellStyle(infoStyle);
// 合并左侧单元格从第0列到中间列-1
if (midColumn > 1) {
org.apache.poi.ss.util.CellRangeAddress leftRegion = new org.apache.poi.ss.util.CellRangeAddress(
currentRowIndex, // 起始行
currentRowIndex, // 结束行
0, // 起始列
midColumn - 1 // 结束列
);
sheet.addMergedRegion(leftRegion);
}
// 右侧列制单时间
HSSFCell createTimeCell = infoRow.createCell(midColumn);
// 格式化制单时间只保留年月日
String formattedCreateTime = formatDateOnly(createTime);
createTimeCell.setCellValue("制单时间:" + formattedCreateTime);
createTimeCell.setCellStyle(infoStyle);
// 合并右侧单元格从中间列到最后一列
if (midColumn < headers.length - 1) {
org.apache.poi.ss.util.CellRangeAddress rightRegion = new org.apache.poi.ss.util.CellRangeAddress(
currentRowIndex, // 起始行
currentRowIndex, // 结束行
midColumn, // 起始列
headers.length - 1 // 结束列
);
sheet.addMergedRegion(rightRegion);
}
currentRowIndex++;
// 创建表头
if (headers != null) {
HSSFRow row = sheet.createRow(currentRowIndex);
// 设置表头行高 - 调高表头高度