You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
4.2 KiB
154 lines
4.2 KiB
/**
|
|
* 卡片类型注册表
|
|
*
|
|
* 新增卡片类型只需在此文件中:
|
|
* 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}" 的配置`)
|
|
}
|
|
}
|
|
}
|
|
|