一款開源且功能強大的WEB甘特圖控件----普加甘特圖(PlusGantt)

甘特圖在項目管理中非常重要,甘特圖的思想比較簡單,即以圖示的方式通過活動列表和時間刻度形象地表示出任何特定項目的活動順序與持續(xù)時間。它直觀地表明任務(wù)計劃在什么時候進行,及實際進展與計劃要求的對比。管理者由此可便利地弄清一項任務(wù)(項目)還剩下哪些工作要做,并可評估工作進度。甘特圖可以顯示幾個部門、機器或設(shè)備的運行和閑置情況。這表示了該系統(tǒng)的有關(guān)工作負荷狀況,這樣可使管理人員了解何種調(diào)整是恰當?shù)摹?/p>

由于項目需要,在網(wǎng)上找了很久,經(jīng)過大量的對比和評估,發(fā)現(xiàn)一款真正開源且功能強大的WEB甘特圖控件普加甘特圖(PlusGantt)(http://http://www.plusgantt.com/project/),效果圖如下:

1.png

該款甘特圖控件具有如下特征:
1、完善的排程計算,類似Project的效果;
2、支持自動任務(wù),手動任務(wù),任務(wù)聯(lián)動,前后置關(guān)系,限制條件等諸多控制;
3、支持資源配置;
4、可對任務(wù)的計劃和實際進行對比,以百分比進行進度跟蹤;
5、支持外觀修改;
6、支持前鋒線;
7、支持關(guān)鍵路徑。
以下為官方演示代碼:

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('另存為項目模板?');

        PlusProject.api.saveTemplate(template, function (success) {
            if (success) {
                alert("項目模板? " + name + "創(chuàng)建成功");
            }
            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();
        }

        if (project.isDataChanged()) {
            if (confirm("是?否?保饋?存?當獺?前°項?目???")) {
                PlusProject.api.saveProject(project, fn);
            } else {
                fn();
            }
        } else {
            fn();
        }
    },

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

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

        if (project.isDataChanged()) {
            if (confirm("是否保存當前項目?")) {
                PlusProject.api.saveProject(project, fn);
            } else {
                fn();
            }
        } else {
            fn();
        }
    },

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

    showCalendarWindow: function () {
        ShowCalendarWindow(this.project);
    },

    showResourcesWindow: function () {
        ShowResourcesWindow(this.project);
    },

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

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

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

    showPrintProjectWindow: function () {
        var win = new PlusProject.PrintProjectWindow({
            project: this.project
        });
        win.setData();
        win.show();
    }

});
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容