1105 lines
111 KiB
JavaScript
1105 lines
111 KiB
JavaScript
layui.define(['table', 'form', 'layer', 'laytpl', 'laydate'], function(exports){
|
||
var $ = layui.$,
|
||
table = layui.table,
|
||
form = layui.form,
|
||
layer = layui.layer,
|
||
laytpl = layui.laytpl,
|
||
laydate = layui.laydate;
|
||
|
||
var baseUrl = window.bonuspath || './';
|
||
|
||
// 全局修改记录存储
|
||
window.modifiedRows = {
|
||
lease: {}, // 领料修改记录
|
||
return: {} // 退料修改记录
|
||
};
|
||
// 【新增】全局原始数据存储(页面初始化时从服务端获取,作为永久对比基准)
|
||
window.originalTableData = {
|
||
lease: [], // 领料原始数据
|
||
return: [] // 退料原始数据
|
||
};
|
||
// 【核心新增】全局列配置(抽离leaseCols/returnCols,解决作用域问题,所有方法可访问)
|
||
window.tableColumnConfig = {
|
||
leaseCols: [], // 领料表格列配置
|
||
returnCols: [] // 退料表格列配置
|
||
};
|
||
|
||
// 字段标签映射
|
||
var fieldLabels = {
|
||
'leaseNum': '领料数量',
|
||
'returnNum': '退料数量',
|
||
'operateTime': '操作时间',
|
||
'price': '单价',
|
||
'amount': '金额',
|
||
'remark': '备注',
|
||
'machineTypeName': '物资名称',
|
||
'machineModel': '规格型号',
|
||
'machineUnit': '单位',
|
||
'leaseUnit': '使用单位',
|
||
'operatePersonName': '操作人',
|
||
'taskCode': '任务编号',
|
||
'projectName': '工程名称'
|
||
};
|
||
|
||
// 设置Layui全局配置,解决乱码问题
|
||
layui.config({
|
||
lang: 'zh-CN'
|
||
});
|
||
|
||
var projectCost = {
|
||
// 标记字段被修改
|
||
markModified: function(type, rowId, field, oldVal, newVal, rowData) {
|
||
if (!window.modifiedRows[type][rowId]) {
|
||
window.modifiedRows[type][rowId] = {
|
||
rowData: $.extend(true, {}, rowData),
|
||
fields: {}
|
||
};
|
||
}
|
||
|
||
// 记录修改
|
||
window.modifiedRows[type][rowId].fields[field] = {
|
||
old: oldVal,
|
||
val: newVal,
|
||
label: fieldLabels[field] || field
|
||
};
|
||
|
||
// 更新rowData
|
||
window.modifiedRows[type][rowId].rowData[field] = newVal;
|
||
|
||
console.log('标记修改:', type, rowId, field, oldVal, '->', newVal);
|
||
},
|
||
|
||
// 检查字段是否被修改
|
||
// 检查字段是否被修改
|
||
isFieldModified: function(type, rowId, field) {
|
||
// 【优化】增加多层空值判断,兼容记录已被删除的情况
|
||
return window.modifiedRows[type] && window.modifiedRows[type][rowId]
|
||
&& window.modifiedRows[type][rowId].fields
|
||
&& window.modifiedRows[type][rowId].fields[field];
|
||
},
|
||
|
||
// 获取所有修改的数据
|
||
getAllModifiedData: function() {
|
||
var result = {
|
||
leaseModified: [],
|
||
returnModified: [],
|
||
totalCount: 0
|
||
};
|
||
|
||
// 处理领料修改(过滤掉无字段的空记录)
|
||
for (var rowId in window.modifiedRows.lease) {
|
||
var item = window.modifiedRows.lease[rowId];
|
||
var fieldKeys = Object.keys(item.fields || {});
|
||
if (fieldKeys.length > 0) { // 仅保留有实际修改字段的记录
|
||
result.leaseModified.push({
|
||
id: rowId,
|
||
machineTypeName: item.rowData.machineTypeName || '',
|
||
fields: item.fields
|
||
});
|
||
result.totalCount += fieldKeys.length;
|
||
}
|
||
}
|
||
|
||
// 处理退料修改(过滤掉无字段的空记录)
|
||
for (var rowId in window.modifiedRows.return) {
|
||
var item = window.modifiedRows.return[rowId];
|
||
var fieldKeys = Object.keys(item.fields || {});
|
||
if (fieldKeys.length > 0) { // 仅保留有实际修改字段的记录
|
||
result.returnModified.push({
|
||
id: rowId,
|
||
machineTypeName: item.rowData.machineTypeName || '',
|
||
fields: item.fields
|
||
});
|
||
result.totalCount += fieldKeys.length;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
},
|
||
|
||
// 显示确认修改弹框
|
||
showConfirmModal: function() {
|
||
var modifiedData = this.getAllModifiedData();
|
||
|
||
if (modifiedData.totalCount === 0) {
|
||
layer.msg('暂无修改的数据');
|
||
return;
|
||
}
|
||
|
||
var content = laytpl($('#confirmModalTpl').html()).render(modifiedData);
|
||
|
||
layer.open({
|
||
type: 1,
|
||
title: '确认修改',
|
||
content: content,
|
||
area: ['700px', '500px'],
|
||
btn: ['确认修改', '取消'],
|
||
yes: function(index, layero) {
|
||
projectCost.submitAllModifications();
|
||
layer.close(index);
|
||
},
|
||
btn2: function(index, layero) {
|
||
layer.close(index);
|
||
}
|
||
});
|
||
},
|
||
|
||
// 提交所有修改到后台
|
||
submitAllModifications: function() {
|
||
// 【修复未定义变量】添加allModifications声明
|
||
var allModifications = [];
|
||
if (!window.editPageField || !window.editPageField.projectId) {
|
||
layer.msg('请选择工程后再提交修改', {icon: 2});
|
||
return;
|
||
}
|
||
|
||
// 收集领料修改
|
||
for (var rowId in window.modifiedRows.lease) {
|
||
var item = window.modifiedRows.lease[rowId];
|
||
if (Object.keys(item.fields).length > 0) {
|
||
var modification = {
|
||
id:rowId,
|
||
newNum:item.rowData.leaseNum,
|
||
operateTime:item.rowData.operateTime,
|
||
operateType:item.rowData.operateType,
|
||
};
|
||
|
||
// // 恢复原始数据用于对比
|
||
// for (var field in item.fields) {
|
||
// modification.originalData[field] = item.fields[field].old;
|
||
// }
|
||
|
||
allModifications.push(modification);
|
||
}
|
||
}
|
||
|
||
// 收集退料修改
|
||
for (var rowId in window.modifiedRows.return) {
|
||
var item = window.modifiedRows.return[rowId];
|
||
if (Object.keys(item.fields).length > 0) {
|
||
var modification = {
|
||
id:rowId,
|
||
newNum:item.rowData.returnNum,
|
||
operateTime:item.rowData.operateTime,
|
||
operateType:item.rowData.operateType,
|
||
};
|
||
|
||
// // 恢复原始数据用于对比
|
||
// for (var field in item.fields) {
|
||
// modification.originalData[field] = item.fields[field].old;
|
||
// }
|
||
|
||
allModifications.push(modification);
|
||
}
|
||
}
|
||
|
||
if (allModifications.length === 0) {
|
||
layer.msg('没有需要提交的修改');
|
||
return;
|
||
}
|
||
|
||
// 显示加载中
|
||
var loadIndex = layer.load(2);
|
||
|
||
// 准备提交数据
|
||
var submitData = {
|
||
calculationId: window.editPageField.calculationId,
|
||
projectId: window.editPageField.projectId,
|
||
startTime: window.editPageField.startTime,
|
||
endTime: window.editPageField.endTime,
|
||
modifications: allModifications
|
||
};
|
||
|
||
console.log('提交的修改数据:', submitData);
|
||
|
||
// 调用后台接口
|
||
$.ajax({
|
||
url: baseUrl + '/backstage/projectCost/submitModifications',
|
||
type: 'post',
|
||
contentType: 'application/json; charset=utf-8',
|
||
data: JSON.stringify(submitData),
|
||
dataType: 'json',
|
||
success: function(res) {
|
||
layer.close(loadIndex);
|
||
|
||
if (typeof res === 'string') {
|
||
try {
|
||
res = JSON.parse(res);
|
||
} catch(e) {
|
||
console.error("无法解析JSON:", e);
|
||
layer.msg('提交失败,请检查网络连接');
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (res.res === 1 || res.success) {
|
||
layer.msg('修改提交成功', {icon: 1, time: 1500}); // 成功提示,1.5秒后执行后续操作
|
||
|
||
// 核心1:清空修改记录(保留原有逻辑)
|
||
window.modifiedRows = {
|
||
lease: {},
|
||
return: {}
|
||
};
|
||
|
||
// 核心2:关闭Layui打开的所有弹窗(包括编辑页、确认框等所有层级弹窗)
|
||
// 核心3:跳转到list.jsp并强制刷新(解决浏览器缓存问题)
|
||
// 拼接list.jsp的完整路径(与你项目的URL规则保持一致)
|
||
var listUrl = baseUrl+'/backstage/projectCost/list';
|
||
// 方式1:最稳妥 - 关闭当前标签页,刷新父级list.jsp(推荐,适配Layui弹窗打开的编辑页)
|
||
if (window.parent) {
|
||
window.parent.location.href = listUrl + '?t=' + new Date().getTime(); // 加时间戳防缓存
|
||
window.close(); // 关闭当前编辑页标签
|
||
} else {
|
||
// 方式2:直接刷新当前页为list.jsp(备用)
|
||
window.location.href = listUrl + '?t=' + new Date().getTime();
|
||
}
|
||
} else {
|
||
layer.msg(res.resMsg || res.msg || '提交失败', {icon: 2});
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
layer.close(loadIndex);
|
||
console.error('提交失败:', status, error);
|
||
layer.msg('网络错误,提交失败', {icon: 2});
|
||
}
|
||
});
|
||
},
|
||
|
||
// 渲染表格,添加修改标记 - 保证改回原始值后无红色标记
|
||
// 渲染表格,添加修改标记 - 保留金额模板+仅核心字段用修改记录值
|
||
renderTableWithModifications: function(elem, data, cols, type) {
|
||
console.log('渲染表格:', elem, '数据长度:', data.length, '类型:', type);
|
||
|
||
// 适配二维数组cols,双层map遍历(行→列)
|
||
var fixedCols = cols.map(function(colRow) {
|
||
return colRow.map(function(col) {
|
||
if (col.field) {
|
||
var originalTemplet = col.templet; // 保留原始模板
|
||
col.templet = function(d) {
|
||
var rowId = type === 'lease' ? (d.supId || d.id) : d.id;
|
||
var value = '';
|
||
// 仅数量、操作时间字段使用修改记录值(核心:避免覆盖金额模板)
|
||
var useModifyValue = ['leaseNum', 'returnNum', 'operateTime'].includes(col.field);
|
||
|
||
// 取值优先级:修改记录(指定字段)→ 行对象本身 → 空值
|
||
if (useModifyValue && rowId && projectCost.isFieldModified(type, rowId, col.field)) {
|
||
value = window.modifiedRows[type][rowId].fields[col.field].val;
|
||
} else if (d[col.field] !== undefined && d[col.field] !== null) {
|
||
value = d[col.field];
|
||
}
|
||
|
||
// 强制保留原有模板逻辑(关键:金额格式化、字段映射不丢失)
|
||
if (originalTemplet) {
|
||
if (typeof originalTemplet === 'function') {
|
||
try {
|
||
value = originalTemplet(d); // 执行原始模板(如金额计算)
|
||
} catch(e) {
|
||
console.warn('模板函数执行失败:', e, '字段:', col.field);
|
||
}
|
||
} else if (typeof originalTemplet === 'string') {
|
||
try {
|
||
value = laytpl(originalTemplet).render(d);
|
||
} catch(e) {
|
||
console.warn('模板渲染失败:', e, '字段:', col.field);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 仅当字段有未删除的修改记录时,添加红色标记
|
||
if (rowId && projectCost.isFieldModified(type, rowId, col.field)) {
|
||
return '<span class="modified-cell">' + (value || '') + '</span>';
|
||
}
|
||
|
||
return value || '';
|
||
};
|
||
}
|
||
return col;
|
||
});
|
||
});
|
||
|
||
// 渲染表格
|
||
table.render({
|
||
elem: elem,
|
||
data: data,
|
||
cols: fixedCols,
|
||
page: false,
|
||
height: 'auto',
|
||
limit: 1000,
|
||
lang: 'zh-CN',
|
||
skin: 'line',
|
||
even: true,
|
||
text: { none: '暂无数据' },
|
||
done: function(res) {
|
||
console.log('表格渲染完成:', elem, '数据量:', res.count);
|
||
},
|
||
error: function(msg) {
|
||
console.error('表格渲染错误:', msg);
|
||
layer.msg('表格渲染出错,请刷新重试');
|
||
}
|
||
});
|
||
},
|
||
|
||
// 打开编辑弹窗
|
||
openEditModal: function(row, type, tableObj) {
|
||
var isLease = type === 'lease';
|
||
var rowId = isLease ? (row.supId || row.id) : row.id;
|
||
var quantityField = isLease ? 'leaseNum' : 'returnNum';
|
||
|
||
console.log('打开编辑弹窗:', row, '类型:', type, 'rowId:', rowId);
|
||
|
||
// 获取原始数据
|
||
var originalRow = $.extend(true, {}, row);
|
||
|
||
layer.open({
|
||
type: 1,
|
||
title: '修改' + (isLease ? '领料' : '退料') + '信息',
|
||
area: ['500px', '350px'],
|
||
content: `
|
||
<div style="padding: 20px;">
|
||
<form class="layui-form" lay-filter="editForm">
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">物资名称</label>
|
||
<div class="layui-input-block">
|
||
<input type="text" value="${row.machineTypeName || ''}" class="layui-input" disabled>
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">${isLease ? '领料' : '退料'}数量</label>
|
||
<div class="layui-input-block">
|
||
<input type="number" id="editQuantity" value="${row[quantityField] || 0}" disabled
|
||
class="layui-input" lay-verify="required|number|integer" step="1" min="0">
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">操作时间</label>
|
||
<div class="layui-input-block">
|
||
<input type="text" id="editOperateTime" value="${row.operateTime || ''}"
|
||
class="layui-input" lay-verify="required">
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item">
|
||
<button type="button" class="layui-btn" id="saveEditBtn">保存修改</button>
|
||
<button type="button" class="layui-btn layui-btn-primary" id="cancelEdit">取消</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
`,
|
||
success: function(layero, index) {
|
||
// 渲染表单
|
||
form.render();
|
||
// 【新增】自定义整数验证规则(限制数量为非负整数)
|
||
form.verify({
|
||
integer: function(value, item){
|
||
if(!/^\d+$/.test(value)){
|
||
return '数量必须为非负整数!';
|
||
}
|
||
}
|
||
});
|
||
// 初始化时间选择器
|
||
laydate.render({
|
||
elem: '#editOperateTime',
|
||
type: 'datetime',
|
||
format: 'yyyy-MM-dd HH:mm:ss',
|
||
lang: 'zh-CN'
|
||
});
|
||
|
||
$('#saveEditBtn').on('click', function () {
|
||
var newQuantity = parseInt($('#editQuantity').val()) || 0;
|
||
var newTime = $('#editOperateTime').val();
|
||
|
||
var hasChange = false;
|
||
var modifiedFields = [];
|
||
// 统一获取唯一标识和字段名(避免重复代码)
|
||
var idField = isLease ? 'supId' : 'id';
|
||
var quantityField = isLease ? 'leaseNum' : 'returnNum';
|
||
|
||
// 从原始数据中获取永久基准值(核心:对比服务端初始值)
|
||
var originalDataList = isLease ? window.originalTableData.lease : window.originalTableData.return;
|
||
var originalSourceRow = originalDataList.find(item => item[idField] == rowId) || row;
|
||
var originalQuantity = parseFloat(originalSourceRow[quantityField]) || 0;
|
||
var originalOperateTime = originalSourceRow.operateTime || '';
|
||
|
||
// 1. 处理数量字段(对比原始值,修复改回逻辑)
|
||
if (newQuantity !== originalQuantity) {
|
||
projectCost.markModified(type, rowId, quantityField, originalQuantity, newQuantity, row);
|
||
row[quantityField] = newQuantity;
|
||
// 【新增核心】自动计算金额:单价 × 新数量,保留2位小数
|
||
var unitPrice = parseFloat(row.price || row.unitPrice || 0);
|
||
row.amount = (unitPrice * newQuantity).toFixed(2);
|
||
hasChange = true;
|
||
modifiedFields.push(quantityField);
|
||
} else if (projectCost.isFieldModified(type, rowId, quantityField)) {
|
||
// 改回原始值:删除该字段修改记录(字段名加引号,避免变量解析)
|
||
delete window.modifiedRows[type][rowId].fields[quantityField];
|
||
// 同步行对象值为原始值(关键:保证数据源与原始值一致)
|
||
row[quantityField] = originalQuantity;
|
||
// 【新增】改回原始值时同步恢复原始金额
|
||
row.amount = (parseFloat(row.price || row.unitPrice || 0) * originalQuantity).toFixed(2);
|
||
hasChange = true; // 标记变更,触发后续数据源更新和表格重渲染
|
||
}
|
||
|
||
// 2. 处理操作时间字段(修复operateTime未加引号问题+改回逻辑)
|
||
if (newTime !== originalOperateTime) {
|
||
projectCost.markModified(type, rowId, 'operateTime', originalOperateTime, newTime, row);
|
||
row.operateTime = newTime;
|
||
hasChange = true;
|
||
modifiedFields.push('operateTime');
|
||
} else if (projectCost.isFieldModified(type, rowId, 'operateTime')) {
|
||
// 【核心修复】operateTime加引号,作为字符串字段名(解决未定义报错)
|
||
delete window.modifiedRows[type][rowId].fields['operateTime'];
|
||
// 同步行对象值为原始值(关键:保证数据源与原始值一致)
|
||
row.operateTime = originalOperateTime;
|
||
hasChange = true; // 标记变更,触发后续数据源更新和表格重渲染
|
||
}
|
||
|
||
// 3. 清理无字段的空修改记录(避免冗余数据)
|
||
if (window.modifiedRows[type][rowId] && Object.keys(window.modifiedRows[type][rowId].fields).length === 0) {
|
||
delete window.modifiedRows[type][rowId];
|
||
}
|
||
|
||
// 4. 统一处理:只要有字段变更/还原,就更新全局数据源+重渲染表格
|
||
if (hasChange) {
|
||
// 同步更新全局数据源(window.currentLeaseData / window.currentReturnData)
|
||
var globalData = isLease ? window.currentLeaseData : window.currentReturnData;
|
||
for (var i = 0; i < globalData.length; i++) {
|
||
if (globalData[i][idField] == rowId) {
|
||
globalData[i] = row;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 【核心修改】调用全局列配置,解决未定义错误
|
||
var tableId = isLease ? '#leaseTable' : '#returnTable';
|
||
var tableData = isLease ? window.currentLeaseData : window.currentReturnData;
|
||
var tableCols = isLease ? window.tableColumnConfig.leaseCols : window.tableColumnConfig.returnCols;
|
||
|
||
// 重新渲染表格(关键:改回原始值时也会执行,保证数据同步)
|
||
projectCost.renderTableWithModifications(tableId, tableData, tableCols, type);
|
||
layer.msg('修改已保存(本地)');
|
||
} else {
|
||
// 无任何变更(包括未修改/已改回原始值),提示无修改
|
||
layer.msg('没有需要修改任何内容');
|
||
}
|
||
|
||
layer.close(index);
|
||
});
|
||
|
||
// 取消按钮
|
||
$('#cancelEdit').click(function() {
|
||
layer.close(index);
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
// 初始化列表页
|
||
init: function() {
|
||
// 初始化日期选择器
|
||
laydate.render({
|
||
elem: '#startDate',
|
||
lang: 'zh-CN'
|
||
});
|
||
laydate.render({
|
||
elem: '#endDate',
|
||
lang: 'zh-CN'
|
||
});
|
||
|
||
// 监听工具条事件
|
||
table.on('tool(LAY-project-cost-list)', function(obj){
|
||
var data = obj.data;
|
||
if(obj.event === 'edit'){
|
||
var editUrl = baseUrl + '/backstage/projectCost/calculation_edit'
|
||
+ '?id=' + data.id
|
||
+ '&projectId=' + data.projectId
|
||
+ '&startTime=' + data.startTime
|
||
+ '&endTime=' + data.endTime;
|
||
layer.open({
|
||
type: 2,
|
||
title: '修改',
|
||
content: editUrl,
|
||
area: ['90%', '90%'],
|
||
maxmin: true
|
||
});
|
||
}
|
||
});
|
||
|
||
},
|
||
|
||
// 生成结算数据 - 修复字段匹配问题
|
||
generateSettlement: function(data) {
|
||
window.editPageField = {
|
||
calculationId: data.calculationId,
|
||
projectId: data.projectId,
|
||
startTime: data.startTime,
|
||
endTime: data.endTime
|
||
};
|
||
|
||
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;
|
||
} else if(res.res === 1) {
|
||
isSuccess = true;
|
||
} else if(res.code === 200 || res.code === 0 || res.code === '0') {
|
||
isSuccess = true;
|
||
} else if(res.status === 'success' || res.status === 200 || res.status === 0) {
|
||
isSuccess = true;
|
||
}
|
||
}
|
||
|
||
console.log("判断是否成功: ", isSuccess, "响应结构:", JSON.stringify(res).substring(0, 100) + "...");
|
||
|
||
if(isSuccess) {
|
||
$('#data-container').empty().show();
|
||
|
||
let responseData = {};
|
||
if(res.data) {
|
||
responseData = res.data;
|
||
} else if(res.obj) {
|
||
responseData = res.obj;
|
||
} else {
|
||
responseData = res;
|
||
}
|
||
|
||
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(", "));
|
||
}
|
||
|
||
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) {
|
||
console.log("未能根据operateType分离数据,显示所有明细作为领料");
|
||
leaseData = details;
|
||
}
|
||
} else {
|
||
console.warn("未找到预期的数据结构,尝试深度查找数据");
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
if(!foundData && res.res === 1) {
|
||
console.log("检测到res.res===1格式的API,尝试从res.obj中提取数据");
|
||
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;
|
||
|
||
// 【新增】初始化原始数据(深拷贝,防止后续修改全局数据源时污染原始值)
|
||
window.originalTableData.lease = $.extend(true, [], leaseData);
|
||
window.originalTableData.return = $.extend(true, [], 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;
|
||
};
|
||
|
||
if(calculationResults.length > 0) {
|
||
var calcHeight = calcTableHeight(calculationResults.length);
|
||
|
||
// 检查calculationResults的字段
|
||
console.log('calculationResults字段:', calculationResults.length > 0 ? Object.keys(calculationResults[0]) : '无数据');
|
||
|
||
table.render({
|
||
elem: '#calculationTable',
|
||
data: calculationResults,
|
||
cols: [[
|
||
{field: 'machineTypeId', title: '物资ID', width: '10%', hide: true},
|
||
{field: 'machineTypeName', title: '物资名称', width: '20%'},
|
||
{field: 'machineModel', title: '规格型号', width: '20%'},
|
||
{field: 'machineUnit', title: '单位', width: '10%'},
|
||
{field: 'currentCount', title: '未退还数量', width: '10%', templet: function(d){
|
||
return d.currentCount || 0;
|
||
}},
|
||
{field: 'price', title: '单价(元/天)', width: '10%', templet: function(d){
|
||
return d.price ? d.price.toFixed(2) : '0.00';
|
||
}},
|
||
{field: 'amount', title: '金额(元)', width: '10%', templet: function(d){
|
||
return d.amount ? d.amount.toFixed(2) : '0.00';
|
||
}},
|
||
{title: '操作', width: '9%', templet: function(d){
|
||
return '<a class="layui-btn layui-btn-xs" lay-event="viewDetail">查看明细</a>';
|
||
}}
|
||
]],
|
||
page: false,
|
||
height: calcHeight,
|
||
limit: 1000,
|
||
lang: 'zh-CN'
|
||
});
|
||
|
||
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;
|
||
|
||
if (currentCount === 0 && operateTimeStr) {
|
||
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>';
|
||
detailHtml += '</div>';
|
||
detailHtml += '</div>';
|
||
|
||
const layerIndex = layer.open({
|
||
type: 1,
|
||
title: data.machineTypeName + ' 使用明细',
|
||
content: detailHtml,
|
||
area: ['800px', '500px'],
|
||
shadeClose: true,
|
||
success: function () {
|
||
layui.element.render('tab');
|
||
}
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
$('#resultTableContainer').html('<div style="padding: 20px; text-align: center;">暂无租赁费用计算结果</div>');
|
||
}
|
||
|
||
// 渲染领料表格 - 修复字段匹配问题
|
||
if (leaseData && leaseData.length > 0) {
|
||
console.log('领料数据字段:', Object.keys(leaseData[0]));
|
||
|
||
// 【修改】赋值给全局列配置,替换原有局部var leaseCols
|
||
window.tableColumnConfig.leaseCols = [[
|
||
{field: 'supId', title: 'ID', hide: true},
|
||
{field: 'machineTypeName', title: '物资名称', width: 150, 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: 70, 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){
|
||
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: 'operateTime', title: '操作时间', width: 180, templet: function(d){
|
||
return d.operateTime || '';
|
||
}},
|
||
{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: 80, 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 || '';
|
||
}},
|
||
{title: '操作', width: 100, align: 'center', fixed: 'right', templet: function(d){
|
||
return '<button class="layui-btn layui-btn-xs layui-btn-normal" lay-event="editLease">修改</button>';
|
||
}}
|
||
]];
|
||
|
||
projectCost.renderTableWithModifications('#leaseTable', leaseData, window.tableColumnConfig.leaseCols, 'lease');
|
||
|
||
// 监听修改事件
|
||
table.on('tool(leaseTable)', function(obj) {
|
||
if (obj.event === 'editLease') {
|
||
projectCost.openEditModal(obj.data, 'lease', obj);
|
||
}
|
||
});
|
||
} else {
|
||
$('#leaseTableContainer').html('<div style="padding: 20px; text-align: center;">暂无物资领料明细</div>');
|
||
}
|
||
|
||
// 渲染退料表格 - 修复字段匹配问题
|
||
// 渲染退料表格 - 修复字段匹配问题
|
||
if (returnData && returnData.length > 0) {
|
||
console.log('退料数据字段:', Object.keys(returnData[0]));
|
||
|
||
// 【修改】赋值给全局列配置,替换原有局部var returnCols
|
||
window.tableColumnConfig.returnCols = [[
|
||
{field: 'id', title: 'ID', hide: true},
|
||
{field: 'machineTypeName', title: '物资名称', width: 150, 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: 70, 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){
|
||
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: 'operateTime', title: '操作时间', width: 180, templet: function(d){
|
||
return d.operateTime || '';
|
||
}},
|
||
{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: 80, 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 || '';
|
||
}},
|
||
{title: '操作', width: 100, align: 'center', fixed: 'right', templet: function(d){
|
||
return '<button class="layui-btn layui-btn-xs layui-btn-normal" lay-event="editReturn">修改</button>';
|
||
}}
|
||
]];
|
||
|
||
projectCost.renderTableWithModifications('#returnTable', returnData, window.tableColumnConfig.returnCols, 'return');
|
||
|
||
// 监听修改事件
|
||
table.on('tool(returnTable)', function(obj) {
|
||
if (obj.event === 'editReturn') {
|
||
projectCost.openEditModal(obj.data, 'return', obj);
|
||
}
|
||
});
|
||
} 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('网络错误,请重试');
|
||
}
|
||
});
|
||
},
|
||
};
|
||
|
||
// 输出接口
|
||
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;
|
||
} |