l cry 2025-05-20 10:00 采纳率: 25%
浏览 11

dhtmlx.gantt自定义编辑器

请教:docs.dhtmlx.gantt自定义编辑器如何保存值?现有业务是点击负责人可以弹出选择用户的弹框,然后选中用户,点击确定之后可以保存当前选中的值。但是现有代码存在两个问题,第一需要双击才能打开选择用户弹框;第二点击弹框确定按钮之后负责人字段没有值。


 // 定义自定义编辑器
gantt.config.editor_types.manager = {
            show: function(id, column, config, placeholder) {
              // 保存当前任务ID和原始值
              this.taskId = id;
              this.originalValue = gantt.getTask(id)[column.name] || [];

              // 创建对话框HTML结构
              var html = `
            <div class="manager-picker-dialog">
                <el-dialog
                    title="选择用户"
                    :visible.sync="dialogVisible"
                    v-if="dialogVisible"
                    width="1100px"
                    append-to-body>
                    <Selector
                        ref="selectorRef"
                        :height="500"
                        :type="1"
                        :multiple="false"
                        :sourceData="sourceData"
                        v-model="selectedUsers">
                        </Selector>
                    <div slot="footer" class="dialog-footer">
                        <el-button type="primary" @click="confirmSelection">确 定</el-button>
                        <el-button type="info" @click="dialogVisible = false">取 消</el-button>
                    </div>
                </el-dialog>
            </div>
        `;

              placeholder.innerHTML = html;

              // 初始化Vue实例来管理对话框
              this.vueInstance = new Vue({
                el: placeholder.querySelector('.manager-picker-dialog'),
                components: {
                  Selector
                },
                data: {
                  dialogVisible: true,
                  sourceData: [], //用户数据源
                  selectedUsers: [...this.originalValue] // 初始化为当前任务的值
                },
                methods: {
                  // 加载用户数据的方法
                  loadUserData() {  },
                  confirmSelection() {
                    this.dialogVisible = false;
                    // // 触发保存
                    const editor = this.$parent.$parent.$parent.$parent.editor;
                    if (editor && editor.save) {
                      editor.save();
                    }
                  }
                },
                mounted() {
                  this.loadUserData();
                }
              });
            },

            hide: function() {
              // 清理Vue实例
              if(this.vueInstance) {
                this.vueInstance.$destroy();
                this.vueInstance = null;
              }
            },

            set_value: function(value, id, column, node) {

            },

            get_value: function(id, column, node) {
              if(this.vueInstance) {
                return this.vueInstance.selectedUsers;
              }
              return this.originalValue || [];
            },

            is_changed: function(value, id, column, node) {
              if(this.vueInstance) {
                // 比较数组内容是否相同
                const current = this.vueInstance.selectedUsers;
                const original = this.originalValue;
                return current.length !== original.length ||
                  current.some((val, index) => val !== original[index]);
              }
              return false;
            },

            is_valid: function(value, id, column, node) {
              return !!(this.vueInstance && this.vueInstance.selectedUsers && this.vueInstance.selectedUsers.length > 0);
            },

            focus: function(node) {
              // 不需要聚焦,因为对话框有自己的交互
            }
          };

          // 配置列
          var managerEditor = {type: "manager", map_to: "manager"};
 gantt.config.columns = [ {name: "manager", label: "任务负责人", align: "center", width: 85, resize: true, editor: managerEditor, template: function (item) {
                if (typeof _this !== 'undefined' && _this.currentStatus === 'other') {
                  if (item.manager === null || item.manager === undefined) {
                    // 当 manager 为空时,返回一个可交互的元素
                    return `<div class="manager-placeholder" data-id="${item.id}">
                  <el-icon class="el-icon-circle-plus-outline"></el-icon>
                </div>`;
                  }
                }
                // 如果不满足条件,返回默认显示
                return `<div>${item.manager || ''}</div>`;
              }
            }]

img

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-05-20 10:02
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    根据你的描述,dhtmlx.gantt 自定义编辑器存在两个问题:

    1. 双击才能打开选择用户弹框:这可能是因为默认的编辑器触发机制被覆盖了。
    2. 点击弹框确定按钮后负责人字段没有值:可能是由于值未正确传递回 Gantt 编辑器。

    以下是解决方案,并对代码进行优化以确保功能正常运行。


    解决方案

    1. 确保单击即可打开弹框

    默认情况下,Gantt 的编辑器会监听单元格的单击事件。如果自定义编辑器的行为被覆盖或未正确绑定事件,则可能导致需要双击才能打开弹框。我们可以通过以下方式修复:

    • show 方法中明确绑定单击事件。
    • 使用 placeholder 元素作为触发点。

    2. 正确保存值到 Gantt

    当用户确认选择后,需要将选中的值传递给 Gantt 编辑器,并触发 save 方法。我们可以通过以下步骤实现:

    • confirmSelection 方法中调用 save 方法。
    • 确保 get_value 方法返回正确的值。

    修改后的代码

    gantt.config.editor_types.manager = {
        show: function(id, column, config, placeholder) {
            // 保存当前任务ID和原始值
            this.taskId = id;
            this.originalValue = gantt.getTask(id)[column.name] || [];
    
            // 创建对话框HTML结构
            var html = `
                <div class="manager-picker-dialog">
                    <el-dialog
                        title="选择用户"
                        :visible.sync="dialogVisible"
                        v-if="dialogVisible"
                        width="1100px"
                        append-to-body>
                        <Selector
                            ref="selectorRef"
                            :height="500"
                            :type="1"
                            :multiple="false"
                            :sourceData="sourceData"
                            v-model="selectedUsers">
                        </Selector>
                        <div slot="footer" class="dialog-footer">
                            <el-button type="primary" @click="confirmSelection">确 定</el-button>
                            <el-button type="info" @click="dialogVisible = false">取 消</el-button>
                        </div>
                    </el-dialog>
                </div>
            `;
    
            placeholder.innerHTML = html;
    
            // 初始化Vue实例来管理对话框
            this.vueInstance = new Vue({
                el: placeholder.querySelector('.manager-picker-dialog'),
                components: {
                    Selector
                },
                data: {
                    dialogVisible: true,
                    sourceData: [], // 用户数据源
                    selectedUsers: [...this.originalValue] // 初始化为当前任务的值
                },
                methods: {
                    // 加载用户数据的方法
                    loadUserData() {
                        // 示例:从 API 获取用户数据
                        this.sourceData = [
                            { id: 1, name: '张三' },
                            { id: 2, name: '李四' }
                        ];
                    },
                    confirmSelection() {
                        this.dialogVisible = false;
                        // 触发保存
                        if (this.$parent && this.$parent.editor && this.$parent.editor.save) {
                            this.$parent.editor.save();
                        }
                    }
                },
                mounted() {
                    this.loadUserData();
                }
            });
        },
    
        hide: function() {
            // 清理Vue实例
            if (this.vueInstance) {
                this.vueInstance.$destroy();
                this.vueInstance = null;
            }
        },
    
        set_value: function(value, id, column, node) {
            // 设置初始值(如果需要)
            this.vueInstance.selectedUsers = value || [];
        },
    
        get_value: function(id, column, node) {
            if (this.vueInstance) {
                return this.vueInstance.selectedUsers; // 返回选中的用户
            }
            return this.originalValue || [];
        },
    
        is_changed: function(value, id, column, node) {
            if (this.vueInstance) {
                // 比较数组内容是否相同
                const current = this.vueInstance.selectedUsers;
                const original = this.originalValue;
                return current.length !== original.length ||
                       current.some((val, index) => val.id !== original[index].id); // 假设用户对象有 id 属性
            }
            return false;
        },
    
        is_valid: function(value, id, column, node) {
            return !!(this.vueInstance && this.vueInstance.selectedUsers && this.vueInstance.selectedUsers.length > 0);
        },
    
        focus: function(node) {
            // 不需要聚焦,因为对话框有自己的交互
        }
    };
    
    // 配置列
    var managerEditor = { type: "manager", map_to: "manager" };
    gantt.config.columns = [
        { name: "manager", label: "任务负责人", align: "center", width: 85, resize: true, editor: managerEditor }
    ];
    

    关键点解析

    1. show 方法

      • 使用 placeholder 元素作为触发点,确保单击即可打开弹框。
      • 初始化 Vue 实例并加载用户数据。
    2. confirmSelection 方法

      • 在用户确认选择后,调用 save 方法,将值传递回 Gantt 编辑器。
    3. get_value 方法

      • 返回当前选中的用户数组,确保值能够正确传递。
    4. is_changed 方法

      • 比较当前值和原始值,判断是否有变化。
    5. set_value 方法

      • 在初始化时设置初始值。

    测试步骤

    1. 点击任务的“任务负责人”列,弹框应立即弹出。
    2. 选择用户并点击“确定”,任务的“任务负责人”列应显示选中的用户。
    3. 再次点击同一列,验证弹框是否能正常弹出。

    通过以上修改,问题应该能够得到解决。

    评论

报告相同问题?

问题事件

  • 创建了问题 5月20日