4a1d949e41
完整 Web 管理平台,涵盖: P0 生产加固: - 会话超时(空闲+绝对) + CSRF 防护 + 登录失败限流 - HTTPS/TLS 证书管理(自签生成/上传/删除/过期提醒) - SSL Bump (HTTPS 透明代理) 可视化配置 - 配置文件 diff 预览 + 二次确认才写入 - 服务控制二次确认 + 操作期间按钮锁定 P1 运维能力: - 日志轮转管理(logrotate) + 日志状态监控 - 告警规则(5xx/命中率/磁盘/客户端流量) - 多 Squid 实例管理 + 一键切换 - squidclient mgr 实时性能指标 - 流量异常检测(突增/大文件/高频小包/新客户端) P2 日志分析增强: - 日志持久化到 SQLite + 历史时间范围查询 - 导出 CSV/JSON(日志/KPI/异常/审计) - GeoIP 地图(Leaflet + ip-api.com 离线可选 GeoLite2) - 每客户端 24h 趋势图 - 自定义 Squid logformat 解析器 P3 体验锦上添花: - 暗/亮主题切换(cookie 持久化) - WebSSH 终端(xterm.js + paramiko) - 完整审计日志 + 用户管理 技术栈: Flask 3.0 + SQLAlchemy 2.0 + SQLite + Chart.js + Leaflet 总代码量: ~16500 行 (15 Python 模块 + 34 模板 + CSS) 路由数: 73
73 lines
2.8 KiB
HTML
73 lines
2.8 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}原始编辑 - Squid Manager{% endblock %}
|
|
{% block content %}
|
|
<div class="page-header">
|
|
<h1>📝 原始配置编辑</h1>
|
|
<div class="page-actions">
|
|
<span class="meta-text">配置文件: <code>{{ squid_conf_path }}</code></span>
|
|
</div>
|
|
</div>
|
|
|
|
{% if error %}
|
|
<div class="flash flash-error">⚠️ {{ error }}</div>
|
|
{% endif %}
|
|
|
|
<div class="card">
|
|
<p class="card-desc">直接编辑 squid.conf 原始内容。保存时可选启用语法校验。
|
|
所有结构化编辑 (主配置、ACL、规则等) 在保存后会重新生成完整配置文件。</p>
|
|
|
|
<form method="post">
|
|
<input type="hidden" name="_csrf" value="{{ csrf_token() }}">
|
|
<div class="form-group">
|
|
<textarea name="content" rows="35" class="form-input monospace raw-editor">{{ content }}</textarea>
|
|
</div>
|
|
<div class="form-actions">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" name="validate" checked> 保存前校验 (<code>squid -k parse</code>)
|
|
</label>
|
|
<button type="submit" class="btn btn-primary">💾 保存</button>
|
|
<button type="button" onclick="validateOnly()" class="btn btn-secondary">🔍 仅校验 (不保存)</button>
|
|
<a href="{{ url_for('backups_view') }}" class="btn btn-secondary">📦 查看备份</a>
|
|
</div>
|
|
</form>
|
|
|
|
<div id="validate-result" class="svc-result" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3 class="card-title">⚠️ 注意事项</h3>
|
|
<ul>
|
|
<li>保存前会自动备份当前配置到 <code>backups/</code> 目录</li>
|
|
<li>校验需要本机安装 squid 二进制 (否则仅做结构解析)</li>
|
|
<li>保存成功后,需要 <a href="{{ url_for('service_view') }}">重载服务</a> 才能生效</li>
|
|
<li>如果使用结构化编辑页面,原始编辑的修改可能被覆盖</li>
|
|
</ul>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
function validateOnly() {
|
|
const content = document.querySelector('textarea[name="content"]').value;
|
|
const box = document.getElementById('validate-result');
|
|
box.style.display = 'block';
|
|
box.className = 'svc-result svc-loading';
|
|
box.textContent = '校验中...';
|
|
fetch('/api/validate', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
body: 'content=' + encodeURIComponent(content)
|
|
})
|
|
.then(r => r.json())
|
|
.then(d => {
|
|
box.className = 'svc-result ' + (d.ok ? 'svc-ok' : 'svc-err');
|
|
box.innerHTML = '<strong>' + (d.ok ? '✅ 校验通过' : '❌ 校验失败') + '</strong><pre>' + (d.message || '') + '</pre>';
|
|
})
|
|
.catch(e => {
|
|
box.className = 'svc-result svc-err';
|
|
box.textContent = '请求失败: ' + e;
|
|
});
|
|
}
|
|
</script>
|
|
{% endblock %}
|