weixin_41244451 2025-08-15 21:55 采纳率: 92.9%
浏览 5

上移或下移内容项后,顺序要变,内容不变


// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 验证全局输入
    $speechRate = max(1, min(10, $speechRate));
    
    // 验证每个内容项的输入
    foreach ($settings as $i => $set) {  // 去掉 &
        $settings[$i]['digit1'] = max(1, $set['digit1']);
        $settings[$i]['digit2'] = max(1, $set['digit2']);
        $settings[$i]['perRow'] = max(1, $set['perRow']);
        $settings[$i]['rows'] = max(1, $set['rows']);
        $settings[$i]['forceDigit2'] = isset($_POST["force_digit2_$i"]) ? $_POST["force_digit2_$i"] : 'unlimited';
    }
    
    // 如果不需要更新题目且已有题目,则保留原题目
    if ($updateProblems === 'no' && isset($_SESSION['problems'])) {
        $problems = $_SESSION['problems'];
    } else {
        $problems = [];
        
        foreach ($settings as $index => $set) {
            $problemsToGenerate = $set['perRow'] * $set['rows'];
            $contentProblems = generateProblems(
                $set['type'],
                $set['subType'],
                $set['digit1'],
                $set['digit2'],
                $problemsToGenerate,
                $set['directRange'],
                $set['digitPosition'],
                $set['forceDigit2']
            );
            $problems = array_merge($problems, $contentProblems);
        }
        $_SESSION['problems'] = $problems;
    }
}

<!-- 模式选择选项卡 -->
            <div class="tab-content" id="mode-tab" style="<?php echo $activeTab === 'mode' ? 'display: block;' : 'display: none;'; ?>">
                <div class="tab-content-header">模式选择</div>
                <!-- 题目模式设置 -->
                <div class="form-group">
                    <label for="read_mode">题目模式</label>
                    <select name="read_mode" id="read_mode">
                        <option value="no" <?php echo $readMode === 'no' ? 'selected' : ''; ?>>列表模式</option>
                        <option value="yes" <?php echo $readMode === 'yes' ? 'selected' : ''; ?>>读题模式</option>
                        <option value="view" <?php echo $readMode === 'view' ? 'selected' : ''; ?>>看题模式</option>
                    </select>
                </div>
                
                <div class="form-row">
                    <div class="form-group">
                        <label for="speech_rate">语速 (1-10)</label>
                        <input type="number" name="speech_rate" id="speech_rate" min="1" max="10" value="<?php echo $speechRate; ?>">
                    </div>
                    <div class="form-group">
                        <label for="display_delay">间隔时间(0-2秒)</label>
                        <input type="number" name="display_delay" id="display_delay" min="0" max="2" step="0.1" value="<?php echo $displayDelay; ?>">
                    </div>
                </div>
                <div class="form-row">
                    <div class="form-group">
                        <label for="show_answer">是否显示答案</label>
                        <select name="show_answer" id="show_answer">
                            <option value="no" <?php echo $showAnswer === 'no' ? 'selected' : ''; ?>></option>
                            <option value="yes" <?php echo $showAnswer === 'yes' ? 'selected' : ''; ?>></option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="update_problems">是否更新题目</label>
                        <select name="update_problems" id="update_problems">
                            <option value="yes" <?php echo $updateProblems === 'yes' ? 'selected' : ''; ?>></option>
                            <option value="no" <?php echo $updateProblems === 'no' ? 'selected' : ''; ?>></option>
                        </select>
                    </div>
                </div>
            </div>

<?php else: ?>
                <!-- 正常预览模式 -->
                <?php
                // 首先定义outputPage函数
                function outputPage($problemGroups, $titlePages, $studentPages, $headerPages, $footerPages, $currentPage, $totalPages, $showAnswer) {
                    // 获取页面标题、学生信息等
                    $title = isset($titlePages[$currentPage - 1]) ? $titlePages[$currentPage - 1] : end($titlePages);
                    $student = isset($studentPages[$currentPage - 1]) ? $studentPages[$currentPage - 1] : end($studentPages);
                    $header = isset($headerPages[$currentPage - 1]) ? $headerPages[$currentPage - 1] : end($headerPages);
                    $footer = isset($footerPages[$currentPage - 1]) ? $footerPages[$currentPage - 1] : end($footerPages);
                    ?>
                    
                    <div class="a4-page">
                        <?php if (!empty($header)): ?>
                            <div class="page-header"><?php echo nl2br(htmlspecialchars($header)); ?></div>
                        <?php endif; ?>
                        
                        <?php if (!empty($title)): ?>
                            <div class="page-title"><?php echo nl2br(htmlspecialchars($title)); ?></div>
                        <?php endif; ?>
                        
                        <?php if (!empty($student)): ?>
                            <div class="student-info <?php 
                                // 判断当前页是否包含乘除法(只要有一个乘除法组就算)
                                $hasMultiplicationDivision = false;
                                foreach ($problemGroups as $group) {
                                    if ($group['settings']['type'] === 'multiplication' || $group['settings']['type'] === 'division') {
                                        $hasMultiplicationDivision = true;
                                        break;
                                    }
                                }
                                echo $hasMultiplicationDivision ? 'multiplication-division-mode' : 'addition-subtraction-mode';
                            ?>">
                                <?php 
                                $studentParts = explode('_______', nl2br(htmlspecialchars($student)));
                                foreach ($studentParts as $index => $part) {
                                    echo $part;
                                    if ($index < count($studentParts) - 1) {
                                        echo '<span class="student-info-line"></span>';
                                    }
                                }
                                ?>
                            </div>
                        <?php endif; ?>
                        
                        <?php 
                        // 输出每个内容组的题目
                        foreach ($problemGroups as $group): 
                            $perRow = $group['settings']['perRow'];
                            $rows = $group['settings']['rows'];
                            $problems = $group['problems'];
                            
                            // 按行分割题目
                            $problemRows = array_chunk($problems, $perRow);
                            
                            foreach ($problemRows as $row): ?>
                                <?php if($group['settings']['type'] === 'addition_subtraction'): ?>
                                    <table class="problems-table addition-subtraction-table">
                                        <tr>
                                            <?php foreach ($row as $colIndex => $problem): ?>
                                                <td style="width: <?php echo (100 / $perRow); ?>%;">
                                                    <div class="problem-index">NO.<?php echo $problem['pageIndex']; ?></div>
                                                    <div class="vertical-underline-top"></div>
                                                    <div class="vertical-problem">
                                                        <?php foreach ($problem['numbers'] as $i => $number): ?>
                                                            <div class="vertical-number">
                                                                <?php if ($i > 0 && $number < 0): ?>
                                                                    -<?php echo abs($number); ?>
                                                                <?php else: ?>
                                                                    <?php echo $i > 0 ? '&nbsp;'.$number : $number; ?>
                                                                <?php endif; ?>
                                                            </div>
                                                        <?php endforeach; ?>
                                                    </div>
                                                    <div class="vertical-underline-top"></div>
                                                    <?php if ($showAnswer === 'yes'): ?>
                                                        <div class="vertical-number answer"><?php echo $problem['result']; ?></div>
                                                    <?php else: ?>
                                                        <div style="height: 20px;"></div>
                                                    <?php endif; ?>
                                                </td>
                                            <?php endforeach; ?>
                                        </tr>
                                    </table>
                                <?php else: ?>
                                    <table class="problems-table multiplication-division-table">
                                        <tr>
                                            <?php foreach ($row as $colIndex => $problem): ?>
                                                <td style="width: <?php echo (100 / $perRow); ?>%;">
                                                    <div class="horizontal-problem">
                                                        <span class="vertical-underline-right">NO.<?php echo $problem['pageIndex']; ?> </span>
                                                        <span>
                                                            <?php echo $problem['numbers'][0]; ?>
                                                            <?php echo $group['settings']['type'] === 'multiplication' ? '×' : '÷'; ?>
                                                            <?php echo $problem['numbers'][1]; ?> = 
                                                        </span>
                                                        <?php if ($showAnswer === 'yes'): ?>
                                                            <span class="answer"><?php echo $problem['result']; ?></span>
                                                        <?php else: ?>
                                                            <span class="space"></span>
                                                        <?php endif; ?>
                                                    </div>
                                                </td>
                                            <?php endforeach; ?>
                                        </tr>
                                    </table>
                                <?php endif; ?>
                            <?php endforeach; ?>
                        <?php endforeach; ?>
                        
                        <div class="page-footer">
                            <?php if (!empty($footer)): ?>
                                <?php echo nl2br(htmlspecialchars($footer)); ?>
                            <?php endif; ?>
                            <span style="float: right;"><?php echo $currentPage; ?>页/共<?php echo $totalPages; ?></span>
                        </div>
                    </div>
                    <?php
                }

                // 计算总题数
                $totalProblems = count($problems);
                $allPerRow = [];
                $allRows = [];

                foreach ($settings as $set) {
                    $allPerRow[] = $set['perRow'];
                    $allRows[] = $set['rows'];
                }

                // 重新组织问题数组,按内容项分组
                $groupedProblems = [];
                $startIndex = 0;
                foreach ($settings as $index => $set) {
                    $contentTotal = $set['perRow'] * $set['rows'];
                    $groupedProblems[$index] = array_slice($problems, $startIndex, $contentTotal);
                    $startIndex += $contentTotal;
                }

                // 初始化页面相关变量
                $currentPage = 1;
                $problemIndex = 0; // 全局题目索引
                $currentPageGroups = []; // 存储当前页的内容组
                $totalPages = 0; // 总页数将在后面计算
                $pageProblemIndex = 0; // 每页题目索引(用于强制换页时重置)

                // 根据强制换页设置组织页面
                foreach ($settings as $currentContentItem => $set) {
                    $forcePageBreak = $set['forcePageBreak'] === 'yes';
                    $contentProblems = $groupedProblems[$currentContentItem];

                    // 如果需要强制换页或者这是第一个内容项,则创建新页面
                    if ($forcePageBreak || empty($currentPageGroups)) {
                        // 如果有累积的内容组,先输出当前页
                        if (!empty($currentPageGroups)) {
                            $totalPages++;
                            outputPage($currentPageGroups, $titlePages, $studentPages, $headerPages, $footerPages, $totalPages, $totalPages, $showAnswer);
                            $currentPageGroups = [];

                            // 强制换页时重置题目编号
                            if ($forcePageBreak) {
                                $pageProblemIndex = 0;
                            }
                        }
                    }

                    // 为当前内容项的题目添加索引
                    foreach ($contentProblems as &$problem) {
                        $problem['index'] = ++$problemIndex; // 全局索引,连续编号
                        $problem['pageIndex'] = ++$pageProblemIndex; // 每页索引,强制换页时重置
                    }
                    unset($problem); // 断开引用

                    // 将当前内容项添加到当前页
                    $currentPageGroups[] = [
                        'settings' => $set,
                        'problems' => $contentProblems
                    ];
                }

                // 输出最后一页(如果有内容组)
                if (!empty($currentPageGroups)) {
                    $totalPages++;
                    outputPage($currentPageGroups, $titlePages, $studentPages, $headerPages, $footerPages, $totalPages, $totalPages, $showAnswer);
                }
                ?>
            <?php endif; ?>

// 上移按钮点击事件
        document.addEventListener('click', function(e) {
            if (e.target && e.target.classList.contains('move-up-btn')) {
                const itemIndex = parseInt(e.target.getAttribute('data-item'));
                if (itemIndex > 1) {
                    moveContentItem(itemIndex, 'up');
                }
            }
        });

        // 下移按钮点击事件
        document.addEventListener('click', function(e) {
            if (e.target && e.target.classList.contains('move-down-btn')) {
                const itemIndex = parseInt(e.target.getAttribute('data-item'));
                const totalItems = parseInt(document.getElementById('content_items').value);
                if (itemIndex < totalItems) {
                    moveContentItem(itemIndex, 'down');
                }
            }
        });

        // 移动内容项函数
        function moveContentItem(itemIndex, direction) {
            const container = document.getElementById('content-items-container');
            const items = container.querySelectorAll('.content-item');
            const currentItem = document.querySelector(`.content-item[data-item="${itemIndex}"]`);

            if (direction === 'up') {
                const prevItem = document.querySelector(`.content-item[data-item="${itemIndex - 1}"]`);
                container.insertBefore(currentItem, prevItem);
            } else {
                const nextItem = document.querySelector(`.content-item[data-item="${itemIndex + 1}"]`);
                container.insertBefore(nextItem, currentItem);
            }

            // 重新编号所有内容项
            renumberContentItems();
        }

        // 重新编号内容项
        function renumberContentItems() {
            const container = document.getElementById('content-items-container');
            const items = container.querySelectorAll('.content-item');

            items.forEach((item, index) => {
                const newIndex = index + 1;
                item.setAttribute('data-item', newIndex);
                item.querySelector('.tab-content-header').textContent = `内容设置#${newIndex}`;

                // 更新所有表单元素的ID和name
                item.querySelectorAll('input, select, textarea, label').forEach(element => {
                    if (element.id) element.id = element.id.replace(/_\d+$/, `_${newIndex}`);
                    if (element.name) element.name = element.name.replace(/_\d+$/, `_${newIndex}`);
                    if (element.htmlFor) element.htmlFor = element.htmlFor.replace(/_\d+$/, `_${newIndex}`);
                });

                // 更新按钮的data-item
                item.querySelectorAll('.remove-content-item, .move-up-btn, .move-down-btn').forEach(btn => {
                    btn.setAttribute('data-item', newIndex);
                });
            });

            // 更新内容项计数
            document.getElementById('content_items').value = items.length;

            // 更新按钮禁用状态
            updateMoveButtonsState();
        }

        // 更新移动按钮状态
        function updateMoveButtonsState() {
            const container = document.getElementById('content-items-container');
            const items = container.querySelectorAll('.content-item');
            const totalItems = items.length;

            items.forEach((item, index) => {
                const itemIndex = index + 1;
                const moveUpBtn = item.querySelector('.move-up-btn');
                const moveDownBtn = item.querySelector('.move-down-btn');

                if (moveUpBtn) {
                    moveUpBtn.disabled = itemIndex === 1;
                }

                if (moveDownBtn) {
                    moveDownBtn.disabled = itemIndex === totalItems;
                }

                /* 第一个内容项不显示删除按钮
                const removeBtn = item.querySelector('.remove-content-item');
                if (removeBtn) {
                    removeBtn.style.display = itemIndex === 1 ? 'none' : 'inline-block';
                }*/
            });
        }

        // 在添加新内容项后调用更新按钮状态
        document.getElementById('add-content-item').addEventListener('click', function() {
            setTimeout(updateMoveButtonsState, 0);
        });

        // 初始化时更新按钮状态
        document.addEventListener('DOMContentLoaded', updateMoveButtonsState);

当【是否更新题目】选择为【否】时,上移或下移内容项后,整行的顺序没有改变,我要的是整行的题目要跟着上移或下移改变,但每行内部的题目顺序保持不变、题目不变。不要创建新的文件。
比如
内容项#1生成了两道题,1+1、1+2
内容项#2生成了两道题,10+10、11+12
这时预览页显示的是:
1+1 1+2
10+10 11+12
这时我把内容项#1下移了,那么预览页就应该要显示:
10+10 11+12
1+1 1+2
但现在我下移了内容#1,显示的还是:
1+1 1+2
10+10 11+12

上面是部分代码,哪里的原代码要改成什么,写清楚。

  • 写回答

6条回答 默认 最新

  • 檀越@新空间 2025-08-15 21:56
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    在您的代码中,您提到“上移或下移内容项后,顺序要变,内容不变”,这通常是指用户可以通过拖拽或其他方式调整内容项的顺序,但内容本身不发生变化。为了实现这一功能,需要考虑以下几个方面:


    1. 实现内容项的可排序功能

    关键点:

    • 使用前端技术(如 HTML5 的 draggable 属性或 JavaScript 库如 jQuery UI)让用户可以拖动内容项。
    • 在拖拽完成后,通过 AJAX 或表单提交将新的顺序发送到服务器。
    • 服务器端根据新的顺序重新排列 $settings 数组。

    2. 前端实现拖拽排序

    您可以使用 HTML5 的 draggable 属性和 JavaScript 来实现拖拽排序功能。以下是一个示例代码片段:

    <!-- 示例:拖拽排序容器 -->
    <ul id="content-sortable">
        <?php foreach ($settings as $i => $set): ?>
            <li class="sortable-item" data-index="<?= $i ?>">
                内容项 <?= $i + 1 ?>: 
                <input type="hidden" name="order[]" value="<?= $i ?>">
                <!-- 其他内容项字段 -->
            </li>
        <?php endforeach; ?>
    </ul>
    
    <script>
        // 拖拽排序逻辑
        const sortable = document.getElementById('content-sortable');
        let dragStartIndex = -1;
    
        sortable.addEventListener('dragstart', (e) => {
            dragStartIndex = e.target.getAttribute('data-index');
        });
    
        sortable.addEventListener('dragover', (e) => {
            e.preventDefault();
        });
    
        sortable.addEventListener('drop', (e) => {
            e.preventDefault();
            const dragEndIndex = e.target.getAttribute('data-index');
            if (dragStartIndex !== -1 && dragEndIndex !== -1 && dragStartIndex !== dragEndIndex) {
                // 交换两个元素的位置
                const temp = settings[dragStartIndex];
                settings[dragStartIndex] = settings[dragEndIndex];
                settings[dragEndIndex] = temp;
    
                // 重新渲染页面或更新隐藏输入框的值
                updateOrderInputs();
            }
        });
    
        function updateOrderInputs() {
            const orderInputs = document.querySelectorAll('input[name="order[]"]');
            orderInputs.forEach((input, index) => {
                input.value = settings[index].index;
            });
        }
    </script>
    

    注意: 上述代码只是一个示例,实际中可能需要结合 PHP 和 AJAX 来保存排序后的数据。


    3. 后端处理排序请求

    当用户完成拖拽并提交表单时,服务器会接收到一个包含新顺序的数组(例如 $_POST['order']),我们需要根据这个顺序来重新排列 $settings

    修改后的 PHP 处理逻辑:

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        // 验证全局输入
        $speechRate = max(1, min(10, $speechRate));
        
        // 如果有排序请求,按新顺序重新排列 $settings
        if (isset($_POST['order'])) {
            $newOrder = $_POST['order'];
            $sortedSettings = [];
    
            foreach ($newOrder as $index) {
                $sortedSettings[] = $settings[$index];
            }
    
            $settings = $sortedSettings;
        }
    
        // 验证每个内容项的输入
        foreach ($settings as $i => $set) {  // 去掉 &
            $settings[$i]['digit1'] = max(1, $set['digit1']);
            $settings[$i]['digit2'] = max(1, $set['digit2']);
            $settings[$i]['perRow'] = max(1, $set['perRow']);
            $settings[$i]['rows'] = max(1, $set['rows']);
            $settings[$i]['forceDigit2'] = isset($_POST["force_digit2_$i"]) ? $_POST["force_digit2_$i"] : 'unlimited';
        }
    
        // ...其余逻辑保持不变 ...
    }
    

    4. 表单提交时传递排序信息

    在表单中添加隐藏字段以保存排序信息:

    <input type="hidden" name="order[]" value="<?= $i ?>" />
    

    或者在拖拽结束后,通过 JavaScript 动态更新这些隐藏字段的值。


    5. 修改后的完整流程

    以下是完整的解决方案步骤:

    1. 前端实现拖拽排序功能

      • 使用 HTML5 的 draggable 或 JavaScript 库(如 jQuery UI)实现拖拽排序。
      • 通过 JavaScript 动态更新隐藏字段的值。
    2. 表单提交时传递排序信息

      • 将排序后的索引值作为 $_POST['order'] 提交。
    3. 后端处理排序信息

      • 根据 $_POST['order'] 重新排列 $settings 数组。
    4. 验证并生成题目

      • 保持原有逻辑不变,确保内容不变,仅顺序变化。

    6. 示例代码总结

    前端部分:

    <ul id="content-sortable">
        <?php foreach ($settings as $i => $set): ?>
            <li class="sortable-item" data-index="<?= $i ?>">
                内容项 <?= $i + 1 ?>
                <input type="hidden" name="order[]" value="<?= $i ?>">
            </li>
        <?php endforeach; ?>
    </ul>
    

    JavaScript 部分:

    // 简化的拖拽排序逻辑
    const sortable = document.getElementById('content-sortable');
    
    sortable.addEventListener('dragover', (e) => {
        e.preventDefault();
    });
    
    sortable.addEventListener('drop', (e) => {
        e.preventDefault();
        const dragStartIndex = e.dataTransfer.getData('text/plain');
        const dragEndIndex = e.target.getAttribute('data-index');
    
        if (dragStartIndex !== null && dragEndIndex !== null && dragStartIndex !== dragEndIndex) {
            // 交换位置
            const temp = settings[dragStartIndex];
            settings[dragStartIndex] = settings[dragEndIndex];
            settings[dragEndIndex] = temp;
    
            // 更新隐藏输入框的值
            updateOrderInputs();
        }
    });
    

    PHP 处理部分:

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (isset($_POST['order'])) {
            $newOrder = $_POST['order'];
            $sortedSettings = [];
    
            foreach ($newOrder as $index) {
                $sortedSettings[] = $settings[$index];
            }
    
            $settings = $sortedSettings;
        }
    
        // 其余逻辑...
    }
    

    7. 注意事项

    • 数据一致性:确保在拖拽过程中,$settings 中的数据是原始数据,而不是经过验证后的数据。
    • 安全性:对 $_POST['order'] 进行验证,防止越界访问(例如检查索引是否有效)。
    • 用户体验:提供反馈提示用户已成功排序。

    总结

    重点总结:

    1. 前端实现拖拽排序,通过 HTML5 或 JavaScript 库实现。
    2. 后端接收排序信息,并根据新顺序重新排列 $settings
    3. 保留内容不变,仅调整顺序,确保业务逻辑正确。

    如果您需要我为您生成完整的拖拽排序功能代码,请告诉我具体需求,我可以进一步完善。

    评论

报告相同问题?

问题事件

  • 创建了问题 8月15日