12 changed files with 3668 additions and 2459 deletions
@ -0,0 +1,154 @@ |
|||
/** |
|||
* 卡片类型注册表 |
|||
* |
|||
* 新增卡片类型只需在此文件中: |
|||
* 1. 在 CardTypes 数组中添加类型值 |
|||
* 2. 在 cardTypeRegistry 中添加对应配置 |
|||
* 3. 创建对应的瀑布流渲染组件 |
|||
* |
|||
* 无需修改 index.vue / CardFormModal / CardDetailModal。 |
|||
*/ |
|||
import type { Component } from 'vue' |
|||
import WaterfallCard from '~/components/index/WaterfallCard.vue' |
|||
import WaterfallTextCard from '~/components/index/WaterfallTextCard.vue' |
|||
import WaterfallImageCard from '~/components/index/WaterfallImageCard.vue' |
|||
import WaterfallPortfolioCard from '~/components/index/WaterfallPortfolioCard.vue' |
|||
import WaterfallProjectCard from '~/components/index/WaterfallProjectCard.vue' |
|||
|
|||
// ============ CardType 常量(与 drizzle schema 保持同步) ============
|
|||
export const CardTypes = [ |
|||
'text', |
|||
'image', |
|||
'image-text', |
|||
'portfolio', |
|||
'project', |
|||
] as const |
|||
export type CardType = (typeof CardTypes)[number] |
|||
|
|||
// ============ 前端卡片数据接口 ============
|
|||
export interface CardItemLike { |
|||
id?: number |
|||
type: CardType |
|||
image?: string |
|||
images?: string[] |
|||
title: string |
|||
description?: string |
|||
tags?: string[] |
|||
aspectRatio: number |
|||
categoryId?: string | null |
|||
createdAt?: string |
|||
} |
|||
|
|||
// ============ 类型配置 ============
|
|||
export interface CardTypeFormFields { |
|||
/** 是否需要单张图片 */ |
|||
image?: boolean |
|||
/** 是否需要多张图片 */ |
|||
multiImage?: boolean |
|||
/** 是否需要描述字段 */ |
|||
description?: boolean |
|||
/** 是否需要标签选择 */ |
|||
tags?: boolean |
|||
} |
|||
|
|||
export interface CardTypeConfig { |
|||
/** 瀑布流渲染组件 */ |
|||
component: Component |
|||
/** 中文标签 */ |
|||
label: string |
|||
/** 图标名 (lucide:xxx) */ |
|||
icon: string |
|||
/** 表单字段需求 */ |
|||
formFields: CardTypeFormFields |
|||
/** 从 CardItemLike 提取该组件需要的 props */ |
|||
mapProps: (item: CardItemLike) => Record<string, unknown> |
|||
} |
|||
|
|||
// ============ 注册表 ============
|
|||
export const cardTypeRegistry: Record<CardType, CardTypeConfig> = { |
|||
text: { |
|||
component: WaterfallTextCard, |
|||
label: '纯文本', |
|||
icon: 'lucide:text', |
|||
formFields: { description: true }, |
|||
mapProps: (item) => ({ |
|||
title: item.title, |
|||
description: item.description ?? '', |
|||
aspectRatio: item.aspectRatio, |
|||
}), |
|||
}, |
|||
image: { |
|||
component: WaterfallImageCard, |
|||
label: '图片', |
|||
icon: 'lucide:image', |
|||
formFields: { image: true }, |
|||
mapProps: (item) => ({ |
|||
image: item.image ?? '', |
|||
title: item.title, |
|||
aspectRatio: item.aspectRatio, |
|||
}), |
|||
}, |
|||
'image-text': { |
|||
component: WaterfallCard, |
|||
label: '图文', |
|||
icon: 'lucide:image-plus', |
|||
formFields: { image: true, description: true }, |
|||
mapProps: (item) => ({ |
|||
image: item.image ?? '', |
|||
title: item.title, |
|||
description: item.description ?? '', |
|||
aspectRatio: item.aspectRatio, |
|||
}), |
|||
}, |
|||
portfolio: { |
|||
component: WaterfallPortfolioCard, |
|||
label: '图集', |
|||
icon: 'lucide:layout-grid', |
|||
formFields: { multiImage: true, description: true }, |
|||
mapProps: (item) => ({ |
|||
images: item.images ?? [], |
|||
title: item.title, |
|||
description: item.description ?? '', |
|||
aspectRatio: item.aspectRatio, |
|||
}), |
|||
}, |
|||
project: { |
|||
component: WaterfallProjectCard, |
|||
label: '项目', |
|||
icon: 'lucide:folder-kanban', |
|||
formFields: { image: true, description: true, tags: true }, |
|||
mapProps: (item) => ({ |
|||
image: item.image ?? '', |
|||
title: item.title, |
|||
description: item.description ?? '', |
|||
tags: item.tags ?? [], |
|||
aspectRatio: item.aspectRatio, |
|||
}), |
|||
}, |
|||
} |
|||
|
|||
// ============ 派生数据(供表单等使用) ============
|
|||
|
|||
/** 类型选项列表(用于表单类型选择器) */ |
|||
export const CARD_TYPE_OPTIONS = CardTypes.map((t) => ({ |
|||
value: t, |
|||
label: cardTypeRegistry[t].label, |
|||
icon: cardTypeRegistry[t].icon, |
|||
})) |
|||
|
|||
/** 获取类型中文标签 */ |
|||
export function getTypeLabel(type: CardType | string): string { |
|||
return cardTypeRegistry[type as CardType]?.label ?? type |
|||
} |
|||
|
|||
/** |
|||
* 运行时校验:确保注册表覆盖了所有 CardType |
|||
* 如果注册表缺少某个类型,会在控制台警告 |
|||
*/ |
|||
if (import.meta.dev) { |
|||
for (const t of CardTypes) { |
|||
if (!cardTypeRegistry[t]) { |
|||
console.warn(`[cardTypes] 注册表缺少类型 "${t}" 的配置`) |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
Binary file not shown.
Loading…
Reference in new issue