GZMachinesWeb/WebContent/static/js/projectCost/projectCost.js

1396 lines
138 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 项目结算模块
*/
layui.define(['table', 'form', 'layer'], function(exports){
var $ = layui.$,
table = layui.table,
form = layui.form,
layer = layui.layer;
var baseUrl = window.bonuspath || './';
// 设置Layui全局配置解决乱码问题
layui.config({
lang: 'zh-CN'
});
// 添加CSS修复乱码问题
(function fixLayuiCss() {
// 基本 CSS 样式
var style = document.createElement('style');
style.type = 'text/css';
var css = '.layui-laypage-skip em{font-style:normal !important;} ' +
'.layui-laydate-content td, .layui-laydate-content th{font-family:"Microsoft YaHei", sans-serif !important;} ' +
'.layui-laydate-footer span{font-family:"Microsoft YaHei", sans-serif !important;}';
if(style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
document.head.appendChild(style);
// 添加直接修复日期选择器显示的函数
window.fixDatepicker = function() {
setTimeout(function() {
try {
// 修复星期标题
$('.layui-laydate-content th').eq(0).text('日');
$('.layui-laydate-content th').eq(1).text('一');
$('.layui-laydate-content th').eq(2).text('二');
$('.layui-laydate-content th').eq(3).text('三');
$('.layui-laydate-content th').eq(4).text('四');
$('.layui-laydate-content th').eq(5).text('五');
$('.layui-laydate-content th').eq(6).text('六');
// 修复按钮提示文字
$('.laydate-prev-m').attr('title', '上个月');
$('.laydate-next-m').attr('title', '下个月');
$('.laydate-prev-y').attr('title', '上一年');
$('.laydate-next-y').attr('title', '下一年');
// 修复底部按钮文字
$('.laydate-btns-now').text('今天');
$('.laydate-btns-clear').text('清空');
$('.laydate-btns-confirm').text('确定');
// 修复年月选择器中的文字
$('.laydate-set-ym span').each(function() {
var text = $(this).text();
text = text.replace('骞', '年').replace('鏈', '月');
$(this).text(text);
});
console.log('日期选择器文字已修复');
} catch(e) {
console.warn('修复日期选择器文字时出错:', e);
}
}, 50);
};
// 在日期选择器打开时自动修复
$(document).on('click', 'input[lay-key]', function() {
window.fixDatepicker();
});
console.log('添加CSS样式修复和日期选择器监听');
})();
// 初始化Layui组件确保使用中文
(function initLayuiLanguage() {
try {
// 修复可能的编码问题
if(layui.device('ie')) {
try {
// 解决IE浏览器下的乱码问题
document.charset = 'UTF-8';
} catch(e) {
console.warn('无法设置文档编码:', e);
}
}
// 修复分页组件的乱码问题
if(layui.laypage && layui.laypage.config) {
try {
// 尝试直接修改laypage的默认文本
layui.laypage.config({
lang: {
first: '首页',
last: '尾页',
prev: '上一页',
next: '下一页',
skip: '跳至',
total: '共',
item: '条',
pagesize: '条/页',
jump: '确定'
}
});
} catch(e) {
console.warn('无法设置laypage配置:', e);
}
}
// 不再尝试全局配置laydate改为在每次创建时设置
console.log('Layui组件语言初始化完成');
} catch(e) {
console.error('初始化Layui组件时出错:', e);
}
})();
// 创建日期选择器配置函数,确保所有日期选择器使用中文
function createDatePicker(elem, options) {
// 检查页面编码,若非 UTF-8 则尝试设置
var metaCharset = document.querySelector('meta[charset]');
if(metaCharset && metaCharset.getAttribute('charset').toLowerCase() !== 'utf-8') {
try {
metaCharset.setAttribute('charset', 'UTF-8');
console.log("页面编码已设置为 UTF-8");
} catch(e) {
console.warn("无法设置页面编码:", e);
}
}
var defaultOptions = {
elem: elem,
lang: 'cn', // 设置中文
format: 'yyyy-MM-dd', // 设置日期格式
theme: 'molv', // 使用墨绿主题,更美观
// 添加事件回调,在每次打开日期选择器时修复文字
ready: function() {
if(window.fixDatepicker) {
window.fixDatepicker();
}
},
change: function() {
if(window.fixDatepicker) {
window.fixDatepicker();
}
}
};
// 合并配置
var finalOptions = $.extend({}, defaultOptions, options || {});
try {
// 渲染日期选择器
var dateInstance = layui.laydate.render(finalOptions);
// 在渲染后尝试修复日期文本编码问题
setTimeout(function() {
if(window.fixDatepicker) {
window.fixDatepicker();
}
}, 100); // 延迟100ms执行确保元素已渲染
return dateInstance;
} catch (e) {
console.warn('创建日期选择器失败,尝试简化配置:', e);
// 如果失败,尝试使用最基本的配置
return layui.laydate.render({
elem: elem
});
}
}
var projectCost = {
// 初始化列表页
init: function() {
// 初始化日期选择器
createDatePicker('#startDate');
createDatePicker('#endDate');
// 初始化表格 - 改为手动加载数据
var tableIns = table.render({
elem: '#LAY-project-cost-list',
// 不使用url自动请求
cols: [[
{field: 'id', title: 'ID', hide: true, width: 80},
{field: 'projectName', title: '工程名称', minWidth: 400},
{field: 'startTime', title: '开始日期', width: 120},
{field: 'endTime', title: '结束日期', width: 120},
{field: 'totalAmount', title: '总金额(元)', width: 120, templet: function(d) {
return d.totalAmount ? d.totalAmount.toFixed(2) : '0.00';
}},
{field: 'createTime', title: '创建时间', minWidth: 160},
{field: 'createUser', title: '创建人', width: 120},
{title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-project-cost-list'}
]],
data: [], // 初始为空数组
page: false,
limit: 1000,
height: 'full-220',
even: true, // 开启隔行背景
size: 'lg', // 大尺寸
autoSort: false, // 关闭自动排序
cellMinWidth: 80, // 最小单元格宽度
text: {
none: '暂无数据'
},
// 添加语言配置,修复乱码问题
lang: 'zh-CN',
i18n: {
'zh-CN': {
page: {
first: '首页',
last: '尾页',
prev: '上一页',
next: '下一页',
skip: '跳至',
total: '共',
item: '条',
pagesize: '条/页',
jump: '确定'
}
}
}
});
// 手动加载数据函数
function loadTableData(params) {
// 显示加载指示器
layer.load(2);
// 默认参数
var defaultParams = {
page: 1,
limit: 1000
};
// 合并参数
params = $.extend({}, defaultParams, params || {});
$.ajax({
url: baseUrl + '/backstage/projectCost/queryCalculationList',
type: 'post',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(params),
success: function(res) {
// 关闭加载指示器
layer.closeAll('loading');
console.log("原始响应:", res);
// 处理可能是字符串的响应
if (typeof res === 'string') {
try {
res = JSON.parse(res);
console.log("解析字符串响应为对象:", res);
} catch(e) {
console.error("无法解析JSON:", e);
// 尝试处理编码问题
try {
var decodedString = decodeURIComponent(escape(res));
res = JSON.parse(decodedString);
console.log("编码转换后成功解析:", res);
} catch(e2) {
console.error("编码转换尝试失败:", e2);
layer.msg('获取数据失败,请检查网络连接');
return;
}
}
}
// 更新表格数据
if (res && res.res === 1 && res.obj) {
// 渲染表格
tableIns.reload({
data: res.obj.data || []
// 移除分页配置,因为我们已取消分页功能
});
console.log("表格数据已更新, 总数:", res.obj.count);
} else {
// 显示错误消息
var errorMsg = (res && res.resMsg) ? res.resMsg : '数据接口请求异常';
// 尝试修复可能的编码问题
try {
errorMsg = decodeURIComponent(escape(errorMsg));
} catch(e) {
console.error("修复错误消息编码失败:", e);
}
layer.msg(errorMsg);
console.error("请求失败:", res);
// 清空表格
tableIns.reload({
data: []
// 移除分页配置,因为我们已取消分页功能
});
}
},
error: function(xhr, status, error) {
// 关闭加载指示器
layer.closeAll('loading');
// 显示错误信息
layer.msg('网络请求失败');
console.error("请求失败:", status, error);
console.log("XHR对象:", xhr);
// 清空表格
tableIns.reload({
data: []
// 移除分页配置,因为我们已取消分页功能
});
}
});
}
// 初始加载数据
loadTableData();
// 监听工具条事件
table.on('tool(LAY-project-cost-list)', function(obj){
var data = obj.data;
if(obj.event === 'detail'){
// 打开详情页
layer.open({
type: 2,
title: '计算结果详情',
content: baseUrl + '/backstage/projectCost/calculation_detail?id=' + data.id,
area: ['90%', '90%'],
maxmin: true
});
} else if(obj.event === 'delete'){
// 删除操作
layer.confirm('确定删除该计算结果吗?', function(index){
$.ajax({
url: baseUrl + '/backstage/projectCost/deleteCalculation',
type: 'post',
data: {id: data.id},
success: function(res){
if (typeof res === 'string') {
try {
res = JSON.parse(res);
} catch(e) {
console.error("无法解析JSON:", e);
layer.msg('删除失败,请检查网络连接');
return;
}
}
if(res.res === 1){
layer.msg('删除成功');
// 删除当前行并重新加载数据,确保表格状态正确
loadTableData();
} else {
layer.msg('删除失败');
}
},
error: function(){
layer.msg('网络错误,删除失败');
}
});
layer.close(index);
});
}
});
// 监听搜索
form.on('submit(LAY-project-cost-search)', function(data){
var field = data.field;
// 处理中文编码问题不再需要因为我们使用JSON提交
console.log("搜索参数:", field);
// 使用自定义加载函数
loadTableData({
projectName: field.projectName,
startDate: field.startDate,
endDate: field.endDate
});
return false;
});
// 注释掉这个事件绑定因为在list.jsp中已经有同样的代码
// 添加按钮点击事件
/*
$('.layui-btn[data-type="add"]').on('click', function(){
layer.open({
type: 2,
title: '新增结算计算',
content: baseUrl + '/backstage/projectCost/calculation_form',
area: ['90%', '90%'],
maxmin: true
});
});
*/
},
// 加载项目下拉框数据
loadProjects: function() {
console.log('开始加载工程列表...');
$.ajax({
url: baseUrl + '/backstage/projectCost/getProjects',
type: 'get',
dataType: 'json',
success: function(res) {
//console.log('工程列表API响应:', res);
// 检查响应是否存在且不为空
if(!res) {
console.error('响应为空');
layer.msg('加载工程列表失败: 响应为空');
return;
}
try {
var projects = [];
// 检查不同可能的数据结构
// 注意AjaxRes使用res=1表示成功而不是success=true
if(res.res === 1 || res.success === true) {
console.log('响应成功标志正确 - res:' + res.res);
if(Array.isArray(res.data)) {
projects = res.data;
console.log('从res.data获取数据数量:', projects.length);
} else if(res.obj && Array.isArray(res.obj)) {
projects = res.obj;
console.log('从res.obj获取数据数量:', projects.length);
} else if(res.obj && res.obj.list && Array.isArray(res.obj.list)) {
projects = res.obj.list;
console.log('从res.obj.list获取数据数量:', projects.length);
} else {
console.warn('响应中未找到有效数组数据');
}
} else {
// 请求不成功,但尝试从响应中提取数据
if(Array.isArray(res)) {
projects = res;
console.log('响应本身是数组,数量:', projects.length);
} else {
console.error('请求不成功且未找到数据:', res.resMsg || res.msg || '未知错误');
layer.msg('加载工程列表失败: ' + (res.resMsg || res.msg || '服务器返回未知错误'));
}
}
if(projects.length === 0) {
console.warn('未获取到工程数据或数据为空');
}
// 生成HTML即使没有数据也会创建下拉框
var html = '<option value="">请选择工程</option>';
for(var i = 0; i < projects.length; i++) {
// 兼容不同返回结构
var id = projects[i].id || projects[i].ID || '';
var name = projects[i].name || projects[i].NAME || projects[i].projectName || '';
console.log('工程数据:', i, id, name);
html += '<option value="' + id + '">' + name + '</option>';
}
console.log('生成的HTML:', html);
// 更新下拉框并重新渲染
$('select[name="projectId"]').html(html);
if(typeof form !== 'undefined' && form.render) {
form.render('select'); // 重新渲染select
console.log('下拉框渲染完成');
} else {
console.error('form对象不存在或不包含render方法');
}
// 如果没有数据,显示提示
if(projects.length === 0) {
layer.msg('未获取到工程数据,请检查系统配置');
}
} catch(error) {
console.error('处理工程数据时出错:', error);
layer.msg('加载工程列表失败: 数据处理错误');
}
},
error: function(xhr, status, error) {
console.error('请求工程列表失败:', status, error);
console.log('XHR对象:', xhr);
layer.msg('网络错误,无法加载工程列表');
}
});
},
// 生成结算数据
generateSettlement: function(data) {
if(!data.projectId) {
layer.msg('请选择工程');
return;
}
if(!data.startTime || !data.endTime) {
layer.msg('请选择统计时间范围');
return;
}
$('#data-loading').show();
$('#data-container').hide();
// 清除旧的表格容器内容,防止多次渲染
if($('#calculationResultSection').length > 0) {
$('#calculationResultSection').remove();
}
$.ajax({
url: baseUrl + '/backstage/projectCost/calculateSettlement',
type: 'post',
data: data,
success: function(res) {
$('#data-loading').hide();
// 打印响应以进行问题排查
console.log("API响应:", res);
console.log("响应类型:", typeof res);
// 处理可能是字符串的响应
if (typeof res === 'string') {
try {
res = JSON.parse(res);
console.log("已将字符串响应解析为对象:", res);
} catch(e) {
console.error("响应无法解析为JSON:", e);
}
}
// 检查响应是否成功,兼容不同的返回格式
let isSuccess = false;
if (res) {
if(res.success === true) {
isSuccess = true;
console.log("通过res.success判断成功");
} else if(res.res === 1) {
isSuccess = true;
console.log("通过res.res判断成功");
} else if(res.code === 200 || res.code === 0 || res.code === '0') {
isSuccess = true;
console.log("通过res.code判断成功");
} else if(res.status === 'success' || res.status === 200 || res.status === 0) {
isSuccess = true;
console.log("通过res.status判断成功");
}
}
console.log("判断是否成功: ", isSuccess, "响应结构:", JSON.stringify(res).substring(0, 100) + "...");
if(isSuccess) {
// 清空并重建容器结构
$('#data-container').empty().show();
// 获取正确的数据,兼容不同的数据结构
let responseData = {};
if(res.data) {
responseData = res.data;
console.log("从res.data获取数据");
} else if(res.obj) {
responseData = res.obj;
console.log("从res.obj获取数据");
} else {
// 尝试直接使用响应本身
responseData = res;
console.log("直接使用整个响应作为数据");
}
console.log("提取的响应数据:", responseData);
// 从详情数据中提取领料和退料明细
let leaseData = [];
let returnData = [];
// 检查返回的数据结构
if(responseData.leaseMaterials) {
// 使用原来的数据结构
leaseData = responseData.leaseMaterials || [];
returnData = responseData.returnMaterials || [];
} else if(responseData.details) {
// 使用后端返回的新数据结构
var details = responseData.details || [];
console.log("发现details数组长度:", details.length);
// 尝试预览第一条数据
if(details.length > 0) {
console.log("第一条数据样例:", details[0]);
// 打印所有字段名,便于排查
console.log("数据字段列表:", Object.keys(details[0]).join(", "));
}
// 按类型分离明细假设operateType=1为领料operateType=2为退料
leaseData = details.filter(function(item) {
return item.operateType !== 2 && item.operateType !== '2';
});
returnData = details.filter(function(item) {
return item.operateType === 2 || item.operateType === '2';
});
if(leaseData.length === 0 && returnData.length === 0 && details.length > 0) {
// 如果没有按类型分离出数据可能是后端没有设置operateType字段则尝试直接使用details
console.log("未能根据operateType分离数据显示所有明细作为领料");
leaseData = details;
}
} else {
// 尝试寻找其他可能的数据结构
console.warn("未找到预期的数据结构,尝试深度查找数据");
// 处理res对象中可能的嵌套数据
var foundData = false;
// 检查是否有任何直接可用的数组
for(var key in responseData) {
if(Array.isArray(responseData[key])) {
console.log("发现数组数据在字段:", key, "长度:", responseData[key].length);
if(responseData[key].length > 0) {
leaseData = responseData[key];
foundData = true;
break;
}
}
}
// 如果是res.res===1格式的API特殊处理
if(!foundData && res.res === 1) {
console.log("检测到res.res===1格式的API尝试从res.obj中提取数据");
// 如果responseData已经是res.obj查找里面的数组
if(res.obj === responseData) {
// 已经在上面处理过
}
// 尝试直接将整个res.obj作为数据源如果是数组
else if(Array.isArray(res.obj)) {
console.log("res.obj是数组直接用作数据源");
leaseData = res.obj;
foundData = true;
}
}
// 最后尝试使用整个响应作为数据源
if(!foundData) {
if(Array.isArray(responseData)) {
console.log("responseData本身是数组直接用作数据源");
leaseData = responseData;
} else if(Array.isArray(res)) {
console.log("整个res是数组直接用作数据源");
leaseData = res;
} else {
console.warn("未找到可用的数组数据");
}
}
}
console.log("处理后的领料数据:", leaseData);
console.log("处理后的退料数据:", returnData);
// 保存当前的领料和退料数据,以便在明细视图中使用
window.currentLeaseData = leaseData;
window.currentReturnData = returnData;
// 获取计算结果数据
let calculationResults = responseData.calculationResults || [];
let totalAmount = responseData.totalAmount || 0;
console.log("计算结果数据:", calculationResults);
console.log("总金额:", totalAmount);
// 保存到全局变量,供保存方法使用
window.calculationResults = calculationResults;
window.totalAmount = totalAmount;
// 创建新的容器结构,使用更明确的方式分隔表格
$('#data-container').html(
'<div class="layui-row">' +
'<div class="layui-col-md12">' +
'<div style="text-align: right; padding: 10px; font-weight: bold; color: #FF5722; font-size: 16px;">' +
'总金额: <span id="totalAmountDisplay">' + totalAmount.toFixed(2) + '</span> 元' +
'</div>' +
'</div>' +
'</div>' +
// 租赁费用计算及领退差缺表格
'<div id="resultTableContainer" style="margin-bottom: 40px; border: 1px solid #e6e6e6; padding: 15px; background-color: #fff; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">' +
'<h3 style="font-size: 16px; font-weight: bold; margin-bottom: 15px;">费用计算及领退差缺表</h3>' +
'<table class="layui-table" id="calculationTable" lay-filter="calculationTable"></table>' +
'</div>' +
// 物资领料明细表格
'<div id="leaseTableContainer" style="margin-bottom: 40px; border: 1px solid #e6e6e6; padding: 15px; background-color: #fff; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">' +
'<h3 style="font-size: 16px; font-weight: bold; margin-bottom: 15px;">物资领料明细</h3>' +
'<table class="layui-table" id="leaseTable" lay-filter="leaseTable"></table>' +
'</div>' +
// 物资退料明细表格
'<div id="returnTableContainer" style="margin-bottom: 40px; border: 1px solid #e6e6e6; padding: 15px; background-color: #fff; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">' +
'<h3 style="font-size: 16px; font-weight: bold; margin-bottom: 15px;">物资退料明细</h3>' +
'<table class="layui-table" id="returnTable" lay-filter="returnTable"></table>' +
'</div>'
);
// 计算合适的表格高度 - 根据数据量调整
var calcTableHeight = function(dataLength) {
// 根据数据行数决定表格高度
if (dataLength <= 3) return 220; // 少量数据用更小高度
if (dataLength <= 6) return 240; // 中等数据用中等高度
return 300; // 大量数据用更大高度
};
// 滚动事件处理 - 确保表格可见
$(window).on('scroll', function() {
var windowHeight = $(window).height();
var scrollTop = $(window).scrollTop();
// 检查每个表格容器是否在视图中
$('#resultTableContainer, #leaseTableContainer, #returnTableContainer').each(function() {
var $container = $(this);
var containerTop = $container.offset().top;
var containerHeight = $container.height();
// 如果容器底部超出视图,添加一个可视指示器
if (containerTop + containerHeight > scrollTop + windowHeight) {
if ($container.find('.scroll-indicator').length === 0) {
$container.append('<div class="scroll-indicator" style="text-align: center; padding: 5px; color: #999;">↓ 向下滚动查看更多 ↓</div>');
}
} else {
$container.find('.scroll-indicator').remove();
}
});
});
// 渲染计算结果表格
if(calculationResults.length > 0) {
var calcHeight = calcTableHeight(calculationResults.length);
table.render({
elem: '#calculationTable',
data: calculationResults,
cols: [[
{field: 'machineTypeId', title: '物资ID', width: 100, hide: true},
{field: 'machineTypeName', title: '物资名称', minWidth: 200},
{field: 'machineModel', title: '规格型号', minWidth: 180},
{field: 'machineUnit', title: '单位', minWidth: 80},
{field: 'currentCount', title: '未退还数量', minWidth: 120, templet: function(d){
return d.currentCount || 0;
}},
{field: 'price', title: '单价(元/天)', width: 120, templet: function(d){
return d.price ? d.price.toFixed(2) : '0.00';
}},
{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: 100, templet: function(d){
return '<a class="layui-btn layui-btn-xs" lay-event="viewDetail">查看明细</a>';
}}
]],
page: false,
height: calcHeight, // 使用计算的高度
limit: 1000,
// 添加语言配置,修复乱码问题
lang: 'zh-CN',
i18n: {
'zh-CN': {
page: {
first: '首页',
last: '尾页',
prev: '上一页',
next: '下一页',
skip: '跳至',
total: '共',
item: '条',
pagesize: '条/页',
jump: '确定'
}
}
}
});
// 监听计算结果表格工具条事件
table.on('tool(calculationTable)', function(obj){
let i;
const data = obj.data;
if(obj.event === 'viewDetail'){
// 显示物资使用明细
let detailHtml = '<div style="padding: 15px;">';
// 添加时间段计算明细表格
detailHtml += '<div class="layui-tab layui-tab-brief" lay-filter="detailTab">';
detailHtml += '<ul class="layui-tab-title">';
detailHtml += '<li class="layui-this">使用时间段</li>';
detailHtml += '<li>物资领退记录</li>';
detailHtml += '</ul>';
detailHtml += '<div class="layui-tab-content">';
// 时段计算内容
detailHtml += '<div class="layui-tab-item layui-show">';
detailHtml += '<table class="layui-table">';
detailHtml += '<thead><tr><th>开始时间</th><th>结束时间</th><th>使用天数</th><th>使用数量</th><th>金额(元)</th></tr></thead>';
detailHtml += '<tbody>';
const segments = data.segments || [];
// 打印调试信息
console.log("时段计算数据:", segments);
// 检查是否有数据
if (segments.length === 0) {
// 如果没有时段数据,尝试从计算结果构建一个简单的时段
detailHtml += '<tr><td colspan="5" style="text-align: center;">没有详细的时段计算数据,显示汇总信息</td></tr>';
// 添加一个汇总行
var amount = data.amount || 0;
var count = data.currentCount || 0;
detailHtml += '<tr style="font-weight: bold;">';
detailHtml += '<td>--</td>';
detailHtml += '<td>--</td>';
detailHtml += '<td>--</td>';
detailHtml += '<td>' + count + '</td>';
detailHtml += '<td>' + (amount ? amount.toFixed(2) : '0.00') + '</td>';
detailHtml += '</tr>';
} else {
var totalDays = 0;
var totalAmount = 0;
for(i = 0; i < segments.length; i++){
var segment = segments[i];
var startTime = formatDateTime(segment.startTime);
var endTime = formatDateTime(segment.endTime);
var days = segment.days || 0;
var count = segment.count || 0;
var amount = segment.amount || 0;
totalDays += days;
totalAmount += amount;
detailHtml += '<tr>';
detailHtml += '<td>' + startTime + '</td>';
detailHtml += '<td>' + endTime + '</td>';
detailHtml += '<td>' + days + '</td>';
detailHtml += '<td>' + count + '</td>';
detailHtml += '<td>' + amount.toFixed(2) + '</td>';
detailHtml += '</tr>';
}
// 添加汇总行
detailHtml += '<tr style="font-weight: bold; background-color: #f2f2f2;">';
detailHtml += '<td colspan="2">合计</td>';
detailHtml += '<td>' + totalDays + '</td>';
detailHtml += '<td>-</td>';
detailHtml += '<td>' + totalAmount.toFixed(2) + '</td>';
detailHtml += '</tr>';
}
detailHtml += '</tbody></table>';
detailHtml += '</div>';
// 操作记录内容
detailHtml += '<div class="layui-tab-item">';
// 添加颜色图例说明
detailHtml += '<div style="margin-bottom: 10px; text-align: right;">';
detailHtml += '<span style="display: inline-block; padding: 2px 8px; margin-right: 10px; background-color: #e8f5e9; color: #388e3c; border-radius: 2px;">领料</span>';
detailHtml += '<span style="display: inline-block; padding: 2px 8px; background-color: #ffebee; color: #d32f2f; border-radius: 2px;">退料</span>';
detailHtml += '</div>';
detailHtml += '<table class="layui-table">';
detailHtml += '<thead><tr style="background-color: #f2f2f2; font-weight: bold;"><th>操作时间</th><th>操作类型</th><th>数量</th><th>现场剩余数量</th></tr></thead>';
detailHtml += '<tbody>';
var details = data.details || [];
var timeline = data.timeline || {};
// 打印调试信息
console.log("明细详情数据:", details);
console.log("时间线数据:", timeline);
// 按操作时间排序
details.sort(function(a, b){
var timeA = a.operateTime ? new Date(a.operateTime) : new Date(0);
var timeB = b.operateTime ? new Date(b.operateTime) : new Date(0);
return timeA - timeB;
});
// 检查是否有数据
if (details.length === 0) {
detailHtml += '<tr><td colspan="4" style="text-align: center;">暂无操作记录数据</td></tr>';
} else {
var totalLeaseQuantity = 0;
var totalReturnQuantity = 0;
var finalCount = 0;
for(i = 0; i < details.length; i++){
var item = details[i];
var operateTimeStr = item.operateTime || '';
var operateTime = formatDateTime(operateTimeStr);
// 确定操作类型
let operateType = '未知';
if (item.operateType === 1 || item.operateType === '1') {
operateType = '领料';
} else if (item.operateType === 2 || item.operateType === '2') {
operateType = '退料';
} else {
operateType = String(item.operateType || '');
}
// 确定数量
var quantity = 0;
if (operateType === '领料') {
quantity = item.leaseNum || item.quantity || item.count || item.num || 0;
totalLeaseQuantity += parseFloat(quantity);
} else if (operateType === '退料') {
quantity = item.returnNum || item.quantity || item.count || item.num || 0;
totalReturnQuantity += parseFloat(quantity);
}
// 查找当前在用数量
var currentCount = timeline[operateTimeStr] || 0;
// 如果在timeline找不到对应的值尝试使用不同格式的时间字符串
if (currentCount === 0 && operateTimeStr) {
// 遍历timeline对象的所有键
for (var timeKey in timeline) {
// 检查是否包含相同的日期部分(忽略精确的时间)
if (timeKey && operateTimeStr.substring(0, 10) === timeKey.substring(0, 10)) {
currentCount = timeline[timeKey];
console.log("找到匹配的时间线数据:", timeKey, currentCount);
break;
}
}
}
// 更新最终数量
finalCount = currentCount;
// 根据操作类型设置不同的行样式
var rowStyle = '';
if (operateType === '领料') {
rowStyle = 'background-color: #e8f5e9; color: #388e3c;'; // 绿色背景,深绿色文字
} else if (operateType === '退料') {
rowStyle = 'background-color: #ffebee; color: #d32f2f;'; // 红色背景,深红色文字
}
detailHtml += '<tr style="' + rowStyle + '">';
detailHtml += '<td>' + operateTime + '</td>';
detailHtml += '<td>' + operateType + '</td>';
detailHtml += '<td>' + quantity + '</td>';
detailHtml += '<td>' + currentCount + '</td>';
detailHtml += '</tr>';
}
// 添加汇总行
detailHtml += '<tr style="font-weight: bold; background-color: #f2f2f2;">';
detailHtml += '<td colspan="2">汇总</td>';
detailHtml += '<td><span style="color: #388e3c;">领料: ' + totalLeaseQuantity + '</span><br><span style="color: #d32f2f;">退料: ' + totalReturnQuantity + '</span></td>';
detailHtml += '<td>' + finalCount + '</td>';
detailHtml += '</tr>';
}
detailHtml += '</tbody></table>';
detailHtml += '</div>';
detailHtml += '</div>'; // 结束 tab-content
detailHtml += '</div>'; // 结束 tab
detailHtml += '</div>'; // 结束外层div
// 打开弹窗
const layerIndex = layer.open({
type: 1,
title: data.machineTypeName + ' 使用明细',
content: detailHtml,
area: ['800px', '500px'],
shadeClose: true,
success: function () {
// 初始化Tab
layui.element.render('tab');
}
});
}
});
} else {
$('#resultTableContainer').html('<div style="padding: 20px; text-align: center;">暂无租赁费用计算结果</div>');
}
// 渲染领料表格
if (leaseData && leaseData.length > 0) {
var leaseHeight = calcTableHeight(leaseData.length);
table.render({
elem: '#leaseTable',
data: leaseData,
cols: [[
{field: 'machineTypeName', title: '物资名称', width: 160, templet: function(d){
return d.machineTypeName || d.machineName || d.materialName || '';
}},
{field: 'machineModel', title: '规格型号', width: 120, templet: function(d){
return d.machineModel || d.specification || '';
}},
{field: 'machineUnit', title: '单位', width: 80, templet: function(d){
return d.machineUnit || d.unit || '';
}},
{field: 'leaseNum', title: '数量', width: 80, templet: function(d){
return d.leaseNum || d.quantity || d.count || d.num || 0;
}},
{field: 'price', title: '单价(元)', width: 100, templet: function(d){
// 如果没有价格字段暂时显示0
return d.price || d.unitPrice || '0.00';
}},
{field: 'amount', title: '金额(元)', width: 100, templet: function(d){
// 尝试使用已有金额,或者根据数量和单价计算
var amount = d.amount || d.totalPrice || d.money || 0;
// 如果没有金额,但有数量,尝试计算
if(amount === 0 && d.leaseNum) {
var price = d.price || d.unitPrice || 0;
if(price > 0) {
amount = (parseFloat(d.leaseNum) * parseFloat(price)).toFixed(2);
}
}
return amount || '0.00';
}},
{field: 'leaseUnit', title: '使用单位', width: 120, templet: function(d){
return d.leaseUnit || '';
}},
{field: 'operatePersonName', title: '操作人', width: 100, templet: function(d){
return d.operatePersonName || '';
}},
{field: 'taskCode', title: '任务编号', width: 120, templet: function(d){
return d.taskCode || '';
}},
{field: 'projectName', title: '工程名称', width: 200, templet: function(d){
return d.projectName || '';
}},
{field: 'operateType', title: '操作类型', width: 100, templet: function(d){
return d.operateType === 1 ? '<span style="color: #2f952d">领料</span>' : (d.operateType === 2 ? '<span style="color: #bc412b">退料</span>' : d.operateType || '');
}},
{field: 'remark', title: '备注', width: 120, templet: function(d){
return d.remark || '';
}}
]],
page: false,
height: leaseHeight, // 使用计算的高度
limit: 1000,
// 添加语言配置,修复乱码问题
lang: 'zh-CN',
i18n: {
'zh-CN': {
page: {
first: '首页',
last: '尾页',
prev: '上一页',
next: '下一页',
skip: '跳至',
total: '共',
item: '条',
pagesize: '条/页',
jump: '确定'
}
}
}
});
} else {
$('#leaseTableContainer').html('<div style="padding: 20px; text-align: center;">暂无物资领料明细</div>');
}
// 渲染退料表格
if (returnData && returnData.length > 0) {
var returnHeight = calcTableHeight(returnData.length);
table.render({
elem: '#returnTable',
data: returnData,
cols: [[
{field: 'machineTypeName', title: '物资名称', width: 160, templet: function(d){
return d.machineTypeName || d.machineName || d.materialName || '';
}},
{field: 'machineModel', title: '规格型号', width: 120, templet: function(d){
return d.machineModel || d.specification || '';
}},
{field: 'machineUnit', title: '单位', width: 80, templet: function(d){
return d.machineUnit || d.unit || '';
}},
{field: 'returnNum', title: '数量', width: 80, templet: function(d){
return d.returnNum || d.quantity || d.count || d.num || 0;
}},
{field: 'price', title: '单价(元)', width: 100, templet: function(d){
// 如果没有价格字段暂时显示0
return d.price || d.unitPrice || '0.00';
}},
{field: 'amount', title: '金额(元)', width: 100, templet: function(d){
// 尝试使用已有金额,或者根据数量和单价计算
var amount = d.amount || d.totalPrice || d.money || 0;
// 如果没有金额,但有数量,尝试计算
if(amount === 0 && d.returnNum) {
var price = d.price || d.unitPrice || 0;
if(price > 0) {
amount = (parseFloat(d.returnNum) * parseFloat(price)).toFixed(2);
}
}
return amount || '0.00';
}},
{field: 'leaseUnit', title: '使用单位', width: 120, templet: function(d){
return d.leaseUnit || '';
}},
{field: 'operatePersonName', title: '操作人', width: 100, templet: function(d){
return d.operatePersonName || '';
}},
{field: 'taskCode', title: '任务编号', width: 120, templet: function(d){
return d.taskCode || '';
}},
{field: 'projectName', title: '工程名称', width: 200, templet: function(d){
return d.projectName || '';
}},
{field: 'operateType', title: '操作类型', width: 100, templet: function(d){
return d.operateType === 1 ? '<span style="color: #2f952d">领料</span>' : (d.operateType === 2 ? '<span style="color: #bc412b">退料</span>' : d.operateType || '');
}},
{field: 'remark', title: '备注', width: 120, templet: function(d){
return d.remark || '';
}}
]],
page: false,
height: returnHeight, // 使用计算的高度
limit: 1000,
// 添加语言配置,修复乱码问题
lang: 'zh-CN',
i18n: {
'zh-CN': {
page: {
first: '首页',
last: '尾页',
prev: '上一页',
next: '下一页',
skip: '跳至',
total: '共',
item: '条',
pagesize: '条/页',
jump: '确定'
}
}
}
});
} else {
$('#returnTableContainer').html('<div style="padding: 20px; text-align: center;">暂无物资退料明细</div>');
}
// 滚动到容器顶部确保用户可以看到结果
$('html, body').animate({
scrollTop: $('#data-container').offset().top - 20
}, 500);
} else {
layer.msg(res.msg || res.resMsg || '数据加载失败');
}
},
error: function(xhr, status, error) {
$('#data-loading').hide();
console.error('请求失败:', status, error);
console.log('XHR对象:', xhr);
layer.msg('网络错误,请重试');
}
});
},
// 保存结算数据
saveSettlement: function(data) {
if(!data.projectId) {
layer.msg('请选择工程');
return;
}
if(!data.startTime || !data.endTime) {
layer.msg('请选择统计时间范围');
return;
}
layer.confirm('确定保存此结算数据吗?', function(index) {
$.ajax({
url: baseUrl + '/backstage/projectCost/saveSettlement',
type: 'post',
contentType: 'application/json',
data: JSON.stringify(data),
success: function(res) {
// 处理可能是字符串的响应
if (typeof res === 'string') {
try {
res = JSON.parse(res);
console.log("已将字符串响应解析为对象:", res);
} catch(e) {
console.error("响应无法解析为JSON:", e);
}
}
if(res.resMsg === '保存成功' || res.res === 1) {
layer.msg('保存成功');
// 可选:关闭当前页并刷新列表
const index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
parent.layui.table.reload('LAY-project-cost-list');
} else {
layer.msg(res.msg || '保存失败');
}
},
error: function() {
layer.msg('网络错误,请重试');
}
});
layer.close(index);
});
},
// 保存计算结果数据
saveCalculation: function(data) {
if(!data.projectId) {
layer.msg('请选择工程');
return;
}
if(!data.startTime || !data.endTime) {
layer.msg('请选择统计时间范围');
return;
}
// 获取当前项目名称
const projectName = $('select[name="projectId"] option:selected').text();
// 检查是否有计算结果数据
if (!window.calculationResults || !window.totalAmount) {
layer.msg('请先生成计算结果再保存');
return;
}
// 准备保存的数据
const saveData = {
projectId: data.projectId,
projectName: projectName,
startTime: data.startTime,
endTime: data.endTime,
calculationResults: window.calculationResults || [],
totalAmount: window.totalAmount || 0
};
layer.confirm('确定保存此计算结果吗?', function(index) {
$.ajax({
url: baseUrl + '/backstage/projectCost/saveCalculation',
type: 'post',
contentType: 'application/json',
data: JSON.stringify(saveData),
success: function(res) {
console.log("响应:", res);
layer.msg('保存成功');
// 可选:关闭当前页并刷新列表
const index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
parent.layui.table.reload('LAY-project-cost-list');
},
error: function() {
layer.msg('网络错误,请重试');
}
});
layer.close(index);
});
},
// 加载详情数据
loadDetail: function(id) {
$.ajax({
url: baseUrl + '/backstage/projectCost/getSettlementDetail',
type: 'get',
data: {id: id},
success: function(res) {
if(res.success) {
var data = res.data;
if(data) {
// 填充表单数据
form.val('detail-form', {
'projectName': data.projectName,
'settlementTime': data.createTime,
'timeRange': data.startTime + ' 至 ' + data.endTime
});
// 渲染领料明细表格
table.render({
elem: '#leaseDetails-table',
url: baseUrl + '/backstage/projectCost/getSettlementLeaseDetails',
where: {settlementId: id},
cols: [[
{field: 'materialName', title: '物资名称', width: 160},
{field: 'specification', title: '规格型号', width: 120},
{field: 'unit', title: '单位', width: 80},
{field: 'quantity', title: '数量', width: 100},
{field: 'price', title: '单价(元)', width: 100},
{field: 'amount', title: '金额(元)', width: 120}
]],
page: false,
height: 'full-500',
// 添加语言配置,修复乱码问题
lang: 'zh-CN',
i18n: {
'zh-CN': {
page: {
first: '首页',
last: '尾页',
prev: '上一页',
next: '下一页',
skip: '跳至',
total: '共',
item: '条',
pagesize: '条/页',
jump: '确定'
}
}
}
});
// 渲染退料明细表格
table.render({
elem: '#returnDetails-table',
url: baseUrl + '/backstage/projectCost/getSettlementReturnDetails',
where: {settlementId: id},
cols: [[
{field: 'materialName', title: '物资名称', width: 160},
{field: 'specification', title: '规格型号', width: 120},
{field: 'unit', title: '单位', width: 80},
{field: 'quantity', title: '数量', width: 100},
{field: 'price', title: '单价(元)', width: 100},
{field: 'amount', title: '金额(元)', width: 120}
]],
page: false,
height: 'full-500',
// 添加语言配置,修复乱码问题
lang: 'zh-CN',
i18n: {
'zh-CN': {
page: {
first: '首页',
last: '尾页',
prev: '上一页',
next: '下一页',
skip: '跳至',
total: '共',
item: '条',
pagesize: '条/页',
jump: '确定'
}
}
}
});
}
} else {
layer.msg(res.msg || '数据加载失败');
}
},
error: function() {
layer.msg('网络错误,请重试');
}
});
},
// 打印详情
printDetail: function(id) {
window.open(baseUrl + '/backstage/projectCost/printDetail?id=' + id);
}
};
// 输出接口
exports('projectCost', projectCost);
});
// 添加日期格式化函数
function formatDateTime(dateTimeStr) {
if(!dateTimeStr) return '';
try {
var date = new Date(dateTimeStr);
if(isNaN(date.getTime())) return dateTimeStr;
return date.getFullYear() + '-' +
padZero(date.getMonth() + 1) + '-' +
padZero(date.getDate()) + ' ' +
padZero(date.getHours()) + ':' +
padZero(date.getMinutes());
} catch(e) {
return dateTimeStr;
}
}
function padZero(num) {
return (num < 10 ? '0' : '') + num;
}