2026-01-21 10:34:06 +08:00
|
|
|
|
let table, layer, form, laydate;
|
|
|
|
|
|
let teamQualityChart = null;
|
|
|
|
|
|
let qualityRatioChart = null;
|
|
|
|
|
|
let currentPage = 1;
|
|
|
|
|
|
let pageSize = 10;
|
2026-01-23 16:33:21 +08:00
|
|
|
|
let bidCode = parent.parent.$('#bidPro').val();
|
|
|
|
|
|
let keyword = '';
|
2026-01-24 14:23:35 +08:00
|
|
|
|
let modalKeyword = '';
|
|
|
|
|
|
let modalQueryParams = {
|
|
|
|
|
|
projectId: bidCode,
|
|
|
|
|
|
startTestDay: '',
|
|
|
|
|
|
endTestDay: ''
|
|
|
|
|
|
};
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-24 18:55:45 +08:00
|
|
|
|
// 获取当天日期
|
|
|
|
|
|
function getTodayDate() {
|
|
|
|
|
|
const now = new Date();
|
|
|
|
|
|
const year = now.getFullYear();
|
|
|
|
|
|
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
|
const day = String(now.getDate()).padStart(2, '0');
|
|
|
|
|
|
return year + '-' + month + '-' + day;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当月第一天和最后一天(保留用于其他功能)
|
2026-01-23 16:33:21 +08:00
|
|
|
|
function getCurrentMonthRange() {
|
|
|
|
|
|
const now = new Date();
|
|
|
|
|
|
const year = now.getFullYear();
|
|
|
|
|
|
const month = now.getMonth();
|
|
|
|
|
|
|
|
|
|
|
|
// 当月第一天
|
|
|
|
|
|
const firstDay = new Date(year, month, 1);
|
|
|
|
|
|
const startDate = year + '-' + String(month + 1).padStart(2, '0') + '-' + String(firstDay.getDate()).padStart(2, '0');
|
|
|
|
|
|
|
|
|
|
|
|
// 当月最后一天
|
|
|
|
|
|
const lastDay = new Date(year, month + 1, 0);
|
|
|
|
|
|
const endDate = year + '-' + String(month + 1).padStart(2, '0') + '-' + String(lastDay.getDate()).padStart(2, '0');
|
|
|
|
|
|
|
|
|
|
|
|
return { startDate, endDate };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-24 18:55:45 +08:00
|
|
|
|
const today = getTodayDate();
|
2026-01-23 16:33:21 +08:00
|
|
|
|
let queryParams = {
|
|
|
|
|
|
projectId: bidCode,
|
2026-01-24 18:55:45 +08:00
|
|
|
|
startTestDay: today,
|
|
|
|
|
|
endTestDay: today,
|
2026-01-23 16:33:21 +08:00
|
|
|
|
}
|
2026-01-21 10:34:06 +08:00
|
|
|
|
|
|
|
|
|
|
layui.use(["layer", "table", "form", "laydate"], function () {
|
2025-10-14 18:16:49 +08:00
|
|
|
|
layer = layui.layer;
|
|
|
|
|
|
table = layui.table;
|
|
|
|
|
|
form = layui.form;
|
2026-01-21 10:34:06 +08:00
|
|
|
|
laydate = layui.laydate;
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 响应成功后的拦截器
|
|
|
|
|
|
$.ajaxSetup({
|
|
|
|
|
|
beforeSend: function (xhr, options) {
|
|
|
|
|
|
var originalSuccess = options.success;
|
|
|
|
|
|
options.success = function (data, textStatus, jqXhr) {
|
|
|
|
|
|
data = modifyResponseData(data);
|
|
|
|
|
|
originalSuccess.apply(this, arguments);
|
|
|
|
|
|
};
|
2025-10-18 15:55:58 +08:00
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
});
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 初始化页面
|
|
|
|
|
|
initPage();
|
|
|
|
|
|
// 初始化日期范围选择器
|
|
|
|
|
|
initDateRangePicker();
|
|
|
|
|
|
});
|
2025-10-18 15:55:58 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 初始化页面
|
|
|
|
|
|
function initPage() {
|
|
|
|
|
|
initTeamQualityChart();
|
|
|
|
|
|
initQualityRatioChart();
|
|
|
|
|
|
initQualityRecordTable();
|
|
|
|
|
|
initWarningList();
|
|
|
|
|
|
// 初始化自适应处理
|
|
|
|
|
|
// initResizeHandler();
|
|
|
|
|
|
}
|
2025-10-18 15:55:58 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 防抖函数
|
|
|
|
|
|
function debounce(func, wait) {
|
|
|
|
|
|
let timeout;
|
|
|
|
|
|
return function executedFunction(...args) {
|
|
|
|
|
|
const later = () => {
|
|
|
|
|
|
clearTimeout(timeout);
|
|
|
|
|
|
func(...args);
|
|
|
|
|
|
};
|
|
|
|
|
|
clearTimeout(timeout);
|
|
|
|
|
|
timeout = setTimeout(later, wait);
|
|
|
|
|
|
};
|
2025-10-14 18:16:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 初始化自适应处理
|
|
|
|
|
|
function initResizeHandler() {
|
|
|
|
|
|
// 创建防抖的resize处理函数
|
2026-01-23 16:33:21 +08:00
|
|
|
|
const handleResize = debounce(function () {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 重新调整所有图表大小
|
|
|
|
|
|
if (teamQualityChart) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
teamQualityChart.resize();
|
2026-01-23 16:33:21 +08:00
|
|
|
|
} catch (e) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
console.error('调整柱状图大小失败:', e);
|
2025-10-18 15:55:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-21 10:34:06 +08:00
|
|
|
|
if (qualityRatioChart) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
qualityRatioChart.resize();
|
2026-01-23 16:33:21 +08:00
|
|
|
|
} catch (e) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
console.error('调整环形图大小失败:', e);
|
|
|
|
|
|
}
|
2025-10-18 15:55:58 +08:00
|
|
|
|
}
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 重新调整表格大小(如果需要)
|
|
|
|
|
|
if (table) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
table.resize('qualityRecordTable');
|
2026-01-23 16:33:21 +08:00
|
|
|
|
} catch (e) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 表格resize可能不支持,忽略错误
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 300); // 300ms防抖延迟
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 监听窗口resize事件
|
|
|
|
|
|
window.addEventListener('resize', handleResize);
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 监听iframe的resize(如果页面在iframe中)
|
|
|
|
|
|
if (window.parent !== window) {
|
|
|
|
|
|
window.parent.addEventListener('resize', handleResize);
|
2025-10-18 15:55:58 +08:00
|
|
|
|
}
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 页面加载完成后也执行一次resize,确保初始状态正确
|
2026-01-23 16:33:21 +08:00
|
|
|
|
setTimeout(function () {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
handleResize();
|
|
|
|
|
|
}, 100);
|
2025-10-18 15:55:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 初始化施工队伍质量合格率柱状图
|
|
|
|
|
|
function initTeamQualityChart() {
|
|
|
|
|
|
const chartDom = document.getElementById('teamQualityChart');
|
|
|
|
|
|
if (!chartDom) return;
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
if (teamQualityChart) {
|
|
|
|
|
|
teamQualityChart.dispose();
|
|
|
|
|
|
}
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
teamQualityChart = echarts.init(chartDom);
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 先设置一个空的图表配置
|
2025-10-14 18:16:49 +08:00
|
|
|
|
const option = {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
backgroundColor: 'transparent',
|
2025-10-14 18:16:49 +08:00
|
|
|
|
tooltip: {
|
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
|
axisPointer: {
|
|
|
|
|
|
type: 'shadow',
|
2026-01-21 10:34:06 +08:00
|
|
|
|
shadowStyle: {
|
|
|
|
|
|
color: 'rgba(6, 189, 221, 0.2)'
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
backgroundColor: 'rgba(13, 34, 37, 0.95)',
|
|
|
|
|
|
borderColor: 'rgba(6, 189, 221, 0.8)',
|
2025-10-14 18:16:49 +08:00
|
|
|
|
borderWidth: 1,
|
2026-01-21 10:34:06 +08:00
|
|
|
|
borderRadius: 4,
|
|
|
|
|
|
padding: [12, 16],
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
fontSize: 12
|
|
|
|
|
|
},
|
2026-01-23 16:33:21 +08:00
|
|
|
|
formatter: function (params) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
if (!params || params.length === 0) return '';
|
2026-01-23 16:33:21 +08:00
|
|
|
|
const param = params[0];
|
|
|
|
|
|
const teamName = param.name;
|
|
|
|
|
|
const passRate = param.value || 0;
|
|
|
|
|
|
return `${teamName},合格率:${passRate.toFixed(2)}%`;
|
2025-10-14 18:16:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
left: '2%',
|
|
|
|
|
|
right: '2%',
|
2026-01-21 10:34:06 +08:00
|
|
|
|
bottom: '3%',
|
|
|
|
|
|
top: '10%',
|
|
|
|
|
|
containLabel: true
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
type: 'category',
|
2026-01-23 16:33:21 +08:00
|
|
|
|
data: [],
|
2026-01-21 10:34:06 +08:00
|
|
|
|
axisLabel: {
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
margin: 10
|
|
|
|
|
|
},
|
2025-10-14 18:16:49 +08:00
|
|
|
|
axisLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
color: 'rgba(255, 255, 255, 0.3)',
|
|
|
|
|
|
width: 1
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
|
|
|
|
|
axisTick: {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
show: false
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
|
|
|
|
|
yAxis: {
|
|
|
|
|
|
type: 'value',
|
2026-01-21 10:34:06 +08:00
|
|
|
|
min: 0,
|
2026-01-23 16:33:21 +08:00
|
|
|
|
max: 100,
|
|
|
|
|
|
interval: 20,
|
2026-01-21 10:34:06 +08:00
|
|
|
|
axisLabel: {
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
fontSize: 12,
|
2026-01-23 16:33:21 +08:00
|
|
|
|
margin: 8,
|
|
|
|
|
|
formatter: '{value}%'
|
2026-01-21 10:34:06 +08:00
|
|
|
|
},
|
2025-10-14 18:16:49 +08:00
|
|
|
|
axisLine: {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
show: true,
|
2025-10-14 18:16:49 +08:00
|
|
|
|
lineStyle: {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
color: 'rgba(255, 255, 255, 0.3)',
|
|
|
|
|
|
width: 1
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
color: 'rgba(255, 255, 255, 0.15)',
|
2025-10-14 18:16:49 +08:00
|
|
|
|
type: 'dashed',
|
2026-01-21 10:34:06 +08:00
|
|
|
|
width: 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
2026-01-23 16:33:21 +08:00
|
|
|
|
name: '合格率',
|
2026-01-21 10:34:06 +08:00
|
|
|
|
type: 'bar',
|
2026-01-23 16:33:21 +08:00
|
|
|
|
data: [],
|
2026-01-21 10:34:06 +08:00
|
|
|
|
barWidth: '45%',
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
|
|
|
|
offset: 0,
|
|
|
|
|
|
color: '#00FFB8'
|
|
|
|
|
|
}, {
|
|
|
|
|
|
offset: 0.5,
|
|
|
|
|
|
color: '#00D4FF'
|
|
|
|
|
|
}, {
|
|
|
|
|
|
offset: 1,
|
|
|
|
|
|
color: '#00A8FF'
|
|
|
|
|
|
}]),
|
|
|
|
|
|
borderRadius: [2, 2, 0, 0],
|
|
|
|
|
|
shadowColor: 'rgba(0, 255, 184, 0.6)',
|
|
|
|
|
|
shadowBlur: 10,
|
|
|
|
|
|
shadowOffsetY: 4,
|
|
|
|
|
|
borderColor: 'rgba(0, 255, 184, 0.3)',
|
|
|
|
|
|
borderWidth: 1
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
emphasis: {
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
shadowBlur: 18,
|
|
|
|
|
|
shadowOffsetY: 6,
|
|
|
|
|
|
shadowColor: 'rgba(0, 255, 184, 0.9)',
|
|
|
|
|
|
borderColor: 'rgba(0, 255, 184, 0.6)',
|
|
|
|
|
|
borderWidth: 2
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
label: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
position: 'top',
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
fontWeight: 'bold',
|
2026-01-23 16:33:21 +08:00
|
|
|
|
formatter: function (params) {
|
|
|
|
|
|
return params.value.toFixed(2) + '%';
|
2026-01-21 10:34:06 +08:00
|
|
|
|
},
|
|
|
|
|
|
textShadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
|
|
|
|
textShadowBlur: 3,
|
|
|
|
|
|
textShadowOffsetX: 1,
|
|
|
|
|
|
textShadowOffsetY: 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
2025-10-14 18:16:49 +08:00
|
|
|
|
};
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
teamQualityChart.setOption(option);
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-24 14:23:35 +08:00
|
|
|
|
// 添加点击事件监听
|
|
|
|
|
|
teamQualityChart.on('click', function (params) {
|
|
|
|
|
|
openQualityRecordModal();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-23 16:33:21 +08:00
|
|
|
|
// 请求数据
|
|
|
|
|
|
const url =
|
|
|
|
|
|
commonUrl +
|
|
|
|
|
|
"screen/project/quality/teamRate?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
|
|
|
|
|
ajaxRequestGet(
|
|
|
|
|
|
url,
|
|
|
|
|
|
"GET",
|
|
|
|
|
|
true,
|
|
|
|
|
|
function () {
|
|
|
|
|
|
},
|
|
|
|
|
|
function (result) {
|
|
|
|
|
|
console.log(result, '施工队伍质量合格率柱状图');
|
|
|
|
|
|
|
|
|
|
|
|
if (result && result.data && Array.isArray(result.data)) {
|
|
|
|
|
|
updateTeamQualityChartData(result.data);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
aqEnnable
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新施工队伍质量合格率图表数据
|
|
|
|
|
|
function updateTeamQualityChartData(data) {
|
|
|
|
|
|
if (!teamQualityChart || !data || !Array.isArray(data) || data.length === 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提取班组名称和合格率
|
|
|
|
|
|
const teamNames = data.map(item => item.teamName || '');
|
|
|
|
|
|
const passRates = data.map(item => {
|
|
|
|
|
|
const rate = item.passRate || 0;
|
|
|
|
|
|
// 确保合格率在0-100范围内
|
|
|
|
|
|
return Math.max(0, Math.min(100, rate));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 更新图表数据
|
|
|
|
|
|
teamQualityChart.setOption({
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
data: teamNames
|
|
|
|
|
|
},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
data: passRates
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
});
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 初始化质量检测合格占比环形图
|
|
|
|
|
|
function initQualityRatioChart() {
|
|
|
|
|
|
const chartDom = document.getElementById('qualityRatioChart');
|
|
|
|
|
|
if (!chartDom) return;
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
if (qualityRatioChart) {
|
|
|
|
|
|
qualityRatioChart.dispose();
|
|
|
|
|
|
}
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
qualityRatioChart = echarts.init(chartDom);
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 默认数据
|
|
|
|
|
|
let passCount = 0;
|
|
|
|
|
|
let failCount = 0;
|
|
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
const option = {
|
|
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
trigger: 'item',
|
|
|
|
|
|
backgroundColor: 'rgba(13, 34, 37, 0.95)',
|
|
|
|
|
|
borderColor: 'rgba(6, 189, 221, 0.8)',
|
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
|
borderRadius: 4,
|
|
|
|
|
|
padding: [12, 16],
|
|
|
|
|
|
position: 'right',
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
fontSize: 12
|
|
|
|
|
|
},
|
|
|
|
|
|
extraCssText: 'z-index: 9999999999;', // 确保tooltip在最上层
|
2026-01-23 16:33:21 +08:00
|
|
|
|
formatter: function (params) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
const name = params.name;
|
|
|
|
|
|
const value = params.value;
|
|
|
|
|
|
const color = params.color;
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
return `
|
|
|
|
|
|
<div style="font-weight: bold; margin-bottom: 10px; color: #FFFFFF; font-size: 13px;">质量检测合格占比</div>
|
|
|
|
|
|
<div style="display: flex; align-items: center; min-width: 150px;">
|
|
|
|
|
|
<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: ${color}; margin-right: 10px; flex-shrink: 0;"></span>
|
|
|
|
|
|
<span style="color: #B9D6D9; margin-right: 10px;">${name}</span>
|
|
|
|
|
|
<span style="color: #FFFFFF; margin-left: auto; font-weight: bold;">${value.toFixed(2)}%</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
`;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
// 外层圆环 - 2-4px宽度,白色/亮色,完整圆环
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '外层圆环',
|
|
|
|
|
|
type: 'pie',
|
|
|
|
|
|
radius: ['94%', '97%'],
|
|
|
|
|
|
center: ['50%', '50%'],
|
|
|
|
|
|
avoidLabelOverlap: false,
|
|
|
|
|
|
silent: true, // 不响应鼠标事件
|
|
|
|
|
|
itemStyle: {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
color: function (params) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 根据图片,外层圆环可能是白色或亮青色,带发光效果
|
|
|
|
|
|
return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
|
|
|
|
offset: 0,
|
2026-01-23 16:33:21 +08:00
|
|
|
|
color: 'rgba(255, 255, 255, 0.9)'
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}, {
|
|
|
|
|
|
offset: 1,
|
|
|
|
|
|
color: 'rgba(0, 255, 212, 0.8)'
|
|
|
|
|
|
}]);
|
|
|
|
|
|
},
|
|
|
|
|
|
borderRadius: 2, // 外层圆环圆角效果
|
|
|
|
|
|
borderColor: 'transparent',
|
|
|
|
|
|
borderWidth: 0,
|
|
|
|
|
|
shadowBlur: 8,
|
|
|
|
|
|
shadowColor: 'rgba(0, 255, 212, 0.6)'
|
|
|
|
|
|
},
|
|
|
|
|
|
label: {
|
|
|
|
|
|
show: false
|
|
|
|
|
|
},
|
|
|
|
|
|
labelLine: {
|
|
|
|
|
|
show: false
|
|
|
|
|
|
},
|
|
|
|
|
|
data: [{
|
|
|
|
|
|
value: 100,
|
|
|
|
|
|
name: ''
|
|
|
|
|
|
}]
|
|
|
|
|
|
},
|
|
|
|
|
|
// 内层圆环 - 15-20px宽度,显示数据
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '质量检测合格占比',
|
|
|
|
|
|
type: 'pie',
|
|
|
|
|
|
radius: ['70%', '80%'],
|
|
|
|
|
|
center: ['50%', '50%'],
|
|
|
|
|
|
avoidLabelOverlap: false,
|
|
|
|
|
|
// 添加分段之间的间隙
|
|
|
|
|
|
gap: 3, // 分段之间的间隙(像素),创建可见的深色间隙
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
borderRadius: 5, // 添加圆角效果,使圆环更圆润
|
|
|
|
|
|
borderColor: 'transparent',
|
|
|
|
|
|
borderWidth: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
label: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
position: 'center',
|
2026-01-23 16:33:21 +08:00
|
|
|
|
formatter: function () {
|
|
|
|
|
|
return '{a|' + passCount.toFixed(2) + '}{b|%}';
|
2026-01-21 10:34:06 +08:00
|
|
|
|
},
|
|
|
|
|
|
rich: {
|
|
|
|
|
|
a: {
|
|
|
|
|
|
fontSize: 32,
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
lineHeight: 40
|
|
|
|
|
|
},
|
|
|
|
|
|
b: {
|
|
|
|
|
|
fontSize: 20,
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
color: '#FFFFFF',
|
|
|
|
|
|
lineHeight: 40
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
emphasis: {
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
borderRadius: 6, // 悬停时圆角更大
|
|
|
|
|
|
shadowBlur: 10,
|
|
|
|
|
|
shadowOffsetX: 0,
|
|
|
|
|
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
|
},
|
|
|
|
|
|
label: {
|
|
|
|
|
|
rich: {
|
|
|
|
|
|
a: {
|
|
|
|
|
|
fontSize: 36,
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
color: '#FFFFFF'
|
|
|
|
|
|
},
|
|
|
|
|
|
b: {
|
|
|
|
|
|
fontSize: 22,
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
color: '#FFFFFF'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
labelLine: {
|
|
|
|
|
|
show: false
|
|
|
|
|
|
},
|
|
|
|
|
|
data: [
|
|
|
|
|
|
{
|
2026-01-23 16:33:21 +08:00
|
|
|
|
value: passCount,
|
2026-01-21 10:34:06 +08:00
|
|
|
|
name: '合格',
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
|
|
|
|
offset: 0,
|
|
|
|
|
|
color: '#00FFD4'
|
|
|
|
|
|
}, {
|
|
|
|
|
|
offset: 0.5,
|
|
|
|
|
|
color: '#00D4FF'
|
|
|
|
|
|
}, {
|
|
|
|
|
|
offset: 1,
|
|
|
|
|
|
color: '#00A8FF'
|
|
|
|
|
|
}])
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-01-23 16:33:21 +08:00
|
|
|
|
value: failCount,
|
2026-01-21 10:34:06 +08:00
|
|
|
|
name: '不合格',
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
|
|
|
|
offset: 0,
|
|
|
|
|
|
color: 'rgba(238, 248, 245, 1)'
|
|
|
|
|
|
}, {
|
|
|
|
|
|
offset: 1,
|
|
|
|
|
|
color: 'rgba(238, 248, 245, 0.8)'
|
|
|
|
|
|
}])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
};
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
qualityRatioChart.setOption(option);
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-24 14:23:35 +08:00
|
|
|
|
// 添加点击事件监听
|
|
|
|
|
|
qualityRatioChart.on('click', function (params) {
|
|
|
|
|
|
openQualityRecordModal();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 更新显示值
|
2026-01-23 16:33:21 +08:00
|
|
|
|
updateQualityRatioDisplay(passCount, failCount);
|
|
|
|
|
|
|
|
|
|
|
|
// 请求数据
|
|
|
|
|
|
const url =
|
|
|
|
|
|
commonUrl +
|
|
|
|
|
|
"screen/project/quality/resultCount?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
|
|
|
|
|
ajaxRequestGet(
|
|
|
|
|
|
url,
|
|
|
|
|
|
"GET",
|
|
|
|
|
|
true,
|
|
|
|
|
|
function () {
|
|
|
|
|
|
},
|
|
|
|
|
|
function (result) {
|
|
|
|
|
|
console.log(result, '质量检测合格占比');
|
|
|
|
|
|
|
|
|
|
|
|
if (result && result.data) {
|
|
|
|
|
|
const { passCount: newPassCount, failCount: newFailCount } = result.data;
|
|
|
|
|
|
updateQualityRatioChartData(newPassCount || 0, newFailCount || 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
aqEnnable
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新质量检测合格占比图表数据(后端返回的是合格/不合格数量,这里换算成百分比)
|
|
|
|
|
|
function updateQualityRatioChartData(passCount, failCount) {
|
|
|
|
|
|
if (!qualityRatioChart) return;
|
|
|
|
|
|
|
|
|
|
|
|
const passNum = Number(passCount) || 0;
|
|
|
|
|
|
const failNum = Number(failCount) || 0;
|
|
|
|
|
|
const total = passNum + failNum;
|
|
|
|
|
|
|
|
|
|
|
|
// 由数量计算百分比
|
|
|
|
|
|
let passRate = 0;
|
|
|
|
|
|
let failRate = 0;
|
|
|
|
|
|
if (total > 0) {
|
|
|
|
|
|
passRate = (passNum / total) * 100;
|
|
|
|
|
|
failRate = (failNum / total) * 100;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 防御性:限制在 0-100 之间,避免小数累计误差
|
|
|
|
|
|
passRate = Math.max(0, Math.min(100, passRate));
|
|
|
|
|
|
failRate = Math.max(0, Math.min(100, failRate));
|
|
|
|
|
|
|
|
|
|
|
|
qualityRatioChart.setOption({
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
// 外层圆环保持不变
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '质量检测合格占比',
|
|
|
|
|
|
label: {
|
|
|
|
|
|
formatter: function () {
|
|
|
|
|
|
return '{a|' + passRate.toFixed(2) + '}{b|%}';
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
data: [
|
|
|
|
|
|
{
|
|
|
|
|
|
value: passRate,
|
|
|
|
|
|
name: '合格'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
value: failRate,
|
|
|
|
|
|
name: '不合格'
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 更新显示值(下方“合格/不合格”文字)
|
|
|
|
|
|
updateQualityRatioDisplay(passRate, failRate);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新质量检测合格占比显示值
|
|
|
|
|
|
function updateQualityRatioDisplay(passCount, failCount) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
const passRatioEl = document.getElementById('passRatio');
|
|
|
|
|
|
const failRatioEl = document.getElementById('failRatio');
|
|
|
|
|
|
if (passRatioEl) {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
passRatioEl.textContent = (passCount || 0).toFixed(2) + '%';
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (failRatioEl) {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
failRatioEl.textContent = (failCount || 0).toFixed(2) + '%';
|
2025-10-18 15:55:58 +08:00
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 初始化质量检测记录表格
|
|
|
|
|
|
function initQualityRecordTable() {
|
|
|
|
|
|
table.render({
|
|
|
|
|
|
elem: '#qualityRecordTable',
|
2026-01-23 16:33:21 +08:00
|
|
|
|
url: commonUrl + 'screen/project/quality/list',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
decrypt: 'decrypt',
|
|
|
|
|
|
Authorization: token
|
|
|
|
|
|
},
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
where: {
|
|
|
|
|
|
projectId: bidCode,
|
|
|
|
|
|
startTestDay: queryParams.startTestDay,
|
|
|
|
|
|
endTestDay: queryParams.endTestDay,
|
|
|
|
|
|
teamName: keyword || ''
|
|
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
skin: 'line',
|
|
|
|
|
|
page: {
|
|
|
|
|
|
layout: ['prev', 'page', 'next', 'count', 'skip'],
|
|
|
|
|
|
groups: 5,
|
2026-01-23 16:33:21 +08:00
|
|
|
|
limit: pageSize,
|
|
|
|
|
|
limits: [10, 20, 30, 50]
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
height: 'full',
|
2026-01-23 16:33:21 +08:00
|
|
|
|
request: {
|
|
|
|
|
|
pageName: 'pageNum',
|
|
|
|
|
|
limitName: 'pageSize'
|
|
|
|
|
|
},
|
|
|
|
|
|
response: {
|
|
|
|
|
|
statusName: 'code',
|
|
|
|
|
|
statusCode: 200,
|
|
|
|
|
|
msgName: 'msg',
|
|
|
|
|
|
countName: 'total',
|
|
|
|
|
|
dataName: 'rows'
|
|
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
cols: [[
|
2026-01-23 16:33:21 +08:00
|
|
|
|
{ type: 'numbers', title: '序号', width: '15%', align: 'center' },
|
|
|
|
|
|
{ field: 'teamName', title: '班组名称', width: '20%', align: 'center' },
|
|
|
|
|
|
{ field: 'content', title: '检测内容', width: '25%', align: 'center' },
|
|
|
|
|
|
{ field: 'testDay', title: '检测日期', width: '20%', align: 'center' },
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'testResult', title: '检测结果', width: '20%', align: 'center', templet: function (d) {
|
|
|
|
|
|
// testResult: "0"为合格,"1"为不合格
|
|
|
|
|
|
return d.testResult === '0' || d.testResult === 0 ?
|
|
|
|
|
|
'<span style="color: #00FFB8;">合格</span>' :
|
|
|
|
|
|
'<span style="color: #FF6B6B;">不合格</span>';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-21 10:34:06 +08:00
|
|
|
|
]]
|
2025-10-14 18:16:49 +08:00
|
|
|
|
});
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化日期范围选择器
|
|
|
|
|
|
function initDateRangePicker() {
|
2026-01-24 18:55:45 +08:00
|
|
|
|
// 设置初始显示值为当天范围
|
2026-01-23 16:33:21 +08:00
|
|
|
|
const initialValue = queryParams.startTestDay + ' ~ ' + queryParams.endTestDay;
|
|
|
|
|
|
$('#dateRange').val(initialValue);
|
|
|
|
|
|
|
|
|
|
|
|
// 使用范围选择器,单个输入框显示日期范围
|
2026-01-21 10:34:06 +08:00
|
|
|
|
laydate.render({
|
2026-01-23 16:33:21 +08:00
|
|
|
|
elem: '#dateRange',
|
2026-01-21 10:34:06 +08:00
|
|
|
|
type: 'date',
|
2026-01-23 16:33:21 +08:00
|
|
|
|
range: true, // 启用范围选择
|
2026-01-21 10:34:06 +08:00
|
|
|
|
format: 'yyyy-MM-dd',
|
|
|
|
|
|
theme: 'dark',
|
2026-01-24 18:55:45 +08:00
|
|
|
|
// 默认值使用当天范围
|
2026-01-23 16:33:21 +08:00
|
|
|
|
value: queryParams.startTestDay + ' - ' + queryParams.endTestDay,
|
|
|
|
|
|
done: function (value, date, endDate) {
|
2026-01-24 18:55:45 +08:00
|
|
|
|
// 重置为当天日期的函数
|
|
|
|
|
|
const resetToToday = function () {
|
|
|
|
|
|
const today = getTodayDate();
|
|
|
|
|
|
queryParams.startTestDay = today;
|
|
|
|
|
|
queryParams.endTestDay = today;
|
|
|
|
|
|
$('#dateRange').val(today + ' ~ ' + today);
|
2026-01-23 16:33:21 +08:00
|
|
|
|
refreshAllModules();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (value && value.trim() !== '') {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
const dates = value.split(' - ');
|
|
|
|
|
|
if (dates.length === 2) {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
const startDate = dates[0].trim();
|
|
|
|
|
|
const endDateStr = dates[1].trim();
|
|
|
|
|
|
|
2026-01-24 18:55:45 +08:00
|
|
|
|
// 在单个输入框中显示日期范围(格式:2026-01-15 ~ 2026-01-15)
|
2026-01-23 16:33:21 +08:00
|
|
|
|
$('#dateRange').val(startDate + ' ~ ' + endDateStr);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新查询参数
|
|
|
|
|
|
queryParams.startTestDay = startDate;
|
|
|
|
|
|
queryParams.endTestDay = endDateStr;
|
|
|
|
|
|
|
|
|
|
|
|
// 日期变化后,重新调用所有模块接口
|
|
|
|
|
|
refreshAllModules();
|
|
|
|
|
|
} else {
|
2026-01-24 18:55:45 +08:00
|
|
|
|
// 如果格式不正确,重置为当天日期
|
|
|
|
|
|
resetToToday();
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
2026-01-23 16:33:21 +08:00
|
|
|
|
} else {
|
2026-01-24 18:55:45 +08:00
|
|
|
|
// 清空时,重置为当天日期
|
|
|
|
|
|
resetToToday();
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
});
|
2026-01-23 16:33:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 刷新所有模块数据
|
|
|
|
|
|
function refreshAllModules() {
|
|
|
|
|
|
// 重新初始化所有模块
|
|
|
|
|
|
initTeamQualityChart();
|
|
|
|
|
|
initQualityRatioChart();
|
|
|
|
|
|
initWarningList();
|
|
|
|
|
|
|
|
|
|
|
|
// 重新加载表格
|
|
|
|
|
|
if (table) {
|
|
|
|
|
|
table.reload('qualityRecordTable', {
|
|
|
|
|
|
where: {
|
|
|
|
|
|
projectId: bidCode,
|
|
|
|
|
|
startTestDay: queryParams.startTestDay,
|
|
|
|
|
|
endTestDay: queryParams.endTestDay,
|
|
|
|
|
|
teamName: keyword || ''
|
|
|
|
|
|
},
|
|
|
|
|
|
page: {
|
|
|
|
|
|
curr: 1
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 查询记录
|
|
|
|
|
|
function queryRecords() {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
keyword = $('#keywordInput').val() || '';
|
|
|
|
|
|
|
|
|
|
|
|
// 重新加载表格
|
2026-01-21 10:34:06 +08:00
|
|
|
|
table.reload('qualityRecordTable', {
|
|
|
|
|
|
where: {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
projectId: bidCode,
|
|
|
|
|
|
startTestDay: queryParams.startTestDay,
|
|
|
|
|
|
endTestDay: queryParams.endTestDay,
|
|
|
|
|
|
teamName: keyword
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
page: {
|
|
|
|
|
|
curr: 1
|
2025-10-14 18:16:49 +08:00
|
|
|
|
}
|
2026-01-21 10:34:06 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化警告列表
|
|
|
|
|
|
function initWarningList() {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
|
|
|
|
|
const url =
|
|
|
|
|
|
commonUrl +
|
|
|
|
|
|
"screen/project/quality/warnlist?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
|
|
|
|
|
ajaxRequestGet(
|
|
|
|
|
|
url,
|
|
|
|
|
|
"GET",
|
|
|
|
|
|
true,
|
|
|
|
|
|
function () {
|
|
|
|
|
|
},
|
|
|
|
|
|
function (result) {
|
|
|
|
|
|
|
|
|
|
|
|
const warnings = result.rows.map(item => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
date: item.txTime,
|
|
|
|
|
|
team: item.txType,
|
|
|
|
|
|
message: item.content
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const warningItemsHtml = warnings.map(function (warning) {
|
|
|
|
|
|
const fullText = `${warning.date} ${warning.team} - ${warning.message}`;
|
|
|
|
|
|
return `
|
|
|
|
|
|
<div class="warning-item">
|
|
|
|
|
|
<div class="warning-icon"></div>
|
|
|
|
|
|
<div class="warning-text" title="${fullText}">
|
|
|
|
|
|
${fullText}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
`;
|
|
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
|
|
|
|
const $warningList = $('#warningList');
|
|
|
|
|
|
|
|
|
|
|
|
// 先渲染一次,检查是否需要滚动
|
|
|
|
|
|
$warningList.html(warningItemsHtml);
|
|
|
|
|
|
|
|
|
|
|
|
// 等待DOM渲染后检查高度
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
|
const $container = $warningList.parent();
|
|
|
|
|
|
const $listElement = $warningList[0];
|
|
|
|
|
|
|
|
|
|
|
|
if (!$listElement) return;
|
|
|
|
|
|
|
|
|
|
|
|
const contentHeight = $listElement.scrollHeight;
|
|
|
|
|
|
const containerHeight = $container.height();
|
|
|
|
|
|
|
|
|
|
|
|
// 如果内容高度超过容器高度,启用无缝滚动
|
|
|
|
|
|
if (contentHeight > containerHeight) {
|
|
|
|
|
|
// 复制2份内容实现无缝循环:原始 + 复制1
|
|
|
|
|
|
const duplicatedHtml = warningItemsHtml + warningItemsHtml;
|
|
|
|
|
|
$warningList.html(duplicatedHtml);
|
|
|
|
|
|
|
|
|
|
|
|
// 等待DOM更新后重新计算高度和启动动画
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
|
const newContentHeight = $listElement.scrollHeight;
|
|
|
|
|
|
const singleListHeight = newContentHeight / 2; // 单份内容的高度
|
|
|
|
|
|
|
|
|
|
|
|
// 添加滚动类
|
|
|
|
|
|
$warningList.addClass('warning-list-scroll');
|
|
|
|
|
|
|
|
|
|
|
|
// 计算动画时长,根据内容高度动态调整
|
|
|
|
|
|
// 滚动距离是单份内容的高度(50%对应单份高度)
|
|
|
|
|
|
// 每25px用1秒,确保滚动速度适中且流畅
|
|
|
|
|
|
const animationDuration = Math.max(25, Math.ceil(singleListHeight / 25));
|
|
|
|
|
|
|
|
|
|
|
|
// 动态设置动画
|
|
|
|
|
|
$warningList.css({
|
|
|
|
|
|
'animation': `scrollWarning ${animationDuration}s linear infinite`,
|
|
|
|
|
|
'animation-fill-mode': 'forwards'
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 200);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 如果内容不需要滚动,也添加类以保持样式一致
|
|
|
|
|
|
$warningList.addClass('warning-list-scroll');
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
},
|
|
|
|
|
|
aqEnnable
|
|
|
|
|
|
);
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 模拟数据 - 后续替换为真实接口数据
|
2026-01-23 16:33:21 +08:00
|
|
|
|
// const warnings = [
|
|
|
|
|
|
// { date: '2026-01-11', team: '班组一', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' },
|
|
|
|
|
|
// { date: '2026-01-11', team: '班组三', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' },
|
|
|
|
|
|
// { date: '2026-01-10', team: '班组五', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' },
|
|
|
|
|
|
// { date: '2026-01-10', team: '班组七', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' },
|
|
|
|
|
|
// { date: '2026-01-09', team: '班组二', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' },
|
|
|
|
|
|
// { date: '2026-01-09', team: '班组四', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' },
|
|
|
|
|
|
// { date: '2026-01-08', team: '班组六', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' },
|
|
|
|
|
|
// { date: '2026-01-08', team: '班组八', message: '质量检测合格率低于80%,请持续关注该班组施工质量情况。' }
|
|
|
|
|
|
// ];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 获取施工队伍质量合格率数据(接口调用)
|
|
|
|
|
|
function getTeamQualityData() {
|
|
|
|
|
|
const bidCode = parent.parent.$('#bidPro').val() || '';
|
|
|
|
|
|
const url = commonUrl + 'screen/largeScreen/dataAnalysis/getTeamQualityPassRate';
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: url,
|
|
|
|
|
|
type: 'GET',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
decrypt: 'decrypt',
|
|
|
|
|
|
Authorization: token
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
2026-01-21 10:34:06 +08:00
|
|
|
|
data: {
|
|
|
|
|
|
bidCode: bidCode
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
2026-01-23 16:33:21 +08:00
|
|
|
|
success: function (res) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
if (res.code === 200 && res.data) {
|
|
|
|
|
|
// 更新图表数据
|
|
|
|
|
|
updateTeamQualityChart(res.data);
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
},
|
2026-01-23 16:33:21 +08:00
|
|
|
|
error: function (err) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
console.error('获取施工队伍质量合格率数据失败:', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-23 16:33:21 +08:00
|
|
|
|
// 更新施工队伍质量合格率图表(兼容旧接口)
|
2026-01-21 10:34:06 +08:00
|
|
|
|
function updateTeamQualityChart(data) {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
// 直接调用新的更新函数
|
|
|
|
|
|
updateTeamQualityChartData(data);
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
// 获取质量检测合格占比数据(接口调用)
|
|
|
|
|
|
function getQualityRatioData() {
|
|
|
|
|
|
const bidCode = parent.parent.$('#bidPro').val() || '';
|
|
|
|
|
|
const url = commonUrl + 'screen/largeScreen/dataAnalysis/getQualityRatio';
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: url,
|
|
|
|
|
|
type: 'GET',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
decrypt: 'decrypt',
|
|
|
|
|
|
Authorization: token
|
|
|
|
|
|
},
|
|
|
|
|
|
data: {
|
|
|
|
|
|
bidCode: bidCode
|
|
|
|
|
|
},
|
2026-01-23 16:33:21 +08:00
|
|
|
|
success: function (res) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
if (res.code === 200 && res.data) {
|
|
|
|
|
|
// 更新图表数据
|
|
|
|
|
|
updateQualityRatioChart(res.data);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2026-01-23 16:33:21 +08:00
|
|
|
|
error: function (err) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
console.error('获取质量检测合格占比数据失败:', err);
|
|
|
|
|
|
}
|
2025-10-14 18:16:49 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-01-21 10:34:06 +08:00
|
|
|
|
|
2026-01-23 16:33:21 +08:00
|
|
|
|
// 更新质量检测合格占比图表(兼容旧接口)
|
2026-01-21 10:34:06 +08:00
|
|
|
|
function updateQualityRatioChart(data) {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
// 优先使用 passCount 和 failCount,如果没有则使用 passRate 和 failRate
|
|
|
|
|
|
const passCount = data.passCount !== undefined ? data.passCount : (data.passRate || 0);
|
|
|
|
|
|
const failCount = data.failCount !== undefined ? data.failCount : (data.failRate || 0);
|
|
|
|
|
|
|
|
|
|
|
|
updateQualityRatioChartData(passCount, failCount);
|
2026-01-21 10:34:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取警告列表数据(接口调用)
|
|
|
|
|
|
function getWarningListData() {
|
|
|
|
|
|
const bidCode = parent.parent.$('#bidPro').val() || '';
|
|
|
|
|
|
const url = commonUrl + 'screen/largeScreen/dataAnalysis/getQualityWarnings';
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: url,
|
|
|
|
|
|
type: 'GET',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
decrypt: 'decrypt',
|
|
|
|
|
|
Authorization: token
|
|
|
|
|
|
},
|
|
|
|
|
|
data: {
|
|
|
|
|
|
bidCode: bidCode
|
|
|
|
|
|
},
|
2026-01-23 16:33:21 +08:00
|
|
|
|
success: function (res) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
if (res.code === 200 && res.data) {
|
|
|
|
|
|
// 更新警告列表
|
|
|
|
|
|
updateWarningList(res.data);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2026-01-23 16:33:21 +08:00
|
|
|
|
error: function (err) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
console.error('获取警告列表数据失败:', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新警告列表
|
|
|
|
|
|
function updateWarningList(data) {
|
2026-01-23 16:33:21 +08:00
|
|
|
|
const warningListHtml = data.map(function (warning) {
|
2026-01-21 10:34:06 +08:00
|
|
|
|
return `
|
|
|
|
|
|
<div class="warning-item">
|
|
|
|
|
|
<div class="warning-icon"></div>
|
|
|
|
|
|
<div class="warning-text">
|
|
|
|
|
|
${warning.date} ${warning.message}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
`;
|
|
|
|
|
|
}).join('');
|
2026-01-23 16:33:21 +08:00
|
|
|
|
|
2026-01-21 10:34:06 +08:00
|
|
|
|
$('#warningList').html(warningListHtml);
|
|
|
|
|
|
}
|
2026-01-24 14:23:35 +08:00
|
|
|
|
|
|
|
|
|
|
// 打开质量检测记录弹框
|
|
|
|
|
|
function openQualityRecordModal() {
|
|
|
|
|
|
const modal = $('#qualityRecordModal');
|
|
|
|
|
|
modal.addClass('show');
|
|
|
|
|
|
|
|
|
|
|
|
// 重置关键字输入框
|
|
|
|
|
|
modalKeyword = '';
|
|
|
|
|
|
$('#modalKeywordInput').val('');
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化弹框内的日期选择器
|
|
|
|
|
|
initModalDateRangePicker();
|
|
|
|
|
|
|
|
|
|
|
|
// 延迟初始化表格,确保弹框完全显示后再渲染表格
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
|
initModalQualityRecordTable();
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭质量检测记录弹框
|
|
|
|
|
|
function closeQualityRecordModal() {
|
|
|
|
|
|
const modal = $('#qualityRecordModal');
|
|
|
|
|
|
modal.removeClass('show');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化弹框内日期范围选择器
|
|
|
|
|
|
function initModalDateRangePicker() {
|
|
|
|
|
|
// 使用当前查询参数初始化弹框日期
|
|
|
|
|
|
const initialValue = queryParams.startTestDay + ' ~ ' + queryParams.endTestDay;
|
|
|
|
|
|
$('#modalDateRange').val(initialValue);
|
|
|
|
|
|
|
|
|
|
|
|
// 同步弹框查询参数
|
|
|
|
|
|
modalQueryParams.startTestDay = queryParams.startTestDay;
|
|
|
|
|
|
modalQueryParams.endTestDay = queryParams.endTestDay;
|
|
|
|
|
|
|
|
|
|
|
|
// 使用范围选择器,单个输入框显示日期范围
|
|
|
|
|
|
laydate.render({
|
|
|
|
|
|
elem: '#modalDateRange',
|
|
|
|
|
|
type: 'date',
|
|
|
|
|
|
range: true,
|
|
|
|
|
|
format: 'yyyy-MM-dd',
|
|
|
|
|
|
theme: 'dark',
|
|
|
|
|
|
value: queryParams.startTestDay + ' - ' + queryParams.endTestDay,
|
|
|
|
|
|
done: function (value, date, endDate) {
|
2026-01-24 18:55:45 +08:00
|
|
|
|
const resetToToday = function () {
|
|
|
|
|
|
const today = getTodayDate();
|
|
|
|
|
|
modalQueryParams.startTestDay = today;
|
|
|
|
|
|
modalQueryParams.endTestDay = today;
|
|
|
|
|
|
$('#modalDateRange').val(today + ' ~ ' + today);
|
2026-01-24 14:23:35 +08:00
|
|
|
|
queryModalRecords();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (value && value.trim() !== '') {
|
|
|
|
|
|
const dates = value.split(' - ');
|
|
|
|
|
|
if (dates.length === 2) {
|
|
|
|
|
|
const startDate = dates[0].trim();
|
|
|
|
|
|
const endDateStr = dates[1].trim();
|
|
|
|
|
|
|
|
|
|
|
|
$('#modalDateRange').val(startDate + ' ~ ' + endDateStr);
|
|
|
|
|
|
|
|
|
|
|
|
modalQueryParams.startTestDay = startDate;
|
|
|
|
|
|
modalQueryParams.endTestDay = endDateStr;
|
|
|
|
|
|
|
|
|
|
|
|
queryModalRecords();
|
|
|
|
|
|
} else {
|
2026-01-24 18:55:45 +08:00
|
|
|
|
resetToToday();
|
2026-01-24 14:23:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2026-01-24 18:55:45 +08:00
|
|
|
|
resetToToday();
|
2026-01-24 14:23:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化弹框内质量检测记录表格
|
|
|
|
|
|
function initModalQualityRecordTable() {
|
|
|
|
|
|
table.render({
|
|
|
|
|
|
elem: '#modalQualityRecordTable',
|
|
|
|
|
|
id: 'modalQualityRecordTable',
|
|
|
|
|
|
url: commonUrl + 'screen/project/quality/list',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
decrypt: 'decrypt',
|
|
|
|
|
|
Authorization: token
|
|
|
|
|
|
},
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
where: {
|
|
|
|
|
|
projectId: bidCode,
|
|
|
|
|
|
startTestDay: modalQueryParams.startTestDay,
|
|
|
|
|
|
endTestDay: modalQueryParams.endTestDay,
|
|
|
|
|
|
teamName: modalKeyword || ''
|
|
|
|
|
|
},
|
|
|
|
|
|
skin: 'line',
|
|
|
|
|
|
page: {
|
|
|
|
|
|
layout: ['prev', 'page', 'next', 'count', 'skip'],
|
|
|
|
|
|
groups: 5,
|
|
|
|
|
|
limit: pageSize,
|
|
|
|
|
|
limits: [10, 20, 30, 50]
|
|
|
|
|
|
},
|
|
|
|
|
|
height: 'full',
|
|
|
|
|
|
request: {
|
|
|
|
|
|
pageName: 'pageNum',
|
|
|
|
|
|
limitName: 'pageSize'
|
|
|
|
|
|
},
|
|
|
|
|
|
response: {
|
|
|
|
|
|
statusName: 'code',
|
|
|
|
|
|
statusCode: 200,
|
|
|
|
|
|
msgName: 'msg',
|
|
|
|
|
|
countName: 'total',
|
|
|
|
|
|
dataName: 'rows'
|
|
|
|
|
|
},
|
|
|
|
|
|
cols: [[
|
|
|
|
|
|
{ type: 'numbers', title: '序号', width: '15%', align: 'center' },
|
|
|
|
|
|
{ field: 'teamName', title: '班组名称', width: '20%', align: 'center' },
|
|
|
|
|
|
{ field: 'content', title: '检测内容', width: '25%', align: 'center' },
|
|
|
|
|
|
{ field: 'testDay', title: '检测日期', width: '20%', align: 'center' },
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'testResult', title: '检测结果', width: '20%', align: 'center', templet: function (d) {
|
|
|
|
|
|
return d.testResult === '0' || d.testResult === 0 ?
|
|
|
|
|
|
'<span style="color: #00FFB8;">合格</span>' :
|
|
|
|
|
|
'<span style="color: #FF6B6B;">不合格</span>';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
]]
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 弹框内查询记录
|
|
|
|
|
|
function queryModalRecords() {
|
|
|
|
|
|
modalKeyword = $('#modalKeywordInput').val() || '';
|
|
|
|
|
|
|
|
|
|
|
|
// 重新加载表格
|
|
|
|
|
|
table.reload('modalQualityRecordTable', {
|
|
|
|
|
|
where: {
|
|
|
|
|
|
projectId: bidCode,
|
|
|
|
|
|
startTestDay: modalQueryParams.startTestDay,
|
|
|
|
|
|
endTestDay: modalQueryParams.endTestDay,
|
|
|
|
|
|
teamName: modalKeyword
|
|
|
|
|
|
},
|
|
|
|
|
|
page: {
|
|
|
|
|
|
curr: 1
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|