0 0 0

给打赏弹窗进行美化 教程

修罗之家 官方团队
9天前 124

改动位置

/fox_reward/oddfox/theme/fox_reward.php

<?php !defined('DEBUG') AND exit('Access Denied.');include _include(APP_PATH.'view/htm/header.inc.htm');?>
<div class="container py-4 d-flex justify-content-center">
    <!-- 外层卡片,保持整体框架 -->
    <div class="card border shadow-sm" style="max-width: 480px; width: 100%; border-radius: 8px;">
        <!-- 卡片头部 -->
        <div class="card-header bg-white border-bottom px-4 py-3" style="border-radius: 8px 8px 0 0;">
            <h5 class="mb-0 text-primary">投币</h5>
        </div>
        
        <!-- 卡片主体 -->
        <div class="card-body ajax-body px-4 py-3">
            <?php if(!empty($user['uid'])){?>
            <form action="<?php echo url("thread-reward-$thread[tid]");?>" method="post" id="mod_reward_form">
                <!-- 我的金币(显示在最顶上) -->
                <div class="mb-4">
                    <div class="input-group border rounded" style="border-radius: 6px;">
                        <div class="input-group-prepend w-25">
                            <span class="input-group-text w-100 bg-light border-0">我的金币</span>
                        </div>
                        <div class="form-control bg-white border-0 text-danger font-weight-medium"><?php echo $user['golds'];?> 枚</div>
                    </div>
                </div>
                
              <!-- 打赏金额卡片区域 -->
<div class="mb-4">
    <p class="text-muted mb-2">选择打赏金额</p>
    <!-- 第一行:5、20、40(正方形卡片+$图标贴合) -->
    <div class="d-flex justify-content-between mb-3">
        <?php 
        $row1Configs = [
            ['amount' => 5, 'desc' => '鼓励一下'],
            ['amount' => 20, 'desc' => '内容不错'],
            ['amount' => 40, 'desc' => '很有帮助']
        ];
        foreach($row1Configs as $config){
            $isDisabled = $config['amount'] > $user['golds'];
            $disabledClass = $isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';
            $dataAttr = $isDisabled ? '' : "data-amount='{$config['amount']}'";
        ?>
        <div class="w-30" style="width: 100px !important;">
            <div class="reward-card border rounded-3 d-flex flex-column justify-content-center align-items-center <?php echo $disabledClass;?>" 
                 <?php echo $dataAttr;?> 
                 style="width: 100%; height: 100px; border-radius: 12px; transition: all 0.3s; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
                <!-- 修复$图标贴合:移除mr-1,用span包裹确保仅在金额前显示 -->
                <span class="font-weight-bold fs-5"><span class="text-primary">$</span><?php echo $config['amount'];?></span>
                <div class="text-xs text-muted mt-1"><?php echo $config['desc'];?></div>
            </div>
        </div>
        <?php }?>
    </div>
    <!-- 第二行:60、80、自定义(正方形卡片+$图标贴合) -->
    <div class="d-flex justify-content-between">
        <?php 
        $row2Configs = [
            ['amount' => 60, 'desc' => '强烈推荐'],
            ['amount' => 80, 'desc' => '支持作者']
        ];
        foreach($row2Configs as $config){
            $isDisabled = $config['amount'] > $user['golds'];
            $disabledClass = $isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';
            $dataAttr = $isDisabled ? '' : "data-amount='{$config['amount']}'";
        ?>
        <div class="w-30" style="width: 100px !important;">
            <div class="reward-card border rounded-3 d-flex flex-column justify-content-center align-items-center <?php echo $disabledClass;?>" 
                 <?php echo $dataAttr;?> 
                 style="width: 100%; height: 100px; border-radius: 12px; transition: all 0.3s; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
                <!-- 修复$图标贴合:移除mr-1,用span包裹确保仅在金额前显示 -->
                <span class="font-weight-bold fs-5"><span class="text-primary">$</span><?php echo $config['amount'];?></span>
                <div class="text-xs text-muted mt-1"><?php echo $config['desc'];?></div>
            </div>
        </div>
        <?php }?>
        <!-- 自定义金额卡片(正方形样式) -->
        <div class="w-30" style="width: 100px !important;">
            <div class="reward-card border rounded-3 d-flex flex-column justify-content-center align-items-center cursor-pointer" 
                 id="custom-amount-card" 
                 style="width: 100%; height: 100px; border-radius: 12px; transition: all 0.3s; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
                <span class="font-weight-bold fs-5">自定义</span>
                <div class="text-xs text-muted mt-1">自由打赏</div>
            </div>
        </div>
    </div>
    <!-- 自定义金额输入框(修复多次开关弹窗后无法输入的问题) -->
    <div class="mt-3" id="custom-amount-input" style="display: none;">
        <div class="input-group border rounded-3" style="border-radius: 12px; max-width: 320px; margin: 0 auto;">
            <div class="input-group-prepend">
                <span class="input-group-text bg-light border-0 text-primary rounded-start-3">$</span>
            </div>
            <!-- 修复输入问题:移除inline事件,改用JS动态绑定(避免多次渲染冲突) -->
            <input type="number" class="form-control border-0 shadow-none rounded-end-3" 
                   id="custom-golds" 
                   name="custom_golds"
                   placeholder="输入金额(1-<?php echo $user['golds'];?>枚)" 
                   min="1" 
                   max="<?php echo $user['golds'];?>">
            <div class="form-text text-danger mt-1" id="custom-gold-tip" style="display: none;"></div>
        </div>
    </div>
    <!-- 隐藏域:存储选中的打赏金额 -->
    <input type="hidden" name="golds_num" id="golds_num" value="" required>
</div>

<?php if(!empty($user['uid'])){?>
<!-- 新增:自定义金额输入逻辑(动态绑定事件,解决多次弹窗冲突) -->
<script ajax-eval="true">
// 页面加载/弹窗打开时初始化自定义金额输入事件
function initCustomGoldInput() {
    const $customGolds = $('#custom-golds');
    const maxGolds = <?php echo $user['golds'];?>;
    const $tip = $('#custom-gold-tip');
    const $goldsNum = $('#golds_num');

    // 先解绑已有事件,避免多次绑定冲突(解决弹窗多次开关问题)
    $customGolds.off('keydown input');

    // 1. 禁止输入e/E/+/-
    $customGolds.on('keydown', function(e) {
        const forbiddenKeys = ['e', 'E', '+', '-'];
        if (forbiddenKeys.includes(e.key)) {
            e.preventDefault();
            return false;
        }
        return true;
    });

    // 2. 实时过滤非数字+限制最大金额
    $customGolds.on('input', function() {
        let val = $(this).val().trim();
        // 过滤非数字
        val = val.replace(/\D/g, '');
        // 限制最大金额
        if (val && parseInt(val) > maxGolds) {
            val = maxGolds.toString();
            $tip.text(`金额不能超过${maxGolds}枚`).show();
        } else if (val && parseInt(val) < 1) {
            val = '1';
            $tip.text('金额不能小于1枚').show();
        } else {
            $tip.hide().text('');
        }
        // 更新输入框和隐藏域值
        $(this).val(val);
        $goldsNum.val(val);
    });

    // 3. 选中自定义卡片时聚焦输入框(确保每次打开都能输入)
    $('#custom-amount-card').off('click').on('click', function() {
        $customGolds.focus().select(); // 聚焦并选中内容,方便重新输入
    });
}

// 页面初始加载时执行
$(document).ready(function() {
    initCustomGoldInput();
    // 若弹窗是动态加载,需在弹窗显示后重新执行(如之前优化的initRewardEvents中调用)
    // 示例:在弹窗shown.bs.modal事件中添加 initCustomGoldInput();
});
</script>
<?php }?>

                
                <!-- 自定义打赏理由(圆润风格同步) -->
                <div class="mb-4">
                    <div class="input-group border rounded-3" style="border-radius: 12px;">
                        <div class="input-group-prepend w-25">
                            <span class="input-group-text w-100 bg-light border-0 rounded-start-3">打赏理由</span>
                        </div>
                        <input type="text" class="form-control border-0 shadow-none rounded-end-3" 
                               name="reason" id="reason" maxlength="30" 
                               value="<?php echo $default_reason;?>" required 
                               placeholder="请输入打赏理由(最多30字)">
                    </div>
                </div>
                
                <!-- 按钮区域(圆润风格同步) -->
                <div class="d-flex justify-content-center gap-3 pt-2">
                    <button type="button" class="btn btn-primary px-5 py-2 rounded-3" 
                            id="mod_reward_submit" data-loading-text="<?php echo lang('submiting');?>...">
                        确认
                    </button>
                    <button type="button" class="btn btn-secondary px-5 py-2 rounded-3" data-dismiss="modal">
                        取消
                    </button>
                </div>
            </form>
            <?php }else{?>
            <!-- 未登录状态(圆润风格同步) -->
            <div class="text-center py-5 border rounded-3" style="border-radius: 12px;">
                <div class="mb-3 text-muted">请先登录后投币</div>
                <div class="d-flex justify-content-center gap-3">
                    <a class="btn btn-primary px-5 py-2 rounded-3" href="<?php echo url('user-login');?>">
                        <<i class="icon-user"></i> <?php echo lang('login');?>
                    </a>
                    <a class="btn btn-success px-5 py-2 rounded-3" href="<?php echo url('user-create');?>">
                        <<i class="icon-user"></i> <?php echo lang('register');?>
                    </a>            
                </div>
            </div>
            <?php }?>
        </div>
    </div>
</div>
<?php include _include(APP_PATH.'view/htm/footer.inc.htm');?>

<?php if(!empty($user['uid'])){?>
<script ajax-eval="true">
var globalJmodal = null;

// 初始化样式
$(document).ready(function() {
    $('#custom-amount-input').hide();
    // 默认选中第一个金额卡片(5金币)
    $('.reward-card').first().addClass('border-primary bg-primary bg-opacity-5 shadow-sm');
    $('#golds_num').val($('.reward-card').first().data('amount'));
});

function initRewardEvents() {
    // 金额卡片点击事件(选中时阴影增强,更有层次感)
    $(document).off('click', '.reward-card').on('click', '.reward-card', function() {
        var $this = $(this);
        var amount = $this.data('amount');
        
        // 重置所有卡片样式
        $('.reward-card').removeClass('border-primary bg-primary bg-opacity-5 shadow-sm').addClass('shadow');
        // 选中当前卡片:加深边框+背景色+增强阴影
        $this.addClass('border-primary bg-primary bg-opacity-5 shadow-sm').removeClass('shadow');
        
        // 处理自定义金额与固定金额的切换
        if ($this.attr('id') === 'custom-amount-card') {
            $('#custom-amount-input').show();
            $('#golds_num').val('');
            $('#custom-golds').focus();
        } else {
            $('#custom-amount-input').hide();
            $('#golds_num').val(amount);
        }
    });

    // 自定义金额输入事件
    $(document).off('input propertychange', '#custom-golds').on('input propertychange', '#custom-golds', function() {
        this.value = this.value.replace(/\D/g, '');
        if (this.value.length > 3) this.value = this.value.slice(0, 3);
        $('#golds_num').val(this.value);
    });

    // 确认提交按钮事件
    $(document).off('click', '#mod_reward_submit').on('click', '#mod_reward_submit', function() {
        var jsubmit = $(this);
        if (jsubmit.prop('disabled')) return;

        var jmodal = globalJmodal || $('.modal.show').first();
        var jform = $("#mod_reward_form");
        var jgolds_num = $("#golds_num");
        var jreason = $("#reason");

        jsubmit.attr("disabled", "disabled");
        jsubmit.button('loading');

        // 验证金额
        var goldsVal = parseInt(jgolds_num.val());
        if (isNaN(goldsVal) || goldsVal < 1) {
            $.alert('请选择或输入有效的打赏金额(至少1枚)!');
            resetButtonState();
            return false;
        }
        // 验证理由
        if (jreason.val().trim() === '' || jreason.val().trim().length > 30) {
            $.alert('请填写1-30字的打赏理由!');
            resetButtonState();
            return false;
        }

        var postdata = jform.serialize();
        $.xpost(jform.attr('action'), postdata, function(code, message) {
            resetButtonState();
            $.alert(message, 1);

            if (code === 0) {
                setTimeout(function() {
                    closeModal(jmodal);
                    $('#fox_reward').load(' #fox_reward_load', function() {
                        initRewardTrigger();
                    });
                }, 1000);
            }
        }).fail(function() {
            resetButtonState();
            $.alert('网络请求失败,请稍后重试', 1);
        });

        function resetButtonState() {
            jsubmit.removeAttr("disabled");
            jsubmit.button('reset');
        }
    });

    // 取消按钮事件
    $(document).off('click', '.btn-secondary[data-dismiss="modal"]').on('click', '.btn-secondary[data-dismiss="modal"]', function() {
        var jmodal = globalJmodal || $(this).closest('.modal');
        closeModal(jmodal);
    });
}

function initRewardTrigger() {
    $(document).off('click', '.reward-trigger').on('click', '.reward-trigger', function() {
        var modalUrl = $(this).data('url') || "<?php echo url("thread-reward-$thread[tid]");?>";
        $('#modal-container').load(modalUrl, function() {
            globalJmodal = $('#modal-container .modal').first();
            if (globalJmodal.length) {
                globalJmodal.modal('show');
                initRewardEvents();
            }
        });
    });
}

function closeModal(jmodal) {
    if (jmodal && typeof jmodal.modal === 'function') {
        jmodal.modal('hide');
        setTimeout(function() {
            jmodal.modal('dispose');
            globalJmodal = null;
        }, 300);
    }
    $('body').removeClass('modal-open').removeAttr('style');
    $('.modal-backdrop').remove();
}

// 页面加载完成后初始化事件
$(document).ready(function() {
    initRewardEvents();
    initRewardTrigger();
});
</script>
<?php }?>
看过的人 (6)
  • 修罗之家
  • hechuan
  • 1000
  • qscm000
  • 笑笑
  • 雨伞
最新回复 (0)

    暂无评论

请先登录后发表评论!

返回
请先登录后发表评论!