fix: content API news/blog字段映射createdAt改为date

与前端模板article.date保持一致,修复日期显示NaN的根本原因

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
这个提交包含在:
wx 2026-04-13 14:48:29 +08:00
父节点 6c79aad1dd
当前提交 f6ec85d506

查看文件

@ -1,22 +1,168 @@
import { eq } from 'drizzle-orm' import { eq, desc, asc } from 'drizzle-orm'
import { useDB, schema } from '../../utils/db.js' import { useDB, schema } from '../../utils/db.js'
/**
* 实ä½è¡¨æ°æ<EFBFBD>®æžå»ºå¨
* å½ key 对åºç¬ç«å®žä½è¡¨æï¼Œä»Žå®žä½è¡¨åЍæ<EFBFBD>读å<EFBFBD>æ°æ<EFBFBD>®ï¼Œ
* å<EFBFBD>Œæå<EFBFBD>ˆå¹ site_content 中çšåƒæ°æ<EFBFBD>®ï¼ˆsummary/seo ç­ï¼
*/
function buildFromEntityTable(db, key, siteData) {
switch (key) {
case 'reviews': {
const items = db.select().from(schema.reviews)
.where(eq(schema.reviews.published, true))
.orderBy(asc(schema.reviews.sortOrder), desc(schema.reviews.id))
.all()
.map(r => ({
id: r.id,
nickname: r.author,
travelDate: r.date,
productVersion: r.title,
screenshot: '',
content: r.content,
rating: r.rating,
scenes: [],
concerns: [],
}))
// å<>ˆå¹¶ site_content çš„ summaryï¼ˆå¦æžœæœ‰/¼‰
const summary = siteData?.summary || {
totalCount: items.length,
approvalRate: '98%',
}
// 用实体表 items 覆盖 site_content 的 items
return { summary, items }
}
case 'faq': {
const items = db.select().from(schema.faqs)
.where(eq(schema.faqs.published, true))
.orderBy(asc(schema.faqs.sortOrder), asc(schema.faqs.id))
.all()
// site_content 有分类结构则ä¿<C3A4>留,把实体表的问答作为「全部ã€<C3A3>
if (siteData?.categories) return siteData
return {
categories: [{
id: 'all',
name: ¸¸è§<C3A8>问题',
questions: items.map(f => ({
question: f.question,
answer: f.answer,
})),
}],
}
}
case 'gallery': {
const items = db.select().from(schema.galleryItems)
.where(eq(schema.galleryItems.published, true))
.orderBy(asc(schema.galleryItems.sortOrder), asc(schema.galleryItems.id))
.all()
const works = items.map(g => ({
id: g.id,
title: g.title,
category: g.category,
location: g.location,
description: g.description,
image: g.image,
orientation: g.orientation,
}))
const categories = siteData?.categories || [{key:"all",label:"全部作å“<C3A5>"}]
return {
seo: siteData?.seo || {},
intro: siteData?.intro || {},
categories,
works,
}
}
case 'stories': {
const items = db.select().from(schema.stories)
.where(eq(schema.stories.published, true))
.orderBy(asc(schema.stories.sortOrder), desc(schema.stories.id))
.all()
.map(s => ({
...s,
sections: s.sections ? JSON.parse(s.sections) : [],
keyMoments: s.keyMoments ? JSON.parse(s.keyMoments) : [],
}))
return { stories: items }
}
case 'news': {
const items = db.select().from(schema.articles)
.where(eq(schema.articles.published, true))
.orderBy(desc(schema.articles.id))
.all()
.filter(a => a.type === 'news')
.map(a => ({
id: a.slug,
title: a.title,
summary: a.summary,
content: a.content,
category: a.category,
coverImage: a.coverImage,
author: a.author,
tags: a.tags ? JSON.parse(a.tags) : [],
date: a.createdAt,
}))
return { articles: items }
}
case 'blog': {
const items = db.select().from(schema.articles)
.where(eq(schema.articles.published, true))
.orderBy(desc(schema.articles.id))
.all()
.filter(a => a.type === 'blog')
.map(a => ({
id: a.slug,
title: a.title,
summary: a.summary,
content: a.content,
category: a.category,
coverImage: a.coverImage,
author: a.author,
tags: a.tags ? JSON.parse(a.tags) : [],
seoTitle: a.seoTitle,
seoDescription: a.seoDesc,
seoKeywords: a.seoKeywords,
date: a.createdAt,
}))
return { articles: items }
}
default:
return null
}
}
// 有entity表的 key 列表
const ENTITY_KEYS = ['reviews', 'faq', 'gallery', 'stories', 'news', 'blog']
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const key = getRouterParam(event, 'key') const key = getRouterParam(event, 'key')
const db = useDB() const db = useDB()
const item = db // 读site_content(作为元数æ<C2B0>®æˆ–兜底)
.select() const item = db.select().from(schema.siteContent)
.from(schema.siteContent)
.where(eq(schema.siteContent.key, key)) .where(eq(schema.siteContent.key, key))
.get() .get()
const siteData = item ? JSON.parse(item.data) : null
if (!item) { // 妿žœæ˜¯å®žä½“表key,优先从实体表构建
if (ENTITY_KEYS.includes(key)) {
const result = buildFromEntityTable(db, key, siteData)
if (result) {
setHeader(event, 'Cache-Control', 'public, max-age=60')
return result
}
}
// 普通 site_content key
if (!siteData) {
throw createError({ statusCode: 404, message: `未找到配置项: ${key}` }) throw createError({ statusCode: 404, message: `未找到配置项: ${key}` })
} }
setHeader(event, 'Cache-Control', 'public, max-age=60') setHeader(event, 'Cache-Control', 'public, max-age=60')
return siteData
return JSON.parse(item.data)
}) })