|
|
@@ -9,7 +9,7 @@ import re
|
|
|
import socket
|
|
|
|
|
|
NETPLAN_FILE = "/etc/netplan/01-netcfg.yaml"
|
|
|
-PORT = 6000 # 定义端口常量
|
|
|
+PORT = 8000 # 定义端口常量
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
@@ -41,7 +41,32 @@ HTML_TEMPLATE = """
|
|
|
}
|
|
|
button:hover { background: #0056b3; }
|
|
|
.info { color: #666; margin-top: 10px; font-size: 14px; }
|
|
|
- .countdown { color: #dc3545; font-weight: bold; }
|
|
|
+ .countdown {
|
|
|
+ color: #dc3545;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-top: 20px;
|
|
|
+ padding: 15px;
|
|
|
+ background-color: #f8f9fa;
|
|
|
+ border-left: 4px solid #dc3545;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ .status-message {
|
|
|
+ margin-top: 20px;
|
|
|
+ padding: 15px;
|
|
|
+ background-color: #d4edda;
|
|
|
+ border-left: 4px solid #28a745;
|
|
|
+ border-radius: 4px;
|
|
|
+ color: #155724;
|
|
|
+ }
|
|
|
+ .error-message {
|
|
|
+ margin-top: 20px;
|
|
|
+ padding: 15px;
|
|
|
+ background-color: #f8d7da;
|
|
|
+ border-left: 4px solid #dc3545;
|
|
|
+ border-radius: 4px;
|
|
|
+ color: #721c24;
|
|
|
+ }
|
|
|
+ .hidden { display: none; }
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
@@ -51,16 +76,22 @@ HTML_TEMPLATE = """
|
|
|
子网掩码位数: <br><input id="mask" value="{{ mask }}"><br>
|
|
|
网关: <br><input id="gateway" value="{{ gateway }}"><br>
|
|
|
DNS服务器: <br><input id="dns" value="{{ dns }}"><br>
|
|
|
- <button type="button" onclick="save()">保存配置</button>
|
|
|
- <div class="info">注意:保存后会有20秒时间确认,超时自动回滚</div>
|
|
|
+ <button type="button" onclick="save()" id="saveBtn">保存配置</button>
|
|
|
</form>
|
|
|
|
|
|
+<div id="statusMessage" class="hidden"></div>
|
|
|
+
|
|
|
<script>
|
|
|
function save() {
|
|
|
- const saveBtn = event.target;
|
|
|
+ const saveBtn = document.getElementById('saveBtn');
|
|
|
const originalText = saveBtn.textContent;
|
|
|
const newIp = document.getElementById('ip').value;
|
|
|
|
|
|
+ // 清除之前的消息
|
|
|
+ const statusDiv = document.getElementById('statusMessage');
|
|
|
+ statusDiv.className = 'hidden';
|
|
|
+ statusDiv.innerHTML = '';
|
|
|
+
|
|
|
// 禁用按钮防止重复点击
|
|
|
saveBtn.disabled = true;
|
|
|
saveBtn.textContent = '保存中...';
|
|
|
@@ -79,40 +110,23 @@ function save() {
|
|
|
.then(res => res.json())
|
|
|
.then(data => {
|
|
|
if (data.success) {
|
|
|
- // 保存成功,显示倒计时并跳转
|
|
|
- let countdown = 15;
|
|
|
- const message = data.status + '\\n\\n将在 ' + countdown + ' 秒后跳转到新地址...';
|
|
|
- alert(message);
|
|
|
+ // 显示成功消息
|
|
|
+ statusDiv.className = 'status-message';
|
|
|
+ statusDiv.innerHTML = data.status;
|
|
|
|
|
|
- // 创建倒计时显示
|
|
|
- const countdownDiv = document.createElement('div');
|
|
|
- countdownDiv.className = 'countdown';
|
|
|
- countdownDiv.innerHTML = '正在跳转到新IP地址,请稍候... <span id="countdown">' + countdown + '</span> 秒';
|
|
|
- document.body.appendChild(countdownDiv);
|
|
|
-
|
|
|
- // 倒计时并跳转
|
|
|
- const countdownInterval = setInterval(() => {
|
|
|
- countdown--;
|
|
|
- document.getElementById('countdown').textContent = countdown;
|
|
|
-
|
|
|
- if (countdown <= 0) {
|
|
|
- clearInterval(countdownInterval);
|
|
|
- // 跳转到新的IP地址,包含端口号
|
|
|
- window.location.href = 'http://' + newIp + ':' + {{ port }};
|
|
|
- }
|
|
|
- }, 1000);
|
|
|
-
|
|
|
- // 同时尝试自动跳转(如果网络已生效)
|
|
|
- setTimeout(() => {
|
|
|
- window.location.href = 'http://' + newIp + ':' + {{ port }};
|
|
|
- }, 3000);
|
|
|
+ // 开始倒计时
|
|
|
+ startCountdown(newIp);
|
|
|
|
|
|
} else {
|
|
|
- alert('保存失败: ' + data.status);
|
|
|
+ // 显示错误消息
|
|
|
+ statusDiv.className = 'error-message';
|
|
|
+ statusDiv.innerHTML = '保存失败: ' + data.status;
|
|
|
}
|
|
|
})
|
|
|
.catch(error => {
|
|
|
- alert('保存失败: ' + error);
|
|
|
+ // 显示错误消息
|
|
|
+ statusDiv.className = 'error-message';
|
|
|
+ statusDiv.innerHTML = '保存失败: ' + error;
|
|
|
})
|
|
|
.finally(() => {
|
|
|
// 恢复按钮状态
|
|
|
@@ -121,6 +135,62 @@ function save() {
|
|
|
saveBtn.style.background = '#007bff';
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+function startCountdown(newIp) {
|
|
|
+ let countdown = 15;
|
|
|
+
|
|
|
+ // 创建倒计时显示区域
|
|
|
+ let countdownDiv = document.getElementById('countdownDisplay');
|
|
|
+ if (!countdownDiv) {
|
|
|
+ countdownDiv = document.createElement('div');
|
|
|
+ countdownDiv.id = 'countdownDisplay';
|
|
|
+ countdownDiv.className = 'countdown';
|
|
|
+ document.body.appendChild(countdownDiv);
|
|
|
+ }
|
|
|
+
|
|
|
+ countdownDiv.innerHTML = '配置保存成功!正在应用网络配置...<br>';
|
|
|
+ countdownDiv.innerHTML += '将在 <span id="countdown">' + countdown + '</span> 秒后自动跳转到新地址<br>';
|
|
|
+ countdownDiv.innerHTML += '跳转地址: http://' + newIp + ':' + {{ port }};
|
|
|
+
|
|
|
+ // 更新状态消息,显示更多信息
|
|
|
+ const statusDiv = document.getElementById('statusMessage');
|
|
|
+ statusDiv.innerHTML += '<br><br>网络配置已保存,正在后台应用...';
|
|
|
+ // statusDiv.innerHTML += '<br>请在20秒内到服务器控制台按Enter键确认,否则配置会自动回滚。';
|
|
|
+ statusDiv.innerHTML += '<br>系统将在15秒后尝试自动跳转到新地址。';
|
|
|
+
|
|
|
+ // 倒计时函数
|
|
|
+ const updateCountdown = () => {
|
|
|
+ countdown--;
|
|
|
+ document.getElementById('countdown').textContent = countdown;
|
|
|
+
|
|
|
+ if (countdown <= 0) {
|
|
|
+ clearInterval(countdownInterval);
|
|
|
+ // 跳转到新的IP地址,包含端口号
|
|
|
+ window.location.href = 'http://' + newIp + ':' + {{ port }};
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 开始倒计时
|
|
|
+ const countdownInterval = setInterval(updateCountdown, 1000);
|
|
|
+
|
|
|
+ // 在倒计时开始3秒后尝试第一次跳转(如果网络已生效)
|
|
|
+ setTimeout(() => {
|
|
|
+ try {
|
|
|
+ window.location.href = 'http://' + newIp + ':' + {{ port }};
|
|
|
+ } catch (e) {
|
|
|
+ console.log('第一次跳转尝试失败,继续等待...');
|
|
|
+ }
|
|
|
+ }, 3000);
|
|
|
+
|
|
|
+ // 在倒计时开始10秒后尝试第二次跳转
|
|
|
+ setTimeout(() => {
|
|
|
+ try {
|
|
|
+ window.location.href = 'http://' + newIp + ':' + {{ port }};
|
|
|
+ } catch (e) {
|
|
|
+ console.log('第二次跳转尝试失败,继续等待...');
|
|
|
+ }
|
|
|
+ }, 10000);
|
|
|
+}
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|
|
|
@@ -273,7 +343,7 @@ def set_network():
|
|
|
|
|
|
return jsonify({
|
|
|
"success": True,
|
|
|
- "status": f"配置已保存并正在应用!\n\n请在20秒内按Enter键确认,否则配置会自动回滚。\n跳转地址: http://{ip}:{PORT}",
|
|
|
+ "status": "配置保存成功!正在应用网络配置...",
|
|
|
"new_ip": ip,
|
|
|
"port": PORT,
|
|
|
"redirect_url": f"http://{ip}:{PORT}"
|