|
|
|
@ -2054,6 +2054,7 @@ |
|
|
|
|
|
|
|
// 联系人数据 |
|
|
|
let contacts = []; |
|
|
|
let isLoadingContacts = false; // 标记联系人是否正在加载中 |
|
|
|
|
|
|
|
// 登录检查 |
|
|
|
function checkLogin() { |
|
|
|
@ -2090,6 +2091,154 @@ |
|
|
|
return parsedUserInfo; |
|
|
|
} |
|
|
|
|
|
|
|
// WebSocket连接管理 |
|
|
|
let ws = null; |
|
|
|
let wsReconnectAttempts = 0; |
|
|
|
const maxReconnectAttempts = 5; |
|
|
|
const reconnectDelay = 3000; // 3秒 |
|
|
|
|
|
|
|
// 保存定时器引用,方便后续清理 |
|
|
|
let timers = { |
|
|
|
loadSupplies: null, |
|
|
|
updateCountdowns: null, |
|
|
|
checkAutoOffline: null |
|
|
|
}; |
|
|
|
|
|
|
|
// 防止loadSupplies并发执行的标志 |
|
|
|
let isLoadingSupplies = false; |
|
|
|
|
|
|
|
// 初始化WebSocket连接 |
|
|
|
function initWebSocket() { |
|
|
|
// 获取当前页面的协议和主机 |
|
|
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; |
|
|
|
const host = window.location.host; |
|
|
|
const wsUrl = `${protocol}//${host}/ws`; |
|
|
|
|
|
|
|
console.log('正在尝试连接WebSocket服务器:', wsUrl); |
|
|
|
|
|
|
|
// 关闭现有的WebSocket连接,避免连接泄漏 |
|
|
|
if (ws) { |
|
|
|
try { |
|
|
|
// 关闭码1000表示正常关闭 |
|
|
|
ws.close(1000, '重新连接'); |
|
|
|
ws = null; |
|
|
|
} catch (error) { |
|
|
|
console.error('关闭旧WebSocket连接失败:', error); |
|
|
|
ws = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
ws = new WebSocket(wsUrl); |
|
|
|
|
|
|
|
// 连接打开事件 |
|
|
|
ws.onopen = function() { |
|
|
|
console.log('WebSocket连接已打开'); |
|
|
|
wsReconnectAttempts = 0; |
|
|
|
// 发送登录用户信息 |
|
|
|
const userInfo = JSON.parse(localStorage.getItem('userInfo')); |
|
|
|
if (userInfo) { |
|
|
|
ws.send(JSON.stringify({ |
|
|
|
type: 'login', |
|
|
|
userId: userInfo.userId || userInfo.id |
|
|
|
})); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 消息接收事件 |
|
|
|
ws.onmessage = function(event) { |
|
|
|
console.log('收到WebSocket消息:', event.data); |
|
|
|
try { |
|
|
|
handleWebSocketMessage(event.data); |
|
|
|
} catch (error) { |
|
|
|
console.error('处理WebSocket消息失败:', error); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 连接关闭事件 |
|
|
|
ws.onclose = function(event) { |
|
|
|
console.log('WebSocket连接已关闭:', event.code, event.reason); |
|
|
|
// 只有在非正常关闭时才重连 |
|
|
|
// 正常关闭码1000表示主动关闭,不需要重连 |
|
|
|
if (event.code !== 1000) { |
|
|
|
attemptReconnect(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 连接错误事件 |
|
|
|
ws.onerror = function(error) { |
|
|
|
console.error('WebSocket错误:', error); |
|
|
|
console.error('WebSocket错误详情:', error.message); |
|
|
|
// 错误发生后,onclose事件会被触发,由onclose处理重连 |
|
|
|
}; |
|
|
|
} catch (error) { |
|
|
|
console.error('WebSocket连接失败:', error); |
|
|
|
attemptReconnect(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 尝试重新连接 |
|
|
|
function attemptReconnect() { |
|
|
|
if (wsReconnectAttempts < maxReconnectAttempts) { |
|
|
|
wsReconnectAttempts++; |
|
|
|
console.log(`尝试重新连接WebSocket (${wsReconnectAttempts}/${maxReconnectAttempts})...`); |
|
|
|
setTimeout(initWebSocket, reconnectDelay); |
|
|
|
} else { |
|
|
|
console.error('WebSocket重连失败,已达到最大重试次数'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 处理WebSocket消息 |
|
|
|
function handleWebSocketMessage(message) { |
|
|
|
try { |
|
|
|
const data = JSON.parse(message); |
|
|
|
|
|
|
|
console.log('处理WebSocket消息:', data); |
|
|
|
|
|
|
|
switch (data.type) { |
|
|
|
case 'supply_update': |
|
|
|
// 货源更新通知,重新加载数据 |
|
|
|
console.log('收到货源更新通知,重新加载数据'); |
|
|
|
loadSupplies(); |
|
|
|
break; |
|
|
|
case 'supply_lock': |
|
|
|
// 货源锁定状态更新 |
|
|
|
console.log('收到货源锁定状态更新,重新加载数据'); |
|
|
|
loadSupplies(); |
|
|
|
break; |
|
|
|
case 'supply_status_change': |
|
|
|
// 货源状态变更 |
|
|
|
console.log('收到货源状态变更,重新加载数据'); |
|
|
|
loadSupplies(); |
|
|
|
break; |
|
|
|
case 'auto_offline': |
|
|
|
// 自动下架通知 |
|
|
|
console.log('收到自动下架通知,重新加载数据'); |
|
|
|
loadSupplies(); |
|
|
|
break; |
|
|
|
case 'ping': |
|
|
|
// 心跳响应 |
|
|
|
if (ws && ws.readyState === WebSocket.OPEN) { |
|
|
|
ws.send(JSON.stringify({ type: 'pong' })); |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
console.log('未知的WebSocket消息类型:', data.type); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('解析WebSocket消息失败:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 向WebSocket服务器发送消息 |
|
|
|
function sendWebSocketMessage(message) { |
|
|
|
if (ws && ws.readyState === WebSocket.OPEN) { |
|
|
|
ws.send(JSON.stringify(message)); |
|
|
|
} else { |
|
|
|
console.warn('WebSocket未连接,无法发送消息'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 初始化 |
|
|
|
window.onload = function() { |
|
|
|
// 登录检查 |
|
|
|
@ -2098,6 +2247,9 @@ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 初始化WebSocket连接 |
|
|
|
initWebSocket(); |
|
|
|
|
|
|
|
loadSupplies(); |
|
|
|
loadContacts(); |
|
|
|
loadFormData(); // 加载保存的表单数据,包括联系人信息 |
|
|
|
@ -2111,48 +2263,70 @@ |
|
|
|
startCountdowns(); |
|
|
|
// 启动自动检查下架时间 |
|
|
|
startAutoOfflineCheck(); |
|
|
|
|
|
|
|
// 启动定期刷新数据,确保label字段变化能实时显示 |
|
|
|
timers.loadSupplies = setInterval(loadSupplies, 5000); // 每5秒刷新一次 |
|
|
|
}; |
|
|
|
|
|
|
|
// 页面卸载时清理资源 |
|
|
|
window.addEventListener('beforeunload', function() { |
|
|
|
console.log('页面正在卸载,清理资源...'); |
|
|
|
|
|
|
|
// 关闭WebSocket连接 |
|
|
|
if (ws) { |
|
|
|
ws.close(1000, '页面卸载'); |
|
|
|
ws = null; |
|
|
|
} |
|
|
|
|
|
|
|
// 清除所有定时器 |
|
|
|
for (const timerName in timers) { |
|
|
|
if (timers[timerName]) { |
|
|
|
clearInterval(timers[timerName]); |
|
|
|
timers[timerName] = null; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 启动倒计时 |
|
|
|
function startCountdowns() { |
|
|
|
// 立即更新一次倒计时 |
|
|
|
updateCountdowns(); |
|
|
|
// 每秒更新一次倒计时 |
|
|
|
setInterval(updateCountdowns, 1000); |
|
|
|
timers.updateCountdowns = setInterval(updateCountdowns, 1000); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新倒计时显示 |
|
|
|
function updateCountdowns() { |
|
|
|
console.log('=== 更新倒计时 ==='); |
|
|
|
// console.log('=== 更新倒计时 ==='); |
|
|
|
// 更新所有倒计时元素 |
|
|
|
const countdownElements = document.querySelectorAll('.countdown-badge, .countdown'); |
|
|
|
console.log('找到的倒计时元素数量:', countdownElements.length); |
|
|
|
// console.log('找到的倒计时元素数量:', countdownElements.length); |
|
|
|
countdownElements.forEach(element => { |
|
|
|
const supplyId = element.dataset.id; |
|
|
|
console.log('处理倒计时元素,supplyId:', supplyId); |
|
|
|
// console.log('处理倒计时元素,supplyId:', supplyId); |
|
|
|
// 查找对应的货源 |
|
|
|
const supply = supplyData.supplies.find(s => String(s.id) === String(supplyId)); |
|
|
|
|
|
|
|
if (supply) { |
|
|
|
console.log('找到对应的货源:', supply.id, supply.productName); |
|
|
|
// console.log('找到对应的货源:', supply.id, supply.productName); |
|
|
|
|
|
|
|
// 检查是否有显式设置的自动下架时间 |
|
|
|
if (supply.autoOfflineHours && supply.autoOfflineHours !== '' && supply.autoOfflineHours !== null) { |
|
|
|
console.log('有显式设置的自动下架时间'); |
|
|
|
// console.log('有显式设置的自动下架时间'); |
|
|
|
// 计算下架时间:updated_at + autoOfflineHours(使用毫秒数计算,更精确) |
|
|
|
const updatedAt = new Date(supply.updated_at || supply.created_at); |
|
|
|
console.log('updatedAt:', updatedAt, 'supply.updated_at:', supply.updated_at, 'supply.created_at:', supply.created_at); |
|
|
|
// console.log('updatedAt:', updatedAt, 'supply.updated_at:', supply.updated_at, 'supply.created_at:', supply.created_at); |
|
|
|
const autoOfflineHours = parseFloat(supply.autoOfflineHours); |
|
|
|
console.log('autoOfflineHours:', autoOfflineHours, 'supply.autoOfflineHours:', supply.autoOfflineHours); |
|
|
|
// console.log('autoOfflineHours:', autoOfflineHours, 'supply.autoOfflineHours:', supply.autoOfflineHours); |
|
|
|
// 将小时转换为毫秒,使用setTime方法更精确 |
|
|
|
const autoOfflineMs = autoOfflineHours * 60 * 60 * 1000; |
|
|
|
const offlineTime = new Date(updatedAt.getTime() + autoOfflineMs); |
|
|
|
console.log('offlineTime:', offlineTime); |
|
|
|
// console.log('offlineTime:', offlineTime); |
|
|
|
|
|
|
|
const now = new Date(); |
|
|
|
console.log('当前时间:', now); |
|
|
|
// console.log('当前时间:', now); |
|
|
|
const timeDiff = offlineTime - now; |
|
|
|
console.log('时间差:', timeDiff, '毫秒'); |
|
|
|
// console.log('时间差:', timeDiff, '毫秒'); |
|
|
|
|
|
|
|
if (timeDiff > 0) { |
|
|
|
// 计算剩余下架时间 |
|
|
|
@ -2214,45 +2388,45 @@ |
|
|
|
// 启动自动检查下架时间 |
|
|
|
function startAutoOfflineCheck() { |
|
|
|
// 每30秒检查一次,平衡及时性和服务器负载 |
|
|
|
setInterval(checkAutoOffline, 30000); |
|
|
|
timers.checkAutoOffline = setInterval(checkAutoOffline, 30000); |
|
|
|
// 立即检查一次 |
|
|
|
checkAutoOffline(); |
|
|
|
} |
|
|
|
|
|
|
|
// 检查自动下架时间 |
|
|
|
async function checkAutoOffline() { |
|
|
|
console.log('=== 开始检查自动下架时间 ==='); |
|
|
|
// console.log('=== 开始检查自动下架时间 ==='); |
|
|
|
const allSupplies = supplyData.supplies; |
|
|
|
const now = new Date(); |
|
|
|
|
|
|
|
console.log('检查的货源总数:', allSupplies.length); |
|
|
|
// console.log('检查的货源总数:', allSupplies.length); |
|
|
|
|
|
|
|
for (const supply of allSupplies) { |
|
|
|
console.log('检查货源:', supply.id, supply.productName, '当前状态:', supply.status); |
|
|
|
// console.log('检查货源:', supply.id, supply.productName, '当前状态:', supply.status); |
|
|
|
|
|
|
|
// 检查所有状态为published的货源,不管前端显示什么 |
|
|
|
if (supply.status === 'published') { |
|
|
|
console.log('处理上架状态的货源:', supply.id); |
|
|
|
// console.log('处理上架状态的货源:', supply.id); |
|
|
|
|
|
|
|
// 只有在显式设置了自动下架时间的情况下才应用自动下架逻辑 |
|
|
|
if (supply.autoOfflineHours && supply.autoOfflineHours !== '' && supply.autoOfflineHours !== null) { |
|
|
|
console.log('有显式设置的自动下架时间'); |
|
|
|
// console.log('有显式设置的自动下架时间'); |
|
|
|
// 计算下架时间:updated_at + autoOfflineHours(使用毫秒数计算,更精确) |
|
|
|
const updatedAt = new Date(supply.updated_at || supply.created_at); |
|
|
|
const autoOfflineHours = parseFloat(supply.autoOfflineHours); // 只转换,不设置默认值 |
|
|
|
console.log('autoOfflineHours:', autoOfflineHours); |
|
|
|
// console.log('autoOfflineHours:', autoOfflineHours); |
|
|
|
// 将小时转换为毫秒,使用setTime方法更精确 |
|
|
|
const autoOfflineMs = autoOfflineHours * 60 * 60 * 1000; |
|
|
|
const offlineTime = new Date(updatedAt.getTime() + autoOfflineMs); |
|
|
|
console.log('计算的下架时间:', offlineTime, '当前时间:', now); |
|
|
|
// console.log('计算的下架时间:', offlineTime, '当前时间:', now); |
|
|
|
|
|
|
|
if (now >= offlineTime) { |
|
|
|
// 时间到了,修改状态 |
|
|
|
console.log('时间到了,调用updateSupplyStatus:', supply.id, '从published改为sold_out'); |
|
|
|
// console.log('时间到了,调用updateSupplyStatus:', supply.id, '从published改为sold_out'); |
|
|
|
await updateSupplyStatus(supply.id, 'sold_out'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.log('没有显式设置自动下架时间,跳过自动下架检查'); |
|
|
|
// console.log('没有显式设置自动下架时间,跳过自动下架检查'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2271,6 +2445,14 @@ |
|
|
|
}); |
|
|
|
|
|
|
|
if (response.ok) { |
|
|
|
// 向WebSocket服务器发送消息,通知其他客户端货源状态已更新 |
|
|
|
sendWebSocketMessage({ |
|
|
|
type: 'supply_status_change', |
|
|
|
supplyId: supplyId, |
|
|
|
action: 'update_status', |
|
|
|
status: status |
|
|
|
}); |
|
|
|
|
|
|
|
// 重新加载货源列表 |
|
|
|
loadSupplies(); |
|
|
|
console.log(`货源 ${supplyId} 状态已更新为 ${status}`); |
|
|
|
@ -2975,8 +3157,23 @@ |
|
|
|
contactIdSelectModal.classList.add('active'); |
|
|
|
// 重置搜索输入 |
|
|
|
document.getElementById('contactIdSearchInput').value = ''; |
|
|
|
filteredContactIdOptions = [...contacts]; |
|
|
|
generateContactIdOptions(); |
|
|
|
|
|
|
|
// 检查contacts数组是否为空,如果为空则尝试重新加载 |
|
|
|
if (contacts.length === 0) { |
|
|
|
console.log('contacts数组为空,尝试重新加载...'); |
|
|
|
loadContacts().then(() => { |
|
|
|
filteredContactIdOptions = [...contacts]; |
|
|
|
generateContactIdOptions(); |
|
|
|
}).catch(error => { |
|
|
|
console.error('重新加载联系人失败:', error); |
|
|
|
// 即使加载失败,也要确保UI更新 |
|
|
|
filteredContactIdOptions = [...contacts]; |
|
|
|
generateContactIdOptions(); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
filteredContactIdOptions = [...contacts]; |
|
|
|
generateContactIdOptions(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 隐藏联系人选择弹窗 |
|
|
|
@ -3841,15 +4038,25 @@ |
|
|
|
|
|
|
|
// 加载联系人数据 |
|
|
|
async function loadContacts() { |
|
|
|
// 防止并发执行 |
|
|
|
if (isLoadingContacts) { |
|
|
|
console.log('loadContacts已在执行中,跳过当前请求'); |
|
|
|
return Promise.resolve(); |
|
|
|
} |
|
|
|
|
|
|
|
isLoadingContacts = true; |
|
|
|
|
|
|
|
try { |
|
|
|
console.log('开始加载联系人数据...'); |
|
|
|
const response = await fetch('/api/contacts'); |
|
|
|
if (!response.ok) { |
|
|
|
throw new Error('服务器响应异常'); |
|
|
|
throw new Error(`服务器响应异常: ${response.status} ${response.statusText}`); |
|
|
|
} |
|
|
|
const result = await response.json(); |
|
|
|
console.log('联系人API返回结果:', result); |
|
|
|
// 确保contacts是一个数组 |
|
|
|
contacts = result.data || []; |
|
|
|
console.log('联系人数据加载成功:', contacts); |
|
|
|
console.log('联系人数据加载成功,共', contacts.length, '个联系人:', contacts); |
|
|
|
|
|
|
|
// 保存到本地缓存,添加时间戳和版本号 |
|
|
|
const contactsCache = { |
|
|
|
@ -3872,7 +4079,7 @@ |
|
|
|
const cacheExpiry = 7 * 24 * 60 * 60 * 1000; |
|
|
|
if (Date.now() - contactsCache.timestamp < cacheExpiry) { |
|
|
|
contacts = contactsCache.data || []; |
|
|
|
console.log('从本地缓存加载联系人数据:', contacts); |
|
|
|
console.log('从本地缓存加载联系人数据,共', contacts.length, '个联系人:', contacts); |
|
|
|
updateContactSelects(); |
|
|
|
return; |
|
|
|
} else { |
|
|
|
@ -3885,6 +4092,9 @@ |
|
|
|
|
|
|
|
// 出错且无有效缓存时,将contacts设为空数组 |
|
|
|
contacts = []; |
|
|
|
} finally { |
|
|
|
// 无论成功还是失败,都要重置加载状态 |
|
|
|
isLoadingContacts = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -3922,6 +4132,14 @@ |
|
|
|
|
|
|
|
// 加载货源列表 |
|
|
|
async function loadSupplies() { |
|
|
|
// 防止并发执行 |
|
|
|
if (isLoadingSupplies) { |
|
|
|
console.log('loadSupplies已在执行中,跳过当前请求'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
isLoadingSupplies = true; |
|
|
|
|
|
|
|
try { |
|
|
|
// 获取当前登录用户信息 |
|
|
|
const userInfo = checkLogin(); |
|
|
|
@ -3962,6 +4180,9 @@ |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('加载货源失败:', error); |
|
|
|
} finally { |
|
|
|
// 无论成功还是失败,都要重置加载状态 |
|
|
|
isLoadingSupplies = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -5512,6 +5733,15 @@ |
|
|
|
// 重置表单状态,确保下次打开时是空白状态 |
|
|
|
resetForm(); |
|
|
|
hideAddSupplyModal(); |
|
|
|
|
|
|
|
// 向WebSocket服务器发送消息,通知其他客户端有新的货源创建 |
|
|
|
sendWebSocketMessage({ |
|
|
|
type: 'supply_create', |
|
|
|
supplyId: result.data.id, |
|
|
|
action: 'create', |
|
|
|
data: result.data |
|
|
|
}); |
|
|
|
|
|
|
|
loadSupplies(); |
|
|
|
} else { |
|
|
|
// 创建失败,保持保存的数据 |
|
|
|
@ -5890,6 +6120,14 @@ |
|
|
|
}); |
|
|
|
const result = await response.json(); |
|
|
|
if (result.success) { |
|
|
|
// 向WebSocket服务器发送消息,通知其他客户端货源已下架 |
|
|
|
sendWebSocketMessage({ |
|
|
|
type: 'supply_status_change', |
|
|
|
supplyId: id, |
|
|
|
action: 'unpublish', |
|
|
|
status: 'hidden' |
|
|
|
}); |
|
|
|
|
|
|
|
alert('下架成功'); |
|
|
|
loadSupplies(); |
|
|
|
} else { |
|
|
|
@ -5912,6 +6150,13 @@ |
|
|
|
}); |
|
|
|
const result = await response.json(); |
|
|
|
if (result.success) { |
|
|
|
// 向WebSocket服务器发送消息,通知其他客户端货源已删除 |
|
|
|
sendWebSocketMessage({ |
|
|
|
type: 'supply_update', |
|
|
|
supplyId: id, |
|
|
|
action: 'delete' |
|
|
|
}); |
|
|
|
|
|
|
|
alert('删除成功'); |
|
|
|
loadSupplies(); |
|
|
|
} else { |
|
|
|
@ -5972,6 +6217,9 @@ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 检查是否被锁定 |
|
|
|
const isLocked = supply.label === 1; |
|
|
|
|
|
|
|
currentEditSupplyId = id; |
|
|
|
// 保存发布模式状态 |
|
|
|
window.currentEditPublishMode = publishMode; |
|
|
|
@ -6122,18 +6370,68 @@ |
|
|
|
// 保存当前图片列表到全局变量,用于编辑时使用 |
|
|
|
editCurrentImages = supply.imageUrls && Array.isArray(supply.imageUrls) ? [...supply.imageUrls] : []; |
|
|
|
|
|
|
|
// 根据模式修改保存按钮文本 |
|
|
|
// 根据模式修改保存按钮文本和状态 |
|
|
|
const saveButton = document.querySelector('#editSupplyModal .modal-btn-primary'); |
|
|
|
if (saveButton) { |
|
|
|
if (publishMode) { |
|
|
|
saveButton.textContent = '上架'; |
|
|
|
saveButton.onclick = publishSupplyAfterEdit; |
|
|
|
if (isLocked) { |
|
|
|
// 锁定状态:按钮变灰色,不可点击 |
|
|
|
saveButton.textContent = publishMode ? '已锁定' : '已锁定'; |
|
|
|
saveButton.className = 'btn-disabled'; |
|
|
|
saveButton.onclick = null; |
|
|
|
} else { |
|
|
|
saveButton.textContent = '保存'; |
|
|
|
saveButton.onclick = saveEditSupply; |
|
|
|
// 未锁定状态:正常功能 |
|
|
|
if (publishMode) { |
|
|
|
saveButton.textContent = '上架'; |
|
|
|
saveButton.className = 'btn-primary'; |
|
|
|
saveButton.onclick = publishSupplyAfterEdit; |
|
|
|
} else { |
|
|
|
saveButton.textContent = '保存'; |
|
|
|
saveButton.className = 'btn-primary'; |
|
|
|
saveButton.onclick = saveEditSupply; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 设置表单元素的只读状态 |
|
|
|
const formElements = document.querySelectorAll('#editSupplyModal input, #editSupplyModal select, #editSupplyModal textarea, #editSupplyModal .modal-select-btn, #editSupplyModal .add-quantity-btn, #editSupplyModal .remove-quantity-btn, #editSupplyModal .delete-image-btn'); |
|
|
|
formElements.forEach(element => { |
|
|
|
if (isLocked) { |
|
|
|
// 锁定状态:设置为只读或禁用 |
|
|
|
if (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA') { |
|
|
|
element.readOnly = true; |
|
|
|
element.style.opacity = '0.6'; |
|
|
|
element.style.cursor = 'not-allowed'; |
|
|
|
} else { |
|
|
|
// 按钮元素 |
|
|
|
element.disabled = true; |
|
|
|
element.className = 'btn-disabled'; |
|
|
|
element.style.cursor = 'not-allowed'; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 未锁定状态:恢复正常 |
|
|
|
if (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA') { |
|
|
|
// 只有规格输入框是只读的,其他可以编辑 |
|
|
|
if (element.className.includes('spec-value')) { |
|
|
|
element.readOnly = true; |
|
|
|
} else { |
|
|
|
element.readOnly = false; |
|
|
|
} |
|
|
|
element.style.opacity = '1'; |
|
|
|
element.style.cursor = 'default'; |
|
|
|
} else { |
|
|
|
// 按钮元素 |
|
|
|
element.disabled = false; |
|
|
|
// 恢复按钮原有样式 |
|
|
|
if (element.className.includes('modal-select-btn')) { |
|
|
|
element.className = 'modal-select-btn'; |
|
|
|
} else if (element.className.includes('add-quantity-btn')) { |
|
|
|
element.className = 'add-quantity-btn'; |
|
|
|
} |
|
|
|
element.style.cursor = 'pointer'; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 显示编辑模态框 |
|
|
|
document.getElementById('editSupplyModal').classList.add('active'); |
|
|
|
// 隐藏body滚动条,避免双滚动条 |
|
|
|
@ -6186,6 +6484,14 @@ |
|
|
|
|
|
|
|
const result = await response.json(); |
|
|
|
if (result.success) { |
|
|
|
// 向WebSocket服务器发送消息,通知其他客户端货源已上架 |
|
|
|
sendWebSocketMessage({ |
|
|
|
type: 'supply_status_change', |
|
|
|
supplyId: id, |
|
|
|
action: 'publish', |
|
|
|
status: 'published' |
|
|
|
}); |
|
|
|
|
|
|
|
alert('上架成功'); |
|
|
|
loadSupplies(); |
|
|
|
} else { |
|
|
|
@ -7003,8 +7309,23 @@ |
|
|
|
const contactIdSelectModal = document.getElementById('editContactIdSelectModal'); |
|
|
|
contactIdSelectModal.classList.add('active'); |
|
|
|
document.getElementById('editContactIdSearchInput').value = ''; |
|
|
|
editFilteredContacts = [...contacts]; |
|
|
|
generateEditContactIdOptions(); |
|
|
|
|
|
|
|
// 检查contacts数组是否为空,如果为空则尝试重新加载 |
|
|
|
if (contacts.length === 0) { |
|
|
|
console.log('contacts数组为空,尝试重新加载...'); |
|
|
|
loadContacts().then(() => { |
|
|
|
editFilteredContacts = [...contacts]; |
|
|
|
generateEditContactIdOptions(); |
|
|
|
}).catch(error => { |
|
|
|
console.error('重新加载联系人失败:', error); |
|
|
|
// 即使加载失败,也要确保UI更新 |
|
|
|
editFilteredContacts = [...contacts]; |
|
|
|
generateEditContactIdOptions(); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
editFilteredContacts = [...contacts]; |
|
|
|
generateEditContactIdOptions(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 隐藏编辑联系人选择弹窗 |
|
|
|
@ -7203,6 +7524,14 @@ |
|
|
|
|
|
|
|
const result = await response.json(); |
|
|
|
if (result.success) { |
|
|
|
// 向WebSocket服务器发送消息,通知其他客户端货源已更新 |
|
|
|
sendWebSocketMessage({ |
|
|
|
type: 'supply_update', |
|
|
|
supplyId: currentEditSupplyId, |
|
|
|
action: 'update', |
|
|
|
data: result.data |
|
|
|
}); |
|
|
|
|
|
|
|
// 如果是直接编辑,显示成功消息;如果是编辑后上架,不显示,由上架函数处理 |
|
|
|
if (!window.currentEditPublishMode) { |
|
|
|
alert('编辑成功'); |
|
|
|
|