57 lines
2.4 KiB
JavaScript
57 lines
2.4 KiB
JavaScript
|
|
/**
|
|||
|
|
* 小程序工作台功能入口下发数据的通用组装工具
|
|||
|
|
* 后端 /xxx-dashboard/entries 返回扁平数组:[{ code, name, description, icon, theme, path, group_name }]
|
|||
|
|
* 这里统一转换成四个工作台首页渲染用的 sections 结构:[{ key, title, items: [{ key, label, desc, icon, theme, path }] }]
|
|||
|
|
* 行为字段(角标/表单预填/弹窗等)由各首页按 code 通过 decorate 回调注入,DB 只管展示与有无
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/** 未配置主题时的兜底配色(与各端硬编码菜单的占位灰一致) */
|
|||
|
|
const FALLBACK_THEME = { bg: 'linear-gradient(135deg, #F3F4F6, #E5E7EB)', color: '#6B7280' };
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 单条下发入口 → 渲染项归一化(首页 sections 与功能页常用/历史共用同一映射,保证字段一致)
|
|||
|
|
* @param {Object} entry 后端下发的入口对象
|
|||
|
|
* @returns {Object|null} { key, label, desc, icon, theme, path, group };非法入口返回 null
|
|||
|
|
*/
|
|||
|
|
export function normalizeEntry(entry) {
|
|||
|
|
if (!entry || !entry.code) return null;
|
|||
|
|
return {
|
|||
|
|
key: entry.code,
|
|||
|
|
label: entry.name || '',
|
|||
|
|
desc: entry.description || '',
|
|||
|
|
icon: entry.icon || 'grid-fill',
|
|||
|
|
theme: entry.theme && entry.theme.bg ? entry.theme : FALLBACK_THEME,
|
|||
|
|
path: entry.path || '',
|
|||
|
|
group: entry.group_name || '',
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 下发入口 → sections 结构
|
|||
|
|
* @param {Array} entries 后端下发的入口数组(已按后台配置排序)
|
|||
|
|
* @param {Function} [decorate] 可选行为装饰回调 (item, entry) => item|null,返回 null 表示丢弃该项
|
|||
|
|
* @returns {Array} sections;entries 为空/非法时返回空数组(调用方据此回落硬编码菜单)
|
|||
|
|
*/
|
|||
|
|
export function groupEntriesToSections(entries, decorate) {
|
|||
|
|
if (!Array.isArray(entries) || entries.length === 0) return [];
|
|||
|
|
const sections = [];
|
|||
|
|
entries.forEach((entry) => {
|
|||
|
|
let item = normalizeEntry(entry);
|
|||
|
|
if (!item) return;
|
|||
|
|
if (typeof decorate === 'function') {
|
|||
|
|
item = decorate(item, entry);
|
|||
|
|
if (!item) return;
|
|||
|
|
}
|
|||
|
|
const title = entry.group_name || '快捷服务';
|
|||
|
|
let section = sections.find((s) => s.title === title);
|
|||
|
|
if (!section) {
|
|||
|
|
// key 用分组标题即可(仅作 v-for key,首个出现顺序即分组展示顺序)
|
|||
|
|
section = { key: title, title, items: [] };
|
|||
|
|
sections.push(section);
|
|||
|
|
}
|
|||
|
|
section.items.push(item);
|
|||
|
|
});
|
|||
|
|
// 丢弃被 decorate 全部过滤掉的空分组
|
|||
|
|
return sections.filter((s) => s.items.length > 0);
|
|||
|
|
}
|