first commit
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}{{ title }} · 本地导航{% endblock %}
|
||||
{% block body %}
|
||||
<header class="topbar">
|
||||
<h1>{{ title }}</h1>
|
||||
<nav>
|
||||
<a href="{{ url_for('admin_groups') }}">返回列表</a>
|
||||
<a href="{{ url_for('index') }}">导航首页</a>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="page-wrap">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="flash-wrap">
|
||||
{% for cat, msg in messages %}
|
||||
<div class="flash {{ cat }}">{{ msg }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<form method="post" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="form-row">
|
||||
{{ form.name.label }}
|
||||
{{ form.name() }}
|
||||
{% if form.name.errors %}
|
||||
<div class="errors">{{ form.name.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ form.sort_order.label }}
|
||||
{{ form.sort_order() }}
|
||||
{% if form.sort_order.errors %}
|
||||
<div class="errors">{{ form.sort_order.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="toolbar" style="margin-top: 1.25rem">
|
||||
{{ form.submit(class="btn btn-primary", style="width: auto") }}
|
||||
<a class="btn btn-secondary" href="{{ url_for('admin_groups') }}">取消</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,69 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}分组管理 · 本地导航{% endblock %}
|
||||
{% block body %}
|
||||
<header class="topbar">
|
||||
<h1>分组管理</h1>
|
||||
<nav>
|
||||
<a href="{{ url_for('index') }}">返回导航</a>
|
||||
<a href="{{ url_for('admin_services') }}">服务管理</a>
|
||||
<a href="{{ url_for('logout') }}">退出</a>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="page-wrap">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="flash-wrap">
|
||||
{% for cat, msg in messages %}
|
||||
<div class="flash {{ cat }}">{{ msg }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<div class="toolbar">
|
||||
<h1 style="margin: 0; flex: 1">自定义分组</h1>
|
||||
<a class="btn btn-primary" href="{{ url_for('admin_group_new') }}" style="width: auto">新建分组</a>
|
||||
</div>
|
||||
|
||||
<div class="table-wrap">
|
||||
<table class="data">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>名称</th>
|
||||
<th>排序</th>
|
||||
<th style="width: 200px">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for g in groups %}
|
||||
<tr>
|
||||
<td>{{ g.id }}</td>
|
||||
<td>{{ g.name }}</td>
|
||||
<td>{{ g.sort_order }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('admin_group_edit', gid=g.id) }}">编辑</a>
|
||||
·
|
||||
<a href="{{ url_for('admin_service_new', group_id=g.id) }}">在此分组添加服务</a>
|
||||
·
|
||||
<form
|
||||
class="inline-form"
|
||||
method="post"
|
||||
action="{{ url_for('admin_group_delete', gid=g.id) }}"
|
||||
onsubmit="return confirm('确定删除该分组?其下所有服务也会被删除。');"
|
||||
>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<button type="submit" class="btn btn-danger">删除</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4" class="hint">暂无分组,点击「新建分组」</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,72 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}{{ title }} · 本地导航{% endblock %}
|
||||
{% block body %}
|
||||
<header class="topbar">
|
||||
<h1>{{ title }}</h1>
|
||||
<nav>
|
||||
<a href="{{ url_for('admin_services') }}">返回列表</a>
|
||||
<a href="{{ url_for('index') }}">导航首页</a>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="page-wrap">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="flash-wrap">
|
||||
{% for cat, msg in messages %}
|
||||
<div class="flash {{ cat }}">{{ msg }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<form method="post" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="form-row">
|
||||
{{ form.name.label }}
|
||||
{{ form.name() }}
|
||||
{% if form.name.errors %}
|
||||
<div class="errors">{{ form.name.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ form.host.label }}
|
||||
{{ form.host(placeholder="例如 192.168.1.10 或 主机名") }}
|
||||
{% if form.host.errors %}
|
||||
<div class="errors">{{ form.host.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ form.port.label }}
|
||||
{{ form.port() }}
|
||||
{% if form.port.errors %}
|
||||
<div class="errors">{{ form.port.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ form.path.label }}
|
||||
{{ form.path(placeholder="/ 或 /path") }}
|
||||
{% if form.path.errors %}
|
||||
<div class="errors">{{ form.path.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ form.group_id.label }}
|
||||
{{ form.group_id() }}
|
||||
{% if form.group_id.errors %}
|
||||
<div class="errors">{{ form.group_id.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ form.sort_order.label }}
|
||||
{{ form.sort_order() }}
|
||||
{% if form.sort_order.errors %}
|
||||
<div class="errors">{{ form.sort_order.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="toolbar" style="margin-top: 1.25rem">
|
||||
{{ form.submit(class="btn btn-primary", style="width: auto") }}
|
||||
<a class="btn btn-secondary" href="{{ url_for('admin_services') }}">取消</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,80 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}服务管理 · 本地导航{% endblock %}
|
||||
{% block body %}
|
||||
<header class="topbar">
|
||||
<h1>服务管理</h1>
|
||||
<nav>
|
||||
<a href="{{ url_for('index') }}">返回导航</a>
|
||||
<a href="{{ url_for('admin_groups') }}">分组管理</a>
|
||||
<a href="{{ url_for('logout') }}">退出</a>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="page-wrap">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="flash-wrap">
|
||||
{% for cat, msg in messages %}
|
||||
<div class="flash {{ cat }}">{{ msg }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<div class="toolbar">
|
||||
<h1 style="margin: 0; flex: 1">内网服务</h1>
|
||||
<a class="btn btn-primary" href="{{ url_for('admin_service_new') }}" style="width: auto">新建服务</a>
|
||||
</div>
|
||||
|
||||
<form class="toolbar" method="get" action="{{ url_for('admin_services') }}">
|
||||
<label for="group_id" class="hint" style="margin: 0">按分组筛选</label>
|
||||
<select name="group_id" id="group_id" onchange="this.form.submit()">
|
||||
<option value="">全部分组</option>
|
||||
{% for g in groups %}
|
||||
<option value="{{ g.id }}" {% if filter_group_id == g.id %}selected{% endif %}>{{ g.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<div class="table-wrap">
|
||||
<table class="data">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>地址</th>
|
||||
<th>分组</th>
|
||||
<th>排序</th>
|
||||
<th style="width: 140px">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for s in services %}
|
||||
<tr>
|
||||
<td>{{ s.name }}</td>
|
||||
<td><code style="font-size: 0.82rem">{{ s.build_url() }}</code></td>
|
||||
<td>{{ s.group.name if s.group else '—' }}</td>
|
||||
<td>{{ s.sort_order }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('admin_service_edit', sid=s.id) }}">编辑</a>
|
||||
·
|
||||
<form
|
||||
class="inline-form"
|
||||
method="post"
|
||||
action="{{ url_for('admin_service_delete', sid=s.id) }}"
|
||||
onsubmit="return confirm('确定删除该服务?');"
|
||||
>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<button type="submit" class="btn btn-danger">删除</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="5" class="hint">暂无服务,点击「新建服务」</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="hint">说明:目标站点若设置禁止被嵌入(如部分面板),iframe 会空白或报错,属对方安全策略,与本站无关。</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{% block title %}本地导航{% endblock %}</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" />
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}导航 · 本地导航{% endblock %}
|
||||
{% block body %}
|
||||
<div class="app-shell">
|
||||
<header class="topbar">
|
||||
<h1>本地导航</h1>
|
||||
<nav>
|
||||
<span class="user">{{ current_user.username }}</span>
|
||||
<a href="{{ url_for('admin_groups') }}">分组管理</a>
|
||||
<a href="{{ url_for('admin_services') }}">服务管理</a>
|
||||
<a href="{{ url_for('logout') }}">退出</a>
|
||||
</nav>
|
||||
</header>
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="flash-wrap" style="padding-top: 0.5rem">
|
||||
{% for cat, msg in messages %}
|
||||
<div class="flash {{ cat }}">{{ msg }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<div class="layout-main">
|
||||
<aside class="sidebar" id="sidebar">
|
||||
{% for group, services in grouped %}
|
||||
<div class="sidebar-section">
|
||||
<h2>{{ group.name }}</h2>
|
||||
{% for svc in services %}
|
||||
<a
|
||||
href="#"
|
||||
class="nav-link"
|
||||
role="button"
|
||||
data-url="{{ svc.build_url() }}"
|
||||
data-name="{{ svc.name | e }}"
|
||||
>{{ svc.name }}</a
|
||||
>
|
||||
{% else %}
|
||||
<div class="hint" style="padding: 0 1rem">该分组下暂无服务</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="hint" style="padding: 1rem">
|
||||
暂无分组与服务,请到「分组管理」「服务管理」添加。
|
||||
</div>
|
||||
{% endfor %}
|
||||
</aside>
|
||||
<div class="frame-wrap">
|
||||
<div class="frame-placeholder" id="placeholder">在左侧点击服务,在此区域以内嵌方式打开(不跳转、不开新标签)</div>
|
||||
<iframe id="svc-frame" title="内嵌服务" hidden></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
var frame = document.getElementById("svc-frame");
|
||||
var placeholder = document.getElementById("placeholder");
|
||||
var links = document.querySelectorAll(".nav-link[data-url]");
|
||||
|
||||
function setActive(el) {
|
||||
links.forEach(function (a) {
|
||||
a.classList.remove("active");
|
||||
});
|
||||
if (el) el.classList.add("active");
|
||||
}
|
||||
|
||||
links.forEach(function (a) {
|
||||
a.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
var url = a.getAttribute("data-url");
|
||||
if (!url) return;
|
||||
placeholder.hidden = true;
|
||||
frame.hidden = false;
|
||||
frame.src = url;
|
||||
setActive(a);
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}登录 · 本地导航{% endblock %}
|
||||
{% block body %}
|
||||
<div class="login-page">
|
||||
<div class="login-card">
|
||||
<h1>本地导航站</h1>
|
||||
<form method="post" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="form-row">
|
||||
{{ form.username.label }}
|
||||
{{ form.username(class="") }}
|
||||
{% if form.username.errors %}
|
||||
<div class="errors">{{ form.username.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
{{ form.password.label }}
|
||||
{{ form.password(class="") }}
|
||||
{% if form.password.errors %}
|
||||
<div class="errors">{{ form.password.errors[0] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-row">{{ form.submit(class="btn btn-primary") }}</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user