From aeb0696f457ca85b62d15ab6586c5779cf5cd97b Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Fri, 31 Jul 2026 16:56:21 +0800
Subject: [PATCH] feat(firewall): 添加访问日志功能

---
 src/main/resources/templates/febs/views/modules/system/firewallCountryList.html |  222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 222 insertions(+), 0 deletions(-)

diff --git a/src/main/resources/templates/febs/views/modules/system/firewallCountryList.html b/src/main/resources/templates/febs/views/modules/system/firewallCountryList.html
new file mode 100644
index 0000000..4fa105a
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/system/firewallCountryList.html
@@ -0,0 +1,222 @@
+<div class="layui-fluid layui-anim febs-anim" id="firewall-country-list" lay-title="防火墙国家白名单">
+    <div class="layui-row febs-container">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">站点国家白名单管理</div>
+                <div class="layui-card-body">
+                    <!-- 站点选择 -->
+                    <div class="layui-form-item">
+                        <label class="layui-form-label">选择站点:</label>
+                        <div class="layui-input-inline" style="width: 250px;">
+                            <select id="site-select" lay-filter="site-select" lay-search="">
+                                <option value="">请选择站点</option>
+                            </select>
+                        </div>
+                        <button class="layui-btn layui-btn-normal" type="button" id="reload-btn" style="margin-left: 10px;">
+                            <i class="layui-icon">&#xe669;</i> 手动reload
+                        </button>
+                    </div>
+
+                    <hr class="layui-bg-gray">
+
+                    <!-- 国家选择区域 -->
+                    <div id="country-area" style="display:none;">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">当前允许国家:</label>
+                            <div class="layui-input-block" id="current-countries" style="padding-top: 9px;">
+                                <span style="color:#999;">暂无数据</span>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">选择国家:</label>
+                            <div class="layui-input-block" id="country-checkboxes" style="padding-top: 5px;">
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <button class="layui-btn" lay-submit="" lay-filter="save-country-rule" id="save-btn">
+                                    <i class="layui-icon">&#xe605;</i> 保存规则
+                                </button>
+                                <span class="layui-word-aux" style="margin-left: 15px;">保存后自动生成Nginx配置并reload</span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<style>
+    .layui-form-label { width: 130px; }
+    .layui-form-item .layui-input-block { margin-left: 160px; }
+    .country-tag {
+        display: inline-block;
+        padding: 2px 12px;
+        margin: 2px 4px;
+        background: #5FB878;
+        color: #fff;
+        border-radius: 2px;
+        font-size: 13px;
+    }
+    .country-checkbox-item {
+        display: inline-block;
+        width: 140px;
+        margin: 4px 0;
+    }
+</style>
+
+<script data-th-inline="none" type="text/javascript">
+    layui.use(['jquery', 'form', 'febs', 'layer'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            form = layui.form,
+            layer = layui.layer,
+            $view = $('#firewall-country-list'),
+            currentSiteId = null;
+
+        // 常用国家列表
+        var allCountries = [
+            {code: 'BR', name: '巴西'},
+            {code: 'US', name: '美国'},
+            {code: 'JP', name: '日本'},
+            {code: 'KR', name: '韩国'},
+            {code: 'SG', name: '新加坡'},
+            {code: 'GB', name: '英国'},
+            {code: 'DE', name: '德国'},
+            {code: 'FR', name: '法国'},
+            {code: 'AU', name: '澳大利亚'},
+            {code: 'CA', name: '加拿大'},
+            {code: 'IT', name: '意大利'},
+            {code: 'ES', name: '西班牙'},
+            {code: 'NL', name: '荷兰'},
+            {code: 'SE', name: '瑞典'},
+            {code: 'CH', name: '瑞士'},
+            {code: 'MX', name: '墨西哥'},
+            {code: 'AR', name: '阿根廷'},
+            {code: 'CL', name: '智利'},
+            {code: 'CO', name: '哥伦比亚'},
+            {code: 'PE', name: '秘鲁'},
+            {code: 'TH', name: '泰国'},
+            {code: 'VN', name: '越南'},
+            {code: 'MY', name: '马来西亚'},
+            {code: 'ID', name: '印度尼西亚'},
+            {code: 'PH', name: '菲律宾'},
+            {code: 'IN', name: '印度'},
+            {code: 'AE', name: '阿联酋'},
+            {code: 'SA', name: '沙特阿拉伯'},
+            {code: 'ZA', name: '南非'},
+            {code: 'RU', name: '俄罗斯'},
+            {code: 'CN', name: '中国'},
+            {code: 'HK', name: '中国香港'},
+            {code: 'TW', name: '中国台湾'},
+            {code: 'MO', name: '中国澳门'}
+        ];
+
+        // 加载站点列表
+        function loadSites() {
+            febs.get(ctx + 'admin/firewall/sites', null, function (res) {
+                var sites = res.data || [];
+                var $select = $('#site-select');
+                $select.empty();
+                $select.append('<option value="">请选择站点</option>');
+                sites.forEach(function (s) {
+                    $select.append('<option value="' + s.id + '">' + s.siteName + ' (' + s.domain + ')</option>');
+                });
+                form.render('select');
+            });
+        }
+
+        // 加载当前站点的国家白名单
+        function loadCountries(siteId) {
+            currentSiteId = siteId;
+            febs.get(ctx + 'admin/firewall/site/' + siteId + '/countries', null, function (res) {
+                var countries = res.data || [];
+                var enabledCodes = {};
+                countries.forEach(function (c) {
+                    enabledCodes[c.code] = true;
+                });
+
+                // 先显示区域,再渲染表单元素(layui 在隐藏 DOM 上渲染可能失败)
+                $('#country-area').show();
+
+                // 渲染当前允许国家标签
+                var $current = $('#current-countries');
+                if (countries.length === 0) {
+                    $current.html('<span style="color:#999;">暂无允许的国家</span>');
+                } else {
+                    var html = '';
+                    countries.forEach(function (c) {
+                        html += '<span class="country-tag">' + c.name + ' (' + c.code + ')</span>';
+                    });
+                    $current.html(html);
+                }
+
+                // 渲染复选框(在可见区域中渲染)
+                var $checkboxes = $('#country-checkboxes');
+                var checkboxHtml = '';
+                allCountries.forEach(function (c) {
+                    var checked = enabledCodes[c.code] ? ' checked' : '';
+                    checkboxHtml += '<span class="country-checkbox-item">'
+                        + '<input type="checkbox" name="country" value="' + c.code + '" title="' + c.name + ' (' + c.code + ')" lay-skin="primary"' + checked + '>'
+                        + '</span>';
+                });
+                $checkboxes.html(checkboxHtml);
+                form.render('checkbox');
+
+                // 完整渲染一次表单,确保所有 layui 组件(select/checkbox/button)正确初始化
+                form.render(null, 'firewall-country-list');
+            });
+        }
+
+        // 站点切换
+        form.on('select(site-select)', function (data) {
+            if (data.value) {
+                loadCountries(data.value);
+            } else {
+                $('#country-area').hide();
+            }
+        });
+
+        // 保存规则
+        form.on('submit(save-country-rule)', function () {
+            if (!currentSiteId) {
+                layer.msg('请先选择站点', {icon: 2});
+                return false;
+            }
+
+            var countries = [];
+            $view.find('input[name="country"]:checked').each(function () {
+                countries.push($(this).val());
+            });
+
+            febs.post(ctx + 'admin/firewall/site/country/save', {
+                siteId: currentSiteId,
+                countries: countries
+            }, function (res) {
+                layer.msg('保存成功,Nginx 配置已更新', {icon: 1});
+                loadCountries(currentSiteId);
+            });
+            return false;
+        });
+
+        // 手动reload
+        $('#reload-btn').on('click', function () {
+            if (!currentSiteId) {
+                layer.msg('请先选择站点', {icon: 2});
+                return;
+            }
+            layer.confirm('确定要手动触发 Nginx reload 吗?', function (index) {
+                febs.post(ctx + 'admin/firewall/site/' + currentSiteId + '/reload', {}, function (res) {
+                    layer.close(index);
+                    layer.msg('Nginx reload 信号已发送', {icon: 1});
+                });
+            });
+        });
+
+        // 初始化
+        loadSites();
+    });
+</script>

--
Gitblit v1.9.1