Files
dns-serrvice/templates/zone_detail.html
T
AI Agent 0a18b94d84 feat: BIND DNS Web Manager - Web interface for managing BIND9 DNS server
- Flask + SQLite web app with user authentication
- Zone management: create/delete zones, edit raw zone files
- Record management: add/delete A/AAAA/CNAME/MX/TXT/NS/PTR/SRV/CAA records
- Service control: start/stop/restart/reload BIND via systemctl/rndc
- Configuration editor: edit named.conf.options/local with syntax validation
- DNS query testing: online dig tool
- Audit log: all operations logged with user/timestamp
- BIND9 backend, listening on port 53
2026-07-09 17:24:44 +08:00

124 lines
5.8 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ zone.name }} - DNS{% endblock %}
{% block content %}
<div class="page-header">
<div>
<h1>{{ zone.name }}</h1>
<div class="zone-meta">
<span class="badge badge-{{ zone.type }}">{{ zone.type }}</span>
<span class="text-mono text-sm">{{ zone.filename }}</span>
<span class="text-muted text-sm">共 {{ records|length }} 条记录</span>
</div>
</div>
<div>
<a href="{{ url_for('zone_raw', zone_name=zone.name) }}" class="btn btn-info btn-sm">📝 原始文件</a>
<form method="POST" action="{{ url_for('zone_delete', zone_name=zone.name) }}" style="display:inline" onsubmit="return confirm('确定删除域名 {{ zone.name }} 及所有记录?')">
<button type="submit" class="btn btn-danger btn-sm">🗑 删除域名</button>
</form>
</div>
</div>
{% if soa %}
<div class="card">
<div class="card-header"><h2>SOA 记录</h2></div>
<div class="card-body">
<table class="table table-compact">
<tr>
<td class="text-muted">主 NS</td><td class="text-mono">{{ soa.raw.split()[0] if soa.raw else '-' }}</td>
<td class="text-muted">管理员</td><td class="text-mono">{{ soa.raw.split()[1] if soa.raw and soa.raw.split()|length > 1 else '-' }}</td>
</tr>
<tr>
<td class="text-muted">Serial</td><td class="text-mono">{{ soa.raw.split()[2] if soa.raw and soa.raw.split()|length > 2 else '-' }}</td>
<td class="text-muted">Refresh</td><td class="text-mono">{{ soa.raw.split()[3] if soa.raw and soa.raw.split()|length > 3 else '-' }}</td>
</tr>
<tr>
<td class="text-muted">Retry</td><td class="text-mono">{{ soa.raw.split()[4] if soa.raw and soa.raw.split()|length > 4 else '-' }}</td>
<td class="text-muted">Expire</td><td class="text-mono">{{ soa.raw.split()[5] if soa.raw and soa.raw.split()|length > 5 else '-' }}</td>
</tr>
<tr>
<td class="text-muted">Min TTL</td><td class="text-mono">{{ soa.raw.split()[6] if soa.raw and soa.raw.split()|length > 6 else '-' }}</td>
<td colspan="2"></td>
</tr>
</table>
</div>
</div>
{% endif %}
<div class="card">
<div class="card-header">
<h2>DNS 记录</h2>
<button type="button" class="btn btn-primary btn-sm" onclick="document.getElementById('addRecordForm').style.display='block'">+ 添加记录</button>
</div>
<div class="card-body">
<div id="addRecordForm" style="display:none" class="record-form-wrap">
<form method="POST" action="{{ url_for('record_add', zone_name=zone.name) }}" class="record-form">
<div class="form-row">
<div class="form-group">
<label>名称</label>
<input type="text" name="name" placeholder="@ 或 www" style="width:150px">
</div>
<div class="form-group">
<label>TTL</label>
<input type="text" name="ttl" placeholder="留空=默认" style="width:100px">
</div>
<div class="form-group">
<label>类型</label>
<select name="type" id="recordType" style="width:100px">
{% for t in record_types %}
<option value="{{ t }}">{{ t }}</option>
{% endfor %}
</select>
</div>
<div class="form-group" style="flex:1">
<label>数据</label>
<input type="text" name="data" placeholder="如 192.168.1.1 或 target.example.com." style="width:100%">
</div>
<div class="form-group form-actions-vertical">
<button type="submit" class="btn btn-primary btn-sm">添加</button>
</div>
</div>
<div class="form-hints">
<p>A: IPv4地址 | AAAA: IPv6地址 | CNAME: 别名(以.结尾) | MX: 优先级 目标(以.结尾)</p>
<p>TXT: 文本 | NS: NS服务器(以.结尾) | PTR: 反向解析(以.结尾) | SRV: 优先级 权重 端口 目标</p>
</div>
</form>
</div>
{% if records %}
<table class="table">
<thead>
<tr>
<th>#</th>
<th>名称</th>
<th>TTL</th>
<th>类型</th>
<th>数据</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for r in records %}
<tr>
<td class="text-muted">{{ loop.index0 }}</td>
<td class="text-mono">{{ r.name }}</td>
<td class="text-mono text-muted">{{ r.ttl }}</td>
<td><span class="badge badge-{{ r.type }}">{{ r.type }}</span></td>
<td class="text-mono">{{ r.data }}</td>
<td>
<form method="POST" action="{{ url_for('record_delete', zone_name=zone.name, idx=loop.index0) }}" style="display:inline" onsubmit="return confirm('确定删除 {{ r.name }} {{ r.type }} {{ r.data }}?')">
<button type="submit" class="btn-sm btn-danger">删除</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="empty-state">
<p>此域名还没有记录</p>
</div>
{% endif %}
</div>
</div>
{% endblock %}