更新 z.ai/notes/index.php

This commit is contained in:
2025-10-13 09:55:56 +00:00
parent 78189cd535
commit b786285183
+160 -17
View File
@@ -4,6 +4,7 @@ session_start();
// 配置
define('DB_FILE', 'notes.db');
define('UPLOAD_DIR', 'uploads');
define('IMAGES_DIR', 'uploads/images');
define('APP_NAME', '简约记事本');
define('VERSION', '1.0.0');
define('NOTES_PER_PAGE', 25);
@@ -14,6 +15,11 @@ if (!file_exists(UPLOAD_DIR)) {
mkdir(UPLOAD_DIR, 0755, true);
}
// 确保图片目录存在
if (!file_exists(IMAGES_DIR)) {
mkdir(IMAGES_DIR, 0755, true);
}
// 获取当前页面基础URL
function getBaseUrl() {
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
@@ -59,6 +65,134 @@ class Encryption {
}
}
// 处理内容中的链接和图片
function processContent($content) {
// 自动下载外部图片并替换为本地链接
$content = processExternalImages($content);
// 自动识别URL并转换为Markdown链接格式
$content = autoFormatLinks($content);
return $content;
}
// 自动下载外部图片
function processExternalImages($content) {
// 匹配Markdown图片格式
$pattern = '/!\[(.*?)\]\((https?:\/\/[^\s)]+)\)/';
$content = preg_replace_callback($pattern, function($matches) {
$alt = $matches[1];
$url = $matches[2];
// 检查是否是外部图片URL
if (isExternalImage($url)) {
$localPath = downloadAndSaveImage($url);
if ($localPath) {
return '![' . $alt . '](' . $localPath . ')';
}
}
return $matches[0];
}, $content);
// 匹配纯图片URL(非Markdown格式)
$pattern = '/(?<!\]\()https?:\/\/[^\s]*\.(jpg|jpeg|png|gif|webp)(?!\))/i';
$content = preg_replace_callback($pattern, function($matches) {
$url = $matches[0];
// 检查是否是外部图片URL
if (isExternalImage($url)) {
$localPath = downloadAndSaveImage($url);
if ($localPath) {
return '![](' . $localPath . ')';
}
}
return $url;
}, $content);
return $content;
}
// 检查是否是外部图片URL
function isExternalImage($url) {
// 检查是否是HTTP/HTTPS URL
if (!preg_match('/^https?:\/\//', $url)) {
return false;
}
// 检查是否是当前域名的URL
$baseUrl = getBaseUrl();
if (strpos($url, $baseUrl) === 0) {
return false;
}
// 检查URL是否包含图片扩展名
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$extension = strtolower(pathinfo($url, PATHINFO_EXTENSION));
return in_array($extension, $imageExtensions);
}
// 下载并保存图片
function downloadAndSaveImage($url) {
try {
// 获取图片内容
$imageData = file_get_contents($url);
if (!$imageData) {
return false;
}
// 获取图片信息
$imageInfo = getimagesizefromstring($imageData);
if (!$imageInfo) {
return false;
}
// 生成唯一文件名
$extension = image_type_to_extension($imageInfo[2]);
$filename = uniqid() . $extension;
$filepath = IMAGES_DIR . '/' . $filename;
// 保存图片
if (file_put_contents($filepath, $imageData)) {
// 返回相对于当前脚本的路径
return IMAGES_DIR . '/' . $filename;
}
return false;
} catch (Exception $e) {
return false;
}
}
// 自动格式化链接
function autoFormatLinks($content) {
// 匹配非Markdown格式的URL
$pattern = '/(?<!\]\()https?:\/\/[^\s\)]+(?!\))/i';
$content = preg_replace_callback($pattern, function($matches) {
$url = $matches[0];
// 如果已经是Markdown链接格式,则跳过
if (preg_match('/\[' . preg_quote($url, '/') . '\]\(' . preg_quote($url, '/') . '\)/', $content)) {
return $url;
}
// 如果是图片URL,则跳过(已在processExternalImages中处理)
if (isExternalImage($url)) {
return $url;
}
// 转换为Markdown链接格式
return '[' . $url . '](' . $url . ')';
}, $content);
return $content;
}
// 初始化数据库
function initDatabase() {
try {
@@ -74,11 +208,11 @@ function initDatabase() {
)
');
// 创建笔记表(加密存储
// 创建笔记表(标题不加密,内容加密)
$db->exec('
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title_enc TEXT NOT NULL,
title TEXT NOT NULL,
content_enc TEXT NOT NULL,
tags TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
@@ -101,6 +235,7 @@ function initDatabase() {
');
// 创建索引
$db->exec('CREATE INDEX IF NOT EXISTS idx_notes_title ON notes(title)');
$db->exec('CREATE INDEX IF NOT EXISTS idx_notes_tags ON notes(tags)');
$db->exec('CREATE INDEX IF NOT EXISTS idx_notes_created ON notes(created_at)');
$db->exec('CREATE INDEX IF NOT EXISTS idx_attachments_note_id ON attachments(note_id)');
@@ -167,10 +302,11 @@ function getNotesCount($search = '', $tag = '') {
$params = [];
if ($search) {
// 搜索需要解密,这里简化处理,只搜索标
$sql .= ' AND tags LIKE ?';
// 现在可以搜索标题了
$sql .= ' AND (title LIKE ? OR tags LIKE ?)';
$searchParam = '%' . $search . '%';
$params[] = $searchParam;
$params[] = $searchParam;
}
if ($tag) {
@@ -195,7 +331,8 @@ function getNotes($page = 1, $search = '', $tag = '') {
$params = [];
if ($search) {
$sql .= ' AND tags LIKE ?';
$sql .= ' AND (title LIKE ? OR tags LIKE ?)';
$params[] = '%' . $search . '%';
$params[] = '%' . $search . '%';
}
@@ -217,10 +354,9 @@ function getNotes($page = 1, $search = '', $tag = '') {
$notes = [];
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
// 解密数据
$row['title'] = Encryption::decrypt($row['title_enc']);
// 解密内容,标题不需要解密
$row['content'] = Encryption::decrypt($row['content_enc']);
unset($row['title_enc'], $row['content_enc']);
unset($row['content_enc']);
$notes[] = $row;
}
@@ -236,10 +372,9 @@ function getNote($id) {
$note = $result->fetchArray(SQLITE3_ASSOC);
if ($note) {
// 解密数据
$note['title'] = Encryption::decrypt($note['title_enc']);
// 解密内容,标题不需要解密
$note['content'] = Encryption::decrypt($note['content_enc']);
unset($note['title_enc'], $note['content_enc']);
unset($note['content_enc']);
}
return $note;
@@ -248,9 +383,13 @@ function getNote($id) {
// 创建笔记
function createNote($title, $content, $tags) {
$db = getDB();
$stmt = $db->prepare('INSERT INTO notes (title_enc, content_enc, tags) VALUES (?, ?, ?)');
$stmt->bindValue(1, Encryption::encrypt($title), SQLITE3_TEXT);
$stmt->bindValue(2, Encryption::encrypt($content), SQLITE3_TEXT);
// 处理内容中的链接和图片
$processedContent = processContent($content);
$stmt = $db->prepare('INSERT INTO notes (title, content_enc, tags) VALUES (?, ?, ?)');
$stmt->bindValue(1, $title, SQLITE3_TEXT);
$stmt->bindValue(2, Encryption::encrypt($processedContent), SQLITE3_TEXT);
$stmt->bindValue(3, $tags, SQLITE3_TEXT);
$stmt->execute();
return $db->lastInsertRowID();
@@ -259,9 +398,13 @@ function createNote($title, $content, $tags) {
// 更新笔记
function updateNote($id, $title, $content, $tags) {
$db = getDB();
$stmt = $db->prepare('UPDATE notes SET title_enc = ?, content_enc = ?, tags = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?');
$stmt->bindValue(1, Encryption::encrypt($title), SQLITE3_TEXT);
$stmt->bindValue(2, Encryption::encrypt($content), SQLITE3_TEXT);
// 处理内容中的链接和图片
$processedContent = processContent($content);
$stmt = $db->prepare('UPDATE notes SET title = ?, content_enc = ?, tags = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?');
$stmt->bindValue(1, $title, SQLITE3_TEXT);
$stmt->bindValue(2, Encryption::encrypt($processedContent), SQLITE3_TEXT);
$stmt->bindValue(3, $tags, SQLITE3_TEXT);
$stmt->bindValue(4, $id, SQLITE3_INTEGER);
return $stmt->execute();