first1
This commit is contained in:
94
src/utils/entryIcon.ts
Normal file
94
src/utils/entryIcon.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import type { EntryTone, PortalEntryCard, PortalEntryGroup, PortalEntryVo } from '@/types/business/home'
|
||||
|
||||
/**
|
||||
* 门户入口的视图映射:后端 icon 字段 → 页面可直接渲染的图标 + 底色
|
||||
*
|
||||
* <p>后端 icon 是「图标名 / url」自由文本,可能为空、可能是图片地址、
|
||||
* 也可能是一个标识符(如 folder)。这里按优先级兜底,保证任何取值都能渲染出可视化图标。</p>
|
||||
*/
|
||||
|
||||
/** 图标底色(设计稿为五色循环),按序号轮转分配 */
|
||||
const TONE_CYCLE: EntryTone[] = ['purple', 'green', 'blue', 'amber', 'red']
|
||||
|
||||
/** 显示名 → emoji 兜底表(后端 icon 为空或非 emoji 时使用) */
|
||||
const NAME_ICON_MAP: Record<string, string> = {
|
||||
项目中心: '🗂️',
|
||||
需求中心: '🧾',
|
||||
需求池: '🧾',
|
||||
工单需求池: '📋',
|
||||
快捷提报: '➕',
|
||||
在线客服: '🎧',
|
||||
客服工作台: '💬',
|
||||
合同管理: '📑',
|
||||
合同台账: '📄',
|
||||
合同列表: '📁',
|
||||
合同档案: '📁',
|
||||
财务管理: '💰',
|
||||
财务台账: '💰',
|
||||
财务档案: '💰',
|
||||
案例库管理: '📁',
|
||||
案例库: '📁',
|
||||
个人中心: '👤',
|
||||
消息中心: '💬',
|
||||
账号安全: '🔒',
|
||||
意见反馈: '✉️',
|
||||
交易列表: '📊',
|
||||
交易明细: '📊',
|
||||
部署管理: '🚀',
|
||||
设备工作台: '🖥️',
|
||||
设备管理: '🖥️',
|
||||
资质列表: '📋',
|
||||
帮助中心: '❓',
|
||||
关于我们: 'ℹ️',
|
||||
}
|
||||
|
||||
/** 兜底图标 */
|
||||
const DEFAULT_ICON = '📦'
|
||||
|
||||
/** 是否图片地址 */
|
||||
function isImageUrl(value: string): boolean {
|
||||
return /^(https?:)?\/\//i.test(value) || value.startsWith('/')
|
||||
}
|
||||
|
||||
/** 是否可直接当作 emoji / 字符图标使用(非纯字母数字标识符) */
|
||||
function isGlyph(value: string): boolean {
|
||||
return !/^[a-zA-Z0-9_-]+$/.test(value)
|
||||
}
|
||||
|
||||
/** 解析单项图标与底色 */
|
||||
function resolveIcon(icon: string | null, name: string): { icon: string; isImage: boolean } {
|
||||
const raw = (icon ?? '').trim()
|
||||
if (raw) {
|
||||
if (isImageUrl(raw)) return { icon: raw, isImage: true }
|
||||
if (isGlyph(raw)) return { icon: raw, isImage: false }
|
||||
}
|
||||
return { icon: NAME_ICON_MAP[name] ?? DEFAULT_ICON, isImage: false }
|
||||
}
|
||||
|
||||
/**
|
||||
* 后端入口 → 页面卡片
|
||||
*
|
||||
* @param vo 后端入口
|
||||
* @param index 组内序号(决定底色轮转)
|
||||
*/
|
||||
export function toPortalEntryCard(vo: PortalEntryVo, index: number): PortalEntryCard | null {
|
||||
if (vo.id == null) return null
|
||||
const label = (vo.name ?? '').trim() || '未命名入口'
|
||||
const { icon, isImage } = resolveIcon(vo.icon, label)
|
||||
return {
|
||||
id: vo.id,
|
||||
label,
|
||||
route: (vo.route ?? '').trim(),
|
||||
groupType: (vo.groupType === '1' ? '1' : '0') as PortalEntryGroup,
|
||||
icon,
|
||||
isImage,
|
||||
tone: TONE_CYCLE[index % TONE_CYCLE.length],
|
||||
}
|
||||
}
|
||||
|
||||
/** 后端入口列表 → 页面卡片列表(过滤无效项,保持后端下发顺序) */
|
||||
export function toPortalEntryCards(list: PortalEntryVo[]): PortalEntryCard[] {
|
||||
return list
|
||||
.map((vo, index) => toPortalEntryCard(vo, index))
|
||||
.filter((item): item is PortalEntryCard => item !== null)
|
||||
}
|
||||
Reference in New Issue
Block a user