fix: SSR趋势路由真正落盘(上次锚点不存在静默未插入)
This commit is contained in:
@@ -64,6 +64,52 @@ router.get('/sitemap.xml', async (req, res) => {
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
// ===== SSR 趋势页(SEO/GEO:真实内容直出,搜索引擎可收录) =====
|
||||
const TREND_PAGE_CSS = 'body{font-family:-apple-system,"PingFang SC",sans-serif;color:#1f2333;max-width:720px;margin:0 auto;padding:24px 18px;line-height:1.7}h1{font-size:22px}.meta{color:#9aa0b4;font-size:12px;margin:4px 0 20px}a{color:#5b5ff8;text-decoration:none}.item{padding:14px 0;border-bottom:1px solid #eef0f6}.item h2{font-size:16px;margin:0 0 6px}.item p{margin:0;font-size:13px;color:#6b7080}.item .m{font-size:11px;color:#a6abbb;margin-top:4px}.tag{display:inline-block;background:rgba(91,95,248,.1);color:#5b5ff8;border-radius:99px;padding:1px 8px;font-size:11px;margin-right:6px}.foot{margin-top:28px;color:#b6bac9;font-size:12px}'
|
||||
|
||||
router.get('/trends', async (req, res) => {
|
||||
const o = origin(req)
|
||||
let items = []
|
||||
try { items = await Trend.find({}).sort({ newsDate: -1 }).limit(30).lean() } catch (e) {}
|
||||
const list = items.map((t) => `
|
||||
<div class="item">
|
||||
<h2><a href="${o}/trends/${t._id}">${esc(t.title)}</a></h2>
|
||||
${t.summary ? `<p>${esc(String(t.summary).slice(0, 120))}</p>` : ''}
|
||||
<div class="m"><span class="tag">${esc(t.category || '资讯')}</span>${esc(t.source || '')} · ${(t.newsDate || t.createdAt || '').toString().slice(0, 10)}</div>
|
||||
</div>`).join('')
|
||||
res.type('html').send(`<!doctype html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>每日 AI 趋势速递 | 宇之然AI维度</title>
|
||||
<meta name="description" content="每天 8:00/20:00 自动采集 Hacker News、arXiv 等来源的 AI 热点:产品发布、论文、工具、公司动态,中文归类速递。">
|
||||
<link rel="canonical" href="${o}/trends">
|
||||
<style>${TREND_PAGE_CSS}</style></head><body>
|
||||
<h1>每日 AI 趋势速递</h1>
|
||||
<div class="meta">宇之然AI维度 · 自动采集更新</div>
|
||||
${list || '<p>暂无内容</p>'}
|
||||
<div class="foot">© ${new Date().getFullYear()} 宇之然 · <a href="/">打开小程序获取完整体验</a></div>
|
||||
</body></html>`)
|
||||
})
|
||||
|
||||
router.get('/trends/:id', async (req, res) => {
|
||||
const o = origin(req)
|
||||
let t = null
|
||||
try { t = await Trend.findById(req.params.id).lean() } catch (e) {}
|
||||
if (!t) return res.status(404).type('html').send('<h3>内容不存在</h3><a href="/trends">返回趋势列表</a>')
|
||||
res.type('html').send(`<!doctype html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>${esc(t.title)} | AI维度趋势</title>
|
||||
<meta name="description" content="${esc(String(t.summary || t.title).slice(0, 100))}">
|
||||
<link rel="canonical" href="${o}/trends/${t._id}">
|
||||
<style>${TREND_PAGE_CSS}</style></head><body>
|
||||
<span class="tag">${esc(t.category || '资讯')}</span>
|
||||
<h1>${esc(t.title)}</h1>
|
||||
<div class="meta">${esc(t.source || '')} · ${(t.newsDate || t.createdAt || '').toString().slice(0, 10)}</div>
|
||||
${t.summary ? `<p>${esc(t.summary)}</p>` : ''}
|
||||
${t.body ? `<div>${esc(t.body).split('\n').map((p) => `<p>${p}</p>`).join('')}</div>` : ''}
|
||||
${t.sourceUrl ? `<p><a href="${esc(t.sourceUrl)}" rel="noopener nofollow" target="_blank">阅读原文 →</a></p>` : ''}
|
||||
<div class="foot"><a href="/trends">← 更多 AI 趋势</a> · © 宇之然</div>
|
||||
</body></html>`)
|
||||
})
|
||||
|
||||
router.get('/llms.txt', (req, res) => {
|
||||
const o = origin(req)
|
||||
res.type('text/markdown').send(
|
||||
|
||||
Reference in New Issue
Block a user