2025-10-24 00:09:45 +08:00
|
|
|
|
{{ define "settings.html" }}
|
|
|
|
|
|
<section>
|
|
|
|
|
|
<h2>系统设置</h2>
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<!-- 系统配置设置 -->
|
2025-10-26 11:57:31 +08:00
|
|
|
|
<div class="layui-panel" style="margin-top: 16px;">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<h3 style="margin: 0; padding: 15px 20px; border-bottom: 1px solid var(--lay-color-border-2); padding-bottom: 10px; margin-bottom: 15px;">安全配置</h3>
|
2025-10-26 11:57:31 +08:00
|
|
|
|
<div style="padding: 20px;">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<form class="layui-form" id="systemForm">
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-form-item">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="maintenance-mode">维护模式</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<div style="display: flex; align-items: center; justify-content: flex-start; gap: 10px;">
|
|
|
|
|
|
<input type="checkbox" name="maintenance_mode" lay-skin="switch" lay-text="开启|关闭" title="开启|关闭">
|
|
|
|
|
|
</div>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="encryption-key">加密密钥</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<div style="display: flex; gap: 10px;">
|
|
|
|
|
|
<input type="text" name="encryption_key" placeholder="请输入数据加密密钥" class="layui-input" readonly>
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-primary" id="generateEncBtn">生成</button>
|
|
|
|
|
|
</div>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="jwt-secret">JWT密钥</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<div style="display: flex; gap: 10px;">
|
|
|
|
|
|
<input type="text" name="jwt_secret" placeholder="请输入JWT签名密钥" class="layui-input" readonly>
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-primary" id="generateJwtBtn">生成</button>
|
|
|
|
|
|
</div>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="jwt-refresh">JWT刷新</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
|
|
|
|
<input type="number" name="jwt_refresh" placeholder="6" min="1" lay-affix="number" class="layui-input"
|
|
|
|
|
|
style="width: 120px;" />
|
|
|
|
|
|
<span class="layui-form-mid">小时(至少1小时)</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="jwt-expire">JWT有效期</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
|
|
|
|
<input type="number" name="jwt_expire" placeholder="24" min="1" lay-affix="number" class="layui-input"
|
|
|
|
|
|
style="width: 120px;" />
|
|
|
|
|
|
<span class="layui-form-mid">小时(至少1小时)</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="save_system">保存安全配置</button>
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm reset-btn" data-type="system">重置</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Cookie 设置 -->
|
|
|
|
|
|
<div class="layui-panel" style="margin-top: 16px;">
|
|
|
|
|
|
<h3 style="margin: 0; padding: 15px 20px; border-bottom: 1px solid var(--lay-color-border-2); padding-bottom: 10px; margin-bottom: 15px;">Cookie 设置</h3>
|
|
|
|
|
|
<div style="padding: 20px;">
|
|
|
|
|
|
<form class="layui-form" id="cookieForm">
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="cookie-secure">Secure</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<div style="display: flex; align-items: center; justify-content: flex-start; gap: 10px;">
|
|
|
|
|
|
<input type="checkbox" name="cookie_secure" lay-skin="switch" lay-text="开启|关闭" title="开启|关闭">
|
|
|
|
|
|
</div>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="cookie-samesite">Same</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<select name="cookie_same_site">
|
|
|
|
|
|
<option value="Strict">Strict</option>
|
|
|
|
|
|
<option value="Lax">Lax</option>
|
|
|
|
|
|
<option value="None">None</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="cookie-domain">Domain</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<input type="text" name="cookie_domain" placeholder="留空则默认为当前域名" class="layui-input">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="cookie-max-age">MaxAge</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
|
|
|
|
<input type="number" name="cookie_max_age" placeholder="86400" min="0" lay-affix="number" class="layui-input"
|
|
|
|
|
|
style="width: 120px;" />
|
|
|
|
|
|
<span class="layui-form-mid">秒</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="save_cookie">保存Cookie设置</button>
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm reset-btn" data-type="cookie">重置</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-26 03:05:27 +08:00
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<!-- 日志清理设置 -->
|
2025-10-26 11:57:31 +08:00
|
|
|
|
<div class="layui-panel" style="margin-top: 16px;">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<h3 style="margin: 0; padding: 15px 20px; border-bottom: 1px solid var(--lay-color-border-2); padding-bottom: 10px; margin-bottom: 15px;">日志清理设置</h3>
|
2025-10-26 11:57:31 +08:00
|
|
|
|
<div style="padding: 20px;">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<form class="layui-form" id="logCleanupForm">
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-form-item">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="login-log-cleanup">登录日志</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
|
|
|
|
<span class="layui-form-mid">保留</span>
|
|
|
|
|
|
<input type="number" name="login_log_cleanup_days" placeholder="30" min="0" lay-affix="number" class="layui-input" style="width: 80px;" />
|
|
|
|
|
|
<span class="layui-form-mid">天,且保留最近</span>
|
|
|
|
|
|
<input type="number" name="login_log_cleanup_limit" placeholder="10000" min="0" lay-affix="number" class="layui-input" style="width: 100px;" />
|
|
|
|
|
|
<span class="layui-form-mid">条(0为不限制)</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="operation-log-cleanup">操作日志</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
|
|
|
|
<span class="layui-form-mid">保留</span>
|
|
|
|
|
|
<input type="number" name="operation_log_cleanup_days" placeholder="30" min="0" lay-affix="number" class="layui-input" style="width: 80px;" />
|
|
|
|
|
|
<span class="layui-form-mid">天,且保留最近</span>
|
|
|
|
|
|
<input type="number" name="operation_log_cleanup_limit" placeholder="10000" min="0" lay-affix="number" class="layui-input" style="width: 100px;" />
|
|
|
|
|
|
<span class="layui-form-mid">条(0为不限制)</span>
|
|
|
|
|
|
</div>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
2026-03-18 21:51:17 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="save_cleanup">保存清理策略</button>
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm reset-btn" data-type="cleanup">重置</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 基本信息设置 -->
|
|
|
|
|
|
<div class="layui-panel" style="margin-top: 16px;">
|
|
|
|
|
|
<h3 style="margin: 0; padding: 15px 20px; border-bottom: 1px solid var(--lay-color-border-2); padding-bottom: 10px; margin-bottom: 15px;">基本信息设置</h3>
|
|
|
|
|
|
<div style="padding: 20px;">
|
|
|
|
|
|
<form class="layui-form" id="basicForm">
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="site-title">站点标题</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<input type="text" name="site_title" lay-verify="required" placeholder="请输入站点标题" class="layui-input" />
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="site-keywords">关键词</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<input type="text" name="site_keywords" placeholder="请输入站点关键词,多个关键词用逗号分隔" class="layui-input" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item layui-form-text">
|
|
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="site-description">站点描述</label>
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<textarea name="site_description" placeholder="请输入站点描述" class="layui-textarea"></textarea>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="site-logo">站点Logo</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<input type="text" name="site_logo" placeholder="/assets/logo.svg" class="layui-input" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="save_basic">保存基本信息</button>
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm reset-btn" data-type="basic">重置</button>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-26 03:05:27 +08:00
|
|
|
|
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<!-- 页脚与备案信息 -->
|
2025-10-26 11:57:31 +08:00
|
|
|
|
<div class="layui-panel" style="margin-top: 16px;">
|
|
|
|
|
|
<h3 style="margin: 0; padding: 15px 20px; border-bottom: 1px solid var(--lay-color-border-2); padding-bottom: 10px; margin-bottom: 15px;">页脚与备案</h3>
|
|
|
|
|
|
<div style="padding: 20px;">
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<form class="layui-form" id="footerForm">
|
|
|
|
|
|
<div class="layui-form-item layui-form-text">
|
2025-10-24 13:00:30 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="footer-text">页脚文本</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<textarea name="footer_text" placeholder="© 2025 凌动技术 保留所有权利" class="layui-textarea"></textarea>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2025-10-24 13:00:30 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="icp-record">ICP备案</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<input type="text" name="icp_record" placeholder="京ICP备12345678号" class="layui-input" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2025-10-24 13:00:30 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="icp-record-link">备案链接</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<input type="url" name="icp_record_link" placeholder="https://beian.miit.gov.cn" class="layui-input" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2025-10-24 13:00:30 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="psb-record">公安备案</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<input type="text" name="psb_record" placeholder="京公网安备11010802012345号" class="layui-input" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="layui-form-item">
|
2025-10-24 13:00:30 +08:00
|
|
|
|
<label class="layui-form-label" style="cursor: pointer;" data-tips="psb-record-link">备案链接</label>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
<div class="layui-input-block">
|
2025-10-26 03:05:27 +08:00
|
|
|
|
<input type="url" name="psb_record_link" placeholder="http://www.beian.gov.cn/portal/registerSystemInfo"
|
|
|
|
|
|
class="layui-input" />
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-18 21:51:17 +08:00
|
|
|
|
<div class="layui-form-item">
|
|
|
|
|
|
<div class="layui-input-block">
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-sm" lay-submit lay-filter="save_footer">保存页脚备案</button>
|
|
|
|
|
|
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm reset-btn" data-type="footer">重置</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-24 00:09:45 +08:00
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-10-24 13:00:30 +08:00
|
|
|
|
// 等待layui加载完成
|
|
|
|
|
|
function waitForLayui(callback) {
|
|
|
|
|
|
if (typeof layui !== 'undefined') {
|
|
|
|
|
|
callback();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
setTimeout(() => waitForLayui(callback), 100);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
waitForLayui(function () {
|
|
|
|
|
|
layui.use(['jquery', 'form', 'layer', 'util'], function () {
|
2025-10-24 13:00:30 +08:00
|
|
|
|
const { $, form, layer, util } = layui;
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
// 缓存上次加载的设置值,用于“重置”恢复
|
|
|
|
|
|
let originalSettings = {};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 加载后台所有设置并回填到三个表单
|
|
|
|
|
|
* - 从 /admin/api/settings 获取 name:value 映射
|
|
|
|
|
|
* - 处理开关型字段(maintenance_mode)
|
|
|
|
|
|
* - 渲染 layui 组件
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadSettings = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await fetch('/admin/api/settings', {
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
|
|
|
|
|
});
|
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
|
if (data.code !== 0) {
|
|
|
|
|
|
layer.msg(data.msg || '加载设置失败', { icon: 2 });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
originalSettings = data.data || {};
|
|
|
|
|
|
fillForms(originalSettings);
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('获取设置失败:', err);
|
|
|
|
|
|
layer.msg('网络错误,无法加载设置', { icon: 2 });
|
2025-10-24 00:09:45 +08:00
|
|
|
|
}
|
2025-10-26 03:05:27 +08:00
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将 settings 数据回填到各表单控件
|
2026-03-18 21:51:17 +08:00
|
|
|
|
* - 拆分为独立的填充函数,便于局部重置
|
2025-10-26 03:05:27 +08:00
|
|
|
|
*/
|
2026-03-18 21:51:17 +08:00
|
|
|
|
const fillSystem = (settings) => {
|
|
|
|
|
|
const maintenanceChecked = (settings.maintenance_mode || '0') === '1';
|
|
|
|
|
|
$('[name="maintenance_mode"]').prop('checked', maintenanceChecked);
|
|
|
|
|
|
$('[name="jwt_secret"]').val(settings.jwt_secret || '');
|
|
|
|
|
|
$('[name="encryption_key"]').val(settings.encryption_key || '');
|
|
|
|
|
|
$('[name="jwt_refresh"]').val(settings.jwt_refresh || '6');
|
|
|
|
|
|
$('[name="jwt_expire"]').val(settings.jwt_expire || '24');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const fillCookie = (settings) => {
|
|
|
|
|
|
const cookieSecureChecked = (settings.cookie_secure || 'true') === 'true' || settings.cookie_secure === '1';
|
|
|
|
|
|
$('[name="cookie_secure"]').prop('checked', cookieSecureChecked);
|
|
|
|
|
|
$('[name="cookie_same_site"]').val(settings.cookie_same_site || 'Lax');
|
|
|
|
|
|
$('[name="cookie_domain"]').val(settings.cookie_domain || '');
|
|
|
|
|
|
$('[name="cookie_max_age"]').val(settings.cookie_max_age || '86400');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const fillCleanup = (settings) => {
|
|
|
|
|
|
$('[name="login_log_cleanup_days"]').val(settings.login_log_cleanup_days || '30');
|
|
|
|
|
|
$('[name="login_log_cleanup_limit"]').val(settings.login_log_cleanup_limit || '10000');
|
|
|
|
|
|
$('[name="operation_log_cleanup_days"]').val(settings.operation_log_cleanup_days || '30');
|
|
|
|
|
|
$('[name="operation_log_cleanup_limit"]').val(settings.operation_log_cleanup_limit || '10000');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const fillBasic = (settings) => {
|
2025-10-26 03:05:27 +08:00
|
|
|
|
$('[name="site_title"]').val(settings.site_title || '');
|
|
|
|
|
|
$('[name="site_keywords"]').val(settings.site_keywords || '');
|
|
|
|
|
|
$('[name="site_description"]').val(settings.site_description || '');
|
|
|
|
|
|
$('[name="site_logo"]').val(settings.site_logo || '');
|
2026-03-18 21:51:17 +08:00
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
const fillFooter = (settings) => {
|
2025-10-26 03:05:27 +08:00
|
|
|
|
$('[name="footer_text"]').val(settings.footer_text || '');
|
|
|
|
|
|
$('[name="icp_record"]').val(settings.icp_record || '');
|
|
|
|
|
|
$('[name="icp_record_link"]').val(settings.icp_record_link || '');
|
|
|
|
|
|
$('[name="psb_record"]').val(settings.psb_record || '');
|
|
|
|
|
|
$('[name="psb_record_link"]').val(settings.psb_record_link || '');
|
2026-03-18 21:51:17 +08:00
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
const fillForms = (settings = {}) => {
|
|
|
|
|
|
fillBasic(settings);
|
|
|
|
|
|
fillSystem(settings);
|
|
|
|
|
|
fillCookie(settings);
|
|
|
|
|
|
fillCleanup(settings);
|
|
|
|
|
|
fillFooter(settings);
|
2025-10-26 03:05:27 +08:00
|
|
|
|
// 渲染 layui 组件
|
|
|
|
|
|
form.render();
|
|
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 收集某个表单下所有可用控件的值
|
|
|
|
|
|
* - 统一将 checkbox 转为 "1"/"0"
|
|
|
|
|
|
* - 其他控件转为字符串,避免后端类型不一致
|
|
|
|
|
|
*/
|
|
|
|
|
|
const collectForm = (selector) => {
|
|
|
|
|
|
const obj = {};
|
|
|
|
|
|
const $form = $(selector);
|
|
|
|
|
|
$form.find('input, textarea, select').each(function () {
|
|
|
|
|
|
const $el = $(this);
|
|
|
|
|
|
const name = $el.attr('name');
|
|
|
|
|
|
if (!name) return; // 无 name 不纳入
|
|
|
|
|
|
const type = ($el.attr('type') || '').toLowerCase();
|
|
|
|
|
|
let value = '';
|
|
|
|
|
|
if (type === 'checkbox') {
|
|
|
|
|
|
value = $el.prop('checked') ? '1' : '0';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value = ($el.val() ?? '').toString();
|
|
|
|
|
|
}
|
|
|
|
|
|
obj[name] = value;
|
|
|
|
|
|
});
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 汇总三个表单的字段为一个扁平对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
const collectAllSettings = () => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...collectForm('#basicForm'),
|
|
|
|
|
|
...collectForm('#systemForm'),
|
2026-03-18 21:51:17 +08:00
|
|
|
|
...collectForm('#cookieForm'),
|
2025-10-26 03:05:27 +08:00
|
|
|
|
...collectForm('#footerForm'),
|
2026-03-18 21:51:17 +08:00
|
|
|
|
...collectForm('#logCleanupForm'),
|
2025-10-26 03:05:27 +08:00
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
/**
|
2026-03-18 21:51:17 +08:00
|
|
|
|
* 提交设置到后端
|
|
|
|
|
|
* @param {Object} payload - 要保存的设置对象
|
|
|
|
|
|
* @param {HTMLElement} btnElem - 触发保存的按钮元素(用于禁用/恢复)
|
|
|
|
|
|
* @param {String} successMsg - 成功提示信息
|
2025-10-26 03:05:27 +08:00
|
|
|
|
*/
|
2026-03-18 21:51:17 +08:00
|
|
|
|
const submitSettings = (payload, btnElem, successMsg = '保存成功') => {
|
|
|
|
|
|
const $btn = $(btnElem);
|
|
|
|
|
|
$btn.prop('disabled', true).addClass('layui-btn-disabled');
|
|
|
|
|
|
const loadIdx = layer.msg('正在保存...', {
|
|
|
|
|
|
icon: 16,
|
|
|
|
|
|
time: 0,
|
|
|
|
|
|
shade: 0.1
|
|
|
|
|
|
});
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
fetch('/admin/api/settings/update', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify(payload)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(resp => resp.json())
|
|
|
|
|
|
.then(res => {
|
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
|
layer.msg(res.msg || successMsg, { icon: 1, time: 1000 });
|
|
|
|
|
|
// 更新本地缓存,合并新保存的设置
|
|
|
|
|
|
originalSettings = { ...originalSettings, ...payload };
|
|
|
|
|
|
} else {
|
|
|
|
|
|
layer.msg(res.msg || '保存失败', { icon: 2 });
|
|
|
|
|
|
}
|
2025-10-24 00:09:45 +08:00
|
|
|
|
})
|
2026-03-18 21:51:17 +08:00
|
|
|
|
.catch(err => {
|
|
|
|
|
|
console.error('保存设置失败:', err);
|
|
|
|
|
|
var msg = '网络错误,保存失败';
|
|
|
|
|
|
if (err.response && err.response.data && err.response.data.msg) {
|
|
|
|
|
|
msg = err.response.data.msg;
|
|
|
|
|
|
} else if (err.message) {
|
|
|
|
|
|
msg = err.message;
|
|
|
|
|
|
}
|
|
|
|
|
|
layer.msg(msg, { icon: 2 });
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
layer.close(loadIdx);
|
|
|
|
|
|
$btn.prop('disabled', false).removeClass('layui-btn-disabled');
|
|
|
|
|
|
});
|
2025-10-26 03:05:27 +08:00
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
/**
|
2026-03-18 21:51:17 +08:00
|
|
|
|
* 绑定各个分块的保存按钮
|
|
|
|
|
|
*/
|
|
|
|
|
|
form.on('submit(save_system)', function(data){
|
|
|
|
|
|
submitSettings(collectForm('#systemForm'), data.elem, '安全配置已保存');
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
form.on('submit(save_cookie)', function(data){
|
|
|
|
|
|
submitSettings(collectForm('#cookieForm'), data.elem, 'Cookie设置已保存');
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
form.on('submit(save_cleanup)', function(data){
|
|
|
|
|
|
submitSettings(collectForm('#logCleanupForm'), data.elem, '清理策略已保存');
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
form.on('submit(save_basic)', function(data){
|
|
|
|
|
|
submitSettings(collectForm('#basicForm'), data.elem, '基本信息已保存');
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
form.on('submit(save_footer)', function(data){
|
|
|
|
|
|
submitSettings(collectForm('#footerForm'), data.elem, '页脚备案已保存');
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 处理各个分块的重置按钮
|
|
|
|
|
|
*/
|
|
|
|
|
|
$(document).on('click', '.reset-btn', function() {
|
|
|
|
|
|
const type = $(this).data('type');
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case 'system':
|
|
|
|
|
|
fillSystem(originalSettings);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'cookie':
|
|
|
|
|
|
fillCookie(originalSettings);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'cleanup':
|
|
|
|
|
|
fillCleanup(originalSettings);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'basic':
|
|
|
|
|
|
fillBasic(originalSettings);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'footer':
|
|
|
|
|
|
fillFooter(originalSettings);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
form.render();
|
|
|
|
|
|
layer.msg('已恢复该部分默认值', { icon: 1, time: 800 });
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 生成安全密钥
|
2025-10-26 03:05:27 +08:00
|
|
|
|
*/
|
2026-03-18 21:51:17 +08:00
|
|
|
|
const generateKey = async (type) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const loadIdx = layer.load(2);
|
|
|
|
|
|
const res = await fetch(`/admin/api/settings/generate_key?type=${type}`, {
|
|
|
|
|
|
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
|
|
|
|
|
});
|
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
|
layer.close(loadIdx);
|
|
|
|
|
|
|
|
|
|
|
|
if (data.code === 0) {
|
|
|
|
|
|
if (type === 'jwt') {
|
|
|
|
|
|
$('[name="jwt_secret"]').val(data.data.key);
|
|
|
|
|
|
} else if (type === 'encryption') {
|
|
|
|
|
|
$('[name="encryption_key"]').val(data.data.key);
|
|
|
|
|
|
}
|
|
|
|
|
|
layer.msg('生成成功', { icon: 1 });
|
|
|
|
|
|
} else {
|
|
|
|
|
|
layer.msg(data.msg || '生成失败', { icon: 2 });
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('生成密钥失败:', err);
|
|
|
|
|
|
layer.closeAll('loading');
|
|
|
|
|
|
layer.msg('网络错误', { icon: 2 });
|
|
|
|
|
|
}
|
2025-10-26 03:05:27 +08:00
|
|
|
|
};
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
$('#generateJwtBtn').on('click', () => generateKey('jwt'));
|
|
|
|
|
|
$('#generateEncBtn').on('click', () => generateKey('encryption'));
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 03:05:27 +08:00
|
|
|
|
// 初始化:加载设置
|
|
|
|
|
|
loadSettings();
|
2025-10-24 13:00:30 +08:00
|
|
|
|
});
|
2025-10-24 00:09:45 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
2026-03-18 21:51:17 +08:00
|
|
|
|
{{ end }}
|