basename($filePath), 'author' => '', 'date' => '', 'platform' => '', 'url' => '', 'tags' => [], 'duration' => '', 'type' => 'article', 'summary' => '' ]; // 解析 YAML front matter if (preg_match('/^---\s*\n(.*?)\n---\s*\n(.*)$/s', $content, $matches)) { $yaml = $matches[1]; $body = $matches[2]; // 解析 YAML 字段 if (preg_match('/^title:\s*["\']?(.+?)["\']?\s*$/m', $yaml, $m)) { $meta['title'] = trim($m[1], '"\''); } if (preg_match('/^author:\s*(.+?)\s*$/m', $yaml, $m)) { $meta['author'] = trim($m[1]); } if (preg_match('/^date:\s*(.+?)\s*$/m', $yaml, $m)) { $meta['date'] = trim($m[1]); } if (preg_match('/^platform:\s*(.+?)\s*$/m', $yaml, $m)) { $meta['platform'] = trim($m[1]); } if (preg_match('/^url:\s*(.+?)\s*$/m', $yaml, $m)) { $meta['url'] = trim($m[1]); } if (preg_match('/^duration:\s*(.+?)\s*$/m', $yaml, $m)) { $meta['duration'] = trim($m[1]); $meta['type'] = 'video'; } if (preg_match('/^tags:\s*\[(.+)\]\s*$/m', $yaml, $m)) { $tagsStr = $m[1]; preg_match_all('/"([^"]+)"/', $tagsStr, $tagMatches); $meta['tags'] = $tagMatches[1] ?? []; } // 提取正文概述 $lines = preg_split('/\r?\n/', trim($body)); $summaryLines = []; foreach ($lines as $line) { $line = trim($line); if (empty($line) || strpos($line, '##') === 0) continue; $summaryLines[] = $line; if (count($summaryLines) >= 2) break; } $meta['summary'] = implode(' ', $summaryLines); } return $meta; } // 递归获取文档列表 $documents = []; function scanDirectory($dir, $baseDir, $search) { $docs = []; if (!is_dir($dir)) return $docs; $items = scandir($dir); foreach ($items as $item) { if ($item === '.' || $item === '..') continue; $fullPath = $dir . '/' . $item; $relativePath = str_replace($baseDir . '/', '', $fullPath); if (is_dir($fullPath)) { $docs = array_merge($docs, scanDirectory($fullPath, $baseDir, $search)); } elseif (is_file($fullPath)) { $ext = strtolower(pathinfo($item, PATHINFO_EXTENSION)); if (!in_array($ext, ['md', 'txt', 'markdown'])) continue; $content = file_get_contents($fullPath); if ($search) { $searchLower = mb_strtolower($search); $contentLower = mb_strtolower($content); if (strpos($contentLower, $searchLower) === false) { continue; } } $meta = parseMarkdownWithMeta($fullPath); $docs[] = [ 'name' => $item, 'path' => $relativePath, 'folder' => dirname($relativePath) === '.' ? '' : dirname($relativePath), 'mtime' => filemtime($fullPath), 'title' => $meta['title'], 'author' => $meta['author'], 'date' => $meta['date'], 'platform' => $meta['platform'], 'url' => $meta['url'], 'tags' => $meta['tags'], 'duration' => $meta['duration'], 'type' => $meta['type'], 'summary' => $meta['summary'] ]; } } return $docs; } $documents = scanDirectory($docDir, $docDir, $search); // 排序 usort($documents, function($a, $b) { if ($a['date'] && $b['date']) { return strcmp($b['date'], $a['date']); } return $b['mtime'] - $a['mtime']; }); // 平台配置 function getPlatformInfo($platform) { $platforms = [ 'bilibili' => ['name' => 'Bilibili', 'icon' => '📺', 'color' => '#fb7299'], 'youtube' => ['name' => 'YouTube', 'icon' => '▶️', 'color' => '#ff0000'], 'zhihu' => ['name' => '知乎', 'icon' => '💡', 'color' => '#0084ff'], 'wechat' => ['name' => '微信', 'icon' => '💬', 'color' => '#07c160'], ]; return $platforms[$platform] ?? ['name' => $platform ?: '未知', 'icon' => '📄', 'color' => '#666']; } // 类型图标 function getTypeIcon($type) { return $type === 'video' ? '🎬' : '📝'; } ?>