diff --git a/Reject.js b/Reject.js index 23d9d64..f72809a 100644 --- a/Reject.js +++ b/Reject.js @@ -3,6 +3,7 @@ const bodyParser = require('body-parser'); const cors = require('cors'); const mysql = require('mysql2/promise'); const path = require('path'); +const OssUploader = require('./oss-uploader'); const app = express(); const PORT = 3000; @@ -714,8 +715,6 @@ app.post('/api/suppliers/:id/terminate', async (req, res) => { } }); -// 导入OSS上传工具 -const OssUploader = require('./oss-uploader'); // 导入图片处理工具 const ImageProcessor = require('./image-processor'); @@ -1170,9 +1169,9 @@ app.put('/api/supplies/:id/edit', async (req, res) => { } } - // 处理媒体文件上传(图片和视频) let uploadedImageUrls = []; + const { imageUrls } = req.body; if (Array.isArray(imageUrls) && imageUrls.length > 0) { console.log('开始处理编辑媒体文件上传,共', imageUrls.length, '个文件'); @@ -1215,20 +1214,27 @@ app.put('/api/supplies/:id/edit', async (req, res) => { console.log('媒体文件处理完成,成功上传', uploadedImageUrls.length, '个文件'); } + // 如果有新上传的图片,更新imageUrls字段 + if (uploadedImageUrls.length > 0) { + await connection.query( + 'UPDATE products SET imageUrls = ? WHERE id = ?', + [JSON.stringify(uploadedImageUrls), productId] + ); + } // 更新货源信息 const updateQuery = ` UPDATE products SET productName = ?, price = ?, quantity = ?, grossWeight = ?, yolk = ?, specification = ?, supplyStatus = ?, description = ?, region = ?, - producting = ?, product_contact = ?, contact_phone = ?, imageUrls = ? + producting = ?, product_contact = ?, contact_phone = ? WHERE id = ? `; await connection.query(updateQuery, [ productName, price.toString(), parseInt(quantity), grossWeight, yolk, specification, supplyStatus, description, region, - producting, productContact, contactPhone, JSON.stringify(uploadedImageUrls), productId + producting, productContact, contactPhone, productId ]); // 提交事务 diff --git a/supply.html b/supply.html index 0b149c2..7929fd6 100644 --- a/supply.html +++ b/supply.html @@ -267,6 +267,23 @@ background-color: #8c8c8c; } + .copy-supply-btn { + display: inline-block; + padding: 4px 12px; + border: 1px solid #d9d9d9; + border-radius: 4px; + font-size: 12px; + background-color: #fff; + color: #333; + cursor: pointer; + margin-left: 8px; + } + + .copy-supply-btn:hover { + border-color: #1677ff; + color: #1677ff; + } + .supply-details { display: grid; grid-template-columns: repeat(2, 1fr); @@ -464,6 +481,29 @@ transition: all 0.3s; } + .delete-image-btn { + position: absolute; + top: 5px; + right: 5px; + width: 24px; + height: 24px; + background-color: rgba(245, 34, 45, 0.9); + color: white; + border: none; + border-radius: 50%; + font-size: 16px; + line-height: 20px; + text-align: center; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + } + + .delete-image-btn:hover { + background-color: #f5222d; + } + .upload-image:hover { transform: scale(1.05); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); @@ -952,6 +992,102 @@ height: 150px; } } + + /* 件数输入样式 */ + #quantityContainer { + display: flex; + flex-direction: column; + gap: 10px; + } + + .quantity-item { + display: flex; + align-items: center; + gap: 10px; + } + + .quantity-input { + flex: 1; + } + + .remove-quantity-btn { + width: 32px; + height: 32px; + border: none; + background-color: #ff4d4f; + color: white; + border-radius: 50%; + font-size: 16px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + } + + .add-quantity-btn { + align-self: flex-start; + padding: 8px 16px; + border: 1px dashed #1677ff; + background-color: white; + color: #1677ff; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + } + + .add-quantity-btn:hover { + background-color: #e6f7ff; + } + + /* 规格和件数对样式 */ + #specQuantityContainer, + #editSpecQuantityContainer { + display: flex; + flex-direction: column; + gap: 10px; + } + + .spec-quantity-pair { + display: flex; + align-items: center; + gap: 10px; + background-color: #fafafa; + padding: 10px; + border-radius: 8px; + border: 1px solid #f0f0f0; + } + + .spec-value { + flex: 1; + padding: 10px; + border: 1px solid #d9d9d9; + border-radius: 8px; + font-size: 14px; + box-sizing: border-box; + background-color: white; + cursor: pointer; + } + + .quantity-input { + width: 120px; + background-color: white; + } + + .add-spec-quantity-btn { + align-self: flex-start; + padding: 8px 16px; + border: 1px dashed #1677ff; + background-color: white; + color: #1677ff; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + margin-top: 5px; + } + + .add-spec-quantity-btn:hover { + background-color: #e6f7ff; + } @@ -997,7 +1133,7 @@ -
+ - +
- -
- 请选择规格 - + +
+ 请选择产品包装 +
-
@@ -1135,6 +1266,19 @@
+ +
+ +
+ +
+ + +
+ + +
+
@@ -1145,24 +1289,18 @@
- -
- - -
- - -
- - -
- + +
+ + +
+
@@ -1184,6 +1322,8 @@ + + @@ -1206,7 +1346,7 @@
第三方货源: 贸易商货源
@@ -1228,7 +1368,7 @@
@@ -1254,7 +1394,7 @@
(如果有色卡可以在货源描述里面填写色度)
@@ -1276,7 +1416,7 @@
@@ -1303,7 +1443,7 @@
@@ -1325,7 +1465,7 @@
@@ -1350,7 +1490,7 @@
@@ -1363,6 +1503,28 @@
+ + +
+
+
+

选择产品包装

+ +
+ +
+
+ +
+
+ +
+
- +
- +
-<<<<<<< Updated upstream -
提示:图片暂不支持编辑
-======= -
最多上传2个媒体文件(图片或视频)
- +
最多上传2张图片
+ ->>>>>>> Stashed changes
@@ -1459,12 +1617,12 @@
- +
- -
- 请选择规格 - + +
+ 请选择产品包装 +
@@ -1479,6 +1637,19 @@
+ +
+ +
+ +
+ + +
+ + +
+
@@ -1489,24 +1660,18 @@
- -
- - -
- - -
- - -
- + +
+ + +
+
@@ -1534,7 +1699,7 @@
@@ -1561,7 +1726,7 @@
第三方货源: 贸易商货源
@@ -1583,7 +1748,7 @@
@@ -1605,7 +1770,7 @@
@@ -1631,7 +1796,7 @@
(如果有色卡可以在货源描述里面填写色度)
@@ -1653,7 +1818,7 @@
@@ -1667,6 +1832,28 @@
+ +
+
+
+

选择产品包装

+ +
+ +
+
+ +
+
+ +
+
+
@@ -1675,7 +1862,7 @@
@@ -1722,7 +1909,7 @@ // 编辑相关全局变量 let currentEditSupplyId = null; - let editSelectedSpec = ''; + let editSelectedSpec = []; let editSelectedProvince = ''; let editSelectedCity = ''; let editSelectedDistrict = ''; @@ -1738,7 +1925,11 @@ let editAllYolkTypes = ['红心', '黄心', '双色', '未知']; let editFilteredYolkTypes = [...editAllYolkTypes]; let editSelectedYolk = ''; + let editAllProductingOptions = ['1*360枚新包装', '1*360枚旧包新拖', '1*360枚旧包旧拖', '1*420枚新包装', '1*480枚新包装', '30枚蛋托散装', '360枚散托']; + let editFilteredProductingOptions = [...editAllProductingOptions]; + let editSelectedProducting = ''; let editFilteredContacts = []; + let editCurrentImages = []; // 编辑时当前的图片列表 let editSelectedContactId = ''; // 联系人数据 @@ -1789,7 +1980,11 @@ loadSupplies(); loadContacts(); + loadFormData(); // 加载保存的表单数据,包括联系人信息 bindEvents(); + + // 初始化至少一个规格和件数对 + addSpecQuantityPair(); }; // 绑定事件 @@ -1863,8 +2058,8 @@ // 处理拖拽或粘贴的图片 async function handleDroppedImages(imageFiles) { for (let i = 0; i < imageFiles.length; i++) { - if (supplyData.uploadedImages.length >= 5) { - alert('最多只能上传5张图片'); + if (supplyData.uploadedImages.length >= 2) { + alert('最多只能上传2张图片'); break; } @@ -1872,17 +2067,14 @@ const reader = new FileReader(); reader.onload = async function(e) { - let mediaUrl = e.target.result; - let isVideo = file.type.startsWith('video/'); + let imageUrl = e.target.result; - // 只为图片添加水印,视频不添加 - if (!isVideo) { - mediaUrl = await addWatermarkToImage(mediaUrl); - } + // 为图片添加水印 + imageUrl = await addWatermarkToImage(imageUrl); - supplyData.uploadedImages.push(mediaUrl); + supplyData.uploadedImages.push(imageUrl); renderUploadedImages(); - // 媒体文件上传后自动保存表单数据 + // 图片上传后自动保存表单数据 saveFormData(); }; @@ -1893,7 +2085,12 @@ // 规格选择功能 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 selectedSpec = ''; + let selectedSpec = []; + + // 产品包装选择功能 + let allProductingOptions = ['1*360枚新包装', '1*360枚旧包新拖', '1*360枚旧包旧拖', '1*420枚新包装', '1*480枚新包装', '30枚蛋托散装', '360枚散托']; + let filteredProductingOptions = [...allProductingOptions]; + let selectedProducting = ''; // 货源类型选择功能 let allSourceTypeOptions = ['平台货源', '鸡场直销', '第三方货源']; @@ -1944,21 +2141,46 @@ const option = document.createElement('div'); option.className = 'select-item'; option.textContent = spec; + + // 检查当前规格是否已被选中 + if (selectedSpec.includes(spec)) { + option.classList.add('selected'); + } + + // 单击选择逻辑 option.onclick = () => { - // 移除所有选项的选中状态 + // 单选逻辑:移除所有选中状态 document.querySelectorAll('.select-item').forEach(item => { item.classList.remove('selected'); }); - // 添加当前选项的选中状态 + + // 添加当前选中状态 option.classList.add('selected'); - selectedSpec = spec; + + // 更新selectedSpec数组为单选 + selectedSpec = [spec]; }; + + // 双击确认逻辑 option.ondblclick = () => { - // 双击直接确认选择 - document.getElementById('specDisplayText').textContent = spec; - document.getElementById('specValue').value = spec; - hideSpecSelectModal(); + // 确保当前选项被选中 + if (!option.classList.contains('selected')) { + // 单选逻辑:移除所有选中状态 + document.querySelectorAll('.select-item').forEach(item => { + item.classList.remove('selected'); + }); + + // 添加当前选中状态 + option.classList.add('selected'); + + // 更新selectedSpec数组为单选 + selectedSpec = [spec]; + } + + // 自动确认选择 + confirmSpecSelection(); }; + specOptionsList.appendChild(option); }); } @@ -1977,13 +2199,163 @@ // 确认规格选择 function confirmSpecSelection() { - if (selectedSpec) { - document.getElementById('specDisplayText').textContent = selectedSpec; - document.getElementById('specValue').value = selectedSpec; + if (currentSpecInput) { + // 如果是为规格和件数对选择规格 + if (selectedSpec.length > 0) { + currentSpecInput.value = selectedSpec.join(', '); + } else { + currentSpecInput.value = ''; + } + } else { + // 否则,为旧的规格选择逻辑 + if (selectedSpec.length > 0) { + document.getElementById('specDisplayText').textContent = selectedSpec.join(', '); + document.getElementById('specValue').value = JSON.stringify(selectedSpec); + // 根据选中的规格数量动态调整件数输入框数量 + adjustQuantityInputs(); + } else { + document.getElementById('specDisplayText').textContent = '请选择规格'; + document.getElementById('specValue').value = '[]'; + } } hideSpecSelectModal(); } + // 添加件数输入项 + function addQuantityItem() { + const container = document.getElementById('quantityContainer'); + const quantityItem = document.createElement('div'); + quantityItem.className = 'quantity-item'; + quantityItem.innerHTML = ` + + + `; + container.insertBefore(quantityItem, container.lastElementChild); + } + + // 删除件数输入项 + function removeQuantityItem(btn) { + const container = document.getElementById('quantityContainer'); + const quantityItems = container.querySelectorAll('.quantity-item'); + + // 至少保留一个件数输入项 + if (quantityItems.length > 1) { + const quantityItem = btn.parentElement; + quantityItem.remove(); + } + } + + // 根据选中的规格数量调整件数输入框数量 + function adjustQuantityInputs() { + const container = document.getElementById('quantityContainer'); + const quantityItems = container.querySelectorAll('.quantity-item'); + const specCount = selectedSpec.length; + + // 如果规格数量大于件数输入框数量,添加缺少的输入框 + while (quantityItems.length < specCount) { + addQuantityItem(); + } + } + + // 添加规格和件数对 + function addSpecQuantityPair() { + const container = document.getElementById('specQuantityPairs'); + const pair = document.createElement('div'); + pair.className = 'spec-quantity-pair'; + pair.innerHTML = ` + + + + `; + container.appendChild(pair); + } + + // 删除规格和件数对 + function removeSpecQuantityPair(btn) { + const pair = btn.parentElement; + const specInput = pair.querySelector('.spec-value'); + const quantityInput = pair.querySelector('.quantity-input'); + + // 清除当前对的输入值 + if (specInput) specInput.value = ''; + if (quantityInput) quantityInput.value = ''; + } + + // 为规格和件数对显示规格选择弹窗 + function showSpecSelectModalForPair(input) { + // 保存当前点击的输入框 + currentSpecInput = input; + showSpecSelectModal(); + } + + // 保存当前点击的规格输入框 + let currentSpecInput = null; + + // 显示产品包装选择弹窗 + function showProductingSelectModal() { + const productingSelectModal = document.getElementById('productingSelectModal'); + productingSelectModal.classList.add('active'); + // 重置搜索输入 + document.getElementById('productingSearchInput').value = ''; + filteredProductingOptions = [...allProductingOptions]; + generateProductingOptions(); + } + + // 隐藏产品包装选择弹窗 + function hideProductingSelectModal() { + const productingSelectModal = document.getElementById('productingSelectModal'); + productingSelectModal.classList.remove('active'); + } + + // 生成产品包装选项 + function generateProductingOptions() { + const productingOptionsList = document.getElementById('productingOptionsList'); + productingOptionsList.innerHTML = ''; + + filteredProductingOptions.forEach(producting => { + const option = document.createElement('div'); + option.className = 'select-item'; + option.textContent = producting; + option.onclick = () => { + // 移除所有选项的选中状态 + document.querySelectorAll('.select-item').forEach(item => { + item.classList.remove('selected'); + }); + // 添加当前选项的选中状态 + option.classList.add('selected'); + selectedProducting = producting; + }; + option.ondblclick = () => { + // 双击直接确认选择 + document.getElementById('productingDisplayText').textContent = producting; + document.getElementById('productingValue').value = producting; + hideProductingSelectModal(); + }; + productingOptionsList.appendChild(option); + }); + } + + // 过滤产品包装选项 + function filterProductingOptions() { + const searchInput = document.getElementById('productingSearchInput'); + const searchKeyword = searchInput.value.toLowerCase(); + + filteredProductingOptions = allProductingOptions.filter(producting => { + return producting.toLowerCase().includes(searchKeyword); + }); + + generateProductingOptions(); + } + + // 确认产品包装选择 + function confirmProductingSelection() { + if (selectedProducting) { + document.getElementById('productingDisplayText').textContent = selectedProducting; + document.getElementById('productingValue').value = selectedProducting; + } + hideProductingSelectModal(); + } + // 显示货源类型选择弹窗 function showSourceTypeSelectModal() { const sourceTypeSelectModal = document.getElementById('sourceTypeSelectModal'); @@ -2997,10 +3369,40 @@ // 确保contacts是一个数组 contacts = result.data || []; console.log('联系人数据加载成功:', contacts); + + // 保存到本地缓存,添加时间戳和版本号 + const contactsCache = { + data: contacts, + version: '1.0', + timestamp: Date.now() + }; + localStorage.setItem('contactsCache', JSON.stringify(contactsCache)); + updateContactSelects(); } catch (error) { console.error('加载联系人数据失败:', error); - // 出错时将contacts设为空数组,避免后续错误 + + // 尝试从本地缓存加载 + try { + const cachedContacts = localStorage.getItem('contactsCache'); + if (cachedContacts) { + const contactsCache = JSON.parse(cachedContacts); + // 检查缓存是否有效(7天内) + const cacheExpiry = 7 * 24 * 60 * 60 * 1000; + if (Date.now() - contactsCache.timestamp < cacheExpiry) { + contacts = contactsCache.data || []; + console.log('从本地缓存加载联系人数据:', contacts); + updateContactSelects(); + return; + } else { + console.log('联系人缓存已过期'); + } + } + } catch (cacheError) { + console.error('加载联系人缓存失败:', cacheError); + } + + // 出错且无有效缓存时,将contacts设为空数组 contacts = []; } } @@ -3260,8 +3662,50 @@ const status = statusMap[supply.status] || { text: '未知', class: 'status-draft' }; - // 处理图片 - const imageUrl = supply.imageUrls && supply.imageUrls.length > 0 ? supply.imageUrls[0] : ''; + // 处理媒体文件(图片和视频) + let firstMediaUrl = ''; + let mediaType = 'image'; // 默认为图片 + let mediaPreviewHTML = ''; + + if (supply.imageUrls && supply.imageUrls.length > 0) { + // 获取第一个媒体文件 + firstMediaUrl = supply.imageUrls[0]; + + // 检测媒体类型 + if (firstMediaUrl.startsWith('data:video/') || + firstMediaUrl.match(/\.(mp4|mov|avi|wmv|flv|webm|mkv)$/i) || + firstMediaUrl.includes('video') || + (supply.imageUrls && supply.imageUrls.some(url => url.startsWith('data:video/') || url.match(/\.(mp4|mov|avi|wmv|flv|webm|mkv)$/i)))) { + mediaType = 'video'; + mediaPreviewHTML = ` + +
+ `; + } else { + mediaType = 'image'; + mediaPreviewHTML = ` + ${supply.productName} + `; + } + } else { + // 无媒体文件时的占位符 + mediaPreviewHTML = ` +
+ 暂无媒体 +
+ `; + } // 处理操作按钮 let actionsHTML = ''; @@ -3285,28 +3729,83 @@ `; } + // 解析规格和件数为数组 + let specifications = []; + let quantities = []; + + try { + if (supply.specification) { + if (typeof supply.specification === 'string') { + // 规格存储为中文逗号分隔的字符串 + specifications = supply.specification.split(',').filter(spec => spec.trim()); + } else if (Array.isArray(supply.specification)) { + specifications = supply.specification; + } else { + specifications = [supply.specification]; + } + } else if (supply.spec) { + specifications = [supply.spec]; + } + } catch (e) { + specifications = [supply.specification || supply.spec || '无']; + } + + try { + if (supply.quantity) { + if (typeof supply.quantity === 'string') { + // 件数存储为英文逗号分隔的字符串 + quantities = supply.quantity.split(',').filter(qty => qty.trim()); + } else if (Array.isArray(supply.quantity)) { + quantities = supply.quantity; + } else { + quantities = [supply.quantity]; + } + } + } catch (e) { + quantities = [supply.quantity || '0']; + } + + // 生成规格-件数对应关系的HTML + let specQuantityBoxes = ''; + const maxLength = Math.max(specifications.length, quantities.length); + for (let i = 0; i < maxLength; i++) { + const spec = specifications[i] || '无'; + const quantity = quantities[i] || '0'; + specQuantityBoxes += `
• 规格${i + 1}: ${spec} - 件数: ${quantity}件
`; + } + return `
-
- ${supply.productName} +
+ ${mediaPreviewHTML}
-
- ${supply.productName} - ${status.text} -
-
-
蛋黄: ${supply.yolk || '无'}
-
规格: ${supply.specification || supply.spec || '无'}
-
货源状态: ${supply.supplyStatus || '未设置'}
-
货源描述: ${supply.description || '无'}
-
件数: ${supply.quantity || '0'}件
-
斤重: ${supply.grossWeight || ''}斤
-
地区: ${supply.region || '未设置'}
-
价格: ¥${supply.price || '0'}
-
创建时间: ${formatDate(supply.created_at)}
+ +
+ +
+
+ ${supply.productName} + ${status.text} + +
+ +
+
蛋黄: ${supply.yolk || '无'}
+
货源状态: ${supply.supplyStatus || '未设置'}
+
货源描述: ${supply.description || '无'}
+
斤重: ${supply.grossWeight || ''}斤
+
地区: ${supply.region || '未设置'}
+
价格: ¥${supply.price || '0'}
+
创建时间: ${formatDate(supply.created_at)}
+
+
+ +
+ ${specQuantityBoxes} +
${actionsHTML} @@ -3323,6 +3822,183 @@ return `${date.getFullYear()}/${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; } + // 复制货源信息 + function copySupply(supplyId) { + try { + // 查找对应的货源信息 + let supply = null; + + // 1. 首先尝试直接从所有货源数组中查找 + if (supplyData.supplies && supplyData.supplies.length > 0) { + supply = supplyData.supplies.find(item => { + return String(item.id) === String(supplyId) || String(item.productId) === String(supplyId) || String(item._id) === String(supplyId); + }); + } + + // 2. 如果没找到,遍历所有状态的货源列表查找 + if (!supply) { + const allSupplies = [ + ...supplyData.publishedSupplies, + ...supplyData.pendingSupplies, + ...supplyData.rejectedSupplies, + ...supplyData.draftSupplies + ]; + + supply = allSupplies.find(item => { + return String(item.id) === String(supplyId) || String(item.productId) === String(supplyId) || String(item._id) === String(supplyId); + }); + } + + // 3. 如果没找到,遍历所有分页货源列表查找 + if (!supply) { + const paginatedSupplies = [ + ...(supplyData.paginatedSupplies.published || []), + ...(supplyData.paginatedSupplies.pending || []), + ...(supplyData.paginatedSupplies.rejected || []), + ...(supplyData.paginatedSupplies.draft || []) + ]; + + supply = paginatedSupplies.find(item => { + return String(item.id) === String(supplyId) || String(item.productId) === String(supplyId) || String(item._id) === String(supplyId); + }); + } + + // 4. 如果还是没找到,尝试从DOM中获取 + if (!supply) { + const supplyItem = document.querySelector(`[data-id="${supplyId}"]`); + if (supplyItem) { + // 从DOM中提取关键信息 + const productName = supplyItem.querySelector('.supply-name').textContent.replace(/已上架|审核中|审核失败|已隐藏|已下架|复制/g, '').trim(); + const priceText = supplyItem.querySelector('.detail-item:last-child').textContent; + const price = priceText.replace(/价格: ¥/, '').trim(); + + // 创建一个简化的supply对象 + supply = { + id: supplyId, + productName: productName, + price: price + }; + } + } + + // 调试日志 + console.log('复制货源信息:', { + supplyId: supplyId, + supplyFound: !!supply, + allSuppliesCount: (supplyData.supplies ? supplyData.supplies.length : 0) + + supplyData.publishedSupplies.length + + supplyData.pendingSupplies.length + + supplyData.rejectedSupplies.length + + supplyData.draftSupplies.length, + paginatedSuppliesCount: + (supplyData.paginatedSupplies.published ? supplyData.paginatedSupplies.published.length : 0) + + (supplyData.paginatedSupplies.pending ? supplyData.paginatedSupplies.pending.length : 0) + + (supplyData.paginatedSupplies.rejected ? supplyData.paginatedSupplies.rejected.length : 0) + + (supplyData.paginatedSupplies.draft ? supplyData.paginatedSupplies.draft.length : 0), + supplyDataKeys: supply ? Object.keys(supply) : 'none', + supplyData: supply + }); + + if (!supply) { + alert('未找到对应的货源信息'); + return; + } + + // 保存到全局变量 + supplyData.copiedSupply = supply; + + // 打开创建货源弹窗 + showAddSupplyModal(); + + // 填充表单数据 + fillFormWithSupplyData(supply); + + alert('货源信息已复制到创建表单'); + } catch (error) { + console.error('复制货源失败:', error); + alert('复制货源失败,请重试'); + } + } + + // 用货源数据填充表单 + function fillFormWithSupplyData(supply) { + // 重置表单 + resetForm(); + + // 填充表单字段 + document.getElementById('price').value = supply.price || ''; + document.getElementById('quantity').value = supply.quantity || ''; + document.getElementById('grossWeight').value = supply.grossWeight || ''; + document.getElementById('description').value = supply.description || ''; + + // 填充选择字段 + // 商品名称 + document.getElementById('productName').value = supply.productName || ''; + document.getElementById('productNameDisplayText').textContent = supply.productName || '请选择商品名称'; + selectedProductName = supply.productName || ''; + + // 货源类型 + document.getElementById('sourceType').value = supply.sourceType || ''; + document.getElementById('sourceTypeDisplayText').textContent = supply.sourceType || '请选择货源类型'; + selectedSourceType = supply.sourceType || ''; + + // 蛋黄类型 + document.getElementById('yolk').value = supply.yolk || ''; + document.getElementById('yolkDisplayText').textContent = supply.yolk || '请选择蛋黄类型'; + selectedYolk = supply.yolk || ''; + + // 地区 + document.getElementById('regionValue').value = supply.region || ''; + document.getElementById('regionDisplayText').textContent = supply.region || '请选择地区'; + + // 规格 + document.getElementById('specValue').value = supply.specification || supply.spec || ''; + document.getElementById('specDisplayText').textContent = (supply.specification || supply.spec) || '请选择规格'; + selectedSpec = supply.specification || supply.spec || ''; + + // 货源状态 + document.getElementById('supplyStatus').value = supply.supplyStatus || ''; + + // 联系人 + document.getElementById('contactId').value = supply.contactId || ''; + document.getElementById('contactIdDisplayText').textContent = supply.product_contact || '请选择联系人'; + selectedContactId = supply.contactId || ''; + + // 产品包装 + document.getElementById('productingValue').value = supply.producting || ''; + document.getElementById('productingDisplayText').textContent = supply.producting || '请选择产品包装'; + selectedProducting = supply.producting || ''; + + // 不复制图片,保持图片列表为空 + supplyData.uploadedImages = []; + renderUploadedImages(); + } + + // 检查是否为重复货源 + async function checkDuplicateSupply(formData) { + try { + // 构建查询参数 + const queryParams = new URLSearchParams({ + productName: formData.productName, + spec: formData.specification || formData.spec, + region: formData.region, + price: formData.price, + checkDuplicate: true + }); + + const response = await fetch(`/api/supplies?${queryParams}`); + const result = await response.json(); + + if (result.success && result.data && result.data.length > 0) { + return true; // 存在重复货源 + } + return false; // 不存在重复货源 + } catch (error) { + console.error('检查重复货源失败:', error); + return false; // 出错时默认允许创建 + } + } + // 切换列表展开/折叠 function toggleSection(type) { const listElement = document.getElementById(`${type}List`); @@ -3404,16 +4080,53 @@ // 重置表单函数(全局函数,以便多个地方可以调用) function resetForm() { - document.getElementById('createSupplyForm').reset(); - document.getElementById('uploadImages').innerHTML = ''; + // 重置表单 + const createSupplyForm = document.getElementById('createSupplyForm'); + if (createSupplyForm) { + createSupplyForm.reset(); + } + + // 重置图片 + const uploadImages = document.getElementById('uploadImages'); + if (uploadImages) { + uploadImages.innerHTML = ''; + } supplyData.uploadedImages = []; + + // 重置规格-件数对 + const specQuantityPairs = document.getElementById('specQuantityPairs'); + if (specQuantityPairs) { + specQuantityPairs.innerHTML = ''; + // 重新添加一个空的规格-件数对 + addSpecQuantityPair(); + } + // 重置自定义选择状态 - document.getElementById('specDisplayText').textContent = '请选择规格'; - document.getElementById('regionDisplayText').textContent = '请选择地区'; - document.getElementById('sourceTypeDisplayText').textContent = '请选择货源类型'; - document.getElementById('productNameDisplayText').textContent = '请选择商品名称'; - document.getElementById('yolkDisplayText').textContent = '请选择蛋黄类型'; - document.getElementById('contactIdDisplayText').textContent = '请选择联系人'; + const regionDisplayText = document.getElementById('regionDisplayText'); + if (regionDisplayText) { + regionDisplayText.textContent = '请选择地区'; + } + + const sourceTypeDisplayText = document.getElementById('sourceTypeDisplayText'); + if (sourceTypeDisplayText) { + sourceTypeDisplayText.textContent = '请选择货源类型'; + } + + const productNameDisplayText = document.getElementById('productNameDisplayText'); + if (productNameDisplayText) { + productNameDisplayText.textContent = '请选择商品名称'; + } + + const yolkDisplayText = document.getElementById('yolkDisplayText'); + if (yolkDisplayText) { + yolkDisplayText.textContent = '请选择蛋黄类型'; + } + + const contactIdDisplayText = document.getElementById('contactIdDisplayText'); + if (contactIdDisplayText) { + contactIdDisplayText.textContent = '请选择联系人'; + } + // 重置选择变量 selectedSpec = ''; selectedProvince = ''; @@ -3422,25 +4135,50 @@ selectedProductName = ''; selectedYolk = ''; selectedContactId = ''; + // 确保隐藏字段也被重置 - document.getElementById('specValue').value = ''; - document.getElementById('regionValue').value = ''; - document.getElementById('supplyStatus').value = ''; - document.getElementById('sourceType').value = ''; - document.getElementById('productName').value = ''; - document.getElementById('yolk').value = ''; - document.getElementById('contactId').value = ''; + const specValue = document.getElementById('specValue'); + if (specValue) specValue.value = ''; + + const regionValue = document.getElementById('regionValue'); + if (regionValue) regionValue.value = ''; + + const supplyStatus = document.getElementById('supplyStatus'); + if (supplyStatus) supplyStatus.value = ''; + + const sourceType = document.getElementById('sourceType'); + if (sourceType) sourceType.value = ''; + + const productName = document.getElementById('productName'); + if (productName) productName.value = ''; + + const yolk = document.getElementById('yolk'); + if (yolk) yolk.value = ''; + + const contactId = document.getElementById('contactId'); + if (contactId) contactId.value = ''; + // 重置货源状态按钮样式 - document.getElementById('preSaleBtn').style.borderColor = '#d9d9d9'; - document.getElementById('preSaleBtn').style.color = '#666'; - document.getElementById('inStockBtn').style.borderColor = '#d9d9d9'; - document.getElementById('inStockBtn').style.color = '#666'; + const preSaleBtn = document.getElementById('preSaleBtn'); + if (preSaleBtn) { + preSaleBtn.style.borderColor = '#d9d9d9'; + preSaleBtn.style.color = '#666'; + } + + const inStockBtn = document.getElementById('inStockBtn'); + if (inStockBtn) { + inStockBtn.style.borderColor = '#d9d9d9'; + inStockBtn.style.color = '#666'; + } } // 显示创建货源模态框 function showAddSupplyModal() { document.getElementById('createSupplyModal').style.display = 'flex'; + // 重新加载联系人数据,确保最新 + loadContacts(); + // 尝试从localStorage加载保存的表单数据 const savedFormData = localStorage.getItem('supplyFormDraft'); if (savedFormData) { @@ -3464,6 +4202,7 @@ const contactId = document.getElementById('contactId'); const specDisplayText = document.getElementById('specDisplayText'); const regionDisplayText = document.getElementById('regionDisplayText'); + const contactIdDisplayText = document.getElementById('contactIdDisplayText'); // 安全地设置表单值 if (productName) productName.value = formData.productName || ''; @@ -3485,6 +4224,10 @@ if (regionDisplayText && formData.regionDisplay) { regionDisplayText.textContent = formData.regionDisplay; } + // 恢复联系人显示文本 + if (contactIdDisplayText && formData.contactIdDisplay) { + contactIdDisplayText.textContent = formData.contactIdDisplay; + } // 恢复其他自定义下拉框显示文本 if (sourceTypeDisplayText && formData.sourceTypeDisplay) { sourceTypeDisplayText.textContent = formData.sourceTypeDisplay; @@ -3578,8 +4321,6 @@ document.getElementById('imageUpload').click(); } -<<<<<<< Updated upstream -======= // 触发编辑页面图片上传 function triggerEditImageUpload() { document.getElementById('editImageUpload').click(); @@ -3592,7 +4333,7 @@ for (let i = 0; i < files.length; i++) { if (editCurrentImages.length >= 2) { - alert('最多只能上传2个媒体文件(图片或视频)'); + alert('最多只能上传2张图片'); break; } @@ -3600,23 +4341,20 @@ const reader = new FileReader(); reader.onload = async function(e) { - let mediaUrl = e.target.result; - let isVideo = file.type.startsWith('video/'); + let imageUrl = e.target.result; try { - // 只为图片添加水印,视频不添加 - if (!isVideo) { - mediaUrl = await addWatermarkToImage(mediaUrl); - } + // 为图片添加水印 + imageUrl = await addWatermarkToImage(imageUrl); - // 添加到当前媒体列表 - editCurrentImages.push(mediaUrl); + // 添加到当前图片列表 + editCurrentImages.push(imageUrl); // 更新显示 updateEditImageDisplay(); } catch (error) { - console.error('媒体处理失败:', error); - alert('媒体处理失败,请重试'); + console.error('图片处理失败:', error); + alert('图片处理失败,请重试'); } }; @@ -3639,36 +4377,44 @@ updateEditImageDisplay(); } - // 更新编辑页面媒体显示(图片或视频) + // 更新编辑页面媒体文件显示 function updateEditImageDisplay() { const editUploadImages = document.getElementById('editUploadImages'); editUploadImages.innerHTML = ''; - editCurrentImages.forEach(mediaUrl => { - const imageElement = document.createElement('div'); - imageElement.className = 'upload-image'; + editCurrentImages.forEach(imageUrl => { + const mediaElement = document.createElement('div'); + mediaElement.className = 'upload-image'; - let mediaHtml = ''; - if (mediaUrl.startsWith('data:video/') || mediaUrl.endsWith('.mp4') || mediaUrl.endsWith('.mov') || mediaUrl.endsWith('.avi') || mediaUrl.endsWith('.wmv') || mediaUrl.endsWith('.flv')) { + let mediaContent; + if (imageUrl.startsWith('data:video/')) { // 视频文件 - mediaHtml = ``; + mediaContent = ` + + + `; } else { // 图片文件 - mediaHtml = `商品图片`; + mediaContent = ` + 商品图片 + + `; } - imageElement.innerHTML = ` - ${mediaHtml} - - `; - editUploadImages.appendChild(imageElement); + mediaElement.innerHTML = mediaContent; + editUploadImages.appendChild(mediaElement); }); } ->>>>>>> Stashed changes - // 为图片添加水印(前端Canvas实现) + // 为媒体文件添加水印(前端Canvas实现,仅处理图片,视频跳过) function addWatermarkToImage(imageUrl) { return new Promise((resolve, reject) => { + // 如果是视频文件,直接返回,不添加水印 + if (imageUrl.startsWith('data:video/')) { + resolve(imageUrl); + return; + } + const img = new Image(); img.crossOrigin = 'anonymous'; // 允许跨域图片 @@ -3719,13 +4465,8 @@ const uploadArea = document.getElementById('uploadImages'); for (let i = 0; i < files.length; i++) { -<<<<<<< Updated upstream - if (supplyData.uploadedImages.length >= 5) { - alert('最多只能上传5张图片'); -======= if (supplyData.uploadedImages.length >= 2) { - alert('最多只能上传2个媒体文件(图片或视频)'); ->>>>>>> Stashed changes + alert('最多只能上传2张图片'); break; } @@ -3751,29 +4492,32 @@ event.target.value = ''; } - // 渲染已上传媒体文件(图片和视频) + // 渲染已上传媒体文件(图片或视频) function renderUploadedImages() { const uploadArea = document.getElementById('uploadImages'); uploadArea.innerHTML = ''; supplyData.uploadedImages.forEach((mediaUrl, index) => { - const imageElement = document.createElement('div'); - imageElement.className = 'upload-image'; + const mediaElement = document.createElement('div'); + mediaElement.className = 'upload-image'; - let mediaHtml = ''; + let mediaContent; if (mediaUrl.startsWith('data:video/')) { // 视频文件 - mediaHtml = ``; + mediaContent = ` + +
+ `; } else { // 图片文件 - mediaHtml = `商品图片`; + mediaContent = ` + 商品图片 +
+ `; } - imageElement.innerHTML = ` - ${mediaHtml} -
- `; - uploadArea.appendChild(imageElement); + mediaElement.innerHTML = mediaContent; + uploadArea.appendChild(mediaElement); }); } @@ -3921,6 +4665,138 @@ } } + // 加载表单数据 + function loadFormData() { + try { + const savedData = localStorage.getItem('supplyFormDraft'); + if (savedData) { + const formData = JSON.parse(savedData); + + // 恢复联系人信息 + if (formData.contactId) { + const contactElement = document.getElementById('contactId'); + const contactDisplayElement = document.getElementById('contactIdDisplayText'); + if (contactElement && contactDisplayElement) { + contactElement.value = formData.contactId; + contactDisplayElement.textContent = formData.contactIdDisplay || '请选择联系人'; + selectedContactId = formData.contactId; + } + } + + // 恢复商品名称 + if (formData.productName) { + const productNameElement = document.getElementById('productName'); + const productNameDisplayElement = document.getElementById('productNameDisplayText'); + if (productNameElement && productNameDisplayElement) { + productNameElement.value = formData.productName; + productNameDisplayElement.textContent = formData.productNameDisplay || '请选择商品名称'; + selectedProductName = formData.selectedProductName || ''; + } + } + + // 恢复价格 + if (formData.price) { + const priceElement = document.getElementById('price'); + if (priceElement) { + priceElement.value = formData.price; + } + } + + // 恢复数量 + if (formData.quantity) { + const quantityElement = document.getElementById('quantity'); + if (quantityElement) { + quantityElement.value = formData.quantity; + } + } + + // 恢复蛋黄类型 + if (formData.yolk) { + const yolkElement = document.getElementById('yolk'); + const yolkDisplayElement = document.getElementById('yolkDisplayText'); + if (yolkElement && yolkDisplayElement) { + yolkElement.value = formData.yolk; + yolkDisplayElement.textContent = formData.yolkDisplay || '请选择蛋黄类型'; + selectedYolk = formData.selectedYolk || ''; + } + } + + // 恢复规格 + if (formData.specification) { + const specValueElement = document.getElementById('specValue'); + const specDisplayElement = document.getElementById('specDisplayText'); + if (specValueElement && specDisplayElement) { + specValueElement.value = formData.specification; + specDisplayElement.textContent = formData.specificationDisplay || '请选择规格'; + selectedSpec = formData.selectedSpec || ''; + } + } + + // 恢复货源状态 + if (formData.supplyStatus) { + const supplyStatusElement = document.getElementById('supplyStatus'); + if (supplyStatusElement) { + supplyStatusElement.value = formData.supplyStatus; + setSupplyStatus(formData.supplyStatus); + } + } + + // 恢复货源类型 + if (formData.sourceType) { + const sourceTypeElement = document.getElementById('sourceType'); + const sourceTypeDisplayElement = document.getElementById('sourceTypeDisplayText'); + if (sourceTypeElement && sourceTypeDisplayElement) { + sourceTypeElement.value = formData.sourceType; + sourceTypeDisplayElement.textContent = formData.sourceTypeDisplay || '请选择货源类型'; + selectedSourceType = formData.selectedSourceType || ''; + } + } + + // 恢复描述 + if (formData.description) { + const descriptionElement = document.getElementById('description'); + if (descriptionElement) { + descriptionElement.value = formData.description; + } + } + + // 恢复地区 + if (formData.region) { + const regionValueElement = document.getElementById('regionValue'); + const regionDisplayElement = document.getElementById('regionDisplayText'); + if (regionValueElement && regionDisplayElement) { + regionValueElement.value = formData.region; + regionDisplayElement.textContent = formData.regionDisplay || '请选择地区'; + selectedProvince = formData.selectedProvince || ''; + selectedCity = formData.selectedCity || ''; + } + } + + // 恢复种类 + if (formData.category) { + const categoryElement = document.getElementById('category'); + const categoryDisplayElement = document.getElementById('categoryDisplayText'); + if (categoryElement && categoryDisplayElement) { + categoryElement.value = formData.category; + categoryDisplayElement.textContent = formData.categoryDisplay || '请选择种类'; + selectedCategory = formData.selectedCategory || ''; + } + } + + // 恢复图片 + if (Array.isArray(formData.imageUrls)) { + supplyData.uploadedImages = formData.imageUrls; + renderUploadedImages(); + } + + console.log('表单数据已从localStorage加载'); + } + } catch (e) { + console.error('加载表单数据失败:', e); + // 加载失败时不影响用户体验,静默处理错误 + } + } + // 创建货源 // 防止重复提交的标志位 let isSubmitting = false; @@ -3935,14 +4811,31 @@ const userInfo = checkLogin(); if (!userInfo) return; + // 获取规格和件数数据 + const pairs = document.querySelectorAll('.spec-quantity-pair'); + const specifications = []; + const quantities = []; + + pairs.forEach(pair => { + const specValue = pair.querySelector('.spec-value').value.trim(); + const quantityValue = pair.querySelector('.quantity-input').value.trim(); + + if (specValue) { + specifications.push(specValue); + // 件数可以为0,所以只检查是否有值(包括"0") + quantities.push(quantityValue); + } + }); + const formData = { productName: document.getElementById('productName').value, category: document.getElementById('category').value, price: document.getElementById('price').value, - quantity: document.getElementById('quantity').value, + quantity: quantities.join(','), // 将件数以英文逗号分隔的字符串形式提交 grossWeight: document.getElementById('grossWeight').value, yolk: document.getElementById('yolk').value, - specification: document.getElementById('specValue').value, + specification: specifications.join(','), // 将规格以中文逗号分隔的字符串形式提交 + producting: document.getElementById('productingValue').value, supplyStatus: document.getElementById('supplyStatus').value, sourceType: document.getElementById('sourceType').value, description: document.getElementById('description').value, @@ -3965,7 +4858,11 @@ alert('请输入价格'); return; } - if (!formData.quantity) { + if (specifications.length === 0) { + alert('请选择规格'); + return; + } + if (quantities.length === 0) { alert('请输入件数'); return; } @@ -3989,6 +4886,18 @@ alert('请上传至少一张商品图片'); return; } + // 增强联系人信息验证 + if (!formData.contactId || formData.contactId.trim() === '') { + alert('联系人信息缺失,请分配联系人'); + return; + } + + // 检查是否为重复货源 + const isDuplicate = await checkDuplicateSupply(formData); + if (isDuplicate) { + alert('检测到重复的货源数据,不允许创建'); + return; + } try { // 设置为提交中状态,禁用按钮 @@ -4060,65 +4969,44 @@ } const previewModal = document.getElementById('imagePreview'); + const previewImage = document.getElementById('previewImage'); - // 更新媒体显示 + // 更新图片显示 updatePreviewImage(); - // 重置缩放和拖动状态(仅图片需要) - const isVideo = imageUrl.startsWith('data:video/') || imageUrl.endsWith('.mp4') || imageUrl.endsWith('.mov') || imageUrl.endsWith('.avi') || imageUrl.endsWith('.wmv') || imageUrl.endsWith('.flv'); - if (!isVideo) { - resetImageTransform(); - } + // 重置缩放和拖动状态 + resetImageTransform(); previewModal.classList.add('active'); - // 设置图片查看器事件(仅图片需要) - if (!isVideo) { - setupImageViewerEvents(); - } - } - - // 专门的视频预览函数 - function previewMedia(mediaUrl, mediaList = []) { - previewImage(mediaUrl, mediaList); + // 设置图片查看器事件 + setupImageViewerEvents(); } - // 更新预览媒体(图片或视频) + // 更新预览媒体文件(图片或视频) function updatePreviewImage() { - // 获取预览元素 const previewImage = document.getElementById('previewImage'); - const previewVideo = document.createElement('video'); - previewVideo.id = 'previewVideo'; - previewVideo.className = 'preview-video'; - previewVideo.style.maxWidth = '100%'; - previewVideo.style.maxHeight = '100%'; - previewVideo.controls = true; - previewVideo.muted = false; - + const previewVideo = document.getElementById('previewVideo'); const previewCounter = document.getElementById('previewCounter'); - const mediaUrl = currentPreviewImages[currentPreviewIndex]; - - // 判断是图片还是视频 - const isVideo = mediaUrl.startsWith('data:video/') || mediaUrl.endsWith('.mp4') || mediaUrl.endsWith('.mov') || mediaUrl.endsWith('.avi') || mediaUrl.endsWith('.wmv') || mediaUrl.endsWith('.flv'); - // 移除旧的视频元素(如果存在) - const existingVideo = document.getElementById('previewVideo'); - if (existingVideo) { - existingVideo.remove(); - } + const mediaUrl = currentPreviewImages[currentPreviewIndex]; - if (isVideo) { - // 视频预览 - previewImage.style.display = 'none'; + // 根据媒体类型显示相应的元素 + if (mediaUrl.startsWith('data:video/') || + mediaUrl.match(/\.(mp4|mov|avi|wmv|flv|webm|mkv)$/i) || + mediaUrl.includes('video')) { + // 视频文件 previewVideo.src = mediaUrl; - previewImage.parentElement.appendChild(previewVideo); + previewVideo.style.display = 'block'; + previewImage.style.display = 'none'; } else { - // 图片预览 - previewImage.style.display = 'block'; + // 图片文件 previewImage.src = mediaUrl; + previewImage.style.display = 'block'; + previewVideo.style.display = 'none'; } - // 更新计数器 + // 更新图片计数器 if (previewCounter) { previewCounter.textContent = `${currentPreviewIndex + 1}/${currentPreviewImages.length}`; } @@ -4145,12 +5033,23 @@ // 关闭图片预览 function closeImagePreview() { const previewModal = document.getElementById('imagePreview'); + const previewVideo = document.getElementById('previewVideo'); + + // 停止视频播放并重置视频状态 + if (previewVideo) { + previewVideo.pause(); + previewVideo.src = ''; + previewVideo.load(); + } + previewModal.classList.remove('active'); } - // 重置图片变换 + // 重置媒体变换 function resetImageTransform() { const previewImage = document.getElementById('previewImage'); + const previewVideo = document.getElementById('previewVideo'); + scale = 1; lastScale = 1; pointX = 0; @@ -4159,10 +5058,17 @@ updateImageTransform(); } - // 更新图片变换 + // 更新媒体变换 function updateImageTransform() { const previewImage = document.getElementById('previewImage'); - previewImage.style.transform = `translate(${pointX}px, ${pointY}px) scale(${scale})`; + const previewVideo = document.getElementById('previewVideo'); + + // 对当前显示的媒体元素应用变换 + if (previewImage.style.display !== 'none') { + previewImage.style.transform = `translate(${pointX}px, ${pointY}px) scale(${scale})`; + } else if (previewVideo.style.display !== 'none') { + previewVideo.style.transform = `translate(${pointX}px, ${pointY}px) scale(${scale})`; + } } // 设置图片查看器事件 @@ -4435,23 +5341,8 @@ // 准备发布货源 async function preparePublishSupply(id) { - if (confirm('确定要上架该货源吗?上架后将进入审核流程。')) { - try { - const response = await fetch(`/api/supplies/${id}/publish`, { - method: 'POST' - }); - const result = await response.json(); - if (result.success) { - alert('上架成功,已进入审核流程'); - loadSupplies(); - } else { - alert('上架失败: ' + (result.message || '未知错误')); - } - } catch (error) { - console.error('上架失败:', error); - alert('上架失败: 网络错误'); - } - } + // 点击上架按钮时,先进入编辑页面,并设置为上架模式 + showEditSupply(id, true); } // 显示审核失败原因 @@ -4486,7 +5377,7 @@ } // 显示编辑货源 - async function showEditSupply(id) { + async function showEditSupply(id, publishMode = false) { try { // 查找要编辑的货源,考虑类型转换 const supply = supplyData.supplies.find(s => String(s.id) === String(id)); @@ -4497,6 +5388,8 @@ } currentEditSupplyId = id; + // 保存发布模式状态 + window.currentEditPublishMode = publishMode; // 填充表单数据 // 货源类型 @@ -4521,36 +5414,116 @@ document.getElementById('editSpecValue').value = supply.specification || ''; editSelectedSpec = supply.specification || ''; + // 产品包装 + document.getElementById('editProductingDisplayText').textContent = supply.producting || '请选择产品包装'; + document.getElementById('editProductingValue').value = supply.producting || ''; + editSelectedProducting = supply.producting || ''; + // 货源状态(使用按钮组) const supplyStatus = supply.supplyStatus || '预售'; document.getElementById('editSupplyStatus').value = supplyStatus; setEditSupplyStatus(supplyStatus); // 分配联系人 - document.getElementById('editContactIdDisplayText').textContent = supply.contactId || '请选择联系人'; + // 显示联系人名称而不是ID + const contactName = supply.product_contact || supply.contactId || '请选择联系人'; + document.getElementById('editContactIdDisplayText').textContent = contactName; document.getElementById('editContactId').value = supply.contactId || ''; editSelectedContactId = supply.contactId || ''; document.getElementById('editDescription').value = supply.description || ''; document.getElementById('editRegionDisplayText').textContent = supply.region || '请选择地区'; document.getElementById('editRegionValue').value = supply.region || ''; document.getElementById('editPrice').value = supply.price || ''; - document.getElementById('editQuantity').value = supply.quantity || ''; document.getElementById('editGrossWeight').value = supply.grossWeight || ''; + // 规格和件数 - 支持中文逗号分隔和英文逗号分隔字符串 + let specifications = []; + let quantities = []; + + // 解析规格(中文逗号分隔字符串) + try { + if (supply.specification) { + if (typeof supply.specification === 'string') { + specifications = supply.specification.split(',').filter(spec => spec.trim()); + } else if (Array.isArray(supply.specification)) { + specifications = supply.specification; + } else { + specifications = [supply.specification]; + } + } else if (supply.spec) { + specifications = [supply.spec]; + } + } catch (e) { + specifications = [supply.specification || supply.spec || '无']; + } + + // 解析件数(英文逗号分隔字符串) + try { + if (supply.quantity) { + if (typeof supply.quantity === 'string') { + quantities = supply.quantity.split(',').filter(qty => qty.trim()); + } else if (Array.isArray(supply.quantity)) { + quantities = supply.quantity; + } else { + quantities = [supply.quantity]; + } + } + } catch (e) { + quantities = [supply.quantity || '0']; + } + + // 动态生成规格-件数对输入框 + const specQuantityPairs = document.getElementById('editSpecQuantityPairs'); + // 清空现有对 + specQuantityPairs.innerHTML = ''; + + // 如果没有规格-件数对,添加一个空的 + if (specifications.length === 0) { + addEditSpecQuantityPair(); + } else { + // 根据规格数量生成相应的规格-件数对 + for (let i = 0; i < specifications.length; i++) { + const pair = document.createElement('div'); + pair.className = 'spec-quantity-pair'; + pair.innerHTML = ` + + + + `; + specQuantityPairs.appendChild(pair); + } + } + // 显示商品图片 const editUploadImages = document.getElementById('editUploadImages'); editUploadImages.innerHTML = ''; if (supply.imageUrls && Array.isArray(supply.imageUrls)) { - supply.imageUrls.forEach(imageUrl => { + supply.imageUrls.forEach((imageUrl, index) => { const imageElement = document.createElement('div'); imageElement.className = 'upload-image'; imageElement.innerHTML = ` 商品图片 + `; editUploadImages.appendChild(imageElement); }); } + // 保存当前图片列表到全局变量,用于编辑时使用 + 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; + } else { + saveButton.textContent = '保存'; + saveButton.onclick = saveEditSupply; + } + } + // 显示编辑模态框 document.getElementById('editSupplyModal').style.display = 'flex'; } catch (error) { @@ -4563,6 +5536,52 @@ function hideEditSupplyModal() { document.getElementById('editSupplyModal').style.display = 'none'; currentEditSupplyId = null; + // 重置发布模式状态 + window.currentEditPublishMode = false; + } + + // 编辑后上架货源 + async function publishSupplyAfterEdit() { + try { + // 先保存编辑的货源信息 + const saveResult = await saveEditSupply(); + if (saveResult) { + // 保存成功后,上架货源 + await publishSupply(currentEditSupplyId); + // 关闭模态框 + hideEditSupplyModal(); + } + } catch (error) { + console.error('上架失败:', error); + alert('上架失败: ' + (error.message || '未知错误')); + } + } + + // 上架货源 + async function publishSupply(id) { + if (!id) { + alert('货源ID不存在'); + return; + } + + try { + const response = await fetch(`/api/supplies/${id}/publish`, { + method: 'POST' + }); + + const result = await response.json(); + if (result.success) { + alert('上架成功'); + loadSupplies(); + } else { + alert('上架失败: ' + (result.message || '未知错误')); + } + return result.success; + } catch (error) { + console.error('上架失败:', error); + alert('上架失败: ' + error.message); + return false; + } } // 编辑规格选择功能 @@ -4593,18 +5612,46 @@ const option = document.createElement('div'); option.className = 'select-item'; option.textContent = spec; - if (spec === editSelectedSpec) { + + // 检查当前规格是否已被选中 + if (editSelectedSpec.includes(spec)) { option.classList.add('selected'); } + + // 单击选择逻辑 option.onclick = () => { - // 移除所有选项的选中状态 + // 单选逻辑:移除所有选中状态 document.querySelectorAll('#editSpecOptionsList .select-item').forEach(item => { item.classList.remove('selected'); }); - // 添加当前选项的选中状态 + + // 添加当前选中状态 option.classList.add('selected'); - editSelectedSpec = spec; + + // 更新editSelectedSpec数组为单选 + editSelectedSpec = [spec]; + }; + + // 双击确认逻辑 + option.ondblclick = () => { + // 确保当前选项被选中 + if (!option.classList.contains('selected')) { + // 单选逻辑:移除所有选中状态 + document.querySelectorAll('#editSpecOptionsList .select-item').forEach(item => { + item.classList.remove('selected'); + }); + + // 添加当前选中状态 + option.classList.add('selected'); + + // 更新editSelectedSpec数组为单选 + editSelectedSpec = [spec]; + } + + // 自动确认选择 + confirmEditSpecSelection(); }; + specOptionsList.appendChild(option); }); } @@ -4623,13 +5670,164 @@ // 确认编辑规格选择 function confirmEditSpecSelection() { - if (editSelectedSpec) { - document.getElementById('editSpecDisplayText').textContent = editSelectedSpec; - document.getElementById('editSpecValue').value = editSelectedSpec; + if (currentEditSpecInput) { + // 如果是为规格和件数对选择规格 + if (editSelectedSpec.length > 0) { + currentEditSpecInput.value = editSelectedSpec.join(', '); + } else { + currentEditSpecInput.value = ''; + } + } else { + // 否则,为旧的规格选择逻辑 + if (editSelectedSpec.length > 0) { + document.getElementById('editSpecDisplayText').textContent = editSelectedSpec.join(', '); + document.getElementById('editSpecValue').value = JSON.stringify(editSelectedSpec); + // 根据选中的规格数量动态调整件数输入框数量 + adjustEditQuantityInputs(); + } else { + document.getElementById('editSpecDisplayText').textContent = '请选择规格'; + document.getElementById('editSpecValue').value = '[]'; + } } hideEditSpecSelectModal(); } + // 添加编辑件数输入项 + function addEditQuantityItem() { + const container = document.getElementById('editQuantityContainer'); + const quantityItem = document.createElement('div'); + quantityItem.className = 'quantity-item'; + quantityItem.innerHTML = ` + + + `; + container.insertBefore(quantityItem, container.lastElementChild); + } + + // 删除编辑件数输入项 + function removeEditQuantityItem(btn) { + const container = document.getElementById('editQuantityContainer'); + const quantityItems = container.querySelectorAll('.quantity-item'); + + // 至少保留一个件数输入项 + if (quantityItems.length > 1) { + const quantityItem = btn.parentElement; + quantityItem.remove(); + } + } + + // 根据选中的规格数量调整编辑件数输入框数量 + function adjustEditQuantityInputs() { + const container = document.getElementById('editQuantityContainer'); + const quantityItems = container.querySelectorAll('.quantity-item'); + const specCount = editSelectedSpec.length; + + // 如果规格数量大于件数输入框数量,添加缺少的输入框 + while (quantityItems.length < specCount) { + addEditQuantityItem(); + } + } + + // 添加编辑规格和件数对 + function addEditSpecQuantityPair() { + const container = document.getElementById('editSpecQuantityPairs'); + const pair = document.createElement('div'); + pair.className = 'spec-quantity-pair'; + pair.innerHTML = ` + + + + `; + container.appendChild(pair); + } + + // 删除编辑规格和件数对 + function removeEditSpecQuantityPair(btn) { + const pair = btn.parentElement; + const specInput = pair.querySelector('.spec-value'); + const quantityInput = pair.querySelector('.quantity-input'); + + // 清除当前对的输入值 + if (specInput) specInput.value = ''; + if (quantityInput) quantityInput.value = ''; + } + + // 为编辑规格和件数对显示规格选择弹窗 + function showEditSpecSelectModalForPair(input) { + // 保存当前点击的输入框 + currentEditSpecInput = input; + showEditSpecSelectModal(); + } + + // 保存当前点击的编辑规格输入框 + let currentEditSpecInput = null; + + // 编辑产品包装选择功能 + // 显示编辑产品包装选择弹窗 + function showEditProductingSelectModal() { + const editProductingSelectModal = document.getElementById('editProductingSelectModal'); + editProductingSelectModal.classList.add('active'); + // 重置搜索输入 + document.getElementById('editProductingSearchInput').value = ''; + editFilteredProductingOptions = [...editAllProductingOptions]; + generateEditProductingOptions(); + } + + // 隐藏编辑产品包装选择弹窗 + function hideEditProductingSelectModal() { + const editProductingSelectModal = document.getElementById('editProductingSelectModal'); + editProductingSelectModal.classList.remove('active'); + } + + // 生成编辑产品包装选项 + function generateEditProductingOptions() { + const editProductingOptionsList = document.getElementById('editProductingOptionsList'); + editProductingOptionsList.innerHTML = ''; + + editFilteredProductingOptions.forEach(producting => { + const option = document.createElement('div'); + option.className = 'select-item'; + option.textContent = producting; + option.onclick = () => { + // 移除所有选项的选中状态 + document.querySelectorAll('#editProductingOptionsList .select-item').forEach(item => { + item.classList.remove('selected'); + }); + // 添加当前选项的选中状态 + option.classList.add('selected'); + editSelectedProducting = producting; + }; + option.ondblclick = () => { + // 双击直接确认选择 + document.getElementById('editProductingDisplayText').textContent = producting; + document.getElementById('editProductingValue').value = producting; + hideEditProductingSelectModal(); + }; + editProductingOptionsList.appendChild(option); + }); + } + + // 过滤编辑产品包装选项 + function filterEditProductingOptions() { + const searchInput = document.getElementById('editProductingSearchInput'); + const searchKeyword = searchInput.value.toLowerCase(); + + editFilteredProductingOptions = editAllProductingOptions.filter(producting => { + return producting.toLowerCase().includes(searchKeyword); + }); + + generateEditProductingOptions(); + } + + // 确认编辑产品包装选择 + function confirmEditProductingSelection() { + if (editSelectedProducting) { + document.getElementById('editProductingDisplayText').textContent = editSelectedProducting; + document.getElementById('editProductingValue').value = editSelectedProducting; + } + hideEditProductingSelectModal(); + } + // 编辑地区选择功能 // 显示编辑地区选择弹窗 function showEditRegionSelectModal() { @@ -5190,37 +6388,83 @@ async function saveEditSupply() { if (!currentEditSupplyId) { alert('货源ID不存在'); - return; + return false; } try { + // 获取规格和件数数据 + const pairs = document.querySelectorAll('#editSpecQuantityPairs .spec-quantity-pair'); + const specifications = []; + const quantities = []; + + pairs.forEach(pair => { + const specValue = pair.querySelector('.spec-value').value.trim(); + const quantityValue = pair.querySelector('.quantity-input').value.trim(); + + if (specValue && quantityValue) { + specifications.push(specValue); + quantities.push(quantityValue); + } + }); + const formData = { productName: document.getElementById('editProductName').value, sourceType: document.getElementById('editSourceType').value, category: document.getElementById('editCategory').value, price: document.getElementById('editPrice').value, - quantity: document.getElementById('editQuantity').value, + quantity: quantities.join(','), // 将件数以英文逗号分隔的字符串形式提交 grossWeight: document.getElementById('editGrossWeight').value, yolk: document.getElementById('editYolk').value, - specification: document.getElementById('editSpecValue').value, + specification: specifications.join(','), // 将规格以中文逗号分隔的字符串形式提交 + producting: document.getElementById('editProductingValue').value, supplyStatus: document.getElementById('editSupplyStatus').value, description: document.getElementById('editDescription').value, region: document.getElementById('editRegionValue').value, - contactId: document.getElementById('editContactId').value + contactId: document.getElementById('editContactId').value, + imageUrls: editCurrentImages // 添加编辑后的图片列表 }; // 验证表单 if (!formData.productName) { alert('请选择商品名称'); - return; + return false; + } + if (!formData.category) { + alert('请选择种类'); + return false; } if (!formData.price) { alert('请输入价格'); - return; + return false; } - if (!formData.quantity) { + if (specifications.length === 0) { + alert('请选择规格'); + return false; + } + if (quantities.length === 0) { alert('请输入件数'); - return; + return false; + } + if (!formData.supplyStatus) { + alert('请选择货源状态(预售/现货)'); + return false; + } + if (!formData.sourceType) { + alert('请选择货源类型'); + return false; + } + if (!formData.region) { + alert('请选择地区'); + return false; + } + if (!formData.contactId) { + alert('请选择联系人'); + return false; + } + // 增强联系人信息验证 + if (!formData.contactId || formData.contactId.trim() === '') { + alert('联系人信息缺失,请分配联系人'); + return false; } const response = await fetch(`/api/supplies/${currentEditSupplyId}/edit`, { @@ -5233,15 +6477,21 @@ const result = await response.json(); if (result.success) { - alert('编辑成功'); - hideEditSupplyModal(); - loadSupplies(); + // 如果是直接编辑,显示成功消息;如果是编辑后上架,不显示,由上架函数处理 + if (!window.currentEditPublishMode) { + alert('编辑成功'); + hideEditSupplyModal(); + loadSupplies(); + } + return true; } else { alert('编辑失败: ' + (result.message || '未知错误')); + return false; } } catch (error) { console.error('编辑失败:', error); alert('编辑失败: 网络错误'); + return false; } } @@ -5249,16 +6499,29 @@ function hideEditSupplyModal() { document.getElementById('editSupplyModal').style.display = 'none'; currentEditSupplyId = null; + // 重置发布模式状态 + window.currentEditPublishMode = false; } // 处理点击模态框外部关闭 window.onclick = function(event) { - const modals = document.querySelectorAll('.modal'); - modals.forEach(modal => { - if (event.target === modal) { - modal.style.display = 'none'; - } - }); + // 确保只处理click事件,不处理拖拽选择文本导致的mouseup事件 + if (event.type === 'click') { + const modals = document.querySelectorAll('.modal'); + modals.forEach(modal => { + if (event.target === modal) { + // 只在真正点击模态框背景时关闭,不在选择文本拖拽到外部时关闭 + // 检查事件是否是通过点击触发的,而不是通过拖拽 + if (!event.isTrusted) return; + + // 检查是否有正在进行的选择操作 + const selection = window.getSelection(); + if (selection && selection.toString()) return; + + modal.style.display = 'none'; + } + }); + } }