Files
inkreach-official-website/docs/superpowers/specs/2026-06-15-product-center-design.md
T
yeuimu 6c61a4e871 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
2026-08-26 14:23:09 +08:00

11 KiB
Raw Blame History

产品中心 (Product Center) 设计规格

概述

为 InkReach 官网新增"产品中心"二级页面,包含三个子系统:

  1. NestJS 后端服务 — Prisma + PostgreSQLRESTful APISDS 定时同步
  2. Vue 3 Admin 后台 — Element Plus,商品/品类/国家/标签/位置管理
  3. Nuxt 4 官网页面 — 产品中心二级页,带侧边栏分类、国家筛选、搜索、分页

架构

  • NestJS 监听 :3001,提供 RESTful API
  • Admin 直连 NestJS API(开发环境 Vite proxy 解决跨域)
  • Website 通过 Nitro server route 代理 NestJS API

实施顺序

后端服务 → Admin 后台 → 官网产品中心页


1. NestJS 后端服务

技术栈

技术 版本 用途
NestJS 10+ 后端框架
Prisma 6+ ORM
PostgreSQL 16+ 数据库
@nestjs/schedule - 定时同步 SDS
passport + jwt - JWT 认证
class-validator - DTO 验证

项目结构

inkreach-official-nestjs/
├── prisma/
│   ├── schema.prisma
│   └── migrations/
├── src/
│   ├── main.ts
│   ├── app.module.ts
│   ├── auth/
│   │   ├── auth.module.ts
│   │   ├── auth.controller.ts
│   │   ├── auth.service.ts
│   │   ├── jwt.strategy.ts
│   │   └── dto/
│   ├── goods/
│   │   ├── goods.module.ts
│   │   ├── goods.controller.ts
│   │   ├── goods.service.ts
│   │   └── dto/
│   ├── categories/
│   ├── countries/
│   ├── tags/
│   ├── positions/
│   ├── origin-goods/
│   └── sync/
│       ├── sync.module.ts
│       ├── sync.service.ts
│       └── sync.controller.ts
├── test/
├── .env
├── nest-cli.json
├── tsconfig.json
└── package.json

Prisma Schema

docs/dev/database-table-design.md 的 DDL 转换为 Prisma schema6 个核心模型:OriginGoods, Country, Category, Tag, Position, Good

关系映射:

  • GoodOriginGoods (多对一, RESTRICT)
  • GoodCountry (多对一, RESTRICT)
  • GoodCategory (多对一, RESTRICT)
  • GoodTag (多对一, SET NULL)
  • GoodPosition (多对一, SET NULL)
  • Category 自关联 (parent_category_id)
  • PositionCountry (多对一, CASCADE)
  • PositionCategory (多对一, CASCADE)

API 设计

认证

方法 路径 描述
POST /auth/login 管理员登录,返回 JWT
POST /auth/register 注册(仅初始化用)

商品管理 (Admin, 需认证)

方法 路径 描述
GET /goods 分页查询商品(支持 country/category/tag/position/keyword 筛选)
GET /goods/:id 商品详情
POST /goods 创建商品
PATCH /goods/:id 更新商品
DELETE /goods/:id 删除商品
PATCH /goods/batch-priority 批量更新优先级
POST /goods/batch 批量创建商品(从 origin_goods 选取)

品类管理 (Admin)

方法 路径 描述
GET /categories 获取品类树
GET /categories/:id 品类详情
POST /categories 创建品类
PATCH /categories/:id 更新品类
DELETE /categories/:id 删除品类

国家管理 (Admin)

方法 路径 描述
GET /countries 国家列表
POST /countries 创建国家
PATCH /countries/:id 更新国家
DELETE /countries/:id 删除国家

标签管理 (Admin)

方法 路径 描述
GET /tags 标签列表
POST /tags 创建标签
PATCH /tags/:id 更新标签
DELETE /tags/:id 删除标签

位置管理 (Admin)

方法 路径 描述
GET /positions 位置列表
POST /positions 创建位置
PATCH /positions/:id 更新位置
DELETE /positions/:id 删除位置

原商品管理 (Admin)

方法 路径 描述
GET /origin-goods 原商品列表(来自 SDS 同步)

同步 (Admin)

方法 路径 描述
POST /sync/categories 手动触发品类同步
POST /sync/products 手动触发产品同步
GET /sync/status 获取最近同步状态

公开 API (Website, 无需认证)

方法 路径 描述
GET /public/categories 品类树(仅含已配置商品的品类)
GET /public/countries 国家列表(仅含已配置商品的国家)
GET /public/goods 分页查询商品(支持 country/category/tag/keyword 筛选)
GET /public/goods/:id 商品详情

SDS 同步逻辑

  1. 品类同步: 调用 https://mapi.sdspod.com/category/tree/3,将返回的树形结构扁平化写入 categories
  2. 产品同步: 按 SDS 分类遍历产品,写入 origin_goods
  3. 定时策略: 每小时自动同步一次 (@Cron('0 * * * *'))
  4. 增量策略: 对比现有记录,存在则跳过,不存在则插入

商品查询逻辑 (公开 API)

排序: good_priority DESC → position.index_val ASC → created_at DESC

筛选参数:

  • countryId — 按国家筛选
  • categoryId — 按品类筛选(含子品类)
  • tagId — 按标签筛选
  • keyword — 按商品名模糊搜索
  • page / pageSize — 分页

2. Admin 后台

技术栈

技术 版本 用途
Vue 3.5+ UI 框架
Vite 6+ 构建工具
Element Plus 2.9+ UI 组件库
Vue Router 4+ 路由
Pinia 3+ 状态管理
Axios 1.7+ HTTP 客户端
TypeScript 5+ 类型安全

项目结构

inkreach-official-admin/
├── src/
│   ├── main.ts
│   ├── App.vue
│   ├── router/index.ts
│   ├── stores/
│   │   ├── auth.ts
│   │   └── app.ts
│   ├── api/
│   │   ├── request.ts
│   │   ├── auth.ts
│   │   ├── goods.ts
│   │   ├── categories.ts
│   │   ├── countries.ts
│   │   ├── tags.ts
│   │   ├── positions.ts
│   │   ├── origin-goods.ts
│   │   └── sync.ts
│   ├── layouts/
│   │   └── DefaultLayout.vue
│   ├── views/
│   │   ├── login/LoginView.vue
│   │   ├── goods/GoodsView.vue
│   │   ├── categories/CategoriesView.vue
│   │   ├── countries/CountriesView.vue
│   │   ├── tags/TagsView.vue
│   │   ├── positions/PositionsView.vue
│   │   └── sync/SyncView.vue
│   ├── components/
│   └── types/index.ts
├── .env
├── vite.config.ts
├── tsconfig.json
└── package.json

核心页面功能

商品管理 (GoodsView):

  • 表格展示:商品名、国家、品类、标签、位置、优先级
  • 筛选:按国家/品类/标签筛选
  • 操作:新增、编辑、删除、调整优先级
  • 批量添加:从 origin_goods 选择商品,批量配置国家/品类/标签/优先级

品类管理 (CategoriesView):

  • 树形表格展示层级关系
  • 新增/编辑/删除品类

同步管理 (SyncView):

  • 显示最近同步时间、同步状态
  • 手动触发品类同步/产品同步按钮

3. 官网产品中心页

页面结构

左右两栏布局:左侧固定宽度侧边栏(品类导航),右侧主内容区(国家筛选 + 筛选栏 + 商品网格 + 分页)。

组件拆分

app/pages/product-center.vue          # 页面入口
app/components/product/
├── ProductSidebar.vue                # 侧边栏品类导航
├── ProductCountryFilter.vue          # 国家标签栏
├── ProductFilterBar.vue              # 筛选下拉 + 已选标签 + 搜索
├── ProductGrid.vue                   # 商品卡片网格
├── ProductCard.vue                   # 单个商品卡片
├── ProductCardSkeleton.vue           # 骨架屏卡片
└── ProductPagination.vue             # 分页控件
app/composables/
└── useProductCenter.ts               # 产品中心数据逻辑

商品卡片设计

  • 商品图片 (1:1 方形)
  • 商品名 (单行截断)
  • 标签行 (pill 样式,颜色体系:绿色=包邮,橙色=工艺,灰色=其他)
  • 价格 (粗体,"¥XX.XX起")

侧边栏品类导航

  • 顶级品类带图标 + 折叠箭头
  • 展开子品类列表,左侧橙色竖条标识当前选中
  • 选中子品类背景 bg-inkreach-homepage-3 + 橙色文字

国家标签栏

  • Pill 形状按钮,每个带国旗图标
  • "全部" 为默认选中,橙色边框 + 橙色文字
  • 未选中为灰色边框

搜索

  • 分体式搜索框:左侧输入框 + 右侧橙色"搜索"按钮
  • 支持按商品名搜索

分页

  • 左侧:"总计 N 个产品"
  • 中间:页码按钮(方形)
  • 右侧:每页条数下拉 + 跳转输入框

骨架屏

数据加载时显示骨架屏:

  • 卡片区域显示 ProductCardSkeleton (4x3 网格)
  • 分页隐藏
  • 侧边栏和筛选区正常显示

Nitro API 代理

server/api/backend/categories.get.ts  -> GET  :3001/public/categories
server/api/backend/countries.get.ts   -> GET  :3001/public/countries
server/api/backend/goods.get.ts       -> GET  :3001/public/goods
server/api/backend/goods/[id].get.ts  -> GET  :3001/public/goods/:id

数据流

  1. 页面加载 → /api/backend/categories → 渲染侧边栏
  2. 页面加载 → /api/backend/countries → 渲染国家标签栏
  3. 筛选/分页变化 → /api/backend/goods?countryId=&categoryId=&keyword=&page=&pageSize= → 渲染商品网格

关联改动

  • 首页 PodProducts.vue 的"更多产品"按钮改为 <NuxtLink to="/product-center">
  • AppHeader.vue 的"产品中心"链接改为 <NuxtLink to="/product-center">

跨项目配置

环境变量

inkreach-official-nestjs/.env:

  • DATABASE_URL=postgresql://postgres:yoyoki219765.@localhost:5432/inkreach-official
  • JWT_SECRET=(generate-secure-secret)
  • SDS_API_BASE=https://mapi.sdspod.com
  • PORT=3001

inkreach-official-admin/.env:

inkreach-official-website:

端口分配

项目 端口
NestJS Backend 3001
Admin (Vite dev) 5173
Website (Nuxt dev) 3000