diff --git a/i18n/en/code.json b/i18n/en/code.json
index 7164d17..31e8f83 100644
--- a/i18n/en/code.json
+++ b/i18n/en/code.json
@@ -1147,6 +1147,10 @@
"message": "Released {v0}",
"description": "发布于 {v0}"
},
+ "catalog.currentVersionReleasedAt": {
+ "message": "Current version released on {v0}",
+ "description": "当前版本发布于 {v0}"
+ },
"site.a2d8188544aa": {
"message": "Release date not provided",
"description": "发布日期未提供"
diff --git a/src/features/catalog/components.tsx b/src/features/catalog/components.tsx
index 69e9542..e29b639 100644
--- a/src/features/catalog/components.tsx
+++ b/src/features/catalog/components.tsx
@@ -419,6 +419,21 @@ export function RecipeCard({
)}
+
+ {r.variant.releaseDate ? (
+
+ ) : (
+ translate({ id: 'site.020ef0cc6f35', message: '日期未提供' })
+ )}
+
- Engine
diff --git a/src/features/catalog/styles.module.css b/src/features/catalog/styles.module.css
index dd76d45..0d40077 100644
--- a/src/features/catalog/styles.module.css
+++ b/src/features/catalog/styles.module.css
@@ -581,6 +581,12 @@
padding: 0 15px 13px;
margin-top: 14px;
}
+.releaseDate {
+ margin: 0 0 8px;
+ color: var(--color-text-muted);
+ font-size: 12px;
+ line-height: 1.6;
+}
.cardFooter dl {
border-top: 1px solid var(--color-border-default);
padding: 9px 0;
diff --git a/tests/e2e/recipe-release-date.spec.ts b/tests/e2e/recipe-release-date.spec.ts
new file mode 100644
index 0000000..46f5667
--- /dev/null
+++ b/tests/e2e/recipe-release-date.spec.ts
@@ -0,0 +1,46 @@
+import { test, expect } from '@playwright/test';
+import baseline from '../../content/catalog/baseline.json';
+import { parseCatalog } from '../../src/features/catalog/data';
+
+for (const context of ['catalog', 'model'] as const) {
+ for (const missing of [false, true]) {
+ test(`${context} card renders ${missing ? 'missing date fallback' : 'release date'}`, async ({
+ page,
+ }) => {
+ const source = parseCatalog(baseline);
+ const model = source.models.find((m) => m.name === 'glm5.3')!;
+ const variant = model.variants.find(
+ (v) => v.id === 'sglang-tp4-b300-optimized',
+ )!;
+ const date = variant.releaseDate!;
+ if (missing) delete variant.releaseDate;
+ await page.route(
+ 'https://modelsphere.github.io/model-catalog/**',
+ (route) =>
+ route.request().url().endsWith('index-v2.json')
+ ? route.fulfill({ json: source })
+ : route.abort(),
+ );
+ await page.goto(
+ context === 'catalog'
+ ? '/models?q=glm5.3'
+ : '/models/detail?modelId=glm5.3',
+ );
+ const card = page.locator(
+ `[data-recipe-id="${model.name}/${variant.id}"]`,
+ );
+ const releaseDate = card.locator('[data-recipe-release-date]');
+ await expect(releaseDate).toHaveText(
+ missing ? '日期未提供' : `当前版本发布于 ${date}`,
+ );
+ if (missing) {
+ await expect(releaseDate.locator('time')).toHaveCount(0);
+ } else {
+ await expect(releaseDate.locator('time')).toHaveAttribute(
+ 'datetime',
+ date,
+ );
+ }
+ });
+ }
+}