main
xgkblog/admin/post_edit.php
post_edit.php6.6 KB
<?php
require 'config.php';
$is_edit = false;
$post_data = ['title'=>'', 'content'=>'', 'category_id'=>0];

// 如果是编辑模式,获取原数据
if (isset($_GET['id'])) {
    $is_edit = true;
    $stmt = $pdo->prepare("SELECT * FROM posts WHERE id = :id");
    $stmt->execute([':id' => $_GET['id']]);
    $post_data = $stmt->fetch(PDO::FETCH_ASSOC);
}

// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
       // 如果是 AJAX 请求,跳过此处的表单保存逻辑(由下方 JS 处理)
    if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        header('Content-Type: application/json');
        
        // 检查是否有图片上传
        if (isset($_FILES['image'])) {
            $file = $_FILES['image'];
            $allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
            
            if (!in_array($file['type'], $allowed_types)) {
                echo json_encode(['errno' => 1, 'message' => '只允许上传 JPG/PNG/GIF 格式']);
                exit;
            }
            
            // 【修改点1】使用 DOCUMENT_ROOT 获取网站真实的物理根目录,拼接 /uploads/
            // 这样无论你的脚本在哪个子目录下,都能准确定位到根目录的 uploads 文件夹
            $upload_dir = $_SERVER['DOCUMENT_ROOT'] . '/uploads/';
            
            if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true);
            
            $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
            $new_name = uniqid() . '.' . $ext;
            $target_path = $upload_dir . $new_name;
            
            if (move_uploaded_file($file['tmp_name'], $target_path)) {
                // 【修改点2】返回给前端编辑器的 URL 必须以 / 开头
                // 这代表相对于网站域名的绝对路径,确保在任何页面都能正确显示图片
                echo json_encode(['errno' => 0, 'data' => '/uploads/' . $new_name]);
            } else {
                echo json_encode(['errno' => 1, 'message' => '文件保存失败']);
            }
        } else {
            echo json_encode(['errno' => 1, 'message' => '未接收到文件']);
        }
        exit;
    }

    // 正常的文章保存逻辑
    $title = $_POST['title'];
    $content = $_POST['content'];
    $cat_id = $_POST['category_id'] ?: null;

    if ($is_edit) {
        $stmt = $pdo->prepare("UPDATE posts SET title=:t, content=:c, category_id=:cid WHERE id=:id");
        $stmt->execute([':t'=>$title, ':c'=>$content, ':cid'=>$cat_id, ':id'=>$_GET['id']]);
    } else {
        $stmt = $pdo->prepare("INSERT INTO posts (title, content, category_id, author_id) VALUES (:t, :c, :cid, :aid)");
        $stmt->execute([':t'=>$title, ':c'=>$content, ':cid'=>$cat_id, ':aid'=>$_SESSION['user_id']]);
    }
    header('Location: posts.php?msg=saved'); exit;
}

// 获取所有分类供下拉框使用
$categories = $pdo->query("SELECT id, name FROM categories")->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title><?php echo $is_edit ? '编辑' : '发布'; ?>文章</title>
</head>
<body style="font-family:sans-serif;padding:30px;max-width:800px;margin:auto;">
    <h1><?php echo $is_edit ? '编辑' : '发布新'; ?>文章</h1>
    
    <form method="POST" id="postForm">
        <label>标题:<br><input type="text" name="title" value="<?php echo htmlspecialchars($post_data['title']); ?>" required style="width:100%;padding:8px;margin-bottom:10px;box-sizing:border-box;"></label><br><br>
        
        <label>分类:<br>
            <select name="category_id" style="width:100%;padding:8px;margin-bottom:10px;">
                <option value="">-- 不选择分类 --</option>
                <?php foreach($categories as $cat): ?>
                    <option value="<?php echo $cat['id']; ?>" <?php echo ($post_data['category_id']==$cat['id'])?'selected':''; ?>>
                        <?php echo htmlspecialchars($cat['name']); ?>
                    </option>
                <?php endforeach; ?>
            </select>
        </label><br><br>
        
        <label>内容:</label>
        <!-- 【新增】图片上传按钮 -->
        <div style="margin-bottom:5px;">
            <input type="file" id="imgInput" accept="image/*" style="display:none;">
            <button type="button" onclick="document.getElementById('imgInput').click()" style="padding:5px 10px;background:#007bff;color:#fff;border:none;cursor:pointer;border-radius:3px;">🖼️ 上传图片并插入</button>
            <span id="uploadStatus" style="margin-left:10px;font-size:12px;color:#888;"></span>
        </div>
        
        <textarea name="content" id="contentArea" rows="15" required style="width:100%;padding:8px;box-sizing:border-box;"><?php echo htmlspecialchars($post_data['content']); ?></textarea><br><br>
        
        <button type="submit" style="padding:10px 20px;background:#333;color:#fff;border:none;cursor:pointer;">保存文章</button>
        <a href="posts.php" style="margin-left:10px;text-decoration:none;">取消</a>
    </form>

<script>
// 监听图片选择事件
document.getElementById('imgInput').addEventListener('change', function() {
    const file = this.files[0];
    if (!file) return;
    
    const statusEl = document.getElementById('uploadStatus');
    statusEl.innerText = '上传中...';
    
    const formData = new FormData();
    formData.append('image', file);
    
    // 使用原生 fetch API 发送 AJAX 请求到当前页面
    fetch(window.location.href, {
        method: 'POST',
        body: formData,
        headers: { 'X-Requested-With': 'XMLHttpRequest' } // 标识为 AJAX 请求
    })
    .then(response => response.json())
    .then(result => {
        if (result.errno === 0) {
            // 将图片 URL 插入到 textarea 的光标处
            const textarea = document.getElementById('contentArea');
            const imgTag = '\n<img src="' + result.data + '" alt="" style="max-width:100%;">\n';
            
            const startPos = textarea.selectionStart;
            const endPos = textarea.selectionEnd;
            textarea.value = textarea.value.substring(0, startPos) + imgTag + textarea.value.substring(endPos);
            
            statusEl.innerText = '✅ 插入成功!';
            setTimeout(() => statusEl.innerText = '', 3000);
        } else {
            statusEl.innerText = '❌ ' + result.message;
        }
    })
    .catch(err => {
        statusEl.innerText = '❌ 网络错误';
    });
    
    // 清空 input,允许重复选择同一张图片
    this.value = ''; 
});
</script>
</body>
</html>