feat: add portal home launcher, favorites UI, and WorkTab overflow eviction
Replace top-bar module navigation with a card home page, persist favorites via API, reopen favorite tabs on cold login, and enable portal multi-tabs with overflow-based eviction. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
7898d65437
commit
2df2ef0808
17 files changed
+2242
-157
No files matched your search
@@ -5,6 +5,37 @@ import type { AppRouteRecord } from '@/types/router'
|
||||
* 与后端菜单对齐时请同步 `sys_menu`(bx 见 docs/sql/20260606_bx_menu.sql;db 见 docs/sql/20260607_db_menu.sql)。
|
||||
*/
|
||||
export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
// ──────────────────────────────────────────────
|
||||
// 门户菜单启动器首页(不在业务菜单树中展示)
|
||||
// ──────────────────────────────────────────────
|
||||
{
|
||||
id: 'HOME00000000000000000000000000001',
|
||||
name: 'PortalHomeRoot',
|
||||
path: '/home-root',
|
||||
component: '/index/index',
|
||||
meta: {
|
||||
title: '首页',
|
||||
keepAlive: false,
|
||||
isHide: true,
|
||||
roles: ['admin', 'super_admin']
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'HOME00000000000000000000000000002',
|
||||
name: 'PortalHome',
|
||||
path: '/home',
|
||||
component: '/portal/home/index',
|
||||
meta: {
|
||||
title: '首页',
|
||||
keepAlive: true,
|
||||
fixedTab: true,
|
||||
isHide: true,
|
||||
roles: ['admin', 'super_admin']
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 控制台(已废弃,门户布局不展示;路由保留兼容旧链接)
|
||||
// ──────────────────────────────────────────────
|
||||
@@ -258,7 +289,12 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
name: 'CrmProductCategory',
|
||||
path: 'product-category',
|
||||
component: '/crm/product-category/index',
|
||||
meta: { title: '产品分类', keepAlive: true, menuCode: 'crm:productCategory:list' }
|
||||
meta: {
|
||||
title: '产品分类',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:productCategory:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM00000000000000000000000000003',
|
||||
@@ -267,92 +303,6 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
component: '/crm/product/index',
|
||||
meta: { title: '产品管理', keepAlive: true, menuCode: 'crm:product:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000010',
|
||||
name: 'CrmClue',
|
||||
path: 'clue',
|
||||
component: '/crm/clue/index',
|
||||
meta: { title: '线索管理', keepAlive: true, menuCode: 'crm:clue:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000011',
|
||||
name: 'CrmClueDetail',
|
||||
path: 'clue/detail/:id',
|
||||
component: '/crm/clue/detail',
|
||||
meta: {
|
||||
title: '线索详情',
|
||||
keepAlive: false,
|
||||
isHide: true,
|
||||
menuCode: 'crm:clue:query'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000012',
|
||||
name: 'CrmClueStatistics',
|
||||
path: 'clue/statistics',
|
||||
component: '/crm/clue/statistics/index',
|
||||
meta: {
|
||||
title: '线索统计',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:clue:statistics'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000010',
|
||||
name: 'CrmOpportunity',
|
||||
path: 'opportunity',
|
||||
component: '/crm/opportunity/index',
|
||||
meta: { title: '商机管理', keepAlive: true, menuCode: 'crm:opportunity:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000011',
|
||||
name: 'CrmOpportunityDetail',
|
||||
path: 'opportunity/detail/:id',
|
||||
component: '/crm/opportunity/detail',
|
||||
meta: {
|
||||
title: '商机详情',
|
||||
keepAlive: false,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:query'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000012',
|
||||
name: 'CrmOpportunityKanban',
|
||||
path: 'opportunity/kanban',
|
||||
component: '/crm/opportunity/kanban',
|
||||
meta: {
|
||||
title: '商机看板',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000013',
|
||||
name: 'CrmOpportunityFunnel',
|
||||
path: 'opportunity/funnel',
|
||||
component: '/crm/opportunity/funnel',
|
||||
meta: {
|
||||
title: '销售漏斗',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000014',
|
||||
name: 'CrmOpportunityStatistics',
|
||||
path: 'opportunity/statistics',
|
||||
component: '/crm/opportunity/statistics',
|
||||
meta: {
|
||||
title: '商机统计',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM3000000000000000000000000010',
|
||||
name: 'CrmQuote',
|
||||
@@ -368,6 +318,7 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
meta: {
|
||||
title: '报价单审批人设置',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:quote:approverSetting'
|
||||
}
|
||||
},
|
||||
@@ -422,6 +373,7 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
meta: {
|
||||
title: '合同审批人设置',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:contract:approverSetting'
|
||||
}
|
||||
},
|
||||
@@ -498,32 +450,6 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
path: 'customer',
|
||||
component: '/crm/customer/index',
|
||||
meta: { title: '客户管理', keepAlive: true, menuCode: 'crm:customer:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000003',
|
||||
name: 'CrmCustomerPool',
|
||||
path: 'customer-pool',
|
||||
component: '/crm/customer/pool/index',
|
||||
meta: { title: '公海池', keepAlive: true, menuCode: 'crm:customerPool:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM3000000000000000000000000040',
|
||||
name: 'CrmSupplierHazard',
|
||||
path: 'supplier-hazard',
|
||||
component: '/crm/supplier-hazard/index',
|
||||
meta: { title: '主体危化品能力', keepAlive: true, menuCode: 'crm:supplierHazard:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000004',
|
||||
name: 'CrmPoolRule',
|
||||
path: 'pool-rule',
|
||||
component: '/crm/customer/pool/RuleIndex',
|
||||
meta: {
|
||||
title: '公海池规则',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:poolRule:list'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -767,6 +693,129 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
menuCode: 'system:operlog:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'SYS_APPROVER_SETTING',
|
||||
name: 'SystemApproverSetting',
|
||||
path: 'approver-setting',
|
||||
component: '/system/approver-setting/index',
|
||||
meta: {
|
||||
title: '报价、合同审批人设置',
|
||||
keepAlive: true,
|
||||
menuCode: 'system:approverSetting'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000010',
|
||||
name: 'CrmClue',
|
||||
path: 'clue',
|
||||
component: '/crm/clue/index',
|
||||
meta: { title: '线索管理', keepAlive: true, menuCode: 'crm:clue:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000011',
|
||||
name: 'CrmClueDetail',
|
||||
path: 'clue/detail/:id',
|
||||
component: '/crm/clue/detail',
|
||||
meta: {
|
||||
title: '线索详情',
|
||||
keepAlive: false,
|
||||
isHide: true,
|
||||
menuCode: 'crm:clue:query'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000012',
|
||||
name: 'CrmClueStatistics',
|
||||
path: 'clue/statistics',
|
||||
component: '/crm/clue/statistics/index',
|
||||
meta: {
|
||||
title: '线索统计',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:clue:statistics'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000010',
|
||||
name: 'CrmOpportunity',
|
||||
path: 'opportunity',
|
||||
component: '/crm/opportunity/index',
|
||||
meta: { title: '商机管理', keepAlive: true, menuCode: 'crm:opportunity:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000011',
|
||||
name: 'CrmOpportunityDetail',
|
||||
path: 'opportunity/detail/:id',
|
||||
component: '/crm/opportunity/detail',
|
||||
meta: {
|
||||
title: '商机详情',
|
||||
keepAlive: false,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:query'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000012',
|
||||
name: 'CrmOpportunityKanban',
|
||||
path: 'opportunity/kanban',
|
||||
component: '/crm/opportunity/kanban',
|
||||
meta: {
|
||||
title: '商机看板',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000013',
|
||||
name: 'CrmOpportunityFunnel',
|
||||
path: 'opportunity/funnel',
|
||||
component: '/crm/opportunity/funnel',
|
||||
meta: {
|
||||
title: '销售漏斗',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM2000000000000000000000000014',
|
||||
name: 'CrmOpportunityStatistics',
|
||||
path: 'opportunity/statistics',
|
||||
component: '/crm/opportunity/statistics',
|
||||
meta: {
|
||||
title: '商机统计',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:opportunity:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000003',
|
||||
name: 'CrmCustomerPool',
|
||||
path: 'customer-pool',
|
||||
component: '/crm/customer/pool/index',
|
||||
meta: { title: '公海池', keepAlive: true, menuCode: 'crm:customerPool:list' }
|
||||
},
|
||||
{
|
||||
id: 'CRM1000000000000000000000000004',
|
||||
name: 'CrmPoolRule',
|
||||
path: 'pool-rule',
|
||||
component: '/crm/customer/pool/RuleIndex',
|
||||
meta: {
|
||||
title: '公海池规则',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'crm:poolRule:list'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'CRM3000000000000000000000000040',
|
||||
name: 'CrmSupplierHazard',
|
||||
path: 'supplier-hazard',
|
||||
component: '/crm/supplier-hazard/index',
|
||||
meta: { title: '主体危化品能力', keepAlive: true, menuCode: 'crm:supplierHazard:list' }
|
||||
},
|
||||
{
|
||||
id: '10000000000000000000000000000008',
|
||||
name: 'UserDetail',
|
||||
|
||||
Reference in new issue
Block a user