2025-11-11 21:39:12 +08:00
|
|
|
|
{% extends "base.html" %}
|
|
|
|
|
|
|
|
|
|
|
|
{% block title %}系统设置 - 软件授权管理系统{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
{% block page_title %}系统设置{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
{% block content %}
|
|
|
|
|
|
<div class="row">
|
|
|
|
|
|
<div class="col-lg-8">
|
|
|
|
|
|
<div class="card shadow mb-4">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h6 class="mb-0">基本设置</h6>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<form id="basic-settings-form">
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="site_name" class="form-label">系统名称</label>
|
|
|
|
|
|
<input type="text" class="form-control" id="site_name" name="site_name" value="{{ config.SITE_NAME or '软件授权管理系统' }}">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="admin_email" class="form-label">管理员邮箱</label>
|
|
|
|
|
|
<input type="email" class="form-control" id="admin_email" name="admin_email" value="{{ config.ADMIN_EMAIL or '' }}">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-11-16 19:06:49 +08:00
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="frontend_domain" class="form-label">前端域名</label>
|
|
|
|
|
|
<input type="text" class="form-control" id="frontend_domain" name="frontend_domain"
|
|
|
|
|
|
value="{{ config.FRONTEND_DOMAIN or '' }}">
|
|
|
|
|
|
<div class="form-text">前端API请求使用的域名,留空则使用当前访问域名</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-11-11 21:39:12 +08:00
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="max_failed_attempts" class="form-label">最大失败尝试次数</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="max_failed_attempts" name="max_failed_attempts"
|
|
|
|
|
|
value="{{ config.MAX_FAILED_ATTEMPTS or 5 }}" min="1" max="20">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="lockout_minutes" class="form-label">锁定时间(分钟)</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="lockout_minutes" name="lockout_minutes"
|
|
|
|
|
|
value="{{ config.LOCKOUT_MINUTES or 10 }}" min="1" max="1440">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="max_unbind_times" class="form-label">最大解绑次数</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="max_unbind_times" name="max_unbind_times"
|
|
|
|
|
|
value="{{ config.MAX_UNBIND_TIMES or 3 }}" min="0" max="100">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="auth_secret_key" class="form-label">授权验证密钥</label>
|
|
|
|
|
|
<input type="text" class="form-control" id="auth_secret_key" name="auth_secret_key"
|
|
|
|
|
|
value="{{ config.AUTH_SECRET_KEY or 'auth-validator-secret-key' }}">
|
|
|
|
|
|
<div class="form-text">用于授权验证的密钥,请妥善保管</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<button type="submit" class="btn btn-primary" id="save-basic-btn">
|
|
|
|
|
|
<i class="fas fa-save me-2"></i>
|
|
|
|
|
|
<span id="save-basic-text">保存设置</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="card shadow mb-4">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h6 class="mb-0">卡密设置</h6>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<form id="license-settings-form">
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="license_key_length" class="form-label">卡密长度</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="license_key_length" name="license_key_length"
|
|
|
|
|
|
value="{{ config.LICENSE_KEY_LENGTH or 32 }}" min="16" max="128">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="license_key_prefix" class="form-label">卡密前缀</label>
|
|
|
|
|
|
<input type="text" class="form-control" id="license_key_prefix" name="license_key_prefix"
|
|
|
|
|
|
value="{{ config.LICENSE_KEY_PREFIX or '' }}" maxlength="10">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="trial_prefix" class="form-label">试用卡密前缀</label>
|
|
|
|
|
|
<input type="text" class="form-control" id="trial_prefix" name="trial_prefix"
|
|
|
|
|
|
value="{{ config.TRIAL_PREFIX or 'TRIAL_' }}" maxlength="10">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="offline_cache_days" class="form-label">离线缓存天数</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="offline_cache_days" name="offline_cache_days"
|
|
|
|
|
|
value="{{ config.OFFLINE_CACHE_DAYS or 7 }}" min="1" max="365">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<button type="submit" class="btn btn-primary" id="save-license-btn">
|
|
|
|
|
|
<i class="fas fa-save me-2"></i>
|
|
|
|
|
|
<span id="save-license-text">保存设置</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="card shadow mb-4">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h6 class="mb-0">API设置</h6>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<form id="api-settings-form">
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="api_version" class="form-label">API版本</label>
|
|
|
|
|
|
<input type="text" class="form-control" id="api_version" name="api_version"
|
|
|
|
|
|
value="{{ config.API_VERSION or 'v1' }}">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="items_per_page" class="form-label">每页显示条目数</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="items_per_page" name="items_per_page"
|
|
|
|
|
|
value="{{ config.ITEMS_PER_PAGE or 20 }}" min="5" max="100">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<button type="submit" class="btn btn-primary" id="save-api-btn">
|
|
|
|
|
|
<i class="fas fa-save me-2"></i>
|
|
|
|
|
|
<span id="save-api-text">保存设置</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="card shadow mb-4">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h6 class="mb-0">文件上传设置</h6>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<form id="upload-settings-form">
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="max_content_length" class="form-label">最大上传文件大小 (MB)</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="max_content_length" name="max_content_length"
|
|
|
|
|
|
value="{{ (config.MAX_CONTENT_LENGTH / 1024 / 1024) | int or 500 }}" min="1" max="1000">
|
|
|
|
|
|
<div class="form-text">当前设置: {{ config.MAX_CONTENT_LENGTH / 1024 / 1024 }} MB</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="upload_folder" class="form-label">上传文件夹</label>
|
|
|
|
|
|
<input type="text" class="form-control" id="upload_folder" name="upload_folder"
|
|
|
|
|
|
value="{{ config.UPLOAD_FOLDER or 'static/uploads' }}">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<button type="submit" class="btn btn-primary" id="save-upload-btn">
|
|
|
|
|
|
<i class="fas fa-save me-2"></i>
|
|
|
|
|
|
<span id="save-upload-text">保存设置</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="card shadow mb-4">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h6 class="mb-0">会话设置</h6>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<form id="session-settings-form">
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
|
<label for="session_lifetime_hours" class="form-label">会话有效期(小时)</label>
|
|
|
|
|
|
<input type="number" class="form-control" id="session_lifetime_hours" name="session_lifetime_hours"
|
|
|
|
|
|
value="{{ (config.PERMANENT_SESSION_LIFETIME.seconds / 3600) | int or 24 }}" min="1" max="720">
|
|
|
|
|
|
<div class="form-text">当前设置: {{ config.PERMANENT_SESSION_LIFETIME.days * 24 + config.PERMANENT_SESSION_LIFETIME.seconds / 3600 }} 小时</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<button type="submit" class="btn btn-primary" id="save-session-btn">
|
|
|
|
|
|
<i class="fas fa-save me-2"></i>
|
|
|
|
|
|
<span id="save-session-text">保存设置</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="col-lg-4">
|
|
|
|
|
|
<div class="card shadow mb-4">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h6 class="mb-0">系统信息</h6>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<dl class="row">
|
|
|
|
|
|
<dt class="col-sm-6">系统版本:</dt>
|
|
|
|
|
|
<dd class="col-sm-6">{{ system_version or 'v1.0.0' }}</dd>
|
|
|
|
|
|
|
|
|
|
|
|
<dt class="col-sm-6">Python版本:</dt>
|
|
|
|
|
|
<dd class="col-sm-6">{{ python_version or 'Unknown' }}</dd>
|
|
|
|
|
|
|
|
|
|
|
|
<dt class="col-sm-6">Flask版本:</dt>
|
|
|
|
|
|
<dd class="col-sm-6">{{ flask_version or 'Unknown' }}</dd>
|
|
|
|
|
|
|
|
|
|
|
|
<dt class="col-sm-6">数据库:</dt>
|
|
|
|
|
|
<dd class="col-sm-6">{{ database_type or 'Unknown' }}</dd>
|
|
|
|
|
|
|
|
|
|
|
|
<dt class="col-sm-6">运行时间:</dt>
|
|
|
|
|
|
<dd class="col-sm-6">{{ uptime or 'Unknown' }}</dd>
|
|
|
|
|
|
|
|
|
|
|
|
<dt class="col-sm-6">API版本:</dt>
|
|
|
|
|
|
<dd class="col-sm-6">{{ config.API_VERSION or 'v1' }}</dd>
|
|
|
|
|
|
|
|
|
|
|
|
<dt class="col-sm-6">上传限制:</dt>
|
|
|
|
|
|
<dd class="col-sm-6">{{ config.MAX_CONTENT_LENGTH / 1024 / 1024 }} MB</dd>
|
|
|
|
|
|
</dl>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="card shadow">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h6 class="mb-0">操作</h6>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<div class="d-grid gap-2">
|
|
|
|
|
|
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#backupModal">
|
|
|
|
|
|
<i class="fas fa-database me-2"></i>
|
|
|
|
|
|
数据备份
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" class="btn btn-outline-warning" data-bs-toggle="modal" data-bs-target="#clearCacheModal">
|
|
|
|
|
|
<i class="fas fa-broom me-2"></i>
|
|
|
|
|
|
清理缓存
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#resetModal">
|
|
|
|
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
|
|
|
|
重置系统
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 数据备份模态框 -->
|
|
|
|
|
|
<div class="modal fade" id="backupModal" tabindex="-1">
|
|
|
|
|
|
<div class="modal-dialog">
|
|
|
|
|
|
<div class="modal-content">
|
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
|
<h5 class="modal-title">数据备份</h5>
|
|
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal-body">
|
|
|
|
|
|
<p>确定要创建数据备份吗?</p>
|
|
|
|
|
|
<div class="form-check">
|
|
|
|
|
|
<input class="form-check-input" type="checkbox" id="include_logs" checked>
|
|
|
|
|
|
<label class="form-check-label" for="include_logs">
|
|
|
|
|
|
包含日志文件
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal-footer">
|
|
|
|
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
|
|
|
|
|
<button type="button" class="btn btn-primary" id="backup-btn">开始备份</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 清理缓存模态框 -->
|
|
|
|
|
|
<div class="modal fade" id="clearCacheModal" tabindex="-1">
|
|
|
|
|
|
<div class="modal-dialog">
|
|
|
|
|
|
<div class="modal-content">
|
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
|
<h5 class="modal-title">清理缓存</h5>
|
|
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal-body">
|
|
|
|
|
|
<p>确定要清理系统缓存吗?这将清除所有临时文件和缓存数据。</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal-footer">
|
|
|
|
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
|
|
|
|
|
<button type="button" class="btn btn-warning" id="clear-cache-btn">确认清理</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 重置系统模态框 -->
|
|
|
|
|
|
<div class="modal fade" id="resetModal" tabindex="-1">
|
|
|
|
|
|
<div class="modal-dialog">
|
|
|
|
|
|
<div class="modal-content">
|
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
|
<h5 class="modal-title">重置系统</h5>
|
|
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal-body">
|
|
|
|
|
|
<div class="alert alert-danger">
|
|
|
|
|
|
<strong>警告!</strong> 此操作将删除所有数据并重置系统到初始状态,无法恢复。
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>请输入"RESET"确认操作:</p>
|
|
|
|
|
|
<input type="text" class="form-control" id="reset-confirm" placeholder="输入RESET确认">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal-footer">
|
|
|
|
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
|
|
|
|
|
<button type="button" class="btn btn-danger" id="reset-btn" disabled>确认重置</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
{% block extra_js %}
|
|
|
|
|
|
<script>
|
|
|
|
|
|
// 页面加载完成后初始化
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
|
|
|
|
initEventListeners();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化事件监听器
|
|
|
|
|
|
function initEventListeners() {
|
|
|
|
|
|
// 基本设置表单
|
|
|
|
|
|
document.getElementById('basic-settings-form').addEventListener('submit', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
saveBasicSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 卡密设置表单
|
|
|
|
|
|
document.getElementById('license-settings-form').addEventListener('submit', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
saveLicenseSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// API设置表单
|
|
|
|
|
|
document.getElementById('api-settings-form').addEventListener('submit', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
saveApiSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 文件上传设置表单
|
|
|
|
|
|
document.getElementById('upload-settings-form').addEventListener('submit', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
saveUploadSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 会话设置表单
|
|
|
|
|
|
document.getElementById('session-settings-form').addEventListener('submit', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
saveSessionSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 重置确认输入
|
|
|
|
|
|
document.getElementById('reset-confirm').addEventListener('input', function() {
|
|
|
|
|
|
const resetBtn = document.getElementById('reset-btn');
|
|
|
|
|
|
resetBtn.disabled = this.value !== 'RESET';
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 重置按钮
|
|
|
|
|
|
document.getElementById('reset-btn').addEventListener('click', function() {
|
|
|
|
|
|
resetSystem();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 清理缓存按钮
|
|
|
|
|
|
document.getElementById('clear-cache-btn').addEventListener('click', function() {
|
|
|
|
|
|
clearCache();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 备份按钮
|
|
|
|
|
|
document.getElementById('backup-btn').addEventListener('click', function() {
|
|
|
|
|
|
backupData();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存基本设置
|
|
|
|
|
|
function saveBasicSettings() {
|
|
|
|
|
|
const saveBtn = document.getElementById('save-basic-btn');
|
|
|
|
|
|
const saveText = document.getElementById('save-basic-text');
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载状态
|
|
|
|
|
|
saveBtn.disabled = true;
|
|
|
|
|
|
saveText.textContent = '保存中...';
|
|
|
|
|
|
|
|
|
|
|
|
// 收集表单数据
|
|
|
|
|
|
const formData = {
|
|
|
|
|
|
site_name: document.getElementById('site_name').value,
|
|
|
|
|
|
admin_email: document.getElementById('admin_email').value,
|
2025-11-16 19:06:49 +08:00
|
|
|
|
frontend_domain: document.getElementById('frontend_domain').value,
|
2025-11-11 21:39:12 +08:00
|
|
|
|
max_failed_attempts: parseInt(document.getElementById('max_failed_attempts').value),
|
|
|
|
|
|
lockout_minutes: parseInt(document.getElementById('lockout_minutes').value),
|
|
|
|
|
|
max_unbind_times: parseInt(document.getElementById('max_unbind_times').value),
|
|
|
|
|
|
auth_secret_key: document.getElementById('auth_secret_key').value
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求保存设置
|
|
|
|
|
|
fetch('/api/v1/settings', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify(formData)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
if (data.success) {
|
|
|
|
|
|
showNotification('基本设置保存成功', 'success');
|
|
|
|
|
|
// 更新页面标题(如果修改了系统名称)
|
|
|
|
|
|
if (formData.site_name) {
|
|
|
|
|
|
document.title = formData.site_name + ' - 软件授权管理系统';
|
|
|
|
|
|
// 更新页面标题元素
|
|
|
|
|
|
const pageTitle = document.querySelector('h1.h2');
|
|
|
|
|
|
if (pageTitle) {
|
|
|
|
|
|
pageTitle.textContent = formData.site_name;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showNotification('保存失败: ' + data.message, 'error');
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('Error:', error);
|
|
|
|
|
|
showNotification('保存失败,请查看控制台了解详情', 'error');
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
saveBtn.disabled = false;
|
|
|
|
|
|
saveText.textContent = '保存设置';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存卡密设置
|
|
|
|
|
|
function saveLicenseSettings() {
|
|
|
|
|
|
const saveBtn = document.getElementById('save-license-btn');
|
|
|
|
|
|
const saveText = document.getElementById('save-license-text');
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载状态
|
|
|
|
|
|
saveBtn.disabled = true;
|
|
|
|
|
|
saveText.textContent = '保存中...';
|
|
|
|
|
|
|
|
|
|
|
|
// 收集表单数据
|
|
|
|
|
|
const formData = {
|
|
|
|
|
|
license_key_length: parseInt(document.getElementById('license_key_length').value),
|
|
|
|
|
|
license_key_prefix: document.getElementById('license_key_prefix').value,
|
|
|
|
|
|
trial_prefix: document.getElementById('trial_prefix').value,
|
|
|
|
|
|
offline_cache_days: parseInt(document.getElementById('offline_cache_days').value)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求保存设置
|
|
|
|
|
|
fetch('/api/v1/settings', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify(formData)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
if (data.success) {
|
|
|
|
|
|
showNotification('卡密设置保存成功', 'success');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showNotification('保存失败: ' + data.message, 'error');
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('Error:', error);
|
|
|
|
|
|
showNotification('保存失败,请查看控制台了解详情', 'error');
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
saveBtn.disabled = false;
|
|
|
|
|
|
saveText.textContent = '保存设置';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存API设置
|
|
|
|
|
|
function saveApiSettings() {
|
|
|
|
|
|
const saveBtn = document.getElementById('save-api-btn');
|
|
|
|
|
|
const saveText = document.getElementById('save-api-text');
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载状态
|
|
|
|
|
|
saveBtn.disabled = true;
|
|
|
|
|
|
saveText.textContent = '保存中...';
|
|
|
|
|
|
|
|
|
|
|
|
// 收集表单数据
|
|
|
|
|
|
const formData = {
|
|
|
|
|
|
api_version: document.getElementById('api_version').value,
|
|
|
|
|
|
items_per_page: parseInt(document.getElementById('items_per_page').value)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求保存设置
|
|
|
|
|
|
fetch('/api/v1/settings', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify(formData)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
if (data.success) {
|
|
|
|
|
|
showNotification('API设置保存成功', 'success');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showNotification('保存失败: ' + data.message, 'error');
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('Error:', error);
|
|
|
|
|
|
showNotification('保存失败,请查看控制台了解详情', 'error');
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
saveBtn.disabled = false;
|
|
|
|
|
|
saveText.textContent = '保存设置';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存文件上传设置
|
|
|
|
|
|
function saveUploadSettings() {
|
|
|
|
|
|
const saveBtn = document.getElementById('save-upload-btn');
|
|
|
|
|
|
const saveText = document.getElementById('save-upload-text');
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载状态
|
|
|
|
|
|
saveBtn.disabled = true;
|
|
|
|
|
|
saveText.textContent = '保存中...';
|
|
|
|
|
|
|
|
|
|
|
|
// 收集表单数据
|
|
|
|
|
|
const formData = {
|
|
|
|
|
|
max_content_length: parseInt(document.getElementById('max_content_length').value),
|
|
|
|
|
|
upload_folder: document.getElementById('upload_folder').value
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求保存设置
|
|
|
|
|
|
fetch('/api/v1/settings', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify(formData)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
if (data.success) {
|
|
|
|
|
|
showNotification('文件上传设置保存成功', 'success');
|
|
|
|
|
|
// 更新显示的上传限制信息
|
|
|
|
|
|
const maxContentLength = formData.max_content_length;
|
|
|
|
|
|
const uploadInfoElements = document.querySelectorAll('div.form-text');
|
|
|
|
|
|
uploadInfoElements.forEach(element => {
|
|
|
|
|
|
if (element.textContent.includes('当前设置:')) {
|
|
|
|
|
|
element.textContent = `当前设置: ${maxContentLength} MB`;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showNotification('保存失败: ' + data.message, 'error');
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('Error:', error);
|
|
|
|
|
|
showNotification('保存失败,请查看控制台了解详情', 'error');
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
saveBtn.disabled = false;
|
|
|
|
|
|
saveText.textContent = '保存设置';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存会话设置
|
|
|
|
|
|
function saveSessionSettings() {
|
|
|
|
|
|
const saveBtn = document.getElementById('save-session-btn');
|
|
|
|
|
|
const saveText = document.getElementById('save-session-text');
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载状态
|
|
|
|
|
|
saveBtn.disabled = true;
|
|
|
|
|
|
saveText.textContent = '保存中...';
|
|
|
|
|
|
|
|
|
|
|
|
// 收集表单数据
|
|
|
|
|
|
const formData = {
|
|
|
|
|
|
session_lifetime_hours: parseInt(document.getElementById('session_lifetime_hours').value)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求保存设置
|
|
|
|
|
|
fetch('/api/v1/settings', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify(formData)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
if (data.success) {
|
|
|
|
|
|
showNotification('会话设置保存成功', 'success');
|
|
|
|
|
|
// 更新显示的会话时间信息
|
|
|
|
|
|
const sessionHours = formData.session_lifetime_hours;
|
|
|
|
|
|
const sessionInfoElements = document.querySelectorAll('div.form-text');
|
|
|
|
|
|
sessionInfoElements.forEach(element => {
|
|
|
|
|
|
if (element.textContent.includes('当前设置:')) {
|
|
|
|
|
|
element.textContent = `当前设置: ${sessionHours} 小时`;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showNotification('保存失败: ' + data.message, 'error');
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('Error:', error);
|
|
|
|
|
|
showNotification('保存失败,请查看控制台了解详情', 'error');
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
saveBtn.disabled = false;
|
|
|
|
|
|
saveText.textContent = '保存设置';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 重置系统
|
|
|
|
|
|
function resetSystem() {
|
|
|
|
|
|
if (confirm('确定要重置系统吗?此操作无法恢复!')) {
|
|
|
|
|
|
showNotification('系统重置功能开发中...', 'info');
|
|
|
|
|
|
// 关闭模态框
|
|
|
|
|
|
const modal = bootstrap.Modal.getInstance(document.getElementById('resetModal'));
|
|
|
|
|
|
modal.hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清理缓存
|
|
|
|
|
|
function clearCache() {
|
|
|
|
|
|
showNotification('正在清理缓存...', 'info');
|
|
|
|
|
|
// 关闭模态框
|
|
|
|
|
|
const modal = bootstrap.Modal.getInstance(document.getElementById('clearCacheModal'));
|
|
|
|
|
|
modal.hide();
|
|
|
|
|
|
|
|
|
|
|
|
// 模拟清理过程
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
showNotification('缓存清理完成', 'success');
|
|
|
|
|
|
}, 2000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 数据备份
|
|
|
|
|
|
function backupData() {
|
|
|
|
|
|
showNotification('正在创建数据备份...', 'info');
|
|
|
|
|
|
// 关闭模态框
|
|
|
|
|
|
const modal = bootstrap.Modal.getInstance(document.getElementById('backupModal'));
|
|
|
|
|
|
modal.hide();
|
|
|
|
|
|
|
|
|
|
|
|
// 模拟备份过程
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
showNotification('数据备份创建成功', 'success');
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
{% endblock %}
|