Files
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

139 lines
4.7 KiB
TypeScript

export interface RecommendItem {
id: number;
title: string;
image: string;
link: string;
}
export interface RecommendCategory {
id: number;
title: string;
items: RecommendItem[];
}
export interface SolutionLink {
id: number;
title: string;
link: string;
tag?: 'hot' | 'new';
}
export interface SolutionColumn {
id: number;
title: string;
links: SolutionLink[];
}
export interface NavBanner {
image: string;
link: string;
title: string;
}
const MOCK_RECOMMEND_CATEGORIES: RecommendCategory[] = [
{
id: 1,
title: '热卖推荐',
items: [
{ id: 101, title: 'T恤 热销爆款', image: '/水洗T恤.png', link: 'https://inkpod.vip/portal/search' },
{ id: 102, title: '卫衣 秋冬必备', image: '/鸭舌帽.png', link: 'https://inkpod.vip/portal/search' },
{ id: 103, title: '帆布袋 创意定制', image: '/帆布袋.png', link: 'https://inkpod.vip/portal/search' },
{ id: 104, title: '手机壳 个性潮流', image: '/设计工具.png', link: 'https://inkpod.vip/portal/search' },
],
},
{
id: 2,
title: '新品上架',
items: [
{ id: 201, title: '棒球帽 运动风潮', image: '/鸭舌帽.png', link: 'https://inkpod.vip/portal/search' },
{ id: 202, title: '马克杯 定制礼物', image: '/设计工具.png', link: 'https://inkpod.vip/portal/search' },
{ id: 203, title: '帆布画 艺术家居', image: '/帆布袋.png', link: 'https://inkpod.vip/portal/search' },
{ id: 204, title: '抱枕 舒适生活', image: '/水洗T恤.png', link: 'https://inkpod.vip/portal/search' },
],
},
{
id: 3,
title: '节日专区',
items: [
{ id: 301, title: '圣诞系列 定制好礼', image: '/帆布袋.png', link: 'https://inkpod.vip/portal/search' },
{ id: 302, title: '情人节 浪漫定制', image: '/水洗T恤.png', link: 'https://inkpod.vip/portal/search' },
{ id: 303, title: '万圣节 搞怪周边', image: '/鸭舌帽.png', link: 'https://inkpod.vip/portal/search' },
{ id: 304, title: '春节 新年好物', image: '/设计工具.png', link: 'https://inkpod.vip/portal/search' },
],
},
];
const MOCK_SOLUTION_COLUMNS: SolutionColumn[] = [
{
id: 1,
title: '跨境电商',
links: [
{ id: 12, title: 'Temu 卖家方案', link: 'https://inkpod.vip/portal/search', tag: 'new' },
{ id: 13, title: 'eBay 卖家方案', link: 'https://inkpod.vip/portal/search' },
{ id: 14, title: '速卖通方案', link: 'https://inkpod.vip/portal/search' },
],
},
{
id: 2,
title: '独立站',
links: [
{ id: 21, title: 'Shopify 方案', link: 'https://inkpod.vip/portal/search', tag: 'hot' },
{ id: 22, title: 'WooCommerce 方案', link: 'https://inkpod.vip/portal/search' },
{ id: 23, title: '品牌出海方案', link: 'https://inkpod.vip/portal/search' },
],
},
{
id: 3,
title: '定制场景',
links: [
{ id: 31, title: '礼品定制', link: 'https://inkpod.vip/portal/search' },
{ id: 32, title: '宠物定制', link: 'https://inkpod.vip/portal/search', tag: 'new' },
{ id: 33, title: '二次元周边', link: 'https://inkpod.vip/portal/search' },
{ id: 34, title: '婚庆定制', link: 'https://inkpod.vip/portal/search' },
{ id: 35, title: '团体定制', link: 'https://inkpod.vip/portal/search' },
],
},
{
id: 4,
title: '服务支持',
links: [
{ id: 41, title: '在线设计工具', link: 'https://inkpod.vip/portal/search' },
{ id: 42, title: '供应链服务', link: 'https://inkpod.vip/portal/search' },
{ id: 43, title: '一件代发', link: 'https://inkpod.vip/portal/search' },
{ id: 44, title: '售后保障', link: 'https://inkpod.vip/portal/search' },
],
},
];
const MOCK_SOLUTION_BANNER: NavBanner = {
image: '/主视觉.png',
link: 'https://inkpod.vip/portal/search',
title: 'InkReach 全球 POD 供应链',
};
export function useNavData() {
const recommendCategories = ref<RecommendCategory[]>(MOCK_RECOMMEND_CATEGORIES);
const solutionColumns = ref<SolutionColumn[]>(MOCK_SOLUTION_COLUMNS);
const solutionBanner = ref<NavBanner | null>(MOCK_SOLUTION_BANNER);
const activeRecommendIdx = ref(0);
const activeRecommendCategory = computed(
() => recommendCategories.value[activeRecommendIdx.value] ?? null,
);
function setActiveRecommend(idx: number): void {
if (idx >= 0 && idx < recommendCategories.value.length) {
activeRecommendIdx.value = idx;
}
}
return {
recommendCategories,
solutionColumns,
solutionBanner,
activeRecommendIdx,
activeRecommendCategory,
setActiveRecommend,
};
}