这这是一个基于PHP和JavaScript的命令执行工具,用于执行系统级别的视频处理脚本。该工具提供了一个Web界面,允许用户通过点击按钮执行预定义的shell脚本。
我运行的脚本命令是下面三条,可用根据自己的需要写出自己需要运行的脚本命令。
sudo -u fnos /home/liaozhenqiang/flv-to-mp4.sh sudo -u fnos /home/liaozhenqiang/flv-rename.sh sudo -u fnos /home/liaozhenqiang/stop-flv.sh
主要功能
三个功能按钮:
FLV转MP4
FLV重命名
停止FLV
处理实时日志显示:执行命令时显示实时输出结果异步执行:使用 AJAX 实现后台执行,不阻塞界面。

<?php
// 危险警告!此代码完全不考虑安全性,仅用于本地测试!
// 允许执行的命令列表(直接以root权限执行)
$allowedCommands = [
'flv-to-mp4' => 'sudo -u liaozhenqiang /home/liaozhenqiang/flv-to-mp4.sh',
'flv-rename' => 'sudo -u liaozhenqiang /home/liaozhenqiang/flv-rename.sh',
'stop-flv' => 'sudo -u liaozhenqiang /home/liaozhenqiang/stop-flv.sh'
];
// 执行结果
$result = [];
// 处理AJAX请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['command'])) {
$commandKey = $_POST['command'];
// 检查命令是否存在
if (isset($allowedCommands[$commandKey])) {
$command = $allowedCommands[$commandKey];
// 执行命令(直接使用exec,不做任何安全过滤)
exec($command . ' 2>&1', $output, $returnCode);
$result = [
'success' => $returnCode === 0,
'output' => implode("\n", $output),
'returnCode' => $returnCode
];
} else {
$result = [
'success' => false,
'error' => '未知命令'
];
}
// 返回JSON响应
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FLV转MP4脚本执行器</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- 配置Tailwind主题 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
danger: '#EF4444',
warning: '#F59E0B',
success: '#10B981',
dark: '#1F2937',
light: '#F9FAFB'
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<!-- 自定义工具类 -->
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.command-card {
@apply bg-white rounded-lg shadow-md p-5 transition-all duration-300 hover:shadow-lg transform hover:-translate-y-1;
}
.btn-execute {
@apply w-full py-3 font-medium rounded-lg transition-all duration-200 flex items-center justify-center;
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<header class="mb-8 text-center">
<div class="inline-flex items-center justify-center w-12 h-12 rounded-full bg-danger/10 mb-4">
<i class="fa fa-exclamation-triangle text-danger text-2xl"></i>
</div>
<h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-800 mb-2">FLV转MP4脚本执行器</h1>
<p class="text-danger font-medium mb-2">警告:此工具以root权限执行命令,仅用于本地测试!</p>
<p>执行系统命令可能导致不可逆的系统变更,请谨慎操作</p>
</header>
<main>
<!-- 命令按钮区域 -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- FLV转MP4按钮 -->
<div class="command-card border-l-4 border-primary">
<div class="flex items-center mb-4">
<div class="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center mr-4">
<i class="fa fa-video-camera text-primary text-xl"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">FLV转MP4</h2>
</div>
<p class="text-gray-600 mb-4">执行视频格式转换脚本</p>
<button id="btn-flv-to-mp4" class="btn-execute bg-success hover:bg-primary/90 text-white">
<i class="fa fa-play-circle mr-2"></i> 执行转换
</button>
</div>
<!-- FLV重命名按钮 -->
<div class="command-card border-l-4 border-warning">
<div class="flex items-center mb-4">
<div class="w-10 h-10 rounded-full bg-warning/10 flex items-center justify-center mr-4">
<i class="fa fa-file-text-o text-warning text-xl"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">FLV重命名</h2>
</div>
<p class="text-gray-600 mb-4">执行文件重命名脚本</p>
<button id="btn-flv-rename" class="btn-execute bg-warning hover:bg-warning/90 text-white">
<i class="fa fa-play-circle mr-2"></i> 执行重命名
</button>
</div>
<!-- 停止FLV处理按钮 -->
<div class="command-card border-l-4 border-danger">
<div class="flex items-center mb-4">
<div class="w-10 h-10 rounded-full bg-danger/10 flex items-center justify-center mr-4">
<i class="fa fa-stop-circle text-danger text-xl"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">停止FLV处理</h2>
</div>
<p class="text-gray-600 mb-4">执行停止脚本,终止处理进程</p>
<button id="btn-stop-flv" class="btn-execute bg-danger hover:bg-danger/90 text-white">
<i class="fa fa-play-circle mr-2"></i> 停止处理
</button>
</div>
</div>
<!-- 日志显示区域 -->
<div class="bg-white rounded-lg shadow-md overflow-hidden">
<div class="p-4 bg-gray-50 border-b border-gray-200 flex justify-between items-center">
<h3 class="font-semibold text-gray-800">执行日志</h3>
<button id="btn-clear-log" class="text-gray-600 hover:text-gray-900 transition-colors duration-200 flex items-center">
<i class="fa fa-trash-o mr-1"></i> 清空日志
</button>
</div>
<div id="log-container" class="h-80 p-4 overflow-y-auto bg-gray-900 text-gray-100 font-mono text-sm">
<div class="text-gray-400 italic">等待命令执行...</div>
</div>
</div>
</main>
<footer class="mt-12 text-center text-gray-500 text-sm">
<p>此工具仅供 <a href="https://lzq520.cn" style="color: red;" id="link"></a> 开发者本地测试使用,不要在生产环境中运行</p>
<script>
// 目标网址(需确认该网站允许跨域访问)
const targetUrl = 'https://lzq520.cn';
// 使用 fetch API 直接请求目标网址
fetch(targetUrl)
.then(response => {
if (!response.ok) throw new Error(`HTTP错误,状态码:${response.status}`);
return response.text(); // 获取HTML内容
})
.then(html => {
// 使用 DOMParser 解析 HTML 字符串
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const title = doc.title || '无标题'; // 获取<title>标签内容
// 设置到链接文本
document.getElementById('link').textContent = title;
})
.catch(error => {
console.error('获取标题失败:', error);
document.getElementById('link').textContent = '毒蘑菇炖鸡';
});
</script>
</footer>
</div>
<script>
// 按钮和日志容器
const btnFlvToMp4 = document.getElementById('btn-flv-to-mp4');
const btnFlvRename = document.getElementById('btn-flv-rename');
const btnStopFlv = document.getElementById('btn-stop-flv');
const btnClearLog = document.getElementById('btn-clear-log');
const logContainer = document.getElementById('log-container');
// 命令映射
const commandMap = {
'btn-flv-to-mp4': 'flv-to-mp4',
'btn-flv-rename': 'flv-rename',
'btn-stop-flv': 'stop-flv'
};
// 为按钮添加点击事件
[btnFlvToMp4, btnFlvRename, btnStopFlv].forEach(button => {
button.addEventListener('click', function() {
const commandKey = commandMap[this.id];
executeCommand(commandKey, this);
});
});
// 清空日志按钮事件
btnClearLog.addEventListener('click', function() {
logContainer.innerHTML = '<div class="text-gray-400 italic">日志已清空</div>';
});
// 执行命令函数
function executeCommand(commandKey, button) {
// 记录开始时间
const startTime = new Date();
// 禁用按钮
button.disabled = true;
button.innerHTML = '<i class="fa fa-spinner fa-spin mr-2"></i> 执行中...';
// 添加执行日志
addLog(`<span>> 正在执行命令: ${commandKey}</span>`);
// 发送AJAX请求
fetch('', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `command=${encodeURIComponent(commandKey)}`
})
.then(response => response.json())
.then(data => {
// 计算执行时间
const endTime = new Date();
const executionTime = (endTime - startTime) / 1000;
if (data.success) {
addLog(`<span>✓ 命令执行成功 (耗时: ${executionTime.toFixed(2)}s)</span>`);
addLog(data.output || '命令执行完毕,但没有输出');
} else {
addLog(`<span>✗ 命令执行失败 (耗时: ${executionTime.toFixed(2)}s)</span>`);
addLog(data.error || '未知错误');
}
// 恢复按钮状态
button.disabled = false;
button.innerHTML = '<i class="fa fa-play-circle mr-2"></i> 执行' +
(commandKey === 'flv-to-mp4' ? '转换' :
commandKey === 'flv-rename' ? '重命名' : '处理');
})
.catch(error => {
// 计算执行时间
const endTime = new Date();
const executionTime = (endTime - startTime) / 1000;
addLog(`<span>✗ 请求失败 (耗时: ${executionTime.toFixed(2)}s)</span>`);
addLog(error.message || '网络错误');
// 恢复按钮状态
button.disabled = false;
button.innerHTML = '<i class="fa fa-play-circle mr-2"></i> 执行' +
(commandKey === 'flv-to-mp4' ? '转换' :
commandKey === 'flv-rename' ? '重命名' : '处理');
});
}
// 添加日志到容器
function addLog(message) {
const logEntry = document.createElement('div');
logEntry.innerHTML = message;
logContainer.appendChild(logEntry);
logContainer.scrollTop = logContainer.scrollHeight;
}
</script>
</body>
</html>
新添加了一个有密码版本账户是:admin 密码:password123
<?php
// 危险警告!此代码完全不考虑安全性,仅用于本地测试!
// 允许执行的命令列表(直接以root权限执行)
$allowedCommands = [
'flv-to-mp4' => 'sudo -u liaozhenqiang /home/liaozhenqiang/flv-to-mp4.sh',
'flv-rename' => 'sudo -u liaozhenqiang /home/liaozhenqiang/flv-rename.sh',
'stop-flv' => 'sudo -u liaozhenqiang /home/liaozhenqiang/stop-flv.sh'
];
// 账户密码配置(实际使用中应使用加密存储)
$validUsers = [
'admin' => 'password123' // 用户名 => 密码,实际环境需加密存储
];
// 执行结果
$result = [];
// 初始化会话
session_start();
// 处理登录请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if (isset($validUsers[$username]) && $validUsers[$username] === $password) {
// 登录成功,设置会话
$_SESSION['authenticated'] = true;
$_SESSION['username'] = $username;
$result = [
'success' => true,
'message' => '登录成功'
];
} else {
$result = [
'success' => false,
'error' => '用户名或密码错误'
];
}
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
// 处理登出请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['logout'])) {
session_destroy();
$result = [
'success' => true,
'message' => '已登出'
];
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
// 处理认证状态检查请求
if (isset($_GET['checkauth'])) {
$result = [
'authenticated' => isset($_SESSION['authenticated']) && $_SESSION['authenticated'] === true
];
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
// 检查是否已认证
$isAuthenticated = isset($_SESSION['authenticated']) && $_SESSION['authenticated'] === true;
// 处理AJAX命令请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['command'])) {
// 验证是否已登录
if (!$isAuthenticated) {
$result = [
'success' => false,
'error' => '请先登录'
];
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
$commandKey = $_POST['command'];
// 检查命令是否存在
if (isset($allowedCommands[$commandKey])) {
$command = $allowedCommands[$commandKey];
// 执行命令(直接使用exec,不做任何安全过滤)
exec($command . ' 2>&1', $output, $returnCode);
$result = [
'success' => $returnCode === 0,
'output' => implode("\n", $output),
'returnCode' => $returnCode
];
} else {
$result = [
'success' => false,
'error' => '未知命令'
];
}
// 返回JSON响应
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FLV转MP4脚本执行器</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- 配置Tailwind主题 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
danger: '#EF4444',
warning: '#F59E0B',
success: '#10B981',
dark: '#1F2937',
light: '#F9FAFB',
primary: '#3B82F6'
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<!-- 自定义工具类 -->
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.command-card {
@apply bg-white rounded-lg shadow-md p-5 transition-all duration-300 hover:shadow-lg transform hover:-translate-y-1;
}
.btn-execute {
@apply w-full py-3 font-medium rounded-lg transition-all duration-200 flex items-center justify-center;
}
.auth-overlay {
@apply fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50;
}
.auth-card {
@apply bg-white rounded-lg shadow-xl p-8 w-full max-w-md;
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<header class="mb-8 text-center">
<div class="inline-flex items-center justify-center w-12 h-12 rounded-full bg-danger/10 mb-4">
<i class="fa fa-exclamation-triangle text-danger text-2xl"></i>
</div>
<h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-800 mb-2">FLV转MP4脚本执行器</h1>
<p class="text-danger font-medium mb-2">警告:此工具以root权限执行命令,仅用于本地测试!</p>
<p>执行系统命令可能导致不可逆的系统变更,请谨慎操作</p>
<div id="auth-status" class="mt-4 text-sm font-medium hidden"></div>
</header>
<main>
<!-- 命令按钮区域 -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- FLV转MP4按钮 -->
<div class="command-card border-l-4 border-primary">
<div class="flex items-center mb-4">
<div class="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center mr-4">
<i class="fa fa-video-camera text-primary text-xl"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">FLV转MP4</h2>
</div>
<p class="text-gray-600 mb-4">执行视频格式转换脚本</p>
<button id="btn-flv-to-mp4" class="btn-execute bg-success hover:bg-primary/90 text-white">
<i class="fa fa-play-circle mr-2"></i> 执行转换
</button>
</div>
<!-- FLV重命名按钮 -->
<div class="command-card border-l-4 border-warning">
<div class="flex items-center mb-4">
<div class="w-10 h-10 rounded-full bg-warning/10 flex items-center justify-center mr-4">
<i class="fa fa-file-text-o text-warning text-xl"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">FLV重命名</h2>
</div>
<p class="text-gray-600 mb-4">执行文件重命名脚本</p>
<button id="btn-flv-rename" class="btn-execute bg-warning hover:bg-warning/90 text-white">
<i class="fa fa-play-circle mr-2"></i> 执行重命名
</button>
</div>
<!-- 停止FLV处理按钮 -->
<div class="command-card border-l-4 border-danger">
<div class="flex items-center mb-4">
<div class="w-10 h-10 rounded-full bg-danger/10 flex items-center justify-center mr-4">
<i class="fa fa-stop-circle text-danger text-xl"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">停止FLV处理</h2>
</div>
<p class="text-gray-600 mb-4">执行停止脚本,终止处理进程</p>
<button id="btn-stop-flv" class="btn-execute bg-danger hover:bg-danger/90 text-white">
<i class="fa fa-play-circle mr-2"></i> 停止处理
</button>
</div>
</div>
<!-- 日志显示区域 -->
<div class="bg-white rounded-lg shadow-md overflow-hidden">
<div class="p-4 bg-gray-50 border-b border-gray-200 flex justify-between items-center">
<h3 class="font-semibold text-gray-800">执行日志</h3>
<div class="flex gap-4">
<button id="btn-logout" class="text-gray-600 hover:text-gray-900 transition-colors duration-200 flex items-center hidden">
<i class="fa fa-sign-out mr-1"></i> 退出登录
</button>
<button id="btn-clear-log" class="text-gray-600 hover:text-gray-900 transition-colors duration-200 flex items-center">
<i class="fa fa-trash-o mr-1"></i> 清空日志
</button>
</div>
</div>
<div id="log-container" class="h-80 p-4 overflow-y-auto bg-gray-900 text-gray-100 font-mono text-sm">
<div class="text-gray-400 italic">等待命令执行...</div>
</div>
</div>
</main>
<footer class="mt-12 text-center text-gray-500 text-sm">
<p>此工具仅供 <a href="https://lzq520.cn" style="color: red;" id="link"></a> 开发者本地测试使用,不要在生产环境中运行</p>
<script>
// 目标网址(需确认该网站允许跨域访问)
const targetUrl = 'https://lzq520.cn';
// 使用 fetch API 直接请求目标网址
fetch(targetUrl)
.then(response => {
if (!response.ok) throw new Error(`HTTP错误,状态码:${response.status}`);
return response.text(); // 获取HTML内容
})
.then(html => {
// 使用 DOMParser 解析 HTML 字符串
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const title = doc.title || '无标题'; // 获取<title>标签内容
// 设置到链接文本
document.getElementById('link').textContent = title;
})
.catch(error => {
console.error('获取标题失败:', error);
document.getElementById('link').textContent = '毒蘑菇炖鸡';
});
</script>
</footer>
</div>
<!-- 登录弹窗 -->
<div id="login-modal" class="auth-overlay hidden">
<div>
<h2 class="text-2xl font-bold text-center mb-6">请登录</h2>
<form id="login-form">
<div>
<label for="username" class="block text-gray-700 mb-2">用户名</label>
<input type="text" id="username" name="username"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
required>
</div>
<div>
<label for="password" class="block text-gray-700 mb-2">密码</label>
<input type="password" id="password" name="password"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
required>
</div>
<button type="submit" class="w-full bg-primary hover:bg-primary/90 text-white font-medium py-2 px-4 rounded-lg transition-colors duration-200">
登录
</button>
<div id="login-error" class="mt-4 text-red-500 text-sm text-center hidden"></div>
</form>
</div>
</div>
<script>
// 按钮和日志容器
const btnFlvToMp4 = document.getElementById('btn-flv-to-mp4');
const btnFlvRename = document.getElementById('btn-flv-rename');
const btnStopFlv = document.getElementById('btn-stop-flv');
const btnClearLog = document.getElementById('btn-clear-log');
const btnLogout = document.getElementById('btn-logout');
const logContainer = document.getElementById('log-container');
const authStatus = document.getElementById('auth-status');
const loginModal = document.getElementById('login-modal');
const loginForm = document.getElementById('login-form');
const loginError = document.getElementById('login-error');
// 命令映射
const commandMap = {
'btn-flv-to-mp4': 'flv-to-mp4',
'btn-flv-rename': 'flv-rename',
'btn-stop-flv': 'stop-flv'
};
// 检查登录状态 - 使用专用API端点
function checkAuthStatus() {
return fetch('?checkauth=true')
.then(response => response.json())
.then(data => {
updateAuthUI(data.authenticated);
return data.authenticated;
})
.catch(error => {
console.error('检查登录状态失败:', error);
return false;
});
}
// 更新登录状态UI
function updateAuthUI(isAuthenticated) {
if (isAuthenticated) {
// 确保登录窗口关闭
loginModal.classList.add('hidden');
loginModal.style.display = 'none';
authStatus.classList.remove('hidden');
authStatus.classList.add('text-success');
authStatus.innerHTML = '<i class="fa fa-check-circle mr-1"></i> 已登录';
btnLogout.classList.remove('hidden');
// 启用命令按钮
[btnFlvToMp4, btnFlvRename, btnStopFlv].forEach(btn => {
btn.disabled = false;
});
} else {
// 显示登录窗口
loginModal.classList.remove('hidden');
loginModal.style.display = 'flex';
authStatus.classList.add('hidden');
btnLogout.classList.add('hidden');
// 禁用命令按钮
[btnFlvToMp4, btnFlvRename, btnStopFlv].forEach(btn => {
btn.disabled = true;
});
}
}
// 页面加载时检查登录状态
document.addEventListener('DOMContentLoaded', () => {
checkAuthStatus();
});
// 登录表单提交
loginForm.addEventListener('submit', async function(e) {
e.preventDefault();
const formData = new FormData();
formData.append('login', 'true');
formData.append('username', document.getElementById('username').value);
formData.append('password', document.getElementById('password').value);
try {
const response = await fetch('', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
// 登录成功后清空错误信息
loginError.classList.add('hidden');
addLog('<span>✓ 登录成功</span>');
// 重置表单
loginForm.reset();
// 强制刷新认证状态并关闭窗口
const isAuthenticated = await checkAuthStatus();
if (isAuthenticated) {
loginModal.classList.add('hidden');
loginModal.style.display = 'none';
}
} else {
// 显示错误信息
loginError.textContent = data.error || '登录失败';
loginError.classList.remove('hidden');
}
} catch (error) {
console.error('登录请求失败:', error);
loginError.textContent = '网络错误,请重试';
loginError.classList.remove('hidden');
}
});
// 登出功能
btnLogout.addEventListener('click', function() {
fetch('', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'logout=true'
})
.then(response => response.json())
.then(data => {
if (data.success) {
addLog('<span>⚠️ 已登出</span>');
updateAuthUI(false);
}
})
.catch(error => {
console.error('登出请求失败:', error);
});
});
// 为按钮添加点击事件
[btnFlvToMp4, btnFlvRename, btnStopFlv].forEach(button => {
button.addEventListener('click', function() {
const commandKey = commandMap[this.id];
executeCommand(commandKey, this);
});
});
// 清空日志按钮事件
btnClearLog.addEventListener('click', function() {
logContainer.innerHTML = '<div class="text-gray-400 italic">等待命令执行...</div>';
});
// 执行命令函数
function executeCommand(commandKey, button) {
// 记录开始时间
const startTime = new Date();
// 禁用按钮
button.disabled = true;
button.innerHTML = '<i class="fa fa-spinner fa-spin mr-2"></i> 执行中...';
// 添加执行日志
addLog(`<span>> 正在执行命令: ${commandKey}</span>`);
// 发送AJAX请求
fetch('', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `command=${encodeURIComponent(commandKey)}`
})
.then(response => response.json())
.then(data => {
// 计算执行时间
const endTime = new Date();
const executionTime = (endTime - startTime) / 1000;
if (data.success) {
addLog(`<span>✓ 命令执行成功 (耗时: ${executionTime.toFixed(2)}s)</span>`);
addLog(data.output || '命令执行完毕,但没有输出');
} else {
// 处理未登录错误
if (data.error === '请先登录') {
updateAuthUI(false);
}
addLog(`<span>✗ 命令执行失败 (耗时: ${executionTime.toFixed(2)}s)</span>`);
addLog(data.error || '未知错误');
}
// 恢复按钮状态
button.disabled = false;
button.innerHTML = '<i class="fa fa-play-circle mr-2"></i> 执行' +
(commandKey === 'flv-to-mp4' ? '转换' :
commandKey === 'flv-rename' ? '重命名' : '处理');
})
.catch(error => {
// 计算执行时间
const endTime = new Date();
const executionTime = (endTime - startTime) / 1000;
addLog(`<span>✗ 请求失败 (耗时: ${executionTime.toFixed(2)}s)</span>`);
addLog(error.message || '网络错误');
// 恢复按钮状态
button.disabled = false;
button.innerHTML = '<i class="fa fa-play-circle mr-2"></i> 执行' +
(commandKey === 'flv-to-mp4' ? '转换' :
commandKey === 'flv-rename' ? '重命名' : '处理');
});
}
// 添加日志到容器
function addLog(message) {
const logEntry = document.createElement('div');
logEntry.innerHTML = message;
logContainer.appendChild(logEntry);
logContainer.scrollTop = logContainer.scrollHeight;
}
</script>
</body>
</html> 版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 1963849530@qq.com 举报,一经查实,本站将立刻删除。如若转载,请注明出处:https://lzq520.cn/narong/136.html
