You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

2444 lines
91 KiB

// 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 = '', specStatusString = '') {
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, ')');
console.log('- specStatusString:', specStatusString, '(类型:', typeof specStatusString, ')');
// 如果没有数据,返回空数组
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);
}
// 处理规格状态字符串,支持逗号分隔的多个状态
let specStatusArray = [];
if (specStatusString && typeof specStatusString === 'string') {
// 支持多种逗号分隔符:英文逗号、中文逗号、全角逗号
specStatusArray = specStatusString.split(/[,,、]/).map(item => item.trim()).filter(item => item);
console.log('从字符串分割得到规格状态数组:', specStatusArray);
}
// 获取最大长度,确保一一对应
const maxLength = Math.max(weightSpecArray.length, quantityArray.length, priceArray.length, costpriceArray.length, specStatusArray.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] || '';
const itemSpecStatus = specStatusArray[i] || '0'; // 默认规格状态为0
console.log(`处理第${i}组数据: weightSpec=${weightSpec}, quantity=${quantity}, price=${itemPrice}, costprice=${itemCostprice}, specStatus=${itemSpecStatus}`);
// 处理净重规格显示格式 - 根据内容类型添加相应前缀
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,
specStatus: itemSpecStatus
});
console.log(`添加显示对象: weightSpec=${weightSpecDisplay}, quantity=${quantityDisplay}, price=${itemPrice}, costprice=${itemCostprice}, specStatus=${itemSpecStatus}`);
}
}
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, // 初始触摸点
// 规格下架相关状态
showSpecUnpublishModal: false, // 控制规格下架弹窗显示
selectedSpecIndices: [], // 选中的规格索引数组,支持多选
isSelected: [] // 每个规格的选中状态数组,true表示选中,false表示未选中
},
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);
// 添加spec_status字段调试
console.log('product.spec_status:', product.spec_status);
console.log('是否包含spec_status字段:', 'spec_status' in product);
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, product.spec_status);
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,
// 添加sellerId字段,确保它存在
sellerId: product.sellerId || product.seller_id || product.userId || product.user_id || product.creatorId || product.creator_id || '',
// 复制原始产品对象中的所有字段,确保不丢失任何数据
...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,
// 确保sellerId字段存在,放在最后覆盖所有来源的值
sellerId: product.sellerId || product.seller_id || (product.seller ? product.seller.userId : '') || product.userId || product.user_id || product.creatorId || product.creator_id || ''
};
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);
}
// 获取当前时间并格式化为统一格式:yyyy-MM-dd HH:mm:ss
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, '0');
const day = now.getDate().toString().padStart(2, '0');
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');
const currentTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
// 获取当前产品日志
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 weightQuantityData = goodsDetail.weightQuantityData || [];
// 计算所有未售空的规格索引
let selectedSpecIndices = [];
let isSelected = [];
// 遍历规格数据,找出所有未售空的规格
weightQuantityData.forEach((item, index) => {
// 如果规格状态不是1(未售空),则默认选中
if (item.specStatus !== '1') {
selectedSpecIndices.push(index);
isSelected[index] = true;
} else {
isSelected[index] = false;
}
});
console.log('默认选中的规格索引:', selectedSpecIndices);
console.log('默认选中的状态数组:', isSelected);
// 显示规格选择弹窗,默认选中所有未售空的规格
this.setData({
showSpecUnpublishModal: true,
selectedSpecIndices: selectedSpecIndices,
isSelected: isSelected
});
},
// 下架商品
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
});
});
},
// 规格下架选择(支持多选)
onSpecUnpublishSelect: function(e) {
const index = e.currentTarget.dataset.index;
let selectedSpecIndices = [...this.data.selectedSpecIndices];
let isSelected = [...this.data.isSelected];
// 确保isSelected数组长度足够
while (isSelected.length <= index) {
isSelected.push(false);
}
// 切换选中状态
const isCurrentlySelected = isSelected[index];
isSelected[index] = !isCurrentlySelected;
// 更新selectedSpecIndices数组
const indexInArray = selectedSpecIndices.indexOf(index);
if (isCurrentlySelected) {
// 已选中,取消选择,从数组中移除
selectedSpecIndices.splice(indexInArray, 1);
} else {
// 未选中,添加选择,添加到数组中
selectedSpecIndices.push(index);
}
this.setData({
selectedSpecIndices: selectedSpecIndices,
isSelected: isSelected
});
},
// 关闭规格下架弹窗
closeSpecUnpublishModal: function() {
this.setData({
showSpecUnpublishModal: false,
selectedSpecIndices: [],
isSelected: []
});
},
// 确认规格下架
confirmSpecUnpublish: function() {
const selectedIndices = this.data.selectedSpecIndices;
if (selectedIndices.length === 0) {
wx.showToast({
title: '请选择要下架的规格',
icon: 'none',
duration: 2000
});
return;
}
// 显示确认提示,防止误点
wx.showModal({
title: '确认下架',
content: `确定要下架选中的${selectedIndices.length}个规格吗?`,
confirmText: '确定',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
const goodsDetail = this.data.goodsDetail;
const productId = goodsDetail.productId || goodsDetail.id;
const weightQuantityData = goodsDetail.weightQuantityData || [];
// 获取当前的spec_status字符串
let currentSpecStatus = goodsDetail.spec_status || '';
let specStatusArray = [];
if (currentSpecStatus) {
specStatusArray = currentSpecStatus.split(/[,,、]/).map(item => item.trim()).filter(item => item);
}
// 确保specStatusArray长度足够
const maxIndex = Math.max(...selectedIndices, weightQuantityData.length - 1);
while (specStatusArray.length <= maxIndex) {
specStatusArray.push('0');
}
// 设置所有选中的规格为售空状态
selectedIndices.forEach(index => {
specStatusArray[index] = '1';
});
// 更新spec_status字符串
const newSpecStatus = specStatusArray.join(',');
// 调用API更新规格状态
wx.showLoading({
title: '处理中...',
mask: true
});
// 添加调试日志
console.log('===== 调试规格更新API调用 =====');
console.log('goodsDetail对象:', JSON.stringify(goodsDetail, null, 2));
console.log('productId:', productId);
console.log('goodsDetail.sellerId:', goodsDetail.sellerId);
console.log('goodsDetail.seller_id:', goodsDetail.seller_id);
console.log('goodsDetail.seller:', JSON.stringify(goodsDetail.seller, null, 2));
console.log('goodsDetail.seller.userId:', goodsDetail.seller ? goodsDetail.seller.userId : 'undefined');
const updateData = {
productId: productId,
sellerId: goodsDetail.sellerId || goodsDetail.seller_id || (goodsDetail.seller ? goodsDetail.seller.userId : ''),
spec_status: newSpecStatus
};
console.log('最终发送的updateData:', JSON.stringify(updateData, null, 2));
API.request('/api/products/edit', 'POST', updateData)
.then(res => {
wx.hideLoading();
console.log('更新规格状态成功:', res);
if (res && (res.code === 200 || res.success === true)) {
wx.showToast({
title: '规格下架成功',
icon: 'success',
duration: 2000
});
// 更新本地数据
const updatedWeightQuantityData = [...weightQuantityData];
// 更新所有选中规格的状态
selectedIndices.forEach(index => {
updatedWeightQuantityData[index].specStatus = '1';
});
// 详细调试日志:检查updatedWeightQuantityData数组的内容
console.log('=== 全部规格下架判断调试 ===');
console.log('更新后的weightQuantityData数组:', JSON.stringify(updatedWeightQuantityData, null, 2));
console.log('数组长度:', updatedWeightQuantityData.length);
// 遍历数组,检查每个规格的specStatus
updatedWeightQuantityData.forEach((item, index) => {
console.log(`${index}个规格: specStatus=${item.specStatus}, 类型=${typeof item.specStatus}`);
});
// 检查是否所有规格都已下架
const allSoldOut = updatedWeightQuantityData.every(item => item.specStatus === '1');
console.log('allSoldOut判断结果:', allSoldOut);
// 更新本地商品状态
this.setData({
'goodsDetail.weightQuantityData': updatedWeightQuantityData,
'goodsDetail.spec_status': newSpecStatus,
'goodsDetail.status': allSoldOut ? 'sold_out' : 'published',
'goodsDetail.label': allSoldOut ? 1 : 0,
showSpecUnpublishModal: false,
selectedSpecIndices: []
});
// 如果所有规格都已下架,调用下架功能接口,确保服务器端更新商品状态
if (allSoldOut) {
console.log('所有规格都已下架,调用下架功能接口更新商品状态');
API.unpublishProduct({ productId: productId })
.then(res => {
console.log('调用下架功能接口成功:', res);
// 再次检查服务器返回后的商品状态
return API.getProductDetail({ productId: productId });
})
.then(detailRes => {
console.log('重新获取商品详情成功:', detailRes);
if (detailRes && detailRes.code === 200 && detailRes.data) {
// 只更新需要的字段,避免丢失本地状态
this.setData({
'goodsDetail.status': detailRes.data.status,
'goodsDetail.label': detailRes.data.label,
'goodsDetail.spec_status': detailRes.data.spec_status
});
}
})
.catch(err => {
console.error('调用下架功能接口失败:', err);
// 接口调用失败不影响本地状态更新,只记录日志
});
} else {
console.log('并非所有规格都已下架,无需调用下架功能接口');
}
} 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
});
}
})