var pageCurr;
|
layui.config({
|
base: baseUrl + "/static/layui/lay/modules/"
|
}).use(['layer', 'form', 'table', 'util', 'admin', 'laydate', 'laytpl'], function () {
|
var $ = layui.jquery;
|
var layer = layui.layer;
|
var form = layui.form;
|
var table = layui.table;
|
var util = layui.util;
|
var admin = layui.admin;
|
var layDate = layui.laydate;
|
var laytpl = layui.laytpl;
|
|
// 渲染表格
|
tableIns = table.render({
|
elem: '#monthlySettle',
|
url: baseUrl + '/monthlySettle/list/auth',
|
headers: {token: localStorage.getItem('token')},
|
method: 'POST',
|
page: true,
|
cellMinWidth: 100,
|
where: {},
|
cols: [[
|
{type: 'numbers'},
|
{field: 'settleNo', title: '月结编号', width: 180},
|
{field: 'startDate$', align: 'center', title: '起始日期', width: 120},
|
{field: 'endDate$', align: 'center', title: '结束日期', width: 120},
|
{field: 'totalInQty', align: 'center', title: '总入库数量', width: 120},
|
{field: 'totalOutQty', align: 'center', title: '总出库数量', width: 120},
|
{field: 'totalMaterials', align: 'center', title: '物料种类数', width: 120},
|
{field: 'createTime$', title: '创建时间', minWidth: 180, width: 180},
|
{align: 'center', title: '操作', toolbar: '#operate', width: 240}
|
]],
|
request: {
|
pageName: 'curr',
|
pageSize: 'limit'
|
},
|
parseData: function (res) {
|
return {
|
'code': res.code,
|
'msg': res.msg,
|
'count': res.data.total,
|
'data': res.data.records
|
}
|
},
|
response: {
|
statusCode: 200
|
},
|
done: function (res, curr, count) {
|
if (res.code === 403) {
|
top.location.href = baseUrl + "/";
|
}
|
pageCurr = curr;
|
// 延迟调用权限控制,确保表格操作列的按钮已经渲染完成
|
setTimeout(function() {
|
var param = window.location.href.split("?")[1];
|
if (null != param) {
|
var resourceId = param.split("=")[1];
|
$.ajax({
|
url: baseUrl+"/power/menu/"+resourceId+"/auth",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'GET',
|
async: false,
|
success: function (res) {
|
if (res.code === 200){
|
for(var i = 0, len = res.data.length; i < len; i++) {
|
var code = res.data[i].code;
|
$('#'+code).css("display", "inline-block");
|
$('.'+code).css("display", "inline-block");
|
}
|
} else if (res.code === 403){
|
top.location.href = baseUrl+"/";
|
} else {
|
layer.msg(res.msg)
|
}
|
}
|
});
|
}
|
}, 200);
|
}
|
});
|
|
// 搜索
|
form.on('submit(search)', function (data) {
|
pageCurr = 1;
|
tableReload(false);
|
});
|
|
// 重置
|
form.on('submit(reset)', function (data) {
|
pageCurr = 1;
|
clearFormVal($('#search-box'));
|
// 手动清空日期范围选择器
|
$('input[name="date_range"]').val('');
|
// 显式清空表格配置中的 where 参数
|
if (tableIns && tableIns.config) {
|
tableIns.config.where = {};
|
}
|
// 使用 setTimeout 确保表单值被完全清空后再重新加载表格
|
setTimeout(function() {
|
tableReload(false);
|
}, 0);
|
});
|
|
// 日期范围选择器
|
layDate.render({
|
elem: '.layui-laydate-range',
|
type: 'date',
|
range: true
|
});
|
|
// 发起月结
|
$('#startSettleBtn').click(function () {
|
showStartSettleDialog();
|
});
|
|
// 显示发起月结弹窗
|
function showStartSettleDialog() {
|
admin.open({
|
type: 1,
|
title: '发起月结',
|
content: $('#startSettleDialog').html(),
|
area: '500px',
|
success: function (layero, dIndex) {
|
var startDateIns = null;
|
var endDateIns = null;
|
|
// 初始化结束日期选择器(先初始化,后续再设置min)
|
// 使用 setTimeout 确保 DOM 已完全渲染
|
setTimeout(function() {
|
var $endDate = layero.find('#endDate');
|
if ($endDate.length > 0) {
|
endDateIns = layDate.render({
|
elem: $endDate[0],
|
type: 'date',
|
done: function(value, date, endDate){
|
var startDate = layero.find('#startDate').val();
|
if (startDate && value < startDate) {
|
layer.msg('结束日期不能早于起始日期', {icon: 2});
|
layero.find('#endDate').val('');
|
checkUnfinishedOrders(startDate, '');
|
return;
|
}
|
checkUnfinishedOrders(startDate, value);
|
}
|
});
|
}
|
}, 50);
|
|
// 获取下一个月结的起始日期(最晚月结记录结束日期的下一天)
|
$.ajax({
|
url: baseUrl + '/monthlySettle/nextStartDate/auth',
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (res) {
|
if (res.code === 200) {
|
// 数据在 msg 字段中
|
var nextStartDate = res.msg;
|
// 确保 nextStartDate 是字符串格式
|
if (nextStartDate != null && nextStartDate !== '') {
|
// 转换为字符串,处理可能的数字或其他类型
|
nextStartDate = String(nextStartDate).trim();
|
if (nextStartDate !== '' && nextStartDate !== 'null') {
|
// 使用 setTimeout 确保 DOM 已完全渲染
|
setTimeout(function() {
|
// 使用 layero.find 查找弹窗内的元素
|
var $startDate = layero.find('#startDate');
|
if ($startDate.length > 0) {
|
$startDate.val(nextStartDate);
|
$startDate.attr('readonly', true);
|
$startDate.css('background-color', '#f5f5f5');
|
$startDate.css('cursor', 'not-allowed');
|
console.log('已设置起始日期:', $startDate.val());
|
} else {
|
console.error('未找到 #startDate 元素');
|
}
|
}, 50);
|
|
// 获取最晚结束日期用于提示
|
$.ajax({
|
url: baseUrl + '/monthlySettle/latestEndDate/auth',
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (latestRes) {
|
var latestEndDate = (latestRes.code === 200 && latestRes.msg) ? String(latestRes.msg) : '';
|
var tipMsg = latestEndDate
|
? '提示:最晚月结记录结束日期为 ' + latestEndDate + ',本次月结起始日期已自动设置为 ' + nextStartDate + ',不可修改'
|
: '提示:本次月结起始日期已自动设置为 ' + nextStartDate + ',不可修改';
|
layero.find('#settleTip').html(tipMsg);
|
},
|
error: function() {
|
layero.find('#settleTip').html('提示:本次月结起始日期已自动设置为 ' + nextStartDate + ',不可修改');
|
}
|
});
|
|
// 重新渲染结束日期选择器,设置最小日期为起始日期
|
setTimeout(function() {
|
endDateIns = layDate.render({
|
elem: layero.find('#endDate')[0],
|
type: 'date',
|
min: nextStartDate,
|
done: function(value, date, endDate){
|
var startDate = layero.find('#startDate').val();
|
if (startDate && value < startDate) {
|
layer.msg('结束日期不能早于起始日期', {icon: 2});
|
layero.find('#endDate').val('');
|
checkUnfinishedOrders(startDate, '');
|
return;
|
}
|
checkUnfinishedOrders(startDate, value);
|
}
|
});
|
}, 100);
|
}
|
} else {
|
// 没有月结记录,允许自由选择起始日期
|
setTimeout(function() {
|
var $startDate = layero.find('#startDate');
|
if ($startDate.length > 0) {
|
startDateIns = layDate.render({
|
elem: $startDate[0],
|
type: 'date',
|
done: function(value, date, endDate){
|
// 当起始日期改变时,重新渲染结束日期选择器,设置最小日期
|
var currentEndDate = layero.find('#endDate').val();
|
if (currentEndDate && currentEndDate < value) {
|
layero.find('#endDate').val('');
|
layero.find('#settleTip').html('<span style="color: #ff5722;">警告:结束日期不能早于起始日期,请重新选择结束日期</span>');
|
}
|
|
// 重新渲染结束日期选择器
|
endDateIns = layDate.render({
|
elem: layero.find('#endDate')[0],
|
type: 'date',
|
min: value,
|
done: function(endValue, endDate, endEndDate){
|
if (value && endValue < value) {
|
layer.msg('结束日期不能早于起始日期', {icon: 2});
|
layero.find('#endDate').val('');
|
checkUnfinishedOrders(value, '');
|
return;
|
}
|
checkUnfinishedOrders(value, endValue);
|
}
|
});
|
|
checkUnfinishedOrders(value, layero.find('#endDate').val());
|
}
|
});
|
layero.find('#settleTip').html('提示:首次月结,请选择起始日期');
|
}
|
}, 50);
|
}
|
} else if (res.code === 403) {
|
top.location.href = baseUrl + "/";
|
}
|
},
|
error: function() {
|
// 如果获取失败,允许自由选择起始日期
|
setTimeout(function() {
|
var $startDate = layero.find('#startDate');
|
if ($startDate.length > 0) {
|
startDateIns = layDate.render({
|
elem: $startDate[0],
|
type: 'date',
|
done: function(value, date, endDate){
|
var currentEndDate = layero.find('#endDate').val();
|
if (currentEndDate && currentEndDate < value) {
|
layero.find('#endDate').val('');
|
layero.find('#settleTip').html('<span style="color: #ff5722;">警告:结束日期不能早于起始日期,请重新选择结束日期</span>');
|
}
|
|
endDateIns = layDate.render({
|
elem: layero.find('#endDate')[0],
|
type: 'date',
|
min: value,
|
done: function(endValue, endDate, endEndDate){
|
if (value && endValue < value) {
|
layer.msg('结束日期不能早于起始日期', {icon: 2});
|
layero.find('#endDate').val('');
|
checkUnfinishedOrders(value, '');
|
return;
|
}
|
checkUnfinishedOrders(value, endValue);
|
}
|
});
|
|
checkUnfinishedOrders(value, layero.find('#endDate').val());
|
}
|
});
|
layero.find('#settleTip').html('提示:请选择起始日期');
|
}
|
}, 50);
|
}
|
});
|
|
// 表单提交事件
|
form.on('submit(startSettleSubmit)', function (data) {
|
var startDate = layero.find('#startDate').val();
|
var endDate = layero.find('#endDate').val();
|
|
if (!startDate || !endDate) {
|
layer.msg('请选择起始日期和结束日期', {icon: 2});
|
return false;
|
}
|
|
if (startDate > endDate) {
|
layer.msg('结束日期不能早于起始日期,请重新选择', {icon: 2});
|
return false;
|
}
|
|
// 将结束日期设置为当天的 23:59:59
|
var endDateTime = endDate + ' 23:59:59';
|
|
layer.load(2);
|
$.ajax({
|
url: baseUrl + '/monthlySettle/start/auth',
|
headers: {'token': localStorage.getItem('token')},
|
data: {
|
startDate: startDate,
|
endDate: endDateTime
|
},
|
method: 'POST',
|
success: function (res) {
|
layer.closeAll('loading');
|
if (res.code === 200) {
|
layer.close(dIndex);
|
tableIns.reload({page: {curr: 1}});
|
layer.msg(res.msg || '月结成功', {icon: 1});
|
} else if (res.code === 403) {
|
top.location.href = baseUrl + "/";
|
} else {
|
layer.msg(res.msg || '月结失败', {icon: 2});
|
}
|
},
|
error: function() {
|
layer.closeAll('loading');
|
layer.msg('月结请求失败', {icon: 2});
|
}
|
});
|
return false;
|
});
|
}
|
});
|
}
|
|
// 检查未完成的订单
|
function checkUnfinishedOrders(startDate, endDate) {
|
if (!startDate && !endDate) {
|
$('#settleTip').html('<span style="color: #999;">请选择起始日期和结束日期</span>');
|
return;
|
}
|
|
if (!startDate) {
|
$('#settleTip').html('<span style="color: #999;">请选择起始日期</span>');
|
return;
|
}
|
|
if (!endDate) {
|
$('#settleTip').html('<span style="color: #999;">请选择结束日期</span>');
|
return;
|
}
|
|
// 验证日期范围
|
if (startDate > endDate) {
|
$('#settleTip').html('<span style="color: #ff5722;">警告:结束日期不能早于起始日期,请重新选择</span>');
|
return;
|
}
|
|
$.ajax({
|
url: baseUrl + '/monthlySettle/checkUnfinished/auth',
|
headers: {'token': localStorage.getItem('token')},
|
data: {
|
startDate: startDate,
|
endDate: endDate
|
},
|
method: 'POST',
|
success: function (res) {
|
if (res.code === 200) {
|
$('#settleTip').html('<span style="color: #5FB878;">✓ 日期范围有效,可以正常进行月结</span>');
|
} else {
|
$('#settleTip').html('<span style="color: #ff5722;">警告:' + (res.msg || '月结时间范围内存在未完成的订单,无法进行月结') + '</span>');
|
}
|
},
|
error: function() {
|
$('#settleTip').html('<span style="color: #ff5722;">检查失败,请重试</span>');
|
}
|
});
|
}
|
|
// 工具条点击事件
|
table.on('tool(monthlySettle)', function (obj) {
|
var data = obj.data;
|
var layEvent = obj.event;
|
if (layEvent === 'detail') {
|
showDetailDialog(data);
|
} else if (layEvent === 'export') {
|
exportDetail(data);
|
} else if (layEvent === 'delete') {
|
deleteSettle(data);
|
}
|
});
|
|
// 显示明细弹窗
|
function showDetailDialog(data) {
|
layer.load(2);
|
$.ajax({
|
url: baseUrl + '/monthlySettle/statistics/' + data.id + '/auth',
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (res) {
|
layer.closeAll('loading');
|
if (res.code === 200) {
|
var settle = res.data.settle;
|
var details = res.data.details;
|
|
// 先渲染模板
|
var template = $('#detailDialog').html();
|
var html = laytpl(template).render(settle);
|
|
admin.open({
|
type: 1,
|
title: '月结明细 - ' + settle.settleNo,
|
content: html,
|
area: ['90%', '80%'],
|
success: function (layero, dIndex) {
|
// 渲染明细表格(对账单格式)
|
table.render({
|
elem: '#detailTable',
|
data: details,
|
page: true,
|
cellMinWidth: 100,
|
width: '100%',
|
cols: [[
|
{type: 'numbers', title: '序号', width: 60, align: 'center'},
|
{field: 'matnr', title: '物料编码', width: 150},
|
{field: 'maktx', title: '物料名称', width: 200},
|
{field: 'batch', title: '批次', width: 120},
|
{field: 'brand', title: '品牌', width: 120},
|
{
|
field: 'beginningQty',
|
align: 'right',
|
title: '期初库存',
|
width: 120,
|
templet: function (d) {
|
var qty = parseFloat(d.beginningQty || 0);
|
return qty.toFixed(2);
|
}
|
},
|
{
|
field: 'endingQty',
|
align: 'right',
|
title: '期末库存',
|
width: 120,
|
templet: function (d) {
|
var qty = parseFloat(d.endingQty || 0);
|
return qty.toFixed(2);
|
}
|
},
|
{
|
field: 'diffQty',
|
align: 'right',
|
title: '差异数量',
|
width: 120,
|
templet: function (d) {
|
var diff = parseFloat(d.diffQty || 0);
|
if (diff > 0) {
|
return '<span style="color: #5FB878;">+' + diff.toFixed(2) + '</span>';
|
} else if (diff < 0) {
|
return '<span style="color: #ff5722;">' + diff.toFixed(2) + '</span>';
|
} else {
|
return diff.toFixed(2);
|
}
|
}
|
},
|
{
|
field: 'inQty',
|
align: 'right',
|
title: '本期入库',
|
width: 120,
|
templet: function (d) {
|
var qty = parseFloat(d.inQty || 0);
|
return qty.toFixed(2);
|
}
|
},
|
{
|
field: 'outQty',
|
align: 'right',
|
title: '本期出库',
|
width: 120,
|
templet: function (d) {
|
var qty = parseFloat(d.outQty || 0);
|
return qty.toFixed(2);
|
}
|
}
|
]]
|
});
|
}
|
});
|
} else if (res.code === 403) {
|
top.location.href = baseUrl + "/";
|
} else {
|
layer.msg(res.msg || '获取明细失败', {icon: 2});
|
}
|
}
|
});
|
}
|
|
// 导出月结明细
|
function exportDetail(data) {
|
layer.confirm('确定导出月结明细 "' + data.settleNo + '" 吗?', {
|
shade: .1,
|
skin: 'layui-layer-admin'
|
}, function (i) {
|
layer.close(i);
|
layer.load(2);
|
$.ajax({
|
url: baseUrl + '/monthlySettle/detail/export/' + data.id + '/auth',
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (res) {
|
layer.closeAll('loading');
|
if (res.code === 200) {
|
// 定义表头
|
var titles = [
|
'物料编码',
|
'物料名称',
|
'批次',
|
'品牌',
|
'期初库存',
|
'期末库存',
|
'差异数量',
|
'本期入库',
|
'本期出库'
|
];
|
// 使用 table.exportFile 导出
|
table.exportFile(titles, res.data, 'xls');
|
layer.msg('导出成功', {icon: 1});
|
} else if (res.code === 403) {
|
top.location.href = baseUrl + "/";
|
} else {
|
layer.msg(res.msg || '导出失败', {icon: 2});
|
}
|
},
|
error: function() {
|
layer.closeAll('loading');
|
layer.msg('导出失败', {icon: 2});
|
}
|
});
|
});
|
}
|
|
// 删除月结记录
|
function deleteSettle(data) {
|
layer.confirm('确认要删除月结记录 "' + data.settleNo + '" 吗?删除后将清除关联的出入库订单月结信息,可以重新进行月结。', {
|
shade: .1,
|
skin: 'layui-layer-admin'
|
}, function (i) {
|
layer.close(i);
|
layer.load(2);
|
$.ajax({
|
url: baseUrl + '/monthlySettle/' + data.id + '/auth',
|
headers: {'token': localStorage.getItem('token')},
|
method: 'DELETE',
|
success: function (res) {
|
layer.closeAll('loading');
|
if (res.code === 200) {
|
tableIns.reload({page: {curr: 1}});
|
layer.msg(res.msg || '删除成功', {icon: 1});
|
} else if (res.code === 403) {
|
top.location.href = baseUrl + "/";
|
} else {
|
layer.msg(res.msg || '删除失败', {icon: 2});
|
}
|
},
|
error: function() {
|
layer.closeAll('loading');
|
layer.msg('删除失败', {icon: 2});
|
}
|
});
|
});
|
}
|
});
|
|
function tableReload(child) {
|
var searchData = {};
|
$.each($('#search-box [name]').serializeArray(), function() {
|
var value = this.value;
|
// 处理日期范围字段
|
if (this.name === 'date_range') {
|
// 只处理非空值
|
if (value && value.trim() !== '') {
|
var dates = value.split(' - ');
|
if (dates.length === 2) {
|
var startDate = dates[0].trim();
|
var endDate = dates[1].trim();
|
if (startDate !== '' && endDate !== '') {
|
searchData.startDate = startDate;
|
searchData.endDate = endDate;
|
}
|
}
|
}
|
} else if (this.name === 'settle_no') {
|
// 只处理非空值
|
var trimmedValue = value ? value.trim() : '';
|
if (trimmedValue !== '') {
|
searchData.settleNo = trimmedValue;
|
}
|
}
|
});
|
|
// 获取 table 实例
|
var tableInstance = child ? parent.tableIns : tableIns;
|
|
// 如果 searchData 为空对象,需要显式传入覆盖所有可能参数的对象
|
// 因为 layui table 可能会合并旧的参数,即使传入空对象也可能保留旧值
|
if (Object.keys(searchData).length === 0) {
|
if (tableInstance && tableInstance.config) {
|
// 先保存旧的 where 中可能存在的所有键
|
var oldWhereKeys = [];
|
if (tableInstance.config.where) {
|
for (var key in tableInstance.config.where) {
|
if (tableInstance.config.where.hasOwnProperty(key)) {
|
oldWhereKeys.push(key);
|
}
|
}
|
}
|
|
// 完全替换 where 对象
|
tableInstance.config.where = {};
|
|
// 如果之前有参数,创建一个明确覆盖的对象,将所有旧参数设置为空字符串
|
// 使用空字符串而不是 null,因为 layui 可能会过滤 null 值
|
if (oldWhereKeys.length > 0) {
|
var overrideWhere = {};
|
oldWhereKeys.forEach(function(key) {
|
overrideWhere[key] = ''; // 设置为空字符串来覆盖旧值
|
});
|
searchData = overrideWhere;
|
console.log('创建覆盖对象,旧参数键:', oldWhereKeys, '覆盖对象:', JSON.stringify(overrideWhere));
|
} else {
|
// 即使没有旧参数,也创建一个包含所有可能参数的空对象
|
// 这样可以确保覆盖任何可能的旧参数
|
searchData = {
|
settleNo: '',
|
startDate: '',
|
endDate: ''
|
};
|
console.log('创建默认覆盖对象:', JSON.stringify(searchData));
|
}
|
}
|
}
|
|
// 构建 reload 参数
|
var reloadOptions = {
|
where: searchData,
|
page: {
|
curr: pageCurr
|
},
|
done: function (res, curr, count) {
|
if (res.code === 403) {
|
top.location.href = baseUrl+"/";
|
}
|
pageCurr=curr;
|
// 延迟调用权限控制,确保表格操作列的按钮已经渲染完成
|
setTimeout(function() {
|
var param = window.location.href.split("?")[1];
|
if (null != param) {
|
var resourceId = param.split("=")[1];
|
$.ajax({
|
url: baseUrl+"/power/menu/"+resourceId+"/auth",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'GET',
|
async: false,
|
success: function (res) {
|
if (res.code === 200){
|
for(var i = 0, len = res.data.length; i < len; i++) {
|
var code = res.data[i].code;
|
$('#'+code).css("display", "inline-block");
|
$('.'+code).css("display", "inline-block");
|
}
|
} else if (res.code === 403){
|
top.location.href = baseUrl+"/";
|
} else {
|
layer.msg(res.msg)
|
}
|
}
|
});
|
}
|
}, 200);
|
if (res.data.length === 0 && count !== 0) {
|
var reloadTableInstance = child ? parent.tableIns : tableIns;
|
// 如果 searchData 为空,也完全替换 where 对象
|
if (Object.keys(searchData).length === 0 && reloadTableInstance && reloadTableInstance.config) {
|
reloadTableInstance.config.where = {};
|
}
|
reloadTableInstance.reload({
|
where: searchData,
|
page: {
|
curr: pageCurr-1
|
}
|
});
|
pageCurr -= 1;
|
}
|
}
|
};
|
|
// 调试:打印 reload 前的配置
|
console.log('reload 前的 config.where:', JSON.stringify(tableInstance.config ? tableInstance.config.where : 'no config'));
|
console.log('reload 时的 where 参数:', JSON.stringify(reloadOptions.where));
|
|
tableInstance.reload(reloadOptions);
|
|
// 调试:打印 reload 后的配置
|
setTimeout(function() {
|
console.log('reload 后的 config.where:', JSON.stringify(tableInstance.config ? tableInstance.config.where : 'no config'));
|
}, 100);
|
}
|