feat(deploy): production deployment setup and fixes

- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma
  binaryTargets for openssl 3.0
- nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal
  cron, http->https redirect
- prisma: add origin_goods.delisted migration, sync missing schema
  (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz
- api: CORS wildcard reflection, helmet CORP cross-origin, price
  backfill in persistProductDetail, categoryIcon ancestor fallback,
  mediaByColor per-color gallery in public goods detail
- admin: /admin base path (vite + router)
- import-data.mjs: udt_name casting, serial sequence advance fix
This commit is contained in:
yeuimu
2026-08-26 14:23:09 +08:00
parent be0b90e68f
commit 6c61a4e871
982 changed files with 74156 additions and 179393 deletions
+117 -117
View File
@@ -1,117 +1,117 @@
# 项目目录结构
## 根目录
```
inkreach-official-website/
├── app/ # Nuxt 应用目录
│ ├── app.vue # 根组件,仅包含 <NuxtPage />
│ ├── pages/ # 页面路由(启用文件式路由)
│ │ ├── index.vue # 首页(组合所有首页区块组件)
│ │ └── product-center.vue # 产品中心页(侧边栏 + 国家/筛选 + 网格 + 分页)
│ ├── assets/ # 静态资源
│ │ └── css/
│ │ └── tailwind.css # Tailwind 主题配置(颜色、动画)
│ ├── composables/ # Vue Composables
│ │ ├── useNavData.ts # 导航数据(选品推荐、解决方案 mock/API)
│ │ ├── usePodProducts.ts # 首页 POD 产品数据(SDS API
│ │ └── useProductCenter.ts # 产品中心数据(NestJS 后端,含类别/国家/商品/分页/筛选)
│ └── components/ # Vue 组件
│ ├── AppHeader.vue # 导航栏(含 mega menu 下拉 + 移动端侧边菜单,含 NuxtLink 产品中心跳转)
│ ├── nav/
│ │ ├── NavMegaMenu.vue # 选品推荐下拉面板(左侧分类+右侧卡片)
│ │ └── NavColumnMenu.vue # 解决方案下拉面板(多列链接+广告)
│ ├── product/ # 产品中心专用组件
│ │ ├── ProductSidebar.vue # 树形品类侧边栏
│ │ ├── ProductCountryFilter.vue # 国家 pill 筛选
│ │ ├── ProductFilterBar.vue # 搜索输入 + 搜索按钮
│ │ ├── ProductCard.vue # 商品卡片
│ │ ├── ProductCardSkeleton.vue # 商品卡片骨架
│ │ ├── ProductGrid.vue # 商品网格
│ │ └── ProductPagination.vue # 分页器
│ ├── HeroBanner.vue # 主视觉横幅
│ ├── TrustSection.vue # 信任背书/数据统计
│ ├── StepProcess.vue # 4步流程
│ ├── PodProducts.vue # 全球POD货盘(含 NuxtLink 到 /product-center
│ ├── FeatureCards.vue # 功能特性卡片
│ ├── WhyInkReach.vue # 为什么选我们
│ ├── CompanyProfile.vue # 公司简介
│ ├── CustomerCases.vue # 客户案例(桌面marquee + 移动滑动)
│ ├── CtaBanner.vue # 行动号召横幅
│ └── AppFooter.vue # 页脚
├── server/ # Nitro 后端代理
│ ├── api/
│ │ ├── pod/ # 原有 SDS POD API 代理
│ │ └── backend/ # 新增:NestJS 后端 API 代理
│ │ ├── categories.get.ts # → GET :3001/public/categories
│ │ ├── countries.get.ts # → GET :3001/public/countries
│ │ ├── goods.get.ts # → GET :3001/public/goods
│ │ └── goods/[id].get.ts # → GET :3001/public/goods/:id
│ └── utils/
│ └── pod-api.ts
├── public/ # 公共静态资源
├── plans/ # 开发计划文档
│ └── feature/
│ ├── nav-mega-menu-feature.md
│ ├── responsive-layout-feature.md
│ └── product-center-feature.md
├── docs/ # 文档
│ ├── references/
│ │ └── structs.md # 本文件
│ └── superpowers/specs/
├── nuxt.config.ts # Nuxt 配置(含 runtimeConfig.public.backendUrl
├── .env # NUXT_PUBLIC_BACKEND_URL=http://localhost:3001
├── AGENTS.md # AI Agent 开发规范
└── README.md # 项目说明
```
## 组件说明
| 组件 | 功能 | 响应式断点 |
|------|------|-----------|
| AppHeader | 导航栏,含 logo、导航链接(含 NuxtLink 到 /product-center)、选品推荐/解决方案 mega menu、登录按钮;移动端汉堡菜单+侧边滑出+手风琴折叠 | lg 断点切换 |
| NavMegaMenu | 选品推荐下拉面板,左侧分类列表+右侧卡片网格,hover 切换 | 仅桌面端 |
| NavColumnMenu | 解决方案下拉面板,多列链接分组+广告 banner,支持 HOT/NEW 标签 | 仅桌面端 |
| ProductSidebar | 产品中心树形品类侧边栏,支持折叠/选中态、橙色竖条高亮 | lg 显示,移动端折叠为顶部 accordion |
| ProductCountryFilter | 产品中心国家筛选 pill 行 | 横向滚动 |
| ProductFilterBar | 产品中心分体式搜索框(输入 + 橙色按钮) | 单行 |
| ProductCard | 商品卡片(1:1 图 + 名称 + 标签 pill + 橙色价格) | 网格项 |
| ProductCardSkeleton | 商品卡片骨架(animate-pulse | 网格项 |
| ProductGrid | 商品网格容器(loading → 12 骨架;empty → 暂无商品) | 2/3/4 列响应 |
| ProductPagination | 分页器(总计 + 页码按钮 + 12/24/48 + 跳转) | 单行 |
| HeroBanner | 主视觉,标题+副标题+产品图+CTA 按钮 | lg 断点调整字号/布局 |
| TrustSection | 4 个数据统计卡片 | 2 列(移动) / 4 列(桌面) |
| StepProcess | 4 步交互流程,点击/hover 切换步骤图片 | 横向滚动(移动) / 纵向布局(桌面) |
| PodProducts | 国家 tab 选择 + 产品网格 + NuxtLink "更多产品" 跳转到 /product-center | 2 列(移动) / 3 列(平板) / 5 列(桌面) |
| FeatureCards | 4 个功能特性卡片,hover 切换图片 | 横向滚动(移动) / 纵向布局(桌面) |
| WhyInkReach | 4 个理由卡片 | 2 列(移动) / 4 列(桌面) |
| CompanyProfile | 公司简介,3 列文字 + 4 个能力卡片 | 自适应网格 |
| CustomerCases | 桌面端 marquee 滚动,移动端横向滑动 | 隐藏 marquee(移动) / 横向滑动(移动) |
| CtaBanner | CTA 横幅 | clamp 字号自适应 |
| AppFooter | 页脚 4 列布局 | 单列(移动) / 2x2(平板) / 4 列(桌面) |
## 路由
| 路径 | 文件 | 说明 |
|------|------|------|
| `/` | `app/pages/index.vue` | 首页 |
| `/product-center` | `app/pages/product-center.vue` | 产品中心页 |
## 后端代理
所有 `/api/backend/*` 请求通过 Nitro 在服务端转发到 NestJS 后端(默认 `http://localhost:3001`,由 `NUXT_PUBLIC_BACKEND_URL` 控制)。
| 前端路由 | 后端路由 | 说明 |
|---------|---------|------|
| GET `/api/backend/categories` | GET `:3001/public/categories` | 品类树(缓存 60s |
| GET `/api/backend/countries` | GET `:3001/public/countries` | 国家列表(缓存 60s |
| GET `/api/backend/goods` | GET `:3001/public/goods` | 分页商品(按 query 缓存 60s |
| GET `/api/backend/goods/:id` | GET `:3001/public/goods/:id` | 商品详情(缓存 60s |
## 断点体系
| 断点 | 范围 | Tailwind 前缀 |
|------|------|--------------|
| 移动端 | < 768px | 默认(无前缀) |
| 平板 | 768px - 1023px | `md:` |
| 桌面 | >= 1024px | `lg:` |
# 项目目录结构
## 根目录
```
inkreach-official-website/
├── app/ # Nuxt 应用目录
│ ├── app.vue # 根组件,仅包含 <NuxtPage />
│ ├── pages/ # 页面路由(启用文件式路由)
│ │ ├── index.vue # 首页(组合所有首页区块组件)
│ │ └── product-center.vue # 产品中心页(侧边栏 + 国家/筛选 + 网格 + 分页)
│ ├── assets/ # 静态资源
│ │ └── css/
│ │ └── tailwind.css # Tailwind 主题配置(颜色、动画)
│ ├── composables/ # Vue Composables
│ │ ├── useNavData.ts # 导航数据(选品推荐、解决方案 mock/API)
│ │ ├── usePodProducts.ts # 首页 POD 产品数据(SDS API
│ │ └── useProductCenter.ts # 产品中心数据(NestJS 后端,含类别/国家/商品/分页/筛选)
│ └── components/ # Vue 组件
│ ├── AppHeader.vue # 导航栏(含 mega menu 下拉 + 移动端侧边菜单,含 NuxtLink 产品中心跳转)
│ ├── nav/
│ │ ├── NavMegaMenu.vue # 选品推荐下拉面板(左侧分类+右侧卡片)
│ │ └── NavColumnMenu.vue # 解决方案下拉面板(多列链接+广告)
│ ├── product/ # 产品中心专用组件
│ │ ├── ProductSidebar.vue # 树形品类侧边栏
│ │ ├── ProductCountryFilter.vue # 国家 pill 筛选
│ │ ├── ProductFilterBar.vue # 搜索输入 + 搜索按钮
│ │ ├── ProductCard.vue # 商品卡片
│ │ ├── ProductCardSkeleton.vue # 商品卡片骨架
│ │ ├── ProductGrid.vue # 商品网格
│ │ └── ProductPagination.vue # 分页器
│ ├── HeroBanner.vue # 主视觉横幅
│ ├── TrustSection.vue # 信任背书/数据统计
│ ├── StepProcess.vue # 4步流程
│ ├── PodProducts.vue # 全球POD货盘(含 NuxtLink 到 /product-center
│ ├── FeatureCards.vue # 功能特性卡片
│ ├── WhyInkReach.vue # 为什么选我们
│ ├── CompanyProfile.vue # 公司简介
│ ├── CustomerCases.vue # 客户案例(桌面marquee + 移动滑动)
│ ├── CtaBanner.vue # 行动号召横幅
│ └── AppFooter.vue # 页脚
├── server/ # Nitro 后端代理
│ ├── api/
│ │ ├── pod/ # 原有 SDS POD API 代理
│ │ └── backend/ # 新增:NestJS 后端 API 代理
│ │ ├── categories.get.ts # → GET :3001/public/categories
│ │ ├── countries.get.ts # → GET :3001/public/countries
│ │ ├── goods.get.ts # → GET :3001/public/goods
│ │ └── goods/[id].get.ts # → GET :3001/public/goods/:id
│ └── utils/
│ └── pod-api.ts
├── public/ # 公共静态资源
├── plans/ # 开发计划文档
│ └── feature/
│ ├── nav-mega-menu-feature.md
│ ├── responsive-layout-feature.md
│ └── product-center-feature.md
├── docs/ # 文档
│ ├── references/
│ │ └── structs.md # 本文件
│ └── superpowers/specs/
├── nuxt.config.ts # Nuxt 配置(含 runtimeConfig.public.backendUrl
├── .env # NUXT_PUBLIC_BACKEND_URL=http://localhost:3001
├── AGENTS.md # AI Agent 开发规范
└── README.md # 项目说明
```
## 组件说明
| 组件 | 功能 | 响应式断点 |
|------|------|-----------|
| AppHeader | 导航栏,含 logo、导航链接(含 NuxtLink 到 /product-center)、选品推荐/解决方案 mega menu、登录按钮;移动端汉堡菜单+侧边滑出+手风琴折叠 | lg 断点切换 |
| NavMegaMenu | 选品推荐下拉面板,左侧分类列表+右侧卡片网格,hover 切换 | 仅桌面端 |
| NavColumnMenu | 解决方案下拉面板,多列链接分组+广告 banner,支持 HOT/NEW 标签 | 仅桌面端 |
| ProductSidebar | 产品中心树形品类侧边栏,支持折叠/选中态、橙色竖条高亮 | lg 显示,移动端折叠为顶部 accordion |
| ProductCountryFilter | 产品中心国家筛选 pill 行 | 横向滚动 |
| ProductFilterBar | 产品中心分体式搜索框(输入 + 橙色按钮) | 单行 |
| ProductCard | 商品卡片(1:1 图 + 名称 + 标签 pill + 橙色价格) | 网格项 |
| ProductCardSkeleton | 商品卡片骨架(animate-pulse | 网格项 |
| ProductGrid | 商品网格容器(loading → 12 骨架;empty → 暂无商品) | 2/3/4 列响应 |
| ProductPagination | 分页器(总计 + 页码按钮 + 12/24/48 + 跳转) | 单行 |
| HeroBanner | 主视觉,标题+副标题+产品图+CTA 按钮 | lg 断点调整字号/布局 |
| TrustSection | 4 个数据统计卡片 | 2 列(移动) / 4 列(桌面) |
| StepProcess | 4 步交互流程,点击/hover 切换步骤图片 | 横向滚动(移动) / 纵向布局(桌面) |
| PodProducts | 国家 tab 选择 + 产品网格 + NuxtLink "更多产品" 跳转到 /product-center | 2 列(移动) / 3 列(平板) / 5 列(桌面) |
| FeatureCards | 4 个功能特性卡片,hover 切换图片 | 横向滚动(移动) / 纵向布局(桌面) |
| WhyInkReach | 4 个理由卡片 | 2 列(移动) / 4 列(桌面) |
| CompanyProfile | 公司简介,3 列文字 + 4 个能力卡片 | 自适应网格 |
| CustomerCases | 桌面端 marquee 滚动,移动端横向滑动 | 隐藏 marquee(移动) / 横向滑动(移动) |
| CtaBanner | CTA 横幅 | clamp 字号自适应 |
| AppFooter | 页脚 4 列布局 | 单列(移动) / 2x2(平板) / 4 列(桌面) |
## 路由
| 路径 | 文件 | 说明 |
|------|------|------|
| `/` | `app/pages/index.vue` | 首页 |
| `/product-center` | `app/pages/product-center.vue` | 产品中心页 |
## 后端代理
所有 `/api/backend/*` 请求通过 Nitro 在服务端转发到 NestJS 后端(默认 `http://localhost:3001`,由 `NUXT_PUBLIC_BACKEND_URL` 控制)。
| 前端路由 | 后端路由 | 说明 |
|---------|---------|------|
| GET `/api/backend/categories` | GET `:3001/public/categories` | 品类树(缓存 60s |
| GET `/api/backend/countries` | GET `:3001/public/countries` | 国家列表(缓存 60s |
| GET `/api/backend/goods` | GET `:3001/public/goods` | 分页商品(按 query 缓存 60s |
| GET `/api/backend/goods/:id` | GET `:3001/public/goods/:id` | 商品详情(缓存 60s |
## 断点体系
| 断点 | 范围 | Tailwind 前缀 |
|------|------|--------------|
| 移动端 | < 768px | 默认(无前缀) |
| 平板 | 768px - 1023px | `md:` |
| 桌面 | >= 1024px | `lg:` |
@@ -1,133 +1,133 @@
# Nav Mega Menu Design Spec
## Overview
仿照 HiCustom 首页导航栏的"选品推荐"和"解决方案"两个导航项的下拉菜单设计,为 InkReach 官网添加类似功能。数据当前使用 mock 模拟,后续通过后台 API 获取。
## Data Structures
```typescript
interface RecommendCategory {
id: number;
title: string;
active?: boolean;
items: RecommendItem[];
}
interface RecommendItem {
id: number;
title: string;
image: string;
link: string;
}
interface SolutionColumn {
id: number;
title: string;
links: SolutionLink[];
}
interface SolutionLink {
id: number;
title: string;
link: string;
tag?: 'hot' | 'new';
}
interface NavBanner {
image: string;
link: string;
title: string;
}
```
## Mock Data
### 选品推荐
| 分类 | 内容项 |
|------|--------|
| 热卖推荐 | T恤、卫衣、手机壳、马克杯、帆布画、抱枕 |
| 新品上架 | 棒球帽、双肩包、鼠标垫、宠物围巾、积木拼图、表带 |
| 节日专区 | 圣诞系列、万圣节系列、情人节系列、春节系列 |
每个内容项包含 banner 占位图、标题、链接。
### 解决方案
| 列 | 链接项 |
|----|--------|
| 跨境电商 | Amazon 卖家方案、Temu 卖家方案、eBay 卖家方案、速卖通方案 |
| 独立站 | Shopify 方案、WooCommerce 方案、品牌出海方案 |
| 定制场景 | 礼品定制、宠物定制、二次元周边、婚庆定制、团体定制 |
| 服务支持 | 设计工具、供应链服务、一件代发、售后保障 |
右侧附带广告 banner。
## Component Architecture
```
app/components/
AppHeader.vue
nav/
NavMegaMenu.vue
NavColumnMenu.vue
app/composables/
useNavData.ts
```
### AppHeader.vue (改造)
在现有导航中加入"选品推荐"和"解决方案"两个导航项,hover 时展示对应下拉面板。移动端在抽屉内用手风琴折叠样式展示。
### NavMegaMenu.vue
选品推荐下拉面板。桌面端:左侧分类列表 + 右侧卡片网格(2 列,每卡片含图片和标题)。hover 左侧分类时切换右侧内容。
### NavColumnMenu.vue
解决方案下拉面板。桌面端:多列链接分组 + 可选广告 banner。每列有标题和链接列表,链接可带 HOT/NEW 标签。
### useNavData.ts
导航数据管理 composable。当前返回 mock 数据,后续替换为 API 调用。暴露:
- `recommendCategories: Ref<RecommendCategory[]>`
- `solutionColumns: Ref<SolutionColumn[]>`
- `solutionBanner: Ref<NavBanner | null>`
- `activeRecommendIndex: Ref<number>`
- `setActiveRecommend(index: number): void`
## Interaction Behavior
### Desktop (>= 1024px)
- Hover 导航项展开下拉面板,鼠标离开关闭
- 选品推荐:hover 左侧分类项切换右侧内容区
- 解决方案:纯展示,点击链接跳转
- 下拉面板出现在导航栏下方,有过渡动画
### Mobile (< 1024px)
- 手风琴折叠样式,点击展开/收起
- 选品推荐:展开后显示分类标签切换
- 解决方案:展开后直接显示链接列表
## Visual Design
- 下拉面板:白色背景,圆角 0.5rem,阴影 `0 4px 25px rgba(179, 185, 191, 0.3)`
- 选品推荐面板宽度约 800px
- 解决方案面板宽度自适应列数(约 700px)
- 卡片 hover 时图片轻微放大(scale 1.05
- 链接 hover 时变为主题色(#FF6800
- HOT 标签:红色背景
- NEW 标签:绿色背景
- 面板展开/收起使用 opacity + translateY 过渡动画
## Implementation Tasks
- [ ] 创建 `useNavData.ts` composable(含 mock 数据和类型定义)
- [ ] 创建 `NavMegaMenu.vue` 选品推荐下拉组件
- [ ] 创建 `NavColumnMenu.vue` 解决方案下拉组件
- [ ] 改造 `AppHeader.vue` 集成新导航项
- [ ] 更新 `docs/references/structs.md`
# Nav Mega Menu Design Spec
## Overview
仿照 HiCustom 首页导航栏的"选品推荐"和"解决方案"两个导航项的下拉菜单设计,为 InkReach 官网添加类似功能。数据当前使用 mock 模拟,后续通过后台 API 获取。
## Data Structures
```typescript
interface RecommendCategory {
id: number;
title: string;
active?: boolean;
items: RecommendItem[];
}
interface RecommendItem {
id: number;
title: string;
image: string;
link: string;
}
interface SolutionColumn {
id: number;
title: string;
links: SolutionLink[];
}
interface SolutionLink {
id: number;
title: string;
link: string;
tag?: 'hot' | 'new';
}
interface NavBanner {
image: string;
link: string;
title: string;
}
```
## Mock Data
### 选品推荐
| 分类 | 内容项 |
|------|--------|
| 热卖推荐 | T恤、卫衣、手机壳、马克杯、帆布画、抱枕 |
| 新品上架 | 棒球帽、双肩包、鼠标垫、宠物围巾、积木拼图、表带 |
| 节日专区 | 圣诞系列、万圣节系列、情人节系列、春节系列 |
每个内容项包含 banner 占位图、标题、链接。
### 解决方案
| 列 | 链接项 |
|----|--------|
| 跨境电商 | Amazon 卖家方案、Temu 卖家方案、eBay 卖家方案、速卖通方案 |
| 独立站 | Shopify 方案、WooCommerce 方案、品牌出海方案 |
| 定制场景 | 礼品定制、宠物定制、二次元周边、婚庆定制、团体定制 |
| 服务支持 | 设计工具、供应链服务、一件代发、售后保障 |
右侧附带广告 banner。
## Component Architecture
```
app/components/
AppHeader.vue
nav/
NavMegaMenu.vue
NavColumnMenu.vue
app/composables/
useNavData.ts
```
### AppHeader.vue (改造)
在现有导航中加入"选品推荐"和"解决方案"两个导航项,hover 时展示对应下拉面板。移动端在抽屉内用手风琴折叠样式展示。
### NavMegaMenu.vue
选品推荐下拉面板。桌面端:左侧分类列表 + 右侧卡片网格(2 列,每卡片含图片和标题)。hover 左侧分类时切换右侧内容。
### NavColumnMenu.vue
解决方案下拉面板。桌面端:多列链接分组 + 可选广告 banner。每列有标题和链接列表,链接可带 HOT/NEW 标签。
### useNavData.ts
导航数据管理 composable。当前返回 mock 数据,后续替换为 API 调用。暴露:
- `recommendCategories: Ref<RecommendCategory[]>`
- `solutionColumns: Ref<SolutionColumn[]>`
- `solutionBanner: Ref<NavBanner | null>`
- `activeRecommendIndex: Ref<number>`
- `setActiveRecommend(index: number): void`
## Interaction Behavior
### Desktop (>= 1024px)
- Hover 导航项展开下拉面板,鼠标离开关闭
- 选品推荐:hover 左侧分类项切换右侧内容区
- 解决方案:纯展示,点击链接跳转
- 下拉面板出现在导航栏下方,有过渡动画
### Mobile (< 1024px)
- 手风琴折叠样式,点击展开/收起
- 选品推荐:展开后显示分类标签切换
- 解决方案:展开后直接显示链接列表
## Visual Design
- 下拉面板:白色背景,圆角 0.5rem,阴影 `0 4px 25px rgba(179, 185, 191, 0.3)`
- 选品推荐面板宽度约 800px
- 解决方案面板宽度自适应列数(约 700px)
- 卡片 hover 时图片轻微放大(scale 1.05
- 链接 hover 时变为主题色(#FF6800
- HOT 标签:红色背景
- NEW 标签:绿色背景
- 面板展开/收起使用 opacity + translateY 过渡动画
## Implementation Tasks
- [ ] 创建 `useNavData.ts` composable(含 mock 数据和类型定义)
- [ ] 创建 `NavMegaMenu.vue` 选品推荐下拉组件
- [ ] 创建 `NavColumnMenu.vue` 解决方案下拉组件
- [ ] 改造 `AppHeader.vue` 集成新导航项
- [ ] 更新 `docs/references/structs.md`