define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
//设置弹窗宽高
Fast.config.openArea = ['80%', '80%'];
var vm, si;
var Controller = {
index: function () {
// 解析JSON格式的Config数据
var statusList = {};
var specTypeList = {};
var goodsTypeList = {};
try {
statusList = Config.statusList ? JSON.parse(Config.statusList) : {};
specTypeList = Config.specTypeList ? JSON.parse(Config.specTypeList) : {};
goodsTypeList = Config.goodsTypeList ? JSON.parse(Config.goodsTypeList) : {};
} catch (e) {
console.error('解析Config数据失败:', e);
statusList = {"normal": "正常", "hidden": "隐藏", "soldout": "售罄"};
specTypeList = {0: "单规格", 1: "多规格"};
goodsTypeList = {1: "普通商品"};
}
// 调试输出Config数据
console.log('解析后的Config数据:', {
statusList: statusList,
specTypeList: specTypeList,
goodsTypeList: goodsTypeList
});
// 添加列表样式优化
$('
`;
$('head').append(styles);
},
// 初始化商品类型卡片交互
initGoodsTypeCards: function() {
// 检查元素是否存在,避免在不支持该功能的页面报错
if ($('.goods-type-card').length === 0) {
return;
}
// 初始化选中状态
function updateTypeCardState() {
var $cards = $('.goods-type-card');
if ($cards.length > 0) {
$cards.removeClass('selected');
$('.goods-type-card input[type="radio"]:checked').closest('.goods-type-card').addClass('selected');
}
}
// 监听单选按钮变化
var $radioInputs = $('.goods-type-card input[type="radio"]');
if ($radioInputs && $radioInputs.length > 0) {
$radioInputs.off('change.typecard').on('change.typecard', function() {
updateTypeCardState();
});
}
// 初始化时设置状态
updateTypeCardState();
// 让FastAdmin处理表单验证和按钮状态
// 无需额外的验证逻辑,data-rule会自动处理
},
// 初始化编辑状态
initEditTypeState: function() {
console.log('初始化编辑状态');
// 如果存在商品数据,设置商品类型选中状态
if (Config.goods && Config.goods.type) {
console.log('设置商品类型:', Config.goods.type);
var $typeRadio = $('input[name="row[type]"][value="' + Config.goods.type + '"]');
if ($typeRadio.length > 0) {
$typeRadio.prop('checked', true);
$typeRadio.trigger('change');
}
}
// 如果存在上架类型数据,设置上架类型选中状态(优先使用online_type字段)
if (Config.goods && Config.goods.online_type !== undefined) {
console.log('设置上架类型(online_type):', Config.goods.online_type);
var $onlineTypeRadio = $('input[name="row[online_type]"][value="' + Config.goods.online_type + '"]');
if ($onlineTypeRadio.length > 0) {
$onlineTypeRadio.prop('checked', true);
$onlineTypeRadio.trigger('change');
}
}
// 设置上下架时间相关字段
if (Config.goods) {
// 设置定时上架时间
if (Config.goods.scheduled_online_time) {
$('#c-scheduled_online_time').val(Config.goods.scheduled_online_time);
}
// 设置自动下架选项
if (Config.goods.is_auto_offline) {
$('#c-is_auto_offline').prop('checked', true);
if (Config.goods.scheduled_offline_time) {
$('#c-scheduled_offline_time').val(Config.goods.scheduled_offline_time);
}
}
}
// 如果存在规格类型数据,设置规格类型选中状态
if (Config.goods && Config.goods.spec_type !== undefined) {
console.log('设置规格类型:', Config.goods.spec_type);
var $specTypeRadio = $('input[name="row[spec_type]"][value="' + Config.goods.spec_type + '"]');
if ($specTypeRadio.length > 0) {
$specTypeRadio.prop('checked', true);
$specTypeRadio.trigger('change');
// 触发FastAdmin的Favisible事件,确保对应的表单区域显示
setTimeout(function() {
$(document).trigger('fa.event.favisible', $specTypeRadio);
}, 100);
}
}
// 如果是单规格且有SKU数据,填充单规格表单
if (Config.goods && Config.goods.spec_type == '0' && Config.goods_skus && Config.goods_skus.length > 0) {
console.log('填充单规格数据');
var sku = Config.goods_skus[0];
// 延迟填充数据,确保DOM已渲染
setTimeout(function() {
$('#c-price').val(sku.price || '');
$('#c-lineation_price').val(sku.lineation_price || '');
$('#c-cost_price').val(sku.cost_price || '');
$('#c-stocks').val(sku.stocks || '');
$('#c-weight').val(sku.weight || '');
$('#c-volume').val(sku.volume || '');
$('#c-sku-sn').val(sku.sku_sn || '');
$('#c-single-image').val(sku.image || '');
// 更新单规格图片预览
if (sku.image) {
var $preview = $('#p-single-image');
var img = '
';
$preview.html(img);
}
console.log('单规格数据填充完成');
}, 200);
} else if (Config.goods && Config.goods.spec_type == '1') {
console.log('多规格商品,等待Vue组件初始化多规格数据');
// 多规格数据由Vue组件的init方法处理
}
},
// 初始化选项卡验证提示系统
initTabValidation: function() {
var that = this;
// 添加错误高亮样式
that.addErrorStyles();
// 清除所有选项卡错误标记
that.clearTabErrors();
// 启用提交按钮(移除disabled类)
$('.btn[type="submit"]').removeClass('disabled');
// 监听表单字段变化,实时验证
var $forms = $('#add-form, #edit-form');
if ($forms && $forms.length > 0) {
$forms.on('change keyup blur', 'input, select, textarea', function() {
setTimeout(function() {
that.validateCurrentTab();
}, 100);
});
}
// 监听选项卡切换
var $tabLinks = $('.nav-tabs a[data-toggle="tab"]');
if ($tabLinks && $tabLinks.length > 0) {
$tabLinks.on('shown.bs.tab', function(e) {
setTimeout(function() {
that.validateCurrentTab();
}, 100);
});
// 当离开选项卡时,验证该选项卡并标记状态
$tabLinks.on('hide.bs.tab', function(e) {
var leavingTab = $(e.target).attr('href');
that.validateAndMarkTab(leavingTab);
});
}
// 页面加载完成后进行一次全面验证,但不跳转,只显示状态
setTimeout(function() {
that.validateAllTabsForStatus();
}, 1000);
},
// 验证当前选项卡
validateCurrentTab: function() {
var that = this;
var $activeTab = $('.nav-tabs li.active a');
if ($activeTab.length === 0) {
return; // 没有活动选项卡,直接返回
}
var activeTab = $activeTab.attr('href');
if (!activeTab) {
return; // 没有href属性,直接返回
}
// 清除当前选项卡的错误标记
that.clearTabError(activeTab);
var hasError = false;
var errorMessage = '';
switch(activeTab) {
case '#basics':
var result = that.validateBasicsTab();
hasError = !result.valid;
errorMessage = result.message;
break;
case '#skus':
var result = that.validateSkusTab();
hasError = !result.valid;
errorMessage = result.message;
break;
case '#delivery':
var result = that.validateDeliveryTab();
hasError = !result.valid;
errorMessage = result.message;
break;
case '#detail':
var result = that.validateDetailTab();
hasError = !result.valid;
errorMessage = result.message;
break;
case '#sales':
var result = that.validateSalesTab();
hasError = !result.valid;
errorMessage = result.message;
break;
}
if (hasError) {
that.showTabError(activeTab, errorMessage);
}
},
// 验证基础信息选项卡
validateBasicsTab: function() {
var errors = [];
console.log('验证基础信息选项卡');
// 验证商品类型
if (!$('input[name="row[type]"]:checked').length) {
errors.push('请选择商品类型');
console.log('商品类型验证失败');
}
// 验证商品编码 - 检查是否有data-rule required
var $goodsSn = $('#c-goods_sn');
if ($goodsSn.length > 0 && $goodsSn.attr('data-rule') && $goodsSn.attr('data-rule').indexOf('required') !== -1) {
var goodsSn = $goodsSn.val();
if (!goodsSn || goodsSn.trim() === '') {
errors.push('请输入商品编码');
console.log('商品编码验证失败');
}
}
// 验证商品标题
var $title = $('#c-title');
if ($title.length > 0 && $title.attr('data-rule') && $title.attr('data-rule').indexOf('required') !== -1) {
var title = $title.val();
if (!title || title.trim() === '') {
errors.push('请输入商品标题');
console.log('商品标题验证失败');
}
}
// 验证商品分类 - 多选控件(兼容不同页面的字段ID)
var $categoryId = $('#c-category_id, #c-category_ids').first();
if ($categoryId.length > 0 && $categoryId.attr('data-rule') && $categoryId.attr('data-rule').indexOf('required') !== -1) {
var categoryId = $categoryId.val();
if (Controller.isMultiSelectEmpty(categoryId)) {
errors.push('请选择商品分类');
console.log('商品分类验证失败');
}
}
// 验证主图
var $image = $('#c-image');
if ($image.length > 0 && $image.attr('data-rule') && $image.attr('data-rule').indexOf('required') !== -1) {
var image = $image.val();
if (!image || image.trim() === '') {
errors.push('请上传商品主图');
console.log('商品主图验证失败');
}
}
console.log('基础信息验证结果:', errors);
return {
valid: errors.length === 0,
message: errors.join('、'),
errors: errors
};
},
// 验证价格库存选项卡
validateSkusTab: function() {
var errors = [];
var specType = $('input[name="row[spec_type]"]:checked').val();
console.log('验证价格库存选项卡, 规格类型:', specType);
if (!specType) {
errors.push('请选择规格类型');
console.log('规格类型未选择');
} else if (specType == '0') {
// 单规格验证
console.log('验证单规格');
// 验证价格
var $price = $('#c-price');
if ($price.length > 0 && $price.attr('data-rule') && $price.attr('data-rule').indexOf('required') !== -1) {
var price = parseFloat($price.val());
if (!price || price <= 0) {
errors.push('销售价必须大于0');
console.log('销售价验证失败');
}
}
// 验证库存
var $stocks = $('#c-stocks');
if ($stocks.length > 0 && $stocks.attr('data-rule') && $stocks.attr('data-rule').indexOf('required') !== -1) {
var stocks = parseInt($stocks.val());
if (isNaN(stocks) || stocks <= 0) {
errors.push('库存必须大于0');
console.log('库存验证失败');
}
}
} else if (specType == '1') {
// 多规格验证
console.log('验证多规格');
if (typeof vm !== 'undefined' && vm && vm.tableData) {
var hasValidSku = false;
var validSkuCount = 0;
console.log('检查SKU数据, tableData长度:', vm.tableData.length);
for (var i = 0; i < vm.tableData.length; i++) {
var sku = vm.tableData[i];
console.log('检查SKU[' + i + ']:', {
status: sku.status,
price: sku.price,
stocks: sku.stocks,
sku_sn: sku.sku_sn
});
// 只检查状态为显示的SKU
var isVisible = (sku.status === 1 || sku.status === '1' || sku.status === true);
console.log('SKU[' + i + '] 显示状态:', sku.status, '可见:', isVisible);
if (isVisible) {
var price = parseFloat(sku.price);
var stocks = parseInt(sku.stocks);
console.log('SKU[' + i + '] 检查通过, price:', price, 'stocks:', stocks);
hasValidSku = true;
validSkuCount++;
// 验证价格必须大于0
if (!price || price <= 0) {
errors.push('SKU销售价必须大于0');
console.log('SKU[' + i + ']销售价验证失败:', price);
break;
}
// 验证库存
if (isNaN(stocks) || stocks <= 0) {
errors.push('SKU库存必须大于0');
console.log('SKU[' + i + ']库存验证失败:', stocks);
break;
}
}
}
console.log('有效SKU数量:', validSkuCount);
if (!hasValidSku) {
errors.push('请至少设置一个有效的SKU');
console.log('没有有效的SKU');
}
} else {
errors.push('请设置商品规格');
console.log('多规格数据不存在');
}
}
console.log('价格库存验证结果:', errors);
return {
valid: errors.length === 0,
message: errors.join('、'),
errors: errors
};
},
// 验证配送设置选项卡
validateDeliveryTab: function() {
var errors = [];
console.log('验证配送设置选项卡');
// 验证配送方式
if (!$('input[name="row[delivery_type]"]:checked').length) {
errors.push('请选择配送方式');
console.log('配送方式未选择');
}
var deliveryType = $('input[name="row[delivery_type]"]:checked').val();
if (deliveryType === 'EXPRESS') {
var expressType = $('input[name="row[express_type]"]:checked').val();
if (expressType === '3') {
// 运费模板
var templateId = $('#c-express_template_id').val();
if (!templateId) {
errors.push('请选择运费模板');
console.log('运费模板未选择');
}
}
}
console.log('配送设置验证结果:', errors);
return {
valid: errors.length === 0,
message: errors.join('、'),
errors: errors
};
},
// 验证商品详情选项卡
validateDetailTab: function() {
console.log('验证商品详情选项卡');
// 商品详情不是必填项,暂时返回有效
return {
valid: true,
message: '',
errors: []
};
},
// 验证销售设置选项卡
validateSalesTab: function() {
var errors = [];
console.log('验证销售设置选项卡');
// 验证库存显示方式
if (!$('input[name="row[stock_show_type]"]:checked').length) {
errors.push('请选择库存显示方式');
console.log('库存显示方式未选择');
}
// 验证销量显示方式
if (!$('input[name="row[sales_show_type]"]:checked').length) {
errors.push('请选择销量显示方式');
console.log('销量显示方式未选择');
}
console.log('销售设置验证结果:', errors);
return {
valid: errors.length === 0,
message: errors.join('、'),
errors: errors
};
},
// 显示选项卡错误
showTabError: function(tabId, message) {
if (!tabId || !message) return;
var $tabLink = $('.nav-tabs a[href="' + tabId + '"]');
if ($tabLink.length > 0 && !$tabLink.hasClass('tab-error')) {
$tabLink.addClass('tab-error');
// 添加错误图标
if ($tabLink.find('.error-icon').length === 0) {
$tabLink.append(' ');
}
// 添加提示信息
$tabLink.attr('title', message);
$tabLink.tooltip('destroy').tooltip({
placement: 'top',
title: message
});
}
},
// 清除选项卡错误
clearTabError: function(tabId) {
if (!tabId) return;
var $tabLink = $('.nav-tabs a[href="' + tabId + '"]');
if ($tabLink.length > 0) {
$tabLink.removeClass('tab-error tab-success');
$tabLink.find('.error-icon, .success-icon').remove();
$tabLink.removeAttr('title');
if ($tabLink.tooltip) {
try {
$tabLink.tooltip('destroy');
} catch (e) {
console.log('单个选项卡tooltip清理错误:', e);
}
}
}
},
// 清除所有选项卡错误
clearTabErrors: function() {
var $navTabs = $('.nav-tabs');
if ($navTabs.length > 0) {
var $tabLinks = $navTabs.find('a');
if ($tabLinks.length > 0) {
$tabLinks.removeClass('tab-error tab-success');
$tabLinks.find('.error-icon, .success-icon').remove();
$tabLinks.removeAttr('title');
if ($tabLinks.tooltip) {
try {
$tabLinks.tooltip('destroy');
} catch (e) {
console.log('tooltip清理错误:', e);
}
}
}
}
},
// 验证并标记单个选项卡状态
validateAndMarkTab: function(tabId) {
if (!tabId) return;
var that = this;
var result = null;
// 清除当前选项卡的标记
that.clearTabError(tabId);
switch(tabId) {
case '#basics':
result = that.validateBasicsTab();
break;
case '#skus':
result = that.validateSkusTab();
break;
case '#delivery':
result = that.validateDeliveryTab();
break;
case '#detail':
result = that.validateDetailTab();
break;
case '#sales':
result = that.validateSalesTab();
break;
}
if (result) {
if (!result.valid) {
that.showTabError(tabId, result.errors.join('、'));
} else {
that.showTabSuccess(tabId);
}
}
},
// 验证所有选项卡但只显示状态,不跳转
validateAllTabsForStatus: function() {
var that = this;
var tabs = ['#basics', '#skus', '#delivery', '#detail', '#sales'];
tabs.forEach(function(tabId) {
that.validateAndMarkTab(tabId);
});
},
// 显示选项卡成功状态
showTabSuccess: function(tabId) {
if (!tabId) return;
var $tabLink = $('.nav-tabs a[href="' + tabId + '"]');
if ($tabLink.length > 0) {
$tabLink.removeClass('tab-error').addClass('tab-success');
$tabLink.find('.error-icon').remove();
// 添加成功图标
if ($tabLink.find('.success-icon').length === 0) {
$tabLink.append(' ');
}
$tabLink.removeAttr('title');
if ($tabLink.tooltip) {
try {
$tabLink.tooltip('destroy');
} catch (e) {
console.log('tooltip错误:', e);
}
}
}
},
// 处理Nice-validator验证错误
handleValidationError: function(validator) {
var that = this;
var $firstInvalidField = null;
// 多种方式获取验证失败的字段
if (validator && typeof validator.getInvalidFields === 'function') {
var $invalidFields = validator.getInvalidFields();
if ($invalidFields && $invalidFields.length > 0) {
$firstInvalidField = $($invalidFields[0]);
}
}
// 如果上面方法失败,尝试查找带有错误类的字段
if (!$firstInvalidField || $firstInvalidField.length === 0) {
$firstInvalidField = $('.form-control.n-invalid, input.n-invalid, select.n-invalid, textarea.n-invalid').first();
}
// 如果还是没有,查找第一个必填但为空的字段
if (!$firstInvalidField || $firstInvalidField.length === 0) {
$firstInvalidField = $('input[data-rule*="required"]:visible').filter(function() {
return !$(this).val();
}).first();
}
if (!$firstInvalidField || $firstInvalidField.length === 0) {
$firstInvalidField = $('select[data-rule*="required"]:visible').filter(function() {
return !$(this).val();
}).first();
}
// 如果找到了错误字段
if ($firstInvalidField && $firstInvalidField.length > 0) {
var fieldName = $firstInvalidField.attr('name') || $firstInvalidField.attr('id');
var errorTab = that.getTabByFieldName(fieldName, $firstInvalidField);
console.log('找到验证错误字段:', fieldName, '对应选项卡:', errorTab);
if (errorTab) {
// 跳转到对应选项卡
var $tabLink = $('.nav-tabs a[href="' + errorTab + '"]');
if ($tabLink.length > 0) {
$tabLink.tab('show');
// 标记错误选项卡
that.showTabError(errorTab, '该选项卡有必填项未完成');
// 滚动到页面顶部
$('html, body').animate({scrollTop: 0}, 300);
// 延迟聚焦到错误字段
setTimeout(function() {
$firstInvalidField.focus();
that.highlightErrorField($firstInvalidField);
}, 500);
}
}
} else {
console.log('未找到验证错误字段,执行通用错误处理');
// 如果找不到具体的错误字段,至少显示一个通用提示
Toastr.error('请检查表单填写是否完整');
}
},
// 根据字段名获取对应的选项卡
getTabByFieldName: function(fieldName, $field) {
if (!fieldName && !$field) return '#basics';
// 根据字段名判断选项卡
if (fieldName) {
// 基础信息相关字段
if (fieldName.indexOf('type') !== -1 ||
fieldName.indexOf('goods_sn') !== -1 ||
fieldName.indexOf('title') !== -1 ||
fieldName.indexOf('category_id') !== -1 ||
fieldName.indexOf('category_ids') !== -1 ||
fieldName.indexOf('brand_id') !== -1 ||
fieldName.indexOf('image') !== -1 && fieldName.indexOf('single') === -1) {
return '#basics';
}
// 价格库存相关字段
if (fieldName.indexOf('spec_type') !== -1 ||
fieldName.indexOf('price') !== -1 ||
fieldName.indexOf('stocks') !== -1 ||
fieldName.indexOf('marketprice') !== -1 ||
fieldName.indexOf('single') !== -1) {
return '#skus';
}
// 配送设置相关字段
if (fieldName.indexOf('delivery_type') !== -1 ||
fieldName.indexOf('express') !== -1 ||
fieldName.indexOf('freight') !== -1) {
return '#delivery';
}
// 商品详情相关字段
if (fieldName.indexOf('content') !== -1 ||
fieldName.indexOf('detail') !== -1) {
return '#detail';
}
// 销售设置相关字段
if (fieldName.indexOf('stock_show_type') !== -1 ||
fieldName.indexOf('sales_show_type') !== -1 ||
fieldName.indexOf('keywords') !== -1 ||
fieldName.indexOf('description') !== -1 ||
fieldName.indexOf('status') !== -1) {
return '#sales';
}
}
// 根据字段所在的选项卡容器判断
if ($field && $field.length > 0) {
var $tabPane = $field.closest('.tab-pane');
if ($tabPane.length > 0) {
var tabId = '#' + $tabPane.attr('id');
return tabId;
}
}
// 默认返回基础信息选项卡
return '#basics';
},
// 高亮错误字段
highlightErrorField: function($field) {
if ($field && $field.length > 0) {
$field.addClass('error-highlight');
setTimeout(function() {
$field.removeClass('error-highlight');
}, 3000);
// 滚动到字段位置
var fieldOffset = $field.offset();
if (fieldOffset) {
$('html, body').animate({
scrollTop: fieldOffset.top - 100
}, 300);
}
}
},
// 验证整个表单并定位到错误选项卡
validateFormAndShowErrors: function() {
var that = this;
var firstErrorTab = null;
var errorMessage = '';
console.log('开始全面验证表单');
// 验证所有选项卡
var tabs = ['#basics', '#skus', '#delivery', '#detail', '#sales'];
tabs.forEach(function(tabId) {
that.clearTabError(tabId);
var result = null;
switch(tabId) {
case '#basics':
result = that.validateBasicsTab();
break;
case '#skus':
result = that.validateSkusTab();
break;
case '#delivery':
result = that.validateDeliveryTab();
break;
case '#detail':
result = that.validateDetailTab();
break;
case '#sales':
result = that.validateSalesTab();
break;
}
console.log('选项卡', tabId, '验证结果:', result);
if (result && !result.valid) {
that.showTabError(tabId, result.message || result.errors.join('、'));
if (!firstErrorTab) {
firstErrorTab = tabId;
errorMessage = result.message || result.errors.join('、');
}
}
});
// 如果有错误,切换到第一个错误选项卡
if (firstErrorTab) {
console.log('发现错误选项卡:', firstErrorTab, '错误信息:', errorMessage);
var $errorTab = $('.nav-tabs a[href="' + firstErrorTab + '"]');
if ($errorTab.length > 0) {
console.log('切换到错误选项卡:', firstErrorTab);
$errorTab.tab('show');
// 显示错误提示
Toastr.error(errorMessage);
// 延迟聚焦到第一个错误字段
setTimeout(function() {
that.focusFirstErrorFieldInTab(firstErrorTab);
}, 500);
}
$('html, body').animate({scrollTop: 0}, 300);
return false;
}
console.log('表单验证通过');
return true;
},
// 聚焦到指定选项卡的第一个错误字段
focusFirstErrorFieldInTab: function(tabId) {
var $tabPane = $(tabId);
if ($tabPane.length === 0) return;
var $errorField = null;
// 查找第一个验证失败的字段
$errorField = $tabPane.find('input[data-rule]:invalid, select[data-rule]:invalid, textarea[data-rule]:invalid').first();
// 如果没有找到invalid字段,查找必填但为空的字段
if (!$errorField || $errorField.length === 0) {
$errorField = $tabPane.find('input[data-rule*="required"]:visible').filter(function() {
return !$(this).val();
}).first();
}
if (!$errorField || $errorField.length === 0) {
$errorField = $tabPane.find('select[data-rule*="required"]:visible').filter(function() {
return !$(this).val();
}).first();
}
// 聚焦并高亮错误字段
if ($errorField && $errorField.length > 0) {
$errorField.focus();
this.highlightErrorField($errorField);
}
},
// 初始化上架时间和下架时间控制
initOnlineOfflineControl: function() {
// 上架时间类型切换事件
$('input[name="row[online_type]"]').change(function() {
var value = $(this).val();
// 当类型为定时上架(3)时,显示上架时间选择
if (value == '3') {
$('#scheduled-online-time').show();
} else {
$('#scheduled-online-time').hide();
}
// 当类型为立即上架(1)或定时上架(3)时,显示定时下架选项
if (value == '1' || value == '3') {
$('#offline-time-setting').show();
} else {
$('#offline-time-setting').hide();
}
});
// 初始执行一次,设置默认状态
$('input[name="row[online_type]"]:checked').trigger('change');
// 定时下架复选框切换事件
$('#c-is_auto_offline').change(function() {
if ($(this).is(':checked')) {
$('#scheduled-offline-time').show();
} else {
$('#scheduled-offline-time').hide();
}
});
// 初始执行一次,检查定时下架复选框状态
if ($('#c-is_auto_offline').is(':checked')) {
$('#scheduled-offline-time').show();
} else {
$('#scheduled-offline-time').hide();
}
},
// 初始化商品详情预览功能
initContentPreview: function() {
// 设置定时刷新预览
var previewTimer = null;
var lastContent = "";
// 监听标签页切换,确保切换到详情标签页时刷新预览
$('a[href="#detail"]').on('shown.bs.tab', function (e) {
updatePreview();
// 设置定时器,每隔1秒检查内容是否有变化
if (previewTimer === null) {
previewTimer = setInterval(function() {
checkContentChange();
}, 1000);
}
});
// 离开详情标签页时清除定时器
$('a').not('a[href="#detail"]').on('shown.bs.tab', function (e) {
if (previewTimer) {
clearInterval(previewTimer);
previewTimer = null;
}
});
// 检查内容变化
function checkContentChange() {
var editor = $("#c-content").data("nkeditor");
if (!editor) return;
var content = editor.html();
if (content !== lastContent) {
lastContent = content;
updatePreview();
}
}
// 更新预览内容
function updatePreview() {
// 获取编辑器实例
var editor = $("#c-content").data("nkeditor");
if (!editor) return;
// 获取编辑器内容
var content = editor.html();
// 更新预览区域
$('#content-preview').html(content || '暂无内容
');
// 调整预览区域的高度
adjustPreviewHeight();
}
// 调整预览区域高度,使其与编辑器一致
function adjustPreviewHeight() {
var $editorContainer = $('.ke-container');
if ($editorContainer.length > 0) {
var editorHeight = $editorContainer.height();
$('#content-preview').css('height', editorHeight - 40 + 'px');
}
}
// 初始预览
setTimeout(function() {
adjustPreviewHeight();
updatePreview();
}, 1000);
},
// 格式化SKU规格属性显示
formatSkuAttr: function(skuAttr) {
if (!skuAttr) {
return '';
}
try {
// 尝试解析JSON格式
var attrs = JSON.parse(skuAttr);
if (Array.isArray(attrs)) {
var formatted = [];
attrs.forEach(function(attr) {
if (attr.name && attr.value) {
formatted.push(attr.name + ': ' + attr.value);
}
});
return formatted.join(' | ');
}
} catch (e) {
// 兼容旧的字符串格式:规格名:规格值,规格名:规格值
if (skuAttr.indexOf(':') !== -1) {
var attrs = skuAttr.split(',');
var formatted = [];
attrs.forEach(function(attr) {
if (attr.indexOf(':') !== -1) {
var parts = attr.split(':');
if (parts.length >= 2) {
formatted.push(parts[0].trim() + ': ' + parts.slice(1).join(':').trim());
}
}
});
return formatted.join(' | ');
}
}
return skuAttr;
},
// 显示表单错误并定位到对应选项卡
showFormError: function(ret) {
var message = ret.msg || '操作失败';
var errorTab = this.getErrorTab(message);
// 如果能定位到具体选项卡,显示错误
if (errorTab) {
var $tabLink = $('.nav-tabs a[href="' + errorTab + '"]');
if ($tabLink.length > 0 && !$tabLink.hasClass('tab-error')) {
$tabLink.addClass('tab-error');
if ($tabLink.find('.error-icon').length === 0) {
$tabLink.append(' ');
}
$tabLink.attr('title', message);
if ($tabLink.tooltip) {
try {
$tabLink.tooltip('destroy').tooltip({
placement: 'top',
title: message
});
} catch (e) {
console.log('tooltip错误:', e);
}
}
}
}
// 显示错误提示
Toastr.error(message);
},
// 跳转到有错误的选项卡
jumpToErrorTab: function(ret) {
var that = this;
var message = ret.msg || '操作失败';
var errorTab = null;
// 首先尝试从错误信息判断选项卡
errorTab = this.getErrorTab(message);
// 如果无法从错误信息判断,则进行全面验证
if (!errorTab) {
errorTab = this.findFirstErrorTab();
}
// 跳转到错误选项卡
if (errorTab) {
var $tabLink = $('.nav-tabs a[href="' + errorTab + '"]');
if ($tabLink.length > 0) {
// 切换到对应选项卡
$tabLink.tab('show');
// 滚动到页面顶部
$('html, body').animate({scrollTop: 0}, 300);
// 延迟聚焦到第一个错误字段
setTimeout(function() {
that.focusFirstErrorField(errorTab);
}, 500);
}
}
},
// 根据错误信息获取对应的选项卡
getErrorTab: function(message) {
if (!message) return null;
// 基础信息相关错误
if (message.indexOf('商品类型') !== -1 ||
message.indexOf('商品编码') !== -1 ||
message.indexOf('商品标题') !== -1 ||
message.indexOf('商品分类') !== -1 ||
message.indexOf('主图') !== -1 ||
message.indexOf('图片') !== -1 ||
message.indexOf('品牌') !== -1) {
return '#basics';
}
// 价格库存相关错误
if (message.indexOf('价格') !== -1 ||
message.indexOf('库存') !== -1 ||
message.indexOf('SKU') !== -1 ||
message.indexOf('规格') !== -1 ||
message.indexOf('销售价') !== -1 ||
message.indexOf('市场价') !== -1) {
return '#skus';
}
// 配送设置相关错误
if (message.indexOf('配送') !== -1 ||
message.indexOf('运费') !== -1 ||
message.indexOf('快递') !== -1 ||
message.indexOf('运费模板') !== -1) {
return '#delivery';
}
// 商品详情相关错误
if (message.indexOf('详情') !== -1 ||
message.indexOf('内容') !== -1) {
return '#detail';
}
// 销售设置相关错误
if (message.indexOf('库存显示') !== -1 ||
message.indexOf('销量显示') !== -1 ||
message.indexOf('关键词') !== -1 ||
message.indexOf('描述') !== -1) {
return '#sales';
}
return null;
},
// 查找第一个有错误的选项卡
findFirstErrorTab: function() {
var tabs = ['#basics', '#skus', '#delivery', '#detail', '#sales'];
console.log('开始查找第一个有错误的选项卡');
for (var i = 0; i < tabs.length; i++) {
var tabId = tabs[i];
var result = null;
console.log('检查选项卡:', tabId);
try {
switch(tabId) {
case '#basics':
result = this.validateBasicsTab();
break;
case '#skus':
result = this.validateSkusTab();
break;
case '#delivery':
result = this.validateDeliveryTab();
break;
case '#detail':
result = this.validateDetailTab();
break;
case '#sales':
result = this.validateSalesTab();
break;
}
console.log('选项卡 ' + tabId + ' 验证结果:', result);
if (result && !result.valid) {
console.log('找到第一个错误选项卡:', tabId, '错误:', result.errors);
return tabId;
}
} catch (e) {
console.error('验证选项卡 ' + tabId + ' 时出错:', e);
}
}
console.log('没有找到错误选项卡');
return null;
},
// 聚焦到第一个错误字段
focusFirstErrorField: function(tabId) {
var $activeTabPane = $(tabId);
if ($activeTabPane.length === 0) return;
// 查找第一个有错误的必填字段
var $errorField = null;
switch(tabId) {
case '#basics':
// 按优先级查找错误字段
$errorField = $activeTabPane.find('#c-goods_sn:invalid, #c-goods_sn[value=""]').first();
if ($errorField.length === 0) {
$errorField = $activeTabPane.find('#c-title:invalid, #c-title[value=""]').first();
}
if ($errorField.length === 0) {
// 对于多选的selectpage控件,需要特殊处理
var $categoryField = $activeTabPane.find('#c-category_id, #c-category_ids').first();
if ($categoryField.length > 0) {
var categoryVal = $categoryField.val();
if (Controller.isMultiSelectEmpty(categoryVal)) {
$errorField = $categoryField;
}
}
}
if ($errorField.length === 0) {
$errorField = $activeTabPane.find('#c-image:invalid, #c-image[value=""]').first();
}
break;
case '#skus':
// 检查规格类型
var specType = $('input[name="row[spec_type]"]:checked').val();
if (specType == '0') {
$errorField = $activeTabPane.find('#c-price:invalid, #c-price[value=""]').first();
if ($errorField.length === 0) {
$errorField = $activeTabPane.find('#c-stocks:invalid, #c-stocks[value=""]').first();
}
}
break;
case '#delivery':
$errorField = $activeTabPane.find('#c-express_template_id:invalid, #c-express_template_id[value=""]').first();
break;
case '#sales':
$errorField = $activeTabPane.find('input[name="row[stock_show_type]"]:invalid').first();
if ($errorField.length === 0) {
$errorField = $activeTabPane.find('input[name="row[sales_show_type]"]:invalid').first();
}
break;
}
// 如果没有找到特定的错误字段,查找第一个有data-rule的空字段
if (!$errorField || $errorField.length === 0) {
$errorField = $activeTabPane.find('input[data-rule]:invalid, input[data-rule][value=""], select[data-rule]:invalid, select[data-rule][value=""], textarea[data-rule]:invalid, textarea[data-rule][value=""]').first();
}
// 聚焦并高亮错误字段
if ($errorField && $errorField.length > 0) {
$errorField.focus();
// 添加错误高亮效果
$errorField.addClass('error-highlight');
setTimeout(function() {
$errorField.removeClass('error-highlight');
}, 2000);
// 滚动到字段位置
var fieldOffset = $errorField.offset();
if (fieldOffset) {
$('html, body').animate({
scrollTop: fieldOffset.top - 100
}, 300);
}
}
},
// 验证基础信息选项卡
validateBasicsTab: function() {
var isValid = true;
var errors = [];
console.log('验证基础信息选项卡');
// 检查商品类型
if (!$('input[name="row[type]"]:checked').length) {
isValid = false;
errors.push('请选择商品类型');
}
// 检查商品编码
var $goodsSn = $('#c-goods_sn');
var goodsSnVal = $goodsSn.val();
console.log('商品编码值:', goodsSnVal);
if ($goodsSn.length > 0 && $goodsSn.attr('data-rule') && $goodsSn.attr('data-rule').indexOf('required') !== -1) {
if (!goodsSnVal || goodsSnVal.trim() === '') {
isValid = false;
errors.push('商品编码不能为空');
}
}
// 检查商品标题
var $title = $('#c-title');
var titleVal = $title.val();
console.log('商品标题值:', titleVal);
if ($title.length > 0 && $title.attr('data-rule') && $title.attr('data-rule').indexOf('required') !== -1) {
if (!titleVal || titleVal.trim() === '') {
isValid = false;
errors.push('商品标题不能为空');
}
}
// 检查分类 - 多选控件(兼容不同页面的字段ID)
var $categoryId = $('#c-category_id, #c-category_ids').first();
var categoryVal = $categoryId.val();
console.log('商品分类值:', categoryVal);
if ($categoryId.length > 0 && $categoryId.attr('data-rule') && $categoryId.attr('data-rule').indexOf('required') !== -1) {
if (Controller.isMultiSelectEmpty(categoryVal)) {
isValid = false;
errors.push('商品分类不能为空');
console.log('商品分类验证失败');
}
}
// 检查主图
var $image = $('#c-image');
var imageVal = $image.val();
console.log('主图值:', imageVal);
if ($image.length > 0 && $image.attr('data-rule') && $image.attr('data-rule').indexOf('required') !== -1) {
if (!imageVal || imageVal.trim() === '') {
isValid = false;
errors.push('商品主图不能为空');
}
}
// 检查轮播图
var $images = $('#c-images');
var imagesVal = $images.val();
console.log('轮播图值:', imagesVal);
if ($images.length > 0 && $images.attr('data-rule') && $images.attr('data-rule').indexOf('required') !== -1) {
if (!imagesVal || imagesVal.trim() === '') {
isValid = false;
errors.push('商品轮播图不能为空');
}
}
console.log('基础信息验证结果:', {valid: isValid, errors: errors});
return {
valid: isValid,
errors: errors
};
},
// 验证价格库存选项卡
validateSkusTab: function() {
var isValid = true;
var errors = [];
// 检查规格类型
var specType = $('input[name="row[spec_type]"]:checked').val();
console.log('验证价格库存选项卡, 规格类型:', specType);
if (specType == '0') {
// 单规格验证
var $price = $('#c-price');
var priceVal = $price.val();
console.log('价格字段值:', priceVal);
if (!priceVal || priceVal.trim() === '' || parseFloat(priceVal) <= 0) {
isValid = false;
errors.push('销售价必须大于0');
}
var $stocks = $('#c-stocks');
var stocksVal = $stocks.val();
console.log('库存字段值:', stocksVal);
if (!stocksVal || stocksVal.trim() === '' || parseInt(stocksVal) <= 0) {
isValid = false;
errors.push('库存必须大于0');
}
} else if (specType == '1') {
// 多规格验证
if (typeof vm === 'undefined' || !vm || !vm.specList || vm.specList.length === 0) {
isValid = false;
errors.push('请设置商品规格');
} else {
// 检查是否有有效的规格组合
if (!vm.tableData || vm.tableData.length === 0) {
isValid = false;
errors.push('请设置规格组合数据');
} else {
// 检查每个有效的SKU是否有正确的价格和库存
var hasValidSku = false;
var validSkuCount = 0;
console.log('第二次验证: 检查SKU数据, tableData长度:', vm.tableData.length);
for (var i = 0; i < vm.tableData.length; i++) {
var sku = vm.tableData[i];
console.log('第二次验证: 检查SKU[' + i + ']:', {
status: sku.status,
price: sku.price,
stocks: sku.stocks
});
// 只检查状态为显示的SKU
var isVisible = (sku.status === 1 || sku.status === '1' || sku.status === true);
console.log('第二次验证: SKU[' + i + '] 显示状态:', sku.status, '可见:', isVisible);
if (isVisible) {
var price = parseFloat(sku.price);
var stocks = parseInt(sku.stocks);
console.log('第二次验证: SKU[' + i + '] 检查通过, price:', price, 'stocks:', stocks);
hasValidSku = true;
validSkuCount++;
// 验证价格必须大于0
if (!price || price <= 0) {
isValid = false;
errors.push('SKU销售价必须大于0');
console.log('第二次验证: SKU[' + i + ']销售价验证失败:', price);
break;
}
// 验证库存
if (isNaN(stocks) || stocks <= 0) {
isValid = false;
errors.push('SKU库存必须大于0');
console.log('第二次验证: SKU[' + i + ']库存验证失败:', stocks);
break;
}
}
}
console.log('第二次验证: 有效SKU数量:', validSkuCount);
if (!hasValidSku) {
isValid = false;
errors.push('请至少设置一个有效的SKU');
console.log('第二次验证: 没有有效的SKU');
}
}
}
} else {
// 如果没有选择规格类型
isValid = false;
errors.push('请选择规格类型');
}
console.log('价格库存验证结果:', {valid: isValid, errors: errors});
return {
valid: isValid,
errors: errors
};
},
// 验证配送设置选项卡
validateDeliveryTab: function() {
var isValid = true;
var errors = [];
// 检查配送方式
var deliveryType = $('input[name="row[delivery_type]"]:checked').val();
if (deliveryType === 'EXPRESS') {
// 如果选择快递配送,检查运费设置
var expressType = $('input[name="row[express_type]"]:checked').val();
if (expressType === '3') {
// 使用运费模板
var $templateId = $('#c-express_template_id');
if ($templateId.length > 0 && !$templateId.val()) {
isValid = false;
errors.push('请选择运费模板');
}
} else if (expressType === '2') {
// 固定运费
var $expressPrice = $('#c-express_price');
if ($expressPrice.length > 0 && (!$expressPrice.val() || parseFloat($expressPrice.val()) < 0)) {
isValid = false;
errors.push('请设置正确的运费');
}
}
}
return {
valid: isValid,
errors: errors
};
},
// 验证商品详情选项卡
validateDetailTab: function() {
// 详情一般不做必填验证,返回有效
return {
valid: true,
errors: []
};
},
// 验证销售设置选项卡
validateSalesTab: function() {
var isValid = true;
var errors = [];
// 检查库存显示类型
var stockShowType = $('input[name="row[stock_show_type]"]:checked').val();
if (!stockShowType) {
isValid = false;
errors.push('请选择库存显示方式');
}
// 检查销量显示类型
var salesShowType = $('input[name="row[sales_show_type]"]:checked').val();
if (!salesShowType) {
isValid = false;
errors.push('请选择销量显示方式');
}
return {
valid: isValid,
errors: errors
};
},
api: {
// 初始化规格类型控制
initSpecTypeControl: function() {
// 监听规格类型切换
$('input[name="row[spec_type]"]').off('change.spectype').on('change.spectype', function() {
var specType = $(this).val();
console.log('规格类型切换为:', specType);
// 使用FastAdmin的Favisible系统自动控制显示隐藏
$(document).trigger('fa.event.favisible');
// 如果切换到单规格,清空多规格数据(可选)
if (specType == '0' && typeof vm !== 'undefined' && vm) {
console.log('切换到单规格,清空多规格数据');
// vm.specList = [];
// vm.tableData = [];
}
// 如果切换到多规格,确保Vue组件已初始化
if (specType == '1' && typeof vm !== 'undefined' && vm) {
console.log('切换到多规格');
var $multiSpecForm = $('#multi-spec-form');
if ($multiSpecForm.length > 0 && !$multiSpecForm.is(':visible')) {
setTimeout(function() {
$(document).trigger('fa.event.favisible');
}, 100);
}
}
});
// 初始触发一次,确保默认状态正确
$('input[name="row[spec_type]"]:checked').trigger('change.spectype');
},
bindevent: function () {
$(document).on("click", ".btn-legal", function (a) {
Fast.api.ajax({
url: "shop/ajax/check_content_islegal",
data: {content: $("#c-content").val()}
}, function (data, ret) {
}, function (data, ret) {
if ($.isArray(data)) {
Layer.alert(__('Banned words') + ":" + data.join(","));
}
});
});
$(document).on("click", ".btn-keywords", function (a) {
Fast.api.ajax({
url: "shop/ajax/get_content_keywords",
data: {title: $("#c-title").val(), content: $("#c-content").val()}
}, function (data, ret) {
$("#c-keywords").val(data.keywords);
$("#c-description").val(data.description);
});
});
// 绑定FastAdmin表单验证事件
var $form = $("form[role=form]");
// 监听提交按钮点击事件,在表单验证前进行自定义验证
$form.find('button[type="submit"], input[type="submit"]').off('click.tabvalidation').on('click.tabvalidation', function(e) {
console.log('提交按钮被点击,开始验证');
// 进行自定义验证
if (!Controller.validateFormAndShowErrors()) {
console.log('自定义验证失败,阻止表单提交');
e.preventDefault();
e.stopPropagation();
return false;
}
console.log('自定义验证通过,继续表单提交流程');
});
// 使用FastAdmin标准方式绑定表单事件
Form.api.bindevent($form, function (data, ret) {
// 提交成功回调
Controller.clearTabErrors();
}, function (data, ret) {
// 提交失败回调
Controller.showFormError(ret);
Controller.jumpToErrorTab(ret);
}, function (success, error) {
// 提交前验证和数据处理
console.log('开始提交表单数据');
// 清除所有选项卡错误标记
Controller.clearTabErrors();
// 进行表单验证,如果失败则跳转到错误选项卡
var validator = $form.data('validator');
if (validator) {
console.log('检查表单验证状态');
// 手动触发验证
var isValid = validator.isFormValid();
console.log('表单验证结果:', isValid);
if (!isValid) {
console.log('表单验证失败,开始处理错误');
Controller.handleValidationError(validator);
return false;
}
} else {
console.log('validator不存在,使用自定义验证');
// 如果validator不存在,使用我们的自定义验证
if (!Controller.validateFormAndShowErrors()) {
console.log('自定义验证失败');
return false;
}
}
let skus = '[]', spec = '[]';
var specType = $('input[name="row[spec_type]"]:checked').val();
console.log('当前规格类型:', specType);
console.log('vm对象:', typeof vm !== 'undefined' ? vm : 'undefined');
if (specType == '1') {
// 多规格处理
if (typeof vm !== 'undefined' && vm && vm.tableData && vm.tableData.length > 0) {
console.log('处理多规格商品, tableData长度:', vm.tableData.length);
try {
// 不需要特殊处理,直接传输所有数据
// 后端会根据status字段判断SKU是否有效
skus = JSON.stringify(vm.tableData);
spec = JSON.stringify(vm.specList || []);
console.log('多规格数据处理完成');
console.log('规格数据 (spec):', vm.specList);
console.log('SKU数据 (skus):', vm.tableData);
console.log('规格数据JSON:', spec);
// 检查规格值中是否包含图片
vm.specList.forEach(function(spec, specIndex) {
if (spec.value && spec.value.length > 0) {
spec.value.forEach(function(value, valueIndex) {
if (value.image) {
console.log('规格[' + specIndex + ']值[' + valueIndex + ']包含图片:', value.image);
}
});
}
});
} catch (e) {
console.log('多规格处理出错:', e);
Toastr.error('多规格数据处理失败');
return false;
}
} else {
console.log('多规格数据不完整');
Toastr.error('请设置完整的多规格数据');
return false;
}
} else {
// 单规格处理 - 统一使用skus和spec格式
console.log('处理单规格商品');
var singleSku = {
sku_sn: $('#c-sku-sn').val() || $('#c-goods_sn').val() || '',
price: parseFloat($('#c-price').val()) || 0,
lineation_price: parseFloat($('#c-lineation_price').val()) || 0,
cost_price: parseFloat($('#c-cost_price').val()) || 0,
stocks: parseInt($('#c-stocks').val()) || 0,
weight: parseFloat($('#c-weight').val()) || 0,
volume: parseFloat($('#c-volume').val()) || 0,
image: $('#c-single-image').val() || '',
sales: 0,
status: 1,
is_default: 1,
skus: []
};
skus = JSON.stringify([singleSku]);
spec = JSON.stringify([]);
console.log('单规格数据处理完成', singleSku);
}
//绑定商品属性
let html = `
`;
this.find('#goods-sku').html(html);
console.log(html);
//提交表单
Form.api.submit(this, success, error);
return false;
});
require(['backend/shop/card'], function (Card) {
Card.api.bindcardevent();
});
},
bindUpload: function () {
if ($('.goods-sku-table table td.td-img button.faupload:not([initialized])').length === 0) {
return;
}
clearTimeout(si);
si = setTimeout(function () {
let doms = $('.goods-sku-table table td.td-img').toArray();
function uploadButtonTask(deadline) {
while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && doms.length > 0) {
bindEvent();
}
if (doms.length > 0)
requestIdleCallback(uploadButtonTask);
}
function bindEvent() {
var dom = doms.shift();
if (dom) {
var $elements = $(".faselect,.fachoose", dom);
if ($elements && $elements.length > 0) {
$elements.off('click');
}
Form.events.plupload(dom);
Form.events.faselect(dom);
}
}
requestIdleCallback(uploadButtonTask, {timeout: 1000});
}, 250);
},
add_sku: function () {
//移除属性的
$('.td-img').find('.faupload').removeAttr('initialized');
require(['vue'], function (Vue) {
vm = new Vue({
el: '#vue-app',
computed: {
specValueText() {
return (skus, k) => {
return !skus || typeof skus[k] == 'undefined' ? '' : skus[k];
}
},
contentHtml() {
return field => {
return ``;
}
}
},
watch: {
specList: {
handler: function (val) {
this.renderTableData(val);
// 延迟绑定上传功能,确保DOM更新完成
var that = this;
that.$nextTick(function() {
Controller.api.bindSpecValueUpload();
Controller.api.rebindMultipleEdit();
// 重新绑定规格值上传按钮
setTimeout(function() {
Controller.api.bindUploadButtons();
// 更新图片预览
that.updateSpecImagePreviews();
}, 300);
});
},
deep: true
}
},
data() {
return {
spec_name: '',
specList: [],
tableData: [],
result: [],
skus: [], //
defaultSpecIndex: 0 // 默认规格索引
}
},
mounted() {
let that = this;
that.init();
// 延迟初始化规格类型切换,确保DOM完全渲染
setTimeout(function() {
Controller.api.initSpecTypeControl();
// 初始绑定规格值上传功能
Controller.api.bindSpecValueUpload();
// 如果是编辑模式且是多规格商品,确保多规格表单显示
if (Config.goods && Config.goods.spec_type == '1') {
console.log('编辑模式:显示多规格表单');
var $multiSpecForm = $('#multi-spec-form');
if ($multiSpecForm.length > 0) {
$multiSpecForm.show();
console.log('多规格表单已显示');
}
}
}, 100);
//批量设置
this.$nextTick(function () {
$('body').on('click', function (e) {
if (!$(e.target).hasClass('multiple-edit') &&
$(e.target).parents('.multiple-edit').length === 0 &&
$(e.target).parents('.popover.in').length === 0) {
$('.multiple-edit').popover('hide');
}
});
$(".multiple-edit").popover({
sanitize: false,
container: "body",
html: true,
placement: "top",
trigger: 'manual'
}).on('click', function (e) {
$(".popover").hide();
$(this).popover('show');
});
$(document).on('click', '.sku-confirm', function () {
let value = $(this).parent().prev().val().trim();
let field = $(this).data('field');
if (field != 'sku_sn' && Number.isNaN(parseFloat(value))) {
Toastr.error('请输入数字');
return;
}
for (let [index] of that.tableData.entries()) {
that.$set(that.tableData[index], field, value);
}
});
require(['selectpage'], function () {
$('.selectpage', $('.spec-template')).selectPage({
eAjaxSuccess: function (data) {
data.totalRow = data.total;
return data;
},
eSelect: function (row) {
let spec_names = row.spec_names.split(';');
let spec_values = row.spec_values.split(';');
let list = [];
for (let [i, v] of spec_names.entries()) {
// 转换规格模板数据为新格式
let valueList = spec_values[i].split(',').map(val => ({
name: val,
image: '',
description: ''
}));
list.push({
name: v,
type: 'basic', // 默认为基础规格
value: valueList
});
}
that.tableData = [];
that.skus = [];
setTimeout(function () {
that.specList = list;
}, 100);
}
});
});
})
},
methods: {
init() {
console.log('Vue组件初始化开始');
console.log('Config数据:', Config);
let skus = [];
if (Config.goods_skus && Config.goods_skus.length) {
console.log('发现商品SKU数据,数量:', Config.goods_skus.length);
console.log('完整SKU数据:', Config.goods_skus);
// 如果是多规格商品,解析规格数据
if (Config.goods && Config.goods.spec_type == '1') {
console.log('初始化多规格数据');
let specList = [];
let specName = {};
for (let item of Config.goods_skus) {
console.log('处理SKU项:', item);
if (item.sku_attr) {
console.log('SKU属性字符串:', item.sku_attr);
let sku_attr = item.sku_attr.split(',');
console.log('分割后的属性数组:', sku_attr);
let attr = [];
for (let res of sku_attr) {
let sku = res.split(':');
console.log('属性键值对:', sku);
if (sku.length >= 2) {
attr.push(sku[1]);
//属性名
if (!specName[sku[0]]) {
specName[sku[0]] = [];
}
if (!specName[sku[0]].includes(sku[1])) {
specName[sku[0]].push(sku[1]);
}
} else {
console.warn('无效的属性格式:', res);
}
}
// 使用字符串作为键,与renderTableData中的查找方式一致
let attrKey = attr.join(',');
skus[attrKey] = item;
console.log('SKU映射:', attrKey, '->', item);
} else {
console.warn('SKU缺少sku_attr字段:', item);
}
}
console.log('解析完成的规格名称映射:', specName);
// 构建规格值映射表(从数据库获取的完整数据)
let specValueMap = {};
if (Config.spec_values && Config.spec_values.length > 0) {
console.log('发现规格值数据:', Config.spec_values);
console.log('规格值数据类型:', typeof Config.spec_values);
console.log('规格值数据结构样例:', Config.spec_values[0]);
Config.spec_values.forEach(function(item) {
if (!specValueMap[item.spec_name]) {
specValueMap[item.spec_name] = {};
}
specValueMap[item.spec_name][item.value] = {
name: item.value,
image: item.image || '',
description: item.description || ''
};
});
console.log('规格值映射表:', specValueMap);
} else {
console.log('没有发现规格值数据,使用默认处理方式');
console.log('Config.spec_values:', Config.spec_values);
}
for (let i in specName) {
// 转换旧格式数据为新格式,优先使用数据库中的完整数据
let valueList = specName[i].map(val => {
if (typeof val === 'string') {
// 从映射表中查找完整数据,如果没有则使用默认值
if (specValueMap[i] && specValueMap[i][val]) {
console.log('找到规格值完整数据:', i, val, specValueMap[i][val]);
return {
name: specValueMap[i][val].name,
image: specValueMap[i][val].image || '',
description: specValueMap[i][val].description || ''
};
} else {
console.log('使用默认规格值数据:', i, val);
return {
name: val,
image: '',
description: ''
};
}
}
// 如果已经是对象格式,确保结构完整
return {
name: val.name || val,
image: val.image || '',
description: val.description || ''
};
});
specList.push({
name: i,
type: 'basic', // 默认为基础规格
value: valueList
});
}
this.skus = skus;
this.specList = specList;
console.log('多规格初始化完成,规格数量:', specList.length);
console.log('规格列表:', specList);
// 延迟触发数据渲染,确保DOM已准备好
this.$nextTick(() => {
console.log('Vue nextTick: 准备渲染多规格表格数据');
if (this.specList.length > 0) {
this.renderTableData(this.specList);
// 在数据渲染完成后,更新规格值图片预览
setTimeout(() => {
this.updateSpecImagePreviews();
}, 500);
}
});
}
}
console.log('Vue组件初始化完成');
},
addSpec() {
if (!this.spec_name.trim()) {
Toastr.error('请输入规格名称');
return;
}
if (this.specList.some(item => item.name == this.spec_name)) {
Toastr.error('已存在规格名称');
return;
}
this.specList.push({
name: this.spec_name,
type: 'basic', // 默认为基础规格
value: [{
name: '',
image: '',
description: ''
}]
});
this.spec_name = '';
},
showAddSpecForm() {
// 添加新的规格
this.specList.push({
name: '',
type: 'basic', // 默认为基础规格
value: [{
name: '',
image: '',
description: ''
}]
});
},
addSpecValue(key) {
this.specList[key].value.push({
name: '',
image: '',
description: ''
});
// 重新绑定上传功能
this.$nextTick(function() {
setTimeout(function() {
Controller.api.bindUploadButtons();
}, 100);
});
},
removeSpecValue(key, index) {
this.specList[key].value.splice(index, 1);
},
//渲染表格数据
renderTableData(list) {
// 判断是否为编辑模式
const isEditMode = Config.goods && Config.goods.id;
// 统一的默认值 - 新增模式使用固定默认值
const defaultValues = {
goods_sn: $('#c-goods_sn').val() || '',
price: '0.01',
lineation_price: '0.00',
cost_price: '0.00',
weight: '0.00',
volume: '0.00',
stocks: '1'
};
let columns = [];
this.result = [];
this.resetSpec(list, 0);
console.log('渲染表格数据,模式:', isEditMode ? '编辑' : '新增');
console.log('固定默认值:', defaultValues);
console.log('SKU数据映射:', this.skus);
//渲染表格数据
this.result.forEach((item, index) => {
let su = this.skus[item];
console.log('处理规格组合[' + index + ']:', item, '对应SKU数据:', su);
let row;
if (isEditMode && su) {
// 编辑模式:完全使用后台SKU数据
console.log('编辑模式:使用后台SKU数据:', su);
row = {
skus: item ? item.split(',') : [],
sku_sn: su.sku_sn || '',
image: su.image || '',
price: parseFloat(su.price) || 0,
lineation_price: parseFloat(su.lineation_price) || 0,
cost_price: parseFloat(su.cost_price) || 0,
weight: parseFloat(su.weight) || 0,
volume: parseFloat(su.volume) || 0,
stocks: parseInt(su.stocks) || 0,
sales: parseInt(su.sales) || 0,
status: su.status !== undefined ? parseInt(su.status) : 1,
is_default: su.is_default !== undefined ? parseInt(su.is_default) : 0
};
console.log('编辑模式最终行数据:', row);
} else {
// 新增模式或编辑模式下没有对应SKU数据:使用固定默认值
console.log('新增模式:使用固定默认值');
row = {
skus: item ? item.split(',') : [],
sku_sn: defaultValues.goods_sn,
image: '',
price: defaultValues.price,
lineation_price: defaultValues.lineation_price,
cost_price: defaultValues.cost_price,
weight: defaultValues.weight,
volume: defaultValues.volume,
stocks: defaultValues.stocks,
sales: 0,
status: 1, // 默认显示状态
is_default: index === 0 ? 1 : 0 // 第一个SKU默认为默认规格
};
console.log('新增模式最终行数据:', row);
}
// 保留已有的用户修改数据(仅在新增模式下)
if (!isEditMode) {
let old = this.tableData[index];
if (old) {
console.log('新增模式:保留用户修改的数据:', old);
for (let i in row) {
// 只有在新值为空且旧值不为空时才使用旧值
if ((row[i] === '' || row[i] === 0 || row[i] === '0.00') && old[i]) {
row[i] = old[i];
}
}
}
}
columns.push(row);
});
this.tableData = columns;
console.log('最终表格数据:', this.tableData);
// 在编辑模式下,设置默认规格的索引
if (isEditMode) {
this.defaultSpecIndex = this.tableData.findIndex(item => item.is_default === 1);
console.log('设置默认规格索引:', this.defaultSpecIndex);
}
//更新dom,加载事件
this.$nextTick(function () {
Controller.api.bindUpload();
Controller.api.bindSpecValueUpload();
// 重新绑定批量编辑popover
Controller.api.rebindMultipleEdit();
});
},
removeSpec(key) {
this.specList.splice(key, 1);
},
// 更新规格值图片预览
updateSpecImagePreviews() {
console.log('开始更新规格值图片预览');
this.specList.forEach((spec, specKey) => {
if (spec.value && spec.value.length > 0) {
spec.value.forEach((value, valueIndex) => {
if (value.image) {
const previewId = 'p-spec-image-' + specKey + '-' + valueIndex;
const $preview = $('#' + previewId);
if ($preview.length > 0) {
const img = '
';
$preview.html(img);
console.log('更新规格值图片预览:', previewId, value.image);
}
}
});
}
});
},
//组合规格属性
resetSpec(list, index) {
if (list[index] != undefined) {
let value = list[index].value.map(item => typeof item === 'string' ? item : item.name);
if (!index) {
this.result = value;
} else {
let res = [];
for (let i of this.result) {
for (let j of value) {
res.push(i + ',' + j);
}
}
if (res.length) {
this.result = res;
}
}
this.resetSpec(list, ++index);
}
},
}
});
});
//情况属性
$(document).on('click', '.btn-del-sku', function () {
vm.specList = [];
vm.tableData = [];
});
//监听图片变化赋值
$(document).on('change', '.sku-images', function () {
let index = $(this).data('index');
let value = $(this).val();
vm.tableData[index].image = value;
});
},
// 重新绑定批量编辑功能
rebindMultipleEdit: function() {
var $multipleEdit = $(".multiple-edit");
if (!$multipleEdit || $multipleEdit.length === 0) {
return;
}
// 销毁之前的popover
$multipleEdit.popover('destroy');
// 重新初始化popover
$multipleEdit.popover({
sanitize: false,
container: "body",
html: true,
placement: "top",
trigger: 'manual'
});
if ($multipleEdit && $multipleEdit.length > 0) {
$multipleEdit.off('click.multiple').on('click.multiple', function (e) {
$(".popover").hide();
$(this).popover('show');
});
}
},
// 绑定规格值图片上传功能
bindSpecValueUpload: function() {
// 检查是否存在规格相关的元素
if ($('.spec-image-input').length === 0) {
return;
}
// 监听规格值图片变化
$(document).off('change.specvalue', '.spec-image-input');
$(document).on('change.specvalue', '.spec-image-input', function () {
var specKey = parseInt($(this).data('spec-key'));
var valueIndex = parseInt($(this).data('value-index'));
var imageUrl = $(this).val();
if (vm && vm.specList && vm.specList[specKey] && vm.specList[specKey].value[valueIndex]) {
vm.$set(vm.specList[specKey].value[valueIndex], 'image', imageUrl);
console.log('规格值图片已更新:', {
specKey: specKey,
valueIndex: valueIndex,
imageUrl: imageUrl,
specData: vm.specList[specKey].value[valueIndex]
});
} else {
console.warn('无法更新规格值图片,数据结构不正确:', {
specKey: specKey,
valueIndex: valueIndex,
hasVm: !!vm,
hasSpecList: !!(vm && vm.specList),
hasSpec: !!(vm && vm.specList && vm.specList[specKey]),
hasValue: !!(vm && vm.specList && vm.specList[specKey] && vm.specList[specKey].value[valueIndex])
});
}
});
// 延迟绑定上传功能,确保DOM已渲染
setTimeout(function() {
Controller.api.bindUploadButtons();
}, 200);
},
// 绑定上传按钮
bindUploadButtons: function() {
// 检查是否存在上传按钮
if ($('.spec-upload-btn').length === 0) {
return;
}
// 延迟执行,确保DOM已完全渲染
setTimeout(function() {
require(['upload'], function (Upload) {
// 绑定规格值上传按钮
$('.spec-upload-btn:not([initialized])').each(function() {
var $btn = $(this);
var specKey = $btn.attr('data-spec-key');
var valueIndex = $btn.attr('data-value-index');
if (specKey !== undefined && valueIndex !== undefined) {
$btn.attr('initialized', true);
if ($btn && $btn.length > 0) {
$btn.off('click.specUpload').on('click.specUpload', function() {
var inputId = 'c-spec-image-' + specKey + '-' + valueIndex;
var previewId = 'p-spec-image-' + specKey + '-' + valueIndex;
// 创建临时按钮用于上传
var tempBtn = $('');
tempBtn.attr('data-input-id', inputId);
tempBtn.attr('data-preview-id', previewId);
tempBtn.attr('data-mimetype', $btn.attr('data-mimetype'));
tempBtn.attr('data-multiple', $btn.attr('data-multiple'));
$('body').append(tempBtn);
// 使用FastAdmin标准上传方法
Upload.api.upload(tempBtn, function(data, ret) {
var url = data.url || '';
console.log('规格值图片上传成功:', {
inputId: inputId,
url: url,
specKey: specKey,
valueIndex: valueIndex
});
// 直接更新Vue数据而不是DOM操作
if (vm && vm.specList && vm.specList[specKey] && vm.specList[specKey].value[valueIndex]) {
vm.$set(vm.specList[specKey].value[valueIndex], 'image', url);
console.log('Vue数据已更新:', vm.specList[specKey].value[valueIndex]);
}
// 同时更新输入框的值以保持同步
$('#' + inputId).val(url);
// 更新预览
var $preview = $('#' + previewId);
if (url) {
var img = '
';
$preview.html(img);
} else {
$preview.empty();
}
// 清理临时按钮
tempBtn.remove();
}, function(data, ret) {
// 错误回调
console.error('上传失败:', ret);
Toastr.error(ret.msg || '上传失败');
tempBtn.remove();
});
// 触发上传
tempBtn.click();
});
}
}
});
// 绑定选择按钮
$('.spec-choose-btn:not([initialized])').each(function() {
var $btn = $(this);
if (!$btn || $btn.length === 0) {
return;
}
var specKey = $btn.attr('data-spec-key');
var valueIndex = $btn.attr('data-value-index');
if (specKey !== undefined && valueIndex !== undefined) {
$btn.attr('initialized', true);
if ($btn && $btn.length > 0) {
$btn.off('click.specChoose').on('click.specChoose', function() {
var inputId = 'c-spec-image-' + specKey + '-' + valueIndex;
var previewId = 'p-spec-image-' + specKey + '-' + valueIndex;
parent.Fast.api.open("general/attachment/select?element_id=" + inputId + "&multiple=false&mimetype=image/*", __('Choose'), {
callback: function(data) {
var url = data.url || '';
// 直接更新Vue数据
if (vm && vm.specList && vm.specList[specKey] && vm.specList[specKey].value[valueIndex]) {
vm.$set(vm.specList[specKey].value[valueIndex], 'image', url);
console.log('选择图片Vue数据已更新:', vm.specList[specKey].value[valueIndex]);
}
// 同时更新输入框的值以保持同步
$('#' + inputId).val(url);
// 更新预览
var $preview = $('#' + previewId);
if (url) {
var img = '
';
$preview.html(img);
} else {
$preview.empty();
}
}
});
});
}
}
});
});
}, 100);
},
// 内容处理
content: function (value, row, index) {
var width = this.width != undefined ? (this.width.match(/^\d+$/) ? this.width + "px" : this.width) : "350px";
return "" + value + "
";
},
}
};
return Controller;
});