甘特图在项目管理中非常重要,甘特图的思想比较简单,即以图示的方式通过活动列表和时间刻度形象地表示出任何特定项目的活动顺序与持续时间。它直观地表明任务计划在什么时候进行,及实际进展与计划要求的对比。管理者由此可便利地弄清一项任务(项目)还剩下哪些工作要做,并可评估工作进度。甘特图可以显示几个部门、机器或设备的运行和闲置情况。这表示了该系统的有关工作负荷状况,这样可使管理人员了解何种调整是恰当的。

      由于项目需要,在网上找了很久,经过大量的对比和评估,发现一款真正开源且功能强大的WEB甘特图控件普加甘特图(PlusGantt)(http://http://www.plusgantt.com/project/),效果图如下:

该款甘特图控件具有如下特征:

1、完善的排程计算,类似Project的效果;

2、支持自动任务,手动任务,任务联动,前后置关系,限制条件等诸多控制;

3、支持资源配置;

4、可对任务的计划和实际进行对比,以百分比进行进度跟踪;

5、支持外观修改;

6、支持前锋线;

7、支持关键路径。

以下为官方演示代码:

var ProjectApp = mini.Panel.extend({

    props: {
        allowUndo: true,
        showHeader: false,
        showToolbar: true,
        borderStyle: 'border:0',
        bodyStyle: "padding:0px",
        toolbarStyle: "border-bottom:0",
        width: "auto",
        height: "100%",
        toolbar: ToolbarTemplate
    },

    constructor: function (config) {
        ProjectApp.base.call(this, config);

        this.initProject();
        this.initColumns();
        this.initMenu();
    },

    initProject: function () {
        this.project = new PlusProject();
        this.project.setStyle("width:100%;height:100%;");
        $(this.bodyEl).append(this.project.el);

        var project = this.project;

            
        project.enableManualSchedule = true;       
        project.enableActualState = true;           
        project.setAllowUndo(this.allowUndo);       
        project.setShowCriticalPath(true);          
        project.setAllowResize(false);
        project.setMultiSelect(true);               
        this.refreshButtons();
        project.on('undochange', this.refreshButtons, this);

        project.on('beforelinkcreate', function (e) {
            e.cancel = true;
            var predecessorTask = project.getTask(e.link.PredecessorUID);
            var task = project.getTask(e.link.TaskUID);
            var prevLink = project.getPredecessorLink(task, predecessorTask);
            if (!prevLink) {
                var links = (task.PredecessorLink || []).clone();
                links.push(e.link);
                var action = new PlusProject.UpdateTaskAction(project, task, 'PredecessorLink', links);
                project.executeAction(action);
            }
        });

        project.on('beforelinkremove', function (e) {
            e.cancel = true;
            var win = new PlusProject.PredecessorLinkWindow({
                closeAction: 'destroy'
            });
            win.project = project;
            win.setData(e.link);
            win.show();
        });

        project.tableView.on("refresh", this.refreshButtons, this);
    },

    initColumns: function () {
        var project = this.project;

        var columns = [
            new PlusProject.IDColumn(),
             new mini.CheckColumn(),
            new PlusProject.StatusColumn(),
            new PlusProject.ManualColumn(),
            new PlusProject.NameColumn(),
            new PlusProject.PredecessorLinkColumn(),
            new PlusProject.WorkColumn(),
            new PlusProject.DurationColumn(),
            new PlusProject.StartColumn(),
            new PlusProject.FinishColumn(),
            new PlusProject.PercentCompleteColumn(),
            new PlusProject.ActualStartColumn(),
            new PlusProject.ActualFinishColumn(),
            new PlusProject.EarlyStartColumn(),
            new PlusProject.EarlyFinishColumn(),
            new PlusProject.LateStartColumn(),
            new PlusProject.LateFinishColumn(),
            new PlusProject.TotalSlackColumn(),
            new PlusProject.CriticalColumn(),
            new PlusProject.DepartmentColumn(),
            new PlusProject.PrincipalColumn(),
            new PlusProject.AssignmentsColumn()
        ];

        project.setColumns(columns);
    },

    initTimeScales: function () {
        this.project.setTopTimeScale('week');
        this.project.setBottomTimeScale('day');
    },

    initMenu: function () {
        var project = this.project;
        this.tableMenu = new PlusProject.TableMenu(project);
        this.tableHeaderMenu = new PlusProject.TableHeaderMenu(project);
        this.ganttMenu = new PlusProject.GanttMenu(project);
        this.ganttHeaderMenu = new PlusProject.GanttHeaderMenu(project);
        this.ganttBarMenu = new PlusProject.GanttBarMenu(project);
    },

    //////////////////////////////////////////////////////////////
    refreshButtons: function () {
        var project = this.project;
        this.refs.undo.setEnabled(project.canUndo());
        this.refs.redo.setEnabled(project.canRedo());

        var saveButton = this.refs.save;
         // saveButton.refs.button.setEnabled(project.isDataChanged());

        var saveItem = saveButton.refs.arrow.menu.items[0];
        //  saveItem.setEnabled(project.isDataChanged());
    },

    execUndo: function () {
        this.project.undo();
    },

    execRedo: function () {
        this.project.redo();
    },

    onAddTask: function () {
        var project = this.project;
        var targetTask = project.getSelected();

        var newTask = project.newTask();
        newTask.Name = '';

        var action = new PlusProject.InsertTaskAction(project, newTask, 'before', targetTask);
        project.executeAction(action);
    },

    onEditTask: function () {
        var project = this.project;
        var item = project.getSelected();
        if (item == project.tasks.root) return
        ShowTaskWindow(project);
    },

    onRemoveTask: function () {
        var project = this.project;
        var items = project.getSelecteds();
        if (items.length == 0) return;

        var action = new PlusProject.RemoveTaskAction(project, items);
        project.executeAction(action);
    },

    onUpgradeTask: function () {
        var project = this.project;
        var tasks = project.getSelecteds();
        if (tasks.length > 0) {
            var action = new PlusProject.UpgradeTaskAction(project, tasks);
            project.executeAction(action);
        }
    },

    onDowngradeTask: function () {
        var project = this.project;
        var tasks = project.getSelecteds();
        if (tasks.length > 0) {
            var action = new PlusProject.DowngradeTaskAction(project, tasks);
            project.executeAction(action);
        }
    },

    saveProject: function () {
        PlusProject.api.saveProject(this.project);
    },

    saveAsTemplate: function () {
        var project = this.project;
        var data = project.data;

        var name = data.Name + ' - ' + mini.formatDate(new Date(), 'yyyy-MM-dd');

        var template = {
            name: name,
            type: 1,                
            data: data
        }

        project.mask('另ⅷ?存?为a项?目?模£板?');

        PlusProject.api.saveTemplate(template, function (success) {
            if (success) {
                alert("项目模板? " + name + " 创建成功");
            }
            project.unmask();
        });
    },

    trackProject: function () {
        TrackProject(this.project);
    },

    showProjectListWindow: function () {
        var win = new PlusProject.ProjectListWindow({
            project: this.project
        });
        win.setData();
        win.show();
    },

    showProjectTemplateWindow: function () {
        var win = new PlusProject.ProjectTemplateWindow({
            project: this.project
        });
        win.setData();
        win.show();
    },

    showTaskTemplateWindow: function () {
        var win = new PlusProject.TaskTemplateWindow({
            project: this.project
        });
        win.setData();
        win.show();
    },

    showNewProjectWindow: function () {
        var project = this.project;

        function fn() {
            var newProject = new PlusProject();

            var win = new PlusProject.ProjectWindow({
                title: '新建项目',
                mode: 'new',
                project: newProject,
                closeHandler: function (action) {
                    if (action == 'ok') {
                        var data = this.getData();
                        var dataProject = mini.clone(newProject.data);
                        $.extend(dataProject, data);
                        project.loadData(dataProject);
                        project.lastScheduleDate = new Date(new Date().getTime() + 1);
                    }
                }
            });
            win.setData();
            win.show();
        }

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐