Files
zkxw/mobile-h5/components/MenuGrid.vue
T
2026-10-13 15:18:01 +08:00

84 lines
2.5 KiB
Vue

<template>
<view class="menu-grid">
<view
v-for="m in menus"
:key="m.id"
class="menu-card"
:class="{ 'menu-card--text-only': !m.icon }"
@click="$emit('select', m)"
>
<view
v-if="m.icon"
class="menu-icon"
:class="[toneClass(m), plainClass(m)]"
:style="iconBoxStyle(m)"
>
<VanIcon :name="m.icon" :color="iconFg(m)" :size="iconSize(m)" />
<text v-if="badgeText(m)" class="menu-badge">{{ badgeText(m) }}</text>
</view>
<text
v-if="showGroupTitle && m.groupTitle"
class="menu-group-title"
>{{ m.groupTitle }}</text>
<text class="menu-title">{{ m.title }}</text>
</view>
</view>
</template>
<script>
import VanIcon from './van-icon/van-icon.vue'
import { resolveMenuIconColors } from '../utils/menu-icon-colors.js'
import { formatOaBadgeCount } from '../utils/oa-badge.js'
export default {
name: 'MenuGrid',
components: { VanIcon },
props: {
menus: { type: Array, default: () => [] },
/** 分区标题栏展示区域名时,卡片内不再重复 groupTitle 胶囊 */
showGroupTitle: { type: Boolean, default: true }
},
emits: ['select'],
methods: {
badgeText(m) {
if (!m) return ''
if (m.badge != null && String(m.badge).trim() !== '' && String(m.badge).trim() !== '0') {
if (typeof m.badge === 'number') return formatOaBadgeCount(m.badge)
return String(m.badge).trim()
}
return formatOaBadgeCount(m.badgeCount)
},
colors(m) {
return resolveMenuIconColors(m)
},
iconFg(m) {
return this.colors(m).iconFg || ''
},
isPlainIcon(m) {
const bg = String(this.colors(m).iconBg || '').trim().toLowerCase()
return bg === 'transparent' || bg === 'none'
},
plainClass(m) {
return this.isPlainIcon(m) ? 'menu-icon--plain' : ''
},
iconSize(m) {
return this.isPlainIcon(m) ? '56rpx' : '52rpx'
},
iconBoxStyle(m) {
const { iconBg, iconFg } = this.colors(m)
const style = {}
if (iconBg) style.background = iconBg
if (this.isPlainIcon(m)) style.boxShadow = 'none'
if (iconFg) style.color = iconFg
return style
},
/** 有自定义色时不再套 tone-*,避免绿底覆盖 */
toneClass(m) {
const { iconBg, iconFg } = this.colors(m)
if (iconBg || iconFg) return ''
return m.tone || ''
}
}
}
</script>