仰望星辰工作室

better-staridc-MNBT

Z zfhsh first commit 2 天前
1<?php
2/** Docker 布局头部(仅认证后页面使用) */
3$active = $active ?? '';
4$me = $me ?? null;
5$plan = $plan ?? null;
6$node = $node ?? null;
7$navItems = [
8 'console' => ['我的容器', 'console.php', '▣'],
9 'appstore' => ['应用商店', 'appstore.php', '▦'],
10 'proxy' => ['反向代理', 'proxy.php', '⇄'],
11 'image' => ['本地镜像', 'image.php', '▤'],
12 'volume' => ['存储卷', 'volume.php', '▥'],
13 'compose' => ['Compose', 'compose.php', '⊟'],
14];
15?>
16<!DOCTYPE html>
17<html lang="zh-CN">
18<head>
19<meta charset="utf-8">
20<meta name="viewport" content="width=device-width, initial-scale=1">
21<title><?= htmlspecialchars($title ?? 'Docker 控制台') ?></title>
22<link rel="icon" href="<?= mnbt_asset_url('images/logo-ico.png') ?>" type="image/ico">
23<link href="<?= mnbt_asset_url('css/bootstrap.min.css') ?>" rel="stylesheet">
24<link href="<?= mnbt_theme_asset('assets/docker.css', 'docker') ?>" rel="stylesheet">
25<script src="<?= mnbt_asset_url('js/jquery.min.js') ?>"></script>
26<script>window.MNBT_CSRF = <?= json_encode(mnbt_csrf_token()) ?>;</script>
27<script>
28// ===== Docker 控制台公共 JS(提前到 head,确保视图 script 可用)=====
29function dkToast(msg, type){
30 type = type || 'info';
31 var wrap = document.getElementById('dkToastWrap');
32 var el = document.createElement('div');
33 el.className = 'dk-toast ' + type;
34 el.textContent = msg;
35 wrap.appendChild(el);
36 setTimeout(function(){ el.style.opacity='0'; el.style.transition='opacity .3s'; setTimeout(function(){ el.remove(); }, 300); }, 2600);
37}
38function dkAjax(gn, data, opts){
39 opts = opts || {};
40 data = data || {};
41 if (typeof data === 'object' && !(data instanceof FormData)) {
42 var fd = new FormData();
43 for (var k in data) fd.append(k, data[k]);
44 data = fd;
45 }
46 data.append('_csrf', window.MNBT_CSRF);
47 return $.ajax({
48 url: 'ajax.php?gn=' + encodeURIComponent(gn),
49 type: 'POST', data: data, processData: false, contentType: false, dataType: 'json',
50 timeout: opts.timeout || 60000
51 }).then(function(r){
52 if (r && r.success) return r;
53 var msg = (r && r.msg) ? r.msg : '请求失败';
54 if (!opts.silent) dkToast(msg, 'error');
55 return $.Deferred().reject(r);
56 }, function(xhr){
57 if (!opts.silent) dkToast('网络错误:' + (xhr.statusText || ''), 'error');
58 return $.Deferred().reject(xhr);
59 });
60}
61function dockerLogout(){
62 dkAjax('logout', {}).then(function(){ window.location.href = 'login.php'; });
63}
64function dkModal(html, title){
65 $('#dkModalMask').html(
66 '<div class="dk-modal"><div class="dk-modal-head"><h3>'+ (title||'') +'</h3><button class="dk-modal-close" onclick="dkCloseModal()">&times;</button></div><div class="dk-modal-body">'+ html +'</div></div>'
67 ).addClass('show');
68}
69function dkCloseModal(){ $('#dkModalMask').removeClass('show').empty(); }
70$(document).on('click', '.dk-modal-mask', function(e){ if (e.target === this) dkCloseModal(); });
71</script>
72</head>
73<body class="dk-body">
74<div class="dk-app">
75 <aside class="dk-sidebar">
76 <div class="dk-sidebar-brand">
77 <img src="<?= mnbt_theme_asset('assets/docker.svg', 'docker') ?>" alt="Docker 控制台" class="dk-logo">
78 </div>
79 <nav class="dk-nav">
80 <div class="dk-nav-section">容器服务</div>
81 <?php foreach ($navItems as $key => $item): ?>
82 <a href="<?= $item[1] ?>" class="<?= $active === $key ? 'active' : '' ?>"><span class="dk-ico"><?= $item[2] ?></span><?= $item[0] ?></a>
83 <?php endforeach; ?>
84 </nav>
85 <div class="dk-sidebar-user">
86 <div class="dk-u-name"><?= htmlspecialchars($me['username'] ?? '') ?></div>
87 <div class="dk-u-meta">节点 <?= htmlspecialchars($node['name'] ?? ($me['ssbt'] ?? '')) ?><?php if ($plan): ?> · <?= htmlspecialchars($plan['name']) ?><?php endif; ?></div>
88 <div style="margin-top:10px"><button class="dk-btn dk-btn-ghost dk-btn-sm dk-btn-block" onclick="dockerLogout()">退出登录</button></div>
89 </div>
90 </aside>
91 <main class="dk-main">
92 <div class="dk-topbar">
93 <h2><?= htmlspecialchars($title ?? '') ?></h2>
94 <div class="dk-badges">
95 <?php if (!empty($plan)): ?>
96 <span class="dk-tag dk-tag-none"><?= htmlspecialchars($plan['name']) ?> · <?= htmlspecialchars($plan['cpu_max']) ?>核 / <?= htmlspecialchars($plan['mem_max']) ?>MB<?php if (!empty($plan['disk_max']) && $plan['disk_max'] !== '0'): ?> / <?= $plan['disk_max'] >= 1024 ? round($plan['disk_max']/1024, 1) . 'GB' : $plan['disk_max'] . 'MB' ?>磁盘<?php endif; ?><?php if (!empty($plan['proxy_max']) && $plan['proxy_max'] !== '0'): ?> / <?= $plan['proxy_max'] ?>代理<?php endif; ?></span>
97 <?php endif; ?>
98 </div>
99 </div>
100 <div class="dk-content">