结算修改

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/

View File

@ -11,7 +11,8 @@
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no,maximum-scale=1.0,minimum-scale=1.0"> <meta name="viewport"
content="width=device-width,initial-scale=1.0,user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
<title>贵送机具管理系统 - 登录</title> <title>贵送机具管理系统 - 登录</title>
<% <%
@ -71,58 +72,83 @@ function showAgreement() {
<div style="color: #333; line-height: 1.6;"> <div style="color: #333; line-height: 1.6;">
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">一、引言</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">一、引言</h4>
<p style="margin-bottom: 10px;">鉴于个人信息和隐私保护的重要性,以及我们对您个人信息和隐私的尊重,我们制定了本《个人信息和隐私保护协议》(以下简称"本协议")。本协议旨在明确我们对您个人信息和隐私的收集、使用、存储、传输和删除等方面的规定,以确保您的个人信息和隐私得到妥善保护。</p> <p style="margin-bottom: 10px;">
鉴于个人信息和隐私保护的重要性,以及我们对您个人信息和隐私的尊重,我们制定了本《个人信息和隐私保护协议》(以下简称"本协议")。本协议旨在明确我们对您个人信息和隐私的收集、使用、存储、传输和删除等方面的规定,以确保您的个人信息和隐私得到妥善保护。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">二、协议适用说明</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">二、协议适用说明</h4>
<p style="margin-bottom: 10px;">1. 个人信息:指能够单独或与其他信息结合后识别特定自然人身份的信息,包括但不限于姓名、性别、出生日期、身份证号、联系方式、家庭住址等。</p> <p style="margin-bottom: 10px;">1.
<p style="margin-bottom: 10px;">2. 隐私安全:指个人在特定社会关系中,享有私人生活,不愿公开的个人信息和私人事务。</p> 个人信息:指能够单独或与其他信息结合后识别特定自然人身份的信息,包括但不限于姓名、性别、出生日期、身份证号、联系方式、家庭住址等。</p>
<p style="margin-bottom: 10px;">3. 适用范围:本协议适用于我们对您个人信息和隐私的保护,包括我们收集、使用、存储、传输和删除您的个人信息和隐私。</p> <p style="margin-bottom: 10px;">2.
隐私安全:指个人在特定社会关系中,享有私人生活,不愿公开的个人信息和私人事务。</p>
<p style="margin-bottom: 10px;">3.
适用范围:本协议适用于我们对您个人信息和隐私的保护,包括我们收集、使用、存储、传输和删除您的个人信息和隐私。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">三、信息收集</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">三、信息收集</h4>
<p style="margin-bottom: 10px;">1. 合法性原则:我们将遵循合法性原则,仅在您同意或法律允许的情况下收集您的个人信息和隐私。</p> <p style="margin-bottom: 10px;">1.
<p style="margin-bottom: 10px;">2. 必要性原则:我们将遵循必要性原则,仅收集与实现我们的服务目的直接相关的信息。</p> 合法性原则:我们将遵循合法性原则,仅在您同意或法律允许的情况下收集您的个人信息和隐私。</p>
<p style="margin-bottom: 10px;">3. 透明性原则:我们将遵循透明性原则,向您公开我们收集的个人信息和隐私的种类、目的和使用方式。</p> <p style="margin-bottom: 10px;">2.
必要性原则:我们将遵循必要性原则,仅收集与实现我们的服务目的直接相关的信息。</p>
<p style="margin-bottom: 10px;">3.
透明性原则:我们将遵循透明性原则,向您公开我们收集的个人信息和隐私的种类、目的和使用方式。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">四、信息使用</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">四、信息使用</h4>
<p style="margin-bottom: 10px;">1. 合法使用:我们将仅在法律允许或您同意的情况下使用您的个人信息和隐私。</p> <p style="margin-bottom: 10px;">1.
<p style="margin-bottom: 10px;">2. 正当使用:我们将遵循正当使用原则,确保使用您的个人信息和隐私是为了实现我们的服务目的,并且不会损害您的合法权益。</p> 合法使用:我们将仅在法律允许或您同意的情况下使用您的个人信息和隐私。</p>
<p style="margin-bottom: 10px;">3. 透明使用:我们将遵循透明使用原则,向您公开我们使用您的个人信息和隐私的具体情况。</p> <p style="margin-bottom: 10px;">2.
正当使用:我们将遵循正当使用原则,确保使用您的个人信息和隐私是为了实现我们的服务目的,并且不会损害您的合法权益。</p>
<p style="margin-bottom: 10px;">3.
透明使用:我们将遵循透明使用原则,向您公开我们使用您的个人信息和隐私的具体情况。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">五、信息存储与传输</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">五、信息存储与传输</h4>
<p style="margin-bottom: 10px;">1. 安全存储:我们将采取必要的技术和组织措施,确保您的个人信息和隐私得到安全存储。</p> <p style="margin-bottom: 10px;">1.
<p style="margin-bottom: 10px;">2. 加密传输:我们将对您的个人信息和隐私进行加密传输,以确保数据传输过程中的安全性。</p> 安全存储:我们将采取必要的技术和组织措施,确保您的个人信息和隐私得到安全存储。</p>
<p style="margin-bottom: 10px;">3. 访问控制:我们将严格控制对您的个人信息和隐私的访问权限,确保只有授权人员才能访问相关信息。</p> <p style="margin-bottom: 10px;">2.
<p style="margin-bottom: 10px;">4. 定期审计:为您提供安全保障,个人信息处理者应当定期对其处理个人信息遵守法律、行政法规的情况进行合规审计。</p> 加密传输:我们将对您的个人信息和隐私进行加密传输,以确保数据传输过程中的安全性。</p>
<p style="margin-bottom: 10px;">3.
访问控制:我们将严格控制对您的个人信息和隐私的访问权限,确保只有授权人员才能访问相关信息。</p>
<p style="margin-bottom: 10px;">4.
定期审计:为您提供安全保障,个人信息处理者应当定期对其处理个人信息遵守法律、行政法规的情况进行合规审计。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">六、信息删除与注销</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">六、信息删除与注销</h4>
<p style="margin-bottom: 10px;">1. 删除原则:我们将遵循删除原则,确保在达到收集目的后或您要求删除时,及时删除您的个人信息和隐私。</p> <p style="margin-bottom: 10px;">1.
<p style="margin-bottom: 10px;">2. 注销权利:您有权要求我们注销您的个人信息和隐私,我们将在收到您的请求后尽快处理。</p> 删除原则:我们将遵循删除原则,确保在达到收集目的后或您要求删除时,及时删除您的个人信息和隐私。</p>
<p style="margin-bottom: 10px;">3. 在不幸发生个人信息安全事件后,我们将按照法律法规的要求向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等。</p> <p style="margin-bottom: 10px;">2.
注销权利:您有权要求我们注销您的个人信息和隐私,我们将在收到您的请求后尽快处理。</p>
<p style="margin-bottom: 10px;">3.
在不幸发生个人信息安全事件后,我们将按照法律法规的要求向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">七、违约责任</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">七、违约责任</h4>
<p style="margin-bottom: 10px;">1. 违反本协议规定的,我们将依法承担相应的法律责任。</p> <p style="margin-bottom: 10px;">1. 违反本协议规定的,我们将依法承担相应的法律责任。</p>
<p style="margin-bottom: 10px;">2. 您违反本协议规定的,我们将有权依法追究您的法律责任。</p> <p style="margin-bottom: 10px;">2. 您违反本协议规定的,我们将有权依法追究您的法律责任。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">八、如何保护你的信息</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">八、如何保护你的信息</h4>
<p style="margin-bottom: 10px;">(一)我们已采取符合业界标准、合理可行的安全防护措施保护您的信息,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。</p> <p style="margin-bottom: 10px;">
<p style="margin-bottom: 10px;">(二)我们有行业先进的以数据为核心,围绕数据生命周期进行的数据安全管理体系,从组织建设、制度设计、人员管理、产品技术等方面多维度提升整个系统的安全性。</p> (一)我们已采取符合业界标准、合理可行的安全防护措施保护您的信息,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。</p>
<p style="margin-bottom: 10px;">
(二)我们有行业先进的以数据为核心,围绕数据生命周期进行的数据安全管理体系,从组织建设、制度设计、人员管理、产品技术等方面多维度提升整个系统的安全性。</p>
<p style="margin-bottom: 10px;">(三)我们会采取合理可行的措施,尽力避免收集无关的个人信息。</p> <p style="margin-bottom: 10px;">(三)我们会采取合理可行的措施,尽力避免收集无关的个人信息。</p>
<p style="margin-bottom: 10px;">(四)互联网并非绝对安全的环境,使用服务时,我们强烈建议通过安全方式、使用复杂密码,协助我们保证您的账号安全。</p> <p style="margin-bottom: 10px;">
(四)互联网并非绝对安全的环境,使用服务时,我们强烈建议通过安全方式、使用复杂密码,协助我们保证您的账号安全。</p>
<p style="margin-bottom: 10px;">(五)在不幸发生个人信息安全事件后,我们将按照法律法规的要求及时告知您。</p> <p style="margin-bottom: 10px;">(五)在不幸发生个人信息安全事件后,我们将按照法律法规的要求及时告知您。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">九、我们如何更新本政策</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">九、我们如何更新本政策</h4>
<p style="margin-bottom: 10px;">1. 为给您提供更好的服务,本应用的产品与服务将不时更新与变化,我们会适时对本协议进行修订。</p> <p style="margin-bottom: 10px;">1.
为给您提供更好的服务,本应用的产品与服务将不时更新与变化,我们会适时对本协议进行修订。</p>
<p style="margin-bottom: 10px;">2. 本协议更新后,我们会在本应用中发出更新版本,并以弹窗的方式提醒您。</p> <p style="margin-bottom: 10px;">2. 本协议更新后,我们会在本应用中发出更新版本,并以弹窗的方式提醒您。</p>
<p style="margin-bottom: 10px;">3. 对于重大变更,我们还会提供更为显著的通知。</p> <p style="margin-bottom: 10px;">3. 对于重大变更,我们还会提供更为显著的通知。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">十、我们如何委托处理、共享、转让、公开披露您的个人信息</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">
<p style="margin-bottom: 10px;">1. 委托处理:为了向您提供更完善、更优质的产品和服务,我们可能会委托合作方处理您的某些个人信息。</p> 十、我们如何委托处理、共享、转让、公开披露您的个人信息</h4>
<p style="margin-bottom: 10px;">2. 共享:在本应用进行用户注册时,您的账号注册信息会在相关政务服务系统间共享。</p> <p style="margin-bottom: 10px;">1.
委托处理:为了向您提供更完善、更优质的产品和服务,我们可能会委托合作方处理您的某些个人信息。</p>
<p style="margin-bottom: 10px;">2.
共享:在本应用进行用户注册时,您的账号注册信息会在相关政务服务系统间共享。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">十一、其他条款</h4> <h4 style="color: #333; font-size: 16px; margin: 15px 0;">十一、其他条款</h4>
<p style="margin-bottom: 10px;">1. 本协议自双方签字或盖章之日起生效。</p> <p style="margin-bottom: 10px;">1. 本协议自双方签字或盖章之日起生效。</p>
<p style="margin-bottom: 10px;">2. 本协议一式两份,双方各执一份。</p> <p style="margin-bottom: 10px;">2. 本协议一式两份,双方各执一份。</p>
<p style="margin-bottom: 10px;">3. 本协议未尽事宜,由双方另行协商确定。如有任何疑问或需要进一步了解,请随时联系我们。</p> <p style="margin-bottom: 10px;">3.
本协议未尽事宜,由双方另行协商确定。如有任何疑问或需要进一步了解,请随时联系我们。</p>
</div> </div>
</div> </div>
</script> </script>
@ -225,8 +251,12 @@ body::before {
} }
@keyframes rotate { @keyframes rotate {
0% { transform: rotate(0deg); } 0% {
100% { transform: rotate(360deg); } transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
} }
.logo-container { .logo-container {
@ -513,11 +543,25 @@ body::before {
transform: translateY(30px); transform: translateY(30px);
} }
.form-group:nth-child(1) { animation-delay: 0.1s; } .form-group:nth-child(1) {
.form-group:nth-child(2) { animation-delay: 0.2s; } animation-delay: 0.1s;
.form-group:nth-child(3) { animation-delay: 0.3s; } }
.form-group:nth-child(4) { animation-delay: 0.4s; }
.form-group:nth-child(5) { animation-delay: 0.5s; } .form-group:nth-child(2) {
animation-delay: 0.2s;
}
.form-group:nth-child(3) {
animation-delay: 0.3s;
}
.form-group:nth-child(4) {
animation-delay: 0.4s;
}
.form-group:nth-child(5) {
animation-delay: 0.5s;
}
@keyframes slideInUp { @keyframes slideInUp {
to { to {
@ -554,8 +598,12 @@ body::before {
} }
@keyframes spin { @keyframes spin {
0% { transform: rotate(0deg); } 0% {
100% { transform: rotate(360deg); } transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
} }
/* Focus indicators for accessibility */ /* Focus indicators for accessibility */
@ -694,7 +742,8 @@ body::before {
> >
记住密码 记住密码
</label> </label>
<a style="display: none ;" href="javascript:void(0)" class="forgot-password" onclick="showForgotPassword()" <a style="display: none ;" href="javascript:void(0)" class="forgot-password"
onclick="showForgotPassword()"
role="button" aria-label="忘记密码">忘记密码?</a> role="button" aria-label="忘记密码">忘记密码?</a>
</div> </div>
</div> </div>
@ -1007,7 +1056,6 @@ body::before {
} }
// 清除所有错误消息 // 清除所有错误消息
function hideAllErrors() { function hideAllErrors() {
$('.error-message').removeClass('show'); $('.error-message').removeClass('show');

View File

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

View File

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

View File

@ -15,58 +15,159 @@
<link rel="stylesheet" href="${bonuspath}/static/css/admin.css" media="all"> <link rel="stylesheet" href="${bonuspath}/static/css/admin.css" media="all">
<link rel="stylesheet" href="${bonuspath}/static/css/common.css" media="all"> <link rel="stylesheet" href="${bonuspath}/static/css/common.css" media="all">
<style> <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 { .filter-area {
padding: 10px 15px;
display: flex; display: flex;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
background-color: #fff; gap: 15px;
} }
.filter-item { .filter-item {
margin-right: 10px;
display: flex; display: flex;
align-items: center; 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 { .filter-label {
width: auto; font-weight: 600;
padding-right: 8px; color: #333;
font-weight: 500; margin-right: 10px;
white-space: nowrap; white-space: nowrap;
font-size: 14px;
} }
.filter-buttons {
margin-left: auto; .filter-item .layui-input {
white-space: nowrap; 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 { .layui-input-inline-auto {
width: auto; width: auto;
min-width: 120px; min-width: 180px;
} }
.layui-input-inline-date { .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) { @media screen and (max-width: 768px) {
.search-bar-wrapper {
padding: 15px;
}
.filter-area { .filter-area {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.filter-item {
width: 100%;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
} }
.filter-item {
margin-bottom: 10px; .filter-label {
margin-bottom: 5px;
}
.layui-input-inline-auto,
.layui-input-inline-date {
width: 100%; width: 100%;
} }
.filter-buttons { .filter-buttons {
margin-left: 0; margin-left: 0;
margin-top: 10px;
width: 100%; width: 100%;
display: flex;
justify-content: space-between; justify-content: space-between;
} }
.filter-buttons .layui-btn {
flex: 1;
}
} }
</style> </style>
</head> </head>
<body> <body>
<div class="layui-fluid"> <div class="layui-fluid">
<div class="layui-card"> <div class="layui-card">
<!-- 搜索栏区域 -->
<div class="search-bar-wrapper">
<div class="layui-form filter-area"> <div class="layui-form filter-area">
<div class="filter-item"> <div class="filter-item">
<div class="filter-label">工程名称</div> <div class="filter-label">工程名称</div>
@ -85,24 +186,32 @@
</div> </div>
</div> </div>
<div class="filter-buttons"> <div class="filter-buttons">
<button class="layui-btn layui-btn-sm" lay-submit lay-filter="LAY-project-cost-search"> <button class="layui-btn" lay-submit lay-filter="LAY-project-cost-search">
<i class="layui-icon layui-icon-search"></i> 搜索 <i class="layui-icon layui-icon-search"></i> 搜索
</button> </button>
<button class="layui-btn layui-btn-sm layui-btn-normal" data-type="add"> <button class="layui-btn layui-btn-normal" data-type="add">
<i class="layui-icon layui-icon-add-1"></i> 新增结算单 <i class="layui-icon layui-icon-add-1"></i> 新增结算单
</button> </button>
</div> </div>
</div> </div>
</div>
<!-- 表格区域 -->
<div class="table-wrapper">
<div class="layui-card-body"> <div class="layui-card-body">
<table id="LAY-project-cost-list" lay-filter="LAY-project-cost-list"></table> <table id="LAY-project-cost-list" lay-filter="LAY-project-cost-list"></table>
<script type="text/html" id="table-project-cost-list"> <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-normal layui-btn-xs" lay-event="detail">
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete"><i class="layui-icon layui-icon-delete"></i>删除</a> <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> </script>
</div> </div>
</div> </div>
</div> </div>
</div>
<script src="${bonuspath}/static/js/layui/layui.js"></script> <script src="${bonuspath}/static/js/layui/layui.js"></script>
<script> <script>
// 先配置模块路径 // 先配置模块路径
@ -139,7 +248,7 @@
$('.layui-btn[data-type="add"]').on('click', function(){ $('.layui-btn[data-type="add"]').on('click', function(){
layer.open({ layer.open({
type: 2, type: 2,
title: '新增计算结果', title: '机具费用结算单',
content: '${bonuspath}/backstage/projectCost/calculation_form', content: '${bonuspath}/backstage/projectCost/calculation_form',
area: ['90%', '90%'], area: ['90%', '90%'],
maxmin: false 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.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -132,6 +133,38 @@ public class ProjectCostServiceImpl implements ProjectCostService {
return String.valueOf(obj); 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 @Override
public List<ProjectLeaseCostDetail> queryProjectLeaseDetails(ProjectLeaseCostDetail o) { public List<ProjectLeaseCostDetail> queryProjectLeaseDetails(ProjectLeaseCostDetail o) {
return projectCostDao.queryProjectLeaseDetails(o); return projectCostDao.queryProjectLeaseDetails(o);
@ -347,6 +380,11 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if (currentCount > 0 && !previousTime.equals(operateTime)) { if (currentCount > 0 && !previousTime.equals(operateTime)) {
// 计算两个时间点之间的天数 // 计算两个时间点之间的天数
long daysBetween = java.time.Duration.between(previousTime, operateTime).toDays(); long daysBetween = java.time.Duration.between(previousTime, operateTime).toDays();
// 如果天数为0开始时间等于结束时间跳过这个时间段
if (daysBetween == 0) {
System.out.println("跳过无效时间段: " + previousTime + "" + operateTime + " (开始时间等于结束时间)");
} else {
// 不足一天按一天计算 // 不足一天按一天计算
if (daysBetween < 1) { if (daysBetween < 1) {
daysBetween = 1; daysBetween = 1;
@ -370,6 +408,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
+ ", 天数: " + daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: " + ", 天数: " + daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: "
+ segmentAmount); + segmentAmount);
} }
}
// 更新当前在用数量 // 更新当前在用数量
if (isLease) { if (isLease) {
@ -399,6 +438,11 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if (currentCount > 0 && !previousTime.equals(endDate)) { if (currentCount > 0 && !previousTime.equals(endDate)) {
// 计算两个时间点之间的天数 // 计算两个时间点之间的天数
long daysBetween = java.time.Duration.between(previousTime, endDate).toDays(); long daysBetween = java.time.Duration.between(previousTime, endDate).toDays();
// 如果天数为0开始时间等于结束时间跳过这个时间段
if (daysBetween == 0) {
System.out.println("跳过无效时间段: " + previousTime + "" + endDate + " (开始时间等于结束时间)");
} else {
// 不足一天按一天计算 // 不足一天按一天计算
if (daysBetween < 1) { if (daysBetween < 1) {
daysBetween = 1; daysBetween = 1;
@ -421,6 +465,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
System.out.println("物资ID: " + machineTypeId + ", 时段: " + previousTime + "" + endDate + ", 天数: " System.out.println("物资ID: " + machineTypeId + ", 时段: " + previousTime + "" + endDate + ", 天数: "
+ daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: " + segmentAmount); + daysBetween + ", 数量: " + currentCount + ", 单价: " + unitPrice + ", 段金额: " + segmentAmount);
} }
}
// 更新总金额 // 更新总金额
totalAmount += totalItemAmount; totalAmount += totalItemAmount;
@ -913,16 +958,16 @@ public class ProjectCostServiceImpl implements ProjectCostService {
String fileName = "物资区间费用表_" + calculation.getProjectName() + "_" + calculation.getId() + ".xls"; String fileName = "物资区间费用表_" + calculation.getProjectName() + "_" + calculation.getId() + ".xls";
String sheetName = "物资区间费用表"; 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 }; 256 * 22, 256 * 16 };
// 数据格式1:String left; 2:String center; 3:String right; 4:int right; 5:float // 数据格式1:String left; 2:String center; 3:String right; 4:int right; 5:float
// right // 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<>(); List<Map<String, Object>> dataList = new ArrayList<>();
@ -939,10 +984,12 @@ public class ProjectCostServiceImpl implements ProjectCostService {
row.put("工程名称", calculation.getProjectName()); // 添加工程名称字段 row.put("工程名称", calculation.getProjectName()); // 添加工程名称字段
row.put("物资类型", detail.getMachineTypeName()); row.put("物资类型", detail.getMachineTypeName());
row.put("规格型号", detail.getMachineModel()); // 添加规格型号字段 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.getDays());
row.put("数量", segment.getCount()); row.put("数量", segment.getCount());
row.put("每日单价(元/天)", detail.getPrice()); // 添加每日单价字段
row.put("金额(元)", segment.getAmount()); row.put("金额(元)", segment.getAmount());
row.put("因故障造成的停用天数", 0); // 默认为0天 row.put("因故障造成的停用天数", 0); // 默认为0天
row.put("扣减费用(元)", 0.00); // 默认为0.00元 row.put("扣减费用(元)", 0.00); // 默认为0.00元
@ -952,8 +999,9 @@ 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);
} }
/** /**
@ -965,11 +1013,13 @@ public class ProjectCostServiceImpl implements ProjectCostService {
* @param widths 列宽 * @param widths 列宽
* @param formats 数据格式 * @param formats 数据格式
* @param dataList 数据列表 * @param dataList 数据列表
* @param projectName 工程名称
* @param createTime 制单时间
* @param response HttpServletResponse对象 * @param response HttpServletResponse对象
* @throws Exception 导出异常 * @throws Exception 导出异常
*/ */
private void exportSegmentExcelWithSignature(String fileName, String sheetName, String[] headers, int[] widths, int[] formats, 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 { try {
// 设置文件名 // 设置文件名
String filename = ""; String filename = "";
@ -989,8 +1039,90 @@ public class ProjectCostServiceImpl implements ProjectCostService {
// 创建一个sheet // 创建一个sheet
HSSFSheet sheet = wb.createSheet(sheetName); HSSFSheet sheet = wb.createSheet(sheetName);
// 创建表头
int currentRowIndex = 0; 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) { if (headers != null) {
HSSFRow row = sheet.createRow(currentRowIndex); HSSFRow row = sheet.createRow(currentRowIndex);
// 设置表头行高 - 调高表头高度 // 设置表头行高 - 调高表头高度