Files
admin-frontend-domain/public/nzcfg.html
T

1209 lines
53 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<title>NEZHA配置生成器</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Arial', sans-serif;
}
body {
padding: 20px;
background-color: #f5f5f5;
}
.container {
display: flex;
flex-direction: column;
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.tabs {
display: flex;
background-color: #333;
}
.tab {
padding: 15px 20px;
color: white;
cursor: pointer;
transition: background-color 0.3s;
}
.tab.active {
background-color: #4CAF50;
}
.tab:hover:not(.active) {
background-color: #555;
}
.tab-content {
display: none;
padding: 20px;
}
.tab-content.active {
display: block;
}
.row {
display: flex;
margin-bottom: 20px;
}
.col-left {
flex: 1;
padding-right: 20px;
}
.col-right {
flex: 1;
position: relative;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"],
input[type="number"],
input[type="date"],
input[type="datetime-local"],
select {
width: 100%;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.input-group {
display: flex;
gap: 10px;
}
.input-group input,
.input-group select {
flex: 1;
}
.checkbox-group {
display: flex;
align-items: center;
margin-top: 5px;
}
.checkbox-group input {
margin-right: 8px;
}
#jsonOutput,
#jsonOutput2 {
width: 100%;
height: 500px;
padding: 15px;
background-color: #f8f8f8;
border: 1px solid #ddd;
border-radius: 4px;
font-family: monospace;
resize: none;
white-space: pre;
overflow-y: auto;
}
button {
padding: 10px 15px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
}
button:hover {
background-color: #45a049;
}
.copy-btn {
position: absolute;
top: 10px;
right: 10px;
padding: 5px 10px;
font-size: 12px;
z-index: 100;
}
.tag-container {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
min-height: 42px;
}
.tag {
display: inline-block;
background-color: #e0e0e0;
padding: 5px 10px;
border-radius: 15px;
font-size: 12px;
cursor: pointer;
}
.tag.selected {
background-color: #4CAF50;
color: white;
}
.tag-selector {
margin-top: 10px;
}
.tag-container {
margin-top: 10px;
}
.carrier-routes {
margin-top: 10px;
}
.carrier-group {
margin-bottom: 10px;
}
.carrier-label {
display: inline-block;
width: 50px;
font-weight: bold;
}
.section-title {
font-size: 18px;
margin-bottom: 15px;
padding-bottom: 5px;
border-bottom: 1px solid #eee;
color: #333;
}
.dark-mode .section-title {
color: #ffffff;
border-bottom-color: #4d4d4d;
}
.dark-mode .token.operator {
background: none;
}
.dark-mode code[class*="language-"] {
text-shadow: none;
}
.traffic-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
}
.traffic-grid>*:nth-child(1) {
grid-column: 1 / 2;
}
.traffic-grid>*:nth-child(2) {
grid-column: 2 / 3;
}
.traffic-grid>*:nth-child(3) {
grid-column: 3 / 4;
}
.traffic-grid>*:nth-child(4) {
grid-column: 2 / 3;
}
.traffic-grid>*:nth-child(5) {
grid-column: 3 / 4;
}
.traffic-grid>*:nth-child(1),
.traffic-grid>*:nth-child(4) {
width: 100%;
}
.amount-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.amount-grid>*:nth-child(1) {
grid-column: 1 / 2;
}
.amount-grid>*:nth-child(2) {
grid-column: 2 / 3;
}
.amount-grid>*:nth-child(3) {
grid-column: 2 / 3;
}
.bandwidth-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.bandwidth-grid>*:nth-child(1) {
grid-column: 1 / 2;
}
.bandwidth-grid>*:nth-child(2) {
grid-column: 2 / 3;
}
.bandwidth-grid>*:nth-child(3) {
grid-column: 2 / 3;
}
.dark-mode {
background-color: #1a1a1a !important;
color: #ffffff !important;
}
.dark-mode .container {
background-color: #2d2d2d;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.dark-mode input[type="text"],
.dark-mode input[type="number"],
.dark-mode input[type="date"],
.dark-mode input[type="datetime-local"],
.dark-mode select {
background-color: #3d3d3d;
color: #ffffff;
border-color: #4d4d4d;
}
.dark-mode #jsonOutput,
.dark-mode #jsonOutput2 {
background-color: #2d2d2d;
border-color: #4d4d4d;
color: #ffffff;
}
.dark-mode .tag {
background-color: #4d4d4d;
color: #ffffff;
}
.dark-mode .tag.selected {
background-color: #4CAF50;
}
.theme-switch {
display: flex;
align-items: center;
margin-left: auto;
padding: 0 10px;
}
#themeToggle {
background: none;
border: none;
color: #fff;
cursor: pointer;
padding: 8px;
border-radius: 50%;
transition: all 0.3s ease;
font-size: 1.2em;
}
#themeToggle:hover {
background-color: rgba(255, 255, 255, 0.1);
transform: rotate(15deg);
}
#themeToggle[data-theme="system"] .fa-sun,
#themeToggle[data-theme="system"] .fa-moon {
display: none;
}
#themeToggle[data-theme="system"] .fa-desktop {
display: inline-block;
}
#themeToggle[data-theme="dark"] .fa-sun,
#themeToggle[data-theme="dark"] .fa-desktop {
display: none;
}
#themeToggle[data-theme="dark"] .fa-moon {
display: inline-block;
}
#themeToggle[data-theme="light"] .fa-moon,
#themeToggle[data-theme="light"] .fa-desktop {
display: none;
}
#themeToggle[data-theme="light"] .fa-sun {
display: inline-block;
}
.github-link {
display: flex;
align-items: center;
padding: 0 10px;
padding-right: 20px;
}
.github-link a {
color: #fff;
font-size: 1.2em;
transition: color 0.3s ease;
}
.github-link a:hover {
color: #4CAF50;
}
</style>
</head>
<body>
<div class="container">
<div class="tabs">
<div class="tab active" onclick="switchTab(0)">公开备注代码</div>
<div class="tab" onclick="switchTab(1)">流量监控代码</div>
<div class="theme-switch">
<button id="themeToggle" onclick="toggleTheme()" data-theme="system">
<i class="fas fa-desktop"></i>
</button>
</div>
<div class="github-link">
<a href="https://github.com/ohotto/nzcfg" target="_blank" title="查看GitHub源码">
<i class="fab fa-github"></i>
</a>
</div>
</div>
<!-- 公开备注代码 -->
<div class="tab-content active" id="publicNoteTab">
<div class="row">
<div class="col-left">
<h3 class="section-title">公开备注代码配置</h3>
<div class="form-group">
<label>时区 (timezone)</label>
<select id="timezone1">
<option value="-12:00">UTC-12:00 (贝克岛)</option>
<option value="-11:00">UTC-11:00 (萨摩亚)</option>
<option value="-10:00">UTC-10:00 (夏威夷)</option>
<option value="-09:00">UTC-09:00 (阿拉斯加)</option>
<option value="-08:00">UTC-08:00 (洛杉矶)</option>
<option value="-07:00">UTC-07:00 (丹佛)</option>
<option value="-06:00">UTC-06:00 (芝加哥)</option>
<option value="-05:00">UTC-05:00 (纽约)</option>
<option value="-04:00">UTC-04:00 (圣地亚哥)</option>
<option value="-03:00">UTC-03:00 (布宜诺斯艾利斯)</option>
<option value="-02:00">UTC-02:00 (费尔南多·迪诺罗尼亚群岛)</option>
<option value="-01:00">UTC-01:00 (佛得角)</option>
<option value="+00:00">UTC+00:00 (伦敦)</option>
<option value="+01:00">UTC+01:00 (巴黎)</option>
<option value="+02:00">UTC+02:00 (开罗)</option>
<option value="+03:00">UTC+03:00 (莫斯科)</option>
<option value="+04:00">UTC+04:00 (迪拜)</option>
<option value="+05:00">UTC+05:00 (卡拉奇)</option>
<option value="+06:00">UTC+06:00 (达卡)</option>
<option value="+07:00">UTC+07:00 (曼谷)</option>
<option value="+08:00" selected>UTC+08:00 (北京)</option>
<option value="+09:00">UTC+09:00 (东京)</option>
<option value="+10:00">UTC+10:00 (悉尼)</option>
<option value="+11:00">UTC+11:00 (所罗门群岛)</option>
<option value="+12:00">UTC+12:00 (奥克兰)</option>
</select>
</div>
<div class="form-group">
<label>账单起始日期 (startDate)</label>
<input type="datetime-local" id="startDate">
</div>
<div class="form-group">
<label>账单结束日期 (endDate)</label>
<input type="datetime-local" id="endDate">
<div class="checkbox-group">
<input type="checkbox" id="unlimitedEndDate" onchange="toggleEndDate()">
<label for="unlimitedEndDate" style="display:inline; font-weight:normal;">无限期</label>
</div>
</div>
<div class="form-group">
<label>自动续费状态 (autoRenewal)</label>
<select id="autoRenewal">
<option value="1">启用 (1)</option>
<option value="0">禁用 (0)</option>
</select>
</div>
<div class="form-group">
<label>账单周期 (cycle)</label>
<select id="cycle" onchange="toggleCustomCycle()">
<option value="月"></option>
<option value="年"></option>
<option value="季"></option>
<option value="半年">半年</option>
<option value="2年">2年</option>
<option value="3年">3年</option>
<option value="custom">自定义</option>
</select>
<input type="text" id="cycleCustom" placeholder="自定义周期" style="display:none; margin-top:5px;">
</div>
<div class="form-group">
<label>账单金额及货币单位 (amount)</label>
<div class="checkbox-group">
<input type="checkbox" id="freeamount" onchange="toggleAmount()">
<label for="freeamount" style="display:inline; font-weight:normal;">免费</label>
</div>
<div class="amount-grid" id="amountInputGroup">
<input type="number" id="amountValue" placeholder="金额">
<select id="amountCurrency" onchange="toggleCustomAmount()">
<option value="元"></option>
<option value="CNY">CNY</option>
<option value="刀"></option>
<option value="USD">USD</option>
<option value="欧"></option>
<option value="EUR">EUR</option>
<option value="custom">自定义</option>
</select>
<input type="text" id="amountCustom" placeholder="自定义货币单位" style="display:none;">
</div>
</div>
<div class="form-group">
<label>服务器带宽信息 (bandwidth)</label>
<div class="checkbox-group">
<input type="checkbox" id="unlimitedBandwidth" onchange="toggleBandwidth()">
<label for="unlimitedBandwidth" style="display:inline; font-weight:normal;">无限</label>
</div>
<div class="bandwidth-grid" id="bandwidthInputGroup">
<input type="number" id="bandwidthValue" placeholder="带宽">
<select id="bandwidthUnit" onchange="toggleCustomBandwidth()">
<option value="Gbps">Gbps</option>
<option value="Mbps">Mbps</option>
<option value="custom">自定义</option>
</select>
<input type="text" id="bandwidthCustom" placeholder="自定义带宽单位" style="display:none;">
</div>
</div>
<div class="form-group">
<label>流量配额及周期 (trafficVol)</label>
<div class="checkbox-group">
<input type="checkbox" id="unlimitedTraffic" onchange="toggleTraffic()">
<label for="unlimitedTraffic" style="display:inline; font-weight:normal;">无限</label>
</div>
<div class="traffic-grid" id="trafficInputGroup">
<input type="number" id="trafficValue" placeholder="流量">
<select id="trafficUnit" onchange="toggleCustomTraffic()">
<option value="TB">TB</option>
<option value="GB">GB</option>
<option value="MB">MB</option>
<option value="custom">自定义</option>
</select>
<select id="trafficPeriod" onchange="toggleCustomTraffic()">
<option value="/月">/月</option>
<option value="/M">/M</option>
<option value="custom">自定义</option>
</select>
<input type="text" id="trafficUnitCustom" placeholder="自定义流量单位" style="display:none;">
<input type="text" id="trafficPeriodCustom" placeholder="自定义周期" style="display:none;">
</div>
</div>
<div class="form-group">
<label>流量类型 (trafficType)</label>
<select id="trafficType">
<option value="1">单向 (1)</option>
<option value="2">双向 (2)</option>
</select>
</div>
<div class="form-group">
<label>IPv4 地址数量</label>
<input type="number" id="ipv4" min="0" value="1">
</div>
<div class="form-group">
<label>IPv6 地址数量</label>
<input type="number" id="ipv6" min="0" value="1">
</div>
<div class="form-group">
<label>网络路由信息 (networkRoute)</label>
<select id="routeMode" onchange="toggleRouteMode()">
<option value="tags">多选标签模式</option>
<option value="carriers">分运营商线路模式</option>
</select>
<div id="selectedTags">
<div class="tag-container" id="selectedTagsContainer"></div>
<input type="text" id="newTagInput" placeholder="输入标签并按回车添加">
</div>
<div id="tagsMode" class="tag-selector">
<div class="tag-container" id="routeTags">
<span class="tag" onclick="toggleTag(this)">163</span>
<span class="tag" onclick="toggleTag(this)">CN2</span>
<span class="tag" onclick="toggleTag(this)">CN2GIA</span>
<span class="tag" onclick="toggleTag(this)">CMI</span>
<span class="tag" onclick="toggleTag(this)">CMIN2</span>
<span class="tag" onclick="toggleTag(this)">4837</span>
<span class="tag" onclick="toggleTag(this)">10099</span>
<span class="tag" onclick="toggleTag(this)">IEPL</span>
<span class="tag" onclick="toggleTag(this)">IPLC</span>
</div>
</div>
<div id="carriersMode" class="carrier-routes" style="display:none;">
<div class="carrier-group">
<span class="carrier-label">电信:</span>
</div>
<div class="carrier-group" style="display: flex; align-items: center; gap: 10px;">
<span style="white-space: nowrap;">去程:</span>
<select id="telecomRoute1">
<option value="">留空</option>
<option value="163">163</option>
<option value="CN2">CN2</option>
<option value="CN2GIA">CN2GIA</option>
<option value="CMI">CMI</option>
<option value="CMIN2">CMIN2</option>
<option value="4837">4837</option>
<option value="10099">10099</option>
<option value="IEPL">IEPL</option>
<option value="IPLC">IPLC</option>
</select>
</div>
<div class="carrier-group" style="display: flex; align-items: center; gap: 10px;">
<span style="white-space: nowrap;">回程:</span>
<select id="telecomRoute2">
<option value="">留空</option>
<option value="163">163</option>
<option value="CN2">CN2</option>
<option value="CN2GIA">CN2GIA</option>
<option value="CMI">CMI</option>
<option value="CMIN2">CMIN2</option>
<option value="4837">4837</option>
<option value="10099">10099</option>
<option value="IEPL">IEPL</option>
<option value="IPLC">IPLC</option>
</select>
</div>
<div class="carrier-group">
<span class="carrier-label">移动:</span>
</div>
<div class="carrier-group" style="display: flex; align-items: center; gap: 10px;">
<span style="white-space: nowrap;">去程:</span>
<select id="mobileRoute1">
<option value="">留空</option>
<option value="163">163</option>
<option value="CN2">CN2</option>
<option value="CN2GIA">CN2GIA</option>
<option value="CMI">CMI</option>
<option value="CMIN2">CMIN2</option>
<option value="4837">4837</option>
<option value="10099">10099</option>
<option value="IEPL">IEPL</option>
<option value="IPLC">IPLC</option>
</select>
</div>
<div class="carrier-group" style="display: flex; align-items: center; gap: 10px;">
<span style="white-space: nowrap;">回程:</span>
<select id="mobileRoute2">
<option value="">留空</option>
<option value="163">163</option>
<option value="CN2">CN2</option>
<option value="CN2GIA">CN2GIA</option>
<option value="CMI">CMI</option>
<option value="CMIN2">CMIN2</option>
<option value="4837">4837</option>
<option value="10099">10099</option>
<option value="IEPL">IEPL</option>
<option value="IPLC">IPLC</option>
</select>
</div>
<div class="carrier-group">
<span class="carrier-label">联通:</span>
</div>
<div class="carrier-group" style="display: flex; align-items: center; gap: 10px;">
<span style="white-space: nowrap;">去程:</span>
<select id="unicomRoute1">
<option value="">留空</option>
<option value="163">163</option>
<option value="CN2">CN2</option>
<option value="CN2GIA">CN2GIA</option>
<option value="CMI">CMI</option>
<option value="CMIN2">CMIN2</option>
<option value="4837">4837</option>
<option value="10099">10099</option>
<option value="IEPL">IEPL</option>
<option value="IPLC">IPLC</option>
</select>
</div>
<div class="carrier-group" style="display: flex; align-items: center; gap: 10px;">
<span style="white-space: nowrap;">回程:</span>
<select id="unicomRoute2">
<option value="">留空</option>
<option value="163">163</option>
<option value="CN2">CN2</option>
<option value="CN2GIA">CN2GIA</option>
<option value="CMI">CMI</option>
<option value="CMIN2">CMIN2</option>
<option value="4837">4837</option>
<option value="10099">10099</option>
<option value="IEPL">IEPL</option>
<option value="IPLC">IPLC</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label>额外备注 (extra)</label>
<input type="text" id="extra">
</div>
<button onclick="generatePublicNoteJSON()">生成 JSON</button>
</div>
<div class="col-right">
<button class="copy-btn" onclick="copyToClipboard('jsonOutput')">复制到剪贴板</button>
<pre id="jsonOutput"><code class="language-json"></code></pre>
</div>
</div>
</div>
<!-- 流量监控代码 -->
<div class="tab-content" id="trafficMonitorTab">
<div class="row">
<div class="col-left">
<h3 class="section-title">流量监控代码配置</h3>
<div class="form-group">
<label>时区 (timezone)</label>
<select id="timezone2">
<option value="-12:00">UTC-12:00 (贝克岛)</option>
<option value="-11:00">UTC-11:00 (萨摩亚)</option>
<option value="-10:00">UTC-10:00 (夏威夷)</option>
<option value="-09:00">UTC-09:00 (阿拉斯加)</option>
<option value="-08:00">UTC-08:00 (洛杉矶)</option>
<option value="-07:00">UTC-07:00 (丹佛)</option>
<option value="-06:00">UTC-06:00 (芝加哥)</option>
<option value="-05:00">UTC-05:00 (纽约)</option>
<option value="-04:00">UTC-04:00 (圣地亚哥)</option>
<option value="-03:00">UTC-03:00 (布宜诺斯艾利斯)</option>
<option value="-02:00">UTC-02:00 (费尔南多·迪诺罗尼亚群岛)</option>
<option value="-01:00">UTC-01:00 (佛得角)</option>
<option value="+00:00">UTC+00:00 (伦敦)</option>
<option value="+01:00">UTC+01:00 (巴黎)</option>
<option value="+02:00">UTC+02:00 (开罗)</option>
<option value="+03:00">UTC+03:00 (莫斯科)</option>
<option value="+04:00">UTC+04:00 (迪拜)</option>
<option value="+05:00">UTC+05:00 (卡拉奇)</option>
<option value="+06:00">UTC+06:00 (达卡)</option>
<option value="+07:00">UTC+07:00 (曼谷)</option>
<option value="+08:00" selected>UTC+08:00 (北京)</option>
<option value="+09:00">UTC+09:00 (东京)</option>
<option value="+10:00">UTC+10:00 (悉尼)</option>
<option value="+11:00">UTC+11:00 (所罗门群岛)</option>
<option value="+12:00">UTC+12:00 (奥克兰)</option>
</select>
</div>
<div class="form-group">
<label>监控类型 (type)</label>
<select id="monitorType">
<option value="transfer_in_cycle">仅入站流量</option>
<option value="transfer_out_cycle">仅出站流量</option>
<option value="transfer_all_cycle">双向流量总和</option>
</select>
</div>
<div class="form-group">
<label>最大流量限制 (max)</label>
<div class="input-group">
<input type="number" id="maxTraffic" placeholder="流量数值">
<select id="maxTrafficUnit">
<option value="TB">TB</option>
<option value="GB">GB</option>
<option value="MB">MB</option>
</select>
</div>
</div>
<div class="form-group">
<label>统计周期开始日期 (cycle_start)</label>
<input type="datetime-local" id="cycleStart">
</div>
<div class="form-group">
<label>统计周期数量 (cycle_interval)</label>
<input type="number" id="cycleInterval" min="1" value="1">
</div>
<div class="form-group">
<label>统计周期单位 (cycle_unit)</label>
<select id="cycleUnit">
<option value="hour">小时 (hour)</option>
<option value="day">天 (day)</option>
<option value="week">周 (week)</option>
<option value="month">月 (month)</option>
<option value="year">年 (year)</option>
</select>
</div>
<div class="form-group" style="display:none;">
<label>是否覆盖 (cover)</label>
<select id="cover">
<option value="1">是 (1)</option>
<option value="0">否 (0)</option>
</select>
</div>
<div class="form-group">
<label>监控的服务器ID (ignore)</label>
<input type="text" id="ignore" placeholder="输入服务器ID,用逗号分隔,如:3,4">
</div>
<button onclick="generateTrafficMonitorJSON()">生成 JSON</button>
</div>
<div class="col-right">
<button class="copy-btn" onclick="copyToClipboard('jsonOutput2')">复制到剪贴板</button>
<pre id="jsonOutput2"><code class="language-json"></code></pre>
</div>
</div>
</div>
</div>
<script>
function formatDateWithTimezone(dateTimeString, tz) {
return dateTimeString + ":00" + tz;
}
document.getElementById('startDate').value = getNowDateTimeLocal();
document.getElementById('endDate').value = getNowDateTimeLocal();
document.getElementById('cycleStart').value = getNowDateTimeLocal();
function getNowDateTimeLocal() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hour = String(now.getHours()).padStart(2, '0'); // 获取当前小时
const minute = String(now.getMinutes()).padStart(2, '0'); // 获取当前分钟
return `${year}-${month}-${day}T${hour}:${minute}`;
}
function switchTab(tabIndex) {
const tabs = document.querySelectorAll('.tab');
const tabContents = document.querySelectorAll('.tab-content');
tabs.forEach((tab, index) => {
tab.classList.remove('active');
tabContents[index].classList.remove('active');
});
tabs[tabIndex].classList.add('active');
tabContents[tabIndex].classList.add('active');
}
document.getElementById('newTagInput').addEventListener('keydown', function (event) {
const selectedTagsContainer = document.getElementById('selectedTagsContainer');
if (event.key === 'Enter') {
const tagText = event.target.value.trim();
if (tagText) {
const newTag = document.createElement('span');
newTag.className = 'tag';
newTag.textContent = tagText;
newTag.onclick = function () {
selectedTagsContainer.removeChild(newTag);
const originalTag = Array.from(document.querySelectorAll('#routeTags .tag')).find(tag => tag.textContent === tagText);
if (originalTag) {
originalTag.classList.remove('selected');
}
};
selectedTagsContainer.appendChild(newTag);
event.target.value = '';
}
}
});
function toggleTag(tagElement) {
tagElement.classList.toggle('selected');
const selectedTagsContainer = document.getElementById('selectedTagsContainer');
const tagText = tagElement.textContent;
if (tagElement.classList.contains('selected')) {
const newTag = document.createElement('span');
newTag.className = 'tag';
newTag.textContent = tagText;
newTag.onclick = function () {
selectedTagsContainer.removeChild(newTag);
tagElement.classList.remove('selected');
};
selectedTagsContainer.appendChild(newTag);
} else {
const tags = selectedTagsContainer.querySelectorAll('.tag');
tags.forEach(tag => {
if (tag.textContent === tagText) {
selectedTagsContainer.removeChild(tag);
}
});
}
}
function copyToClipboard(elementId) {
var text = document.querySelector("#" + elementId + " code").innerText;
navigator.clipboard.writeText(text).then(function () {
if (window.opener) {
window.opener.postMessage({ type: 'NZCFG_JSON', target: elementId === 'jsonOutput' ? 'public_note' : 'traffic', payload: text }, '*');
alert('已生成并同步至控制面板中!');
window.close();
} else {
alert('已复制到剪贴板!');
}
});
}
function toggleEndDate() {
const unlimitedEndDateCheckbox = document.getElementById('unlimitedEndDate');
const endDateInput = document.getElementById('endDate');
if (unlimitedEndDateCheckbox.checked) {
endDateInput.disabled = true;
endDateInput.value = ''; // 清空当前值,因为它会被固定为无限期
} else {
endDateInput.disabled = false;
endDateInput.value = getNowDateTimeLocal(); // 恢复为当前日期时间
}
}
function toggleCustomCycle() {
const cycleSelect = document.getElementById('cycle');
const cycleCustomInput = document.getElementById('cycleCustom');
cycleCustomInput.style.display = cycleSelect.value === 'custom' ? 'block' : 'none';
}
function toggleAmount() {
const freeamountCheckbox = document.getElementById('freeamount');
const amountInputGroup = document.getElementById('amountInputGroup');
const amountCustomInput = document.getElementById('amountCustom');
amountInputGroup.style.display = freeamountCheckbox.checked ? 'none' : 'grid';
amountCustomInput.style.display = 'none';
}
function toggleCustomAmount() {
const amountCurrencySelect = document.getElementById('amountCurrency');
const amountCustomInput = document.getElementById('amountCustom');
amountCustomInput.style.display = amountCurrencySelect.value === 'custom' ? 'block' : 'none';
}
function toggleBandwidth() {
const unlimitedBandwidthCheckbox = document.getElementById('unlimitedBandwidth');
const bandwidthInputGroup = document.getElementById('bandwidthInputGroup');
const bandwidthCustomInput = document.getElementById('bandwidthCustom');
bandwidthInputGroup.style.display = unlimitedBandwidthCheckbox.checked ? 'none' : 'grid';
bandwidthCustomInput.style.display = 'none';
}
function toggleCustomBandwidth() {
const bandwidthUnitSelect = document.getElementById('bandwidthUnit');
const bandwidthCustomInput = document.getElementById('bandwidthCustom');
bandwidthCustomInput.style.display = bandwidthUnitSelect.value === 'custom' ? 'block' : 'none';
}
function toggleTraffic() {
const unlimitedTrafficCheckbox = document.getElementById('unlimitedTraffic');
const trafficInputGroup = document.getElementById('trafficInputGroup');
const trafficUnitCustom = document.getElementById('trafficUnitCustom');
const trafficPeriodCustom = document.getElementById('trafficPeriodCustom');
trafficInputGroup.style.display = unlimitedTrafficCheckbox.checked ? 'none' : 'grid';
trafficUnitCustom.style.display = 'none';
trafficPeriodCustom.style.display = 'none';
}
function toggleCustomTraffic() {
const trafficUnitSelect = document.getElementById('trafficUnit');
const trafficPeriodSelect = document.getElementById('trafficPeriod');
const trafficUnitCustom = document.getElementById('trafficUnitCustom');
const trafficPeriodCustom = document.getElementById('trafficPeriodCustom');
if (trafficUnitSelect.value === 'custom' && trafficPeriodSelect.value === 'custom') {
trafficUnitCustom.style.display = 'block';
trafficPeriodCustom.style.display = 'block';
} else if (trafficUnitSelect.value === 'custom' && trafficPeriodSelect.value !== 'custom') {
trafficUnitCustom.style.display = 'block';
trafficPeriodCustom.style.display = 'none';
} else if (trafficUnitSelect.value !== 'custom' && trafficPeriodSelect.value === 'custom') {
trafficUnitCustom.style.display = 'none';
trafficPeriodCustom.style.display = 'block';
} else {
trafficUnitCustom.style.display = 'none';
trafficPeriodCustom.style.display = 'none';
}
}
function toggleRouteMode() {
const routeModeSelect = document.getElementById('routeMode');
const tagsModeDiv = document.getElementById('tagsMode');
const carriersModeDiv = document.getElementById('carriersMode');
const selectedTags = document.getElementById('selectedTags');
if (routeModeSelect.value === 'tags') {
tagsModeDiv.style.display = 'block';
carriersModeDiv.style.display = 'none';
selectedTags.style.display = 'block';
} else {
tagsModeDiv.style.display = 'none';
carriersModeDiv.style.display = 'block';
selectedTags.style.display = 'none';
}
}
function generatePublicNoteJSON() {
const tz = document.getElementById('timezone1').value;
const startDate = document.getElementById('startDate').value;
const unlimitedEndDateCheckbox = document.getElementById('unlimitedEndDate');
let endDate;
if (unlimitedEndDateCheckbox.checked) {
endDate = "0000-00-00T23:59:59" + tz; // 设置为无限期
} else {
endDate = formatDateWithTimezone(document.getElementById('endDate').value, tz);
}
const autoRenewal = document.getElementById('autoRenewal').value;
const cycleSelect = document.getElementById('cycle');
const cycleCustom = document.getElementById('cycleCustom').value;
const cycle = cycleSelect.value === 'custom' ? cycleCustom : cycleSelect.value;
const freeamountCheckbox = document.getElementById('freeamount');
let amount = "0";
if (!freeamountCheckbox.checked) {
const amountValue = document.getElementById('amountValue').value;
const amountCurrencySelect = document.getElementById('amountCurrency');
const amountCustom = document.getElementById('amountCustom').value;
const amountCurrency = amountCurrencySelect.value === 'custom' ? amountCustom : amountCurrencySelect.value;
amount = amountValue + amountCurrency;
}
const unlimitedBandwidthCheckbox = document.getElementById('unlimitedBandwidth');
let bandwidth = "无限";
if (!unlimitedBandwidthCheckbox.checked) {
const bandwidthValue = document.getElementById('bandwidthValue').value;
const bandwidthUnitSelect = document.getElementById('bandwidthUnit');
const bandwidthCustom = document.getElementById('bandwidthCustom').value;
const bandwidthUnit = bandwidthUnitSelect.value === 'custom' ? bandwidthCustom : bandwidthUnitSelect.value;
bandwidth = bandwidthValue + bandwidthUnit;
}
const unlimitedTrafficCheckbox = document.getElementById('unlimitedTraffic');
let trafficVol = "无限";
if (!unlimitedTrafficCheckbox.checked) {
const trafficValue = document.getElementById('trafficValue').value;
const trafficUnitSelect = document.getElementById('trafficUnit');
const trafficPeriodSelect = document.getElementById('trafficPeriod');
const trafficUnitCustom = document.getElementById('trafficUnitCustom').value;
const trafficPeriodCustom = document.getElementById('trafficPeriodCustom').value;
let trafficUnit = trafficUnitSelect.value === 'custom' ? trafficUnitCustom : trafficUnitSelect.value;
let trafficPeriod = trafficPeriodSelect.value === 'custom' ? trafficPeriodCustom : trafficPeriodSelect.value;
trafficVol = trafficValue + trafficUnit + trafficPeriod;
}
const trafficType = document.getElementById('trafficType').value;
const ipv4 = document.getElementById('ipv4').value;
const ipv6 = document.getElementById('ipv6').value;
let networkRoute = '';
const routeModeSelect = document.getElementById('routeMode');
if (routeModeSelect.value === 'tags') {
const selectedTagsContainer = document.getElementById('selectedTagsContainer');
const selectedTags = Array.from(selectedTagsContainer.querySelectorAll('.tag')).map(tag => tag.textContent);
networkRoute = selectedTags.join('|');
} else {
const telecomRoute1 = document.getElementById('telecomRoute1').value;
const telecomRoute2 = document.getElementById('telecomRoute2').value;
const mobileRoute1 = document.getElementById('mobileRoute1').value;
const mobileRoute2 = document.getElementById('mobileRoute2').value;
const unicomRoute1 = document.getElementById('unicomRoute1').value;
const unicomRoute2 = document.getElementById('unicomRoute2').value;
const telecomRoutes = [telecomRoute1, telecomRoute2].filter(route => route !== '').join('|');
const mobileRoutes = [mobileRoute1, mobileRoute2].filter(route => route !== '').join('|');
const unicomRoutes = [unicomRoute1, unicomRoute2].filter(route => route !== '').join('|');
const routes = [];
if (telecomRoutes) routes.push(`电信${telecomRoutes}`);
if (mobileRoutes) routes.push(`移动${mobileRoutes}`);
if (unicomRoutes) routes.push(`联通${unicomRoutes}`);
networkRoute = routes.join(' ');
}
const extra = document.getElementById('extra').value;
const jsonOutput = document.getElementById('jsonOutput');
const json = {
billingDataMod: {
startDate: formatDateWithTimezone(startDate, tz),
endDate: endDate, // 使用经过处理的endDate
autoRenewal: autoRenewal,
cycle: cycle,
amount: amount
},
planDataMod: {
bandwidth: bandwidth,
trafficVol: trafficVol,
trafficType: trafficType,
IPv4: ipv4,
IPv6: ipv6,
networkRoute: networkRoute,
extra: extra
}
};
document.querySelector("#jsonOutput code").innerHTML =
Prism.highlight(JSON.stringify(json, null, 2), Prism.languages.json, 'json');
}
function generateTrafficMonitorJSON() {
const tz = document.getElementById('timezone2').value;
const monitorType = document.getElementById('monitorType').value;
const maxTrafficValue = document.getElementById('maxTraffic').value;
const maxTrafficUnit = document.getElementById('maxTrafficUnit').value;
const cycleStart = document.getElementById('cycleStart').value;
const cycleInterval = document.getElementById('cycleInterval').value;
const cycleUnit = document.getElementById('cycleUnit').value;
const cover = document.getElementById('cover').value;
const ignore = document.getElementById('ignore').value;
let maxBytes = parseFloat(maxTrafficValue);
if (maxTrafficUnit === 'GB') {
maxBytes *= 1024 * 1024 * 1024;
} else if (maxTrafficUnit === 'TB') {
maxBytes *= 1024 * 1024 * 1024 * 1024;
} else { // MB
maxBytes *= 1024 * 1024;
}
const ignoreArray = ignore.split(',').map(item => item.trim()).filter(item => item !== '');
const ignoreObject = {};
ignoreArray.forEach(item => {
ignoreObject[item] = true;
});
const jsonOutput2 = document.getElementById('jsonOutput2');
const json = [
{
type: monitorType,
max: maxBytes,
cycle_start: formatDateWithTimezone(cycleStart, tz),
cycle_interval: parseInt(cycleInterval),
cycle_unit: cycleUnit,
cover: parseInt(cover),
ignore: ignoreObject
}
];
document.querySelector("#jsonOutput2 code").innerHTML =
Prism.highlight(JSON.stringify(json, null, 2), Prism.languages.json, 'json');
}
function toggleTheme() {
const body = document.body;
const themeToggle = document.getElementById('themeToggle');
const currentTheme = themeToggle.getAttribute('data-theme');
let newTheme;
if (currentTheme === 'system') {
newTheme = 'light';
body.classList.remove('dark-mode');
themeToggle.innerHTML = '<i class="fas fa-sun"></i>';
} else if (currentTheme === 'light') {
newTheme = 'dark';
body.classList.add('dark-mode');
themeToggle.innerHTML = '<i class="fas fa-moon"></i>';
} else {
newTheme = 'system';
themeToggle.innerHTML = '<i class="fas fa-desktop"></i>';
applySystemTheme();
}
themeToggle.setAttribute('data-theme', newTheme);
localStorage.setItem('theme-preference', newTheme);
}
function applySystemTheme() {
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.body.classList.toggle('dark-mode', isDarkMode);
}
function setupSystemThemeListener() {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
mediaQuery.addEventListener('change', (e) => {
const themeToggle = document.getElementById('themeToggle');
if (themeToggle.getAttribute('data-theme') === 'system') {
document.body.classList.toggle('dark-mode', e.matches);
}
});
}
document.addEventListener('DOMContentLoaded', () => {
const themeToggle = document.getElementById('themeToggle');
const savedTheme = localStorage.getItem('theme-preference') || 'system';
themeToggle.setAttribute('data-theme', savedTheme);
if (savedTheme === 'system') {
themeToggle.innerHTML = '<i class="fas fa-desktop"></i>';
applySystemTheme();
} else if (savedTheme === 'dark') {
themeToggle.innerHTML = '<i class="fas fa-moon"></i>';
document.body.classList.add('dark-mode');
} else {
themeToggle.innerHTML = '<i class="fas fa-sun"></i>';
document.body.classList.remove('dark-mode');
}
setupSystemThemeListener();
// Initialize end date checkbox state
toggleEndDate();
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-json.min.js"></script>
</body>
</html>