feat(vip): 增强VIP客户数据加载的健壮性和错误处理

- 添加多URL尝试机制,优先使用绝对路径
- 改进JSON解析错误处理,包括格式修复尝试
- 支持嵌套数据结构解析
- 增加详细的调试日志和状态更新
- 添加测试页面用于诊断VIP数据加载问题
This commit is contained in:
2025-11-19 17:28:58 +08:00
parent 07030b0b4b
commit b67e9a89ac
2 changed files with 726 additions and 64 deletions
+155 -64
View File
@@ -735,86 +735,177 @@ $packages_json = json_encode(array_map(function($package) {
console.log('开始加载VIP客户列表...');
return new Promise((resolve, reject) => {
fetch('get_vip_customers.php')
.then(response => {
console.log('VIP客户API响应状态:', response.status);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
// 定义多个可能的API路径,优先使用绝对路径
const apiUrls = [
'/carwashorder/carwash_order/get_vip_customers.php', // 推荐的绝对路径
'get_vip_customers.php', // 原始相对路径
'./get_vip_customers.php' // 另一种相对路径
];
let currentAttempt = 0;
function tryNextUrl() {
if (currentAttempt >= apiUrls.length) {
const errorMsg = '所有URL尝试失败,请检查API路径是否正确';
console.error(errorMsg);
updateDebugStatus(errorMsg, 'error');
reject(new Error(errorMsg));
return;
}
return response.text();
})
.then(text => {
console.log('VIP客户API原始响应:', text);
const currentUrl = apiUrls[currentAttempt];
console.log(`尝试加载VIP数据 (${currentAttempt + 1}/${apiUrls.length}): ${currentUrl}`);
try {
// 先检查是否为空响应
if (!text || text.trim() === '') {
throw new Error('API返回空响应');
fetch(currentUrl)
.then(response => {
console.log(`URL ${currentUrl} 响应状态: ${response.status} ${response.statusText}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = JSON.parse(text);
return response.text();
})
.then(text => {
console.log(`URL ${currentUrl} 原始响应文本长度: ${text.length} 字符`);
// 检查是否是错误响应
if (data.error) {
throw new Error(data.message || 'API返回错误');
// 显示部分原始响应以便调试
if (text.length > 0) {
console.log('原始响应前100字符:', text.substring(0, Math.min(100, text.length)));
}
console.log('VIP客户数据解析成功:', data);
// 确保数据是数组格式
if (!Array.isArray(data)) {
throw new Error('API返回数据不是数组格式');
}
window.allVIPCustomers = data; // 存储所有VIP客户数据
updateVIPSelect(data); // 更新下拉列表
console.log('VIP客户列表加载完成,共', data.length, '条记录');
// 更新调试面板状态和数据预览
updateDebugStatus('加载成功,共 ' + data.length + ' 条记录');
// 在调试面板中显示部分数据预览
const historyElem = document.getElementById('debug-search-history');
if (historyElem) {
const previewEntry = document.createElement('div');
previewEntry.style.cssText = 'border-bottom: 1px solid #eee; padding: 5px 0; color: #444;';
previewEntry.innerHTML = `
<div style="font-weight: bold;">📋 VIP数据预览:</div>
<div>加载了 ${data.length} 个VIP客户</div>
`;
// 显示前3个VIP客户作为预览
if (data.length > 0) {
let previewHtml = '<div style="margin-top: 5px; font-size: 11px;">';
data.slice(0, 3).forEach((vip, idx) => {
previewHtml += `${idx + 1}. ${vip.customer_name}: ${vip.phone}<br>`;
});
previewHtml += '</div>';
previewEntry.innerHTML += previewHtml;
try {
// 先检查是否为空响应
if (!text || text.trim() === '') {
throw new Error('API返回空响应');
}
historyElem.innerHTML = '';
historyElem.appendChild(previewEntry);
}
resolve(data); // 成功完成Promise
// 检查是否包含HTML标签(可能是错误页面)
if (text.includes('<html') || text.includes('<body') || text.includes('</html>')) {
throw new Error('响应包含HTML内容而非JSON');
}
// 尝试解析JSON
let data;
try {
data = JSON.parse(text);
} catch (parseError) {
// 尝试修复常见的JSON格式问题
console.warn('JSON解析失败,尝试修复格式...');
// 移除可能的BOM字符
const cleanText = text.replace(/^\uFEFF/, '');
// 移除可能的多余逗号
const fixedText = cleanText.replace(/,\s*}/g, '}').replace(/,\s*\]/g, ']');
if (fixedText !== text) {
console.log('使用修复后的文本重新解析');
try {
data = JSON.parse(fixedText);
console.log('修复后解析成功!');
} catch (fixError) {
// 如果修复失败,继续尝试下一个URL
currentAttempt++;
tryNextUrl();
return;
}
} else {
// 如果没有修复,继续尝试下一个URL
currentAttempt++;
tryNextUrl();
return;
}
}
// 检查是否是错误响应
if (data.error) {
// 如果API返回错误,继续尝试下一个URL
currentAttempt++;
tryNextUrl();
return;
}
console.log('VIP客户数据解析成功:', typeof data);
// 处理可能的嵌套数据结构
let finalData = data;
if (!Array.isArray(data)) {
console.log('数据不是数组,检查是否有嵌套结构...');
if (data && data.customers && Array.isArray(data.customers)) {
console.log('发现嵌套的customers数组');
finalData = data.customers;
} else if (data && data.vip_customers && Array.isArray(data.vip_customers)) {
console.log('发现嵌套的vip_customers数组');
finalData = data.vip_customers;
} else {
// 格式不符合预期,继续尝试下一个URL
currentAttempt++;
tryNextUrl();
return;
}
}
console.log('最终VIP数据类型检查:', Array.isArray(finalData));
console.log('VIP客户数量:', finalData.length);
// 存储VIP客户数据
window.allVIPCustomers = finalData;
updateVIPSelect(finalData); // 更新下拉列表
// 更新调试面板状态
updateDebugStatus('加载成功,共 ' + finalData.length + ' 条记录', 'success');
// 显示前几个VIP客户信息(如果有的话)
if (finalData.length > 0) {
console.log('前3个VIP客户信息:');
finalData.slice(0, 3).forEach((vip, index) => {
console.log(`${index + 1}. ${vip.customer_name || '未知'} - ${vip.phone || '未知'}`);
});
}
// 在调试面板中显示部分数据预览
const historyElem = document.getElementById('debug-search-history');
if (historyElem) {
const previewEntry = document.createElement('div');
previewEntry.style.cssText = 'border-bottom: 1px solid #eee; padding: 5px 0; color: #444;';
previewEntry.innerHTML = `
<div style="font-weight: bold;">📋 VIP数据预览:</div>
<div>加载了 ${finalData.length} 个VIP客户</div>
`;
// 显示前3个VIP客户作为预览
if (finalData.length > 0) {
let previewHtml = '<div style="margin-top: 5px; font-size: 11px;">';
finalData.slice(0, 3).forEach((vip, idx) => {
previewHtml += `${idx + 1}. ${vip.customer_name || '未知'}: ${vip.phone || '未知'}<br>`;
});
previewHtml += '</div>';
previewEntry.innerHTML += previewHtml;
}
historyElem.innerHTML = '';
historyElem.appendChild(previewEntry);
}
// 成功完成,resolve Promise(使用处理后的finalData
resolve(finalData);
} catch(e) {
console.error('VIP客户数据解析失败:', e);
window.allVIPCustomers = [];
updateDebugStatus('解析失败: ' + e.message);
reject(e); // 拒绝Promise
console.error('VIP客户数据处理过程中发生异常:', e);
// 继续尝试下一个URL
currentAttempt++;
tryNextUrl();
}
})
.catch(error => {
console.error('加载VIP客户列表失败:', error);
updateDebugStatus('加载失败: ' + error.message);
window.allVIPCustomers = [];
reject(error); // 拒绝Promise
console.error(`URL ${currentUrl} 请求失败:`, error.message);
// 继续尝试下一个URL
currentAttempt++;
tryNextUrl();
});
}
// 开始尝试第一个URL
tryNextUrl();
});
}