diff --git a/favicon.png b/favicon.png
new file mode 100644
index 0000000..a78b7fe
Binary files /dev/null and b/favicon.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..89508ee
--- /dev/null
+++ b/index.html
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+ 哪吒面板流量警告规则生成器
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..451f8a5
--- /dev/null
+++ b/script.js
@@ -0,0 +1,156 @@
+$(document).ready(function () {
+ // 获取所有时区
+ const allTimezones = moment.tz.names();
+
+ // 按 UTC 偏移量排序时区
+ allTimezones.sort((a, b) => {
+ const offsetA = moment.tz(a).utcOffset();
+ const offsetB = moment.tz(b).utcOffset();
+ return offsetA - offsetB;
+ });
+
+ // 生成时区选项
+ const timezoneOptions = allTimezones.map(timezone => {
+ const offset = moment.tz(timezone).format('Z');
+ return ``;
+ }).join('');
+
+
+ $('#cycleStartTimezone').html(timezoneOptions);
+
+ // 设置默认时区为 UTC+8 上海时间
+ $('#cycleStartTimezone').val('Asia/Shanghai');
+
+ // 初始化日期选择器
+ const datePickr = flatpickr('#cycleStartDate', {
+ defaultDate: moment().startOf('month').toDate(),
+ dateFormat: 'Y-m-d',
+ onChange: updateCycleStart
+ });
+
+ // 初始化时间选择器
+ const timePickr = flatpickr('#cycleStartTime', {
+ noCalendar: true,
+ enableTime: true,
+ dateFormat: 'H:i',
+ time_24hr: true,
+ defaultDate: '00:00',
+ onChange: updateCycleStart
+ });
+
+ // 页面加载时生成初始的 RFC3339 和 规则
+ updateCycleStart();
+ generateRule();
+
+ // 更新统计周期开始时间
+ function updateCycleStart() {
+ const timezone = $('#cycleStartTimezone').val();
+ const date = $('#cycleStartDate').val();
+ const time = $('#cycleStartTime').val();
+ const formattedDate = moment.tz(`${date} ${time}`, timezone).format();
+ $('#cycleStart').val(formattedDate);
+ generateRule();
+ }
+
+ // 防止用户编辑 RFC3339 格式时间
+ $('#cycleStart').on('input', function () {
+ showErrorModal('请使用上方的时间选择器选择时间');
+ $(this).val(moment.tz($('#cycleStartDate').val() + ' ' + $('#cycleStartTime').val(), $('#cycleStartTimezone').val()).format());
+ });
+
+ // 生成规则按钮
+ $('#generateRuleBtn').click(generateRule);
+
+ // 生成规则
+ function generateRule() {
+ const serverIds = $('#serverIds').val().split(',').map(id => id.trim());
+ const cycleStart = $('#cycleStart').val();
+ const trafficType = $('#trafficType').val();
+ const cycleUnit = $('#cycleUnit').val();
+ const cycleInterval = parseInt($('#cycleInterval').val());
+ const maxTraffic = $('#maxTraffic').val() * $('#trafficUnit').val();
+
+ if (!validateInput(serverIds, cycleStart, trafficType, cycleUnit, cycleInterval, maxTraffic)) {
+ return;
+ }
+
+ const rule = [{
+ type: trafficType,
+ max: maxTraffic,
+ cycle_start: cycleStart,
+ cycle_interval: cycleInterval,
+ cycle_unit: cycleUnit,
+ cover: 1,
+ ignore: serverIds.reduce((obj, id) => {
+ obj[id] = true;
+ return obj;
+ }, {})
+ }];
+
+ const ruleJson = JSON.stringify(rule, null, 2);
+ $('#ruleOutput').text(ruleJson);
+ hljs.highlightBlock(document.getElementById('ruleOutput'));
+ }
+
+ // 复制规则按钮
+ $('#copyRuleBtn').click(function () {
+ const ruleOutput = document.getElementById('ruleOutput');
+ const range = document.createRange();
+ range.selectNode(ruleOutput);
+ window.getSelection().removeAllRanges();
+ window.getSelection().addRange(range);
+ document.execCommand('copy');
+ window.getSelection().removeAllRanges();
+ showSuccessModal('JSON 规则已复制到剪贴板');
+ });
+
+ // 输入验证
+ function validateInput(serverIds, cycleStart, trafficType, cycleUnit, cycleInterval, maxTraffic) {
+ if (serverIds.length === 0 || (serverIds.length === 1 && serverIds[0] === '')) {
+ showErrorModal('请输入服务器 ID');
+ return false;
+ }
+
+ if (!cycleStart) {
+ showErrorModal('请选择统计周期开始时间');
+ return false;
+ }
+
+ if (!trafficType) {
+ showErrorModal('请选择流量类型');
+ return false;
+ }
+
+ if (!cycleUnit) {
+ showErrorModal('请选择周期单位');
+ return false;
+ }
+
+ if (isNaN(cycleInterval) || cycleInterval <= 0) {
+ showErrorModal('请输入有效的周期间隔 (大于 0 的数字)');
+ return false;
+ }
+
+ if (isNaN(maxTraffic) || maxTraffic <= 0) {
+ showErrorModal('请输入有效的流量上限 (大于 0 的数字)');
+ return false;
+ }
+
+ return true;
+ }
+
+ // 时区选择器变更事件
+ $('#cycleStartTimezone').change(updateCycleStart);
+
+
+ function showErrorModal(message) {
+ $('#errorMessage').text(message);
+ $('#errorModal').modal('show');
+ }
+
+
+ function showSuccessModal(message) {
+ $('#errorMessage').text(message);
+ $('#errorModal').modal('show');
+ }
+});
\ No newline at end of file
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..6f5eab4
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,21 @@
+body {
+ background-color: #f8f9fa;
+}
+
+.container {
+ max-width: 800px;
+}
+
+.form-group label {
+ font-weight: bold;
+}
+
+#ruleOutput {
+ font-family: 'Courier New', Courier, monospace;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+.rule-output {
+ min-height: 200px;
+}
\ No newline at end of file