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

Oracle APEX交互式网格如何自动分配DETAIL_ORDER列值维护行顺序

在Oracle APEX交互式网格中自动维护明细行的DETAIL_ORDER排序值

针对你提到的一对多表结构,要实现用户拖动交互式网格(IG)行调整顺序后,自动更新DETAIL_ORDER列的值,采用中间值分配的方案可以完美解决,具体实现步骤如下:

一、交互式网格基础配置

  • 基于T_DETAIL创建可编辑交互式网格,通过MASTER_GUID关联T_MASTER表
  • 将DETAIL_ORDER列设置为隐藏或只读,避免用户手动修改干扰自动排序逻辑
  • 配置IG初始排序规则为按DETAIL_ORDER升序排列

二、核心实现逻辑

通过前端事件触发+后端计算的方式,完成行拖动后的DETAIL_ORDER自动赋值:

1. 前端行排序事件监听

在交互式网格的JavaScript初始化代码中添加排序变更事件,获取当前行的前后行排序值,调用后端计算新的排序值:

function(config) {
    const $ = apex.jQuery;
    const grid = config.widget;

    grid.on("interactivegridviewsortchange", function(event, ui) {
        // 获取当前操作行的核心数据
        const currentRow = ui.row;
        const currentRecord = grid.model.getRecord(currentRow);
        const masterGuid = grid.model.getValue(currentRecord, "MASTER_GUID");
        const detailGuid = grid.model.getValue(currentRecord, "DETAIL_GUID");
        
        // 获取前后行的DETAIL_ORDER值
        const prevRow = currentRow.prev();
        const nextRow = currentRow.next();
        const prevOrder = prevRow.length ? grid.model.getValue(grid.model.getRecord(prevRow), "DETAIL_ORDER") : 0;
        const nextOrder = nextRow.length ? grid.model.getValue(grid.model.getRecord(nextRow), "DETAIL_ORDER") : 1000000; // 默认最大初始值
        
        // 调用后端AJAX过程更新排序值
        apex.server.process("UPDATE_DETAIL_ORDER", {
            x01: masterGuid,
            x02: detailGuid,
            x03: prevOrder,
            x04: nextOrder
        }, {
            success: function(data) {
                // 同步更新前端模型值并刷新视图
                grid.model.setValue(currentRecord, "DETAIL_ORDER", data.new_order);
                grid.view.refresh();
            }
        });
    });

    return config;
}

2. 后端PL/SQL计算过程

创建AJAX可调用的PL/SQL过程,计算中间值并更新T_DETAIL表:

CREATE OR REPLACE PROCEDURE UPDATE_DETAIL_ORDER (
    p_master_guid IN RAW,
    p_detail_guid IN RAW,
    p_prev_order  IN NUMBER,
    p_next_order  IN NUMBER
) AS
    v_new_order NUMBER;
BEGIN
    -- 根据前后行排序值计算中间值
    IF p_prev_order = 0 THEN
        -- 插入到开头,取后行值的一半
        v_new_order := p_next_order / 2;
    ELSIF p_next_order = 1000000 THEN
        -- 插入到末尾,取前行值的两倍
        v_new_order := p_prev_order * 2;
    ELSE
        -- 插入到中间,取前后值的平均值
        v_new_order := (p_prev_order + p_next_order) / 2;
    END IF;

    -- 更新当前行的DETAIL_ORDER
    UPDATE T_DETAIL
    SET DETAIL_ORDER = v_new_order
    WHERE DETAIL_GUID = p_detail_guid
      AND MASTER_GUID = p_master_guid;

    -- 返回新排序值给前端
    apex_json.open_object;
    apex_json.write('new_order', v_new_order);
    apex_json.close_object;
END;
/

3. 绑定AJAX过程

在APEX应用的共享组件 > Web服务模块中,创建PL/SQL类型的Web服务,绑定上述UPDATE_DETAIL_ORDER过程,参数映射关系为:

  • x01 → p_master_guid
  • x02 → p_detail_guid
  • x03 → p_prev_order
  • x04 → p_next_order

三、初始数据排序初始化

为新插入的明细行自动分配初始排序值,创建插入触发器:

CREATE OR REPLACE TRIGGER TRG_T_DETAIL_INSERT
BEFORE INSERT ON T_DETAIL
FOR EACH ROW
DECLARE
    v_max_order NUMBER;
BEGIN
    SELECT NVL(MAX(DETAIL_ORDER), 0) + 100
    INTO v_max_order
    FROM T_DETAIL
    WHERE MASTER_GUID = :NEW.MASTER_GUID;

    :NEW.DETAIL_ORDER := v_max_order;
END;
/

注意事项

  • 确保IG的允许排序属性设置为"是",开启行拖动排序功能
  • 若多次插入后出现数值精度问题,可定期执行归一化脚本,将DETAIL_ORDER重置为100、200、300...等整数序列
  • 批量调整多行顺序时,可优化逻辑为一次性计算所有行的排序值,减少AJAX调用次数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:43:30