<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>升级包管理</title>
    <link rel="stylesheet" href="{{ asset('CmsProUi/component/pear/css/pear.css') }}">
    <link rel="stylesheet" href="{{ asset('CmsProUi/font-awesome/4.7.0/css/font-awesome.min.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/admin.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/variables.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/reset.css') }}">
</head>
<body>
<div class="pear-container">
    <div class="layui-card">
        <div class="layui-card-body">
            <table id="pkg-table" lay-filter="pkg-table"></table>
        </div>
    </div>
</div>

<script type="text/html" id="pkg-toolbar">
    <button class="layui-btn layui-btn-sm" lay-event="upload"><i class="fa fa-upload"></i> 上传升级包</button>
    <button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="refresh"><i class="fa fa-refresh"></i> 刷新</button>
</script>

<script type="text/html" id="pkg-source-tpl">
@verbatim
{{# if(d.source === 'local'){ }}
    <span class="layui-badge layui-bg-blue">本地上传</span>
{{# } else { }}
    <span class="layui-badge layui-bg-green">远程下载</span>
{{# } }}
@endverbatim
</script>

<script type="text/html" id="pkg-status-tpl">
@verbatim
{{# if(d.status == 1){ }}
    <span class="layui-badge layui-bg-green">可用</span>
{{# } else { }}
    <span class="layui-badge layui-bg-gray">禁用</span>
{{# } }}
@endverbatim
</script>

<script type="text/html" id="pkg-bar">
@verbatim
    {{# if(d._canUpgrade){ }}
    <a class="layui-btn layui-btn-xs" lay-event="upgrade">升级</a>
    {{# } else { }}
    <a class="layui-btn layui-btn-xs layui-btn-disabled" title="{{ d._upgradeTip }}">升级</a>
    {{# } }}
    <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
@endverbatim
</script>

<script src="{{ asset('CmsProUi/component/layui/layui.js') }}"></script>
<script src="{{ asset('CmsProUi/component/pear/pear.js') }}"></script>
<script>
layui.use(['table', 'jquery', 'layer'], function(){
    var table = layui.table,
        $ = layui.jquery,
        layer = layui.layer;

    $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' } });

    // 当前系统版本与构建号，用于判断升级按钮可用性
    var currentVersion = '{{ $currentVersion }}';
    var currentBuild = '{{ $currentBuild }}';

    // 升级任务状态中文映射，供进度弹窗使用
    var statusMap = {
        'idle': '空闲',
        'pending': '等待中',
        'running': '升级中',
        'success': '升级成功',
        'failed': '升级失败',
        'rolling_back': '回滚中',
        'rolled_back': '已回滚',
        'rollback_failed': '回滚失败'
    };

    // 比较两个语义化版本号，返回 -1/0/1
    function compareVersion(a, b) {
        var pa = String(a).split('.'), pb = String(b).split('.');
        var len = Math.max(pa.length, pb.length);
        for (var i = 0; i < len; i++) {
            var na = parseInt(pa[i], 10) || 0, nb = parseInt(pb[i], 10) || 0;
            if (na > nb) return 1;
            if (na < nb) return -1;
        }
        return 0;
    }

    // 计算某个升级包是否可执行升级，并给出禁用原因
    function resolveUpgradeState(row) {
        var cmp = compareVersion(row.to_version, currentVersion);
        if (cmp === 0 && String(row.build) === String(currentBuild)) {
            row._canUpgrade = false;
            row._upgradeTip = '当前系统已是该版本（' + row.to_version + ' Build ' + row.build + '）';
        } else if (cmp < 0) {
            row._canUpgrade = false;
            row._upgradeTip = '目标版本低于当前系统版本，不支持降级';
        } else if (cmp === 0 && String(row.build) !== String(currentBuild)) {
            row._canUpgrade = false;
            row._upgradeTip = '目标版本与当前系统版本一致，不支持跨构建升级';
        } else {
            row._canUpgrade = true;
            row._upgradeTip = '';
        }
        return row;
    }

    var cols = [[
        { title: 'ID', field: 'id', align: 'center', width: 70, sort: true },
        { title: '源版本', field: 'from_version', width: 100 },
        { title: '目标版本', field: 'to_version', width: 100 },
        { title: '构建号', field: 'build', width: 100 },
        { title: '来源', field: 'source', align: 'center', width: 100, templet: '#pkg-source-tpl' },
        { title: '文件大小', field: 'package_size', width: 100, templet: function(d) { var s = d.package_size || 0; if(s < 1024) return s + 'B'; if(s < 1048576) return (s/1024).toFixed(1) + 'KB'; return (s/1048576).toFixed(1) + 'MB'; } },
        { title: '状态', field: 'status', align: 'center', width: 80, templet: '#pkg-status-tpl' },
        { title: '更新日志', field: 'changelog', minWidth: 200 },
        { title: '操作', toolbar: '#pkg-bar', align: 'center', width: 140, fixed: 'right' }
    ]];

    table.render({
        elem: '#pkg-table',
        url: '/admin/versionmgr/api/packages',
        page: { layout: ['count','prev','page','next','limit'], groups: 5, limit: 15 },
        cols: cols,
        toolbar: '#pkg-toolbar',
        defaultToolbar: [{ title:'刷新', layEvent:'refresh', icon:'layui-icon-refresh' }],
        parseData: function(res) {
            var items = res.data ? res.data.items : [];
            items = (items || []).map(resolveUpgradeState);
            return {
                code: res.code === 0 ? 0 : 1,
                msg: res.message || '',
                count: res.data && res.data.pagination ? res.data.pagination.total : 0,
                data: items
            };
        }
    });

    table.on('toolbar(pkg-table)', function(obj) {
        if (obj.event === 'upload') {
            layer.open({ type:2, title:'上传升级包', shade:0.1, area:['600px','444px'], content:'/admin/versionmgr/packages/upload' });
        } else if (obj.event === 'refresh') {
            table.reload('pkg-table');
        }
    });

    table.on('tool(pkg-table)', function(obj) {
        if (obj.event === 'upgrade') {
            if (!obj.data._canUpgrade) {
                layer.msg(obj.data._upgradeTip || '当前升级包不可用', {icon: 2});
                return;
            }
            layer.confirm('确定使用此升级包执行升级？升级过程中系统将暂时不可用。', {icon:3}, function(idx) {
                layer.close(idx);

                // 自定义进度弹窗，避免长时间空白 loading
                var progressLayerIdx = layer.open({
                    type: 1,
                    title: '升级进度',
                    shade: 0.3,
                    shadeClose: 0,
                    closeBtn: 0,
                    area: ['420px', '220px'],
                    content: '<div style="padding:20px;">' +
                        '<div id="pkgProgressInfo" style="margin-bottom:10px;">正在升级到 v' + obj.data.to_version + ' ...</div>' +
                        '<div class="layui-progress" lay-filter="pkgProgressBar"><div class="layui-progress-bar" lay-percent="0%"></div></div>' +
                        '<div id="pkgProgressDetail" style="margin-top:10px;color:#999;font-size:13px;">状态：等待开始</div>' +
                        '</div>',
                    success: function() {
                        layui.element.render('progress');
                    }
                });

                // 启动进度轮询
                var pollTimer = null;
                var pollCount = 0;
                var maxPolls = 200;
                pollTimer = setInterval(function() {
                    pollCount++;
                    if (pollCount > maxPolls) {
                        clearInterval(pollTimer);
                        layer.msg('升级状态查询超时，请刷新页面查看', {icon: 2});
                        return;
                    }
                    $.get('/admin/versionmgr/api/upgrade/status', function(res) {
                        if (res.code !== 0) return;
                        var data = res.data;
                        layui.element.progress('pkgProgressBar', (data.progress || 0) + '%');
                        var detail = '状态：' + (statusMap[data.status] || data.status);
                        if (data.completed_steps && data.completed_steps.length > 0) {
                            detail += '<br>已完成：v' + data.completed_steps.join(', v');
                        }
                        if (data.error_message) {
                            detail += '<br><span style="color:red;">错误：' + data.error_message + '</span>';
                        }
                        $('#pkgProgressDetail').html(detail);

                        var terminalStates = ['success', 'failed', 'rolled_back', 'rollback_failed'];
                        if (data.status === 'success') {
                            clearInterval(pollTimer);
                            layer.close(progressLayerIdx);
                            layer.msg('升级成功！', {icon: 1, time: 1500}, function() {
                                location.reload();
                            });
                            setTimeout(function() { location.reload(); }, 2000);
                        } else if (terminalStates.indexOf(data.status) !== -1) {
                            clearInterval(pollTimer);
                            layer.close(progressLayerIdx);
                            layer.msg('升级失败：' + (data.error_message || '未知错误'), {icon: 2});
                        }
                    });
                }, 3000);

                // 同步升级接口阻塞等待最终结果
                $.post('/admin/versionmgr/api/packages/' + obj.data.id + '/upgrade', function(res) {
                    if (res.code === 0 && res.data.status === 'success') {
                        clearInterval(pollTimer);
                        layer.close(progressLayerIdx);
                        layer.msg('升级成功！', {icon: 1, time: 1500}, function() {
                            location.reload();
                        });
                        setTimeout(function() { location.reload(); }, 2000);
                    } else if (res.code === 0 && res.data.status === 'failed') {
                        clearInterval(pollTimer);
                        layer.close(progressLayerIdx);
                        layer.alert('升级失败：' + (res.data.error_message || '请查看日志'), {icon: 2, title: '升级失败'});
                    } else if (res.code === 0) {
                        layer.msg(res.message || '升级任务已启动', {icon: 1});
                    } else {
                        clearInterval(pollTimer);
                        layer.close(progressLayerIdx);
                        layer.msg(res.message, {icon: 2});
                    }
                }).fail(function() {
                    layer.msg('升级请求网络异常，正在继续查询进度...', {icon: 2});
                });
            });
        } else if (obj.event === 'del') {
            layer.confirm('确定删除此升级包？', {icon:3}, function(idx) {
                layer.close(idx);
                $.ajax({ url:'/admin/versionmgr/api/packages/'+obj.data.id, type:'DELETE', dataType:'json',
                    success: function(res) {
                        if (res.code === 0) { layer.msg('删除成功', {icon:1}, function(){ table.reload('pkg-table'); }); }
                        else { layer.msg(res.message, {icon:2}); }
                    }
                });
            });
        }
    });
});
</script>
</body>
</html>
