@ -549,7 +549,6 @@ if (!yearChips.length) yearChips = yearSeed
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Alpine from "alpinejs"
|
|
||||||
import { getArticles, getBrands, toAbs, type ArticleItem, type BrandEntry } from "@/lib/api"
|
import { getArticles, getBrands, toAbs, type ArticleItem, type BrandEntry } from "@/lib/api"
|
||||||
|
|
||||||
const ICON_USER = `<svg viewBox="0 0 12 12" width="9" height="9" aria-hidden="true"><circle cx="6" cy="4" r="2" stroke="currentColor" fill="none" stroke-width="1"/><path d="M2 10c0-2 1.8-3 4-3s4 1 4 3" stroke="currentColor" fill="none" stroke-width="1" stroke-linecap="round"/></svg>`
|
const ICON_USER = `<svg viewBox="0 0 12 12" width="9" height="9" aria-hidden="true"><circle cx="6" cy="4" r="2" stroke="currentColor" fill="none" stroke-width="1"/><path d="M2 10c0-2 1.8-3 4-3s4 1 4 3" stroke="currentColor" fill="none" stroke-width="1" stroke-linecap="round"/></svg>`
|
||||||
|
|||||||
@ -53,7 +53,7 @@ const homeHref = locale === "cn" ? "/cn" : "/en/"
|
|||||||
const archiveHref = locale === "cn" ? "/cn/shows" : "/en/shows"
|
const archiveHref = locale === "cn" ? "/cn/shows" : "/en/shows"
|
||||||
const crumbs: { label: string; href: string }[] = [
|
const crumbs: { label: string; href: string }[] = [
|
||||||
{ label: "Home", href: homeHref },
|
{ label: "Home", href: homeHref },
|
||||||
{ label: "Runway Archive", href: archiveHref },
|
{ label: "Runway Looks", href: archiveHref },
|
||||||
]
|
]
|
||||||
if (article?.brand_id) {
|
if (article?.brand_id) {
|
||||||
crumbs.push({
|
crumbs.push({
|
||||||
@ -98,9 +98,6 @@ if (article?.brand_id) {
|
|||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div class="mt-16 pt-6 border-t border-black">
|
|
||||||
<a href={homeHref} class="text-[12px] font-mono uppercase tracking-widest hover:opacity-60 transition-opacity">{lbl.back}</a>
|
|
||||||
</div>
|
|
||||||
</article>
|
</article>
|
||||||
) : (
|
) : (
|
||||||
<div class="flex flex-col items-center justify-center min-h-[60vh] px-5 text-center">
|
<div class="flex flex-col items-center justify-center min-h-[60vh] px-5 text-center">
|
||||||
@ -137,7 +134,7 @@ if (article?.brand_id) {
|
|||||||
class="relative block w-full aspect-[3/4] mb-2 rounded-[2px] overflow-hidden cursor-pointer transition-all duration-200"
|
class="relative block w-full aspect-[3/4] mb-2 rounded-[2px] overflow-hidden cursor-pointer transition-all duration-200"
|
||||||
:class="lbIndex === i ? 'opacity-100 scale-[1.03] ring-2 ring-[#111]' : 'opacity-40 hover:opacity-85'"
|
:class="lbIndex === i ? 'opacity-100 scale-[1.03] ring-2 ring-[#111]' : 'opacity-40 hover:opacity-85'"
|
||||||
>
|
>
|
||||||
<img :src="im.url" alt="" class="w-full h-full object-cover block" />
|
<img :src="im.url" alt="" loading="lazy" class="w-full h-full object-cover block" />
|
||||||
<span
|
<span
|
||||||
class="absolute left-1 top-1 z-10 font-mono text-[8px] sm:text-[9px] font-semibold tracking-widest text-white px-1 py-0.5 rounded-[3px] bg-black/55 backdrop-blur-sm"
|
class="absolute left-1 top-1 z-10 font-mono text-[8px] sm:text-[9px] font-semibold tracking-widest text-white px-1 py-0.5 rounded-[3px] bg-black/55 backdrop-blur-sm"
|
||||||
:class="lbIndex === i ? '!bg-[#111]' : ''"
|
:class="lbIndex === i ? '!bg-[#111]' : ''"
|
||||||
@ -177,6 +174,7 @@ if (article?.brand_id) {
|
|||||||
:src="images[lbIndex].url"
|
:src="images[lbIndex].url"
|
||||||
:alt="images[lbIndex].name || ''"
|
:alt="images[lbIndex].name || ''"
|
||||||
@click="toggleZoom()"
|
@click="toggleZoom()"
|
||||||
|
loading="lazy"
|
||||||
class="block select-none transition-opacity duration-200"
|
class="block select-none transition-opacity duration-200"
|
||||||
:class="lbZoomed ? 'w-full max-w-full h-auto max-h-none cursor-zoom-out' : 'max-w-full max-h-full object-contain cursor-zoom-in'"
|
:class="lbZoomed ? 'w-full max-w-full h-auto max-h-none cursor-zoom-out' : 'max-w-full max-h-full object-contain cursor-zoom-in'"
|
||||||
/>
|
/>
|
||||||
@ -198,6 +196,7 @@ if (article?.brand_id) {
|
|||||||
<!-- Alpine.js 业务逻辑:仅负责灯箱交互,图片数据由服务端注入 -->
|
<!-- Alpine.js 业务逻辑:仅负责灯箱交互,图片数据由服务端注入 -->
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('alpine:init', () => {
|
document.addEventListener('alpine:init', () => {
|
||||||
|
alert(1212)
|
||||||
Alpine.data('articleView', (images = []) => ({
|
Alpine.data('articleView', (images = []) => ({
|
||||||
images,
|
images,
|
||||||
lbOpen: false,
|
lbOpen: false,
|
||||||
|
|||||||
14
src/env.d.ts
vendored
Normal file
14
src/env.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// 全局类型声明补充
|
||||||
|
// @astrojs/alpinejs 集成会在运行时把 Alpine 挂到全局(window.Alpine),
|
||||||
|
// 但 @types/alpinejs 是 CJS(export = Alpine),其顶层 declare const Alpine
|
||||||
|
// 不会自动进入模块上下文(.astro 的 <script> 是模块),导致 IDE 报 “Cannot find name 'Alpine'”。
|
||||||
|
// 这里用 namespace 导入取真实的 Alpine.Alpine 接口类型作为全局声明,
|
||||||
|
// 既消除报错、又让 Alpine.data / .store / .magic 等方法以及 data 组件内的 this 都有完整提示。
|
||||||
|
// 注意:@types/alpinejs 是 export = 形式,不能用默认导入(会解析成 namespace 而非类型)。
|
||||||
|
import type * as Alpine from "alpinejs";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
const Alpine: Alpine.Alpine;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
import Layout from "@/layouts/Layout.astro"
|
|
||||||
import Article from "@/components/pages/article.astro"
|
|
||||||
import { fetchArticleById } from "@/lib/data"
|
|
||||||
|
|
||||||
// 按需 SSR:服务端按 ?id= 取数并渲染(保留既有 /article?id= 链接,无需改动其他页面)
|
|
||||||
export const prerender = false
|
|
||||||
|
|
||||||
const API = (import.meta.env.API_SSR || import.meta.env.PUBLIC_API_BASE || "http://localhost:8090").replace(/\/$/, "")
|
|
||||||
const id = Astro.url.searchParams.get("id")
|
|
||||||
let article: import("@/lib/data").RawArticle | null = null
|
|
||||||
let error: "missing" | "failed" | null = null
|
|
||||||
if (!id) {
|
|
||||||
error = "missing"
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
article = await fetchArticleById(id, API)
|
|
||||||
} catch {
|
|
||||||
article = null
|
|
||||||
}
|
|
||||||
error = article ? null : "failed"
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
<Layout>
|
|
||||||
<Article article={article} locale="en" apiBase={API} error={error} />
|
|
||||||
</Layout>
|
|
||||||
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"extends": "astro/tsconfigs/strict",
|
"extends": "astro/tsconfigs/strict",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"ignoreDeprecations": "6.0",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user