feat(admin): add ephemeral staging DB, read-only posts overview, and dynamic search

- Implement ephemeral staging mode (APP_ENV=staging) to isolate test/dev DB writes in /tmp
- Add read-only posts management dashboard under /guanli/posts with live links and comment counters
- Add hot re-indexing endpoint (/guanli/reindex) to refresh Markdown without restarting server
- Replace static recommended search config with dynamic frequency-based trending searches
- Remove early scaffold mockup file (dropbox/zh.md) and clean legacy mock test queries
- Add native Makefile with dev, dev-persistent, test, lint, and docker targets
- Update test suite and documentation for development workflows
This commit is contained in:
2026-09-16 23:09:14 -07:00
parent f52b3fe9e4
commit 95a7dcb93b
12 changed files with 510 additions and 83 deletions
+5 -13
View File
@@ -5,7 +5,6 @@ const contentService = require('../services/content');
const { loadSiteConfig } = require('../config');
function getRecommendedSearches() {
const config = loadSiteConfig();
const taxonomy = contentService.getTaxonomy();
const dbService = require('../services/db');
@@ -29,26 +28,19 @@ function getRecommendedSearches() {
});
}
// 3. Add top trending searches from SQLite database
const trendingDb = dbService.getTopSearchRecommendations(4);
// 3. Add genuine trending searches by frequency from search_logs (result_count > 0)
const trendingDb = dbService.getTopSearchQueries(6);
const customPills = [];
for (const item of trendingDb) {
if (!dynamicPills.some(p => p.query === item.query)) {
if (!dynamicPills.some(p => p.query.toLowerCase() === item.query.toLowerCase())) {
customPills.push({
label: item.label,
query: item.query
query: item.query,
frequency: item.frequency
});
}
}
// 4. Add any static curated pills from config
const staticConfig = (config.search && config.search.recommended) || [];
for (const item of staticConfig) {
if (!dynamicPills.some(p => p.query === item.query) && !customPills.some(p => p.query === item.query)) {
customPills.push(item);
}
}
return {
dynamicPills,
customPills