// pages/goods-update/goods-update.js const API = require('../../utils/api.js') // 获取当前用户的本地手机号 function getLocalPhoneNumber() { try { // 尝试从多个可能的存储位置获取手机号 const users = wx.getStorageSync('users') || {}; const userId = wx.getStorageSync('userId'); if (userId && users[userId] && users[userId].phoneNumber) { return users[userId].phoneNumber; } const userInfo = wx.getStorageSync('userInfo'); if (userInfo && userInfo.phoneNumber) { return userInfo.phoneNumber; } return wx.getStorageSync('phoneNumber') || ''; } catch (e) { console.error('获取本地手机号失败:', e); return ''; } } // 检查用户是否为管理员 function checkIsAdmin(phoneNumber) { return new Promise((resolve, reject) => { if (!phoneNumber) { resolve(false); return; } API.checkPersonnelByPhone(phoneNumber) .then(res => { console.log('checkPersonnelByPhone响应:', res); if (res.exists && res.data) { // 处理数据库返回多条记录的情况 const dataArray = Array.isArray(res.data) ? res.data : [res.data]; // 检查是否有记录的projectName为管理员标识 const isAdmin = dataArray.some(item => item.projectName === '管理员'); resolve(isAdmin); } else { resolve(false); } }) .catch(err => { console.error('检查管理员权限失败:', err); resolve(false); }); }); } // 根据sourceType获取对应的颜色 function getSourceTypeColor(sourceType) { const colorMap = { '三方认证': '#4d9dff', '三方未认证': '#ff4d4f', '平台货源': '#2ad21f' }; return colorMap[sourceType] || '#4d9dff'; } // 媒体类型判断函数 function isVideoUrl(url) { if (!url || typeof url !== 'string') { return false; } // 转换为小写,确保大小写不敏感 const lowerUrl = url.toLowerCase(); // 支持的视频格式 const videoExtensions = ['.mp4', '.mov', '.avi', '.wmv', '.flv', '.webm', '.m4v', '.3gp']; // 检查URL是否以视频扩展名结尾 for (const ext of videoExtensions) { if (lowerUrl.endsWith(ext)) { return true; } } return false; } // 预处理媒体URL,返回包含type字段的媒体对象数组 function processMediaUrls(urls) { if (!urls || !Array.isArray(urls)) { return []; } return urls.map(url => { return { url: url, type: isVideoUrl(url) ? 'video' : 'image' }; }); } // 格式化毛重显示的辅助函数 function formatGrossWeight(grossWeight, weight) { if (grossWeight !== null && grossWeight !== undefined && grossWeight !== '') { return grossWeight; } if (weight !== null && weight !== undefined && weight !== '') { return weight; } return ""; } // 提取地区中的省份信息 function extractProvince(region) { if (!region || typeof region !== 'string') { return region; } // 查找各种省份格式的位置 const provinceEndIndex = region.indexOf('省'); const autonomousRegionEndIndex = region.indexOf('自治区'); const municipalityEndIndex = region.indexOf('市'); // 用于直辖市,如北京市、上海市 const specialRegionEndIndex = region.indexOf('特别行政区'); // 用于香港、澳门 if (provinceEndIndex !== -1) { // 包含"省"字,提取到"省"字结束 return region.substring(0, provinceEndIndex + 1); } else if (autonomousRegionEndIndex !== -1) { // 包含"自治区",提取到"自治区"结束 return region.substring(0, autonomousRegionEndIndex + 3); } else if (specialRegionEndIndex !== -1) { // 包含"特别行政区",提取到"特别行政区"结束 return region.substring(0, specialRegionEndIndex + 5); } else if (municipalityEndIndex === 2) { // 直辖市(如北京市、上海市),市字在第2个字符位置 return region.substring(0, municipalityEndIndex + 1); } // 如果没有找到匹配的格式,返回原字符串 return region; } // 格式化日期时间函数 function formatDateTime(dateString) { if (!dateString) return ''; // 尝试解析日期字符串 const date = new Date(dateString); // 检查是否是有效的日期对象 if (isNaN(date.getTime())) { // 如果解析失败,返回原始字符串 return dateString; } // 如果是 ISO 格式的字符串(包含 T 字符),则转换为本地时间格式 if (typeof dateString === 'string' && dateString.includes('T')) { const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); return `${year}-${month}-${day} ${hours}:${minutes}`; } // 对于其他格式的字符串,直接返回,不进行转换 return dateString; } // 获取用户手机号 function getUserPhoneNumber() { return new Promise((resolve, reject) => { try { // 尝试从多个可能的存储位置获取手机号 const users = wx.getStorageSync('users') || {}; const userId = wx.getStorageSync('userId'); if (userId && users[userId] && users[userId].phoneNumber) { resolve(users[userId].phoneNumber); return; } const userInfo = wx.getStorageSync('userInfo'); if (userInfo && userInfo.phoneNumber) { resolve(userInfo.phoneNumber); return; } const phoneNumber = wx.getStorageSync('phoneNumber'); if (phoneNumber) { resolve(phoneNumber); return; } reject(new Error('未找到手机号')); } catch (e) { console.error('获取手机号失败:', e); reject(e); } }); } // 处理净重件数对应数据,支持逗号分隔的价格与规格一一对应 function processWeightAndQuantityData(weightSpecString, quantityString, specString, price = '', costprice = '') { console.log('===== 处理净重、件数和规格数据 ====='); console.log('输入参数:'); console.log('- weightSpecString:', weightSpecString, '(类型:', typeof weightSpecString, ')'); console.log('- quantityString:', quantityString, '(类型:', typeof quantityString, ')'); console.log('- specString:', specString, '(类型:', typeof specString, ')'); console.log('- price:', price, '(类型:', typeof price, ')'); console.log('- costprice:', costprice, '(类型:', typeof costprice, ')'); // 如果没有数据,返回空数组 if (!weightSpecString && !quantityString && !specString) { console.log('没有数据,返回空数组'); return []; } // 处理净重/规格字符串(它可能包含净重信息) let weightSpecArray = []; if (weightSpecString && typeof weightSpecString === 'string') { // 支持多种逗号分隔符:英文逗号、中文逗号、全角逗号 weightSpecArray = weightSpecString.split(/[,,、]/).map(item => item.trim()).filter(item => item); console.log('从字符串分割得到净重规格数组:', weightSpecArray); } else if (weightSpecString) { weightSpecArray = [String(weightSpecString)]; console.log('将净重规格转换为数组:', weightSpecArray); } // 处理件数字符串 let quantityArray = []; if (quantityString && typeof quantityString === 'string') { // 支持多种逗号分隔符:英文逗号、中文逗号、全角逗号 quantityArray = quantityString.split(/[,,、]/).map(item => item.trim()).filter(item => item); console.log('从字符串分割得到数量数组:', quantityArray); } else if (quantityString) { quantityArray = [String(quantityString)]; console.log('将数量转换为数组:', quantityArray); } // 处理销售价格字符串,支持逗号分隔的多个价格 let priceArray = []; if (price && typeof price === 'string') { // 支持多种逗号分隔符:英文逗号、中文逗号、全角逗号 priceArray = price.split(/[,,、]/).map(item => item.trim()).filter(item => item); console.log('从字符串分割得到销售价格数组:', priceArray); } else if (price) { priceArray = [String(price)]; console.log('将销售价格转换为数组:', priceArray); } // 处理采购价格字符串,支持逗号分隔的多个价格 let costpriceArray = []; if (costprice && typeof costprice === 'string') { // 支持多种逗号分隔符:英文逗号、中文逗号、全角逗号 costpriceArray = costprice.split(/[,,、]/).map(item => item.trim()).filter(item => item); console.log('从字符串分割得到采购价格数组:', costpriceArray); } else if (costprice) { costpriceArray = [String(costprice)]; console.log('将采购价格转换为数组:', costpriceArray); } // 获取最大长度,确保一一对应 const maxLength = Math.max(weightSpecArray.length, quantityArray.length, priceArray.length, costpriceArray.length); console.log('最大长度:', maxLength); const result = []; for (let i = 0; i < maxLength; i++) { const weightSpec = weightSpecArray[i] || ''; const quantity = quantityArray[i] || ''; const itemPrice = priceArray[i] || ''; const itemCostprice = costpriceArray[i] || ''; console.log(`处理第${i}组数据: weightSpec=${weightSpec}, quantity=${quantity}, price=${itemPrice}, costprice=${itemCostprice}`); // 处理净重规格显示格式 - 根据内容类型添加相应前缀 let weightSpecDisplay = ''; if (weightSpec) { if (weightSpec.includes('净重') || weightSpec.includes('毛重')) { // 如果已包含"净重"或"毛重"前缀,保持不变 weightSpecDisplay = weightSpec; } else { // 否则,根据内容自动判断添加前缀 if (weightSpec.includes('-')) { // 如果包含"-", 认为是净重范围,添加"净重"前缀 weightSpecDisplay = `净重${weightSpec}`; } else { // 否则,认为是毛重,添加"毛重"前缀 weightSpecDisplay = `毛重${weightSpec}`; } } } // 处理件数显示格式 let quantityDisplay = quantity; if (quantity && !quantity.includes('件')) { // 如果不包含"件"后缀,添加"件"后缀 quantityDisplay = `${quantity}件`; } if (weightSpecDisplay || quantityDisplay || itemPrice || itemCostprice) { result.push({ weightSpec: weightSpecDisplay, quantity: quantityDisplay, price: itemPrice, costprice: itemCostprice }); console.log(`添加显示对象: weightSpec=${weightSpecDisplay}, quantity=${quantityDisplay}, price=${itemPrice}, costprice=${itemCostprice}`); } } console.log('净重件数对应数据处理结果:', result); return result; } Page({ // 分享给朋友/群聊 onShareAppMessage() { const goodsDetail = this.data.goodsDetail || {}; const title = goodsDetail.name ? `优质鸡蛋 - ${goodsDetail.name}` : '优质鸡蛋货源'; return { title: title, path: `/pages/goods-update/goods-update?productId=${goodsDetail.productId || goodsDetail.id}`, imageUrl: goodsDetail.imageUrls && goodsDetail.imageUrls.length > 0 ? goodsDetail.imageUrls[0] : '/images/你有好蛋.png' } }, data: { goodsDetail: {}, // 当前商品详情 showImagePreview: false, // 控制图片预览弹窗显示 previewImageUrls: [], // 预览的图片URL列表 previewImageIndex: 0, // 当前预览图片的索引 showEditModal: false, // 控制编辑弹窗显示 showSpecSelectModal: false, // 控制规格选择弹窗显示 modalSpecSearchKeyword: '', // 规格弹窗中的搜索关键词 filteredModalSpecOptions: [], // 弹窗中过滤后的规格选项 selectedModalSpecIndex: -1, // 弹窗中选中的规格索引 currentSpecMode: 'edit', // 当前规格选择模式:create 或 edit showNameSelectModal: false, // 控制商品名称选择弹窗显示 showYolkSelectModal: false, // 控制蛋黄选择弹窗显示 selectedNameIndex: -1, // 商品名称弹窗中选中的索引 selectedYolkIndex: -1,//蛋黄弹窗中选中的索引, // 销售员列表 salesPersonnelOptions: [], filteredSalesPersonnelOptions: [], selectedSalesPersonIndex: -1, showSalesPersonSelectModal: false, modalSalesPersonSearchKeyword: '', // 商品名称选项列表 productNameOptions: ['罗曼粉', '伊莎粉', '罗曼灰', '海蓝灰', '海蓝褐', '绿壳', '粉一', '粉二', '粉八', '京粉1号', '京红', '京粉6号', '京粉3号', '农大系列', '黑鸡土蛋', '双黄蛋', '大午金凤', '黑凤'], // 蛋黄选项 yolkOptions: ['红心', '黄心', '双色'], // 规格选项 specOptions: ['格子装', '散托', '不限规格', '净重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以下'], // 编辑货源数据 editSupply: { id: '', imageUrls: [], name: '', price: '', minOrder: '', yolk: '', spec: '', region: '', grossWeight: '' }, // 图片缩放相关状态 scale: 1, // 当前缩放比例 lastScale: 1, // 上一次缩放比例 startDistance: 0, // 双指起始距离 doubleTapTimer: null, // 双击计时器 lastTapTime: 0, // 上一次单击时间 isScaling: false, // 是否正在缩放中 offsetX: 0, // X轴偏移量 offsetY: 0, // Y轴偏移量 initialTouch: null, // 初始触摸点 }, onLoad: function (options) { console.log('商品编辑页面加载,参数:', options); // 解析传入的商品数据 let goodsData = null; if (options.goodsData) { try { goodsData = JSON.parse(decodeURIComponent(options.goodsData)); console.log('解析后的商品数据:', goodsData); // 优先使用传入的商品数据 this.setData({ goodsDetail: goodsData }); } catch (error) { console.error('解析商品数据失败:', error); } } // 从商品数据中提取商品ID let productId; if (goodsData && goodsData.productId) { // 优先使用字符串类型的productId productId = goodsData.productId; } else if (options.productId) { productId = options.productId; } else if (goodsData && goodsData.id) { // 如果没有productId,再尝试使用id productId = goodsData.id; } else { console.error('未找到商品ID'); wx.showToast({ title: '商品信息有误', icon: 'none', duration: 2000 }); // 2秒后返回上一页 setTimeout(() => { wx.navigateBack(); }, 2000); return; } console.log('最终使用的商品ID:', productId); // 加载销售员列表 this.loadSalesPersonnel(); // 加载商品详情(即使已有goodsData,也调用API获取最新数据) this.loadGoodsDetail(productId, goodsData); }, // 加载销售员列表 loadSalesPersonnel: function () { console.log('加载销售员列表'); API.getSalesPersonnel() .then(res => { console.log('获取销售员列表成功:', res); const salesOptions = res.map(item => ({ id: item.id, name: item.alias || item.name || '未知', phoneNumber: item.phoneNumber || '' })); this.setData({ salesPersonnelOptions: salesOptions, filteredSalesPersonnelOptions: salesOptions }); console.log('销售员列表数据:', this.data.salesPersonnelOptions); }) .catch(err => { console.error('获取销售员列表失败:', err); }); }, loadGoodsDetail: function (productId, preloadedData = null) { // 首先显示预加载的数据,确保UI快速响应 if (preloadedData) { console.log('使用预加载数据显示UI'); } console.log('调用API获取商品详情,productId:', productId); API.getProductDetail({ productId: productId }) .then(res => { console.log('获取商品详情成功:', res); if (res && res.code === 200 && res.data) { const product = res.data; console.log('=== API返回的product原始数据 ==='); console.log('product对象的所有key:', Object.keys(product)); console.log('product中是否包含seller相关字段:'); console.log(' - sellerId:', product.sellerId); console.log(' - seller_id:', product.seller_id); console.log(' - seller:', product.seller); console.log(' - userId:', product.userId); console.log(' - user_id:', product.user_id); console.log(' - creator:', product.creator); console.log(' - 创建人ID:', product.creatorId); console.log(' - 创建人ID:', product.creator_id); // 只过滤hidden状态的商品 if (product.status === 'hidden') { wx.showToast({ title: '商品已下架', icon: 'none', duration: 2000 }); // 2秒后返回上一页 setTimeout(() => { wx.navigateBack(); }, 2000); return; } // 确保商品ID的一致性 const productIdStr = String(product.productId || product.id); // 关键修改:直接使用API返回的reservedCount值 const finalReservationCount = product.reservedCount || 0; // 确保imageUrls是数组 let imageUrls = product.imageUrls || []; if (!Array.isArray(imageUrls)) { console.error('imageUrls不是数组,转换为数组'); imageUrls = [imageUrls]; } // 处理grossWeight为null或无效的情况,返回空字符串以支持文字输入 const grossWeightValue = product.grossWeight !== null && product.grossWeight !== undefined ? product.grossWeight : ''; // 转换supplyStatus字段值 let supplyStatusValue = product.supplyStatus || ''; // 将"平台货源"、"三方认证"、"三方未认证"修改为"现货"、"预售" if (supplyStatusValue === '平台货源' || supplyStatusValue === '三方认证') { supplyStatusValue = '现货'; } else if (supplyStatusValue === '三方未认证') { supplyStatusValue = '预售'; } // 预处理媒体URL,添加类型信息 const mediaItems = processMediaUrls(imageUrls || []); console.log('预处理后的媒体数据:', mediaItems); // 处理净重、件数据和规格数据,获取一一对应的显示数组 // 注意:数据库中的规格字段包含净重信息,我们需要与件数数据正确匹配 // 首先处理净重和规格数据(它们可能都在spec字段中) let weightSpecString = ''; let quantityString = ''; // 检查规格字段是否包含净重或毛重信息 console.log('=== 数据库字段调试信息 ==='); console.log('product.spec:', product.spec); console.log('product.specification:', product.specification); console.log('product.quantity:', product.quantity); console.log('product.minOrder:', product.minOrder); if (product.spec && typeof product.spec === 'string' && (product.spec.includes('净重') || product.spec.includes('毛重'))) { // 如果规格字段包含净重或毛重信息,则使用该字段作为重量规格数据 weightSpecString = product.spec; console.log('使用规格字段作为重量规格数据:', weightSpecString); } else if (product.specification && typeof product.specification === 'string' && (product.specification.includes('净重') || product.specification.includes('毛重'))) { // 检查specification字段 weightSpecString = product.specification; console.log('使用specification字段作为重量规格数据:', weightSpecString); } else if (grossWeightValue) { // 如果有单独的重量字段,则使用该字段 weightSpecString = grossWeightValue; console.log('使用重量字段作为重量规格数据:', weightSpecString); } else { console.log('未找到重量规格数据'); } // 处理件数数据 console.log('=== 件数数据调试信息 ==='); console.log('原始件数数据:', product.quantity); console.log('原始minOrder数据:', product.minOrder); // 修复:与格式化数据保持一致,优先使用minOrder if (product.minOrder) { quantityString = String(product.minOrder); console.log('使用minOrder作为件数数据:', quantityString); } else if (product.quantity && typeof product.quantity === 'string') { quantityString = product.quantity; console.log('件数数据为字符串:', quantityString); } else if (product.quantity) { // 如果件数不是字符串,转换为字符串 quantityString = String(product.quantity); console.log('件数数据转换为字符串:', quantityString); } else { console.log('未找到件数数据'); } console.log('准备传递给processWeightAndQuantityData的数据:', { weightSpecString: weightSpecString, quantityString: quantityString }); const weightQuantityData = processWeightAndQuantityData(weightSpecString, quantityString, '', product.price, product.costprice); console.log('=== 处理结果调试信息 ==='); console.log('weightSpecString:', weightSpecString); console.log('quantityString:', quantityString); console.log('weightQuantityData处理结果:', weightQuantityData); // 处理规格信息,生成格式化的specInfo let specInfo = []; const spec = product.spec || product.specification || ''; const minOrder = product.minOrder || product.quantity; // 生成格式化的规格信息 if (spec && minOrder) { // 如果有规格和件数,生成格式:"毛重48-49——200件" if (grossWeightValue) { specInfo.push(`毛重${grossWeightValue}——${minOrder}件`); } else { specInfo.push(`${spec}——${minOrder}件`); } } else if (spec) { specInfo.push(spec); } else if (grossWeightValue) { specInfo.push(`毛重${grossWeightValue}`); } // 确定creatorName - 优先使用预加载数据,然后使用与goods页面相同的逻辑 console.log('产品seller信息:', JSON.stringify(product.seller)); console.log('预加载数据:', preloadedData); // 优先使用预加载数据中的creatorName,如果没有则使用API返回的数据 let creatorName; if (preloadedData && preloadedData.creatorName) { creatorName = preloadedData.creatorName; console.log('使用预加载数据中的creatorName:', creatorName); } else { creatorName = product.seller?.nickName || product.seller?.sellerNickName || product.seller?.name || product.name || '未知'; console.log('使用API返回数据生成creatorName:', creatorName); } // 格式化创建时间 const createdAt = preloadedData?.created_at || preloadedData?.createdAt || product.created_at || product.createdAt; const formattedCreatedAt = formatDateTime(createdAt); console.log('formattedCreatedAt:', formattedCreatedAt); // 格式化修改时间 const updatedAt = preloadedData?.updated_at || preloadedData?.updatedAt || product.updated_at || product.updatedAt; const formattedUpdatedAt = formatDateTime(updatedAt); console.log('formattedUpdatedAt:', formattedUpdatedAt); // 详细追踪地区信息 console.log('=== 地区信息详细追踪 ==='); console.log('预加载数据中的region:', preloadedData?.region); console.log('原始product.region:', product.region, '(类型:', typeof product.region, ')'); console.log('product是否有region属性:', 'region' in product); // 确定最终的地区值 - 优先使用预加载数据 const finalRegion = preloadedData?.region || product.region || product.area || product.location || '暂无'; console.log('finalRegion:', finalRegion); // 详细调试商品状态 console.log('=== 商品状态详细调试 ==='); console.log('API返回的完整product对象:', JSON.stringify(product, null, 2)); console.log('API返回的product.status:', product.status); console.log('商品label字段:', product.label); console.log('商品label类型:', typeof product.label); console.log('商品是否包含status字段:', 'status' in product); console.log('商品是否包含label字段:', 'label' in product); // 检查预加载数据中的状态信息 console.log('=== 预加载数据状态检查 ==='); console.log('预加载数据中的status:', preloadedData?.status); console.log('预加载数据中的label:', preloadedData?.label); // 定义已下架状态列表 const soldOutStatuses = ['sold_out', 'unpublished', 'hidden']; // 检查商品是否已下架 // 1. 首先检查预加载数据中的状态 const preloadedIsSoldOut = (preloadedData?.label === 1 || preloadedData?.label === '1' || preloadedData?.label === true) || (preloadedData?.status && soldOutStatuses.includes(preloadedData?.status.toLowerCase())); // 2. 然后检查API返回的数据中的状态 const apiIsSoldOut = (product.label === 1 || product.label === '1' || product.label === true) || (product.status && soldOutStatuses.includes(product.status.toLowerCase())); // 3. 综合判断,只要有一个为true就表示已下架 const isSoldOut = preloadedIsSoldOut || apiIsSoldOut; // 根据是否已下架设置最终状态 let finalStatus = isSoldOut ? 'sold_out' : 'published'; // 详细记录状态判断信息 console.log('=== 状态判断结果 ==='); console.log('预加载数据判断是否已下架:', preloadedIsSoldOut); console.log('API数据判断是否已下架:', apiIsSoldOut); console.log('最终是否已下架:', isSoldOut); console.log('最终状态:', finalStatus); // 提取第一个规格的价格信息作为默认价格 let defaultPrice = product.price; let defaultCostprice = product.costprice; // 如果有规格数据,提取第一个规格的价格信息 if (weightQuantityData && weightQuantityData.length > 0) { // 处理销售价格 if (product.price && typeof product.price === 'string') { const priceArray = product.price.split(/[,,、]/).map(item => item.trim()).filter(item => item); if (priceArray.length > 0) { defaultPrice = priceArray[0]; } } // 处理采购价格 if (product.costprice && typeof product.costprice === 'string') { const costpriceArray = product.costprice.split(/[,,、]/).map(item => item.trim()).filter(item => item); if (costpriceArray.length > 0) { defaultCostprice = costpriceArray[0]; } } } // 处理产品日志信息 let productLog = []; if (product.product_log) { if (typeof product.product_log === 'string') { // 尝试解析JSON字符串 try { const parsedLog = JSON.parse(product.product_log); if (Array.isArray(parsedLog)) { productLog = parsedLog; } else { // 如果解析后不是数组,可能是单个日志字符串 productLog = [parsedLog]; } } catch (e) { // 如果解析失败,可能是普通字符串,直接作为单个日志 productLog = [product.product_log]; } } else if (Array.isArray(product.product_log)) { // 已经是数组格式 productLog = product.product_log; } else { // 其他情况,转换为数组 productLog = [product.product_log]; } } // 转换商品数据格式 const formattedGoods = { id: productIdStr, productId: productIdStr, // 直接使用数据库字段名 name: product.productName || product.name || '商品名称', price: defaultPrice, costprice: defaultCostprice, minOrder: minOrder, yolk: product.yolk, spec: spec, specInfo: specInfo, // 添加格式化的规格信息 // 保留原始字段引用,确保数据完整性 imageUrls: imageUrls || [], // 添加预处理后的媒体数据,包含类型信息 mediaItems: mediaItems, displayGrossWeight: formatGrossWeight(grossWeightValue, product.weight), created_at: product.created_at || product.createdAt, updated_at: product.updated_at || product.updatedAt, status: finalStatus, // 使用处理后的状态 label: product.label, // 保留原始label字段 supplyStatus: supplyStatusValue, sourceType: product.sourceType || '', sourceTypeColor: getSourceTypeColor(product.sourceType), // 添加净重和件数的一一对应数据 weightQuantityData: weightQuantityData, // 格式化创建时间 formattedCreatedAt: formattedCreatedAt, // 格式化修改时间 formattedUpdatedAt: formattedUpdatedAt, // 创建者信息 creatorName: creatorName, // 地区信息(先设置,后面会被覆盖) region: finalRegion, // 产品日志信息 - 确保是数组格式 product_log: productLog, // 复制原始产品对象中的所有字段,确保不丢失任何数据 ...product, // 重新设置关键字段,防止被product数据覆盖 status: finalStatus, // 确保状态字段使用我们处理后的值 label: product.label, creatorName: creatorName, formattedCreatedAt: formattedCreatedAt, formattedUpdatedAt: formattedUpdatedAt, created_at: createdAt, updated_at: updatedAt, // 添加产品包装字段(放在product之后,确保不被覆盖) producting: product.producting || '', // 添加货源描述字段 description: product.description || product.remark || '', // 直接使用数据库字段名,确保与表结构完全一致,放在后面覆盖前面的值 product_contact: product.product_contact || '联系人信息暂不可用', contact_phone: product.contact_phone || '暂无联系电话', // 确保地区信息正确显示,放在最后覆盖所有来源的值 region: finalRegion, // 确保reservedCount字段使用我们计算得到的值,放在最后以覆盖其他来源的值 reservedCount: finalReservationCount, // 添加新鲜程度字段 freshness: product.freshness || '', // 确保价格字段使用我们提取的第一个规格价格 price: defaultPrice, costprice: defaultCostprice, // 确保产品日志字段使用我们处理后的值 - 确保是数组格式 product_log: productLog }; console.log('最终formattedGoods.status:', formattedGoods.status); console.log('最终formattedGoods.label:', formattedGoods.label); console.log('最终formattedGoods.region:', formattedGoods.region); // 调试输出完整的formattedGoods对象 // 调试日志:检查product_log字段 console.log('=== 产品日志调试 ==='); console.log('原始product.product_log:', product.product_log); console.log('处理后的productLog:', productLog); console.log('productLog类型:', typeof productLog); console.log('productLog是否为数组:', Array.isArray(productLog)); console.log('productLog长度:', productLog.length); console.log('最终格式化的商品数据:', JSON.stringify(formattedGoods, null, 2)); // 强制将测试商品设置为已下架状态,用于调试 // formattedGoods.status = 'sold_out'; // formattedGoods.label = 1; console.log('=== 最终商品状态 ==='); console.log('goodsDetail.status:', formattedGoods.status); console.log('goodsDetail.label:', formattedGoods.label); console.log('按钮是否应该被禁用:', formattedGoods.status === 'sold_out'); console.log('是否应该显示disabled-button类:', formattedGoods.status === 'sold_out'); console.log('是否应该显示日志区域:', formattedGoods.product_log && formattedGoods.product_log.length > 0); this.setData({ goodsDetail: formattedGoods }); // 延迟检查数据绑定情况 setTimeout(() => { const currentStatus = this.data.goodsDetail.status; console.log('=== 数据绑定后检查 ==='); console.log('当前goodsDetail.status:', currentStatus); console.log('按钮是否被正确绑定:', currentStatus === 'sold_out'); }, 100); } else { wx.showToast({ title: '获取商品详情失败', icon: 'none', duration: 2000 }); } }) .catch(err => { console.error('获取商品详情失败:', err); wx.showToast({ title: '获取商品详情失败', icon: 'none', duration: 2000 }); }) .finally(() => { wx.hideLoading(); }); }, // 显示编辑弹窗 showEditModal: function() { console.log('显示编辑弹窗 - 开始权限验证'); const goodsDetail = this.data.goodsDetail; const contactPhone = goodsDetail.contact_phone || ''; // 权限控制 const userPhone = getLocalPhoneNumber(); console.log('当前用户手机号:', userPhone); console.log('联系人电话:', contactPhone); // 使用更详细的请求参数,确保后端返回所有记录 const requestData = { phone: userPhone, // 添加额外参数,确保后端返回所有记录 getAll: true, pageSize: 100 // 设置较大的页大小,确保能返回所有记录 }; // 直接调用request函数获取完整的人员信息,现在该端点返回所有匹配的记录 API.request('/api/personnel/get', 'POST', requestData) .then(res => { console.log('直接请求personnel表响应:', res); let hasPermission = false; // 详细记录响应数据结构,便于调试 console.log('响应数据类型:', typeof res.data); console.log('响应数据是否为数组:', Array.isArray(res.data)); if (typeof res.data === 'object') { console.log('响应数据的所有属性:', Object.keys(res.data)); // 检查是否有其他可能包含数据的属性 if (res.data.rows) { console.log('响应数据包含rows属性,类型:', typeof res.data.rows, '是否为数组:', Array.isArray(res.data.rows)); } if (res.data.data) { console.log('响应数据包含data属性,类型:', typeof res.data.data, '是否为数组:', Array.isArray(res.data.data)); } } if (res && res.code === 200 && res.data) { // 处理数据库返回的各种格式,确保能获取到所有记录 let allPersonnelData = []; // 处理不同的数据格式 if (Array.isArray(res.data)) { // 情况1:data直接是数组(现在后端返回的是这种格式) allPersonnelData = res.data; } else if (typeof res.data === 'object') { // 情况2:data是对象 // 检查是否有rows属性(常见于分页接口) if (Array.isArray(res.data.rows)) { allPersonnelData = res.data.rows; } // 检查是否有data属性(嵌套data) else if (Array.isArray(res.data.data)) { allPersonnelData = res.data.data; } // 检查是否有children属性 else if (Array.isArray(res.data.children)) { allPersonnelData = res.data.children; } // 检查是否有list属性 else if (Array.isArray(res.data.list)) { allPersonnelData = res.data.list; } // 检查是否有items属性 else if (Array.isArray(res.data.items)) { allPersonnelData = res.data.items; } // 情况3:兼容旧格式,单个对象转换为数组 else { allPersonnelData = [res.data]; } } console.log('最终处理后的所有身份记录:', allPersonnelData); console.log('用户所有身份:', allPersonnelData.map(item => { console.log('单个身份记录:', item); return item.projectName || item.position || item.role || '未知身份'; })); // 将获取到的personnel数据存储到本地,以便在saveEdit中使用 wx.setStorageSync('personnel', allPersonnelData); console.log('【权限验证】已将personnel数据存储到本地'); // 检查是否有管理员、采购员或销售员身份 // 优先级:管理员 > 采购员/销售员 const isAdmin = allPersonnelData.some(item => (item.projectName && item.projectName === '管理员') || (item.position && item.position === '管理员') || (item.role && item.role === '管理员') ); const isBuyer = allPersonnelData.some(item => (item.projectName && item.projectName === '采购员') || (item.position && item.position === '采购员') || (item.role && item.role === '采购员') ); const isSeller = allPersonnelData.some(item => (item.projectName && item.projectName === '销售员') || (item.position && item.position === '销售员') || (item.role && item.role === '销售员') ); console.log('权限检查结果 - 管理员:', isAdmin, '采购员:', isBuyer, '销售员:', isSeller); if (isAdmin) { // 管理员权限最高,直接允许编辑 hasPermission = true; console.log('管理员权限验证通过,允许编辑'); } else if (isBuyer || isSeller) { // 采购员或销售员,检查是否为联系人 if (userPhone === contactPhone) { hasPermission = true; console.log('采购员/销售员且为联系人,允许编辑'); } else { console.log('采购员/销售员但非联系人,无编辑权限'); } } else { console.log('无匹配身份,无编辑权限'); } } else { console.log('未找到用户信息,无编辑权限'); } if (hasPermission) { this.openEditModal(goodsDetail); } else { // 没有权限 wx.showModal({ title: '权限不足', content: '你没有权限编辑此货源', showCancel: false }); } }) .catch(err => { console.error('权限验证失败:', err); wx.showModal({ title: '权限验证失败', content: '无法验证权限,请稍后重试', showCancel: false }); }); }, // 打开编辑弹窗(实际执行打开操作的内部方法) openEditModal: function(goodsDetail) { const spec = goodsDetail.spec || ''; let specArray = []; let priceArray = []; let costpriceArray = []; // 分割规格字符串,支持多种逗号分隔符:英文逗号、中文逗号、全角逗号 if (spec) { specArray = spec.split(/[,,、]/).map(item => item.trim()).filter(item => item); } else { // 如果没有spec,尝试从weightQuantityData中获取规格 if (goodsDetail.weightQuantityData && goodsDetail.weightQuantityData.length > 0) { specArray = goodsDetail.weightQuantityData.map(item => { // 移除净重/毛重前缀 return item.weightSpec.replace(/^(净重|毛重)/, ''); }); } else { specArray = ['']; } } // 从weightQuantityData中获取每个规格对应的价格和采购价格 if (goodsDetail.weightQuantityData && goodsDetail.weightQuantityData.length > 0) { // 遍历weightQuantityData,获取每个规格对应的价格和采购价格 for (let i = 0; i < specArray.length; i++) { // 查找当前规格对应的weightQuantityData项 const currentSpec = specArray[i]; // 处理规格前缀匹配问题,支持带净重/毛重前缀和不带前缀的情况 const matchingItem = goodsDetail.weightQuantityData.find(item => { // 完全匹配 if (item.weightSpec === currentSpec) return true; // 处理带前缀的情况 const hasPrefix = item.weightSpec.includes('净重') || item.weightSpec.includes('毛重'); if (hasPrefix) { // 如果weightSpec有前缀,移除前缀后比较 const specWithoutPrefix = item.weightSpec.replace(/^(净重|毛重)/, ''); return specWithoutPrefix === currentSpec; } else { // 如果weightSpec没有前缀,检查currentSpec是否包含weightSpec return currentSpec.includes(item.weightSpec); } }); if (matchingItem) { // 如果找到匹配项,使用匹配项的价格和采购价格 priceArray[i] = matchingItem.price || ''; costpriceArray[i] = matchingItem.costprice || ''; } else { // 如果没有找到匹配项,使用空字符串或默认值 priceArray[i] = ''; costpriceArray[i] = ''; } } } else { // 如果没有weightQuantityData,使用原有的处理方式 // 处理销售价格字段 const price = goodsDetail.price || ''; if (price) { if (typeof price === 'string' && price.includes(',')) { // 如果价格是字符串且包含逗号,分割成数组 priceArray = price.split(/[,,、]/).map(item => item.trim()).filter(item => item); } else { // 如果只有一个价格,为所有规格设置相同的价格 priceArray = Array(specArray.length).fill(String(price)); } } // 处理采购价格字段 const costprice = goodsDetail.costprice || ''; if (costprice) { if (typeof costprice === 'string' && costprice.includes(',')) { // 如果采购价格是字符串且包含逗号,分割成数组 costpriceArray = costprice.split(/[,,、]/).map(item => item.trim()).filter(item => item); } else { // 如果只有一个采购价格,为所有规格设置相同的采购价格 costpriceArray = Array(specArray.length).fill(String(costprice)); } } } // 创建editSupply对象 const editSupply = { id: goodsDetail.productId || goodsDetail.id, imageUrls: goodsDetail.imageUrls || [], name: goodsDetail.name || '', spec: spec, specArray: specArray, // 新增:规格数组 priceArray: priceArray, // 新增:价格数组 costpriceArray: costpriceArray, // 新增:采购价格数组 minOrder: goodsDetail.minOrder || '', yolk: goodsDetail.yolk || '', region: goodsDetail.region || '', grossWeight: goodsDetail.grossWeight || '', product_contact: goodsDetail.product_contact || '', contact_phone: goodsDetail.contact_phone || '' }; // 保存原始规格和价格信息,用于比较差异 const originalSpecPriceInfo = { specArray: [...specArray], priceArray: [...priceArray] }; this.setData({ editSupply: editSupply, originalSpecPriceInfo: originalSpecPriceInfo, showEditModal: true }); }, // 隐藏编辑弹窗 hideEditModal: function() { this.setData({ showEditModal: false }); }, // 保存编辑 saveEdit: function() { console.log('保存编辑'); const editSupply = this.data.editSupply; const goodsDetail = this.data.goodsDetail; // 处理价格字段,将价格数组合并成字符串 let priceStr = ''; if (editSupply.priceArray && editSupply.priceArray.length > 0) { // 验证所有价格输入框都必须填写 for (const price of editSupply.priceArray) { if (!price || price.trim() === '') { wx.showToast({ title: '请填写所有规格的销售价格', icon: 'none', duration: 2000 }); return; } } // 验证价格是否为有效数字 for (const price of editSupply.priceArray) { const priceNum = parseFloat(price); if (isNaN(priceNum) || priceNum < 0) { wx.showToast({ title: '请填写有效的价格', icon: 'none', duration: 2000 }); return; } } // 合并价格数组为字符串 priceStr = editSupply.priceArray.join(','); } else if (editSupply.price) { // 兼容旧的单个价格字段 const priceNum = parseFloat(editSupply.price); if (isNaN(priceNum) || priceNum < 0) { wx.showToast({ title: '请填写有效的价格', icon: 'none', duration: 2000 }); return; } priceStr = editSupply.price; } else { // 没有价格 wx.showToast({ title: '请填写销售价格', icon: 'none', duration: 2000 }); return; } // 验证联系人 if (!editSupply.product_contact || editSupply.product_contact === '联系人信息暂不可用') { wx.showToast({ title: '请选择有效的联系人', icon: 'none', duration: 2000 }); return; } // 验证联系电话 if (!editSupply.contact_phone || editSupply.contact_phone === '暂无联系电话') { wx.showToast({ title: '请填写有效的联系电话', icon: 'none', duration: 2000 }); return; } wx.showLoading({ title: '保存中...', mask: true }); // 调试日志:查看editSupply的完整数据 console.log('【saveEdit】editSupply完整数据:', JSON.stringify(editSupply, null, 2)); // 调试日志:查看productId的值 const productId = editSupply.productId || editSupply.id; console.log('【saveEdit】editSupply.productId:', editSupply.productId); console.log('【saveEdit】editSupply.id:', editSupply.id); console.log('【saveEdit】最终使用的productId:', productId); // 使用新的快速更新接口,只更新价格、联系人和电话 const updateData = { productId: productId, price: priceStr, product_contact: editSupply.product_contact || '', contact_phone: editSupply.contact_phone || '', }; console.log('【saveEdit】快速更新数据:', updateData); API.request('/api/products/quick-update', 'POST', updateData) .then(res => { wx.hideLoading(); console.log('更新商品成功:', res); if (res && res.code === 200) { // 获取原始规格和价格信息 const originalSpecPriceInfo = this.data.originalSpecPriceInfo || {}; const originalSpecArray = originalSpecPriceInfo.specArray || []; const originalPriceArray = originalSpecPriceInfo.priceArray || []; // 获取新的规格和价格信息 const newSpecArray = editSupply.specArray || []; const newPriceArray = editSupply.priceArray || []; console.log('【saveEdit】原始规格数组:', originalSpecArray); console.log('【saveEdit】原始价格数组:', originalPriceArray); console.log('【saveEdit】新规格数组:', newSpecArray); console.log('【saveEdit】新价格数组:', newPriceArray); // 检查每个规格的价格是否有变化,生成价格变化日志 const priceChanges = []; for (let i = 0; i < Math.max(originalSpecArray.length, newSpecArray.length); i++) { const originalSpec = originalSpecArray[i] || ''; const newSpec = newSpecArray[i] || ''; const originalPrice = originalPriceArray[i] || ''; const newPrice = newPriceArray[i] || ''; // 只有当规格存在且价格有变化时,才记录日志 if ((originalSpec || newSpec) && originalPrice !== newPrice) { // 使用新规格名称(如果有),否则使用原始规格名称 const specName = newSpec || originalSpec; priceChanges.push({ spec: specName, oldPrice: originalPrice, newPrice: newPrice }); } } // 如果有价格变化,记录日志 if (priceChanges.length > 0) { console.log('【saveEdit】有规格价格变化,记录日志:', priceChanges); // 获取当前用户信息 const userPhone = getLocalPhoneNumber(); let operatorName = userPhone; // 尝试从本地存储获取用户名 try { // 尝试从personnel数据中获取姓名 const personnelData = wx.getStorageSync('personnel') || []; const personnel = Array.isArray(personnelData) ? personnelData : [personnelData]; console.log('【saveEdit】本地存储的personnel数据:', personnel); // 查找当前用户的personnel信息 const userInfo = personnel.find(item => item.phoneNumber === userPhone || item.phone === userPhone || (item.phoneNumber && item.phoneNumber.includes(userPhone)) || (item.phone && item.phone.includes(userPhone)) ); console.log('【saveEdit】找到的userInfo:', userInfo); if (userInfo) { // 使用alias或name作为姓名,优先使用alias,不包含电话号码 const userName = userInfo.alias || userInfo.name || '未知用户'; console.log('【saveEdit】获取到的userName:', userName); operatorName = userName; console.log('【saveEdit】生成的operatorName:', operatorName); } else { // 尝试从users中获取,不包含电话号码 const users = wx.getStorageSync('users') || {}; const userId = wx.getStorageSync('userId'); if (userId && users[userId] && users[userId].name) { operatorName = users[userId].name; } else if (userId && users[userId] && users[userId].nickName) { operatorName = users[userId].nickName; } else { // 如果没有找到用户信息,使用默认名称 operatorName = '未知用户'; console.log('【saveEdit】未找到用户姓名,使用默认operatorName:', operatorName); } } } catch (e) { console.error('获取用户名失败:', e); console.log('【saveEdit】获取用户名异常,使用默认operatorName:', operatorName); } // 获取当前时间 const currentTime = new Date().toLocaleString('zh-CN'); // 获取当前产品日志 let productLog = []; if (goodsDetail.product_log) { if (Array.isArray(goodsDetail.product_log)) { // 已经是数组格式 productLog = [...goodsDetail.product_log]; } else if (typeof goodsDetail.product_log === 'string') { // 旧数据可能是JSON字符串 try { const parsedLog = JSON.parse(goodsDetail.product_log); if (Array.isArray(parsedLog)) { productLog = parsedLog; } else { // 旧数据可能是单个字符串,转换为数组 productLog = [parsedLog]; } } catch (e) { // 可能是普通字符串,直接作为第一条日志 productLog = [goodsDetail.product_log]; } } } // 为每个价格变化生成日志记录 priceChanges.forEach(change => { // 生成包含具体规格信息的日志字符串,添加元单位 const logRecord = `${operatorName}在${currentTime}将${change.spec}规格的销售价格从${change.oldPrice ? `${change.oldPrice}元` : ''}修改为了${change.newPrice}元`; // 添加新日志 productLog.push(logRecord); }); console.log('【saveEdit】更新后的日志:', productLog); // 更新产品日志 API.request('/api/products/update-log', 'POST', { productId: productId, product_log: productLog // 直接传递字符串数组,后端会处理序列化 }) .then(logRes => { console.log('更新产品日志成功:', logRes); }) .catch(logErr => { console.error('更新产品日志失败:', logErr); }); } wx.showToast({ title: '更新成功', icon: 'success', duration: 2000 }); // 隐藏编辑弹窗 this.hideEditModal(); // 重新加载商品详情,传入当前数据保持创建人和创建时间不变 this.loadGoodsDetail(productId, this.data.goodsDetail); } else { wx.showToast({ title: '更新失败', icon: 'none', duration: 2000 }); } }) .catch(err => { wx.hideLoading(); console.error('更新商品失败:', err); wx.showToast({ title: '更新失败', icon: 'none', duration: 2000 }); }); }, // 准备上架 preparePublishSupply: function() { console.log('准备上架商品'); // 权限控制:先获取用户手机号并检查权限 wx.showLoading({ title: '正在验证权限...', mask: true }); getUserPhoneNumber() .then(phoneNumber => { console.log('获取到用户手机号:', phoneNumber); return checkUserPermission(phoneNumber); }) .then(hasPermission => { wx.hideLoading(); if (!hasPermission) { wx.showModal({ title: '权限不足', content: '您没有上架商品的权限,请联系管理员。', showCancel: false }); return; } // 权限验证通过,继续执行上架流程 const goodsDetail = this.data.goodsDetail; const productId = goodsDetail.productId || goodsDetail.id; wx.showModal({ title: '确认上架', content: '确定要上架此商品吗?', success: (res) => { if (res.confirm) { this.publishSupply(productId); } } }); }) .catch(err => { wx.hideLoading(); console.error('权限验证失败:', err); wx.showToast({ title: '权限验证失败', icon: 'none' }); }); }, // 上架商品 publishSupply: function(productId) { console.log('上架商品,productId:', productId); wx.showLoading({ title: '上架中...', mask: true }); // 获取商品数据 const goodsDetail = this.data.goodsDetail; // 调用API上架商品 API.publishProduct(goodsDetail) .then(res => { wx.hideLoading(); console.log('上架商品成功:', res); if (res && res.code === 200) { wx.showToast({ title: '上架成功', icon: 'success', duration: 2000 }); // 重新加载商品详情 this.loadGoodsDetail(productId); } else { wx.showToast({ title: '上架失败', icon: 'none', duration: 2000 }); } }) .catch(err => { wx.hideLoading(); console.error('上架商品失败:', err); wx.showToast({ title: '上架失败', icon: 'none', duration: 2000 }); }); }, // 准备下架 prepareUnpublishSupply: function() { console.log('准备下架商品 - 开始权限验证'); const goodsDetail = this.data.goodsDetail; console.log('完整goodsDetail结构:', JSON.stringify(goodsDetail, null, 2)); const productSellerId = goodsDetail.sellerId || goodsDetail.seller_id || goodsDetail.userId || goodsDetail.user_id || goodsDetail.creatorId || goodsDetail.creator_id || goodsDetail.product?.sellerId || goodsDetail.product?.seller_id || goodsDetail.product?.userId || goodsDetail.seller?.userId || ''; const contactPhone = goodsDetail.contact_phone || goodsDetail.product_contact || ''; const userPhone = getLocalPhoneNumber(); const currentUserId = wx.getStorageSync('userId'); console.log('当前用户手机号:', userPhone); console.log('当前用户userId:', currentUserId, '(类型:', typeof currentUserId, ')'); console.log('商品sellerId(创建人):', productSellerId, '(类型:', typeof productSellerId, ')'); console.log('商品联系人电话:', contactPhone); // 使用更详细的请求参数,确保后端返回所有记录 const requestData = { phone: userPhone, // 添加额外参数,确保后端返回所有记录 getAll: true, pageSize: 100 // 设置较大的页大小,确保能返回所有记录 }; // 直接调用request函数获取完整的人员信息,现在该端点返回所有匹配的记录 API.request('/api/personnel/get', 'POST', requestData) .then(res => { console.log('直接请求personnel表响应:', res); let hasPermission = false; // 详细记录响应数据结构,便于调试 console.log('响应数据类型:', typeof res.data); console.log('响应数据是否为数组:', Array.isArray(res.data)); if (typeof res.data === 'object') { console.log('响应数据的所有属性:', Object.keys(res.data)); // 检查是否有其他可能包含数据的属性 if (res.data.rows) { console.log('响应数据包含rows属性,类型:', typeof res.data.rows, '是否为数组:', Array.isArray(res.data.rows)); } if (res.data.data) { console.log('响应数据包含data属性,类型:', typeof res.data.data, '是否为数组:', Array.isArray(res.data.data)); } } if (res && res.code === 200 && res.data) { // 处理数据库返回的各种格式,确保能获取到所有记录 let allPersonnelData = []; // 处理不同的数据格式 if (Array.isArray(res.data)) { // 情况1:data直接是数组(现在后端返回的是这种格式) allPersonnelData = res.data; } else if (typeof res.data === 'object') { // 情况2:data是对象 // 检查是否有rows属性(常见于分页接口) if (Array.isArray(res.data.rows)) { allPersonnelData = res.data.rows; } // 检查是否有data属性(嵌套data) else if (Array.isArray(res.data.data)) { allPersonnelData = res.data.data; } // 检查是否有children属性 else if (Array.isArray(res.data.children)) { allPersonnelData = res.data.children; } // 检查是否有list属性 else if (Array.isArray(res.data.list)) { allPersonnelData = res.data.list; } // 检查是否有items属性 else if (Array.isArray(res.data.items)) { allPersonnelData = res.data.items; } // 情况3:兼容旧格式,单个对象转换为数组 else { allPersonnelData = [res.data]; } } console.log('最终处理后的所有身份记录:', allPersonnelData); console.log('用户所有身份:', allPersonnelData.map(item => { console.log('单个身份记录:', item); return item.projectName || item.position || item.role || '未知身份'; })); // 检查是否为管理员 const isAdmin = allPersonnelData.some(item => (item.projectName && item.projectName === '管理员') || (item.position && item.position === '管理员') || (item.role && item.role === '管理员') ); // 检查是否为创建人 const isCreator = String(currentUserId) === String(productSellerId); // 检查是否为联系人 const isContact = userPhone === contactPhone; // 检查是否为采购员或销售员 const isBuyerOrSeller = allPersonnelData.some(item => (item.projectName && item.projectName === '采购员') || (item.projectName && item.projectName === '销售员') || (item.position && item.position === '采购员') || (item.position && item.position === '销售员') || (item.role && item.role === '采购员') || (item.role && item.role === '销售员') ); console.log('权限检查结果 - 管理员:', isAdmin, '创建人:', isCreator, '联系人:', isContact, '采购员/销售员:', isBuyerOrSeller); if (isAdmin) { // 管理员权限最高,直接允许下架 hasPermission = true; console.log('管理员权限验证通过,允许下架'); } else if (isCreator) { // 创建人允许下架 hasPermission = true; console.log('创建人权限验证通过,允许下架'); } else if (isContact && isBuyerOrSeller) { // 采购员或销售员且为联系人,允许下架 hasPermission = true; console.log('采购员/销售员且为联系人,允许下架'); } else { console.log('没有下架权限'); } } else { console.log('未找到用户信息,无下架权限'); } if (hasPermission) { this.confirmUnpublish(); } else { wx.showModal({ title: '权限不足', content: '您没有权限下架此货源', showCancel: false }); } }) .catch(err => { console.error('权限验证失败:', err); wx.showModal({ title: '权限验证失败', content: '无法验证权限,请稍后重试', showCancel: false }); }); }, // 确认下架(实际执行下架确认的内部方法) confirmUnpublish: function() { const goodsDetail = this.data.goodsDetail; const productId = goodsDetail.productId || goodsDetail.id; wx.showModal({ title: '确认下架', content: '确定要下架此商品吗?', success: (res) => { if (res.confirm) { this.unpublishSupply(productId); } } }); }, // 下架商品 unpublishSupply: function(productId) { console.log('下架商品,productId:', productId); wx.showLoading({ title: '下架中...', mask: true }); API.unpublishProduct({ productId: productId }) .then(res => { wx.hideLoading(); console.log('下架商品成功:', res); // 更灵活的成功判断条件,支持多种返回格式 if (res && (res.code === 200 || res.success === true || res.status === 'success')) { wx.showToast({ title: '下架成功', icon: 'success', duration: 2000 }); this.setData({ 'goodsDetail.status': 'sold_out', 'goodsDetail.label': 1 // 保留label字段的更新,确保兼容性 }); } else { wx.showToast({ title: '下架失败', icon: 'none', duration: 2000 }); } }) .catch(err => { wx.hideLoading(); console.error('下架商品失败:', err); wx.showToast({ title: '下架失败', icon: 'none', duration: 2000 }); }); }, // 编辑输入处理 onEditInput: function(e) { const field = e.currentTarget.dataset.field; const value = e.detail.value; this.setData({ [`editSupply.${field}`]: value }); }, // 价格输入处理(用于动态生成的价格输入框) onEditPriceInput: function(e) { const index = e.currentTarget.dataset.index; const value = e.detail.value; // 更新价格数组中的对应元素 this.setData({ [`editSupply.priceArray[${index}]`]: value }); }, // 打开规格选择弹窗(编辑模式) onEditSpecChange: function() { console.log('打开规格选择弹窗(编辑模式)'); const editSupply = this.data.editSupply; const specOptions = this.data.specOptions; // 查找当前规格在选项中的索引 const currentSpecIndex = specOptions.indexOf(editSupply.spec); this.setData({ showSpecSelectModal: true, currentSpecMode: 'edit', selectedModalSpecIndex: currentSpecIndex >= 0 ? currentSpecIndex : -1, modalSpecSearchKeyword: '', filteredModalSpecOptions: specOptions }); }, // 关闭规格选择弹窗 closeSpecSelectModal: function() { this.setData({ showSpecSelectModal: false }); }, // 规格弹窗搜索输入 onModalSpecSearchInput: function(e) { const keyword = e.detail.value; const specOptions = this.data.specOptions; // 过滤规格选项 const filteredOptions = specOptions.filter(option => { return option.includes(keyword); }); this.setData({ modalSpecSearchKeyword: keyword, filteredModalSpecOptions: filteredOptions, selectedModalSpecIndex: -1 }); }, // 清除规格弹窗搜索关键词 clearModalSpecSearch: function() { this.setData({ modalSpecSearchKeyword: '', filteredModalSpecOptions: this.data.specOptions, selectedModalSpecIndex: -1 }); }, // 选择规格 onModalSpecSelect: function(e) { const index = e.currentTarget.dataset.index; this.setData({ selectedModalSpecIndex: index }); }, // 确认规格选择 confirmSpecSelection: function() { const selectedIndex = this.data.selectedModalSpecIndex; const filteredOptions = this.data.filteredModalSpecOptions; const currentSpecMode = this.data.currentSpecMode; if (selectedIndex >= 0 && selectedIndex < filteredOptions.length) { const selectedSpec = filteredOptions[selectedIndex]; if (currentSpecMode === 'edit') { // 编辑模式 this.setData({ [`editSupply.spec`]: selectedSpec }); } this.closeSpecSelectModal(); } }, // 打开商品名称选择弹窗 openNameSelectModal: function() { console.log('打开商品名称选择弹窗'); const editSupply = this.data.editSupply; const productNameOptions = this.data.productNameOptions; // 查找当前商品名称在选项中的索引 const currentNameIndex = productNameOptions.indexOf(editSupply.name); this.setData({ showNameSelectModal: true, selectedNameIndex: currentNameIndex >= 0 ? currentNameIndex : -1 }); }, // 关闭商品名称选择弹窗 closeNameSelectModal: function() { this.setData({ showNameSelectModal: false }); }, // 选择商品名称 onNameSelect: function(e) { const index = e.currentTarget.dataset.index; this.setData({ selectedNameIndex: index }); }, // 确认商品名称选择 confirmNameSelection: function() { const selectedIndex = this.data.selectedNameIndex; const productNameOptions = this.data.productNameOptions; if (selectedIndex >= 0 && selectedIndex < productNameOptions.length) { const selectedName = productNameOptions[selectedIndex]; this.setData({ [`editSupply.name`]: selectedName, showNameSelectModal: false }); } }, // 打开蛋黄选择弹窗 openYolkSelectModal: function() { console.log('打开蛋黄选择弹窗'); const editSupply = this.data.editSupply; const yolkOptions = this.data.yolkOptions; // 查找当前蛋黄在选项中的索引 const currentYolkIndex = yolkOptions.indexOf(editSupply.yolk); this.setData({ showYolkSelectModal: true, selectedYolkIndex: currentYolkIndex >= 0 ? currentYolkIndex : -1 }); }, // 关闭蛋黄选择弹窗 closeYolkSelectModal: function() { this.setData({ showYolkSelectModal: false }); }, // 选择蛋黄 onYolkSelect: function(e) { const index = e.currentTarget.dataset.index; this.setData({ selectedYolkIndex: index }); }, // 确认蛋黄选择 confirmYolkSelection: function() { const selectedIndex = this.data.selectedYolkIndex; const yolkOptions = this.data.yolkOptions; if (selectedIndex >= 0 && selectedIndex < yolkOptions.length) { const selectedYolk = yolkOptions[selectedIndex]; this.setData({ [`editSupply.yolk`]: selectedYolk, showYolkSelectModal: false }); } }, // 打开销售员选择弹窗 openSalesPersonModal: function() { console.log('打开销售员选择弹窗'); const editSupply = this.data.editSupply; const salesPersonnelOptions = this.data.salesPersonnelOptions; // 查找当前联系人在选项中的索引 let currentSalesPersonIndex = -1; if (editSupply.product_contact) { currentSalesPersonIndex = salesPersonnelOptions.findIndex( item => item.name === editSupply.product_contact ); } this.setData({ showSalesPersonSelectModal: true, selectedSalesPersonIndex: currentSalesPersonIndex >= 0 ? currentSalesPersonIndex : -1, modalSalesPersonSearchKeyword: '', filteredSalesPersonnelOptions: salesPersonnelOptions }); }, // 关闭销售员选择弹窗 closeSalesPersonSelectModal: function() { this.setData({ showSalesPersonSelectModal: false }); }, // 销售员弹窗搜索输入 onModalSalesPersonSearchInput: function(e) { const keyword = e.detail.value; const salesPersonnelOptions = this.data.salesPersonnelOptions; // 过滤销售员选项 const filteredOptions = salesPersonnelOptions.filter(option => { return option.name.includes(keyword) || (option.phoneNumber && option.phoneNumber.includes(keyword)); }); this.setData({ modalSalesPersonSearchKeyword: keyword, filteredSalesPersonnelOptions: filteredOptions, selectedSalesPersonIndex: -1 }); }, // 清除销售员弹窗搜索关键词 clearModalSalesPersonSearch: function() { this.setData({ modalSalesPersonSearchKeyword: '', filteredSalesPersonnelOptions: this.data.salesPersonnelOptions, selectedSalesPersonIndex: -1 }); }, // 选择销售员 onSalesPersonSelect: function(e) { const index = e.currentTarget.dataset.index; this.setData({ selectedSalesPersonIndex: index }); }, // 确认销售员选择 confirmSalesPersonSelection: function() { const selectedIndex = this.data.selectedSalesPersonIndex; const filteredOptions = this.data.filteredSalesPersonnelOptions; if (selectedIndex >= 0 && selectedIndex < filteredOptions.length) { const selectedSalesPerson = filteredOptions[selectedIndex]; // 更新联系人和联系电话 this.setData({ ['editSupply.product_contact']: selectedSalesPerson.name, ['editSupply.contact_phone']: selectedSalesPerson.phoneNumber || this.data.editSupply.contact_phone, showSalesPersonSelectModal: false }); console.log('选择销售员后更新editSupply:', this.data.editSupply); } }, // 选择图片 chooseImage: function(e) { const type = e.currentTarget.dataset.type; const maxCount = 5; const currentCount = type === 'edit' ? this.data.editSupply.imageUrls.length : 0; const canChooseCount = maxCount - currentCount; if (canChooseCount <= 0) { wx.showToast({ title: '最多只能上传5张图片', icon: 'none', duration: 2000 }); return; } wx.chooseImage({ count: canChooseCount, sizeType: ['compressed'], sourceType: ['album', 'camera'], success: (res) => { const tempFilePaths = res.tempFilePaths; // 上传图片到服务器 this.uploadImages(tempFilePaths, type); }, fail: (err) => { console.error('选择图片失败:', err); } }); }, // 上传图片 uploadImages: function(filePaths, type) { console.log('上传图片,type:', type); wx.showLoading({ title: '上传中...', mask: true }); // 这里应该调用API上传图片,获取图片URL // 由于没有具体的上传API,这里模拟上传成功 setTimeout(() => { wx.hideLoading(); // 模拟上传成功,使用临时文件路径作为图片URL if (type === 'edit') { const editSupply = this.data.editSupply; const newImageUrls = [...editSupply.imageUrls, ...filePaths]; this.setData({ 'editSupply.imageUrls': newImageUrls }); } wx.showToast({ title: '上传成功', icon: 'success', duration: 2000 }); }, 1000); }, // 预览图片 previewImage: function(e) { const urls = e.currentTarget.dataset.urls; const currentIndex = e.currentTarget.dataset.index; // 过滤出图片URL const imageUrls = urls.filter(url => !isVideoUrl(url)); // 如果没有图片URL,不打开预览 if (imageUrls.length === 0) { return; } wx.previewImage({ urls: imageUrls, current: imageUrls[currentIndex] }); }, // 移除图片 removeImage: function(e) { const type = e.currentTarget.dataset.type; const index = e.currentTarget.dataset.index; if (type === 'edit') { const editSupply = this.data.editSupply; const newImageUrls = editSupply.imageUrls.filter((item, i) => i !== index); this.setData({ 'editSupply.imageUrls': newImageUrls }); } }, // 保存图片 saveImageToPhotosAlbum: function(e) { const url = e.currentTarget.dataset.url; wx.downloadFile({ url: url, success: function(res) { if (res.statusCode === 200) { wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: function() { wx.showToast({ title: '保存成功', icon: 'success', duration: 2000 }); }, fail: function(err) { console.error('保存图片失败:', err); wx.showToast({ title: '保存失败', icon: 'none', duration: 2000 }); } }); } }, fail: function(err) { console.error('下载图片失败:', err); wx.showToast({ title: '下载失败', icon: 'none', duration: 2000 }); } }); }, // 处理图片点击事件 handleImageTap: function(e) { console.log('图片点击事件:', e); // 双击放大图片的逻辑 const currentTime = Date.now(); const lastTapTime = this.data.lastTapTime; if (currentTime - lastTapTime < 300) { // 双击事件 this.setData({ scale: this.data.scale === 1 ? 2 : 1, isScaling: false }); this.data.doubleTapTimer && clearTimeout(this.data.doubleTapTimer); this.setData({ doubleTapTimer: null, lastTapTime: 0 }); } else { // 单击事件 this.setData({ lastTapTime: currentTime }); this.data.doubleTapTimer && clearTimeout(this.data.doubleTapTimer); this.setData({ doubleTapTimer: setTimeout(() => { this.setData({ lastTapTime: 0 }); }, 300) }); } }, // 触摸开始事件 handleTouchStart: function(e) { // 记录初始触摸点 if (e.touches.length === 1) { // 单指触摸,记录初始位置 this.setData({ initialTouch: { x: e.touches[0].clientX, y: e.touches[0].clientY } }); } else if (e.touches.length === 2) { // 双指触摸,计算初始距离 const x1 = e.touches[0].clientX; const y1 = e.touches[0].clientY; const x2 = e.touches[1].clientX; const y2 = e.touches[1].clientY; const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); this.setData({ startDistance: distance, lastScale: this.data.scale, isScaling: true }); } }, // 触摸移动事件 handleTouchMove: function(e) { if (e.touches.length === 2 && this.data.isScaling) { // 双指缩放 const x1 = e.touches[0].clientX; const y1 = e.touches[0].clientY; const x2 = e.touches[1].clientX; const y2 = e.touches[1].clientY; const currentDistance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); const scale = this.data.lastScale * (currentDistance / this.data.startDistance); // 限制缩放范围 const limitedScale = Math.min(Math.max(scale, 0.5), 3); this.setData({ scale: limitedScale }); } else if (e.touches.length === 1 && this.data.initialTouch && this.data.scale !== 1) { // 单指拖动(只有在缩放状态下才允许拖动) const currentX = e.touches[0].clientX; const currentY = e.touches[0].clientY; const deltaX = currentX - this.data.initialTouch.x; const deltaY = currentY - this.data.initialTouch.y; this.setData({ offsetX: deltaX, offsetY: deltaY }); // 更新初始触摸点,以便下一次移动计算 this.setData({ initialTouch: { x: currentX, y: currentY } }); } }, // 触摸结束事件 handleTouchEnd: function(e) { if (this.data.isScaling) { this.setData({ isScaling: false }); } }, // 图片加载完成事件 onPreviewImageLoad: function() { // 图片加载完成后可以进行一些操作 }, // 关闭图片预览弹窗 closeImagePreview: function() { this.setData({ showImagePreview: false }); } })