wip(freight): migration 0017 + model/column-list groundwork for add-freight-templates

This commit is contained in:
Chengdong Zhang
2026-09-23 17:39:45 +08:00
parent a83e857bdf
commit 5b426486ac
105 changed files with 6193 additions and 1566 deletions
+54 -24
View File
@@ -31,7 +31,9 @@ const quickLinks = computed(() => content.value.quick_links);
const promos = computed(() => content.value.promos);
const heroQuickLinks = computed(() => quickLinks.value.slice(0, 6));
const sidePromos = computed(() => promos.value.slice(0, 2));
const stripPromos = computed(() => (promos.value.length > 2 ? promos.value.slice(2, 5) : promos.value.slice(0, 3)));
const stripPromos = computed(() =>
promos.value.length > 2 ? promos.value.slice(2, 5) : promos.value.slice(0, 3),
);
// Floor structure comes from the category tree and floor products from the
// catalog API; advert art is an ordered pool assigned to floors in turn.
@@ -62,17 +64,26 @@ const visibleFloors = computed(() => floors.value ?? []);
<template>
<div>
<section class="mx-auto max-w-mall px-4">
<div class="grid h-hero grid-cols-[240px_minmax(0,1fr)_220px] bg-surface">
<section class="max-w-mall mx-auto px-4">
<div class="h-hero bg-surface grid grid-cols-[240px_minmax(0,1fr)_220px]">
<ShellCategoryMenu pinned />
<div class="min-w-0">
<UiCarousel :images="banners" :height="450" />
</div>
<aside class="flex h-full flex-col border-l border-border bg-surface">
<ul class="grid list-none grid-cols-2 gap-px bg-border p-px">
<aside class="border-border bg-surface flex h-full flex-col border-l">
<ul class="bg-border grid list-none grid-cols-2 gap-px p-px">
<li v-for="q in heroQuickLinks" :key="q.id" class="bg-surface text-center">
<NuxtLink :to="q.url" class="block px-1 py-3 text-[12px] text-muted no-underline transition-colors hover:text-primary">
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" class="mx-auto mb-1.5">
<NuxtLink
:to="q.url"
class="text-muted hover:text-primary block px-1 py-3 text-[12px] no-underline transition-colors"
>
<svg
viewBox="0 0 24 24"
width="24"
height="24"
fill="currentColor"
class="mx-auto mb-1.5"
>
<path :d="q.glyph" />
</svg>
<span>{{ pick(q.label, locale) }}</span>
@@ -80,41 +91,60 @@ const visibleFloors = computed(() => floors.value ?? []);
</li>
</ul>
<div class="mt-2 flex-1 space-y-2 px-2 pb-2">
<NuxtLink
v-for="p in sidePromos"
:key="p.id"
:to="p.url"
class="block overflow-hidden"
>
<img :src="p.image" :alt="t('home.hotPromo')" loading="lazy" class="block h-[106px] w-full object-cover" />
<NuxtLink v-for="p in sidePromos" :key="p.id" :to="p.url" class="block overflow-hidden">
<img
:src="p.image"
:alt="t('home.hotPromo')"
loading="lazy"
class="block h-[106px] w-full object-cover"
/>
</NuxtLink>
</div>
</aside>
</div>
</section>
<section v-if="stripPromos.length > 0" class="mx-auto mb-5 mt-5 max-w-mall px-4">
<section v-if="stripPromos.length > 0" class="max-w-mall mx-auto mt-5 mb-5 px-4">
<div class="grid grid-cols-3 gap-3">
<NuxtLink v-for="p in stripPromos" :key="p.id" :to="p.url" class="block overflow-hidden">
<img :src="p.image" :alt="t('home.hotPromo')" loading="lazy" class="block h-40 w-full object-cover" />
<img
:src="p.image"
:alt="t('home.hotPromo')"
loading="lazy"
class="block h-40 w-full object-cover"
/>
</NuxtLink>
</div>
</section>
<div class="bg-bg py-8">
<section v-for="floor in visibleFloors" :key="floor.categoryId" class="mx-auto mb-[30px] max-w-mall px-4 last:mb-0">
<header class="flex items-end justify-between border-b-2 border-primary">
<section
v-for="floor in visibleFloors"
:key="floor.categoryId"
class="max-w-mall mx-auto mb-[30px] px-4 last:mb-0"
>
<header class="border-primary flex items-end justify-between border-b-2">
<h2 class="m-0 py-[10px] text-[18px] leading-none">{{ pick(floor.name, locale) }}</h2>
<NuxtLink
:to="`/search?category=${floor.categoryId}`"
class="pb-2 text-[12px] text-muted no-underline transition-colors hover:text-primary"
>{{ t("home.viewMore") }} ›</NuxtLink>
class="text-muted hover:text-primary pb-2 text-[12px] no-underline transition-colors"
>{{ t("home.viewMore") }} ›</NuxtLink
>
</header>
<div class="flex bg-surface">
<NuxtLink v-if="floor.advImage" :to="floor.advUrl" class="shrink-0 border-r border-border">
<img :src="floor.advImage" :alt="pick(floor.name, locale)" loading="lazy" class="block h-[614px] w-[234px] object-cover" />
<div class="bg-surface flex">
<NuxtLink
v-if="floor.advImage"
:to="floor.advUrl"
class="border-border shrink-0 border-r"
>
<img
:src="floor.advImage"
:alt="pick(floor.name, locale)"
loading="lazy"
class="block h-[614px] w-[234px] object-cover"
/>
</NuxtLink>
<div class="grid min-w-0 flex-1 grid-cols-4 gap-px bg-border p-px">
<div class="bg-border grid min-w-0 flex-1 grid-cols-4 gap-px p-px">
<UiProductCard v-for="p in floor.products" :key="p.id" :product="p" />
</div>
</div>