Files

85 lines
1.9 KiB
Vue
Raw Permalink Normal View History

2026-08-19 08:17:18 +08:00
<template>
<!-- 主题图标:line / fill / duotone / block -->
<view class="theme-icon" :class="'theme-icon--' + mode" :style="wrapStyle">
<u-icon
v-if="name"
:name="name"
:color="glyphColor"
:size="size"
/>
<image
v-else-if="src"
:src="src"
class="theme-icon__img"
mode="aspectFit"
:style="{ width: size + 'px', height: size + 'px' }"
/>
<slot v-else />
</view>
</template>
<script>
import { getActiveLayout, getActiveVars } from '@/utils/theme'
export default {
name: 'ThemeIcon',
props: {
name: { type: String, default: '' },
src: { type: String, default: '' },
size: { type: [Number, String], default: 20 },
/** 覆盖 effect.icon */
icon: { type: String, default: '' },
},
computed: {
mode() {
if (this.icon) return this.icon
const effect = (getActiveLayout().effect) || {}
return effect.icon || 'line'
},
vars() {
return getActiveVars()
},
primary() {
return this.vars['--color-primary'] || '#B08D57'
},
surface() {
return this.vars['--color-surface'] || '#fff'
},
glyphColor() {
if (this.mode === 'block') return this.surface
if (this.mode === 'fill' || this.mode === 'duotone') return this.primary
return this.primary
},
wrapStyle() {
if (this.mode === 'block') {
return {
background: this.primary,
borderRadius: this.vars['--radius-sm'] || '8rpx',
padding: '10rpx',
}
}
if (this.mode === 'duotone') {
return {
background: this.vars['--color-primary-soft'] || 'rgba(0,0,0,0.06)',
borderRadius: '999rpx',
padding: '8rpx',
}
}
return {}
},
},
}
</script>
<style lang="scss" scoped>
.theme-icon {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.theme-icon__img {
display: block;
}
</style>