project_index.hbs 15.7 KB
<div class="pageheader">
    <div class="media">
        <div class="pageicon pull-left">
            <i class="fa fa-th-list"></i>
        </div>
        <div class="media-body">
            <ul class="breadcrumb">
                <li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li>
                <li><a href="/servers">Projects</a></li>
                <li>{{project.name}}</li>
            </ul>
            <h4>{{project.name}} ({{project.subname}})</h4>
            <input id="info" type="hidden" data-id='{{project._id}}' data-env='{{deploy.env}}'>
        </div>
    </div>
    <!-- media -->
</div>

<div class="contentpanel project-index-page">
    <div class="panel panel-default" data-env='{{deploy.env}}'>
        <div class="panel-heading">
            <div class="pull-right">
                {{#if is_master}}
                    <a class="btn btn-info btn-rounded mr5 log-btn"><i class="fa fa-eye"></i> 查看构建日志</a>
                    <a class="btn btn-success btn-rounded mr20 build-btn"><i class="glyphicon glyphicon-plus"></i> 新增构建</a>
                {{^}}
                    {{#if deploy.is_preview}}
                        <a class="btn btn-info btn-rounded mr5 log-btn"><i class="fa fa-eye"></i> 查看构建日志</a>
                        <a class="btn btn-success btn-rounded mr20 build-btn"><i class="glyphicon glyphicon-plus"></i> 新增构建</a>
                    {{/if}}
                {{/if}}
                <a href="" class="tooltips panel-minimize"><i class="fa fa-minus"></i></a>
            </div>
            <h4 class="panel-title">{{deploy.name}}</h4>
            <p>分支:<code>{{deploy.branchName}}</code></p>
        </div>
        <div class="panel-body">
            <table id="table-building-{{project._id}}" class="table table-striped table-bordered building-table">
                <thead>
                <tr>
                    <th>构建版本</th>
                    <th>分支名称</th>
                    <th>状态</th>
                    <th>构建时间</th>
                    <th>操作</th>
                </tr>
                </thead>
            </table>
        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-heading">
            <h4>服务器信息</h4>
            <p>点击状态Label,可以查看实时日志</p>
            {{#equals @root.project.type 'php'}}
            <button class="btn btn-info btn-xs restart-btn" data-host='all'>全部重启</button>
            {{^}}
            <button class="btn btn-info btn-xs restart-btn" data-host='all'>全部重启</button>
            <button class="btn btn-warning btn-xs deleterestart-btn" data-host='all'>全部删除重启</button>
            {{/equals}}
        </div>
        <div class="panel-body">
            <div class="row">
                {{#each targets}}
                    <div class="col-md-4 host-info" id="d-{{hostFm}}" data-host="{{host}}">
                        <div class="panel panel-info noborder">
                            <div class="panel-heading noborder">
                                <div class="panel-btns">
                                </div><!-- panel-btns -->
                                <div class="panel-icon"><i class="fa fa-cloud" style="padding-left:12px;"></i></div>
                                <div class="media-body">
                                    <h2 class="nomargin">{{host}}</h2> 
                                    <h5 class="md-title mt5 version">当前运行版本:&nbsp;<code>{{#if info}}{{info.building}}{{^}}
                                        未知部署{{/if}}</code></h5>
                                </div><!-- media-body -->
                                <hr class="mt10 mb10">
                                <div class="clearfix mt5" style="padding-left:10px;">
                                    {{#equals @root.project.type 'php'}}
                                    <button class="btn btn-info btn-xs restart-btn" data-host='{{host}}'>重启</button>
                                    {{^}}
                                    <button class="btn btn-info btn-xs restart-btn" data-host='{{host}}'>重启</button>
                                    <button class="btn btn-warning btn-xs deleterestart-btn" data-host='{{host}}'>删除重启</button>
                                    {{/equals}}
                                </div>
                                 <div class="clearfix mt5" style="padding-left:10px;">
                                    <h5 class="md-title mt10">服务器状态</h5>
                                    <span class="label label-serstatus"></span>
                                </div>
                                <div class="clearfix mt5">
                                    <div class="col-xs-4 project-env" data-env="test">
                                        <h5 class="md-title mt10">当前状态</h5>
                                    </div>
                                    <div class="col-xs-4">
                                        <h5 class="md-title mt10">进程状态</h5>
                                    </div>
                                </div>
                                 <div class="clearfix mt5">
                                    <div class="col-xs-4 project-env" data-env="test">
                                        <span class="label label-success deploy-log-btn" data-host="{{host}}"><i
                                                class="fa fa-spinner fa-spin fa-fw margin-bottom"></i> <b>{{#if info}}{{info.state}}{{^}}
                                            未知部署{{/if}}</b></span>
                                    </div>
                                    <div class="col-xs-4">
                                        <span class="label label-status"></span>
                                    </div>
                                </div>
                            </div><!-- panel-body -->
                        </div><!-- panel -->
                    </div>
                {{/each}}
            </div>
        </div>
    </div>
</div>

<div id="log-area" class="panel panel-default panel-alt" style="display:none;height: 100%;">
    <div class="panel-body nopadding" style="height: 100%;">
        <textarea name="code" id="code" style="height: 100%;"></textarea>
    </div>
</div>

<script>
    $(document).on('ready pjax:success', function() {

        var tables = {};
        $('#table-building-{{project._id}}').each(function() {
            var env = $(this).parents('.panel').data('env');
            tables[env] = $(this).DataTable({
                retrieve: true,
                responsive: true,
                searching: false,
                ajax: '/projects/{{project._id}}/buildings?env=' + env,
                columns: [
                    {data: "buildTime"},
                    {data: "branch"},
                    {data: "state"},
                    {data: "updatedAt"},
                    {data: "_id"}
                ],
                order: [[0, 'desc']],
                columnDefs: [{
                    render: function(data, type, row) {
                        var color = 'warning';
                        if (data == 'success') {
                            color = 'success';
                        } else if (data == 'fail') {
                            color = 'danger';
                        }
                        var html = '<span id="b-' + row._id + '" class="label label-' + color + '">';
                        if (data != 'success' && data != 'fail') {
                            html += '<i class="fa fa-spinner fa-spin fa-fw margin-bottom"></i>';
                        }
                        html += data + '</span>';
                        return html;
                    },
                    targets: 2
                }, {
                    render: function(data, type, row) {
                        var disabled = row.state !== 'success';
                        var button_str = '<button ' + (disabled ? 'disabled' : '') + ' class="btn btn-success btn-xs deploy-btn" data-id="' + data + '" data-build=' + row.buildTime + '>分发</button>';
                        {{#if is_master}}
                            return button_str;
                        {{^}}
                            {{#if deploy.is_preview}}
                                return button_str;
                            {{^}}
                                return '';
                            {{/if}}
                        {{/if}}
                    },
                    targets: 4
                }]
            });

            $(this).on('draw.dt', function() {
                $('.deploy-btn').click(function() {
                    var id = $(this).data('id');
                    var build = $(this).data('build');
                    layer.confirm('确定发布版本<code>' + build + '</code>吗?', {
                        btn: ['确定', '取消']
                    }, function() {
                        doDeploy(id);
                    });
                });
            });
        });

        function doDeploy(build) {
            $.post('/projects/deploy/' + build, function(ret) {
                if (ret.code == 200) {
                    layer.msg('正在分发中');
                } else {
                    layer.msg(ret.msg, {icon: 5});
                }
            });
        }

        $('.build-btn').click(function() {
            var env = $(this).parents('.panel').data('env');
            var i = layer.prompt({
                title: '请输入需要构建的分支,默认为 {{deploy.branchName}}',
                value: 'master'
            }, function(branch) {
                branch = branch || '{{deploy.branchName}}';
                $.post('/projects/build/{{project._id}}', {env: env, branch: branch}, function(ret) {
                    if (ret.code == 200) {
                        tables[env].ajax.reload();
                        layer.close(i);
                    }
                });
            });

        });

        $('.restart-btn').click(function(){
            var id = $('#info').data('id');
            var env = $('#info').data('env');
            var host = $(this).parents('.host-info').data('host');

            layer.confirm('确定重启吗?', {
                btn: ['确定', '取消']
            }, function() {
                $.post('/projects/restart', {
                    id: id,
                    host: host,
                    env: env
                },function(ret) {
                    if (ret.code == 200) {
                        layer.msg('正在重启中');
                    } else {
                        layer.msg(ret.msg, {icon: 5});
                    }
                });
            });
        });

        $('.deleterestart-btn').click(function(){
            var id = $('#info').data('id');
            var env = $('#info').data('env');
            var host = $(this).data('host');

            layer.confirm('确定删除后重启吗?', {
                btn: ['确定', '取消']
            }, function() {
                $.post('/projects/deleterestart', {
                    id: id,
                    host: host,
                    env: env
                },function(ret) {
                    if (ret.code == 200) {
                        layer.msg('正在删除重启中');
                    } else {
                        layer.msg(ret.msg, {icon: 5});
                    }
                });
            });
        })

        $('.rollback-btn').click(function() {
            layer.prompt({
                title: '请输入回滚到哪个版本'
            }, function(build) {
                doDeploy(build);
            });
        });

        $('.log-btn').click(function() {
            viewLog('');
        });

        $('.deploy-log-btn').click(function() {
            var host = $(this).data('host');
            viewLog(host);
        });

        function viewLog(tag) {
        }
    });

    $(function() {
        var ws = io();
        ws.on('connect', function() {
            ws.on('/building/{{project._id}}', function(data) {
                console.log(data);
                $('#b-' + data.bid).text(data.state);
                if (data.state == 'success') {
                    $('#b-' + data.bid).removeClass('label-warning').addClass('label-success')
                    $('#b-' + data.bid).parent().parent().find('.deploy-btn').removeAttr('disabled');
                    $('#b-' + data.bid).find('i').remove();
                } else if (data.state == 'fail') {
                    $('#b-' + data.bid).removeClass('label-warning').addClass('label-danger');
                    $('#b-' + data.bid).find('i').remove();
                }
            });

            // ws.on('/building/{{project._id}}/log', function(data){
            //     if(tag == '') {
            //         cm.replaceRange("> " + data + "\n", {line: Infinity});
            //     }
            // });

            ws.on('/deploy/{{project._id}}', function(data) {
                console.log(data);
                $('#d-' + data.host.replace(/\./g, '-')).find('b').text(data.state);
            });

            ws.on('/restart/{{project._id}}', function(data) {
                console.log(data);
                $('#d-' + data.host.replace(/\./g, '-')).find('b').text(data.state);
            });

            ws.on('/deleterestart/{{project._id}}', function(data) {
                console.log(data);
                $('#d-' + data.host.replace(/\./g, '-')).find('b').text(data.state);
            });

            ws.on('/monit/{{project._id}}', function(data) {
                console.log(data);
                var label = $('#d-' + data.host.replace(/\./g, '-')).find('.label-status');
                var servers = $('#d-' + data.host.replace(/\./g, '-')).find('.label-serstatus');

                data = data.monitdata;
                if (data.errmsg) {
                    label.text(data.errmsg).removeClass('label-success').addClass('label-danger');
                    servers.text("获取失败").removeClass('label-success').addClass('label-danger');
                } else {
                    var msg = "线程:" + data.total
                    for(var s in data.status) {
                        msg += ';   [' + s + ']:' + data.status[s];
                    }
                    label.text(msg);

                    if (data.total != data.status.online) {
                        label.removeClass('label-success').addClass('label-danger');
                    } else {
                        label.removeClass('label-danger').addClass('label-success');
                    }

                    msg = "";
                    if (data.cpuUsg) msg += "CPU:" + data.cpuUsg + ";";
                    if (data.freeMen) msg += "可用内存:" + data.freeMen;
                    servers.text(msg).removeClass('label-danger').addClass('label-success');
                }
            });

            // ws.on('/deploy/{{project._id}}/log', function(data){
            //     if(tag == data.host){
            //         cm.replaceRange("> " +data.msg+ "\n", {line: Infinity});
            //     }
            // });
        });
        ws.on('error', function() {
            console.log('connect fail');
        });
        
        var projectid = $('#info').data('id');
        var env = $('#info').data('env');
        var monit = function() {
            $.post('/projects/monit', {
                id: projectid,
                env: env
            },function(ret) {
                if (ret.code != 200) {
                    layer.msg(ret.msg, {icon: 5});
                }
            });
        }
        setInterval(function(){
            // 监控服务状态(轮训)
            monit();
        }, 5000);

        monit(); 
        
    });
</script>