Browse Source

修复货源自动下架问题,为编辑功能添加图片复制功能

Boss2
Default User 2 months ago
parent
commit
fdf1a38491
  1. 2
      Reject.html
  2. 346
      supply.html
  3. 224
      test/api.test.js

2
Reject.html

@ -3425,7 +3425,7 @@ function showImageViewer(imgElement) {
<div class="image-viewer" id="imageViewer"> <div class="image-viewer" id="imageViewer">
<button class="image-viewer-prev" onclick="showPrevImage(event)">&lt;</button> <button class="image-viewer-prev" onclick="showPrevImage(event)">&lt;</button>
<div class="image-viewer-content"> <div class="image-viewer-content">
<img id="viewerImage" src="" alt="大图查看"> <img id="viewerImage" src="data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%22 height=%22100%22%3E%3Crect width=%22100%22 height=%22100%22 fill=%22%23f5f5f5%22/%3E%3Ctext x=%2250%22 y=%2250%22 font-family=%22Arial%22 font-size=%2212%22 fill=%22%23999%22 text-anchor=%22middle%22 dominant-baseline=%22middle%22%3E暂无图片%3C/text%3E%3C/svg%3E" alt="大图查看">
<span class="image-counter" id="imageCounter"></span> <span class="image-counter" id="imageCounter"></span>
</div> </div>
<button class="image-viewer-next" onclick="showNextImage(event)">&gt;</button> <button class="image-viewer-next" onclick="showNextImage(event)">&gt;</button>

346
supply.html

@ -1344,7 +1344,7 @@
<!-- 上一张按钮 --> <!-- 上一张按钮 -->
<button class="image-viewer-nav prev-btn" onclick="prevPreviewImage()"></button> <button class="image-viewer-nav prev-btn" onclick="prevPreviewImage()"></button>
<!-- 图片显示 --> <!-- 图片显示 -->
<img id="previewImage" class="preview-image" src="" style="transform: scale(1); transition: transform 0.1s ease;"> <img id="previewImage" class="preview-image" src="data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%22 height=%22100%22%3E%3Crect width=%22100%22 height=%22100%22 fill=%22%23f5f5f5%22/%3E%3Ctext x=%2250%22 y=%2250%22 font-family=%22Arial%22 font-size=%2212%22 fill=%22%23999%22 text-anchor=%22middle%22 dominant-baseline=%22middle%22%3E暂无图片%3C/text%3E%3C/svg%3E" style="transform: scale(1); transition: transform 0.1s ease;">
<!-- 下一张按钮 --> <!-- 下一张按钮 -->
<button class="image-viewer-nav next-btn" onclick="nextPreviewImage()"></button> <button class="image-viewer-nav next-btn" onclick="nextPreviewImage()"></button>
<!-- 关闭按钮 --> <!-- 关闭按钮 -->
@ -2058,58 +2058,73 @@
if (supply) { if (supply) {
console.log('找到对应的货源:', supply.id, supply.productName); console.log('找到对应的货源:', supply.id, supply.productName);
// 计算下架时间: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);
const autoOfflineHours = parseFloat(supply.autoOfflineHours) || 24; // 默认24小时,转换为数字
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);
const now = new Date(); // 检查是否有显式设置的自动下架时间
console.log('当前时间:', now); if (supply.autoOfflineHours && supply.autoOfflineHours !== '' && supply.autoOfflineHours !== null) {
const timeDiff = offlineTime - now; console.log('有显式设置的自动下架时间');
console.log('时间差:', timeDiff, '毫秒'); // 计算下架时间:updated_at + autoOfflineHours(使用毫秒数计算,更精确)
const updatedAt = new Date(supply.updated_at || supply.created_at);
if (timeDiff > 0) { console.log('updatedAt:', updatedAt, 'supply.updated_at:', supply.updated_at, 'supply.created_at:', supply.created_at);
// 计算剩余下架时间 const autoOfflineHours = parseFloat(supply.autoOfflineHours);
const days = Math.floor(timeDiff / (1000 * 60 * 60 * 24)); console.log('autoOfflineHours:', autoOfflineHours, 'supply.autoOfflineHours:', supply.autoOfflineHours);
const hours = Math.floor((timeDiff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); // 将小时转换为毫秒,使用setTime方法更精确
const minutes = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60)); const autoOfflineMs = autoOfflineHours * 60 * 60 * 1000;
const seconds = Math.floor((timeDiff % (1000 * 60)) / 1000); const offlineTime = new Date(updatedAt.getTime() + autoOfflineMs);
console.log('offlineTime:', offlineTime);
console.log('剩余下架时间:', days, '天', hours, '小时', minutes, '分钟', seconds, '秒'); const now = new Date();
console.log('当前时间:', now);
const timeDiff = offlineTime - now;
console.log('时间差:', timeDiff, '毫秒');
// 更新显示 if (timeDiff > 0) {
let countdownText = ''; // 计算剩余下架时间
if (days > 0) { const days = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
countdownText = `${days}天${hours}时${minutes}分`; const hours = Math.floor((timeDiff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
} else if (hours > 0) { const minutes = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60));
countdownText = `${hours}时${minutes}分`; const seconds = Math.floor((timeDiff % (1000 * 60)) / 1000);
console.log('剩余下架时间:', days, '天', hours, '小时', minutes, '分钟', seconds, '秒');
// 更新显示
let countdownText = '';
if (days > 0) {
countdownText = `${days}天${hours}时${minutes}分`;
} else if (hours > 0) {
countdownText = `${hours}时${minutes}分`;
} else {
countdownText = `${minutes}分${seconds}秒`;
}
// 根据元素类型设置不同的显示格式
if (element.classList.contains('countdown-badge')) {
element.innerHTML = `⏰ ${countdownText}`;
element.style.background = 'linear-gradient(135deg, #ff6b6b, #ee5a6f)';
element.style.boxShadow = '0 2px 4px rgba(255, 107, 107, 0.3)';
} else if (element.classList.contains('countdown')) {
element.innerHTML = `剩余下架时间: ${countdownText}`;
}
console.log('更新倒计时显示为:', countdownText);
} else { } else {
countdownText = `${minutes}分${seconds}秒`; // 时间到了
} console.log('时间已到,显示已下架');
if (element.classList.contains('countdown-badge')) {
// 根据元素类型设置不同的显示格式 element.innerHTML = '⏰ 已下架';
if (element.classList.contains('countdown-badge')) { element.style.background = '#8c8c8c';
element.innerHTML = `⏰ ${countdownText}`; element.style.boxShadow = '0 2px 4px rgba(140, 140, 140, 0.3)';
element.style.background = 'linear-gradient(135deg, #ff6b6b, #ee5a6f)'; } else if (element.classList.contains('countdown')) {
element.style.boxShadow = '0 2px 4px rgba(255, 107, 107, 0.3)'; element.innerHTML = '剩余下架时间: 已下架';
} else if (element.classList.contains('countdown')) { }
element.innerHTML = `剩余下架时间: ${countdownText}`;
} }
console.log('更新倒计时显示为:', countdownText);
} else { } else {
// 时间到了 // 没有设置自动下架时间,隐藏倒计时或显示无倒计时
console.log('时间已到,显示已下架'); console.log('没有设置自动下架时间,隐藏倒计时');
if (element.classList.contains('countdown-badge')) { if (element.classList.contains('countdown-badge')) {
element.innerHTML = '⏰ 已下架'; element.innerHTML = '⏰ 无倒计时';
element.style.background = '#8c8c8c'; element.style.background = '#52c41a';
element.style.boxShadow = '0 2px 4px rgba(140, 140, 140, 0.3)'; element.style.boxShadow = '0 2px 4px rgba(82, 196, 26, 0.3)';
} else if (element.classList.contains('countdown')) { } else if (element.classList.contains('countdown')) {
element.innerHTML = '剩余下架时间: 已下架'; element.innerHTML = '剩余下架时间: ';
} }
} }
} else { } else {
@ -2141,19 +2156,26 @@
// 检查所有状态为published的货源,不管前端显示什么 // 检查所有状态为published的货源,不管前端显示什么
if (supply.status === 'published') { if (supply.status === 'published') {
console.log('处理上架状态的货源:', supply.id); console.log('处理上架状态的货源:', supply.id);
// 计算下架时间:updated_at + autoOfflineHours(使用毫秒数计算,更精确)
const updatedAt = new Date(supply.updated_at || supply.created_at);
const autoOfflineHours = parseFloat(supply.autoOfflineHours) || 24; // 默认24小时,转换为数字
console.log('autoOfflineHours:', autoOfflineHours);
// 将小时转换为毫秒,使用setTime方法更精确
const autoOfflineMs = autoOfflineHours * 60 * 60 * 1000;
const offlineTime = new Date(updatedAt.getTime() + autoOfflineMs);
console.log('计算的下架时间:', offlineTime, '当前时间:', now);
if (now >= offlineTime) { // 只有在显式设置了自动下架时间的情况下才应用自动下架逻辑
// 时间到了,修改状态 if (supply.autoOfflineHours && supply.autoOfflineHours !== '' && supply.autoOfflineHours !== null) {
console.log('时间到了,调用updateSupplyStatus:', supply.id, '从published改为sold_out'); console.log('有显式设置的自动下架时间');
await updateSupplyStatus(supply.id, 'sold_out'); // 计算下架时间:updated_at + autoOfflineHours(使用毫秒数计算,更精确)
const updatedAt = new Date(supply.updated_at || supply.created_at);
const autoOfflineHours = parseFloat(supply.autoOfflineHours); // 只转换,不设置默认值
console.log('autoOfflineHours:', autoOfflineHours);
// 将小时转换为毫秒,使用setTime方法更精确
const autoOfflineMs = autoOfflineHours * 60 * 60 * 1000;
const offlineTime = new Date(updatedAt.getTime() + autoOfflineMs);
console.log('计算的下架时间:', offlineTime, '当前时间:', now);
if (now >= offlineTime) {
// 时间到了,修改状态
console.log('时间到了,调用updateSupplyStatus:', supply.id, '从published改为sold_out');
await updateSupplyStatus(supply.id, 'sold_out');
}
} else {
console.log('没有显式设置自动下架时间,跳过自动下架检查');
} }
} }
} }
@ -2222,29 +2244,89 @@
} }
}); });
// 编辑页面拖拽上传事件
const editUploadArea = document.getElementById('editUploadImages');
if (editUploadArea) {
editUploadArea.addEventListener('dragenter', (e) => {
e.preventDefault();
e.stopPropagation();
editUploadArea.style.border = '2px dashed #1677ff';
editUploadArea.style.backgroundColor = '#f0f8ff';
editUploadArea.style.padding = '20px';
editUploadArea.style.borderRadius = '8px';
});
editUploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
e.stopPropagation();
});
editUploadArea.addEventListener('dragleave', (e) => {
e.preventDefault();
e.stopPropagation();
editUploadArea.style.border = 'none';
editUploadArea.style.backgroundColor = 'transparent';
editUploadArea.style.padding = '0';
});
editUploadArea.addEventListener('drop', (e) => {
e.preventDefault();
e.stopPropagation();
editUploadArea.style.border = 'none';
editUploadArea.style.backgroundColor = 'transparent';
editUploadArea.style.padding = '0';
const files = Array.from(e.dataTransfer.files);
// 过滤出图片文件
const imageFiles = files.filter(file => file.type.startsWith('image/'));
if (imageFiles.length > 0) {
handleEditDroppedImages(imageFiles);
}
});
}
// 复制粘贴上传事件 // 复制粘贴上传事件
document.addEventListener('paste', (e) => { document.addEventListener('paste', (e) => {
// 检查是否在创建货源模态框中 // 检查是否在创建货源模态框中
const createSupplyModal = document.getElementById('createSupplyModal'); const createSupplyModal = document.getElementById('createSupplyModal');
if (createSupplyModal.style.display !== 'flex') { const editSupplyModal = document.getElementById('editSupplyModal');
return;
} // 检查是否在创建或编辑货源模态框中
if (createSupplyModal && createSupplyModal.style.display === 'flex') {
// 检查是否有粘贴的图片
const items = e.clipboardData.items;
const imageFiles = [];
for (let i = 0; i < items.length; i++) {
if (items[i].type.startsWith('image/')) {
const file = items[i].getAsFile();
if (file) {
imageFiles.push(file);
}
}
}
// 检查是否有粘贴的图片 if (imageFiles.length > 0) {
const items = e.clipboardData.items; handleDroppedImages(imageFiles);
const imageFiles = []; }
} else if (editSupplyModal && editSupplyModal.style.display === 'flex') {
// 检查是否有粘贴的图片
const items = e.clipboardData.items;
const imageFiles = [];
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (items[i].type.startsWith('image/')) { if (items[i].type.startsWith('image/')) {
const file = items[i].getAsFile(); const file = items[i].getAsFile();
if (file) { if (file) {
imageFiles.push(file); imageFiles.push(file);
}
} }
} }
}
if (imageFiles.length > 0) { if (imageFiles.length > 0) {
handleDroppedImages(imageFiles); handleEditDroppedImages(imageFiles);
}
} }
}); });
} }
@ -2276,6 +2358,38 @@
} }
} }
// 处理编辑页面拖拽或粘贴的图片
async function handleEditDroppedImages(imageFiles) {
for (let i = 0; i < imageFiles.length; i++) {
if (editCurrentImages.length >= 2) {
alert('最多只能上传2张图片');
break;
}
const file = imageFiles[i];
const reader = new FileReader();
reader.onload = async function(e) {
let imageUrl = e.target.result;
try {
// 为图片添加水印
imageUrl = await addWatermarkToImage(imageUrl);
// 添加到当前编辑图片列表
editCurrentImages.push(imageUrl);
// 更新显示
updateEditImageDisplay();
} catch (error) {
console.error('图片处理失败:', error);
alert('图片处理失败,请重试');
}
};
reader.readAsDataURL(file);
}
}
// 规格选择功能 // 规格选择功能
let allSpecOptions = ['净重47+', '净重46-47', '净重45-46', '净重44-45', '净重43-44', '净重42-43', '净重41-42', '净重40-41', '净重39-40', '净重38-39', '净重37-39', '净重37-38', '净重36-38', '净重36-37', '净重35-36', '净重34-35', '净重33-34', '净重32-33', '净重32-34', '净重31-32', '净重30-35', '净重30-34', '净重30-32', '净重30-31', '净重29-31', '净重29-30', '净重28-29', '净重28以下', '毛重52以上', '毛重50-51', '毛重48-49', '毛重47-48', '毛重46-47', '毛重45-47', '毛重45-46', '毛重44-45', '毛重43-44', '毛重42-43', '毛重41-42', '毛重40-41', '毛重38-39', '毛重36-37', '毛重34-35', '毛重32-33', '毛重30-31', '毛重30以下']; let allSpecOptions = ['净重47+', '净重46-47', '净重45-46', '净重44-45', '净重43-44', '净重42-43', '净重41-42', '净重40-41', '净重39-40', '净重38-39', '净重37-39', '净重37-38', '净重36-38', '净重36-37', '净重35-36', '净重34-35', '净重33-34', '净重32-33', '净重32-34', '净重31-32', '净重30-35', '净重30-34', '净重30-32', '净重30-31', '净重29-31', '净重29-30', '净重28-29', '净重28以下', '毛重52以上', '毛重50-51', '毛重48-49', '毛重47-48', '毛重46-47', '毛重45-47', '毛重45-46', '毛重44-45', '毛重43-44', '毛重42-43', '毛重41-42', '毛重40-41', '毛重38-39', '毛重36-37', '毛重34-35', '毛重32-33', '毛重30-31', '毛重30以下'];
let filteredSpecOptions = [...allSpecOptions]; let filteredSpecOptions = [...allSpecOptions];
@ -3603,28 +3717,29 @@
// 更新联系人选择下拉框 // 更新联系人选择下拉框
function updateContactSelects() { function updateContactSelects() {
// 更新创建表单的联系人选择框
const contactSelect = document.getElementById('contactId'); const contactSelect = document.getElementById('contactId');
if (!contactSelect) return; if (contactSelect) {
// 清空现有选项
// 清空现有选项 contactSelect.innerHTML = '';
contactSelect.innerHTML = '';
// 添加默认选项
// 添加默认选项 const defaultOption = document.createElement('option');
const defaultOption = document.createElement('option'); defaultOption.value = '';
defaultOption.value = ''; defaultOption.textContent = '请选择联系人';
defaultOption.textContent = '请选择联系人'; contactSelect.appendChild(defaultOption);
contactSelect.appendChild(defaultOption);
// 添加联系人选项,只显示有电话号码的联系人
// 添加联系人选项,只显示有电话号码的联系人 contacts.forEach(contact => {
contacts.forEach(contact => { // 确保联系人有电话号码
// 确保联系人有电话号码 if (contact.phoneNumber && contact.phoneNumber.trim() !== '') {
if (contact.phoneNumber && contact.phoneNumber.trim() !== '') { const option = document.createElement('option');
const option = document.createElement('option'); option.value = contact.id;
option.value = contact.id; option.textContent = `${contact.name} (${contact.phoneNumber})`;
option.textContent = `${contact.name} (${contact.phoneNumber})`; contactSelect.appendChild(option);
contactSelect.appendChild(option); }
} });
}); }
} }
// 处理窗口大小变化 // 处理窗口大小变化
@ -3950,7 +4065,7 @@
<div class="supply-name"> <div class="supply-name">
${supply.productName} ${supply.productName}
<span class="supply-status ${status.class}">${status.text}</span> <span class="supply-status ${status.class}">${status.text}</span>
<span class="countdown-badge" data-id="${supply.id}" style="margin-left: 8px; padding: 4px 12px; background: linear-gradient(135deg, #ff6b6b, #ee5a6f); color: white; border-radius: 16px; font-size: 12px; font-weight: 500; box-shadow: 0 2px 4px rgba(255, 107, 107, 0.3); display: inline-flex; align-items: center; gap: 4px;">⏰ 计算中...</span> ${supply.autoOfflineHours && supply.autoOfflineHours !== '' && supply.autoOfflineHours !== null ? `<span class="countdown-badge" data-id="${supply.id}" style="margin-left: 8px; padding: 4px 12px; background: linear-gradient(135deg, #ff6b6b, #ee5a6f); color: white; border-radius: 16px; font-size: 12px; font-weight: 500; box-shadow: 0 2px 4px rgba(255, 107, 107, 0.3); display: inline-flex; align-items: center; gap: 4px;">⏰ 计算中...</span>` : ''}
<button class="copy-supply-btn" onclick="copySupply('${supply.id}')">复制</button> <button class="copy-supply-btn" onclick="copySupply('${supply.id}')">复制</button>
</div> </div>
<!-- 基本信息 --> <!-- 基本信息 -->
@ -3962,7 +4077,7 @@
<div class="detail-item">地区: ${supply.region || '未设置'}</div> <div class="detail-item">地区: ${supply.region || '未设置'}</div>
<div class="detail-item" style="color: #f5222d;">价格: ¥${supply.price || '0'}</div> <div class="detail-item" style="color: #f5222d;">价格: ¥${supply.price || '0'}</div>
<div class="detail-item" style="font-size: 12px; color: #999;">创建时间: ${formatDate(supply.created_at)}</div> <div class="detail-item" style="font-size: 12px; color: #999;">创建时间: ${formatDate(supply.created_at)}</div>
<div class="detail-item" style="color: #faad14;"><span class="countdown" data-id="${supply.id}">剩余下架时间: 计算中...</span></div> ${supply.autoOfflineHours && supply.autoOfflineHours !== '' && supply.autoOfflineHours !== null ? `<div class="detail-item" style="color: #faad14;"><span class="countdown" data-id="${supply.id}">剩余下架时间: 计算中...</span></div>` : ''}
</div> </div>
</div> </div>
<!-- 右侧规格-件数对 --> <!-- 右侧规格-件数对 -->
@ -4122,10 +4237,21 @@
// 货源状态 // 货源状态
document.getElementById('supplyStatus').value = supply.supplyStatus || ''; document.getElementById('supplyStatus').value = supply.supplyStatus || '';
// 联系人 // 联系人 - 使用contacts数组查找完整信息
document.getElementById('contactId').value = supply.contactId || ''; document.getElementById('contactId').value = supply.contactId || '';
document.getElementById('contactIdDisplayText').textContent = supply.product_contact || '请选择联系人';
selectedContactId = supply.contactId || ''; selectedContactId = supply.contactId || '';
if (supply.contactId) {
// 从contacts数组(可能包含本地缓存数据)中查找联系人
const contact = contacts.find(c => String(c.id) === String(supply.contactId));
if (contact) {
document.getElementById('contactIdDisplayText').textContent = `${contact.name} (${contact.phoneNumber})`;
} else {
// 如果找不到联系人,使用supply中的数据或默认值
document.getElementById('contactIdDisplayText').textContent = supply.product_contact || `联系人ID: ${supply.contactId}` || '请选择联系人';
}
} else {
document.getElementById('contactIdDisplayText').textContent = '请选择联系人';
}
// 产品包装 // 产品包装
document.getElementById('productingValue').value = supply.producting || ''; document.getElementById('productingValue').value = supply.producting || '';
@ -5422,10 +5548,6 @@
} }
// 显示编辑货源 // 显示编辑货源
function showEditSupply(id) {
alert('编辑功能开发中');
}
// 删除货源 // 删除货源
async function deleteSupply(id) { async function deleteSupply(id) {
if (confirm('确定要删除该货源吗?删除后将无法恢复。')) { if (confirm('确定要删除该货源吗?删除后将无法恢复。')) {
@ -5528,12 +5650,21 @@
document.getElementById('editSupplyStatus').value = supplyStatus; document.getElementById('editSupplyStatus').value = supplyStatus;
setEditSupplyStatus(supplyStatus); setEditSupplyStatus(supplyStatus);
// 分配联系人 // 分配联系人 - 使用contacts数组查找完整信息
// 显示联系人名称而不是ID
const contactName = supply.product_contact || supply.contactId || '请选择联系人';
document.getElementById('editContactIdDisplayText').textContent = contactName;
document.getElementById('editContactId').value = supply.contactId || ''; document.getElementById('editContactId').value = supply.contactId || '';
editSelectedContactId = supply.contactId || ''; editSelectedContactId = supply.contactId || '';
if (supply.contactId) {
// 从contacts数组(可能包含本地缓存数据)中查找联系人
const contact = contacts.find(c => String(c.id) === String(supply.contactId));
if (contact) {
document.getElementById('editContactIdDisplayText').textContent = `${contact.name} (${contact.phoneNumber})`;
} else {
// 如果找不到联系人,使用supply中的数据或默认值
document.getElementById('editContactIdDisplayText').textContent = supply.product_contact || `联系人ID: ${supply.contactId}` || '请选择联系人';
}
} else {
document.getElementById('editContactIdDisplayText').textContent = '请选择联系人';
}
document.getElementById('editDescription').value = supply.description || ''; document.getElementById('editDescription').value = supply.description || '';
document.getElementById('editRegionDisplayText').textContent = supply.region || '请选择地区'; document.getElementById('editRegionDisplayText').textContent = supply.region || '请选择地区';
document.getElementById('editRegionValue').value = supply.region || ''; document.getElementById('editRegionValue').value = supply.region || '';
@ -6575,13 +6706,6 @@
} }
// 隐藏编辑货源模态框 // 隐藏编辑货源模态框
function hideEditSupplyModal() {
document.getElementById('editSupplyModal').style.display = 'none';
currentEditSupplyId = null;
// 重置发布模式状态
window.currentEditPublishMode = false;
}
// 处理点击模态框外部关闭 // 处理点击模态框外部关闭
window.onclick = function(event) { window.onclick = function(event) {
// 确保只处理click事件,不处理拖拽选择文本导致的mouseup事件 // 确保只处理click事件,不处理拖拽选择文本导致的mouseup事件

224
test/api.test.js

@ -0,0 +1,224 @@
const request = require('supertest');
const expect = require('chai').expect;
const app = require('../Reject.js');
// 测试API端点
describe('API Endpoints', () => {
// 测试数据库连接
describe('GET /api/test-db', () => {
it('should return database connection status', async () => {
const res = await request(app)
.get('/api/test-db')
.set('Accept', 'application/json');
expect(res.status).to.equal(200);
expect(res.body).to.be.an('object');
expect(res.body).to.have.property('success');
});
});
// 测试获取货源列表
describe('GET /api/supplies', () => {
it('should return supplies list', async () => {
const res = await request(app)
.get('/api/supplies')
.set('Accept', 'application/json');
expect(res.status).to.equal(200);
expect(res.body).to.be.an('object');
expect(res.body).to.have.property('success');
expect(res.body).to.have.property('data');
});
});
// 测试获取供应商列表
describe('GET /api/suppliers', () => {
it('should return suppliers list', async () => {
const res = await request(app)
.get('/api/suppliers')
.set('Accept', 'application/json');
expect(res.status).to.equal(200);
expect(res.body).to.be.an('object');
expect(res.body).to.have.property('success');
expect(res.body).to.have.property('data');
});
});
// 测试获取联系人列表
describe('GET /api/contacts', () => {
it('should return contacts list', async () => {
const res = await request(app)
.get('/api/contacts')
.set('Accept', 'application/json');
expect(res.status).to.equal(200);
expect(res.body).to.be.an('object');
expect(res.body).to.have.property('success');
expect(res.body).to.have.property('data');
});
});
// 测试获取审核失败原因
describe('GET /api/supplies/:id/reject-reason', () => {
it('should return reject reason for supply', async () => {
// 首先获取一个货源ID
const suppliesRes = await request(app)
.get('/api/supplies')
.set('Accept', 'application/json');
if (suppliesRes.body.data && suppliesRes.body.data.length > 0) {
const supplyId = suppliesRes.body.data[0].id;
const res = await request(app)
.get(`/api/supplies/${supplyId}/reject-reason`)
.set('Accept', 'application/json');
expect(res.status).to.equal(200);
expect(res.body).to.be.an('object');
expect(res.body).to.have.property('success');
}
});
});
// 测试获取拒绝审核API路由注册
describe('GET /api/supplies/:id/reject', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/supplies/1/reject')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取供应商审核通过API路由注册
describe('GET /api/suppliers/:id/approve', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/suppliers/1/approve')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取供应商审核拒绝API路由注册
describe('GET /api/suppliers/:id/reject', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/suppliers/1/reject')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取供应商开始合作API路由注册
describe('GET /api/suppliers/:id/cooperate', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/suppliers/1/cooperate')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取供应商终止合作API路由注册
describe('GET /api/suppliers/:id/terminate', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/suppliers/1/terminate')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取创建货源API路由注册
describe('GET /api/supplies/create', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/supplies/create')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取图片上传API路由注册
describe('GET /api/upload-image', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/upload-image')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取下架货源API路由注册
describe('GET /api/supplies/:id/unpublish', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/supplies/1/unpublish')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取上架货源API路由注册
describe('GET /api/supplies/:id/publish', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/supplies/1/publish')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取删除货源API路由注册
describe('GET /api/supplies/:id/delete', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/supplies/1/delete')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取更新货源状态API路由注册
describe('GET /api/supplies/:id', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/supplies/1')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
// 测试获取编辑货源API路由注册
describe('GET /api/supplies/:id/edit', () => {
it('should return method not allowed for GET', async () => {
const res = await request(app)
.get('/api/supplies/1/edit')
.set('Accept', 'application/json');
expect(res.status).to.equal(405); // Method Not Allowed
});
});
});
// 测试服务器启动
describe('Server', () => {
it('should be listening on port 3000', () => {
// 这个测试主要验证app对象是否被正确导出
expect(app).to.be.an('object');
expect(app).to.have.property('listen');
expect(app.listen).to.be.a('function');
});
});
Loading…
Cancel
Save