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; });