array_values($index)], JSON_UNESCAPED_UNICODE); exit; } if ($action === 'get') { $id = $_GET['id'] ?? ''; if (!$id || !safeId($id)) { http_response_code(400); echo json_encode(['error'=>'bad id']); exit; } $index = readJson($indexFile); $title = ''; foreach ($index as $it) { if ($it['id'] === $id) { $title = $it['title'] ?? ''; break; } } $file = $docsDir . DIRECTORY_SEPARATOR . $id . '.html'; $content = file_exists($file) ? file_get_contents($file) : ''; echo json_encode(['id'=>$id,'title'=>$title,'content'=>$content], JSON_UNESCAPED_UNICODE); exit; } if ($action === 'save') { $body = json_decode(file_get_contents('php://input'), true); $id = $body['id'] ?? ''; $title = trim($body['title'] ?? ''); $content = $body['content'] ?? ''; $index = readJson($indexFile); if (!$id) { $id = 'doc_' . uniqid(); $index[] = ['id' => $id, 'title' => $title ?: '未命名']; } else { if (!safeId($id)) { http_response_code(400); echo json_encode(['error'=>'bad id']); exit; } $found = false; foreach ($index as &$it) { if ($it['id'] === $id) { $it['title'] = $title ?: ($it['title'] ?? '未命名'); $found = true; break; } } if (!$found) { $index[] = ['id' => $id, 'title' => $title ?: '未命名']; } } writeJson($indexFile, $index); $file = $docsDir . DIRECTORY_SEPARATOR . $id . '.html'; file_put_contents($file, $content); echo json_encode(['ok'=>true,'id'=>$id], JSON_UNESCAPED_UNICODE); exit; } if ($action === 'delete') { $body = json_decode(file_get_contents('php://input'), true); $id = $body['id'] ?? ''; if (!$id || !safeId($id)) { http_response_code(400); echo json_encode(['error'=>'bad id']); exit; } $index = readJson($indexFile); $index = array_values(array_filter($index, function($it) use ($id) { return $it['id'] !== $id; })); writeJson($indexFile, $index); $file = $docsDir . DIRECTORY_SEPARATOR . $id . '.html'; if (file_exists($file)) unlink($file); echo json_encode(['ok'=>true]); exit; } // 生成分享链接(支持永久、24h、一次性) if ($action === 'share_create' || $action === 'share') { $id = $_GET['id'] ?? ''; $mode = $_GET['mode'] ?? 'permanent'; // permanent | 24h | one_time if (!$id || !safeId($id)) { http_response_code(400); echo json_encode(['error'=>'bad id']); exit; } $shares = readJson($sharesFile); if (!is_array($shares)) $shares = []; // 生成随机令牌 try { $token = bin2hex(random_bytes(16)); } catch (Throwable $e) { $token = uniqid('t_', true); } $now = time(); $expiresAt = null; $singleUse = false; if ($mode === '24h') { $expiresAt = $now + 24*3600; } if ($mode === 'one_time') { $singleUse = true; } $record = [ 'id' => $id, 'token' => $token, 'created_at' => $now, 'expires_at' => $expiresAt, 'single_use' => $singleUse, 'used' => false, 'revoked' => false, ]; $shares[] = $record; writeJson($sharesFile, $shares); $url = '/share.php?token=' . urlencode($token); echo json_encode(['url' => $url, 'token' => $token, 'expires_at' => $expiresAt, 'single_use' => $singleUse], JSON_UNESCAPED_UNICODE); exit; } // 取消当前文档的所有分享 if ($action === 'share_revoke_all') { $id = $_GET['id'] ?? ''; if (!$id || !safeId($id)) { http_response_code(400); echo json_encode(['error'=>'bad id']); exit; } $shares = readJson($sharesFile); if (!is_array($shares)) $shares = []; $new = []; foreach ($shares as $rec) { if (($rec['id'] ?? '') !== $id) { $new[] = $rec; } } writeJson($sharesFile, $new); echo json_encode(['ok' => true]); exit; } http_response_code(404); echo json_encode(['error' => 'unknown action']);