Files
leonapp/developer/version_control.php
Leonmmcoset 9ce282f0a2 fix(version_control): 修复版本控制页面表格列缺失问题
添加缺失的表格列闭合标签,确保下载、修改和删除按钮正确对齐
2025-09-23 18:11:33 +08:00

689 lines
33 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once '../config.php';
require_once '../includes/logger.php';
session_start();
// 检查开发者登录状态
if (!isset($_SESSION['developer_id'])) {
header('Location: login.php');
exit;
}
$developerId = $_SESSION['developer_id'];
// 验证App ID
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
header('Location: dashboard.php?error=无效的App ID');
exit;
}
$appId = $_GET['id'];
// 获取App信息并验证所有权
$app = null;
$getAppSql = "SELECT * FROM apps WHERE id = ? AND developer_id = ?";
$stmt = $conn->prepare($getAppSql);
if (!$stmt) {
log_error("应用所有权验证查询准备失败: " . $conn->error, __FILE__, __LINE__);
header('Location: dashboard.php?error=验证应用所有权失败');
exit;
}
$stmt->bind_param("ii", $appId, $developerId);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
header('Location: dashboard.php?error=App不存在或无权访问');
exit;
}
$app = $result->fetch_assoc();
$platforms = json_decode($app['platforms'], true);
$success = '';
$error = '';
// 处理版本上传请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['upload_version'])) {
// 验证版本信息
if (empty($_POST['version']) || empty($_FILES['app_file']['name'])) {
$error = '版本号和安装包不能为空';
} else {
// 处理App文件上传
$uploadDir = __DIR__ . '/../uploads/apps/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
// 验证文件大小 (500MB)
if ($_FILES['app_file']['size'] > 500 * 1024 * 1024) {
log_error('应用文件过大: ' . number_format($_FILES['app_file']['size'] / 1024 / 1024, 2) . 'MB', __FILE__, __LINE__);
$error = '应用文件大小不能超过500MB';
} else {
$appExtension = pathinfo($_FILES['app_file']['name'], PATHINFO_EXTENSION);
// 生成6位随机数
$randomNumber = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT);
// 清理应用名称中的特殊字符
$cleanAppName = preg_replace('/[^a-zA-Z0-9_]/', '_', $app['name']);
$appFileName = $cleanAppName . '_' . $randomNumber . '.' . $appExtension;
$appRelativePath = 'uploads/apps/' . $appFileName;
$targetPath = $uploadDir . $appFileName;
if (move_uploaded_file($_FILES['app_file']['tmp_name'], $targetPath)) {
$version = $_POST['version'];
$changelog = $_POST['changelog'] ?? '';
// 插入新版本记录
$insertVersionSql = "INSERT INTO app_versions (app_id, version, changelog, file_path) VALUES (?, ?, ?, ?)";
$verStmt = $conn->prepare($insertVersionSql);
if (!$verStmt) {
log_error("版本插入准备失败: " . $conn->error, __FILE__, __LINE__);
$error = '版本保存失败,请稍后再试';
unlink($targetPath); // 清理已上传文件
} else {
$verStmt->bind_param("isss", $appId, $version, $changelog, $appRelativePath);
if ($verStmt->execute()) {
// 更新应用表中的最新版本
$updateAppSql = "UPDATE apps SET version = ? WHERE id = ?";
$updStmt = $conn->prepare($updateAppSql);
if (!$updStmt) {
log_error("应用版本更新准备失败: " . $conn->error, __FILE__, __LINE__);
$error = '更新应用版本失败,请稍后再试';
unlink($targetPath); // 数据库更新失败,删除文件
} else {
$updStmt->bind_param("si", $version, $appId);
$updStmt->execute();
$success = '版本上传成功';
}
} else {
$error = '版本保存失败: '. $conn->error;
unlink($targetPath); // 数据库更新失败,删除文件
}
}
} else {
$error = '文件上传失败';
}
}
}
}
// 处理版本修改请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['version_id'])) {
$versionId = $_POST['version_id'];
$version = $_POST['version'];
$changelog = $_POST['changelog'] ?? '';
// 检查是否有新文件上传
if (!empty($_FILES['new_app_file']['name'])) {
$uploadDir = __DIR__ . '/../uploads/apps/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
// 验证文件大小 (500MB)
if ($_FILES['new_app_file']['size'] > 500 * 1024 * 1024) {
log_error('应用文件过大: ' . number_format($_FILES['new_app_file']['size'] / 1024 / 1024, 2) . 'MB', __FILE__, __LINE__);
$error = '应用文件大小不能超过500MB';
} else {
$appExtension = pathinfo($_FILES['new_app_file']['name'], PATHINFO_EXTENSION);
// 生成6位随机数
$randomNumber = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT);
// 清理应用名称中的特殊字符
$cleanAppName = preg_replace('/[^a-zA-Z0-9_]/', '_', $app['name']);
$appFileName = $cleanAppName . '_' . $randomNumber . '.' . $appExtension;
$appRelativePath = 'uploads/apps/' . $appFileName;
$newFilePath = $uploadDir . $appFileName;
if (move_uploaded_file($_FILES['new_app_file']['tmp_name'], $newFilePath)) {
// 获取旧文件路径并删除
$getOldPathSql = "SELECT file_path FROM app_versions WHERE id = ?";
$getOldPathStmt = $conn->prepare($getOldPathSql);
if (!$getOldPathStmt) {
log_error("获取旧文件路径查询准备失败: " . $conn->error, __FILE__, __LINE__);
$error = '版本修改失败,请稍后再试';
unlink($newFilePath);
} else {
$getOldPathStmt->bind_param("i", $versionId);
$getOldPathStmt->execute();
$oldPathResult = $getOldPathStmt->get_result();
if ($oldPathResult->num_rows > 0) {
$oldPathRow = $oldPathResult->fetch_assoc();
$oldFilePath = __DIR__ . '/../' . $oldPathRow['file_path'];
if (file_exists($oldFilePath)) {
unlink($oldFilePath);
}
}
// 更新版本信息
$updateVersionSql = "UPDATE app_versions SET version = ?, changelog = ?, file_path = ? WHERE id = ?";
$updateVersionStmt = $conn->prepare($updateVersionSql);
if (!$updateVersionStmt) {
log_error("版本更新查询准备失败: " . $conn->error, __FILE__, __LINE__);
$error = '版本修改失败,请稍后再试';
unlink($newFilePath);
} else {
$updateVersionStmt->bind_param("sssi", $version, $changelog, $appRelativePath, $versionId);
if ($updateVersionStmt->execute()) {
$success = '版本修改成功';
} else {
$error = '版本修改失败: ' . $conn->error;
unlink($newFilePath);
}
}
}
} else {
$error = '文件上传失败';
}
}
} else {
// 仅更新版本号和更新日志
$updateVersionSql = "UPDATE app_versions SET version = ?, changelog = ? WHERE id = ?";
$updateVersionStmt = $conn->prepare($updateVersionSql);
if (!$updateVersionStmt) {
log_error("版本更新查询准备失败: " . $conn->error, __FILE__, __LINE__);
$error = '版本修改失败,请稍后再试';
} else {
$updateVersionStmt->bind_param("ssi", $version, $changelog, $versionId);
if ($updateVersionStmt->execute()) {
$success = '版本修改成功';
} else {
$error = '版本修改失败: ' . $conn->error;
}
}
}
}
// 处理版本删除请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_version'])) {
// 设置内容类型为纯文本
header('Content-Type: text/plain');
$versionId = $_POST['version_id'];
// 初始化消息变量
$message = '';
// 开始事务
$conn->begin_transaction();
try {
// 1. 获取文件路径
$filePath = '';
$getFilePathSql = "SELECT file_path FROM app_versions WHERE id = ?";
$getFileStmt = $conn->prepare($getFilePathSql);
if (!$getFileStmt) {
throw new Exception("获取文件路径查询准备失败: " . $conn->error);
}
$getFileStmt->bind_param("i", $versionId);
$getFileStmt->execute();
$fileResult = $getFileStmt->get_result();
if ($fileResult->num_rows > 0) {
$fileRow = $fileResult->fetch_assoc();
$filePath = __DIR__ . '/../' . $fileRow['file_path'];
}
// 2. 从数据库删除版本记录
$deleteVersionSql = "DELETE FROM app_versions WHERE id = ?";
$deleteVersionStmt = $conn->prepare($deleteVersionSql);
if (!$deleteVersionStmt) {
throw new Exception("版本删除查询准备失败: " . $conn->error);
}
$deleteVersionStmt->bind_param("i", $versionId);
if (!$deleteVersionStmt->execute()) {
throw new Exception("版本删除执行失败: " . $conn->error);
}
// 检查是否有记录被删除
if ($deleteVersionStmt->affected_rows === 0) {
throw new Exception("未找到要删除的版本记录");
}
// 3. 如果数据库删除成功,尝试删除文件(即使文件删除失败也不回滚数据库操作)
if (!empty($filePath) && file_exists($filePath)) {
if (!unlink($filePath)) {
log_error("文件删除失败: " . $filePath, __FILE__, __LINE__);
// 文件删除失败不影响数据库操作,继续处理
}
}
// 提交事务
$conn->commit();
$message = '版本删除成功';
} catch (Exception $e) {
// 回滚事务
$conn->rollback();
log_error("版本删除异常: " . $e->getMessage(), __FILE__, __LINE__);
$message = '版本删除失败: ' . $e->getMessage();
}
// 只输出消息不包含任何HTML
echo $message;
// 确保脚本终止,不执行后续代码
exit;
}
// 获取现有版本列表
$versions = [];
$getVersionsSql = "SELECT * FROM app_versions WHERE app_id = ? ORDER BY id DESC";
$verStmt = $conn->prepare($getVersionsSql);
if (!$verStmt) {
log_error("版本查询准备失败: " . $conn->error, __FILE__, __LINE__);
$error = '获取版本列表失败,请稍后再试';
} else {
$verStmt->bind_param("i", $appId);
$verStmt->execute();
$versionsResult = $verStmt->get_result();
while ($ver = $versionsResult->fetch_assoc()) {
$versions[] = $ver;
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>版本控制 - <?php echo htmlspecialchars($app['name']); ?></title>
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome -->
<link rel="stylesheet" href="/css/all.min.css">
<link rel="stylesheet" href="../styles.css">
<script src="/js/sweetalert.js"></script>
<!-- Marked.js库用于Markdown解析 -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
.blur-bg {
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, 0.5);
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light blur-bg">
<div class="container">
<a href="../index.php"><img src="/favicon.jpeg" alt="Logo" style="height: 30px; margin-right: 10px; border-radius: var(--border-radius);"></a>
<a class="navbar-brand" href="../index.php"><?php echo APP_STORE_NAME; ?></a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="dashboard.php">我的应用</a>
</li>
<li class="nav-item">
<a class="nav-link" href="upload_app.php">上传新应用</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="version_control.php?id=<?php echo $appId; ?>">版本控制</a>
</li>
<li class="nav-item">
<a class="nav-link" href="profile.php">个人资料</a>
</li>
<li class="nav-item">
<a class="nav-link" href="logout.php">退出登录</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-4">
<?php if (!empty($success)): ?>
<!-- <script>Swal.fire('成功', '<?php echo addslashes($success); ?>', 'success');</script> -->
<?php endif; ?>
<?php if (!empty($error)): ?>
<!-- <script>Swal.fire('错误', '<?php echo addslashes($error); ?>', 'error');</script> -->
<?php endif; ?>
<div class="card blur-bg mb-4">
<div class="card-header">
<h2>应用版本控制: <?php echo htmlspecialchars($app['name']); ?></h2>
</div>
<div class="card-body">
<h4>上传新版本</h4>
<form method="post" enctype="multipart/form-data" class="mb-4">
<div class="row g-3">
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="version" name="version" placeholder="版本号" required>
<label for="version">版本号 (如: 1.0.0)</label>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="app_file" class="form-label">安装包文件</label>
<input class="form-control" type="file" id="app_file" name="app_file" required>
</div>
</div>
</div>
<div class="mb-3">
<div class="mb-1">
<label for="changelog" class="form-label">更新日志支持Markdown</label>
<div class="btn-group float-end">
<button type="button" id="writeModeBtn" class="btn btn-sm btn-primary active">编辑</button>
<button type="button" id="previewModeBtn" class="btn btn-sm btn-secondary">预览</button>
</div>
</div>
<div id="writeModeDiv">
<textarea class="form-control" id="changelog" name="changelog" rows="6" placeholder="更新日志支持Markdown语法"></textarea>
</div>
<div id="previewModeDiv" class="p-3 border rounded bg-light" style="min-height: 200px; display: none;"></div>
</div>
<button type="submit" class="btn btn-primary" name="upload_version"><i class="fas fa-cloud-upload-alt me-1"></i>上传新版本</button>
<a href="dashboard.php" class="btn btn-secondary ms-2"><i class="fas fa-arrow-left me-1"></i>返回</a>
</form>
<hr>
<h4>版本历史</h4>
<?php if (empty($versions)): ?>
<div class="alert alert-info">暂无版本记录</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>版本号</th>
<th>上传时间</th>
<th>更新日志</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($versions as $ver): ?>
<tr>
<td><?php echo htmlspecialchars($ver['version']); ?></td>
<td><?php echo htmlspecialchars($ver['upload_time']); ?></td>
<td>
<div class="changelog-content" data-markdown="<?php echo htmlspecialchars($ver['changelog'] ?: '无'); ?>">
<?php echo nl2br(htmlspecialchars($ver['changelog'] ?: '无')); ?>
</div>
</td>
<td>
<a href="../download.php?id=<?php echo $ver['id']; ?>&type=version" class="btn btn-sm btn-outline-primary"><i class="fas fa-download me-1"></i>下载</a>
<a href="#" class="btn btn-sm btn-outline-warning ms-2" onclick="openEditModal(<?php echo $ver['id']; ?>, '<?php echo htmlspecialchars($ver['version']); ?>', '<?php echo htmlspecialchars($ver['changelog']); ?>')"><i class="fas fa-edit me-1"></i>修改</a>
<a href="#" class="btn btn-sm btn-outline-danger ms-2" onclick="confirmDelete(<?php echo $ver['id']; ?>)"><i class="fas fa-trash-alt me-1"></i>删除</a>
<?php if ($ver['is_current'] == 1): ?>
<span class="badge bg-success">当前版本</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
<script src="../js/bootstrap.bundle.js"></script>
<script>
// Markdown预览功能实现
function initMarkdownPreview() {
// 上传表单的Markdown预览
const writeModeBtn = document.getElementById('writeModeBtn');
const previewModeBtn = document.getElementById('previewModeBtn');
const writeModeDiv = document.getElementById('writeModeDiv');
const previewModeDiv = document.getElementById('previewModeDiv');
const changelogTextarea = document.getElementById('changelog');
writeModeBtn.addEventListener('click', function() {
writeModeBtn.classList.add('active');
writeModeBtn.classList.remove('btn-secondary');
writeModeBtn.classList.add('btn-primary');
previewModeBtn.classList.remove('active');
previewModeBtn.classList.remove('btn-primary');
previewModeBtn.classList.add('btn-secondary');
writeModeDiv.style.display = 'block';
previewModeDiv.style.display = 'none';
});
previewModeBtn.addEventListener('click', function() {
previewModeBtn.classList.add('active');
previewModeBtn.classList.remove('btn-secondary');
previewModeBtn.classList.add('btn-primary');
writeModeBtn.classList.remove('active');
writeModeBtn.classList.remove('btn-primary');
writeModeBtn.classList.add('btn-secondary');
writeModeDiv.style.display = 'none';
previewModeDiv.style.display = 'block';
// 解析Markdown并显示预览
if (changelogTextarea && marked) {
previewModeDiv.innerHTML = marked.parse(changelogTextarea.value || '无更新日志');
}
});
// 实时更新预览
changelogTextarea.addEventListener('input', function() {
if (previewModeDiv.style.display !== 'none' && marked) {
previewModeDiv.innerHTML = marked.parse(changelogTextarea.value || '无更新日志');
}
});
}
function openEditModal(versionId, version, changelog) {
const modal = `
<div class="modal fade" id="editVersionModal" tabindex="-1" aria-labelledby="editVersionModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editVersionModalLabel">修改版本</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="editVersionForm" method="post" enctype="multipart/form-data">
<div class="modal-body">
<input type="hidden" name="version_id" value="${versionId}">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="editVersion" name="version" value="${version}" required>
<label for="editVersion">版本号</label>
</div>
<div class="mb-3">
<div class="mb-1">
<label for="editChangelog" class="form-label">更新日志</label>
<div class="btn-group float-end">
<button type="button" id="editWriteModeBtn" class="btn btn-sm btn-primary active">编辑</button>
<button type="button" id="editPreviewModeBtn" class="btn btn-sm btn-secondary">预览</button>
</div>
</div>
<div id="editWriteModeDiv">
<textarea class="form-control" id="editChangelog" name="changelog" rows="6">${changelog}</textarea>
</div>
<div id="editPreviewModeDiv" class="p-3 border rounded bg-light" style="min-height: 200px; display: none;"></div>
</div>
<div class="mb-3">
<label for="new_app_file" class="form-label">更新App文件 (可选)</label>
<input class="form-control" type="file" id="new_app_file" name="new_app_file">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><i class="fas fa-times me-1"></i>取消</button>
<button type="submit" class="btn btn-primary"><i class="fas fa-save me-1"></i>保存修改</button>
</div>
</form>
</div>
</div>
</div>`;
document.body.insertAdjacentHTML('beforeend', modal);
const editModal = new bootstrap.Modal(document.getElementById('editVersionModal'));
editModal.show();
document.getElementById('editVersionForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch('version_control.php', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(data => {
editModal.hide();
window.location.reload();
})
.catch(error => {
editModal.hide();
window.location.reload();
});
});
// 编辑模态框的Markdown预览功能
const editWriteModeBtn = document.getElementById('editWriteModeBtn');
const editPreviewModeBtn = document.getElementById('editPreviewModeBtn');
const editWriteModeDiv = document.getElementById('editWriteModeDiv');
const editPreviewModeDiv = document.getElementById('editPreviewModeDiv');
const editChangelogTextarea = document.getElementById('editChangelog');
editWriteModeBtn.addEventListener('click', function() {
editWriteModeBtn.classList.add('active');
editWriteModeBtn.classList.remove('btn-secondary');
editWriteModeBtn.classList.add('btn-primary');
editPreviewModeBtn.classList.remove('active');
editPreviewModeBtn.classList.remove('btn-primary');
editPreviewModeBtn.classList.add('btn-secondary');
editWriteModeDiv.style.display = 'block';
editPreviewModeDiv.style.display = 'none';
});
editPreviewModeBtn.addEventListener('click', function() {
editPreviewModeBtn.classList.add('active');
editPreviewModeBtn.classList.remove('btn-secondary');
editPreviewModeBtn.classList.add('btn-primary');
editWriteModeBtn.classList.remove('active');
editWriteModeBtn.classList.remove('btn-primary');
editWriteModeBtn.classList.add('btn-secondary');
editWriteModeDiv.style.display = 'none';
editPreviewModeDiv.style.display = 'block';
// 解析Markdown并显示预览
if (editChangelogTextarea && marked) {
editPreviewModeDiv.innerHTML = marked.parse(editChangelogTextarea.value || '无更新日志');
}
});
// 实时更新预览
editChangelogTextarea.addEventListener('input', function() {
if (editPreviewModeDiv.style.display !== 'none' && marked) {
editPreviewModeDiv.innerHTML = marked.parse(editChangelogTextarea.value || '无更新日志');
}
});
// 模态框关闭时移除元素
document.getElementById('editVersionModal').addEventListener('hidden.bs.modal', function() {
this.remove();
});
}
function confirmDelete(versionId) {
// 使用Sweet Alert弹窗进行确认
Swal.fire({
title: '确定要删除这个版本吗?',
text: "此操作无法撤销,删除后将无法恢复。",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: '确认删除',
cancelButtonText: '取消'
}).then((result) => {
if (result.isConfirmed) {
const formData = new FormData();
formData.append('delete_version', 'true');
formData.append('version_id', versionId);
fetch('version_control.php', {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest' // 添加AJAX请求标识
}
})
.then(response => response.text())
.then(data => {
// 清理返回的文本去除任何可能的HTML标签或额外空格
const cleanMessage = data.trim();
// 显示操作结果
if (cleanMessage.includes('成功')) {
Swal.fire({
title: '操作成功',
text: '版本已成功删除',
icon: 'success'
}).then(() => {
window.location.reload();
});
} else {
Swal.fire(
'操作失败',
cleanMessage || '版本删除失败,请稍后再试',
'error'
).then(() => {
window.location.reload();
});
}
})
.catch(error => {
console.error('删除请求错误:', error);
Swal.fire(
'操作失败',
'版本删除失败,请稍后再试',
'error'
).then(() => {
window.location.reload();
});
});
}
});
}
// 页面加载完成后初始化Markdown预览功能
document.addEventListener('DOMContentLoaded', function() {
initMarkdownPreview();
// 为版本历史中的更新日志添加Markdown渲染
renderChangelogHistory();
});
// 渲染版本历史中的更新日志
function renderChangelogHistory() {
const changelogElements = document.querySelectorAll('.changelog-content');
changelogElements.forEach(element => {
const markdownText = element.getAttribute('data-markdown');
if (markdownText && marked) {
try {
// 创建一个切换按钮
const toggleBtn = document.createElement('button');
toggleBtn.className = 'btn btn-xs btn-outline-secondary mb-1';
toggleBtn.textContent = '查看格式化';
let isFormatted = false;
const originalContent = element.innerHTML;
toggleBtn.addEventListener('click', function() {
if (isFormatted) {
element.innerHTML = originalContent;
toggleBtn.textContent = '查看格式化';
} else {
element.innerHTML = marked.parse(markdownText);
toggleBtn.textContent = '查看原始';
}
isFormatted = !isFormatted;
});
// 将按钮添加到元素前
element.parentNode.insertBefore(toggleBtn, element);
} catch (error) {
console.error('Markdown解析错误:', error);
}
}
});
}
</script>
</body>
</html>