You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Codyhouse产品构建器单选按钮点击后持续加载问题求助

问题描述

我正在搭建一款产品构建器,使用Codyhouse的适配模板时遇到异常:点击单选按钮后,按钮始终处于加载状态,无法继续流程。修改过JS和CSS也未解决问题,怀疑是JS问题但无法确定。

单选按钮加载状态截图

相关JS代码
jQuery(document).ready(function($){
    function ProductBuilder( element ) {
        this.element = element;
        this.stepsWrapper = this.element.children('.cd-builder-steps');
        this.steps = this.element.find('.builder-step');
        // 存储特定构建步骤
        this.models = this.element.find('[data-selection="models"]'); 
        this.summary;
        this.optionsLists = this.element.find('.options-list');
        // 底部摘要栏
        this.fixedSummary = this.element.find('.cd-builder-footer');
        this.modelPreview = this.element.find('.selected-product').find('img');
        this.totPriceWrapper = this.element.find('.tot-price').find('b');
        // 构建器导航
        this.mainNavigation = this.element.find('.cd-builder-main-nav');
        this.secondaryNavigation = this.element.find('.cd-builder-secondary-nav');
        // 标记构建器内容是否加载完成
        this.loaded = true;
        
        // 绑定事件
        this.bindEvents();
    }

    ProductBuilder.prototype.bindEvents = function() {
        var self = this;

        // 左侧导航点击事件
        this.mainNavigation.on('click', 'li:not(.active)', function(event){
            event.preventDefault();
            self.loaded && self.newContentSelected($(this).index());
        });

        // 底部固定导航点击事件
        this.secondaryNavigation.on('click', '.nav-item li:not(.buy)', function(event){ 
            event.preventDefault();
            var stepNumber = ( $(this).parents('.next').length > 0 ) ? $(this).index() + 1 : $(this).index() - 1;
            self.loaded && self.newContentSelected(stepNumber);
        });
        // 选项列表点击事件(如型号、配件)
        this.optionsLists.on('click', '.js-option', function(event){
            self.updateListOptions($(this));
        });
        // 自定义控件点击事件(如颜色选择)
        this.stepsWrapper.on('click', '.cd-product-customizer a', function(event){
            event.preventDefault();
            self.customizeModel($(this));
        });
    };

    ProductBuilder.prototype.newContentSelected = function(nextStep) {
        // 先检查是否已选择型号,未选择则无法继续导航
        if( this.fixedSummary.hasClass('disabled') ) {
            // 未选择型号,显示提示
            this.fixedSummary.addClass('show-alert');
        } else {
            // 已选择型号,切换内容
            // 如果当前是颜色选择步骤,更新底部预览图
            if( this.steps.filter('.active').is('[data-selection="colors"]') ) {
                var imageSelected = this.steps.filter('.active').find('.cd-product-previews').children('.selected').children('img').attr('src');
                this.modelPreview.attr('src', imageSelected);
            }
            // 如果切换到摘要步骤,更新摘要内容
            if( nextStep + 1 >= this.steps.length ) {
                this.createSummary();
            }
            
            this.showNewContent(nextStep);
            this.updatePrimaryNav(nextStep);
            this.updateSecondaryNav(nextStep);
        }
    }

    ProductBuilder.prototype.showNewContent = function(nextStep) {
        var actualStep = this.steps.filter('.active').index() + 1;
        if( actualStep < nextStep + 1 ) {
            // 切换到下一节
            this.steps.eq(actualStep-1).removeClass('active back').addClass('move-left');
            this.steps.eq(nextStep).addClass('active').removeClass('move-left back');
        } else {
            // 切换到上一节
            this.steps.eq(actualStep-1).removeClass('active back move-left');
            this.steps.eq(nextStep).addClass('active back').removeClass('move-left');
        }
    }

    ProductBuilder.prototype.updatePrimaryNav = function(nextStep) {
        this.mainNavigation.find('li').eq(nextStep).addClass('active').siblings('.active').removeClass('active');
    }

    ProductBuilder.prototype.updateSecondaryNav = function(nextStep) {
        ( nextStep == 0 ) ? this.fixedSummary.addClass('step-1') : this.fixedSummary.removeClass('step-1');

        this.secondaryNavigation.find('.nav-item.next').find('li').eq(nextStep).addClass('visible').removeClass('visited').prevAll().removeClass('visited').addClass('visited').end().nextAll().removeClass('visible visited');
        this.secondaryNavigation.find('.nav-item.prev').find('li').eq(nextStep).addClass('visible').removeClass('visited').prevAll().removeClass('visited').addClass('visited').end().nextAll().removeClass('visible visited');
    }

    ProductBuilder.prototype.createSummary = function() {
        var self = this;
        this.steps.each(function(){
            // 根据构建步骤更新摘要内容,可按需修改
            var step = $(this);
            if( $(this).data('selection') == 'colors' ) {
                // 生成颜色摘要
                var colorSelected = $(this).find('.cd-product-customizer').find('.selected'),
                    color = colorSelected.children('a').data('color'),
                    colorName = colorSelected.data('content'),
                    imageSelected = $(this).find('.cd-product-previews').find('.selected img').attr('src');
                
                self.summary.find('.summary-color').find('.color-label').text(colorName).siblings('.color-swatch').attr('data-color', color);
                self.summary.find('.product-preview').attr('src', imageSelected);
            } else if( $(this).data('selection') == 'accessories' ) {
                var selectedOptions = $(this).find('.js-option.selected'),
                    optionsContent = '';

                if( selectedOptions.length == 0 ) {
                    optionsContent = '<li><p>未选择任何配件;</p></li>';
                } else {
                    selectedOptions.each(function(){
                        optionsContent +='<li><p>'+$(this).find('p').text()+'</p></li>';
                    });
                }

                self.summary.find('.summary-accessories').children('li').remove().end().append($(optionsContent));
            }
        });
    }

    ProductBuilder.prototype.updateListOptions = function(listItem) {
        var self = this;
        
        if( listItem.hasClass('js-radio') ) {
            // 单选类型(如型号),取消其他已选项
            var alreadySelectedOption = listItem.siblings('.selected'),
                price = (alreadySelectedOption.length > 0 ) ? -Number(alreadySelectedOption.data('price')) : 0;

            // 如果当前选项已选中,取消时扣除对应价格;否则添加价格
            ( listItem.hasClass('selected') ) 
                ? price = -Number(listItem.data('price'))
                : price = Number(listItem.data('price')) + price;

            alreadySelectedOption.removeClass('selected');
            listItem.toggleClass('selected');
            // 非型号步骤才更新总价
            (listItem.parents('[data-selection="models"]').length == 0) && self.updatePrice(price);
        } else {
            // 多选类型,切换当前选项状态并更新总价
            var price = ( listItem.hasClass('selected') ) ? -Number(listItem.data('price')) : Number(listItem.data('price'));
            listItem.toggleClass('selected');
            self.updatePrice(price);
        }
        
        // 如果是型号选项,更新构建器内容
        if( listItem.parents('[data-selection="models"]').length > 0 ) {
            self.updateModelContent(listItem);
        }
    };

    ProductBuilder.prototype.updateModelContent = function(model) {
        var self = this;
        if( model.hasClass('selected') ) {
            var modelType = model.data('model'),
                modelImage = model.find('img').attr('src');

            // 更新底部预览图
            this.modelPreview.attr('src', modelImage);

            // 移除其他型号内容,加载当前型号对应的内容
            this.models.siblings('li').remove();
            $.ajax({
                type       : "GET",
                dataType   : "html",
                url        : modelType+".html",
                beforeSend : function(){
                    self.loaded = false;
                    model.siblings().removeClass('loaded');
                },
                success    : function(data){
                    self.models.after(data);
                    self.loaded = true;
                    model.addClass('loaded');
                    // 激活导航
                    self.fixedSummary.add(self.mainNavigation).removeClass('disabled show-alert');
                    // 更新对象属性
                    self.steps = self.element.find('.builder-step');
                    self.summary = self.element.find('[data-selection="summary"]');
                    // 重新绑定选项列表点击事件
                    self.optionsLists.off('click', '.js-option');
                    self.optionsLists = self.element.find('.options-list');
                    self.optionsLists.on('click', '.js-option', function(event){
                        self.updateListOptions($(this));
                    });

                    // 移除首次加载动画标记
                    self.element.find('.first-load').removeClass('first-load');
                },
                error     : function(jqXHR, textStatus, errorThrown) {
                    // 此处可添加错误提示
                }
            });

            // 更新总价为当前型号价格
            this.totPriceWrapper.text(model.data('price'));
        } else {
            // 取消型号选择,重置状态
            this.fixedSummary.add(this.mainNavigation).addClass('disabled');
            this.totPriceWrapper.text('0');
            this.models.find('.loaded').removeClass('loaded');
        }
    };

    ProductBuilder.prototype.customizeModel = function(target) {
        var parent = target.parent('li')
            index = parent.index();
        
        // 更新总价:如果当前选项已选中则价格不变,否则替换为当前选项价格
        var price = ( parent.hasClass('selected') )
            ? 0
            : Number(parent.data('price')) - parent.siblings('.selected').data('price');

        this.updatePrice(price);
        target.parent('li').addClass('selected').siblings().removeClass('selected').parents('.cd-product-customizer').siblings('.cd-product-previews').children('.selected').removeClass('selected').end().children('li').eq(index).addClass('selected');
    };

    ProductBuilder.prototype.updatePrice = function(price) {
        var actualPrice = Number(this.totPriceWrapper.text()) + price;
        this.totPriceWrapper.text(actualPrice);
    };

    if( $('.cd-product-builder').length > 0 ) {
        $('.cd-product-builder').each(function(){
            // 为每个产品构建器实例化对象
            new ProductBuilder($(this));
        });
    }
});
问题分析与修复方案

从代码和现象来看,单选按钮点击后一直处于加载状态的核心原因是:updateModelContent方法中的AJAX请求失败,但代码未处理错误状态,导致self.loaded一直为false,后续所有操作被阻塞。

具体修复步骤:

  1. 完善AJAX错误处理逻辑
    在AJAX的error回调中重置加载状态,取消选中并提示用户:
error     : function(jqXHR, textStatus, errorThrown) {
    self.loaded = true;
    model.removeClass('selected');
    alert('模型内容加载失败,请检查文件路径或网络连接');
    self.fixedSummary.add(self.mainNavigation).addClass('disabled');
}
  1. 验证文件路径正确性
    确保AJAX请求的modelType+".html"文件存在,且路径与项目结构匹配(比如选中的型号data-model为"basic",则需存在basic.html文件)。

  2. 调试请求状态
    打开浏览器开发者工具(F12)→ Network标签,点击单选按钮查看请求状态码,确认是否是404(文件不存在)或其他网络错误。

  3. 添加加载状态视觉反馈
    可在beforeSend中给按钮添加加载样式,成功/失败后移除,让用户明确当前状态。

内容的提问来源于stack exchange,提问作者timharrymurphy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:45:29