This commit is contained in:
2026-08-12 16:31:46 +08:00
parent c15d21b986
commit d8bbfe05f3
40 changed files with 1541 additions and 248 deletions
+28 -18
View File
@@ -1,7 +1,6 @@
import type { Component } from 'vue'
import {
Building2,
BarChart3,
ContactRound,
ClipboardList,
CircleDollarSign,
@@ -15,6 +14,21 @@ import {
Users,
Warehouse as WarehouseIcon,
} from '@lucide/vue'
import {
PrototypeContainerIcon,
PrototypeCustomerIcon,
PrototypeDashboardIcon,
PrototypeDeliveryIcon,
PrototypeDomesticWarehouseIcon,
PrototypeFinanceIcon,
PrototypeGeneralIcon,
PrototypeOverseasBusinessIcon,
PrototypeOverseasWarehouseIcon,
PrototypeSalesIcon,
PrototypeServiceIcon,
PrototypeSupplierIcon,
PrototypeSystemIcon,
} from './prototypeMenuIcons'
export interface AdminNavigationNode {
key: string
@@ -36,12 +50,11 @@ export interface AdminNavigationLeaf extends AdminNavigationNode {
}
export const adminNavigation: AdminNavigationNode[] = [
{ key: 'dashboard', title: '首页数据看板', icon: BarChart3, path: '/dashboard' },
{ key: 'dashboard', title: '首页数据看板', icon: PrototypeDashboardIcon, path: '/dashboard' },
{
key: 'customers',
title: '客户管理',
icon: Building2,
iconColor: '#52c41a',
icon: PrototypeCustomerIcon,
children: [
{ key: 'customers-list', title: '客户列表', icon: Building2, path: '/customers', permission: 'platform:customer:list', permissionAnyOf: ['platform:customer:review'] },
{ key: 'warehouse-tier-fee', title: '海外仓阶梯费用', icon: Building2, path: '/customers/overseas-storage-fees', permission: 'platform:overseas-storage-fee:list' },
@@ -50,8 +63,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'domestic-warehouse',
title: '国内仓',
icon: WarehouseIcon,
iconColor: '#52c41a',
icon: PrototypeDomesticWarehouseIcon,
children: [
{ key: 'order-list', title: '订单列表', icon: ClipboardList, path: '/orders', permission: 'platform:order:list', permissionAnyOf: ['platform:firstleg:inbound:list'] },
{ key: 'inbound-dedup', title: '订单测量', icon: ClipboardList, path: '/prototype/domestic-warehouse/inbound-dedup', hidden: true },
@@ -63,7 +75,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'overseas-delivery',
title: '海外派送',
icon: Truck,
icon: PrototypeDeliveryIcon,
hidden: true,
children: [
{ key: 'outbound-dispatch', title: '派送单列表', icon: Truck, path: '/prototype/overseas-delivery/dispatch-list' },
@@ -75,7 +87,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'service-center',
title: '服务中心',
icon: ClipboardList,
icon: PrototypeServiceIcon,
children: [
{ key: 'booking-list', title: '订舱列表', icon: ClipboardList, path: '/ocean-bookings', permission: 'platform:firstleg:ocean-booking:list' },
{ key: 'port-schedules', title: '船期信息', icon: ClipboardList, path: '/port-schedules', permission: 'platform:firstleg:port-schedule:list' },
@@ -87,7 +99,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'supplier-center',
title: '供应商中心',
icon: ContactRound,
icon: PrototypeSupplierIcon,
children: [
{ key: 'supplier-list', title: '供应商列表', icon: ContactRound, path: '/prototype/supplier-center/supplier-list', hidden: true },
{ key: 'express-companies', title: '快递公司', icon: Truck, path: '/master-data/express-companies', permission: 'platform:express:list' },
@@ -97,7 +109,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'container-management',
title: '货柜管理',
icon: WarehouseIcon,
icon: PrototypeContainerIcon,
children: [
{ key: 'container-list', title: '货柜列表', icon: WarehouseIcon, path: '/container-loading', permission: 'platform:firstleg:container:list' },
{ key: 'container-smart-loading', title: '智能装柜', icon: ClipboardList, path: '/container-loading/smart-loading', permission: 'platform:firstleg:smart-loading:list' },
@@ -108,7 +120,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'overseas-business',
title: '海外业务',
icon: Building2,
icon: PrototypeOverseasBusinessIcon,
hidden: true,
children: [
{ key: 'overseas-purchase', title: '采购订单', icon: ClipboardList, path: '/prototype/overseas-business/purchase-orders' },
@@ -119,7 +131,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'overseas-inventory',
title: '海外仓库存',
icon: WarehouseIcon,
icon: PrototypeOverseasWarehouseIcon,
hidden: true,
children: [
{ key: 'fba-inbound-order', title: '入库单', icon: ClipboardList, path: '/prototype/fba-returns/inbound-orders' },
@@ -135,7 +147,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'finance',
title: '财务管理',
icon: CircleDollarSign,
icon: PrototypeFinanceIcon,
children: [
{ key: 'finance-customer-accounts', title: '客户账户', icon: CircleDollarSign, path: '/finance/customer-accounts', permission: 'platform:finance:account:view' },
{ key: 'finance-customer-arap', title: '客户应收应付', icon: Database, path: '/finance/customer-arap', permission: 'platform:finance:bill:view' },
@@ -147,7 +159,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'sales',
title: '销售管理',
icon: Users,
icon: PrototypeSalesIcon,
hidden: true,
children: [
{ key: 'sales-visits', title: '拜访记录', icon: Users, path: '/prototype/sales/visit-records' },
@@ -157,8 +169,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'general',
title: '通用',
icon: Database,
iconColor: '#722ed1',
icon: PrototypeGeneralIcon,
children: [
// { key: 'first-leg-orders', title: '头程订单', icon: ClipboardList, path: '/orders/first-leg', permission: 'platform:order:list', hidden: true },
{ key: 'general-product', title: '产品信息', icon: Database, path: '/prototype/general/product-information', hidden: true },
@@ -172,8 +183,7 @@ export const adminNavigation: AdminNavigationNode[] = [
{
key: 'system',
title: '系统管理',
icon: Settings,
iconColor: '#8c8c8c',
icon: PrototypeSystemIcon,
children: [
{ key: 'internal-users', title: '用户管理', icon: Users, path: '/system/users', permission: 'platform:user:list' },
{ key: 'roles', title: '角色权限', icon: ShieldCheck, path: '/system/roles', permission: 'platform:role:list' },
@@ -0,0 +1,32 @@
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import {
PrototypeCustomerIcon,
PrototypeDashboardIcon,
PrototypeFinanceIcon,
} from './prototypeMenuIcons'
describe('prototype menu icons', () => {
it('renders the prototype shapes at the requested size', () => {
const wrapper = mount(PrototypeDashboardIcon, { props: { size: 22 } })
expect(wrapper.attributes()).toMatchObject({
width: '22',
height: '22',
viewBox: '0 0 24 24',
'aria-hidden': 'true',
})
expect(wrapper.findAll('rect')).toHaveLength(4)
expect(wrapper.findAll('rect').map((node) => node.attributes('fill'))).toEqual([
'#1677ff',
'#1677ff',
'#1677ff',
'#1677ff',
])
})
it('preserves the original menu colors', () => {
expect(mount(PrototypeCustomerIcon).find('path').attributes('fill')).toBe('#52c41a')
expect(mount(PrototypeFinanceIcon).find('circle').attributes('stroke')).toBe('#f5a623')
})
})
+90
View File
@@ -0,0 +1,90 @@
import { defineComponent, h, type Component, type SVGAttributes } from 'vue'
type SvgChild = ReturnType<typeof h>
function createPrototypeMenuIcon(name: string, children: SvgChild[]): Component {
return defineComponent({
name,
inheritAttrs: false,
props: {
size: { type: [Number, String], default: 20 },
},
setup(props, { attrs }) {
return () => h('svg', {
...attrs,
width: props.size,
height: props.size,
viewBox: '0 0 24 24',
fill: 'none',
'aria-hidden': 'true',
} satisfies SVGAttributes, children)
},
})
}
export const PrototypeDashboardIcon = createPrototypeMenuIcon('PrototypeDashboardIcon', [
h('rect', { x: 3, y: 3, width: 7, height: 8, rx: 1.5, fill: '#1677ff' }),
h('rect', { x: 14, y: 3, width: 7, height: 5, rx: 1.5, fill: '#1677ff', opacity: 0.6 }),
h('rect', { x: 3, y: 14, width: 7, height: 7, rx: 1.5, fill: '#1677ff', opacity: 0.3 }),
h('rect', { x: 14, y: 11, width: 7, height: 10, rx: 1.5, fill: '#1677ff', opacity: 0.8 }),
])
export const PrototypeCustomerIcon = createPrototypeMenuIcon('PrototypeCustomerIcon', [
h('path', { d: 'M3 21h7v-7H3v7zm0-9h7V3H3v9zm11 9h7v-5h-7v5zm0-9h7V3h-7v9z', fill: '#52c41a' }),
])
export const PrototypeDomesticWarehouseIcon = createPrototypeMenuIcon('PrototypeDomesticWarehouseIcon', [
h('path', { d: 'M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2', stroke: '#52c41a', 'stroke-width': 2, 'stroke-linecap': 'round' }),
h('path', { d: 'M9 14l2 2 4-4', stroke: '#52c41a', 'stroke-width': 2, 'stroke-linecap': 'round', 'stroke-linejoin': 'round' }),
])
export const PrototypeOverseasWarehouseIcon = createPrototypeMenuIcon('PrototypeOverseasWarehouseIcon', [
h('path', { d: 'M4 12a8 8 0 112.34 5.6', stroke: '#eb2f96', 'stroke-width': 2, 'stroke-linecap': 'round' }),
h('path', { d: 'M4 12V7M4 12h5', stroke: '#eb2f96', 'stroke-width': 2, 'stroke-linecap': 'round' }),
h('circle', { cx: 12, cy: 12, r: 2.4, fill: '#eb2f96' }),
])
export const PrototypeDeliveryIcon = createPrototypeMenuIcon('PrototypeDeliveryIcon', [
h('path', { d: 'M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z', fill: '#1890ff' }),
])
export const PrototypeServiceIcon = createPrototypeMenuIcon('PrototypeServiceIcon', [
h('path', { d: 'M4 6h16v12H4z', stroke: '#722ed1', 'stroke-width': 2 }),
h('path', { d: 'M4 10h16M8 14h3', stroke: '#722ed1', 'stroke-width': 2, 'stroke-linecap': 'round' }),
])
export const PrototypeSupplierIcon = createPrototypeMenuIcon('PrototypeSupplierIcon', [
h('path', { d: 'M3 21V9l9-6 9 6v12', stroke: '#eb2f96', 'stroke-width': 2, 'stroke-linejoin': 'round' }),
h('path', { d: 'M9 21v-6h6v6', stroke: '#eb2f96', 'stroke-width': 2, 'stroke-linejoin': 'round' }),
])
export const PrototypeContainerIcon = createPrototypeMenuIcon('PrototypeContainerIcon', [
h('rect', { x: 2, y: 3, width: 20, height: 18, rx: 1, stroke: '#52c41a', 'stroke-width': 2 }),
h('path', { d: 'M2 8h20M8 3v5M16 3v5', stroke: '#52c41a', 'stroke-width': 2, 'stroke-linecap': 'round' }),
])
export const PrototypeOverseasBusinessIcon = createPrototypeMenuIcon('PrototypeOverseasBusinessIcon', [
h('circle', { cx: 12, cy: 12, r: 9, stroke: '#8c8c8c', 'stroke-width': 1.5 }),
h('path', { d: 'M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18', stroke: '#8c8c8c', 'stroke-width': 1.5, 'stroke-linecap': 'round' }),
])
export const PrototypeFinanceIcon = createPrototypeMenuIcon('PrototypeFinanceIcon', [
h('circle', { cx: 12, cy: 12, r: 10, stroke: '#f5a623', 'stroke-width': 2 }),
h('path', { d: 'M12 6v6l4 2', stroke: '#f5a623', 'stroke-width': 2, 'stroke-linecap': 'round' }),
h('circle', { cx: 12, cy: 12, r: 2, fill: '#f5a623' }),
])
export const PrototypeSalesIcon = createPrototypeMenuIcon('PrototypeSalesIcon', [
h('circle', { cx: 12, cy: 12, r: 10, stroke: '#1677ff', 'stroke-width': 2 }),
h('path', { d: 'M12 6v12M6 12h12', stroke: '#1677ff', 'stroke-width': 2, 'stroke-linecap': 'round' }),
])
export const PrototypeGeneralIcon = createPrototypeMenuIcon('PrototypeGeneralIcon', [
h('rect', { x: 3, y: 3, width: 18, height: 18, rx: 2, stroke: '#722ed1', 'stroke-width': 2 }),
h('path', { d: 'M8 12h8M12 8v8', stroke: '#722ed1', 'stroke-width': 2, 'stroke-linecap': 'round' }),
])
export const PrototypeSystemIcon = createPrototypeMenuIcon('PrototypeSystemIcon', [
h('circle', { cx: 12, cy: 12, r: 3, fill: '#8c8c8c' }),
h('path', { d: 'M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83', stroke: '#8c8c8c', 'stroke-width': 1.5, 'stroke-linecap': 'round' }),
])